@@ -29,13 +29,10 @@ using namespace swift;
2929
3030GenericParameterReferenceInfo &
3131GenericParameterReferenceInfo::operator |=(const GenericParameterReferenceInfo &other) {
32- hasCovariantSelfResult |= other.hasCovariantSelfResult ;
33- if (other.selfRef > selfRef) {
34- selfRef = other.selfRef ;
35- }
36- if (other.assocTypeRef > assocTypeRef) {
37- assocTypeRef = other.assocTypeRef ;
38- }
32+ DirectRefs |= other.DirectRefs ;
33+ DepMemberTyRefs |= other.DepMemberTyRefs ;
34+ HasCovariantGenericParamResult |= other.HasCovariantGenericParamResult ;
35+
3936 return *this ;
4037}
4138
@@ -296,9 +293,9 @@ findGenericParameterReferencesRec(CanGenericSignature genericSig,
296293 // A direct reference to 'Self'.
297294 if (type->is <GenericTypeParamType>()) {
298295 if (position == TypePosition::Covariant && canBeCovariantResult)
299- return GenericParameterReferenceInfo::forCovariantResult ();
296+ return GenericParameterReferenceInfo::forCovariantGenericParamResult ();
300297
301- return GenericParameterReferenceInfo::forSelfRef (position);
298+ return GenericParameterReferenceInfo::forDirectRef (position);
302299 }
303300
304301 if (origParam != openedParam) {
@@ -332,7 +329,7 @@ findGenericParameterReferencesRec(CanGenericSignature genericSig,
332329 }
333330
334331 // A reference to an associated type rooted on 'Self'.
335- return GenericParameterReferenceInfo::forAssocTypeRef (position);
332+ return GenericParameterReferenceInfo::forDependentMemberTypeRef (position);
336333}
337334
338335GenericParameterReferenceInfo
@@ -393,7 +390,7 @@ bool HasSelfOrAssociatedTypeRequirementsRequest::evaluate(
393390 // For value members, look at their type signatures.
394391 if (auto valueMember = dyn_cast<ValueDecl>(member)) {
395392 const auto info = findExistentialSelfReferences (valueMember);
396- if (info.selfRef > TypePosition::Covariant || info.assocTypeRef ) {
393+ if (info.hasNonCovariantRef () || info.hasDependentMemberTypeRef () ) {
397394 return true ;
398395 }
399396 }
@@ -516,39 +513,81 @@ static bool doesMemberHaveUnfulfillableConstraintsWithExistentialBase(
516513 return false ;
517514}
518515
519- bool swift::isMemberAvailableOnExistential (
520- Type baseTy, const ValueDecl *member) {
516+ ExistentialMemberAccessLimitation
517+ swift::isMemberAvailableOnExistential (Type baseTy, const ValueDecl *member) {
518+ auto *dc = member->getDeclContext ();
519+ if (!dc->getSelfProtocolDecl ()) {
520+ return ExistentialMemberAccessLimitation::None;
521+ }
521522
522523 auto &ctx = member->getASTContext ();
523524 auto existentialSig = ctx.getOpenedExistentialSignature (baseTy);
524525
525- auto *dc = member->getDeclContext ();
526- ASSERT (dc->getSelfProtocolDecl ());
527-
528526 auto origParam = dc->getSelfInterfaceType ()->castTo <GenericTypeParamType>();
529527 auto openedParam = existentialSig.SelfType ->castTo <GenericTypeParamType>();
530528
529+ // An accessor or non-storage member is not available if its interface type
530+ // contains a non-covariant reference to a 'Self'-rooted type parameter in the
531+ // context of the base type's existential signature.
531532 auto info = findGenericParameterReferences (
532533 member, existentialSig.OpenedSig , origParam, openedParam,
533534 std::nullopt );
534535
535- if (info.selfRef > TypePosition::Covariant ||
536- info.assocTypeRef > TypePosition::Covariant) {
537- return false ;
538- }
536+ auto result = ExistentialMemberAccessLimitation::None;
537+ if (!info) {
538+ // Nothing to do.
539+ } else if (info.hasRef (TypePosition::Invariant)) {
540+ // An invariant reference is decisive.
541+ result = ExistentialMemberAccessLimitation::Unsupported;
542+ } else if (isa<AbstractFunctionDecl>(member)) {
543+ // Anything non-covariant is decisive for functions.
544+ if (info.hasRef (TypePosition::Contravariant)) {
545+ result = ExistentialMemberAccessLimitation::Unsupported;
546+ }
547+ } else {
548+ const auto isGetterUnavailable = info.hasRef (TypePosition::Contravariant);
549+ auto isSetterUnavailable = true ;
550+
551+ if (isa<VarDecl>(member)) {
552+ // For properties, the setter is unavailable if the interface type has a
553+ // covariant reference, which becomes contravariant is the setter.
554+ isSetterUnavailable = info.hasRef (TypePosition::Covariant);
555+ } else {
556+ // For subscripts specifically, we must scan the setter directly because
557+ // whether a covariant reference in the interface type becomes
558+ // contravariant in the setter depends on the location of the reference
559+ // (in the indices or the result type).
560+ auto *setter =
561+ cast<SubscriptDecl>(member)->getAccessor (AccessorKind::Set);
562+ const auto setterInfo = setter ? findGenericParameterReferences (
563+ setter, existentialSig.OpenedSig ,
564+ origParam, openedParam, std::nullopt )
565+ : GenericParameterReferenceInfo ();
566+
567+ isSetterUnavailable = setterInfo.hasRef (TypePosition::Contravariant);
568+ }
539569
540- // FIXME: Appropriately diagnose assignments instead.
541- if (auto *const storageDecl = dyn_cast<AbstractStorageDecl>(member)) {
542- if (info.hasCovariantSelfResult && storageDecl->supportsMutation ())
543- return false ;
570+ if (isGetterUnavailable && isSetterUnavailable) {
571+ result = ExistentialMemberAccessLimitation::Unsupported;
572+ } else if (isGetterUnavailable) {
573+ result = ExistentialMemberAccessLimitation::WriteOnly;
574+ } else if (isSetterUnavailable) {
575+ result = ExistentialMemberAccessLimitation::ReadOnly;
576+ }
544577 }
545578
579+ // If the member access is not supported whatsoever, we are done.
580+ if (result == ExistentialMemberAccessLimitation::Unsupported)
581+ return result;
582+
583+ // Before proceeding with the result, see if we find a generic requirement
584+ // that cannot be satisfied; if we do, the member is unavailable after all.
546585 if (doesMemberHaveUnfulfillableConstraintsWithExistentialBase (existentialSig,
547586 member)) {
548- return false ;
587+ return ExistentialMemberAccessLimitation::Unsupported ;
549588 }
550589
551- return true ;
590+ return result ;
552591}
553592
554593std::optional<std::tuple<GenericTypeParamType *, TypeVariableType *,
@@ -686,8 +725,7 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
686725 callee, existentialSig.OpenedSig , genericParam,
687726 existentialSig.SelfType ->castTo <GenericTypeParamType>(),
688727 /* skipParamIdx=*/ paramIdx);
689- if (referenceInfo.selfRef > TypePosition::Covariant ||
690- referenceInfo.assocTypeRef > TypePosition::Covariant)
728+ if (referenceInfo.hasNonCovariantRef ())
691729 return std::nullopt ;
692730
693731 return std::make_tuple (genericParam, paramTypeVar, argTy, adjustments);
@@ -898,4 +936,4 @@ Type swift::typeEraseOpenedArchetypesFromEnvironment(
898936
899937 return Type ();
900938 });
901- }
939+ }
0 commit comments