Skip to content

Commit dea79e0

Browse files
committed
[ConstraintSystem] Detect that function type has failures before applying arguments
If a type variable representing "function type" is a hole or it could be bound to some concrete type with a help of a fix, let's propagate holes to the "input" type. Doing so provides more information to upcoming argument and result matching.
1 parent c7c9510 commit dea79e0

File tree

4 files changed

+26
-14
lines changed

4 files changed

+26
-14
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7518,6 +7518,18 @@ ConstraintSystem::simplifyApplicableFnConstraint(
75187518
// following: $T1 -> $T2.
75197519
auto func1 = type1->castTo<FunctionType>();
75207520

7521+
// If a type variable representing "function type" is a hole
7522+
// or it could be bound to some concrete type with a help of
7523+
// a fix, let's propagate holes to the "input" type. Doing so
7524+
// provides more information to upcoming argument and result matching.
7525+
if (shouldAttemptFixes()) {
7526+
if (auto *typeVar = type2->getAs<TypeVariableType>()) {
7527+
auto *locator = typeVar->getImpl().getLocator();
7528+
if (typeVar->isHole() || hasFixFor(locator))
7529+
recordPotentialHole(func1);
7530+
}
7531+
}
7532+
75217533
// Before stripping lvalue-ness and optional types, save the original second
75227534
// type for handling `func callAsFunction` and `@dynamicCallable`
75237535
// applications. This supports the following cases:
@@ -7730,10 +7742,7 @@ ConstraintSystem::simplifyApplicableFnConstraint(
77307742

77317743
// If there are any type variables associated with arguments/result
77327744
// they have to be marked as "holes".
7733-
type1.visit([&](Type subType) {
7734-
if (auto *typeVar = subType->getAs<TypeVariableType>())
7735-
recordPotentialHole(typeVar);
7736-
});
7745+
recordPotentialHole(func1);
77377746

77387747
if (desugar2->isHole())
77397748
return SolutionKind::Solved;
@@ -8007,11 +8016,7 @@ ConstraintSystem::simplifyDynamicCallableApplicableFnConstraint(
80078016
return SolutionKind::Error;
80088017

80098018
recordPotentialHole(tv);
8010-
8011-
Type(func1).visit([&](Type type) {
8012-
if (auto *typeVar = type->getAs<TypeVariableType>())
8013-
recordPotentialHole(typeVar);
8014-
});
8019+
recordPotentialHole(func1);
80158020

80168021
return SolutionKind::Solved;
80178022
}
@@ -8572,6 +8577,14 @@ void ConstraintSystem::recordPotentialHole(TypeVariableType *typeVar) {
85728577
typeVar->getImpl().enableCanBindToHole(getSavedBindings());
85738578
}
85748579

8580+
void ConstraintSystem::recordPotentialHole(FunctionType *fnType) {
8581+
assert(fnType);
8582+
Type(fnType).visit([&](Type type) {
8583+
if (auto *typeVar = type->getAs<TypeVariableType>())
8584+
recordPotentialHole(typeVar);
8585+
});
8586+
}
8587+
85758588
ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
85768589
ConstraintFix *fix, Type type1, Type type2, ConstraintKind matchKind,
85778590
TypeMatchOptions flags, ConstraintLocatorBuilder locator) {

lib/Sema/ConstraintSystem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2361,6 +2361,7 @@ class ConstraintSystem {
23612361
bool recordFix(ConstraintFix *fix, unsigned impact = 1);
23622362

23632363
void recordPotentialHole(TypeVariableType *typeVar);
2364+
void recordPotentialHole(FunctionType *fnType);
23642365

23652366
/// Determine whether constraint system already has a fix recorded
23662367
/// for a particular location.

test/Constraints/bridging.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ func rdar19831698() {
265265
var v71 = true + 1.0 // expected-error{{binary operator '+' cannot be applied to operands of type 'Bool' and 'Double'}}
266266
// expected-note@-1{{overloads for '+'}}
267267
var v72 = true + true // expected-error{{binary operator '+' cannot be applied to two 'Bool' operands}}
268-
var v73 = true + [] // expected-error@:13 {{cannot convert value of type 'Bool' to expected argument type 'Array<Bool>'}}
268+
var v73 = true + [] // expected-error@:18 {{binary operator '+' cannot be applied to operands of type 'Bool' and '[Any]'}}
269269
var v75 = true + "str" // expected-error@:13 {{cannot convert value of type 'Bool' to expected argument type 'String'}}
270270
}
271271

test/expr/expressions.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -748,10 +748,8 @@ func invalidDictionaryLiteral() {
748748
}
749749

750750

751-
[4].joined(separator: [1]) // expected-error {{cannot convert value of type 'Int' to expected element type 'String'}}
752-
// expected-error@-1 {{cannot convert value of type '[Int]' to expected argument type 'String'}}
753-
[4].joined(separator: [[[1]]]) // expected-error {{cannot convert value of type 'Int' to expected element type 'String'}}
754-
// expected-error@-1 {{cannot convert value of type '[[[Int]]]' to expected argument type 'String'}}
751+
[4].joined(separator: [1]) // expected-error {{referencing instance method 'joined(separator:)' on 'Sequence' requires that 'Int' conform to 'Sequence'}}
752+
[4].joined(separator: [[[1]]]) // expected-error {{referencing instance method 'joined(separator:)' on 'Sequence' requires that 'Int' conform to 'Sequence'}}
755753

756754
//===----------------------------------------------------------------------===//
757755
// nil/metatype comparisons

0 commit comments

Comments
 (0)