@@ -4699,148 +4699,172 @@ bool ProtocolDecl::existentialConformsToSelf() const {
46994699}
47004700
47014701// / 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
47034705findProtocolSelfReferences (const ProtocolDecl *proto, Type type,
4704- bool skipAssocTypes ) {
4706+ SelfReferencePosition position ) {
47054707 // Tuples preserve variance.
47064708 if (auto tuple = type->getAs <TupleType>()) {
4707- auto kind = SelfReferenceKind::None ();
4709+ auto info = SelfReferenceInfo ();
47084710 for (auto &elt : tuple->getElements ()) {
4709- kind |= findProtocolSelfReferences (proto, elt.getType (), skipAssocTypes );
4711+ info |= findProtocolSelfReferences (proto, elt.getType (), position );
47104712 }
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;
47124718 }
47134719
47144720 // Function preserve variance in the result type, and flip variance in
47154721 // the parameter type.
47164722 if (auto funcTy = type->getAs <AnyFunctionType>()) {
4717- auto inputKind = SelfReferenceKind::None ();
4723+ auto inputInfo = SelfReferenceInfo ();
47184724 for (auto param : funcTy->getParams ()) {
47194725 // inout parameters are invariant.
47204726 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 ;
47254730 }
4726- inputKind |= findProtocolSelfReferences (proto, param.getParameterType (),
4727- skipAssocTypes );
4731+ inputInfo |= findProtocolSelfReferences (proto, param.getParameterType (),
4732+ position. flipped () );
47284733 }
4729- auto resultKind = findProtocolSelfReferences (proto, funcTy->getResult (),
4730- skipAssocTypes);
47314734
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;
47354744 }
47364745
47374746 // Metatypes preserve variance.
47384747 if (auto metaTy = type->getAs <MetatypeType>()) {
47394748 return findProtocolSelfReferences (proto, metaTy->getInstanceType (),
4740- skipAssocTypes );
4749+ position );
47414750 }
47424751
47434752 // Optionals preserve variance.
47444753 if (auto optType = type->getOptionalObjectType ()) {
4745- return findProtocolSelfReferences (proto, optType,
4746- skipAssocTypes);
4754+ return findProtocolSelfReferences (proto, optType, position);
47474755 }
47484756
47494757 // DynamicSelfType preserves variance.
47504758 // FIXME: This shouldn't ever appear in protocol requirement
47514759 // signatures.
47524760 if (auto selfType = type->getAs <DynamicSelfType>()) {
4753- return findProtocolSelfReferences (proto, selfType->getSelfType (),
4754- skipAssocTypes);
4761+ return findProtocolSelfReferences (proto, selfType->getSelfType (), position);
47554762 }
47564763
47574764 // Bound generic types are invariant.
47584765 if (auto boundGenericType = type->getAs <BoundGenericType>()) {
4766+ auto info = SelfReferenceInfo ();
47594767 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);
47644770 }
4771+
4772+ return info;
47654773 }
47664774
4767- // A direct reference to 'Self' is covariant .
4775+ // A direct reference to 'Self'.
47684776 if (proto->getSelfInterfaceType ()->isEqual (type))
4769- return SelfReferenceKind::Result ( );
4777+ return SelfReferenceInfo::forSelfRef (position );
47704778
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>()) {
47734781 type = type->getRootGenericParam ();
47744782 if (proto->getSelfInterfaceType ()->isEqual (type))
4775- return SelfReferenceKind::Other ( );
4783+ return SelfReferenceInfo::forAssocTypeRef (position );
47764784 }
47774785
4778- return SelfReferenceKind::None ();
4786+ return SelfReferenceInfo ();
47794787}
47804788
47814789// / 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 {
47864792 // Types never refer to 'Self'.
47874793 if (isa<TypeDecl>(value))
4788- return SelfReferenceKind::None ();
4794+ return SelfReferenceInfo ();
47894795
47904796 auto type = value->getInterfaceType ();
47914797
47924798 // Skip invalid declarations.
47934799 if (type->hasError ())
4794- return SelfReferenceKind::None ();
4800+ return SelfReferenceInfo ();
47954801
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 ();
47994806
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 ;
48144814 }
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 ;
48154821
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;
48184831 }
48194832
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;
48224841 } else {
4823- assert (isa<AbstractStorageDecl >(value));
4842+ assert (isa<VarDecl >(value));
48244843
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;
48274851 }
48284852
4829- return SelfReferenceKind::None ();
4853+ return SelfReferenceInfo ();
48304854}
48314855
48324856bool 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 ) {
48394862 return false ;
4863+ }
48404864
48414865 // FIXME: Appropriately diagnose assignments instead.
48424866 if (auto *const storageDecl = dyn_cast<AbstractStorageDecl>(decl)) {
4843- if (selfKind. result && storageDecl->supportsMutation ())
4867+ if (info. hasCovariantSelfResult && storageDecl->supportsMutation ())
48444868 return false ;
48454869 }
48464870
0 commit comments