Skip to content

Commit b004dce

Browse files
committed
[CSBindings] Attempt l-value fallback for force unwrap only after r-value type failed
Previously l-value binding would be paired with discovered r-value one but that is not necessary and can cause issues with ranking since there is no way to filter this "fallback" binding from the set.
1 parent f7432f8 commit b004dce

File tree

1 file changed

+27
-20
lines changed

1 file changed

+27
-20
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,19 @@ bool PotentialBindings::isDelayed() const {
9898
});
9999
}
100100

101+
if (auto *locator = TypeVar->getImpl().getLocator()) {
102+
// Since force unwrap preserves l-valueness, resulting
103+
// type variable has to be delayed until either l-value
104+
// binding becomes available or there are no other
105+
// variables to attempt.
106+
if (locator->directlyAt<ForceValueExpr>() &&
107+
TypeVar->getImpl().canBindToLValue()) {
108+
return llvm::none_of(Bindings, [](const PotentialBinding &binding) {
109+
return binding.BindingType->is<LValueType>();
110+
});
111+
}
112+
}
113+
101114
return !DelayedBy.empty();
102115
}
103116

@@ -1088,26 +1101,7 @@ void PotentialBindings::infer(Constraint *constraint) {
10881101
if (!binding)
10891102
break;
10901103

1091-
auto type = binding->BindingType;
1092-
if (addPotentialBinding(*binding)) {
1093-
// Determines whether this type variable represents an object
1094-
// of the optional type extracted by force unwrap.
1095-
if (auto *locator = TypeVar->getImpl().getLocator()) {
1096-
auto anchor = locator->getAnchor();
1097-
// Result of force unwrap is always connected to its base
1098-
// optional type via `OptionalObject` constraint which
1099-
// preserves l-valueness, so in case where object type got
1100-
// inferred before optional type (because it got the
1101-
// type from context e.g. parameter type of a function call),
1102-
// we need to test type with and without l-value after
1103-
// delaying bindings for as long as possible.
1104-
if (isExpr<ForceValueExpr>(anchor) &&
1105-
TypeVar->getImpl().canBindToLValue() && !type->is<LValueType>()) {
1106-
(void)addPotentialBinding(binding->withType(LValueType::get(type)));
1107-
DelayedBy.push_back(constraint);
1108-
}
1109-
}
1110-
}
1104+
addPotentialBinding(*binding);
11111105
break;
11121106
}
11131107
case ConstraintKind::KeyPathApplication: {
@@ -1424,6 +1418,19 @@ bool TypeVarBindingProducer::computeNext() {
14241418
}
14251419
}
14261420

1421+
if (getLocator()->directlyAt<ForceValueExpr>() &&
1422+
TypeVar->getImpl().canBindToLValue() &&
1423+
!binding.BindingType->is<LValueType>()) {
1424+
// Result of force unwrap is always connected to its base
1425+
// optional type via `OptionalObject` constraint which
1426+
// preserves l-valueness, so in case where object type got
1427+
// inferred before optional type (because it got the
1428+
// type from context e.g. parameter type of a function call),
1429+
// we need to test type with and without l-value after
1430+
// delaying bindings for as long as possible.
1431+
addNewBinding(binding.withType(LValueType::get(binding.BindingType)));
1432+
}
1433+
14271434
// Allow solving for T even for a binding kind where that's invalid
14281435
// if fixes are allowed, because that gives us the opportunity to
14291436
// match T? values to the T binding by adding an unwrap fix.

0 commit comments

Comments
 (0)