@@ -29,13 +29,10 @@ using namespace swift;
29
29
30
30
GenericParameterReferenceInfo &
31
31
GenericParameterReferenceInfo::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
+
39
36
return *this ;
40
37
}
41
38
@@ -296,9 +293,9 @@ findGenericParameterReferencesRec(CanGenericSignature genericSig,
296
293
// A direct reference to 'Self'.
297
294
if (type->is <GenericTypeParamType>()) {
298
295
if (position == TypePosition::Covariant && canBeCovariantResult)
299
- return GenericParameterReferenceInfo::forCovariantResult ();
296
+ return GenericParameterReferenceInfo::forCovariantGenericParamResult ();
300
297
301
- return GenericParameterReferenceInfo::forSelfRef (position);
298
+ return GenericParameterReferenceInfo::forDirectRef (position);
302
299
}
303
300
304
301
if (origParam != openedParam) {
@@ -332,7 +329,7 @@ findGenericParameterReferencesRec(CanGenericSignature genericSig,
332
329
}
333
330
334
331
// A reference to an associated type rooted on 'Self'.
335
- return GenericParameterReferenceInfo::forAssocTypeRef (position);
332
+ return GenericParameterReferenceInfo::forDependentMemberTypeRef (position);
336
333
}
337
334
338
335
GenericParameterReferenceInfo
@@ -393,7 +390,7 @@ bool HasSelfOrAssociatedTypeRequirementsRequest::evaluate(
393
390
// For value members, look at their type signatures.
394
391
if (auto valueMember = dyn_cast<ValueDecl>(member)) {
395
392
const auto info = findExistentialSelfReferences (valueMember);
396
- if (info.selfRef > TypePosition::Covariant || info.assocTypeRef ) {
393
+ if (info.hasNonCovariantRef () || info.hasDependentMemberTypeRef () ) {
397
394
return true ;
398
395
}
399
396
}
@@ -516,39 +513,81 @@ static bool doesMemberHaveUnfulfillableConstraintsWithExistentialBase(
516
513
return false ;
517
514
}
518
515
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
+ }
521
522
522
523
auto &ctx = member->getASTContext ();
523
524
auto existentialSig = ctx.getOpenedExistentialSignature (baseTy);
524
525
525
- auto *dc = member->getDeclContext ();
526
- ASSERT (dc->getSelfProtocolDecl ());
527
-
528
526
auto origParam = dc->getSelfInterfaceType ()->castTo <GenericTypeParamType>();
529
527
auto openedParam = existentialSig.SelfType ->castTo <GenericTypeParamType>();
530
528
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.
531
532
auto info = findGenericParameterReferences (
532
533
member, existentialSig.OpenedSig , origParam, openedParam,
533
534
std::nullopt);
534
535
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
+ }
539
569
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
+ }
544
577
}
545
578
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.
546
585
if (doesMemberHaveUnfulfillableConstraintsWithExistentialBase (existentialSig,
547
586
member)) {
548
- return false ;
587
+ return ExistentialMemberAccessLimitation::Unsupported ;
549
588
}
550
589
551
- return true ;
590
+ return result ;
552
591
}
553
592
554
593
std::optional<std::tuple<GenericTypeParamType *, TypeVariableType *,
@@ -686,8 +725,7 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
686
725
callee, existentialSig.OpenedSig , genericParam,
687
726
existentialSig.SelfType ->castTo <GenericTypeParamType>(),
688
727
/* skipParamIdx=*/ paramIdx);
689
- if (referenceInfo.selfRef > TypePosition::Covariant ||
690
- referenceInfo.assocTypeRef > TypePosition::Covariant)
728
+ if (referenceInfo.hasNonCovariantRef ())
691
729
return std::nullopt;
692
730
693
731
return std::make_tuple (genericParam, paramTypeVar, argTy, adjustments);
@@ -898,4 +936,4 @@ Type swift::typeEraseOpenedArchetypesFromEnvironment(
898
936
899
937
return Type ();
900
938
});
901
- }
939
+ }
0 commit comments