Skip to content

Commit b82a8c5

Browse files
committed
[ConstraintSystem] Diagnose missing explicit calls in assignment
If the source of the assignment is a function type which has a result that could be converted to expected destination type, let's diagnose that as missing call if such function doesn't have any parameters.
1 parent 0ad0a84 commit b82a8c5

File tree

3 files changed

+37
-5
lines changed

3 files changed

+37
-5
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,6 +1589,17 @@ bool MissingCallFailure::diagnoseAsError() {
15891589
}
15901590
}
15911591

1592+
if (auto *AE = dyn_cast<AssignExpr>(baseExpr)) {
1593+
auto *srcExpr = AE->getSrc();
1594+
if (auto *fnType = getType(srcExpr)->getAs<FunctionType>()) {
1595+
emitDiagnostic(srcExpr->getLoc(), diag::missing_nullary_call,
1596+
fnType->getResult())
1597+
.highlight(srcExpr->getSourceRange())
1598+
.fixItInsertAfter(srcExpr->getEndLoc(), "()");
1599+
return true;
1600+
}
1601+
}
1602+
15921603
emitDiagnostic(baseExpr->getLoc(), diag::did_not_call_function_value)
15931604
.fixItInsertAfter(insertLoc, "()");
15941605
return true;

lib/Sema/CSSimplify.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1985,16 +1985,37 @@ bool ConstraintSystem::repairFailures(
19851985
auto *anchor = locator.getLocatorParts(path);
19861986

19871987
if (path.empty()) {
1988+
if (!anchor)
1989+
return false;
1990+
19881991
// If method reference forms a value type of the key path,
19891992
// there is going to be a constraint to match result of the
19901993
// member lookup to the generic parameter `V` of *KeyPath<R, V>
19911994
// type associated with key path expression, which we need to
19921995
// fix-up here.
1993-
if (anchor && isa<KeyPathExpr>(anchor)) {
1996+
if (isa<KeyPathExpr>(anchor)) {
19941997
auto *fnType = lhs->getAs<FunctionType>();
19951998
if (fnType && fnType->getResult()->isEqual(rhs))
19961999
return true;
19972000
}
2001+
2002+
if (isa<AssignExpr>(anchor)) {
2003+
if (auto *fnType = lhs->getAs<FunctionType>()) {
2004+
// If left-hand side is a function type but right-hand
2005+
// side isn't, let's check it would be possible to fix
2006+
// this by forming an explicit call.
2007+
if (!rhs->is<FunctionType>() && !rhs->isVoid() &&
2008+
fnType->getNumParams() == 0 &&
2009+
matchTypes(fnType->getResult(), rhs, ConstraintKind::Conversion,
2010+
TypeMatchFlags::TMF_ApplyingFix, locator)
2011+
.isSuccess()) {
2012+
conversionsOrFixes.push_back(
2013+
InsertExplicitCall::create(*this, getConstraintLocator(locator)));
2014+
return true;
2015+
}
2016+
}
2017+
}
2018+
19982019
return false;
19992020
}
20002021

@@ -6447,6 +6468,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
64476468
return result;
64486469
}
64496470

6471+
case FixKind::InsertCall:
64506472
case FixKind::SkipSameTypeRequirement:
64516473
case FixKind::SkipSuperclassRequirement:
64526474
case FixKind::ContextualMismatch:
@@ -6455,7 +6477,6 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
64556477
}
64566478

64576479
case FixKind::UseSubscriptOperator:
6458-
case FixKind::InsertCall:
64596480
case FixKind::ExplicitlyEscaping:
64606481
case FixKind::CoerceToCheckedCast:
64616482
case FixKind::RelabelArguments:

test/Constraints/fixes.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ func f4() -> B { }
1414
func f5(_ a: A) { }
1515
func f6(_ a: A, _: Int) { }
1616

17-
func createB() -> B { } // expected-note {{found this candidate}}
18-
func createB(_ i: Int) -> B { } // expected-note {{found this candidate}}
17+
func createB() -> B { }
18+
func createB(_ i: Int) -> B { }
1919

2020
func f7(_ a: A, _: @escaping () -> Int) -> B { }
2121
func f7(_ a: A, _: Int) -> Int { }
@@ -37,7 +37,7 @@ func forgotCall() {
3737
f6(f4, f2) // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}}{{8-8=()}}
3838

3939
// With overloading: only one succeeds.
40-
a = createB // expected-error{{ambiguous reference to member 'createB()'}}
40+
a = createB // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}}
4141

4242
// With overloading, pick the fewest number of fixes.
4343
var b = f7(f4, f1) // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}}

0 commit comments

Comments
 (0)