@@ -2107,6 +2107,245 @@ auto AssociatedTypeInference::solve(ConformanceChecker &checker)
2107
2107
return None;
2108
2108
}
2109
2109
2110
+ TypeWitnessSystem::TypeWitnessSystem (
2111
+ ArrayRef<AssociatedTypeDecl *> assocTypes) {
2112
+ for (auto *assocType : assocTypes) {
2113
+ this ->TypeWitnesses .try_emplace (assocType->getName ());
2114
+ }
2115
+ }
2116
+
2117
+ TypeWitnessSystem::~TypeWitnessSystem () {
2118
+ for (auto *equivClass : this ->EquivalenceClasses ) {
2119
+ delete equivClass;
2120
+ }
2121
+ }
2122
+
2123
+ bool TypeWitnessSystem::hasResolvedTypeWitness (Identifier name) const {
2124
+ return (bool )getResolvedTypeWitness (name);
2125
+ }
2126
+
2127
+ Type TypeWitnessSystem::getResolvedTypeWitness (Identifier name) const {
2128
+ assert (this ->TypeWitnesses .count (name));
2129
+
2130
+ if (auto *equivClass = this ->TypeWitnesses .lookup (name).EquivClass ) {
2131
+ return equivClass->ResolvedTy ;
2132
+ }
2133
+
2134
+ return Type ();
2135
+ }
2136
+
2137
+ const AssociatedTypeDecl *
2138
+ TypeWitnessSystem::getDefaultedAssocType (Identifier name) const {
2139
+ assert (this ->TypeWitnesses .count (name));
2140
+
2141
+ return this ->TypeWitnesses .lookup (name).DefaultedAssocType ;
2142
+ }
2143
+
2144
+ void TypeWitnessSystem::addTypeWitness (Identifier name, Type type) {
2145
+ assert (this ->TypeWitnesses .count (name));
2146
+
2147
+ if (const auto *depTy = type->getAs <DependentMemberType>()) {
2148
+ // If the type corresponds to a name variable in the system, form an
2149
+ // equivalence between variables.
2150
+ if (depTy->getBase ()->is <GenericTypeParamType>()) {
2151
+ if (this ->TypeWitnesses .count (depTy->getName ())) {
2152
+ return addEquivalence (name, depTy->getName ());
2153
+ }
2154
+ } else {
2155
+ while (depTy->getBase ()->is <DependentMemberType>()) {
2156
+ depTy = depTy->getBase ()->castTo <DependentMemberType>();
2157
+ }
2158
+
2159
+ // Equivalences of the form 'Self.X == Self.X.*' do not contribute
2160
+ // to solving the system, so just ignore them.
2161
+ if (name == depTy->getName ()) {
2162
+ return ;
2163
+ }
2164
+ }
2165
+ }
2166
+
2167
+ auto &tyWitness = this ->TypeWitnesses [name];
2168
+
2169
+ // Assume that the type resolves the type witness.
2170
+ //
2171
+ // If we already have a resolved type, keep going only if the new one is
2172
+ // better.
2173
+ if (tyWitness.EquivClass && tyWitness.EquivClass ->ResolvedTy ) {
2174
+ if (!isBetterResolvedType (type, tyWitness.EquivClass ->ResolvedTy )) {
2175
+ return ;
2176
+ }
2177
+ }
2178
+
2179
+ // If we can find an existing equivalence class for this type, use it.
2180
+ for (auto *const equivClass : this ->EquivalenceClasses ) {
2181
+ if (equivClass->ResolvedTy && equivClass->ResolvedTy ->isEqual (type)) {
2182
+ if (tyWitness.EquivClass ) {
2183
+ mergeEquivalenceClasses (equivClass, tyWitness.EquivClass );
2184
+ } else {
2185
+ tyWitness.EquivClass = equivClass;
2186
+ }
2187
+
2188
+ return ;
2189
+ }
2190
+ }
2191
+
2192
+ if (tyWitness.EquivClass ) {
2193
+ tyWitness.EquivClass ->ResolvedTy = type;
2194
+ } else {
2195
+ auto *equivClass = new EquivalenceClass{type};
2196
+ this ->EquivalenceClasses .insert (equivClass);
2197
+
2198
+ tyWitness.EquivClass = equivClass;
2199
+ }
2200
+ }
2201
+
2202
+ void TypeWitnessSystem::addDefaultTypeWitness (
2203
+ Type type, const AssociatedTypeDecl *defaultedAssocType) {
2204
+ const auto name = defaultedAssocType->getName ();
2205
+ assert (this ->TypeWitnesses .count (name));
2206
+
2207
+ auto &tyWitness = this ->TypeWitnesses [name];
2208
+ assert (!hasResolvedTypeWitness (name) && " already resolved a type witness" );
2209
+ assert (!tyWitness.DefaultedAssocType &&
2210
+ " already recorded a default type witness" );
2211
+
2212
+ // Set the defaulted associated type.
2213
+ tyWitness.DefaultedAssocType = defaultedAssocType;
2214
+
2215
+ // Record the type witness.
2216
+ addTypeWitness (name, type);
2217
+ }
2218
+
2219
+ void TypeWitnessSystem::addSameTypeRequirement (const Requirement &req) {
2220
+ assert (req.getKind () == RequirementKind::SameType);
2221
+
2222
+ auto *const depTy1 = req.getFirstType ()->getAs <DependentMemberType>();
2223
+ auto *const depTy2 = req.getSecondType ()->getAs <DependentMemberType>();
2224
+
2225
+ // Equivalences other than 'Self.X == ...' (or '... == Self.X'), where
2226
+ // 'X' is a name variable in this system, do not contribute to solving
2227
+ // the system.
2228
+ if (depTy1 && depTy1->getBase ()->is <GenericTypeParamType>() &&
2229
+ this ->TypeWitnesses .count (depTy1->getName ())) {
2230
+ addTypeWitness (depTy1->getName (), req.getSecondType ());
2231
+ } else if (depTy2 && depTy2->getBase ()->is <GenericTypeParamType>() &&
2232
+ this ->TypeWitnesses .count (depTy2->getName ())) {
2233
+ addTypeWitness (depTy2->getName (), req.getFirstType ());
2234
+ }
2235
+ }
2236
+
2237
+ void TypeWitnessSystem::dump (
2238
+ llvm::raw_ostream &out,
2239
+ const NormalProtocolConformance *conformance) const {
2240
+ llvm::SmallVector<Identifier, 4 > sortedNames;
2241
+ sortedNames.reserve (this ->TypeWitnesses .size ());
2242
+
2243
+ for (const auto &pair : this ->TypeWitnesses ) {
2244
+ sortedNames.push_back (pair.first );
2245
+ }
2246
+
2247
+ // Deterministic ordering.
2248
+ llvm::array_pod_sort (sortedNames.begin (), sortedNames.end (),
2249
+ [](const Identifier *lhs, const Identifier *rhs) -> int {
2250
+ return lhs->compare (*rhs);
2251
+ });
2252
+
2253
+ out << " Abstract type witness system for conformance"
2254
+ << " of " << conformance->getType () << " to "
2255
+ << conformance->getProtocol ()->getName () << " : {\n " ;
2256
+
2257
+ for (const auto &name : sortedNames) {
2258
+ out.indent (2 ) << name << " => " ;
2259
+
2260
+ const auto *eqClass = this ->TypeWitnesses .lookup (name).EquivClass ;
2261
+ if (eqClass) {
2262
+ if (eqClass->ResolvedTy ) {
2263
+ out << eqClass->ResolvedTy ;
2264
+ } else {
2265
+ out << " (unresolved)" ;
2266
+ }
2267
+ } else {
2268
+ out << " (unresolved)" ;
2269
+ }
2270
+
2271
+ if (eqClass) {
2272
+ out << " , " << eqClass;
2273
+ }
2274
+ out << " \n " ;
2275
+ }
2276
+ out << " }\n " ;
2277
+ }
2278
+
2279
+ void TypeWitnessSystem::addEquivalence (Identifier name1, Identifier name2) {
2280
+ assert (this ->TypeWitnesses .count (name1));
2281
+ assert (this ->TypeWitnesses .count (name2));
2282
+
2283
+ if (name1 == name2) {
2284
+ return ;
2285
+ }
2286
+
2287
+ auto &tyWitness1 = this ->TypeWitnesses [name1];
2288
+ auto &tyWitness2 = this ->TypeWitnesses [name2];
2289
+
2290
+ // If both candidates are associated with existing equivalence classes,
2291
+ // merge them.
2292
+ if (tyWitness1.EquivClass && tyWitness2.EquivClass ) {
2293
+ mergeEquivalenceClasses (tyWitness1.EquivClass , tyWitness2.EquivClass );
2294
+ return ;
2295
+ }
2296
+
2297
+ if (tyWitness1.EquivClass ) {
2298
+ tyWitness2.EquivClass = tyWitness1.EquivClass ;
2299
+ } else if (tyWitness2.EquivClass ) {
2300
+ tyWitness1.EquivClass = tyWitness2.EquivClass ;
2301
+ } else {
2302
+ // Neither has an associated equivalence class.
2303
+ auto *equivClass = new EquivalenceClass{nullptr };
2304
+ this ->EquivalenceClasses .insert (equivClass);
2305
+
2306
+ tyWitness1.EquivClass = equivClass;
2307
+ tyWitness2.EquivClass = equivClass;
2308
+ }
2309
+ }
2310
+
2311
+ void TypeWitnessSystem::mergeEquivalenceClasses (
2312
+ EquivalenceClass *equivClass1, const EquivalenceClass *equivClass2) {
2313
+ assert (equivClass1 && equivClass2);
2314
+ if (equivClass1 == equivClass2) {
2315
+ return ;
2316
+ }
2317
+
2318
+ // Merge the second resolved type into the first.
2319
+ if (equivClass1->ResolvedTy && equivClass2->ResolvedTy ) {
2320
+ if (isBetterResolvedType (equivClass2->ResolvedTy ,
2321
+ equivClass1->ResolvedTy )) {
2322
+ equivClass1->ResolvedTy = equivClass2->ResolvedTy ;
2323
+ }
2324
+ } else if (equivClass2->ResolvedTy ) {
2325
+ equivClass1->ResolvedTy = equivClass2->ResolvedTy ;
2326
+ }
2327
+
2328
+ // Migrate members of the second equivalence class to the first.
2329
+ for (auto &pair : this ->TypeWitnesses ) {
2330
+ if (pair.second .EquivClass == equivClass2) {
2331
+ pair.second .EquivClass = equivClass1;
2332
+ }
2333
+ }
2334
+
2335
+ // Finally, dispose of the second equivalence class.
2336
+ this ->EquivalenceClasses .erase (const_cast <EquivalenceClass *>(equivClass2));
2337
+ delete equivClass2;
2338
+ }
2339
+
2340
+ bool TypeWitnessSystem::isBetterResolvedType (Type ty1, Type ty2) {
2341
+ assert (ty1 && ty2);
2342
+ assert (
2343
+ (ty1->isTypeParameter () || ty2->isTypeParameter () || ty1->isEqual (ty2)) &&
2344
+ " Ambigious concrete resolved type" );
2345
+
2346
+ return !ty1->isTypeParameter () && ty2->isTypeParameter ();
2347
+ }
2348
+
2110
2349
void ConformanceChecker::resolveTypeWitnesses () {
2111
2350
// Attempt to infer associated type witnesses.
2112
2351
AssociatedTypeInference inference (getASTContext (), Conformance);
0 commit comments