24
24
25
25
using namespace swift ;
26
26
27
- bool Substitution::operator ==(const Substitution &other) const {
28
- // The archetypes may be missing, but we can compare them directly
29
- // because archetypes are always canonical.
30
- return
31
- Replacement->getCanonicalType () == other.Replacement ->getCanonicalType () &&
32
- Conformance.equals (other.Conformance );
33
- }
34
-
35
- Substitution::Substitution (Type Replacement,
36
- ArrayRef<ProtocolConformanceRef> Conformance)
37
- : Replacement(Replacement), Conformance(Conformance)
38
- {
39
- // The replacement type must be materializable.
40
- assert (Replacement->isMaterializable ()
41
- && " cannot substitute with a non-materializable type" );
42
- }
43
-
44
- Substitution Substitution::subst (Module *module ,
45
- GenericSignature *sig,
46
- GenericEnvironment *env,
47
- ArrayRef<Substitution> subs) const {
48
- TypeSubstitutionMap subMap;
49
- ArchetypeConformanceMap conformanceMap;
50
-
51
- assert (sig && env);
52
- env->getSubstitutionMap (module , sig, subs, subMap, conformanceMap);
53
- return subst (module , subMap, conformanceMap);
54
- }
55
-
56
- static Optional<ProtocolConformanceRef>
27
+ Optional<ProtocolConformanceRef> ArchetypeConformanceMap::
57
28
lookupArchetypeConformance (ProtocolDecl *proto,
58
- ArrayRef<ProtocolConformanceRef> conformances) {
29
+ ArrayRef<ProtocolConformanceRef> conformances) const {
59
30
for (ProtocolConformanceRef found : conformances) {
60
31
auto foundProto = found.getRequirement ();
61
32
if (foundProto == proto) {
@@ -73,40 +44,93 @@ lookupArchetypeConformance(ProtocolDecl *proto,
73
44
return None;
74
45
}
75
46
76
- static Optional<ProtocolConformanceRef>
47
+ Optional<ProtocolConformanceRef> ArchetypeConformanceMap::
77
48
lookupArchetypeConformance (ArchetypeType *replacement,
78
- ProtocolDecl *proto,
79
- ArchetypeConformanceMap &conformanceMap) {
49
+ ProtocolDecl *proto) const {
80
50
// Check for conformances for the type that apply to the original
81
51
// substituted archetype.
82
- auto it = conformanceMap.find (replacement);
83
- if (it != conformanceMap.end ()) {
84
- if (auto conformance = lookupArchetypeConformance (proto, it->second )) {
52
+ auto foundReplacement = map.find (replacement);
53
+ if (foundReplacement != map.end ()) {
54
+ auto substReplacement = foundReplacement->second ;
55
+ if (auto conformance = lookupArchetypeConformance (proto, substReplacement))
85
56
return conformance;
86
- }
87
57
}
88
58
89
- // Check if we have substitutions for the parent.
90
- if (auto *parent = replacement->getParent ()) {
91
- auto *assocType = replacement->getAssocType ();
92
- auto *parentProto = assocType->getProtocol ();
59
+ // Check if we have substitutions from one of our parent archetypes.
60
+ auto foundParents = parents.find (replacement);
61
+ if (foundParents == parents.end ())
62
+ return None;
63
+
64
+ for (auto parent : foundParents->second ) {
65
+ auto *parentProto = parent.second ->getProtocol ();
93
66
auto conformance =
94
- lookupArchetypeConformance (parent, parentProto, conformanceMap );
67
+ lookupArchetypeConformance (parent. first , parentProto);
95
68
96
69
if (conformance) {
97
70
if (!conformance->isConcrete ())
98
71
return ProtocolConformanceRef (proto);
99
72
100
73
auto sub = conformance->getConcrete ()->getTypeWitnessSubstAndDecl (
101
- assocType , nullptr ).first ;
74
+ parent. second , nullptr ).first ;
102
75
103
- return lookupArchetypeConformance (proto, sub.getConformances ());
76
+ if (auto result = lookupArchetypeConformance (proto, sub.getConformances ()))
77
+ return result;
104
78
}
105
79
}
106
80
107
81
return None;
108
82
}
109
83
84
+ void ArchetypeConformanceMap::
85
+ addArchetypeConformances (ArchetypeType *replacement,
86
+ ArrayRef<ProtocolConformanceRef> conformances) {
87
+ assert (replacement);
88
+
89
+ auto result = map.insert (std::make_pair (replacement, conformances));
90
+ assert (result.second );
91
+ (void ) result;
92
+
93
+ if (auto *parent = replacement->getParent ())
94
+ addArchetypeParent (replacement, parent, replacement->getAssocType ());
95
+ }
96
+
97
+ void ArchetypeConformanceMap::
98
+ addArchetypeParent (ArchetypeType *replacement,
99
+ ArchetypeType *parent,
100
+ AssociatedTypeDecl *assocType) {
101
+ assert (replacement && parent && assocType);
102
+ parents[replacement].push_back (std::make_pair (parent, assocType));
103
+ }
104
+
105
+ bool Substitution::operator ==(const Substitution &other) const {
106
+ // The archetypes may be missing, but we can compare them directly
107
+ // because archetypes are always canonical.
108
+ return
109
+ Replacement->getCanonicalType () == other.Replacement ->getCanonicalType () &&
110
+ Conformance.equals (other.Conformance );
111
+ }
112
+
113
+ Substitution::Substitution (Type Replacement,
114
+ ArrayRef<ProtocolConformanceRef> Conformance)
115
+ : Replacement(Replacement), Conformance(Conformance)
116
+ {
117
+ // The replacement type must be materializable.
118
+ assert (Replacement->isMaterializable ()
119
+ && " cannot substitute with a non-materializable type" );
120
+ }
121
+
122
+ Substitution Substitution::subst (Module *module ,
123
+ GenericSignature *sig,
124
+ GenericEnvironment *env,
125
+ ArrayRef<Substitution> subs) const {
126
+ TypeSubstitutionMap subMap;
127
+ ArchetypeConformanceMap conformanceMap;
128
+
129
+ assert (sig && env);
130
+ env->getSubstitutionMap (module , sig, subs, subMap, conformanceMap);
131
+ return subst (module , subMap, conformanceMap);
132
+ }
133
+
110
134
Substitution Substitution::subst (Module *module ,
111
135
TypeSubstitutionMap &subMap,
112
136
ArchetypeConformanceMap &conformanceMap) const {
@@ -143,8 +167,8 @@ Substitution Substitution::subst(Module *module,
143
167
144
168
// If the original type was an archetype, check the conformance map.
145
169
if (auto replacementArch = Replacement->getAs <ArchetypeType>()) {
146
- conformance = lookupArchetypeConformance (replacementArch, proto,
147
- conformanceMap );
170
+ conformance = conformanceMap. lookupArchetypeConformance (
171
+ replacementArch, proto );
148
172
}
149
173
150
174
// If that didn't find anything, we can still synthesize AnyObject
0 commit comments