@@ -2208,19 +2208,25 @@ static bool isMainDispatchQueueMember(ConstraintLocator *locator) {
22082208 return true ;
22092209}
22102210
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.
22142212// /
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) {
22242230 assert (baseTy->isExistentialType ());
22252231 if (!containsFn (refTy))
22262232 return refTy;
@@ -2234,15 +2240,28 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
22342240
22352241 if (t->is <MetatypeType>()) {
22362242 const auto instanceTy = t->getMetatypeInstanceType ();
2237- const auto erasedTy = typeEraseExistentialSelfReferences (
2243+ auto erasedTy = typeEraseExistentialSelfReferences (
22382244 instanceTy, baseTy, currPos, existentialSig, containsFn,
2239- predicateFn, projectionFn, force, metatypeDepth + 1 );
2240-
2245+ predicateFn, projectionFn, force);
22412246 if (instanceTy.getPointer () == erasedTy.getPointer ()) {
22422247 return Type (t);
22432248 }
22442249
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));
22462265 }
22472266
22482267 // Opaque types whose substitutions involve this type parameter are
@@ -2252,8 +2271,7 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
22522271 opaque->getSubstitutions ().getReplacementTypes ()) {
22532272 auto erasedReplacementType = typeEraseExistentialSelfReferences (
22542273 replacementType, baseTy, TypePosition::Covariant,
2255- existentialSig, containsFn, predicateFn, projectionFn, force,
2256- metatypeDepth);
2274+ existentialSig, containsFn, predicateFn, projectionFn, force);
22572275 if (erasedReplacementType.getPointer () !=
22582276 replacementType.getPointer ())
22592277 return opaque->getExistentialType ();
@@ -2266,7 +2284,7 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
22662284 for (auto argType : parameterized->getArgs ()) {
22672285 auto erasedArgType = typeEraseExistentialSelfReferences (
22682286 argType, baseTy, TypePosition::Covariant, existentialSig,
2269- containsFn, predicateFn, projectionFn, force, metatypeDepth );
2287+ containsFn, predicateFn, projectionFn, force);
22702288 if (erasedArgType.getPointer () != argType.getPointer ())
22712289 return parameterized->getBaseType ();
22722290 }
@@ -2278,7 +2296,7 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
22782296 typeEraseExistentialSelfReferences(
22792297 objTy, baseTy, currPos,
22802298 existentialSig, containsFn, predicateFn, projectionFn,
2281- force, metatypeDepth );
2299+ force);
22822300
22832301 if (erasedTy.getPointer() == objTy.getPointer())
22842302 return Type(lvalue);
@@ -2296,6 +2314,8 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
22962314 if (!paramTy)
22972315 return Type (t);
22982316
2317+ assert (paramTy->isTypeParameter ());
2318+
22992319 // This can happen with invalid code.
23002320 if (!existentialSig->isValidTypeParameter (paramTy)) {
23012321 return Type (t);
@@ -2307,11 +2327,8 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
23072327 concreteTy, baseTy, currPos, existentialSig,
23082328 [](Type t) { return t->hasTypeParameter (); },
23092329 [](Type t) { return t->isTypeParameter (); },
2310- [](Type t) { return t; }, force, metatypeDepth );
2330+ [](Type t) { return t; }, force);
23112331 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.
23152332 return Type (t);
23162333 }
23172334
@@ -2339,11 +2356,6 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
23392356 erasedTy = existentialSig->getExistentialType (paramTy);
23402357 }
23412358
2342- if (metatypeDepth) {
2343- if (const auto existential = erasedTy->getAs <ExistentialType>())
2344- return existential->getConstraintType ();
2345- }
2346-
23472359 return erasedTy;
23482360 });
23492361}
0 commit comments