@@ -3739,12 +3739,13 @@ SelfReferenceInfo::operator|=(const SelfReferenceInfo &other) {
3739
3739
return *this ;
3740
3740
}
3741
3741
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.
3743
3744
// /
3744
3745
// / \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) {
3748
3749
// If there are no type parameters, we're done.
3749
3750
if (!type->hasTypeParameter ())
3750
3751
return SelfReferenceInfo ();
@@ -3753,7 +3754,8 @@ static SelfReferenceInfo findProtocolSelfReferences(const ProtocolDecl *proto,
3753
3754
if (auto tuple = type->getAs <TupleType>()) {
3754
3755
auto info = SelfReferenceInfo ();
3755
3756
for (auto &elt : tuple->getElements ()) {
3756
- info |= findProtocolSelfReferences (proto, elt.getType (), position);
3757
+ info |= findExistentialSelfReferences (existentialSig, elt.getType (),
3758
+ position);
3757
3759
}
3758
3760
3759
3761
// A covariant Self result inside a tuple will not be bona fide.
@@ -3769,19 +3771,19 @@ static SelfReferenceInfo findProtocolSelfReferences(const ProtocolDecl *proto,
3769
3771
for (auto param : funcTy->getParams ()) {
3770
3772
// inout parameters are invariant.
3771
3773
if (param.isInOut ()) {
3772
- inputInfo |= findProtocolSelfReferences (proto, param. getPlainType (),
3773
- TypePosition::Invariant);
3774
+ inputInfo |= findExistentialSelfReferences (
3775
+ existentialSig, param. getPlainType (), TypePosition::Invariant);
3774
3776
continue ;
3775
3777
}
3776
- inputInfo |= findProtocolSelfReferences (proto, param. getParameterType (),
3777
- position.flipped ());
3778
+ inputInfo |= findExistentialSelfReferences (
3779
+ existentialSig, param. getParameterType (), position.flipped ());
3778
3780
}
3779
3781
3780
3782
// A covariant Self result inside a parameter will not be bona fide.
3781
3783
inputInfo.hasCovariantSelfResult = false ;
3782
3784
3783
- auto resultInfo =
3784
- findProtocolSelfReferences (proto , funcTy->getResult (), position);
3785
+ auto resultInfo = findExistentialSelfReferences (
3786
+ existentialSig , funcTy->getResult (), position);
3785
3787
if (resultInfo.selfRef == TypePosition::Covariant) {
3786
3788
resultInfo.hasCovariantSelfResult = true ;
3787
3789
}
@@ -3790,46 +3792,48 @@ static SelfReferenceInfo findProtocolSelfReferences(const ProtocolDecl *proto,
3790
3792
3791
3793
// Metatypes preserve variance.
3792
3794
if (auto metaTy = type->getAs <MetatypeType>()) {
3793
- return findProtocolSelfReferences (proto, metaTy-> getInstanceType () ,
3794
- position);
3795
+ return findExistentialSelfReferences (existentialSig ,
3796
+ metaTy-> getInstanceType (), position);
3795
3797
}
3796
3798
3797
3799
// Optionals preserve variance.
3798
3800
if (auto optType = type->getOptionalObjectType ()) {
3799
- return findProtocolSelfReferences (proto , optType, position);
3801
+ return findExistentialSelfReferences (existentialSig , optType, position);
3800
3802
}
3801
3803
3802
3804
// DynamicSelfType preserves variance.
3803
3805
// FIXME: This shouldn't ever appear in protocol requirement
3804
3806
// signatures.
3805
3807
if (auto selfType = type->getAs <DynamicSelfType>()) {
3806
- return findProtocolSelfReferences (proto, selfType->getSelfType (), position);
3808
+ return findExistentialSelfReferences (existentialSig,
3809
+ selfType->getSelfType (), position);
3807
3810
}
3808
3811
3809
3812
if (auto *const nominal = type->getAs <NominalOrBoundGenericNominalType>()) {
3810
3813
auto info = SelfReferenceInfo ();
3811
3814
3812
3815
// Don't forget to look in the parent.
3813
3816
if (const auto parent = nominal->getParent ()) {
3814
- info |= findProtocolSelfReferences (proto , parent, position);
3817
+ info |= findExistentialSelfReferences (existentialSig , parent, position);
3815
3818
}
3816
3819
3817
3820
// Most bound generic types are invariant.
3818
3821
if (auto *const bgt = type->getAs <BoundGenericType>()) {
3819
3822
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);
3823
3826
} 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);
3829
3833
} else {
3830
3834
for (auto paramType : bgt->getGenericArgs ()) {
3831
- info |= findProtocolSelfReferences (proto , paramType,
3832
- TypePosition::Invariant);
3835
+ info |= findExistentialSelfReferences (existentialSig , paramType,
3836
+ TypePosition::Invariant);
3833
3837
}
3834
3838
}
3835
3839
}
@@ -3849,29 +3853,45 @@ static SelfReferenceInfo findProtocolSelfReferences(const ProtocolDecl *proto,
3849
3853
if (auto *comp = constraint->getAs <ProtocolCompositionType>()) {
3850
3854
// 'Self' may be referenced only in a superclass component.
3851
3855
if (const auto superclass = comp->getSuperclass ()) {
3852
- return findProtocolSelfReferences (proto, superclass, position);
3856
+ return findExistentialSelfReferences (existentialSig, superclass,
3857
+ position);
3853
3858
}
3854
3859
3855
3860
return SelfReferenceInfo ();
3856
3861
}
3857
3862
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
+
3858
3872
// A direct reference to 'Self'.
3859
- if (proto-> getSelfInterfaceType ()-> isEqual (type))
3873
+ if (selfTy-> isEqual (type)) {
3860
3874
return SelfReferenceInfo::forSelfRef (position);
3875
+ }
3861
3876
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 ();
3867
3881
}
3868
3882
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);
3870
3889
}
3871
3890
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
+
3875
3895
// Types never refer to 'Self'.
3876
3896
if (isa<TypeDecl>(this ))
3877
3897
return SelfReferenceInfo ();
@@ -3882,6 +3902,8 @@ SelfReferenceInfo ValueDecl::findProtocolSelfReferences(
3882
3902
if (type->hasError ())
3883
3903
return SelfReferenceInfo ();
3884
3904
3905
+ const auto sig = getASTContext ().getOpenedArchetypeSignature (baseTy);
3906
+
3885
3907
if (isa<AbstractFunctionDecl>(this ) || isa<SubscriptDecl>(this )) {
3886
3908
// For a method, skip the 'self' parameter.
3887
3909
if (isa<AbstractFunctionDecl>(this ))
@@ -3891,12 +3913,12 @@ SelfReferenceInfo ValueDecl::findProtocolSelfReferences(
3891
3913
for (auto param : type->castTo <AnyFunctionType>()->getParams ()) {
3892
3914
// inout parameters are invariant.
3893
3915
if (param.isInOut ()) {
3894
- inputInfo |= ::findProtocolSelfReferences (proto , param.getPlainType (),
3895
- TypePosition::Invariant);
3916
+ inputInfo |= ::findExistentialSelfReferences (sig , param.getPlainType (),
3917
+ TypePosition::Invariant);
3896
3918
continue ;
3897
3919
}
3898
- inputInfo |= ::findProtocolSelfReferences (proto, param. getParameterType (),
3899
- TypePosition::Contravariant);
3920
+ inputInfo |= ::findExistentialSelfReferences (
3921
+ sig, param. getParameterType (), TypePosition::Contravariant);
3900
3922
}
3901
3923
3902
3924
// A covariant Self result inside a parameter will not be bona fide.
@@ -3913,8 +3935,8 @@ SelfReferenceInfo ValueDecl::findProtocolSelfReferences(
3913
3935
inputInfo.selfRef = TypePosition::Invariant;
3914
3936
}
3915
3937
3916
- auto resultInfo = ::findProtocolSelfReferences (
3917
- proto , type->castTo <AnyFunctionType>()->getResult (),
3938
+ auto resultInfo = ::findExistentialSelfReferences (
3939
+ sig , type->castTo <AnyFunctionType>()->getResult (),
3918
3940
TypePosition::Covariant);
3919
3941
if (resultInfo.selfRef == TypePosition::Covariant) {
3920
3942
resultInfo.hasCovariantSelfResult = true ;
@@ -3925,7 +3947,7 @@ SelfReferenceInfo ValueDecl::findProtocolSelfReferences(
3925
3947
assert (isa<VarDecl>(this ));
3926
3948
3927
3949
auto info =
3928
- ::findProtocolSelfReferences (proto , type, TypePosition::Covariant);
3950
+ ::findExistentialSelfReferences (sig , type, TypePosition::Covariant);
3929
3951
if (info.selfRef == TypePosition::Covariant) {
3930
3952
info.hasCovariantSelfResult = true ;
3931
3953
}
0 commit comments