Skip to content

Commit f7432f8

Browse files
committed
[CSBindings] Attempt Void fallback for closure result only when other choices have failed
Since there is a conversion from `() -> T` to `() -> Void` for closures, solver has to attempt a `Void` when other bindings (inferred from the body) have failed. Let's try it post factum instead of adding `Void` fallback to the binding set after every discovered supertype binding. Old scheme wouldn't work in incremental mode anyway because it's possible to find a subtype binding (which makes it clear that body has to have a result type) after a supertype and end up attempting `Void` although it would be incorrect.
1 parent 8726d88 commit f7432f8

File tree

1 file changed

+11
-12
lines changed

1 file changed

+11
-12
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,18 +1106,6 @@ void PotentialBindings::infer(Constraint *constraint) {
11061106
(void)addPotentialBinding(binding->withType(LValueType::get(type)));
11071107
DelayedBy.push_back(constraint);
11081108
}
1109-
1110-
// If this is a type variable representing closure result,
1111-
// which is on the right-side of some relational constraint
1112-
// let's have it try `Void` as well because there is an
1113-
// implicit conversion `() -> T` to `() -> Void` and this
1114-
// helps to avoid creating a thunk to support it.
1115-
auto voidType = CS.getASTContext().TheEmptyTupleType;
1116-
if (locator->isLastElement<LocatorPathElt::ClosureResult>() &&
1117-
binding->Kind == AllowedBindingKind::Supertypes) {
1118-
(void)addPotentialBinding({voidType, binding->Kind, constraint},
1119-
/*allowJoinMeet=*/false);
1120-
}
11211109
}
11221110
}
11231111
break;
@@ -1476,6 +1464,17 @@ bool TypeVarBindingProducer::computeNext() {
14761464
}
14771465

14781466
if (binding.Kind == BindingKind::Supertypes) {
1467+
// If this is a type variable representing closure result,
1468+
// which is on the right-side of some relational constraint
1469+
// let's have it try `Void` as well because there is an
1470+
// implicit conversion `() -> T` to `() -> Void` and this
1471+
// helps to avoid creating a thunk to support it.
1472+
if (getLocator()->isLastElement<LocatorPathElt::ClosureResult>() &&
1473+
binding.Kind == AllowedBindingKind::Supertypes) {
1474+
auto voidType = CS.getASTContext().TheEmptyTupleType;
1475+
addNewBinding(binding.withSameSource(voidType, BindingKind::Exact));
1476+
}
1477+
14791478
for (auto supertype : enumerateDirectSupertypes(type)) {
14801479
// If we're not allowed to try this binding, skip it.
14811480
if (auto simplifiedSuper = checkTypeOfBinding(TypeVar, supertype))

0 commit comments

Comments
 (0)