Skip to content

Commit 6dece8a

Browse files
authored
Merge pull request #86072 from xedin/originator-in-the-binding
[CSBindings] Store the originator type variable in a transitive binding
2 parents 15cb8d6 + 91eefb9 commit 6dece8a

File tree

4 files changed

+58
-34
lines changed

4 files changed

+58
-34
lines changed

include/swift/Sema/CSBindings.h

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,20 @@ struct PotentialBinding {
8484
/// because they are synthetic, they have a locator instead.
8585
PointerUnion<Constraint *, ConstraintLocator *> BindingSource;
8686

87+
/// When the binding is transferred through a subtype chain, this
88+
/// marks a type variable for which it was originally inferred.
89+
TypeVariableType *Originator;
90+
8791
PotentialBinding(Type type, AllowedBindingKind kind,
88-
PointerUnion<Constraint *, ConstraintLocator *> source)
89-
: BindingType(type), Kind(kind), BindingSource(source) {}
92+
PointerUnion<Constraint *, ConstraintLocator *> source,
93+
TypeVariableType *originator)
94+
: BindingType(type), Kind(kind), BindingSource(source),
95+
Originator(originator) {}
9096

9197
PotentialBinding(Type type, AllowedBindingKind kind, Constraint *source)
9298
: PotentialBinding(
93-
type, kind,
94-
PointerUnion<Constraint *, ConstraintLocator *>(source)) {}
99+
type, kind, PointerUnion<Constraint *, ConstraintLocator *>(source),
100+
/*originator=*/nullptr) {}
95101

96102
bool isDefaultableBinding() const {
97103
if (auto *constraint = BindingSource.dyn_cast<Constraint *>())
@@ -124,13 +130,20 @@ struct PotentialBinding {
124130
Constraint *getSource() const { return cast<Constraint *>(BindingSource); }
125131

126132
PotentialBinding withType(Type type) const {
127-
return {type, Kind, BindingSource};
133+
return {type, Kind, BindingSource, Originator};
128134
}
129135

130136
PotentialBinding withSameSource(Type type, AllowedBindingKind kind) const {
131-
return {type, kind, BindingSource};
137+
return {type, kind, BindingSource, Originator};
138+
}
139+
140+
PotentialBinding asTransitiveFrom(TypeVariableType *originator) const {
141+
ASSERT(originator);
142+
return {BindingType, Kind, BindingSource, originator};
132143
}
133144

145+
bool isTransitive() const { return bool(Originator); }
146+
134147
/// Determine whether this binding could be a viable candidate
135148
/// to be "joined" with some other binding. It has to be at least
136149
/// a non-default r-value supertype binding with no type variables.
@@ -140,12 +153,13 @@ struct PotentialBinding {
140153
ConstraintLocator *locator) {
141154
return {PlaceholderType::get(typeVar->getASTContext(), typeVar),
142155
AllowedBindingKind::Exact,
143-
/*source=*/locator};
156+
/*source=*/locator, /*originator=*/nullptr};
144157
}
145158

146159
static PotentialBinding forPlaceholder(Type placeholderTy) {
147160
return {placeholderTy, AllowedBindingKind::Exact,
148-
PointerUnion<Constraint *, ConstraintLocator *>()};
161+
PointerUnion<Constraint *, ConstraintLocator *>(),
162+
/*originator=*/nullptr};
149163
}
150164

151165
void print(llvm::raw_ostream &out, const PrintOptions &PO) const;
@@ -492,7 +506,7 @@ class BindingSet {
492506
/// \param isTransitive Indicates whether this binding has been
493507
/// acquired through transitive inference and requires extra
494508
/// checking.
495-
bool isViable(PotentialBinding &binding, bool isTransitive);
509+
bool isViable(PotentialBinding &binding);
496510

497511
/// Determine whether this set has any "viable" (or non-hole) bindings.
498512
///
@@ -624,10 +638,7 @@ class BindingSet {
624638
/// Add a new binding to the set.
625639
///
626640
/// \param binding The binding to add.
627-
/// \param isTransitive Indicates whether this binding has been
628-
/// acquired through transitive inference and requires validity
629-
/// checking.
630-
void addBinding(PotentialBinding binding, bool isTransitive);
641+
void addBinding(PotentialBinding binding);
631642

632643
void addDefault(Constraint *constraint);
633644

include/swift/Sema/CSTrail.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ class SolverTrail {
145145
/// of a PotentialBinding.
146146
Type BindingType;
147147
PointerUnion<Constraint *, ConstraintLocator *> BindingSource;
148+
TypeVariableType *Originator;
148149
} Binding;
149150

150151
ConstraintFix *TheFix;

lib/Sema/CSBindings.cpp

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ BindingSet::BindingSet(ConstraintSystem &CS, TypeVariableType *TypeVar,
5353
: CS(CS), TypeVar(TypeVar), Info(info) {
5454

5555
for (const auto &binding : info.Bindings)
56-
addBinding(binding, /*isTransitive=*/false);
56+
addBinding(binding);
5757

5858
for (const auto &literal : info.Literals)
5959
Literals.push_back(literal);
@@ -594,7 +594,7 @@ void BindingSet::inferTransitiveKeyPathBindings() {
594594

595595
// Copy the bindings over to the root.
596596
for (const auto &binding : bindings.Bindings)
597-
addBinding(binding, /*isTransitive=*/true);
597+
addBinding(binding.asTransitiveFrom(contextualRootVar));
598598

599599
// Make a note that the key path root is transitively adjacent
600600
// to contextual root type variable and all of its variables.
@@ -604,9 +604,9 @@ void BindingSet::inferTransitiveKeyPathBindings() {
604604
bindings.AdjacentVars.end());
605605
}
606606
} else {
607-
addBinding(
608-
binding.withSameSource(inferredRootTy, AllowedBindingKind::Exact),
609-
/*isTransitive=*/true);
607+
auto newBinding = binding.withSameSource(
608+
inferredRootTy, AllowedBindingKind::Exact);
609+
addBinding(newBinding.asTransitiveFrom(keyPathTy));
610610
}
611611
}
612612
}
@@ -699,8 +699,9 @@ void BindingSet::inferTransitiveSupertypeBindings() {
699699
if (ConstraintSystem::typeVarOccursInType(TypeVar, type))
700700
continue;
701701

702-
addBinding(binding.withSameSource(type, AllowedBindingKind::Supertypes),
703-
/*isTransitive=*/true);
702+
auto newBinding =
703+
binding.withSameSource(type, AllowedBindingKind::Supertypes);
704+
addBinding(newBinding.asTransitiveFrom(entry.first));
704705
}
705706
}
706707
}
@@ -733,8 +734,7 @@ void BindingSet::inferTransitiveUnresolvedMemberRefBindings() {
733734
continue;
734735
}
735736

736-
addBinding({protocolTy, AllowedBindingKind::Exact, constraint},
737-
/*isTransitive=*/false);
737+
addBinding({protocolTy, AllowedBindingKind::Exact, constraint});
738738
}
739739
}
740740
}
@@ -849,8 +849,8 @@ bool BindingSet::finalizeKeyPathBindings() {
849849
// better diagnostics.
850850
auto keyPathTy = getKeyPathType(ctx, *capability, rootTy,
851851
CS.getKeyPathValueType(keyPath));
852-
updatedBindings.insert(
853-
{keyPathTy, AllowedBindingKind::Exact, locator});
852+
updatedBindings.insert({keyPathTy, AllowedBindingKind::Exact, locator,
853+
/*originator=*/nullptr});
854854
} else if (CS.shouldAttemptFixes()) {
855855
auto fixedRootTy = CS.getFixedType(rootTy);
856856
// If key path is structurally correct and has a resolved root
@@ -911,11 +911,11 @@ void BindingSet::finalizeUnresolvedMemberChainResult() {
911911
}
912912
}
913913

914-
void BindingSet::addBinding(PotentialBinding binding, bool isTransitive) {
914+
void BindingSet::addBinding(PotentialBinding binding) {
915915
if (Bindings.count(binding))
916916
return;
917917

918-
if (!isViable(binding, isTransitive))
918+
if (!isViable(binding))
919919
return;
920920

921921
SmallPtrSet<TypeVariableType *, 4> referencedTypeVars;
@@ -979,14 +979,26 @@ void BindingSet::addBinding(PotentialBinding binding, bool isTransitive) {
979979
for (auto existingBinding = Bindings.begin();
980980
existingBinding != Bindings.end();) {
981981
if (existingBinding->isViableForJoin()) {
982-
auto join =
982+
auto joinType =
983983
Type::join(existingBinding->BindingType, binding.BindingType);
984984

985-
if (join && isAcceptableJoin(*join)) {
985+
if (joinType && isAcceptableJoin(*joinType)) {
986986
// Result of the join has to use new binding because it refers
987987
// to the constraint that triggered the join that replaced the
988988
// existing binding.
989-
joined.push_back(binding.withType(*join));
989+
//
990+
// For "join" to be transitive, both bindings have to be as
991+
// well, otherwise we consider it a refinement of a direct
992+
// binding.
993+
auto *origintor =
994+
binding.isTransitive() && existingBinding->isTransitive()
995+
? binding.Originator
996+
: nullptr;
997+
998+
PotentialBinding join(*joinType, binding.Kind, binding.BindingSource,
999+
origintor);
1000+
1001+
joined.push_back(join);
9901002
// Remove existing binding from the set.
9911003
// It has to be re-introduced later, since its type has been changed.
9921004
existingBinding = Bindings.erase(existingBinding);
@@ -1469,15 +1481,15 @@ static bool hasConversions(Type type) {
14691481
type->is<BuiltinType>() || type->is<ArchetypeType>());
14701482
}
14711483

1472-
bool BindingSet::isViable(PotentialBinding &binding, bool isTransitive) {
1484+
bool BindingSet::isViable(PotentialBinding &binding) {
14731485
// Prevent against checking against the same opened nominal type
14741486
// over and over again. Doing so means redundant work in the best
14751487
// case. In the worst case, we'll produce lots of duplicate solutions
14761488
// for this constraint system, which is problematic for overload
14771489
// resolution.
14781490
auto type = binding.BindingType;
14791491

1480-
if (isTransitive && !checkTypeOfBinding(TypeVar, type))
1492+
if (binding.isTransitive() && !checkTypeOfBinding(TypeVar, type))
14811493
return false;
14821494

14831495
auto *NTD = type->getAnyNominal();

lib/Sema/CSTrail.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ SolverTrail::Change::RetractedBinding(TypeVariableType *typeVar,
334334
result.Binding.TypeVar = typeVar;
335335
result.Binding.BindingType = binding.BindingType;
336336
result.Binding.BindingSource = binding.BindingSource;
337+
result.Binding.Originator = binding.Originator;
337338
result.Options = unsigned(binding.Kind);
338339

339340
return result;
@@ -579,9 +580,8 @@ void SolverTrail::Change::undo(ConstraintSystem &cs) const {
579580
break;
580581

581582
case ChangeKind::RetractedBinding: {
582-
PotentialBinding binding(Binding.BindingType,
583-
AllowedBindingKind(Options),
584-
Binding.BindingSource);
583+
PotentialBinding binding(Binding.BindingType, AllowedBindingKind(Options),
584+
Binding.BindingSource, Binding.Originator);
585585

586586
auto &bindings = cg[BindingRelation.TypeVar].getPotentialBindings();
587587
bindings.Bindings.push_back(binding);

0 commit comments

Comments
 (0)