Skip to content

Commit bb51a8f

Browse files
committed
[ConstraintSystem] Use originating constraint as a source for a binding
Unify all of the fields of `PotentialBinding` which have to do with location information into a single field with is either a constraint (for regular bindings) or constraint locator (for "holes"). This helps to reduce the amount of space used by `PotentialBinding` as well as propagate more contextual information when binding gets attempted.
1 parent 9cbc761 commit bb51a8f

File tree

2 files changed

+91
-52
lines changed

2 files changed

+91
-52
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 26 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ ConstraintSystem::determineBestBindings() {
8181
continue;
8282

8383
bindings.addPotentialBinding(
84-
{type, AllowedBindingKind::Supertypes, binding.BindingSource});
84+
binding.withSameSource(type, AllowedBindingKind::Supertypes));
8585
}
8686
}
8787

@@ -143,8 +143,8 @@ void ConstraintSystem::PotentialBindings::addPotentialBinding(
143143
!binding.BindingType->hasUnresolvedType() &&
144144
!binding.BindingType->hasTypeVariable() &&
145145
!binding.BindingType->hasUnboundGenericType() &&
146-
!binding.DefaultedProtocol && !binding.isDefaultableBinding() &&
147-
allowJoinMeet) {
146+
!binding.hasDefaultedLiteralProtocol() &&
147+
!binding.isDefaultableBinding() && allowJoinMeet) {
148148
if (lastSupertypeIndex) {
149149
auto &lastBinding = Bindings[*lastSupertypeIndex];
150150
auto lastType = lastBinding.BindingType->getWithoutSpecifierType();
@@ -164,7 +164,7 @@ void ConstraintSystem::PotentialBindings::addPotentialBinding(
164164
lastSupertypeIndex = Bindings.size();
165165
}
166166

167-
if (auto *literalProtocol = binding.DefaultedProtocol)
167+
if (auto *literalProtocol = binding.getDefaultedLiteralProtocol())
168168
foundLiteralBinding(literalProtocol);
169169

170170
// If the type variable can't bind to an lvalue, make sure the
@@ -371,7 +371,7 @@ ConstraintSystem::getPotentialBindingForRelationalConstraint(
371371
kind = AllowedBindingKind::Exact;
372372
}
373373

374-
return PotentialBinding{type, kind, constraint->getKind()};
374+
return PotentialBinding{type, kind, constraint};
375375
}
376376

377377
/// Retrieve the set of potential type bindings for the given
@@ -466,9 +466,8 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
466466
path.back().getKind() == ConstraintLocator::ClosureResult &&
467467
binding->Kind == AllowedBindingKind::Supertypes &&
468468
exactTypes.insert(voidType).second) {
469-
result.addPotentialBinding(
470-
{voidType, binding->Kind, constraint->getKind()},
471-
/*allowJoinMeet=*/false);
469+
result.addPotentialBinding({voidType, binding->Kind, constraint},
470+
/*allowJoinMeet=*/false);
472471
}
473472
}
474473
}
@@ -551,9 +550,8 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
551550
if (!exactTypes.insert(defaultType->getCanonicalType()).second)
552551
continue;
553552

554-
literalBindings.push_back({defaultType, AllowedBindingKind::Subtypes,
555-
constraint->getKind(),
556-
constraint->getProtocol()});
553+
literalBindings.push_back(
554+
{defaultType, AllowedBindingKind::Subtypes, constraint});
557555
continue;
558556
}
559557

@@ -578,9 +576,8 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
578576

579577
if (!matched) {
580578
exactTypes.insert(defaultType->getCanonicalType());
581-
literalBindings.push_back({defaultType, AllowedBindingKind::Subtypes,
582-
constraint->getKind(),
583-
constraint->getProtocol()});
579+
literalBindings.push_back(
580+
{defaultType, AllowedBindingKind::Subtypes, constraint});
584581
}
585582

586583
break;
@@ -677,7 +674,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
677674
// might be covered by non-defaulted bindings.
678675
bool updatedBindingType = false;
679676
for (auto &literalBinding : literalBindings) {
680-
auto *protocol = literalBinding.DefaultedProtocol;
677+
auto *protocol = literalBinding.getDefaultedLiteralProtocol();
681678

682679
assert(protocol);
683680

@@ -716,7 +713,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
716713
}
717714

718715
for (auto &literalBinding : literalBindings) {
719-
auto *protocol = literalBinding.DefaultedProtocol;
716+
auto *protocol = literalBinding.getDefaultedLiteralProtocol();
720717
// For any literal type that has been covered, skip them.
721718
if (coveredLiteralProtocols.count(protocol) == 0)
722719
result.addPotentialBinding(std::move(literalBinding));
@@ -729,9 +726,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
729726
if (!exactTypes.insert(type->getCanonicalType()).second)
730727
continue;
731728

732-
result.addPotentialBinding({type, AllowedBindingKind::Exact,
733-
constraint->getKind(), nullptr,
734-
constraint->getLocator()});
729+
result.addPotentialBinding({type, AllowedBindingKind::Exact, constraint});
735730
}
736731

737732
// If there are no bindings, typeVar may be a hole.
@@ -745,9 +740,8 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
745740
if (locator->isLastElement<LocatorPathElt::MemberRefBase>())
746741
result.PotentiallyIncomplete = true;
747742

748-
result.addPotentialBinding({getASTContext().TheUnresolvedType,
749-
AllowedBindingKind::Exact, ConstraintKind::Defaultable, nullptr,
750-
typeVar->getImpl().getLocator()});
743+
result.addPotentialBinding(
744+
PotentialBinding::forHole(getASTContext(), locator));
751745
}
752746

753747
// Determine if the bindings only constrain the type variable from above with
@@ -918,11 +912,11 @@ bool TypeVarBindingProducer::computeNext() {
918912

919913
// If we have a protocol with a default type, look for alternative
920914
// types to the default.
921-
if (NumTries == 0 && binding.DefaultedProtocol) {
922-
auto knownKind = *(binding.DefaultedProtocol->getKnownProtocolKind());
915+
if (NumTries == 0 && binding.hasDefaultedLiteralProtocol()) {
916+
auto knownKind =
917+
*(binding.getDefaultedLiteralProtocol()->getKnownProtocolKind());
923918
for (auto altType : CS.getAlternativeLiteralTypes(knownKind)) {
924-
addNewBinding({altType, BindingKind::Subtypes, binding.BindingSource,
925-
binding.DefaultedProtocol});
919+
addNewBinding(binding.withSameSource(altType, BindingKind::Subtypes));
926920
}
927921
}
928922

@@ -939,10 +933,10 @@ bool TypeVarBindingProducer::computeNext() {
939933
if (auto otherTypeVar = objTy->getAs<TypeVariableType>()) {
940934
if (TypeVar->getImpl().canBindToLValue() ==
941935
otherTypeVar->getImpl().canBindToLValue()) {
942-
addNewBinding({objTy, binding.Kind, binding.BindingSource});
936+
addNewBinding(binding.withSameSource(objTy, binding.Kind));
943937
}
944938
} else {
945-
addNewBinding({objTy, binding.Kind, binding.BindingSource});
939+
addNewBinding(binding.withSameSource(objTy, binding.Kind));
946940
}
947941
}
948942
}
@@ -953,7 +947,7 @@ bool TypeVarBindingProducer::computeNext() {
953947
for (auto supertype : enumerateDirectSupertypes(type)) {
954948
// If we're not allowed to try this binding, skip it.
955949
if (auto simplifiedSuper = CS.checkTypeOfBinding(TypeVar, supertype))
956-
addNewBinding({*simplifiedSuper, binding.Kind, binding.BindingSource});
950+
addNewBinding(binding.withType(*simplifiedSuper));
957951
}
958952
}
959953

@@ -970,10 +964,10 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
970964
auto type = Binding.BindingType;
971965
auto *locator = TypeVar->getImpl().getLocator();
972966

973-
if (Binding.DefaultedProtocol) {
967+
if (Binding.hasDefaultedLiteralProtocol()) {
974968
type = cs.openUnboundGenericType(type, locator);
975969
type = type->reconstituteSugar(/*recursive=*/false);
976-
} else if (Binding.BindingSource == ConstraintKind::ArgumentConversion &&
970+
} else if (Binding.getSourceKind() == ConstraintKind::ArgumentConversion &&
977971
!type->hasTypeVariable() && cs.isCollectionType(type)) {
978972
// If the type binding comes from the argument conversion, let's
979973
// instead of binding collection types directly, try to bind
@@ -994,7 +988,7 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
994988

995989
// If this was from a defaultable binding note that.
996990
if (Binding.isDefaultableBinding()) {
997-
cs.DefaultedConstraints.push_back(Binding.DefaultableBinding);
991+
cs.DefaultedConstraints.push_back(Binding.getLocator());
998992

999993
if (locator->isForGenericParameter() && type->isHole()) {
1000994
// Drop `generic parameter` locator element so that all missing

lib/Sema/ConstraintSystem.h

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3288,28 +3288,72 @@ class ConstraintSystem {
32883288
/// The kind of bindings permitted.
32893289
AllowedBindingKind Kind;
32903290

3291-
/// The kind of the constraint this binding came from.
3292-
ConstraintKind BindingSource;
3293-
3294-
/// The defaulted protocol associated with this binding.
3295-
ProtocolDecl *DefaultedProtocol;
3296-
3297-
/// If this is a binding that comes from a \c Defaultable constraint,
3298-
/// the locator of that constraint.
3299-
ConstraintLocator *DefaultableBinding = nullptr;
3291+
protected:
3292+
/// The source of the type information.
3293+
///
3294+
/// Determines whether this binding represents a "hole" in
3295+
/// constraint system. Such bindings have no originating constraint
3296+
/// because they are synthetic, they have a locator instead.
3297+
PointerUnion<Constraint *, ConstraintLocator *> BindingSource;
33003298

33013299
PotentialBinding(Type type, AllowedBindingKind kind,
3302-
ConstraintKind bindingSource,
3303-
ProtocolDecl *defaultedProtocol = nullptr,
3304-
ConstraintLocator *defaultableBinding = nullptr)
3300+
PointerUnion<Constraint *, ConstraintLocator *> source)
3301+
: BindingType(type->getWithoutParens()), Kind(kind),
3302+
BindingSource(source) {}
3303+
3304+
public:
3305+
PotentialBinding(Type type, AllowedBindingKind kind, Constraint *source)
33053306
: BindingType(type->getWithoutParens()), Kind(kind),
3306-
BindingSource(bindingSource), DefaultedProtocol(defaultedProtocol),
3307-
DefaultableBinding(defaultableBinding) {}
3307+
BindingSource(source) {}
3308+
3309+
bool isDefaultableBinding() const {
3310+
if (auto *constraint = BindingSource.dyn_cast<Constraint *>())
3311+
return constraint->getKind() == ConstraintKind::Defaultable;
3312+
// If binding source is not constraint - it's a hole, which is
3313+
// a last resort default binding for a type variable.
3314+
return true;
3315+
}
3316+
3317+
bool hasDefaultedLiteralProtocol() const {
3318+
return bool(getDefaultedLiteralProtocol());
3319+
}
33083320

3309-
bool isDefaultableBinding() const { return DefaultableBinding != nullptr; }
3321+
ProtocolDecl *getDefaultedLiteralProtocol() const {
3322+
auto *constraint = BindingSource.dyn_cast<Constraint *>();
3323+
if (!constraint)
3324+
return nullptr;
3325+
3326+
return constraint->getKind() == ConstraintKind::LiteralConformsTo
3327+
? constraint->getProtocol()
3328+
: nullptr;
3329+
}
3330+
3331+
ConstraintKind getSourceKind() const {
3332+
if (auto *constraint = BindingSource.dyn_cast<Constraint *>())
3333+
return constraint->getKind();
3334+
// If binding source is not constraint - it's a hole which is
3335+
// always a `Bind` constraint.
3336+
return ConstraintKind::Bind;
3337+
}
3338+
3339+
ConstraintLocator *getLocator() const {
3340+
if (auto *constraint = BindingSource.dyn_cast<Constraint *>())
3341+
return constraint->getLocator();
3342+
return BindingSource.get<ConstraintLocator *>();
3343+
}
33103344

33113345
PotentialBinding withType(Type type) const {
3312-
return {type, Kind, BindingSource, DefaultedProtocol, DefaultableBinding};
3346+
return {type, Kind, BindingSource};
3347+
}
3348+
3349+
PotentialBinding withSameSource(Type type, AllowedBindingKind kind) {
3350+
return {type, Kind, BindingSource};
3351+
}
3352+
3353+
static PotentialBinding forHole(ASTContext &ctx,
3354+
ConstraintLocator *locator) {
3355+
return {ctx.TheUnresolvedType, AllowedBindingKind::Exact,
3356+
/*source=*/locator};
33133357
}
33143358
};
33153359

@@ -3464,9 +3508,8 @@ class ConstraintSystem {
34643508
out << "(supertypes of) ";
34653509
break;
34663510
}
3467-
if (binding.DefaultedProtocol)
3468-
out << "(default from "
3469-
<< binding.DefaultedProtocol->getName() << ") ";
3511+
if (auto *literal = binding.getDefaultedLiteralProtocol())
3512+
out << "(default from " << literal->getName() << ") ";
34703513
out << type.getString(PO);
34713514
},
34723515
[&]() { out << "; "; });
@@ -4196,7 +4239,9 @@ class TypeVariableBinding {
41964239

41974240
bool isDefaultable() const { return Binding.isDefaultableBinding(); }
41984241

4199-
bool hasDefaultedProtocol() const { return Binding.DefaultedProtocol; }
4242+
bool hasDefaultedProtocol() const {
4243+
return Binding.hasDefaultedLiteralProtocol();
4244+
}
42004245

42014246
bool attempt(ConstraintSystem &cs) const;
42024247

0 commit comments

Comments
 (0)