@@ -3741,62 +3741,79 @@ class ClassDecl final : public NominalTypeDecl {
3741
3741
}
3742
3742
};
3743
3743
3744
+ // / A convenience wrapper around the \c SelfReferencePosition::Kind enum.
3745
+ struct SelfReferencePosition final {
3746
+ enum Kind : uint8_t { None, Covariant, Contravariant, Invariant };
3744
3747
3745
- // / Describes whether a requirement refers to 'Self', for use in the
3746
- // / is-inheritable and is-available-existential checks.
3747
- struct SelfReferenceKind {
3748
- bool result;
3749
- bool parameter;
3750
- bool requirement;
3751
- bool other;
3748
+ private:
3749
+ Kind kind;
3752
3750
3753
- // / The type does not refer to 'Self' at all.
3754
- static SelfReferenceKind None () {
3755
- return SelfReferenceKind (false , false , false , false );
3751
+ public:
3752
+ SelfReferencePosition (Kind kind) : kind(kind) {}
3753
+
3754
+ SelfReferencePosition flipped () const {
3755
+ switch (kind) {
3756
+ case None:
3757
+ case Invariant:
3758
+ return *this ;
3759
+ case Covariant:
3760
+ return Contravariant;
3761
+ case Contravariant:
3762
+ return Covariant;
3763
+ }
3756
3764
}
3757
3765
3758
- // / The type refers to 'Self', but only as the type of a property or
3759
- // / the result type of a method/subscript.
3760
- static SelfReferenceKind Result () {
3761
- return SelfReferenceKind (true , false , false , false );
3762
- }
3766
+ explicit operator bool () const { return kind > None; }
3763
3767
3764
- // / The type refers to 'Self', but only as the parameter type
3765
- // / of a method/subscript.
3766
- static SelfReferenceKind Parameter () {
3767
- return SelfReferenceKind (false , true , false , false );
3768
- }
3768
+ operator Kind () const { return kind; }
3769
+ };
3769
3770
3770
- // / The type refers to 'Self' within a same-type requiement.
3771
- static SelfReferenceKind Requirement () {
3772
- return SelfReferenceKind (false , false , true , false );
3773
- }
3771
+ // / Describes the least favorable positions at which a requirement refers
3772
+ // / to 'Self' in terms of variance, for use in the is-inheritable and
3773
+ // / is-available-existential checks.
3774
+ struct SelfReferenceInfo final {
3775
+ using Position = SelfReferencePosition;
3776
+
3777
+ bool hasCovariantSelfResult;
3778
+ Position selfRef;
3779
+ Position assocTypeRef;
3774
3780
3775
- // / The type refers to 'Self' in a position that is invariant.
3776
- static SelfReferenceKind Other () {
3777
- return SelfReferenceKind (false , false , false , true );
3781
+ // / A reference to 'Self'.
3782
+ static SelfReferenceInfo forSelfRef (Position position) {
3783
+ assert (position);
3784
+ return SelfReferenceInfo (false , position, Position::None);
3778
3785
}
3779
3786
3780
- SelfReferenceKind flip () const {
3781
- return SelfReferenceKind (parameter, result, requirement, other);
3787
+ // / A reference to 'Self' through an associated type.
3788
+ static SelfReferenceInfo forAssocTypeRef (Position position) {
3789
+ assert (position);
3790
+ return SelfReferenceInfo (false , Position::None, position);
3782
3791
}
3783
3792
3784
- SelfReferenceKind operator |=(SelfReferenceKind kind) {
3785
- result |= kind.result ;
3786
- requirement |= kind.requirement ;
3787
- parameter |= kind.parameter ;
3788
- other |= kind.other ;
3793
+ SelfReferenceInfo operator |=(const SelfReferenceInfo &pos) {
3794
+ hasCovariantSelfResult |= pos.hasCovariantSelfResult ;
3795
+ if (pos.selfRef > selfRef) {
3796
+ selfRef = pos.selfRef ;
3797
+ }
3798
+ if (pos.assocTypeRef > assocTypeRef) {
3799
+ assocTypeRef = pos.assocTypeRef ;
3800
+ }
3789
3801
return *this ;
3790
3802
}
3791
3803
3792
- operator bool () const {
3793
- return result || parameter || requirement || other ;
3804
+ explicit operator bool () const {
3805
+ return hasCovariantSelfResult || selfRef || assocTypeRef ;
3794
3806
}
3795
3807
3808
+ SelfReferenceInfo ()
3809
+ : hasCovariantSelfResult(false ), selfRef(Position::None),
3810
+ assocTypeRef (Position::None) {}
3811
+
3796
3812
private:
3797
- SelfReferenceKind (bool result, bool parameter, bool requirement, bool other)
3798
- : result(result), parameter(parameter), requirement(requirement),
3799
- other (other) { }
3813
+ SelfReferenceInfo (bool hasCovariantSelfResult, Position selfRef,
3814
+ Position assocTypeRef)
3815
+ : hasCovariantSelfResult(hasCovariantSelfResult), selfRef(selfRef),
3816
+ assocTypeRef(assocTypeRef) {}
3800
3817
};
3801
3818
3802
3819
// / The set of known protocols for which derived conformances are supported.
@@ -3978,15 +3995,12 @@ class ProtocolDecl final : public NominalTypeDecl {
3978
3995
3979
3996
// / Find direct Self references within the given requirement.
3980
3997
// /
3981
- // / \param allowCovariantParameters If true, 'Self' is assumed to be
3982
- // / covariant anywhere; otherwise, only in the return type of the top-level
3983
- // / function type.
3984
- // /
3985
- // / \param skipAssocTypes If true, associated types of 'Self' are ignored;
3986
- // / otherwise, they count as an 'other' usage of 'Self'.
3987
- SelfReferenceKind findProtocolSelfReferences (const ValueDecl *decl,
3988
- bool allowCovariantParameters,
3989
- bool skipAssocTypes) const ;
3998
+ // / \param treatNonResultCovariantSelfAsInvariant If true, 'Self' is only
3999
+ // / assumed to be covariant in a top-level non-function type, or in the
4000
+ // / eventual result type of a top-level function type.
4001
+ SelfReferenceInfo
4002
+ findProtocolSelfReferences (const ValueDecl *decl,
4003
+ bool treatNonResultCovariantSelfAsInvariant) const ;
3990
4004
3991
4005
// / Determine whether we are allowed to refer to an existential type
3992
4006
// / conforming to this protocol. This is only permitted if the type of
0 commit comments