@@ -2265,26 +2265,14 @@ static bool isMainDispatchQueueMember(ConstraintLocator *locator) {
2265
2265
return true ;
2266
2266
}
2267
2267
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`.
2282
2271
static 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,
2285
2274
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) {
2288
2276
if (!containsFn (refTy))
2289
2277
return refTy;
2290
2278
@@ -2298,8 +2286,8 @@ static Type typeEraseExistentialSelfReferences(
2298
2286
if (t->is <MetatypeType>()) {
2299
2287
const auto instanceTy = t->getMetatypeInstanceType ();
2300
2288
auto erasedTy = typeEraseExistentialSelfReferences (
2301
- instanceTy, baseTy, currPos, existentialSig, containsFn ,
2302
- predicateFn, projectionFn, force );
2289
+ instanceTy, currPos,
2290
+ containsFn, predicateFn, eraseFn );
2303
2291
if (instanceTy.getPointer () == erasedTy.getPointer ()) {
2304
2292
return Type (t);
2305
2293
}
@@ -2327,8 +2315,8 @@ static Type typeEraseExistentialSelfReferences(
2327
2315
for (auto replacementType :
2328
2316
opaque->getSubstitutions ().getReplacementTypes ()) {
2329
2317
auto erasedReplacementType = typeEraseExistentialSelfReferences (
2330
- replacementType, baseTy, TypePosition::Covariant,
2331
- existentialSig, containsFn, predicateFn, projectionFn, force );
2318
+ replacementType, TypePosition::Covariant,
2319
+ containsFn, predicateFn, eraseFn );
2332
2320
if (erasedReplacementType.getPointer () !=
2333
2321
replacementType.getPointer ())
2334
2322
return opaque->getExistentialType ();
@@ -2340,8 +2328,8 @@ static Type typeEraseExistentialSelfReferences(
2340
2328
if (auto parameterized = dyn_cast<ParameterizedProtocolType>(t)) {
2341
2329
for (auto argType : parameterized->getArgs ()) {
2342
2330
auto erasedArgType = typeEraseExistentialSelfReferences (
2343
- argType, baseTy, TypePosition::Covariant, existentialSig ,
2344
- containsFn, predicateFn, projectionFn, force );
2331
+ argType, TypePosition::Covariant,
2332
+ containsFn, predicateFn, eraseFn );
2345
2333
if (erasedArgType.getPointer () != argType.getPointer ())
2346
2334
return parameterized->getBaseType ();
2347
2335
}
@@ -2351,9 +2339,8 @@ static Type typeEraseExistentialSelfReferences(
2351
2339
auto objTy = lvalue->getObjectType();
2352
2340
auto erasedTy =
2353
2341
typeEraseExistentialSelfReferences(
2354
- objTy, baseTy, currPos,
2355
- existentialSig, containsFn, predicateFn, projectionFn,
2356
- force);
2342
+ objTy, currPos,
2343
+ containsFn, predicateFn, eraseFn);
2357
2344
2358
2345
if (erasedTy.getPointer() == objTy.getPointer())
2359
2346
return Type(lvalue);
@@ -2367,52 +2354,10 @@ static Type typeEraseExistentialSelfReferences(
2367
2354
return std::nullopt;
2368
2355
}
2369
2356
2370
- auto paramTy = projectionFn (t );
2371
- if (!paramTy )
2357
+ auto erasedTy = eraseFn (t, currPos );
2358
+ if (!erasedTy )
2372
2359
return Type (t);
2373
2360
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
-
2416
2361
return erasedTy;
2417
2362
});
2418
2363
}
@@ -2422,58 +2367,109 @@ Type constraints::typeEraseOpenedExistentialReference(
2422
2367
TypePosition outermostPosition) {
2423
2368
auto existentialSig =
2424
2369
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
+ };
2427
2401
2428
2402
return typeEraseExistentialSelfReferences (
2429
- type, existentialBaseType, outermostPosition, existentialSig,
2403
+ type,
2404
+ outermostPosition,
2430
2405
/* containsFn=*/ [](Type t) {
2431
2406
return t->hasTypeVariable ();
2432
2407
},
2433
2408
/* predicateFn=*/ [](Type t) {
2434
2409
return t->isTypeVariableOrMember ();
2435
2410
},
2436
- /* projectionFn =*/ [&](Type t) {
2411
+ /* eraseFn =*/ [&](Type t, TypePosition currPos) -> Type {
2437
2412
bool found = false ;
2438
- auto result = t.transformRec ([&](Type t) -> std::optional<Type> {
2413
+ auto paramTy = t.transformRec ([&](Type t) -> std::optional<Type> {
2439
2414
if (t.getPointer () == openedTypeVar) {
2440
2415
found = true ;
2441
- return selfGP ;
2416
+ return existentialSig. SelfType ;
2442
2417
}
2443
2418
return std::nullopt;
2444
2419
});
2445
2420
2446
2421
if (!found)
2447
2422
return Type ();
2448
2423
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
+ });
2453
2451
}
2454
2452
2455
2453
Type constraints::typeEraseOpenedArchetypesFromEnvironment (
2456
2454
Type type, GenericEnvironment *env) {
2457
2455
assert (env->getKind () == GenericEnvironment::Kind::OpenedExistential);
2458
2456
2459
- auto sig = env->getGenericSignature ();
2460
-
2461
2457
return typeEraseExistentialSelfReferences (
2462
- type, env->getOpenedExistentialType (), TypePosition::Covariant, sig,
2458
+ type,
2459
+ TypePosition::Covariant,
2463
2460
/* containsFn=*/ [](Type t) {
2464
2461
return t->hasOpenedExistential ();
2465
2462
},
2466
2463
/* predicateFn=*/ [](Type t) {
2467
2464
return t->is <OpenedArchetypeType>();
2468
2465
},
2469
- /* projectionFn =*/ [&](Type t) {
2466
+ /* eraseFn =*/ [&](Type t, TypePosition currPos ) {
2470
2467
auto *openedTy = t->castTo <OpenedArchetypeType>();
2471
2468
if (openedTy->getGenericEnvironment () == env)
2472
- return openedTy->getInterfaceType ();
2469
+ return openedTy->getExistentialType ();
2473
2470
2474
2471
return Type ();
2475
- },
2476
- /* force=*/ true );
2472
+ });
2477
2473
}
2478
2474
2479
2475
static bool isExistentialMemberAccessWithExplicitBaseExpression (
0 commit comments