@@ -4699,148 +4699,172 @@ bool ProtocolDecl::existentialConformsToSelf() const {
4699
4699
}
4700
4700
4701
4701
// / Classify usages of Self in the given type.
4702
- static SelfReferenceKind
4702
+ // /
4703
+ // / \param position The position we are currently at, in terms of variance.
4704
+ static SelfReferenceInfo
4703
4705
findProtocolSelfReferences (const ProtocolDecl *proto, Type type,
4704
- bool skipAssocTypes ) {
4706
+ SelfReferencePosition position ) {
4705
4707
// Tuples preserve variance.
4706
4708
if (auto tuple = type->getAs <TupleType>()) {
4707
- auto kind = SelfReferenceKind::None ();
4709
+ auto info = SelfReferenceInfo ();
4708
4710
for (auto &elt : tuple->getElements ()) {
4709
- kind |= findProtocolSelfReferences (proto, elt.getType (), skipAssocTypes );
4711
+ info |= findProtocolSelfReferences (proto, elt.getType (), position );
4710
4712
}
4711
- return kind;
4713
+
4714
+ // A covariant Self result inside a tuple will not be bona fide.
4715
+ info.hasCovariantSelfResult = false ;
4716
+
4717
+ return info;
4712
4718
}
4713
4719
4714
4720
// Function preserve variance in the result type, and flip variance in
4715
4721
// the parameter type.
4716
4722
if (auto funcTy = type->getAs <AnyFunctionType>()) {
4717
- auto inputKind = SelfReferenceKind::None ();
4723
+ auto inputInfo = SelfReferenceInfo ();
4718
4724
for (auto param : funcTy->getParams ()) {
4719
4725
// inout parameters are invariant.
4720
4726
if (param.isInOut ()) {
4721
- if (findProtocolSelfReferences (proto, param.getPlainType (),
4722
- skipAssocTypes)) {
4723
- return SelfReferenceKind::Other ();
4724
- }
4727
+ inputInfo |= findProtocolSelfReferences (
4728
+ proto, param.getPlainType (), SelfReferencePosition::Invariant);
4729
+ continue ;
4725
4730
}
4726
- inputKind |= findProtocolSelfReferences (proto, param.getParameterType (),
4727
- skipAssocTypes );
4731
+ inputInfo |= findProtocolSelfReferences (proto, param.getParameterType (),
4732
+ position. flipped () );
4728
4733
}
4729
- auto resultKind = findProtocolSelfReferences (proto, funcTy->getResult (),
4730
- skipAssocTypes);
4731
4734
4732
- auto kind = inputKind.flip ();
4733
- kind |= resultKind;
4734
- return kind;
4735
+ // A covariant Self result inside a parameter will not be bona fide.
4736
+ inputInfo.hasCovariantSelfResult = false ;
4737
+
4738
+ auto resultInfo =
4739
+ findProtocolSelfReferences (proto, funcTy->getResult (), position);
4740
+ if (resultInfo.selfRef == SelfReferencePosition::Covariant) {
4741
+ resultInfo.hasCovariantSelfResult = true ;
4742
+ }
4743
+ return inputInfo |= resultInfo;
4735
4744
}
4736
4745
4737
4746
// Metatypes preserve variance.
4738
4747
if (auto metaTy = type->getAs <MetatypeType>()) {
4739
4748
return findProtocolSelfReferences (proto, metaTy->getInstanceType (),
4740
- skipAssocTypes );
4749
+ position );
4741
4750
}
4742
4751
4743
4752
// Optionals preserve variance.
4744
4753
if (auto optType = type->getOptionalObjectType ()) {
4745
- return findProtocolSelfReferences (proto, optType,
4746
- skipAssocTypes);
4754
+ return findProtocolSelfReferences (proto, optType, position);
4747
4755
}
4748
4756
4749
4757
// DynamicSelfType preserves variance.
4750
4758
// FIXME: This shouldn't ever appear in protocol requirement
4751
4759
// signatures.
4752
4760
if (auto selfType = type->getAs <DynamicSelfType>()) {
4753
- return findProtocolSelfReferences (proto, selfType->getSelfType (),
4754
- skipAssocTypes);
4761
+ return findProtocolSelfReferences (proto, selfType->getSelfType (), position);
4755
4762
}
4756
4763
4757
4764
// Bound generic types are invariant.
4758
4765
if (auto boundGenericType = type->getAs <BoundGenericType>()) {
4766
+ auto info = SelfReferenceInfo ();
4759
4767
for (auto paramType : boundGenericType->getGenericArgs ()) {
4760
- if (findProtocolSelfReferences (proto, paramType,
4761
- skipAssocTypes)) {
4762
- return SelfReferenceKind::Other ();
4763
- }
4768
+ info |= findProtocolSelfReferences (proto, paramType,
4769
+ SelfReferencePosition::Invariant);
4764
4770
}
4771
+
4772
+ return info;
4765
4773
}
4766
4774
4767
- // A direct reference to 'Self' is covariant .
4775
+ // A direct reference to 'Self'.
4768
4776
if (proto->getSelfInterfaceType ()->isEqual (type))
4769
- return SelfReferenceKind::Result ( );
4777
+ return SelfReferenceInfo::forSelfRef (position );
4770
4778
4771
- // Special handling for associated types .
4772
- if (!skipAssocTypes && type->is <DependentMemberType>()) {
4779
+ // A reference to an associated type rooted on 'Self' .
4780
+ if (type->is <DependentMemberType>()) {
4773
4781
type = type->getRootGenericParam ();
4774
4782
if (proto->getSelfInterfaceType ()->isEqual (type))
4775
- return SelfReferenceKind::Other ( );
4783
+ return SelfReferenceInfo::forAssocTypeRef (position );
4776
4784
}
4777
4785
4778
- return SelfReferenceKind::None ();
4786
+ return SelfReferenceInfo ();
4779
4787
}
4780
4788
4781
4789
// / Find Self references within the given requirement.
4782
- SelfReferenceKind
4783
- ProtocolDecl::findProtocolSelfReferences (const ValueDecl *value,
4784
- bool allowCovariantParameters,
4785
- bool skipAssocTypes) const {
4790
+ SelfReferenceInfo ProtocolDecl::findProtocolSelfReferences (
4791
+ const ValueDecl *value, bool treatNonResultCovariantSelfAsInvariant) const {
4786
4792
// Types never refer to 'Self'.
4787
4793
if (isa<TypeDecl>(value))
4788
- return SelfReferenceKind::None ();
4794
+ return SelfReferenceInfo ();
4789
4795
4790
4796
auto type = value->getInterfaceType ();
4791
4797
4792
4798
// Skip invalid declarations.
4793
4799
if (type->hasError ())
4794
- return SelfReferenceKind::None ();
4800
+ return SelfReferenceInfo ();
4795
4801
4796
- if (auto func = dyn_cast<AbstractFunctionDecl>(value)) {
4797
- // Skip the 'self' parameter.
4798
- type = type->castTo <AnyFunctionType>()->getResult ();
4802
+ if (isa<AbstractFunctionDecl>(value) || isa<SubscriptDecl>(value)) {
4803
+ // For a method, skip the 'self' parameter.
4804
+ if (isa<AbstractFunctionDecl>(value))
4805
+ type = type->castTo <AnyFunctionType>()->getResult ();
4799
4806
4800
- // Methods of non-final classes can only contain a covariant 'Self'
4801
- // as a function result type.
4802
- if (!allowCovariantParameters) {
4803
- auto inputKind = SelfReferenceKind::None ();
4804
- for (auto param : type->castTo <AnyFunctionType>()->getParams ()) {
4805
- // inout parameters are invariant.
4806
- if (param.isInOut ()) {
4807
- if (::findProtocolSelfReferences (this , param.getPlainType (),
4808
- skipAssocTypes)) {
4809
- return SelfReferenceKind::Other ();
4810
- }
4811
- }
4812
- inputKind |= ::findProtocolSelfReferences (this , param.getParameterType (),
4813
- skipAssocTypes);
4807
+ auto inputInfo = SelfReferenceInfo ();
4808
+ for (auto param : type->castTo <AnyFunctionType>()->getParams ()) {
4809
+ // inout parameters are invariant.
4810
+ if (param.isInOut ()) {
4811
+ inputInfo |= ::findProtocolSelfReferences (
4812
+ this , param.getPlainType (), SelfReferencePosition::Invariant);
4813
+ continue ;
4814
4814
}
4815
+ inputInfo |= ::findProtocolSelfReferences (
4816
+ this , param.getParameterType (), SelfReferencePosition::Contravariant);
4817
+ }
4818
+
4819
+ // A covariant Self result inside a parameter will not be bona fide.
4820
+ inputInfo.hasCovariantSelfResult = false ;
4815
4821
4816
- if (inputKind.parameter )
4817
- return SelfReferenceKind::Other ();
4822
+ // FIXME: Rather than having a special flag for the is-inheritable check,
4823
+ // ensure non-result covariant Self is always diagnosed during type
4824
+ // resolution.
4825
+ //
4826
+ // Methods of non-final classes can only contain a covariant 'Self'
4827
+ // as their result type.
4828
+ if (treatNonResultCovariantSelfAsInvariant &&
4829
+ inputInfo.selfRef == SelfReferencePosition::Covariant) {
4830
+ inputInfo.selfRef = SelfReferencePosition::Invariant;
4818
4831
}
4819
4832
4820
- return ::findProtocolSelfReferences (this , type,
4821
- skipAssocTypes);
4833
+ auto resultInfo = ::findProtocolSelfReferences (
4834
+ this , type->castTo <AnyFunctionType>()->getResult (),
4835
+ SelfReferencePosition::Covariant);
4836
+ if (resultInfo.selfRef == SelfReferencePosition::Covariant) {
4837
+ resultInfo.hasCovariantSelfResult = true ;
4838
+ }
4839
+
4840
+ return inputInfo |= resultInfo;
4822
4841
} else {
4823
- assert (isa<AbstractStorageDecl >(value));
4842
+ assert (isa<VarDecl >(value));
4824
4843
4825
- return ::findProtocolSelfReferences (this , type,
4826
- skipAssocTypes);
4844
+ auto info = ::findProtocolSelfReferences (this , type,
4845
+ SelfReferencePosition::Covariant);
4846
+ if (info.selfRef == SelfReferencePosition::Covariant) {
4847
+ info.hasCovariantSelfResult = true ;
4848
+ }
4849
+
4850
+ return info;
4827
4851
}
4828
4852
4829
- return SelfReferenceKind::None ();
4853
+ return SelfReferenceInfo ();
4830
4854
}
4831
4855
4832
4856
bool ProtocolDecl::isAvailableInExistential (const ValueDecl *decl) const {
4833
- // If the member type uses 'Self' in non-covariant position,
4834
- // we cannot use the existential type.
4835
- auto selfKind = findProtocolSelfReferences (decl,
4836
- /* allowCovariantParameters=*/ true ,
4837
- /* skipAssocTypes=*/ false );
4838
- if (selfKind.parameter || selfKind.other )
4857
+ // If the member type references 'Self' in non-covariant position, or an
4858
+ // associated type in any position, we cannot use the existential type.
4859
+ const auto info = findProtocolSelfReferences (
4860
+ decl, /* treatNonResultCovariantSelfAsInvariant=*/ false );
4861
+ if (info.selfRef > SelfReferencePosition::Covariant || info.assocTypeRef ) {
4839
4862
return false ;
4863
+ }
4840
4864
4841
4865
// FIXME: Appropriately diagnose assignments instead.
4842
4866
if (auto *const storageDecl = dyn_cast<AbstractStorageDecl>(decl)) {
4843
- if (selfKind. result && storageDecl->supportsMutation ())
4867
+ if (info. hasCovariantSelfResult && storageDecl->supportsMutation ())
4844
4868
return false ;
4845
4869
}
4846
4870
0 commit comments