Skip to content

Commit b3db3e4

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) (cherry picked from commit cb3252e)
1 parent bc9d233 commit b3db3e4

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
@@ -1688,6 +1688,33 @@ bool MissingCallFailure::diagnoseAsError() {
16881688
if (isa<KeyPathExpr>(baseExpr))
16891689
return false;
16901690

1691+
auto path = getLocator()->getPath();
1692+
if (!path.empty()) {
1693+
const auto &last = path.back();
1694+
1695+
switch (last.getKind()) {
1696+
case ConstraintLocator::ContextualType:
1697+
case ConstraintLocator::ApplyArgToParam: {
1698+
auto fnType = getType(baseExpr)->castTo<FunctionType>();
1699+
assert(fnType->getNumParams() == 0);
1700+
emitDiagnostic(baseExpr->getLoc(), diag::missing_nullary_call,
1701+
fnType->getResult())
1702+
.fixItInsertAfter(baseExpr->getEndLoc(), "()");
1703+
return true;
1704+
}
1705+
1706+
case ConstraintLocator::AutoclosureResult: {
1707+
auto &cs = getConstraintSystem();
1708+
auto loc = cs.getConstraintLocator(getRawAnchor(), path.drop_back(),
1709+
/*summaryFlags=*/0);
1710+
AutoClosureForwardingFailure failure(cs, loc);
1711+
return failure.diagnoseAsError();
1712+
}
1713+
default:
1714+
break;
1715+
}
1716+
}
1717+
16911718
if (auto *DRE = dyn_cast<DeclRefExpr>(baseExpr)) {
16921719
emitDiagnostic(baseExpr->getLoc(), diag::did_not_call_function,
16931720
DRE->getDecl()->getBaseName().getIdentifier())

lib/Sema/CSSimplify.cpp

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

1981+
// If there is a missing explicit call it could be:
1982+
//
1983+
// a). Contextual e.g. `let _: R = foo`
1984+
// b). Argument is a function value passed to parameter
1985+
// which expects its result type e.g. `foo(bar)`
1986+
// c). Assigment destination type matches return type of
1987+
// of the function value e.g. `foo = bar` or `foo = .bar`
1988+
auto repairByInsertingExplicitCall = [&](Type srcType, Type dstType) -> bool {
1989+
auto fnType = srcType->getAs<FunctionType>();
1990+
if (!fnType || fnType->getNumParams() > 0)
1991+
return false;
1992+
1993+
auto resultType = fnType->getResult();
1994+
// If this is situation like `x = { ... }` where closure results in
1995+
// `Void`, let's not suggest to call the closure, because it's most
1996+
// likely not intended.
1997+
if (anchor && isa<AssignExpr>(anchor)) {
1998+
auto *assignment = cast<AssignExpr>(anchor);
1999+
if (isa<ClosureExpr>(assignment->getSrc()) && resultType->isVoid())
2000+
return false;
2001+
}
2002+
2003+
// If left-hand side is a function type but right-hand
2004+
// side isn't, let's check it would be possible to fix
2005+
// this by forming an explicit call.
2006+
auto convertTo = dstType->lookThroughAllOptionalTypes();
2007+
// Right-hand side can't be - a function, a type variable or dependent
2008+
// member, or `Any` (if function conversion to `Any` didn't succeed there
2009+
// is something else going on e.g. problem with escapiness).
2010+
if (convertTo->is<FunctionType>() || convertTo->isTypeVariableOrMember() ||
2011+
convertTo->isAny())
2012+
return false;
2013+
2014+
auto result = matchTypes(resultType, dstType, ConstraintKind::Conversion,
2015+
TypeMatchFlags::TMF_ApplyingFix, locator);
2016+
2017+
if (result.isSuccess()) {
2018+
conversionsOrFixes.push_back(
2019+
InsertExplicitCall::create(*this, getConstraintLocator(locator)));
2020+
return true;
2021+
}
2022+
2023+
return false;
2024+
};
2025+
19812026
if (path.empty()) {
19822027
if (!anchor)
19832028
return false;
@@ -1994,21 +2039,8 @@ bool ConstraintSystem::repairFailures(
19942039
}
19952040

19962041
if (auto *AE = dyn_cast<AssignExpr>(anchor)) {
1997-
if (auto *fnType = lhs->getAs<FunctionType>()) {
1998-
// If left-hand side is a function type but right-hand
1999-
// side isn't, let's check it would be possible to fix
2000-
// this by forming an explicit call.
2001-
auto convertTo = rhs->lookThroughAllOptionalTypes();
2002-
if (!convertTo->is<FunctionType>() && !convertTo->isVoid() &&
2003-
fnType->getNumParams() == 0 &&
2004-
matchTypes(fnType->getResult(), rhs, ConstraintKind::Conversion,
2005-
TypeMatchFlags::TMF_ApplyingFix, locator)
2006-
.isSuccess()) {
2007-
conversionsOrFixes.push_back(
2008-
InsertExplicitCall::create(*this, getConstraintLocator(locator)));
2009-
return true;
2010-
}
2011-
}
2042+
if (repairByInsertingExplicitCall(lhs, rhs))
2043+
return true;
20122044

20132045
if (isa<InOutExpr>(AE->getSrc())) {
20142046
conversionsOrFixes.push_back(
@@ -2024,6 +2056,9 @@ bool ConstraintSystem::repairFailures(
20242056
switch (elt.getKind()) {
20252057
case ConstraintLocator::LValueConversion:
20262058
case ConstraintLocator::ApplyArgToParam: {
2059+
if (repairByInsertingExplicitCall(lhs, rhs))
2060+
return true;
2061+
20272062
if (lhs->getOptionalObjectType() && !rhs->getOptionalObjectType()) {
20282063
conversionsOrFixes.push_back(
20292064
ForceOptional::create(*this, lhs, lhs->getOptionalObjectType(),
@@ -2095,6 +2130,9 @@ bool ConstraintSystem::repairFailures(
20952130
return true;
20962131
}
20972132

2133+
if (repairByInsertingExplicitCall(lhs, rhs))
2134+
return true;
2135+
20982136
// If both types are key path, the only differences
20992137
// between them are mutability and/or root, value type mismatch.
21002138
if (isKnownKeyPathType(lhs) && isKnownKeyPathType(rhs)) {
@@ -2112,6 +2150,12 @@ bool ConstraintSystem::repairFailures(
21122150
break;
21132151
}
21142152

2153+
case ConstraintLocator::AutoclosureResult: {
2154+
if (repairByInsertingExplicitCall(lhs, rhs))
2155+
return true;
2156+
break;
2157+
}
2158+
21152159
default:
21162160
break;
21172161
}

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)