@@ -2265,26 +2265,14 @@ static bool isMainDispatchQueueMember(ConstraintLocator *locator) {
22652265 return true ;
22662266}
22672267
2268- // / Transforms `refTy` as follows.
2269- // /
2270- // / For each occurrence of a type **type** that satisfies `predicateFn` in
2271- // / covariant position:
2272- // / 1. **type** is projected to a type parameter using `projectionFn`.
2273- // / 2. If the type parameter is not bound to a concrete type, it is type-erased
2274- // / to the most specific upper bounds using `existentialSig` and substituted
2275- // / for **type**. Otherwise, the concrete type is transformed recursively.
2276- // / The result is substituted for **type** unless it is an identity
2277- // / transform.
2278- // /
2279- // / `baseTy` is used as a ready substitution for the `Self` generic parameter.
2280- // /
2281- // / @param force If `true`, proceeds regardless of a type's variance position.
2268+ // / For each occurrence of a type **type** in `refTy` that satisfies
2269+ // / `predicateFn` in covariant position, **type** is erased to an
2270+ // / existential using `eraseFn`.
22822271static Type typeEraseExistentialSelfReferences (
2283- Type refTy, Type baseTy, TypePosition outermostPosition,
2284- GenericSignature existentialSig, llvm::function_ref<bool (Type)> containsFn,
2272+ Type refTy, TypePosition outermostPosition,
2273+ llvm::function_ref<bool (Type)> containsFn,
22852274 llvm::function_ref<bool(Type)> predicateFn,
2286- llvm::function_ref<Type(Type)> projectionFn, bool force) {
2287- assert (baseTy->isExistentialType ());
2275+ llvm::function_ref<Type(Type, TypePosition)> eraseFn) {
22882276 if (!containsFn (refTy))
22892277 return refTy;
22902278
@@ -2298,8 +2286,8 @@ static Type typeEraseExistentialSelfReferences(
22982286 if (t->is <MetatypeType>()) {
22992287 const auto instanceTy = t->getMetatypeInstanceType ();
23002288 auto erasedTy = typeEraseExistentialSelfReferences (
2301- instanceTy, baseTy, currPos, existentialSig, containsFn ,
2302- predicateFn, projectionFn, force );
2289+ instanceTy, currPos,
2290+ containsFn, predicateFn, eraseFn );
23032291 if (instanceTy.getPointer () == erasedTy.getPointer ()) {
23042292 return Type (t);
23052293 }
@@ -2327,8 +2315,8 @@ static Type typeEraseExistentialSelfReferences(
23272315 for (auto replacementType :
23282316 opaque->getSubstitutions ().getReplacementTypes ()) {
23292317 auto erasedReplacementType = typeEraseExistentialSelfReferences (
2330- replacementType, baseTy, TypePosition::Covariant,
2331- existentialSig, containsFn, predicateFn, projectionFn, force );
2318+ replacementType, TypePosition::Covariant,
2319+ containsFn, predicateFn, eraseFn );
23322320 if (erasedReplacementType.getPointer () !=
23332321 replacementType.getPointer ())
23342322 return opaque->getExistentialType ();
@@ -2340,8 +2328,8 @@ static Type typeEraseExistentialSelfReferences(
23402328 if (auto parameterized = dyn_cast<ParameterizedProtocolType>(t)) {
23412329 for (auto argType : parameterized->getArgs ()) {
23422330 auto erasedArgType = typeEraseExistentialSelfReferences (
2343- argType, baseTy, TypePosition::Covariant, existentialSig ,
2344- containsFn, predicateFn, projectionFn, force );
2331+ argType, TypePosition::Covariant,
2332+ containsFn, predicateFn, eraseFn );
23452333 if (erasedArgType.getPointer () != argType.getPointer ())
23462334 return parameterized->getBaseType ();
23472335 }
@@ -2351,9 +2339,8 @@ static Type typeEraseExistentialSelfReferences(
23512339 auto objTy = lvalue->getObjectType();
23522340 auto erasedTy =
23532341 typeEraseExistentialSelfReferences(
2354- objTy, baseTy, currPos,
2355- existentialSig, containsFn, predicateFn, projectionFn,
2356- force);
2342+ objTy, currPos,
2343+ containsFn, predicateFn, eraseFn);
23572344
23582345 if (erasedTy.getPointer() == objTy.getPointer())
23592346 return Type(lvalue);
@@ -2367,52 +2354,10 @@ static Type typeEraseExistentialSelfReferences(
23672354 return std::nullopt ;
23682355 }
23692356
2370- auto paramTy = projectionFn (t );
2371- if (!paramTy )
2357+ auto erasedTy = eraseFn (t, currPos );
2358+ if (!erasedTy )
23722359 return Type (t);
23732360
2374- assert (paramTy->isTypeParameter ());
2375-
2376- // This can happen with invalid code.
2377- if (!existentialSig->isValidTypeParameter (paramTy)) {
2378- return Type (t);
2379- }
2380-
2381- // If the type parameter is fixed to a concrete type, recurse into it.
2382- if (const auto concreteTy = existentialSig->getConcreteType (paramTy)) {
2383- auto erasedTy = typeEraseExistentialSelfReferences (
2384- concreteTy, baseTy, currPos, existentialSig,
2385- [](Type t) { return t->hasTypeParameter (); },
2386- [](Type t) { return t->isTypeParameter (); },
2387- [](Type t) { return t; }, force);
2388- if (erasedTy.getPointer () == concreteTy.getPointer ()) {
2389- return Type (t);
2390- }
2391-
2392- return erasedTy;
2393- }
2394-
2395- if (!force) {
2396- switch (currPos) {
2397- case TypePosition::Covariant:
2398- break ;
2399-
2400- case TypePosition::Contravariant:
2401- case TypePosition::Invariant:
2402- case TypePosition::Shape:
2403- return Type (t);
2404- }
2405- }
2406-
2407- Type erasedTy;
2408-
2409- // The upper bounds of 'Self' is the existential base type.
2410- if (paramTy->is <GenericTypeParamType>()) {
2411- erasedTy = baseTy;
2412- } else {
2413- erasedTy = existentialSig->getExistentialType (paramTy);
2414- }
2415-
24162361 return erasedTy;
24172362 });
24182363}
@@ -2422,58 +2367,109 @@ Type constraints::typeEraseOpenedExistentialReference(
24222367 TypePosition outermostPosition) {
24232368 auto existentialSig =
24242369 type->getASTContext ().getOpenedExistentialSignature (
2425- existentialBaseType, GenericSignature ());
2426- auto selfGP = existentialSig.getGenericParams ()[0 ];
2370+ existentialBaseType);
2371+
2372+ auto applyOuterSubstitutions = [&](Type t) -> Type {
2373+ if (t->hasTypeParameter ()) {
2374+ auto outerSubs = existentialSig.Generalization ;
2375+ unsigned depth = existentialSig.OpenedSig ->getMaxDepth ();
2376+ OuterSubstitutions replacer{outerSubs, depth};
2377+ return t.subst (replacer, replacer);
2378+ }
2379+
2380+ return t;
2381+ };
2382+
2383+ auto erase = [&](Type paramTy, TypePosition currPos) -> Type {
2384+ switch (currPos) {
2385+ case TypePosition::Covariant:
2386+ break ;
2387+
2388+ case TypePosition::Contravariant:
2389+ case TypePosition::Invariant:
2390+ case TypePosition::Shape:
2391+ return Type ();
2392+ }
2393+
2394+ // The upper bounds of 'Self' is the existential base type.
2395+ if (paramTy->is <GenericTypeParamType>())
2396+ return existentialBaseType;
2397+
2398+ return applyOuterSubstitutions (
2399+ existentialSig.OpenedSig ->getExistentialType (paramTy));
2400+ };
24272401
24282402 return typeEraseExistentialSelfReferences (
2429- type, existentialBaseType, outermostPosition, existentialSig,
2403+ type,
2404+ outermostPosition,
24302405 /* containsFn=*/ [](Type t) {
24312406 return t->hasTypeVariable ();
24322407 },
24332408 /* predicateFn=*/ [](Type t) {
24342409 return t->isTypeVariableOrMember ();
24352410 },
2436- /* projectionFn =*/ [&](Type t) {
2411+ /* eraseFn =*/ [&](Type t, TypePosition currPos) -> Type {
24372412 bool found = false ;
2438- auto result = t.transformRec ([&](Type t) -> std::optional<Type> {
2413+ auto paramTy = t.transformRec ([&](Type t) -> std::optional<Type> {
24392414 if (t.getPointer () == openedTypeVar) {
24402415 found = true ;
2441- return selfGP ;
2416+ return existentialSig. SelfType ;
24422417 }
24432418 return std::nullopt ;
24442419 });
24452420
24462421 if (!found)
24472422 return Type ();
24482423
2449- assert (result->isTypeParameter ());
2450- return result;
2451- },
2452- /* force=*/ false );
2424+ assert (paramTy->isTypeParameter ());
2425+
2426+ // This can happen with invalid code.
2427+ if (!existentialSig.OpenedSig ->isValidTypeParameter (paramTy)) {
2428+ return Type (t);
2429+ }
2430+
2431+ // Check if this existential fixes this `Self`-rooted type to something
2432+ // in the existential's outer generic signature.
2433+ Type reducedTy = existentialSig.OpenedSig .getReducedType (paramTy);
2434+ if (!reducedTy->isEqual (paramTy)) {
2435+ reducedTy = applyOuterSubstitutions (reducedTy);
2436+
2437+ auto erasedTy = typeEraseExistentialSelfReferences (
2438+ reducedTy, currPos,
2439+ [&](Type t) { return t->hasTypeParameter (); },
2440+ [&](Type t) { return t->isTypeParameter (); },
2441+ [&](Type t, TypePosition currPos) { return erase (t, currPos); });
2442+ if (erasedTy.getPointer () == reducedTy.getPointer ()) {
2443+ return Type (t);
2444+ }
2445+
2446+ return erasedTy;
2447+ }
2448+
2449+ return erase (paramTy, currPos);
2450+ });
24532451}
24542452
24552453Type constraints::typeEraseOpenedArchetypesFromEnvironment (
24562454 Type type, GenericEnvironment *env) {
24572455 assert (env->getKind () == GenericEnvironment::Kind::OpenedExistential);
24582456
2459- auto sig = env->getGenericSignature ();
2460-
24612457 return typeEraseExistentialSelfReferences (
2462- type, env->getOpenedExistentialType (), TypePosition::Covariant, sig,
2458+ type,
2459+ TypePosition::Covariant,
24632460 /* containsFn=*/ [](Type t) {
24642461 return t->hasOpenedExistential ();
24652462 },
24662463 /* predicateFn=*/ [](Type t) {
24672464 return t->is <OpenedArchetypeType>();
24682465 },
2469- /* projectionFn =*/ [&](Type t) {
2466+ /* eraseFn =*/ [&](Type t, TypePosition currPos ) {
24702467 auto *openedTy = t->castTo <OpenedArchetypeType>();
24712468 if (openedTy->getGenericEnvironment () == env)
2472- return openedTy->getInterfaceType ();
2469+ return openedTy->getExistentialType ();
24732470
24742471 return Type ();
2475- },
2476- /* force=*/ true );
2472+ });
24772473}
24782474
24792475static bool isExistentialMemberAccessWithExplicitBaseExpression (
0 commit comments