@@ -7447,14 +7447,21 @@ static bool doesMemberHaveUnfulfillableConstraintsWithExistentialBase(
7447
7447
return false ;
7448
7448
}
7449
7449
7450
- class IsDependentOnSelfInBaseTypeContextWalker : public TypeWalker {
7451
- CanGenericSignature Sig;
7450
+ auto &ctx = member->getASTContext ();
7451
+ auto existentialSig = ctx.getOpenedExistentialSignature (baseTy);
7452
+
7453
+ class IsDependentOnOpenedExistentialSelf : public TypeWalker {
7454
+ OpenedExistentialSignature existentialSig;
7452
7455
7453
7456
public:
7454
- explicit IsDependentOnSelfInBaseTypeContextWalker (CanGenericSignature Sig )
7455
- : Sig(Sig ) {}
7457
+ explicit IsDependentOnOpenedExistentialSelf (OpenedExistentialSignature existentialSig )
7458
+ : existentialSig(existentialSig ) {}
7456
7459
7457
7460
Action walkToTypePre (Type ty) override {
7461
+ // We're looking at the interface type of a protocol member, so it's written
7462
+ // in terms of `Self` (tau_0_0) and possibly type parameters at higher depth:
7463
+ //
7464
+ // <Self, ... where Self: P, ...>
7458
7465
if (!ty->isTypeParameter ()) {
7459
7466
return Action::Continue;
7460
7467
}
@@ -7463,25 +7470,44 @@ static bool doesMemberHaveUnfulfillableConstraintsWithExistentialBase(
7463
7470
return Action::SkipNode;
7464
7471
}
7465
7472
7466
- if (!Sig->isValidTypeParameter (ty)) {
7473
+ // Ok, we found a type parameter rooted in `Self`. Replace `Self` with the
7474
+ // opened Self type in the existential signature, which looks like this:
7475
+ //
7476
+ // <..., Self where ..., Self: P>
7477
+ ty = ty.subst (
7478
+ [&](SubstitutableType *type) -> Type {
7479
+ return existentialSig.SelfType ;
7480
+ },
7481
+ MakeAbstractConformanceForGenericType ());
7482
+
7483
+ // Make sure this is valid first.
7484
+ if (!existentialSig.OpenedSig ->isValidTypeParameter (ty)) {
7467
7485
return Action::SkipNode;
7468
7486
}
7469
7487
7470
- const auto concreteTy = Sig->getConcreteType (ty);
7471
- if (concreteTy && !concreteTy->hasTypeParameter ()) {
7488
+ // If the existential type constrains Self.U to a type from the outer
7489
+ // context, then the reduced type of Self.U in the existential signature
7490
+ // will no longer contain Self.
7491
+ ty = existentialSig.OpenedSig .getReducedType (ty);
7492
+
7493
+ if (!ty.findIf ([&](Type t) -> bool {
7494
+ if (auto *paramTy = t->getAs <GenericTypeParamType>())
7495
+ return paramTy->isEqual (existentialSig.SelfType );
7496
+ return false ;
7497
+ })) {
7472
7498
return Action::SkipNode;
7473
7499
}
7474
7500
7501
+ // Ok, we found a type that depends on the opened existential Self.
7475
7502
return Action::Stop;
7476
7503
}
7477
- } isDependentOnSelfWalker (member->getASTContext ().getOpenedExistentialSignature (
7478
- baseTy, GenericSignature ()));
7504
+ } isDependentOnSelf (existentialSig);
7479
7505
7480
7506
for (const auto &req : sig.getRequirements ()) {
7481
7507
switch (req.getKind ()) {
7482
7508
case RequirementKind::Superclass: {
7483
7509
if (req.getFirstType ()->getRootGenericParam ()->getDepth () > 0 &&
7484
- req.getSecondType ().walk (isDependentOnSelfWalker )) {
7510
+ req.getSecondType ().walk (isDependentOnSelf )) {
7485
7511
return true ;
7486
7512
}
7487
7513
@@ -7495,9 +7521,9 @@ static bool doesMemberHaveUnfulfillableConstraintsWithExistentialBase(
7495
7521
};
7496
7522
7497
7523
if ((isNonSelfRootedTypeParam (req.getFirstType ()) &&
7498
- req.getSecondType ().walk (isDependentOnSelfWalker )) ||
7524
+ req.getSecondType ().walk (isDependentOnSelf )) ||
7499
7525
(isNonSelfRootedTypeParam (req.getSecondType ()) &&
7500
- req.getFirstType ().walk (isDependentOnSelfWalker ))) {
7526
+ req.getFirstType ().walk (isDependentOnSelf ))) {
7501
7527
return true ;
7502
7528
}
7503
7529
0 commit comments