@@ -3741,62 +3741,79 @@ class ClassDecl final : public NominalTypeDecl {
37413741 }
37423742};
37433743
3744+ // / A convenience wrapper around the \c SelfReferencePosition::Kind enum.
3745+ struct SelfReferencePosition final {
3746+ enum Kind : uint8_t { None, Covariant, Contravariant, Invariant };
37443747
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;
37523750
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+ }
37563764 }
37573765
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; }
37633767
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+ };
37693770
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;
37743780
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);
37783785 }
37793786
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);
37823791 }
37833792
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+ }
37893801 return *this ;
37903802 }
37913803
3792- operator bool () const {
3793- return result || parameter || requirement || other ;
3804+ explicit operator bool () const {
3805+ return hasCovariantSelfResult || selfRef || assocTypeRef ;
37943806 }
37953807
3808+ SelfReferenceInfo ()
3809+ : hasCovariantSelfResult(false ), selfRef(Position::None),
3810+ assocTypeRef (Position::None) {}
3811+
37963812private:
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) {}
38003817};
38013818
38023819// / The set of known protocols for which derived conformances are supported.
@@ -3978,15 +3995,12 @@ class ProtocolDecl final : public NominalTypeDecl {
39783995
39793996 // / Find direct Self references within the given requirement.
39803997 // /
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 ;
39904004
39914005 // / Determine whether we are allowed to refer to an existential type
39924006 // / conforming to this protocol. This is only permitted if the type of
0 commit comments