@@ -3739,12 +3739,13 @@ SelfReferenceInfo::operator|=(const SelfReferenceInfo &other) {
37393739 return *this ;
37403740}
37413741
3742- // / Report references to 'Self' within the given type.
3742+ // / Report references to 'Self' within the given type using the given
3743+ // / existential generic signature.
37433744// /
37443745// / \param position The current position in terms of variance.
3745- static SelfReferenceInfo findProtocolSelfReferences ( const ProtocolDecl *proto,
3746- Type type,
3747- TypePosition position) {
3746+ static SelfReferenceInfo
3747+ findExistentialSelfReferences (CanGenericSignature existentialSig, Type type,
3748+ TypePosition position) {
37483749 // If there are no type parameters, we're done.
37493750 if (!type->hasTypeParameter ())
37503751 return SelfReferenceInfo ();
@@ -3753,7 +3754,8 @@ static SelfReferenceInfo findProtocolSelfReferences(const ProtocolDecl *proto,
37533754 if (auto tuple = type->getAs <TupleType>()) {
37543755 auto info = SelfReferenceInfo ();
37553756 for (auto &elt : tuple->getElements ()) {
3756- info |= findProtocolSelfReferences (proto, elt.getType (), position);
3757+ info |= findExistentialSelfReferences (existentialSig, elt.getType (),
3758+ position);
37573759 }
37583760
37593761 // A covariant Self result inside a tuple will not be bona fide.
@@ -3769,19 +3771,19 @@ static SelfReferenceInfo findProtocolSelfReferences(const ProtocolDecl *proto,
37693771 for (auto param : funcTy->getParams ()) {
37703772 // inout parameters are invariant.
37713773 if (param.isInOut ()) {
3772- inputInfo |= findProtocolSelfReferences (proto, param. getPlainType (),
3773- TypePosition::Invariant);
3774+ inputInfo |= findExistentialSelfReferences (
3775+ existentialSig, param. getPlainType (), TypePosition::Invariant);
37743776 continue ;
37753777 }
3776- inputInfo |= findProtocolSelfReferences (proto, param. getParameterType (),
3777- position.flipped ());
3778+ inputInfo |= findExistentialSelfReferences (
3779+ existentialSig, param. getParameterType (), position.flipped ());
37783780 }
37793781
37803782 // A covariant Self result inside a parameter will not be bona fide.
37813783 inputInfo.hasCovariantSelfResult = false ;
37823784
3783- auto resultInfo =
3784- findProtocolSelfReferences (proto , funcTy->getResult (), position);
3785+ auto resultInfo = findExistentialSelfReferences (
3786+ existentialSig , funcTy->getResult (), position);
37853787 if (resultInfo.selfRef == TypePosition::Covariant) {
37863788 resultInfo.hasCovariantSelfResult = true ;
37873789 }
@@ -3790,46 +3792,48 @@ static SelfReferenceInfo findProtocolSelfReferences(const ProtocolDecl *proto,
37903792
37913793 // Metatypes preserve variance.
37923794 if (auto metaTy = type->getAs <MetatypeType>()) {
3793- return findProtocolSelfReferences (proto, metaTy-> getInstanceType () ,
3794- position);
3795+ return findExistentialSelfReferences (existentialSig ,
3796+ metaTy-> getInstanceType (), position);
37953797 }
37963798
37973799 // Optionals preserve variance.
37983800 if (auto optType = type->getOptionalObjectType ()) {
3799- return findProtocolSelfReferences (proto , optType, position);
3801+ return findExistentialSelfReferences (existentialSig , optType, position);
38003802 }
38013803
38023804 // DynamicSelfType preserves variance.
38033805 // FIXME: This shouldn't ever appear in protocol requirement
38043806 // signatures.
38053807 if (auto selfType = type->getAs <DynamicSelfType>()) {
3806- return findProtocolSelfReferences (proto, selfType->getSelfType (), position);
3808+ return findExistentialSelfReferences (existentialSig,
3809+ selfType->getSelfType (), position);
38073810 }
38083811
38093812 if (auto *const nominal = type->getAs <NominalOrBoundGenericNominalType>()) {
38103813 auto info = SelfReferenceInfo ();
38113814
38123815 // Don't forget to look in the parent.
38133816 if (const auto parent = nominal->getParent ()) {
3814- info |= findProtocolSelfReferences (proto , parent, position);
3817+ info |= findExistentialSelfReferences (existentialSig , parent, position);
38153818 }
38163819
38173820 // Most bound generic types are invariant.
38183821 if (auto *const bgt = type->getAs <BoundGenericType>()) {
38193822 if (bgt->isArray ()) {
3820- // Swift.Array preserves variance in its Value type.
3821- info |= findProtocolSelfReferences (proto, bgt-> getGenericArgs (). front (),
3822- position);
3823+ // Swift.Array preserves variance in its ' Value' type.
3824+ info |= findExistentialSelfReferences (
3825+ existentialSig, bgt-> getGenericArgs (). front (), position);
38233826 } else if (bgt->isDictionary ()) {
3824- // Swift.Dictionary preserves variance in its Element type.
3825- info |= findProtocolSelfReferences (proto, bgt->getGenericArgs ().front (),
3826- TypePosition::Invariant);
3827- info |= findProtocolSelfReferences (proto, bgt->getGenericArgs ().back (),
3828- position);
3827+ // Swift.Dictionary preserves variance in its 'Element' type.
3828+ info |= findExistentialSelfReferences (existentialSig,
3829+ bgt->getGenericArgs ().front (),
3830+ TypePosition::Invariant);
3831+ info |= findExistentialSelfReferences (
3832+ existentialSig, bgt->getGenericArgs ().back (), position);
38293833 } else {
38303834 for (auto paramType : bgt->getGenericArgs ()) {
3831- info |= findProtocolSelfReferences (proto , paramType,
3832- TypePosition::Invariant);
3835+ info |= findExistentialSelfReferences (existentialSig , paramType,
3836+ TypePosition::Invariant);
38333837 }
38343838 }
38353839 }
@@ -3849,29 +3853,45 @@ static SelfReferenceInfo findProtocolSelfReferences(const ProtocolDecl *proto,
38493853 if (auto *comp = constraint->getAs <ProtocolCompositionType>()) {
38503854 // 'Self' may be referenced only in a superclass component.
38513855 if (const auto superclass = comp->getSuperclass ()) {
3852- return findProtocolSelfReferences (proto, superclass, position);
3856+ return findExistentialSelfReferences (existentialSig, superclass,
3857+ position);
38533858 }
38543859
38553860 return SelfReferenceInfo ();
38563861 }
38573862
3863+ if (!type->isTypeParameter ()) {
3864+ return SelfReferenceInfo ();
3865+ }
3866+
3867+ const auto selfTy = existentialSig.getGenericParams ().front ();
3868+ if (!type->getRootGenericParam ()->isEqual (selfTy)) {
3869+ return SelfReferenceInfo ();
3870+ }
3871+
38583872 // A direct reference to 'Self'.
3859- if (proto-> getSelfInterfaceType ()-> isEqual (type))
3873+ if (selfTy-> isEqual (type)) {
38603874 return SelfReferenceInfo::forSelfRef (position);
3875+ }
38613876
3862- // A reference to an associated type rooted on 'Self'.
3863- if (type->is <DependentMemberType>()) {
3864- type = type->getRootGenericParam ();
3865- if (proto->getSelfInterfaceType ()->isEqual (type))
3866- return SelfReferenceInfo::forAssocTypeRef (position);
3877+ // If the type parameter is beyond the domain of the existential generic
3878+ // signature, ignore it.
3879+ if (!existentialSig->isValidTypeInContext (type)) {
3880+ return SelfReferenceInfo ();
38673881 }
38683882
3869- return SelfReferenceInfo ();
3883+ if (const auto concreteTy = existentialSig->getConcreteType (type)) {
3884+ return findExistentialSelfReferences (existentialSig, concreteTy, position);
3885+ }
3886+
3887+ // A reference to an associated type rooted on 'Self'.
3888+ return SelfReferenceInfo::forAssocTypeRef (position);
38703889}
38713890
3872- SelfReferenceInfo ValueDecl::findProtocolSelfReferences (
3873- const ProtocolDecl *proto,
3874- bool treatNonResultCovariantSelfAsInvariant) const {
3891+ SelfReferenceInfo ValueDecl::findExistentialSelfReferences (
3892+ Type baseTy, bool treatNonResultCovariantSelfAsInvariant) const {
3893+ assert (baseTy->isExistentialType ());
3894+
38753895 // Types never refer to 'Self'.
38763896 if (isa<TypeDecl>(this ))
38773897 return SelfReferenceInfo ();
@@ -3882,6 +3902,8 @@ SelfReferenceInfo ValueDecl::findProtocolSelfReferences(
38823902 if (type->hasError ())
38833903 return SelfReferenceInfo ();
38843904
3905+ const auto sig = getASTContext ().getOpenedArchetypeSignature (baseTy);
3906+
38853907 if (isa<AbstractFunctionDecl>(this ) || isa<SubscriptDecl>(this )) {
38863908 // For a method, skip the 'self' parameter.
38873909 if (isa<AbstractFunctionDecl>(this ))
@@ -3891,12 +3913,12 @@ SelfReferenceInfo ValueDecl::findProtocolSelfReferences(
38913913 for (auto param : type->castTo <AnyFunctionType>()->getParams ()) {
38923914 // inout parameters are invariant.
38933915 if (param.isInOut ()) {
3894- inputInfo |= ::findProtocolSelfReferences (proto , param.getPlainType (),
3895- TypePosition::Invariant);
3916+ inputInfo |= ::findExistentialSelfReferences (sig , param.getPlainType (),
3917+ TypePosition::Invariant);
38963918 continue ;
38973919 }
3898- inputInfo |= ::findProtocolSelfReferences (proto, param. getParameterType (),
3899- TypePosition::Contravariant);
3920+ inputInfo |= ::findExistentialSelfReferences (
3921+ sig, param. getParameterType (), TypePosition::Contravariant);
39003922 }
39013923
39023924 // A covariant Self result inside a parameter will not be bona fide.
@@ -3913,8 +3935,8 @@ SelfReferenceInfo ValueDecl::findProtocolSelfReferences(
39133935 inputInfo.selfRef = TypePosition::Invariant;
39143936 }
39153937
3916- auto resultInfo = ::findProtocolSelfReferences (
3917- proto , type->castTo <AnyFunctionType>()->getResult (),
3938+ auto resultInfo = ::findExistentialSelfReferences (
3939+ sig , type->castTo <AnyFunctionType>()->getResult (),
39183940 TypePosition::Covariant);
39193941 if (resultInfo.selfRef == TypePosition::Covariant) {
39203942 resultInfo.hasCovariantSelfResult = true ;
@@ -3925,7 +3947,7 @@ SelfReferenceInfo ValueDecl::findProtocolSelfReferences(
39253947 assert (isa<VarDecl>(this ));
39263948
39273949 auto info =
3928- ::findProtocolSelfReferences (proto , type, TypePosition::Covariant);
3950+ ::findExistentialSelfReferences (sig , type, TypePosition::Covariant);
39293951 if (info.selfRef == TypePosition::Covariant) {
39303952 info.hasCovariantSelfResult = true ;
39313953 }
0 commit comments