@@ -2208,19 +2208,25 @@ static bool isMainDispatchQueueMember(ConstraintLocator *locator) {
2208
2208
return true ;
2209
2209
}
2210
2210
2211
- // / Type-erase occurrences of covariant 'Self'-rooted type parameters to their
2212
- // / most specific upper bounds throughout the given type, using \p baseTy as
2213
- // / the existential base object type.
2211
+ // / Transforms `refTy` as follows.
2214
2212
// /
2215
- // / \note If a 'Self'-rooted type parameter is bound to a concrete type, this
2216
- // / routine will recurse into the concrete type.
2217
- static Type typeEraseExistentialSelfReferences (Type refTy, Type baseTy,
2218
- TypePosition outermostPosition,
2219
- GenericSignature existentialSig,
2220
- llvm::function_ref<bool (Type)> containsFn,
2221
- llvm::function_ref<bool(Type)> predicateFn,
2222
- llvm::function_ref<Type(Type)> projectionFn,
2223
- bool force, unsigned metatypeDepth = 0) {
2213
+ // / For each occurrence of a type **type** that satisfies `predicateFn` in
2214
+ // / covariant position:
2215
+ // / 1. **type** is projected to a type parameter using `projectionFn`.
2216
+ // / 2. If the type parameter is not bound to a concrete type, it is type-erased
2217
+ // / to the most specific upper bounds using `existentialSig` and substituted
2218
+ // / for **type**. Otherwise, the concrete type is transformed recursively.
2219
+ // / The result is substituted for **type** unless it is an identity
2220
+ // / transform.
2221
+ // /
2222
+ // / `baseTy` is used as a ready substitution for the `Self` generic parameter.
2223
+ // /
2224
+ // / @param force If `true`, proceeds regardless of a type's variance position.
2225
+ static Type typeEraseExistentialSelfReferences (
2226
+ Type refTy, Type baseTy, TypePosition outermostPosition,
2227
+ GenericSignature existentialSig, llvm::function_ref<bool (Type)> containsFn,
2228
+ llvm::function_ref<bool(Type)> predicateFn,
2229
+ llvm::function_ref<Type(Type)> projectionFn, bool force) {
2224
2230
assert (baseTy->isExistentialType ());
2225
2231
if (!containsFn (refTy))
2226
2232
return refTy;
@@ -2234,15 +2240,28 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
2234
2240
2235
2241
if (t->is <MetatypeType>()) {
2236
2242
const auto instanceTy = t->getMetatypeInstanceType ();
2237
- const auto erasedTy = typeEraseExistentialSelfReferences (
2243
+ auto erasedTy = typeEraseExistentialSelfReferences (
2238
2244
instanceTy, baseTy, currPos, existentialSig, containsFn,
2239
- predicateFn, projectionFn, force, metatypeDepth + 1 );
2240
-
2245
+ predicateFn, projectionFn, force);
2241
2246
if (instanceTy.getPointer () == erasedTy.getPointer ()) {
2242
2247
return Type (t);
2243
2248
}
2244
2249
2245
- return Type (ExistentialMetatypeType::get (erasedTy));
2250
+ // - If the output instance type is an existential, but the input is
2251
+ // not, wrap the output in an existential metatype.
2252
+ //
2253
+ // X.Type → X → any Y → any Y.Type
2254
+ //
2255
+ // - Otherwise, both are existential or the output instance type is
2256
+ // not existential; wrap the output in a singleton metatype.
2257
+ if (erasedTy->isAnyExistentialType () &&
2258
+ !erasedTy->isConstraintType () &&
2259
+ !(instanceTy->isAnyExistentialType () &&
2260
+ !instanceTy->isConstraintType ())) {
2261
+ return Type (ExistentialMetatypeType::get (erasedTy));
2262
+ }
2263
+
2264
+ return Type (MetatypeType::get (erasedTy));
2246
2265
}
2247
2266
2248
2267
// Opaque types whose substitutions involve this type parameter are
@@ -2252,8 +2271,7 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
2252
2271
opaque->getSubstitutions ().getReplacementTypes ()) {
2253
2272
auto erasedReplacementType = typeEraseExistentialSelfReferences (
2254
2273
replacementType, baseTy, TypePosition::Covariant,
2255
- existentialSig, containsFn, predicateFn, projectionFn, force,
2256
- metatypeDepth);
2274
+ existentialSig, containsFn, predicateFn, projectionFn, force);
2257
2275
if (erasedReplacementType.getPointer () !=
2258
2276
replacementType.getPointer ())
2259
2277
return opaque->getExistentialType ();
@@ -2266,7 +2284,7 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
2266
2284
for (auto argType : parameterized->getArgs ()) {
2267
2285
auto erasedArgType = typeEraseExistentialSelfReferences (
2268
2286
argType, baseTy, TypePosition::Covariant, existentialSig,
2269
- containsFn, predicateFn, projectionFn, force, metatypeDepth );
2287
+ containsFn, predicateFn, projectionFn, force);
2270
2288
if (erasedArgType.getPointer () != argType.getPointer ())
2271
2289
return parameterized->getBaseType ();
2272
2290
}
@@ -2278,7 +2296,7 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
2278
2296
typeEraseExistentialSelfReferences(
2279
2297
objTy, baseTy, currPos,
2280
2298
existentialSig, containsFn, predicateFn, projectionFn,
2281
- force, metatypeDepth );
2299
+ force);
2282
2300
2283
2301
if (erasedTy.getPointer() == objTy.getPointer())
2284
2302
return Type(lvalue);
@@ -2296,6 +2314,8 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
2296
2314
if (!paramTy)
2297
2315
return Type (t);
2298
2316
2317
+ assert (paramTy->isTypeParameter ());
2318
+
2299
2319
// This can happen with invalid code.
2300
2320
if (!existentialSig->isValidTypeParameter (paramTy)) {
2301
2321
return Type (t);
@@ -2307,11 +2327,8 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
2307
2327
concreteTy, baseTy, currPos, existentialSig,
2308
2328
[](Type t) { return t->hasTypeParameter (); },
2309
2329
[](Type t) { return t->isTypeParameter (); },
2310
- [](Type t) { return t; }, force, metatypeDepth );
2330
+ [](Type t) { return t; }, force);
2311
2331
if (erasedTy.getPointer () == concreteTy.getPointer ()) {
2312
- // Don't return the concrete type if we haven't type-erased
2313
- // anything inside it, or else we might inadvertently transform a
2314
- // normal metatype into an existential one.
2315
2332
return Type (t);
2316
2333
}
2317
2334
@@ -2339,11 +2356,6 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
2339
2356
erasedTy = existentialSig->getExistentialType (paramTy);
2340
2357
}
2341
2358
2342
- if (metatypeDepth) {
2343
- if (const auto existential = erasedTy->getAs <ExistentialType>())
2344
- return existential->getConstraintType ();
2345
- }
2346
-
2347
2359
return erasedTy;
2348
2360
});
2349
2361
}
0 commit comments