Skip to content

Commit 5f07747

Browse files
committed
[Sema] Diagnose user-specified placeholders which couldn’t be resolved
1 parent c305cb0 commit 5f07747

File tree

7 files changed

+73
-1
lines changed

7 files changed

+73
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3596,6 +3596,9 @@ ERROR(unresolved_nil_literal,none,
35963596
ERROR(cannot_force_unwrap_nil_literal,none,
35973597
"'nil' literal cannot be force unwrapped", ())
35983598

3599+
ERROR(could_not_infer_placeholder,none,
3600+
"could not infer type for placeholder", ())
3601+
35993602
ERROR(type_of_expression_is_ambiguous,none,
36003603
"type of expression is ambiguous without more context", ())
36013604

include/swift/Sema/CSFix.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,10 @@ enum class FixKind : uint8_t {
328328
/// another property wrapper that is a part of the same composed
329329
/// property wrapper.
330330
AllowWrappedValueMismatch,
331+
332+
/// Specify a type for an explicitly written placeholder that could not be
333+
/// resolved.
334+
SpecifyTypeForPlaceholder
331335
};
332336

333337
class ConstraintFix {
@@ -2257,6 +2261,25 @@ class SpecifyContextualTypeForNil final : public ConstraintFix {
22572261
ConstraintLocator * locator);
22582262
};
22592263

2264+
class SpecifyTypeForPlaceholder final : public ConstraintFix {
2265+
SpecifyTypeForPlaceholder(ConstraintSystem &cs, ConstraintLocator *locator)
2266+
: ConstraintFix(cs, FixKind::SpecifyTypeForPlaceholder, locator) {}
2267+
2268+
public:
2269+
std::string getName() const override {
2270+
return "specify type for placeholder";
2271+
}
2272+
2273+
bool diagnose(const Solution &solution, bool asNote = false) const override;
2274+
2275+
bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override {
2276+
return diagnose(*commonFixes.front().first);
2277+
}
2278+
2279+
static SpecifyTypeForPlaceholder *create(ConstraintSystem &cs,
2280+
ConstraintLocator *locator);
2281+
};
2282+
22602283
class AllowRefToInvalidDecl final : public ConstraintFix {
22612284
AllowRefToInvalidDecl(ConstraintSystem &cs, ConstraintLocator *locator)
22622285
: ConstraintFix(cs, FixKind::AllowRefToInvalidDecl, locator) {}

lib/Sema/CSBindings.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1904,6 +1904,11 @@ TypeVariableBinding::fixForHole(ConstraintSystem &cs) const {
19041904
return std::make_pair(fix, defaultImpact);
19051905
}
19061906

1907+
if (srcLocator->isLastElement<LocatorPathElt::PlaceholderType>()) {
1908+
ConstraintFix *fix = SpecifyTypeForPlaceholder::create(cs, srcLocator);
1909+
return std::make_pair(fix, defaultImpact);
1910+
}
1911+
19071912
if (dstLocator->directlyAt<NilLiteralExpr>()) {
19081913
// This is a dramatic event, it means that there is absolutely
19091914
// no contextual information to resolve type of `nil`.

lib/Sema/CSDiagnostics.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7501,6 +7501,19 @@ bool MissingContextualTypeForNil::diagnoseAsError() {
75017501
return true;
75027502
}
75037503

7504+
bool CouldNotInferPlaceholderType::diagnoseAsError() {
7505+
// If this placeholder was explicitly written out by the user, they can maybe
7506+
// fix things by specifying an actual type.
7507+
if (auto *typeExpr = getAsExpr<TypeExpr>(getAnchor())) {
7508+
if (typeExpr->getLoc().isValid()) {
7509+
emitDiagnostic(diag::could_not_infer_placeholder);
7510+
return true;
7511+
}
7512+
}
7513+
7514+
return false;
7515+
}
7516+
75047517
bool ReferenceToInvalidDeclaration::diagnoseAsError() {
75057518
auto &DE = getASTContext().Diags;
75067519

lib/Sema/CSDiagnostics.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2406,6 +2406,21 @@ class MissingContextualTypeForNil final : public FailureDiagnostic {
24062406
bool diagnoseAsError() override;
24072407
};
24082408

2409+
/// Diagnose situations where there is no context to determine the type of a
2410+
/// placeholder, e.g.,
2411+
///
2412+
/// \code
2413+
/// let _ = _.foo
2414+
/// \endcode
2415+
class CouldNotInferPlaceholderType final : public FailureDiagnostic {
2416+
public:
2417+
CouldNotInferPlaceholderType(const Solution &solution,
2418+
ConstraintLocator *locator)
2419+
: FailureDiagnostic(solution, locator) {}
2420+
2421+
bool diagnoseAsError() override;
2422+
};
2423+
24092424
/// Diagnostic situations where AST node references an invalid declaration.
24102425
///
24112426
/// \code

lib/Sema/CSFix.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,6 +1750,18 @@ SpecifyContextualTypeForNil::create(ConstraintSystem &cs,
17501750
return new (cs.getAllocator()) SpecifyContextualTypeForNil(cs, locator);
17511751
}
17521752

1753+
bool SpecifyTypeForPlaceholder::diagnose(const Solution &solution,
1754+
bool asNote) const {
1755+
CouldNotInferPlaceholderType failure(solution, getLocator());
1756+
return failure.diagnose(asNote);
1757+
}
1758+
1759+
SpecifyTypeForPlaceholder *
1760+
SpecifyTypeForPlaceholder::create(ConstraintSystem &cs,
1761+
ConstraintLocator *locator) {
1762+
return new (cs.getAllocator()) SpecifyTypeForPlaceholder(cs, locator);
1763+
}
1764+
17531765
bool AllowRefToInvalidDecl::diagnose(const Solution &solution,
17541766
bool asNote) const {
17551767
ReferenceToInvalidDeclaration failure(solution, getLocator());

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11484,7 +11484,8 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1148411484
case FixKind::AllowAlwaysSucceedCheckedCast:
1148511485
case FixKind::AllowInvalidStaticMemberRefOnProtocolMetatype:
1148611486
case FixKind::AllowWrappedValueMismatch:
11487-
case FixKind::RemoveExtraneousArguments: {
11487+
case FixKind::RemoveExtraneousArguments:
11488+
case FixKind::SpecifyTypeForPlaceholder: {
1148811489
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
1148911490
}
1149011491

0 commit comments

Comments
 (0)