Skip to content

Commit df8113b

Browse files
committed
[Diagnostics] Contextual mismatch should be attached to the closure if its body is empty/implicit
If there is a contextual mismatch associated with a closure body, make sure that the diagnostic is attached to the closure even if the body is empty or implicit. Resolves: rdar://52204608
1 parent 4de232e commit df8113b

File tree

3 files changed

+27
-0
lines changed

3 files changed

+27
-0
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2121,6 +2121,24 @@ Diag<StringRef> AssignmentFailure::findDeclDiagonstic(ASTContext &ctx,
21212121
return diag::assignment_lhs_is_immutable_variable;
21222122
}
21232123

2124+
SourceLoc ContextualFailure::getLoc() const {
2125+
auto *locator = getLocator();
2126+
2127+
// `getSingleExpressionBody` can point to an implicit expression
2128+
// without source information in cases like `{ return }`.
2129+
if (locator->isLastElement<LocatorPathElt::ClosureBody>()) {
2130+
auto *closure = castToExpr<ClosureExpr>(locator->getAnchor());
2131+
if (closure->hasSingleExpressionBody()) {
2132+
auto *body = closure->getSingleExpressionBody();
2133+
if (auto loc = body->getLoc())
2134+
return loc;
2135+
}
2136+
return closure->getLoc();
2137+
}
2138+
2139+
return FailureDiagnostic::getLoc();
2140+
}
2141+
21242142
bool ContextualFailure::diagnoseAsError() {
21252143
auto anchor = getAnchor();
21262144
auto path = getLocator()->getPath();

lib/Sema/CSDiagnostics.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,8 @@ class ContextualFailure : public FailureDiagnostic {
603603
: FailureDiagnostic(solution, locator), CTP(purpose), RawFromType(lhs),
604604
RawToType(rhs) {}
605605

606+
SourceLoc getLoc() const override;
607+
606608
Type getFromType() const { return resolve(RawFromType); }
607609

608610
Type getToType() const { return resolve(RawToType); }

test/Constraints/closures.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,3 +1077,10 @@ let _: (@convention(c) () -> Void)? = Bool.random() ? nil : {} // OK on type che
10771077
let _: (@convention(block) () -> Void)? = Bool.random() ? {} : {} // OK
10781078
let _: (@convention(thin) () -> Void)? = Bool.random() ? {} : {} // OK
10791079
let _: (@convention(c) () -> Void)? = Bool.random() ? {} : {} // OK on type checking, diagnostics are deffered to SIL
1080+
1081+
// Make sure that diagnostic is attached to the closure even when body is empty (implicitly returns `Void`)
1082+
var emptyBodyMismatch: () -> Int {
1083+
return { // expected-error {{cannot convert value of type '()' to closure result type 'Int'}}
1084+
return
1085+
}
1086+
}

0 commit comments

Comments
 (0)