Skip to content

Commit 08edd56

Browse files
committed
RequirementMachine: Drop protocols that the superclass conforms to when building an archetype
1 parent 049b6e5 commit 08edd56

File tree

4 files changed

+58
-4
lines changed

4 files changed

+58
-4
lines changed

include/swift/AST/GenericSignature.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ class GenericSignature {
173173
Type concreteType;
174174
Type superclass;
175175

176-
SmallVector<ProtocolDecl *, 2> protos;
176+
RequiredProtocols protos;
177177
LayoutConstraint layout;
178178
};
179179

lib/AST/RequirementMachine/EquivalenceClassMap.cpp

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,41 @@
6363
using namespace swift;
6464
using namespace rewriting;
6565

66+
/// This papers over a behavioral difference between
67+
/// GenericSignature::getRequiredProtocols() and ArchetypeType::getConformsTo();
68+
/// the latter drops any protocols to which the superclass requirement
69+
/// conforms to concretely.
70+
llvm::TinyPtrVector<const ProtocolDecl *>
71+
EquivalenceClass::getConformsToExcludingSuperclassConformances() const {
72+
llvm::TinyPtrVector<const ProtocolDecl *> result;
73+
74+
if (SuperclassConformances.empty()) {
75+
result = ConformsTo;
76+
return result;
77+
}
78+
79+
// The conformances in SuperclassConformances should appear in the same order
80+
// as the protocols in ConformsTo.
81+
auto conformanceIter = SuperclassConformances.begin();
82+
83+
for (const auto *proto : ConformsTo) {
84+
if (conformanceIter == SuperclassConformances.end()) {
85+
result.push_back(proto);
86+
continue;
87+
}
88+
89+
if (proto == (*conformanceIter)->getProtocol()) {
90+
++conformanceIter;
91+
continue;
92+
}
93+
94+
result.push_back(proto);
95+
}
96+
97+
assert(conformanceIter == SuperclassConformances.end());
98+
return result;
99+
}
100+
66101
void EquivalenceClass::dump(llvm::raw_ostream &out) const {
67102
out << Key << " => {";
68103

@@ -650,6 +685,7 @@ void EquivalenceClassMap::concretizeNestedTypesFromConcreteParents(
650685
equivClass->ConcreteType->getConcreteType(),
651686
equivClass->ConcreteType->getSubstitutions(),
652687
equivClass->getConformsTo(),
688+
equivClass->ConcreteConformances,
653689
inducedRules);
654690
}
655691

@@ -664,6 +700,7 @@ void EquivalenceClassMap::concretizeNestedTypesFromConcreteParents(
664700
equivClass->Superclass->getSuperclass(),
665701
equivClass->Superclass->getSubstitutions(),
666702
equivClass->getConformsTo(),
703+
equivClass->SuperclassConformances,
667704
inducedRules);
668705
}
669706
}
@@ -705,6 +742,7 @@ void EquivalenceClassMap::concretizeNestedTypesFromConcreteParent(
705742
const MutableTerm &key, RequirementKind requirementKind,
706743
CanType concreteType, ArrayRef<Term> substitutions,
707744
ArrayRef<const ProtocolDecl *> conformsTo,
745+
llvm::TinyPtrVector<ProtocolConformance *> &conformances,
708746
SmallVectorImpl<std::pair<MutableTerm, MutableTerm>> &inducedRules) const {
709747
assert(requirementKind == RequirementKind::SameType ||
710748
requirementKind == RequirementKind::Superclass);
@@ -730,12 +768,16 @@ void EquivalenceClassMap::concretizeNestedTypesFromConcreteParent(
730768
// opaque result type?
731769
assert(!conformance.isAbstract());
732770

771+
auto *concrete = conformance.getConcrete();
772+
773+
// Record the conformance for use by
774+
// EquivalenceClass::getConformsToExcludingSuperclassConformances().
775+
conformances.push_back(concrete);
776+
733777
auto assocTypes = Protos.getProtocolInfo(proto).AssociatedTypes;
734778
if (assocTypes.empty())
735779
continue;
736780

737-
auto *concrete = conformance.getConcrete();
738-
739781
for (auto *assocType : assocTypes) {
740782
if (DebugConcretizeNestedTypes) {
741783
llvm::dbgs() << "^^ " << "Looking up type witness for "

lib/AST/RequirementMachine/EquivalenceClassMap.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,17 @@ class EquivalenceClass {
6363
/// The most specific superclass constraint this type satisfies.
6464
Optional<Atom> Superclass;
6565

66+
/// All concrete conformances of Superclass to the protocols in the
67+
/// ConformsTo list.
68+
llvm::TinyPtrVector<ProtocolConformance *> SuperclassConformances;
69+
6670
/// The most specific concrete type constraint this type satisfies.
6771
Optional<Atom> ConcreteType;
6872

73+
/// All concrete conformances of ConcreteType to the protocols in the
74+
/// ConformsTo list.
75+
llvm::TinyPtrVector<ProtocolConformance *> ConcreteConformances;
76+
6977
explicit EquivalenceClass(const MutableTerm &key) : Key(key) {}
7078

7179
void addProperty(Atom property,
@@ -117,6 +125,9 @@ class EquivalenceClass {
117125
ArrayRef<const ProtocolDecl *> getConformsTo() const {
118126
return ConformsTo;
119127
}
128+
129+
llvm::TinyPtrVector<const ProtocolDecl *>
130+
getConformsToExcludingSuperclassConformances() const;
120131
};
121132

122133
/// Stores all rewrite rules of the form T.[p] => T, where [p] is a property
@@ -167,6 +178,7 @@ class EquivalenceClassMap {
167178
const MutableTerm &key, RequirementKind requirementKind,
168179
CanType concreteType, ArrayRef<Term> substitutions,
169180
ArrayRef<const ProtocolDecl *> conformsTo,
181+
llvm::TinyPtrVector<ProtocolConformance *> &conformances,
170182
SmallVectorImpl<std::pair<MutableTerm, MutableTerm>> &inducedRules) const;
171183

172184
MutableTerm computeConstraintTermForTypeWitness(

lib/AST/RequirementMachine/RequirementMachine.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ RequirementMachine::getLocalRequirements(
476476
Impl->Context);
477477
}
478478

479-
for (const auto *proto : equivClass->getConformsTo())
479+
for (const auto *proto : equivClass->getConformsToExcludingSuperclassConformances())
480480
result.protos.push_back(const_cast<ProtocolDecl *>(proto));
481481

482482
result.layout = equivClass->getLayoutConstraint();

0 commit comments

Comments
 (0)