Skip to content

Commit cb3252e

Browse files
committed
[ConstraintSystem] Extend use of missing explicit call fix
Now covers following new areas (alongside simple assignments): - Contextual type coercions: - In assignment e.g. `let _: X = foo` - In return type positions e.g. `func foo() -> A { return bar }` - Argument-to-parameter applications (including @autoclosure)
1 parent 49710ab commit cb3252e

File tree

5 files changed

+92
-18
lines changed

5 files changed

+92
-18
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,33 @@ bool MissingCallFailure::diagnoseAsError() {
17451745
if (isa<KeyPathExpr>(baseExpr))
17461746
return false;
17471747

1748+
auto path = getLocator()->getPath();
1749+
if (!path.empty()) {
1750+
const auto &last = path.back();
1751+
1752+
switch (last.getKind()) {
1753+
case ConstraintLocator::ContextualType:
1754+
case ConstraintLocator::ApplyArgToParam: {
1755+
auto fnType = getType(baseExpr)->castTo<FunctionType>();
1756+
assert(fnType->getNumParams() == 0);
1757+
emitDiagnostic(baseExpr->getLoc(), diag::missing_nullary_call,
1758+
fnType->getResult())
1759+
.fixItInsertAfter(baseExpr->getEndLoc(), "()");
1760+
return true;
1761+
}
1762+
1763+
case ConstraintLocator::AutoclosureResult: {
1764+
auto &cs = getConstraintSystem();
1765+
auto loc = cs.getConstraintLocator(getRawAnchor(), path.drop_back(),
1766+
/*summaryFlags=*/0);
1767+
AutoClosureForwardingFailure failure(cs, loc);
1768+
return failure.diagnoseAsError();
1769+
}
1770+
default:
1771+
break;
1772+
}
1773+
}
1774+
17481775
if (auto *DRE = dyn_cast<DeclRefExpr>(baseExpr)) {
17491776
emitDiagnostic(baseExpr->getLoc(), diag::did_not_call_function,
17501777
DRE->getDecl()->getBaseName().getIdentifier())

lib/Sema/CSSimplify.cpp

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2020,6 +2020,51 @@ bool ConstraintSystem::repairFailures(
20202020
SmallVector<LocatorPathElt, 4> path;
20212021
auto *anchor = locator.getLocatorParts(path);
20222022

2023+
// If there is a missing explicit call it could be:
2024+
//
2025+
// a). Contextual e.g. `let _: R = foo`
2026+
// b). Argument is a function value passed to parameter
2027+
// which expects its result type e.g. `foo(bar)`
2028+
// c). Assigment destination type matches return type of
2029+
// of the function value e.g. `foo = bar` or `foo = .bar`
2030+
auto repairByInsertingExplicitCall = [&](Type srcType, Type dstType) -> bool {
2031+
auto fnType = srcType->getAs<FunctionType>();
2032+
if (!fnType || fnType->getNumParams() > 0)
2033+
return false;
2034+
2035+
auto resultType = fnType->getResult();
2036+
// If this is situation like `x = { ... }` where closure results in
2037+
// `Void`, let's not suggest to call the closure, because it's most
2038+
// likely not intended.
2039+
if (anchor && isa<AssignExpr>(anchor)) {
2040+
auto *assignment = cast<AssignExpr>(anchor);
2041+
if (isa<ClosureExpr>(assignment->getSrc()) && resultType->isVoid())
2042+
return false;
2043+
}
2044+
2045+
// If left-hand side is a function type but right-hand
2046+
// side isn't, let's check it would be possible to fix
2047+
// this by forming an explicit call.
2048+
auto convertTo = dstType->lookThroughAllOptionalTypes();
2049+
// Right-hand side can't be - a function, a type variable or dependent
2050+
// member, or `Any` (if function conversion to `Any` didn't succeed there
2051+
// is something else going on e.g. problem with escapiness).
2052+
if (convertTo->is<FunctionType>() || convertTo->isTypeVariableOrMember() ||
2053+
convertTo->isAny())
2054+
return false;
2055+
2056+
auto result = matchTypes(resultType, dstType, ConstraintKind::Conversion,
2057+
TypeMatchFlags::TMF_ApplyingFix, locator);
2058+
2059+
if (result.isSuccess()) {
2060+
conversionsOrFixes.push_back(
2061+
InsertExplicitCall::create(*this, getConstraintLocator(locator)));
2062+
return true;
2063+
}
2064+
2065+
return false;
2066+
};
2067+
20232068
if (path.empty()) {
20242069
if (!anchor)
20252070
return false;
@@ -2036,21 +2081,8 @@ bool ConstraintSystem::repairFailures(
20362081
}
20372082

20382083
if (auto *AE = dyn_cast<AssignExpr>(anchor)) {
2039-
if (auto *fnType = lhs->getAs<FunctionType>()) {
2040-
// If left-hand side is a function type but right-hand
2041-
// side isn't, let's check it would be possible to fix
2042-
// this by forming an explicit call.
2043-
auto convertTo = rhs->lookThroughAllOptionalTypes();
2044-
if (!convertTo->is<FunctionType>() && !convertTo->isVoid() &&
2045-
fnType->getNumParams() == 0 &&
2046-
matchTypes(fnType->getResult(), rhs, ConstraintKind::Conversion,
2047-
TypeMatchFlags::TMF_ApplyingFix, locator)
2048-
.isSuccess()) {
2049-
conversionsOrFixes.push_back(
2050-
InsertExplicitCall::create(*this, getConstraintLocator(locator)));
2051-
return true;
2052-
}
2053-
}
2084+
if (repairByInsertingExplicitCall(lhs, rhs))
2085+
return true;
20542086

20552087
if (isa<InOutExpr>(AE->getSrc())) {
20562088
conversionsOrFixes.push_back(
@@ -2066,6 +2098,9 @@ bool ConstraintSystem::repairFailures(
20662098
switch (elt.getKind()) {
20672099
case ConstraintLocator::LValueConversion:
20682100
case ConstraintLocator::ApplyArgToParam: {
2101+
if (repairByInsertingExplicitCall(lhs, rhs))
2102+
return true;
2103+
20692104
if (lhs->getOptionalObjectType() && !rhs->getOptionalObjectType()) {
20702105
conversionsOrFixes.push_back(
20712106
ForceOptional::create(*this, lhs, lhs->getOptionalObjectType(),
@@ -2137,6 +2172,9 @@ bool ConstraintSystem::repairFailures(
21372172
return true;
21382173
}
21392174

2175+
if (repairByInsertingExplicitCall(lhs, rhs))
2176+
return true;
2177+
21402178
// If both types are key path, the only differences
21412179
// between them are mutability and/or root, value type mismatch.
21422180
if (isKnownKeyPathType(lhs) && isKnownKeyPathType(rhs)) {
@@ -2154,6 +2192,12 @@ bool ConstraintSystem::repairFailures(
21542192
break;
21552193
}
21562194

2195+
case ConstraintLocator::AutoclosureResult: {
2196+
if (repairByInsertingExplicitCall(lhs, rhs))
2197+
return true;
2198+
break;
2199+
}
2200+
21572201
default:
21582202
break;
21592203
}

test/Constraints/closures.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func inoutToSharedConversions() {
5555
// Autoclosure
5656
func f1(f: @autoclosure () -> Int) { }
5757
func f2() -> Int { }
58-
f1(f: f2) // expected-error{{function produces expected type 'Int'; did you mean to call it with '()'?}}{{9-9=()}}
58+
f1(f: f2) // expected-error{{add () to forward @autoclosure parameter}}{{9-9=()}}
5959
f1(f: 5)
6060

6161
// Ternary in closure
@@ -268,7 +268,7 @@ func someFunc(_ foo: ((String) -> String)?,
268268

269269
func verify_NotAC_to_AC_failure(_ arg: () -> ()) {
270270
func takesAC(_ arg: @autoclosure () -> ()) {}
271-
takesAC(arg) // expected-error {{function produces expected type '()'; did you mean to call it with '()'?}}
271+
takesAC(arg) // expected-error {{add () to forward @autoclosure parameter}} {{14-14=()}}
272272
}
273273

274274
// SR-1069 - Error diagnostic refers to wrong argument

test/Constraints/fixes.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ func forgotCall() {
3939
// With overloading: only one succeeds.
4040
a = createB // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}}
4141

42+
let _: A = createB // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}} {{21-21=()}}
43+
let _: B = createB // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}} {{21-21=()}}
44+
4245
// With overloading, pick the fewest number of fixes.
4346
var b = f7(f4, f1) // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}}
4447
b.iAmAB()

test/Constraints/keyword_arguments.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ func testClosures() {
317317

318318
func acceptAutoclosure(f: @autoclosure () -> Int) { }
319319
func produceInt() -> Int { }
320-
acceptAutoclosure(f: produceInt) // expected-error{{function produces expected type 'Int'; did you mean to call it with '()'?}} {{32-32=()}}
320+
acceptAutoclosure(f: produceInt) // expected-error{{add () to forward @autoclosure parameter}} {{32-32=()}}
321321

322322
// -------------------------------------------
323323
// Trailing closures

0 commit comments

Comments
 (0)