Skip to content

Commit bdfd4a8

Browse files
authored
Merge pull request swiftlang#35833 from xedin/couple-minor-incrementality-adjustments
[CSBindings] NFC: Couple minor incrementality adjustments
2 parents e2e78c6 + c7169ed commit bdfd4a8

File tree

2 files changed

+68
-56
lines changed

2 files changed

+68
-56
lines changed

include/swift/Sema/CSBindings.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -413,11 +413,7 @@ struct PotentialBindings {
413413

414414
/// Add a potential binding to the list of bindings,
415415
/// coalescing supertype bounds when we are able to compute the meet.
416-
///
417-
/// \returns true if this binding has been added to the set,
418-
/// false otherwise (e.g. because binding with this type is
419-
/// already in the set).
420-
bool addPotentialBinding(PotentialBinding binding, bool allowJoinMeet = true);
416+
void addPotentialBinding(PotentialBinding binding, bool allowJoinMeet = true);
421417

422418
/// Check if this binding is viable for inclusion in the set.
423419
bool isViable(PotentialBinding &binding) const;

lib/Sema/CSBindings.cpp

Lines changed: 67 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,6 @@ bool PotentialBinding::isViableForJoin() const {
5757
}
5858

5959
bool PotentialBindings::isDelayed() const {
60-
if (!DelayedBy.empty())
61-
return true;
62-
6360
if (isHole()) {
6461
auto *locator = TypeVar->getImpl().getLocator();
6562
assert(locator && "a hole without locator?");
@@ -76,9 +73,45 @@ bool PotentialBindings::isDelayed() const {
7673
// relies solely on contextual information.
7774
if (locator->directlyAt<NilLiteralExpr>())
7875
return true;
76+
77+
// It's possible that type of member couldn't be determined,
78+
// and if so it would be beneficial to bind member to a hole
79+
// early to propagate that information down to arguments,
80+
// result type of a call that references such a member.
81+
//
82+
// Note: This is done here instead of during binding inference,
83+
// because it's possible that variable is marked as a "hole"
84+
// (or that status is propagated to it) after constraints
85+
// mentioned below are recorded.
86+
return llvm::any_of(DelayedBy, [&](Constraint *constraint) {
87+
switch (constraint->getKind()) {
88+
case ConstraintKind::ApplicableFunction:
89+
case ConstraintKind::DynamicCallableApplicableFunction:
90+
case ConstraintKind::BindOverload: {
91+
return !ConstraintSystem::typeVarOccursInType(
92+
TypeVar, CS.simplifyType(constraint->getSecondType()));
93+
}
94+
95+
default:
96+
return true;
97+
}
98+
});
7999
}
80100

81-
return false;
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+
114+
return !DelayedBy.empty();
82115
}
83116

84117
bool PotentialBindings::involvesTypeVariables() const {
@@ -613,12 +646,12 @@ PotentialBindings::isLiteralCoveredBy(const LiteralRequirement &literal,
613646
} while (true);
614647
}
615648

616-
bool PotentialBindings::addPotentialBinding(PotentialBinding binding,
649+
void PotentialBindings::addPotentialBinding(PotentialBinding binding,
617650
bool allowJoinMeet) {
618651
assert(!binding.BindingType->is<ErrorType>());
619652

620653
if (Bindings.count(binding))
621-
return false;
654+
return;
622655

623656
// If this is a non-defaulted supertype binding,
624657
// check whether we can combine it with another
@@ -657,7 +690,7 @@ bool PotentialBindings::addPotentialBinding(PotentialBinding binding,
657690
// If new binding has been joined with at least one of existing
658691
// bindings, there is no reason to include it into the set.
659692
if (!joined.empty())
660-
return false;
693+
return;
661694
}
662695

663696
// If the type variable can't bind to an lvalue, make sure the
@@ -668,7 +701,7 @@ bool PotentialBindings::addPotentialBinding(PotentialBinding binding,
668701
}
669702

670703
if (!isViable(binding))
671-
return false;
704+
return;
672705

673706
// Check whether the given binding covers any of the literal protocols
674707
// associated with this type variable.
@@ -703,7 +736,7 @@ bool PotentialBindings::addPotentialBinding(PotentialBinding binding,
703736
}
704737
}
705738

706-
return Bindings.insert(std::move(binding));
739+
Bindings.insert(std::move(binding));
707740
}
708741

709742
void PotentialBindings::addLiteral(Constraint *constraint) {
@@ -1106,38 +1139,7 @@ void PotentialBindings::infer(Constraint *constraint) {
11061139
if (!binding)
11071140
break;
11081141

1109-
auto type = binding->BindingType;
1110-
if (addPotentialBinding(*binding)) {
1111-
// Determines whether this type variable represents an object
1112-
// of the optional type extracted by force unwrap.
1113-
if (auto *locator = TypeVar->getImpl().getLocator()) {
1114-
auto anchor = locator->getAnchor();
1115-
// Result of force unwrap is always connected to its base
1116-
// optional type via `OptionalObject` constraint which
1117-
// preserves l-valueness, so in case where object type got
1118-
// inferred before optional type (because it got the
1119-
// type from context e.g. parameter type of a function call),
1120-
// we need to test type with and without l-value after
1121-
// delaying bindings for as long as possible.
1122-
if (isExpr<ForceValueExpr>(anchor) &&
1123-
TypeVar->getImpl().canBindToLValue() && !type->is<LValueType>()) {
1124-
(void)addPotentialBinding(binding->withType(LValueType::get(type)));
1125-
DelayedBy.push_back(constraint);
1126-
}
1127-
1128-
// If this is a type variable representing closure result,
1129-
// which is on the right-side of some relational constraint
1130-
// let's have it try `Void` as well because there is an
1131-
// implicit conversion `() -> T` to `() -> Void` and this
1132-
// helps to avoid creating a thunk to support it.
1133-
auto voidType = CS.getASTContext().TheEmptyTupleType;
1134-
if (locator->isLastElement<LocatorPathElt::ClosureResult>() &&
1135-
binding->Kind == AllowedBindingKind::Supertypes) {
1136-
(void)addPotentialBinding({voidType, binding->Kind, constraint},
1137-
/*allowJoinMeet=*/false);
1138-
}
1139-
}
1140-
}
1142+
addPotentialBinding(*binding);
11411143
break;
11421144
}
11431145
case ConstraintKind::KeyPathApplication: {
@@ -1220,16 +1222,6 @@ void PotentialBindings::infer(Constraint *constraint) {
12201222
case ConstraintKind::ApplicableFunction:
12211223
case ConstraintKind::DynamicCallableApplicableFunction:
12221224
case ConstraintKind::BindOverload: {
1223-
// It's possible that type of member couldn't be determined,
1224-
// and if so it would be beneficial to bind member to a hole
1225-
// early to propagate that information down to arguments,
1226-
// result type of a call that references such a member.
1227-
if (CS.shouldAttemptFixes() && TypeVar->getImpl().canBindToHole()) {
1228-
if (ConstraintSystem::typeVarOccursInType(
1229-
TypeVar, CS.simplifyType(constraint->getSecondType())))
1230-
break;
1231-
}
1232-
12331225
DelayedBy.push_back(constraint);
12341226
break;
12351227
}
@@ -1464,6 +1456,19 @@ bool TypeVarBindingProducer::computeNext() {
14641456
}
14651457
}
14661458

1459+
if (getLocator()->directlyAt<ForceValueExpr>() &&
1460+
TypeVar->getImpl().canBindToLValue() &&
1461+
!binding.BindingType->is<LValueType>()) {
1462+
// Result of force unwrap is always connected to its base
1463+
// optional type via `OptionalObject` constraint which
1464+
// preserves l-valueness, so in case where object type got
1465+
// inferred before optional type (because it got the
1466+
// type from context e.g. parameter type of a function call),
1467+
// we need to test type with and without l-value after
1468+
// delaying bindings for as long as possible.
1469+
addNewBinding(binding.withType(LValueType::get(binding.BindingType)));
1470+
}
1471+
14671472
// Allow solving for T even for a binding kind where that's invalid
14681473
// if fixes are allowed, because that gives us the opportunity to
14691474
// match T? values to the T binding by adding an unwrap fix.
@@ -1504,6 +1509,17 @@ bool TypeVarBindingProducer::computeNext() {
15041509
}
15051510

15061511
if (binding.Kind == BindingKind::Supertypes) {
1512+
// If this is a type variable representing closure result,
1513+
// which is on the right-side of some relational constraint
1514+
// let's have it try `Void` as well because there is an
1515+
// implicit conversion `() -> T` to `() -> Void` and this
1516+
// helps to avoid creating a thunk to support it.
1517+
if (getLocator()->isLastElement<LocatorPathElt::ClosureResult>() &&
1518+
binding.Kind == AllowedBindingKind::Supertypes) {
1519+
auto voidType = CS.getASTContext().TheEmptyTupleType;
1520+
addNewBinding(binding.withSameSource(voidType, BindingKind::Exact));
1521+
}
1522+
15071523
for (auto supertype : enumerateDirectSupertypes(type)) {
15081524
// If we're not allowed to try this binding, skip it.
15091525
if (auto simplifiedSuper = checkTypeOfBinding(TypeVar, supertype))

0 commit comments

Comments
 (0)