Skip to content

Commit edaf7b0

Browse files
authored
Merge pull request #28240 from xedin/port-clj-explicit-result-mismatch
[Diagnostics] Port explicit closure result contextual mismatch
2 parents 0ebe9a1 + eb3a1b3 commit edaf7b0

File tree

6 files changed

+34
-35
lines changed

6 files changed

+34
-35
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3243,35 +3243,6 @@ bool FailureDiagnosis::diagnoseClosureExpr(
32433243
return true;
32443244
}
32453245

3246-
// If the body of the closure looked ok, then look for a contextual type
3247-
// error. This is necessary because FailureDiagnosis::diagnoseExprFailure
3248-
// doesn't do this for closures.
3249-
if (contextualType) {
3250-
auto fnType = contextualType->getAs<AnyFunctionType>();
3251-
if (!fnType || fnType->isEqual(CS.getType(CE)))
3252-
return false;
3253-
3254-
auto contextualResultType = fnType->getResult();
3255-
// If the result type was unknown, it doesn't really make
3256-
// sense to diagnose from expected to unknown here.
3257-
if (isInvalidClosureResultType(contextualResultType))
3258-
return false;
3259-
3260-
// If the closure had an explicitly written return type incompatible with
3261-
// the contextual type, diagnose that.
3262-
if (CE->hasExplicitResultType() &&
3263-
CE->getExplicitResultTypeLoc().getTypeRepr()) {
3264-
auto explicitResultTy = CE->getExplicitResultTypeLoc().getType();
3265-
if (fnType && !explicitResultTy->isEqual(contextualResultType)) {
3266-
auto repr = CE->getExplicitResultTypeLoc().getTypeRepr();
3267-
diagnose(repr->getStartLoc(), diag::incorrect_explicit_closure_result,
3268-
explicitResultTy, fnType->getResult())
3269-
.fixItReplace(repr->getSourceRange(),fnType->getResult().getString());
3270-
return true;
3271-
}
3272-
}
3273-
}
3274-
32753246
// Otherwise, we can't produce a specific diagnostic.
32763247
return false;
32773248
}

lib/Sema/CSDiagnostics.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,6 +1986,17 @@ bool ContextualFailure::diagnoseAsError() {
19861986
Diag<Type, Type> diagnostic;
19871987
switch (path.back().getKind()) {
19881988
case ConstraintLocator::ClosureResult: {
1989+
auto *closure = cast<ClosureExpr>(getRawAnchor());
1990+
if (closure->hasExplicitResultType() &&
1991+
closure->getExplicitResultTypeLoc().getTypeRepr()) {
1992+
auto resultRepr = closure->getExplicitResultTypeLoc().getTypeRepr();
1993+
emitDiagnostic(resultRepr->getStartLoc(),
1994+
diag::incorrect_explicit_closure_result, getFromType(),
1995+
getToType())
1996+
.fixItReplace(resultRepr->getSourceRange(), getToType().getString());
1997+
return true;
1998+
}
1999+
19892000
diagnostic = diag::cannot_convert_closure_result;
19902001
break;
19912002
}

lib/Sema/CSSimplify.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3265,8 +3265,25 @@ bool ConstraintSystem::repairFailures(
32653265
break;
32663266
}
32673267

3268+
case ConstraintLocator::FunctionResult: {
3269+
auto *loc = getConstraintLocator(anchor, {path.begin(), path.end() - 1});
3270+
// If this is a mismatch between contextual type and (trailing)
3271+
// closure with explicitly specified result type let's record it
3272+
// as contextual type mismatch.
3273+
if (loc->isLastElement<LocatorPathElt::ContextualType>() ||
3274+
loc->isLastElement<LocatorPathElt::ApplyArgToParam>()) {
3275+
auto *argExpr = simplifyLocatorToAnchor(loc);
3276+
if (argExpr && isa<ClosureExpr>(argExpr)) {
3277+
conversionsOrFixes.push_back(ContextualMismatch::create(
3278+
*this, lhs, rhs,
3279+
getConstraintLocator(argExpr, ConstraintLocator::ClosureResult)));
3280+
break;
3281+
}
3282+
}
3283+
LLVM_FALLTHROUGH;
3284+
}
3285+
32683286
case ConstraintLocator::Member:
3269-
case ConstraintLocator::FunctionResult:
32703287
case ConstraintLocator::DynamicLookupResult: {
32713288
// Most likely this is an attempt to use get-only subscript as mutating,
32723289
// or assign a value of a result of function/member ref e.g. `foo() = 42`

test/Constraints/closures.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ overloaded { print("hi"); print("bye") } // multiple expression closure without
765765
func not_overloaded(_ handler: () -> Int) {}
766766

767767
not_overloaded { } // empty body
768-
// expected-error@-1 {{cannot convert value of type '() -> ()' to expected argument type '() -> Int'}}
768+
// expected-error@-1 {{cannot convert value of type '()' to closure result type 'Int'}}
769769

770770
not_overloaded { print("hi") } // single-expression closure
771771
// expected-error@-1 {{cannot convert value of type '()' to closure result type 'Int'}}
@@ -786,7 +786,7 @@ func test() -> Int? {
786786
}
787787

788788
var fn: () -> [Int] = {}
789-
// expected-error@-1 {{cannot convert value of type '() -> ()' to specified type '() -> [Int]'}}
789+
// expected-error@-1 {{cannot convert value of type '()' to closure result type '[Int]'}}
790790

791791
fn = {}
792792
// expected-error@-1 {{cannot assign value of type '() -> ()' to type '() -> [Int]'}}

test/Sema/immutability.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -656,8 +656,8 @@ func sr4214() {
656656
let closure = { val in val.x = 7 } as (inout MutableSubscripts) -> () // Ok
657657
var v = MutableSubscripts()
658658
closure(&v)
659-
// FIXME: This diagnostic isn't really all that much better
660-
// expected-error@+1 {{cannot convert value of type '(inout MutableSubscripts) -> ()' to expected argument type '(_) -> _'}}
659+
// expected-error@+2 {{declared closure result '()' is incompatible with contextual type 'MutableSubscripts'}}
660+
// expected-error@+1 {{cannot convert value of type '(inout MutableSubscripts) -> ()' to expected argument type '(MutableSubscripts) -> MutableSubscripts'}}
661661
sequence(v) { (state : inout MutableSubscripts) -> () in
662662
_ = MutableSubscripts.initialize(from: &state)
663663
return ()

test/Sema/substring_to_string_conversion_swift4.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ do {
4545

4646
// CTP_ClosureResult
4747
do {
48-
[ss].map { (x: Substring) -> String in x } // expected-error {{cannot convert value of type 'Substring' to closure result type 'String'}} {{42-42=String(}} {{43-43=)}}
48+
[ss].map { (x: Substring) -> String in x } // expected-error {{declared closure result 'Substring' is incompatible with contextual type 'String'}}
4949
}
5050

5151
// CTP_ArrayElement

0 commit comments

Comments
 (0)