Skip to content

Commit 54406b4

Browse files
committed
[ConstraintSystem] Track constraints that caused bindings to be "fully bound"
- Keep track of all constraints which caused a particular type variable to be de-prioritized. - Convert a property to a method which would determine whether given set of potential bindings is "fully bound" and has to be delayed until certain constraints are simplified.
1 parent 509f905 commit 54406b4

File tree

2 files changed

+42
-32
lines changed

2 files changed

+42
-32
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4738,9 +4738,8 @@ class ConstraintSystem {
47384738
/// The set of constraints which would be used to infer default types.
47394739
llvm::TinyPtrVector<Constraint *> Defaults;
47404740

4741-
/// Whether these bindings should be delayed until the rest of the
4742-
/// constraint system is considered "fully bound".
4743-
bool FullyBound = false;
4741+
/// The set of constraints which delay attempting this type variable.
4742+
llvm::TinyPtrVector<Constraint *> DelayedBy;
47444743

47454744
/// Whether the bindings of this type involve other type variables.
47464745
bool InvolvesTypeVariables = false;
@@ -4763,6 +4762,10 @@ class ConstraintSystem {
47634762
/// Determine whether the set of bindings is non-empty.
47644763
explicit operator bool() const { return !Bindings.empty(); }
47654764

4765+
/// Whether these bindings should be delayed until the rest of the
4766+
/// constraint system is considered "fully bound".
4767+
bool isFullyBound() const;
4768+
47664769
/// Whether the bindings represent (potentially) incomplete set,
47674770
/// there is no way to say with absolute certainty if that's the
47684771
/// case, but that could happen when certain constraints like
@@ -4805,7 +4808,7 @@ class ConstraintSystem {
48054808

48064809
return std::make_tuple(b.isHole(),
48074810
!hasNoDefaultableBindings,
4808-
b.FullyBound,
4811+
b.isFullyBound(),
48094812
b.isSubtypeOfExistentialType(),
48104813
b.InvolvesTypeVariables,
48114814
static_cast<unsigned char>(b.LiteralBinding),
@@ -4952,7 +4955,7 @@ class ConstraintSystem {
49524955
out.indent(indent);
49534956
if (isPotentiallyIncomplete())
49544957
out << "potentially_incomplete ";
4955-
if (FullyBound)
4958+
if (isFullyBound())
49564959
out << "fully_bound ";
49574960
if (isSubtypeOfExistentialType())
49584961
out << "subtype_of_existential ";

lib/Sema/CSBindings.cpp

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,31 @@ bool ConstraintSystem::PotentialBinding::isViableForJoin() const {
3333
!isDefaultableBinding();
3434
}
3535

36+
bool ConstraintSystem::PotentialBindings::isFullyBound() const {
37+
if (!DelayedBy.empty())
38+
return true;
39+
40+
if (isHole()) {
41+
auto *locator = TypeVar->getImpl().getLocator();
42+
assert(locator && "a hole without locator?");
43+
44+
// Delay resolution of the code completion expression until
45+
// the very end to give it a chance to be bound to some
46+
// contextual type even if it's a hole.
47+
if (locator->directlyAt<CodeCompletionExpr>())
48+
return true;
49+
50+
// Delay resolution of the `nil` literal to a hole until
51+
// the very end to give it a change to be bound to some
52+
// other type, just like code completion expression which
53+
// relies solely on contextual information.
54+
if (locator->directlyAt<NilLiteralExpr>())
55+
return true;
56+
}
57+
58+
return false;
59+
}
60+
3661
bool ConstraintSystem::PotentialBindings::isPotentiallyIncomplete() const {
3762
// Generic parameters are always potentially incomplete.
3863
if (isGenericParameter())
@@ -555,19 +580,6 @@ void ConstraintSystem::PotentialBindings::finalize(
555580
// very last moment possible, just like generic parameters.
556581
auto *locator = TypeVar->getImpl().getLocator();
557582

558-
// Delay resolution of the code completion expression until
559-
// the very end to give it a chance to be bound to some
560-
// contextual type even if it's a hole.
561-
if (locator->directlyAt<CodeCompletionExpr>())
562-
FullyBound = true;
563-
564-
// Delay resolution of the `nil` literal to a hole until
565-
// the very end to give it a change to be bound to some
566-
// other type, just like code completion expression which
567-
// relies solely on contextual information.
568-
if (locator->directlyAt<NilLiteralExpr>())
569-
FullyBound = true;
570-
571583
// If this type variable is associated with a code completion token
572584
// and it failed to infer any bindings let's adjust hole's locator
573585
// to point to a code completion token to avoid attempting to "fix"
@@ -776,7 +788,7 @@ bool ConstraintSystem::PotentialBindings::isViable(
776788

777789
bool ConstraintSystem::PotentialBindings::favoredOverDisjunction(
778790
Constraint *disjunction) const {
779-
if (isHole() || FullyBound)
791+
if (isHole() || isFullyBound())
780792
return false;
781793

782794
// If this bindings are for a closure and there are no holes,
@@ -872,7 +884,7 @@ ConstraintSystem::getPotentialBindingForRelationalConstraint(
872884
if (auto *typeVar = first->getAs<TypeVariableType>()) {
873885
if (typeVar->getImpl().isClosureType()) {
874886
result.InvolvesTypeVariables = true;
875-
result.FullyBound = true;
887+
result.DelayedBy.push_back(constraint);
876888
return None;
877889
}
878890
}
@@ -918,7 +930,7 @@ ConstraintSystem::getPotentialBindingForRelationalConstraint(
918930
if (type->is<DependentMemberType>()) {
919931
if (!ConstraintSystem::typeVarOccursInType(typeVar, type,
920932
&result.InvolvesTypeVariables)) {
921-
result.FullyBound = true;
933+
result.DelayedBy.push_back(constraint);
922934
}
923935

924936
return None;
@@ -1056,7 +1068,7 @@ bool ConstraintSystem::PotentialBindings::infer(
10561068
// delaying bindings for as long as possible.
10571069
if (isExpr<ForceValueExpr>(anchor) && !type->is<LValueType>()) {
10581070
addPotentialBinding(binding->withType(LValueType::get(type)));
1059-
FullyBound = true;
1071+
DelayedBy.push_back(constraint);
10601072
}
10611073

10621074
// If this is a type variable representing closure result,
@@ -1076,9 +1088,6 @@ bool ConstraintSystem::PotentialBindings::infer(
10761088
break;
10771089
}
10781090
case ConstraintKind::KeyPathApplication: {
1079-
if (FullyBound)
1080-
return false;
1081-
10821091
// If this variable is in the application projected result type, mark the
10831092
// result as `FullyBound` to ensure we delay binding until we've bound
10841093
// other type variables in the KeyPathApplication constraint. This ensures
@@ -1087,8 +1096,9 @@ bool ConstraintSystem::PotentialBindings::infer(
10871096
SmallPtrSet<TypeVariableType *, 4> typeVars;
10881097
findInferableTypeVars(cs.simplifyType(constraint->getThirdType()),
10891098
typeVars);
1090-
if (typeVars.count(TypeVar))
1091-
FullyBound = true;
1099+
if (typeVars.count(TypeVar)) {
1100+
DelayedBy.push_back(constraint);
1101+
}
10921102

10931103
break;
10941104
}
@@ -1162,15 +1172,12 @@ bool ConstraintSystem::PotentialBindings::infer(
11621172
case ConstraintKind::ApplicableFunction:
11631173
case ConstraintKind::DynamicCallableApplicableFunction:
11641174
case ConstraintKind::BindOverload: {
1165-
if (FullyBound && InvolvesTypeVariables)
1166-
return false;
1167-
11681175
// If this variable is in the left-hand side, it is fully bound.
11691176
SmallPtrSet<TypeVariableType *, 4> typeVars;
11701177
findInferableTypeVars(cs.simplifyType(constraint->getFirstType()),
11711178
typeVars);
11721179
if (typeVars.count(TypeVar))
1173-
FullyBound = true;
1180+
DelayedBy.push_back(constraint);
11741181

11751182
if (InvolvesTypeVariables)
11761183
return false;
@@ -1203,7 +1210,7 @@ bool ConstraintSystem::PotentialBindings::infer(
12031210
if (ConstraintSystem::typeVarOccursInType(
12041211
TypeVar, cs.simplifyType(constraint->getSecondType()),
12051212
&InvolvesTypeVariables)) {
1206-
FullyBound = true;
1213+
DelayedBy.push_back(constraint);
12071214
}
12081215
break;
12091216

0 commit comments

Comments
 (0)