Skip to content

Commit 56cefdc

Browse files
committed
AST: Clean up findGenericParameterReferences()
1 parent a499bfc commit 56cefdc

File tree

6 files changed

+72
-107
lines changed

6 files changed

+72
-107
lines changed

include/swift/AST/Decl.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3337,14 +3337,7 @@ class ValueDecl : public Decl {
33373337

33383338
/// Find references to 'Self' in the type signature of this declaration in the
33393339
/// context of the given existential base type.
3340-
///
3341-
/// \param treatNonResultCovariantSelfAsInvariant When set, covariant 'Self'
3342-
/// references that are not in covariant result type position are considered
3343-
/// invariant. This position is the uncurried interface type of a declaration,
3344-
/// stripped of any optionality. For example, this is true for 'Self' in
3345-
/// 'func foo(Int) -> () -> Self?'.
3346-
GenericParameterReferenceInfo findExistentialSelfReferences(
3347-
Type baseTy, bool treatNonResultCovariantSelfAsInvariant) const;
3340+
GenericParameterReferenceInfo findExistentialSelfReferences(Type baseTy) const;
33483341
};
33493342

33503343
/// This is a common base class for declarations which declare a type.
@@ -9533,7 +9526,6 @@ class MacroExpansionDecl : public Decl, public FreestandingMacroExpansion {
95339526
GenericParameterReferenceInfo
95349527
findGenericParameterReferences(const ValueDecl *value, CanGenericSignature sig,
95359528
GenericTypeParamType *genericParam,
9536-
bool treatNonResultCovarianceAsInvariant,
95379529
std::optional<unsigned> skipParamIndex);
95389530

95399531
inline void

lib/AST/Decl.cpp

Lines changed: 64 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -4825,8 +4825,8 @@ GenericParameterReferenceInfo::operator|=(const GenericParameterReferenceInfo &o
48254825

48264826
/// Forward declaration.
48274827
static GenericParameterReferenceInfo
4828-
findGenericParameterReferences(CanGenericSignature, GenericTypeParamType *,
4829-
Type, TypePosition, bool, bool);
4828+
findGenericParameterReferencesRec(CanGenericSignature, GenericTypeParamType *,
4829+
Type, TypePosition, bool);
48304830

48314831
/// Determine whether a function type with the given result type may have
48324832
/// a covariant generic parameter type result. This is true if the result type
@@ -4848,8 +4848,7 @@ static bool canResultTypeHaveCovariantGenericParameterResult(Type resultTy) {
48484848
static GenericParameterReferenceInfo findGenericParameterReferencesInFunction(
48494849
CanGenericSignature genericSig, GenericTypeParamType *genericParam,
48504850
const AnyFunctionType *fnType, TypePosition position,
4851-
bool treatNonResultCovarianceAsInvariant, bool canBeCovariantResult,
4852-
std::optional<unsigned> skipParamIndex) {
4851+
bool canBeCovariantResult, std::optional<unsigned> skipParamIndex) {
48534852
// If there are no type parameters, we're done.
48544853
if (!isa<GenericFunctionType>(fnType) && !fnType->hasTypeParameter())
48554854
return GenericParameterReferenceInfo();
@@ -4864,10 +4863,9 @@ static GenericParameterReferenceInfo findGenericParameterReferencesInFunction(
48644863
const auto &param = params[paramIdx];
48654864
// inout types are invariant.
48664865
if (param.isInOut()) {
4867-
inputInfo |= ::findGenericParameterReferences(
4866+
inputInfo |= ::findGenericParameterReferencesRec(
48684867
genericSig, genericParam, param.getPlainType(),
4869-
TypePosition::Invariant, treatNonResultCovarianceAsInvariant,
4870-
/*canBeCovariantResult=*/false);
4868+
TypePosition::Invariant, /*canBeCovariantResult=*/false);
48714869
continue;
48724870
}
48734871

@@ -4878,19 +4876,19 @@ static GenericParameterReferenceInfo findGenericParameterReferencesInFunction(
48784876
if (skipParamIndex && paramIdx < *skipParamIndex)
48794877
paramPos = TypePosition::Invariant;
48804878

4881-
inputInfo |= ::findGenericParameterReferences(
4879+
inputInfo |= ::findGenericParameterReferencesRec(
48824880
genericSig, genericParam, param.getParameterType(), paramPos,
4883-
treatNonResultCovarianceAsInvariant, /*canBeCovariantResult=*/false);
4881+
/*canBeCovariantResult=*/false);
48844882
}
48854883

48864884
canBeCovariantResult =
48874885
// &= does not short-circuit.
48884886
canBeCovariantResult &&
48894887
canResultTypeHaveCovariantGenericParameterResult(fnType->getResult());
48904888

4891-
const auto resultInfo = ::findGenericParameterReferences(
4892-
genericSig, genericParam, fnType->getResult(), position,
4893-
treatNonResultCovarianceAsInvariant, canBeCovariantResult);
4889+
const auto resultInfo = ::findGenericParameterReferencesRec(
4890+
genericSig, genericParam, fnType->getResult(),
4891+
position, canBeCovariantResult);
48944892

48954893
return inputInfo |= resultInfo;
48964894
}
@@ -4900,12 +4898,11 @@ static GenericParameterReferenceInfo findGenericParameterReferencesInFunction(
49004898
///
49014899
/// \param position The current position in terms of variance.
49024900
static GenericParameterReferenceInfo
4903-
findGenericParameterReferences(CanGenericSignature genericSig,
4904-
GenericTypeParamType *genericParam,
4905-
Type type,
4906-
TypePosition position,
4907-
bool treatNonResultCovarianceAsInvariant,
4908-
bool canBeCovariantResult) {
4901+
findGenericParameterReferencesRec(CanGenericSignature genericSig,
4902+
GenericTypeParamType *genericParam,
4903+
Type type,
4904+
TypePosition position,
4905+
bool canBeCovariantResult) {
49094906
// If there are no type parameters, we're done.
49104907
if (!type->hasTypeParameter())
49114908
return GenericParameterReferenceInfo();
@@ -4914,9 +4911,8 @@ findGenericParameterReferences(CanGenericSignature genericSig,
49144911
if (auto tuple = type->getAs<TupleType>()) {
49154912
auto info = GenericParameterReferenceInfo();
49164913
for (auto &elt : tuple->getElements()) {
4917-
info |= findGenericParameterReferences(
4914+
info |= findGenericParameterReferencesRec(
49184915
genericSig, genericParam, elt.getType(), position,
4919-
treatNonResultCovarianceAsInvariant,
49204916
/*canBeCovariantResult=*/false);
49214917
}
49224918

@@ -4927,69 +4923,61 @@ findGenericParameterReferences(CanGenericSignature genericSig,
49274923
// the parameter type.
49284924
if (auto funcTy = type->getAs<AnyFunctionType>()) {
49294925
return findGenericParameterReferencesInFunction(
4930-
genericSig, genericParam, funcTy, position,
4931-
treatNonResultCovarianceAsInvariant, canBeCovariantResult,
4926+
genericSig, genericParam, funcTy,
4927+
position, canBeCovariantResult,
49324928
/*skipParamIndex=*/std::nullopt);
49334929
}
49344930

49354931
// Metatypes preserve variance.
49364932
if (auto metaTy = type->getAs<MetatypeType>()) {
4937-
return findGenericParameterReferences(genericSig, genericParam,
4938-
metaTy->getInstanceType(), position,
4939-
treatNonResultCovarianceAsInvariant,
4940-
canBeCovariantResult);
4933+
return findGenericParameterReferencesRec(genericSig, genericParam,
4934+
metaTy->getInstanceType(),
4935+
position, canBeCovariantResult);
49414936
}
49424937

49434938
// Optionals preserve variance.
49444939
if (auto optType = type->getOptionalObjectType()) {
4945-
return findGenericParameterReferences(
4946-
genericSig, genericParam, optType, position,
4947-
treatNonResultCovarianceAsInvariant, canBeCovariantResult);
4940+
return findGenericParameterReferencesRec(
4941+
genericSig, genericParam, optType, position, canBeCovariantResult);
49484942
}
49494943

49504944
// DynamicSelfType preserves variance.
49514945
if (auto selfType = type->getAs<DynamicSelfType>()) {
4952-
return findGenericParameterReferences(genericSig, genericParam,
4953-
selfType->getSelfType(), position,
4954-
treatNonResultCovarianceAsInvariant,
4955-
/*canBeCovariantResult=*/false);
4946+
return findGenericParameterReferencesRec(genericSig, genericParam,
4947+
selfType->getSelfType(), position,
4948+
/*canBeCovariantResult=*/false);
49564949
}
49574950

49584951
if (auto *const nominal = type->getAs<NominalOrBoundGenericNominalType>()) {
49594952
auto info = GenericParameterReferenceInfo();
49604953

49614954
// Don't forget to look in the parent.
49624955
if (const auto parent = nominal->getParent()) {
4963-
info |= findGenericParameterReferences(
4956+
info |= findGenericParameterReferencesRec(
49644957
genericSig, genericParam, parent, position,
4965-
treatNonResultCovarianceAsInvariant,
49664958
/*canBeCovariantResult=*/false);
49674959
}
49684960

49694961
// Most bound generic types are invariant.
49704962
if (auto *const bgt = type->getAs<BoundGenericType>()) {
49714963
if (bgt->isArray()) {
49724964
// Swift.Array preserves variance in its 'Value' type.
4973-
info |= findGenericParameterReferences(
4965+
info |= findGenericParameterReferencesRec(
49744966
genericSig, genericParam, bgt->getGenericArgs().front(),
4975-
position, treatNonResultCovarianceAsInvariant,
4976-
/*canBeCovariantResult=*/false);
4967+
position, /*canBeCovariantResult=*/false);
49774968
} else if (bgt->isDictionary()) {
49784969
// Swift.Dictionary preserves variance in its 'Element' type.
4979-
info |= findGenericParameterReferences(
4970+
info |= findGenericParameterReferencesRec(
49804971
genericSig, genericParam, bgt->getGenericArgs().front(),
4981-
TypePosition::Invariant, treatNonResultCovarianceAsInvariant,
4982-
/*canBeCovariantResult=*/false);
4983-
info |= findGenericParameterReferences(
4972+
TypePosition::Invariant, /*canBeCovariantResult=*/false);
4973+
info |= findGenericParameterReferencesRec(
49844974
genericSig, genericParam, bgt->getGenericArgs().back(),
4985-
position, treatNonResultCovarianceAsInvariant,
4986-
/*canBeCovariantResult=*/false);
4975+
position, /*canBeCovariantResult=*/false);
49874976
} else {
49884977
for (const auto &paramType : bgt->getGenericArgs()) {
4989-
info |= findGenericParameterReferences(
4990-
genericSig, genericParam, paramType, TypePosition::Invariant,
4991-
treatNonResultCovarianceAsInvariant,
4992-
/*canBeCovariantResult=*/false);
4978+
info |= findGenericParameterReferencesRec(
4979+
genericSig, genericParam, paramType,
4980+
TypePosition::Invariant, /*canBeCovariantResult=*/false);
49934981
}
49944982
}
49954983
}
@@ -5012,40 +5000,37 @@ findGenericParameterReferences(CanGenericSignature genericSig,
50125000
continue;
50135001

50145002
case RequirementKind::SameType:
5015-
info |= findGenericParameterReferences(
5003+
info |= findGenericParameterReferencesRec(
50165004
genericSig, genericParam, req.getFirstType(),
5017-
TypePosition::Invariant, treatNonResultCovarianceAsInvariant,
5018-
/*canBeCovariantResult=*/false);
5005+
TypePosition::Invariant, /*canBeCovariantResult=*/false);
50195006

50205007
LLVM_FALLTHROUGH;
50215008

50225009
case RequirementKind::Superclass:
5023-
info |= findGenericParameterReferences(
5010+
info |= findGenericParameterReferencesRec(
50245011
genericSig, genericParam, req.getSecondType(),
5025-
TypePosition::Invariant, treatNonResultCovarianceAsInvariant,
5026-
/*canBeCovariantResult=*/false);
5012+
TypePosition::Invariant, /*canBeCovariantResult=*/false);
50275013
break;
50285014
}
50295015
}
50305016

50315017
return info;
50325018
}
50335019

5034-
// Protocol compositions preserve variance.
50355020
if (auto *existential = type->getAs<ExistentialType>())
50365021
type = existential->getConstraintType();
5022+
5023+
// Protocol compositions are invariant.
50375024
if (auto *comp = type->getAs<ProtocolCompositionType>()) {
5038-
// 'Self' may be referenced only in an explicit superclass component.
5039-
for (const auto member : comp->getMembers()) {
5040-
if (member->getClassOrBoundGenericClass()) {
5041-
return findGenericParameterReferences(
5042-
genericSig, genericParam, member, position,
5043-
treatNonResultCovarianceAsInvariant,
5044-
/*canBeCovariantResult=*/false);
5045-
}
5025+
auto info = GenericParameterReferenceInfo();
5026+
5027+
for (auto member : comp->getMembers()) {
5028+
info |= findGenericParameterReferencesRec(
5029+
genericSig, genericParam, member,
5030+
TypePosition::Invariant, /*canBeCovariantResult=*/false);
50465031
}
50475032

5048-
return GenericParameterReferenceInfo();
5033+
return info;
50495034
}
50505035

50515036
if (!type->isTypeParameter()) {
@@ -5059,13 +5044,8 @@ findGenericParameterReferences(CanGenericSignature genericSig,
50595044

50605045
// A direct reference to 'Self'.
50615046
if (selfTy->isEqual(type)) {
5062-
if (position == TypePosition::Covariant) {
5063-
if (canBeCovariantResult) {
5064-
return GenericParameterReferenceInfo::forCovariantResult();
5065-
} else if (treatNonResultCovarianceAsInvariant) {
5066-
position = TypePosition::Invariant;
5067-
}
5068-
}
5047+
if (position == TypePosition::Covariant && canBeCovariantResult)
5048+
return GenericParameterReferenceInfo::forCovariantResult();
50695049

50705050
return GenericParameterReferenceInfo::forSelfRef(position);
50715051
}
@@ -5077,9 +5057,9 @@ findGenericParameterReferences(CanGenericSignature genericSig,
50775057
}
50785058

50795059
if (const auto concreteTy = genericSig->getConcreteType(type)) {
5080-
return findGenericParameterReferences(
5081-
genericSig, genericParam, concreteTy, position,
5082-
treatNonResultCovarianceAsInvariant, canBeCovariantResult);
5060+
return findGenericParameterReferencesRec(
5061+
genericSig, genericParam, concreteTy,
5062+
position, canBeCovariantResult);
50835063
}
50845064

50855065
// A reference to an associated type rooted on 'Self'.
@@ -5090,9 +5070,8 @@ GenericParameterReferenceInfo
50905070
swift::findGenericParameterReferences(const ValueDecl *value,
50915071
CanGenericSignature sig,
50925072
GenericTypeParamType *genericParam,
5093-
bool treatNonResultCovarianceAsInvariant,
50945073
std::optional<unsigned> skipParamIndex) {
5095-
assert(isa<TypeDecl>(value) == false);
5074+
assert(!isa<TypeDecl>(value));
50965075
assert(sig->getGenericParamOrdinal(genericParam) <
50975076
sig.getGenericParams().size());
50985077

@@ -5102,25 +5081,25 @@ swift::findGenericParameterReferences(const ValueDecl *value,
51025081
if (type->hasError())
51035082
return GenericParameterReferenceInfo();
51045083

5084+
// For functions and subscripts, take skipParamIndex into account.
51055085
if (isa<AbstractFunctionDecl>(value) || isa<SubscriptDecl>(value)) {
5106-
// For a method, skip the 'self' parameter.
5086+
// And for a method, skip the 'self' parameter.
51075087
if (value->hasCurriedSelf())
51085088
type = type->castTo<AnyFunctionType>()->getResult();
51095089

51105090
return ::findGenericParameterReferencesInFunction(
51115091
sig, genericParam, type->castTo<AnyFunctionType>(),
5112-
TypePosition::Covariant, treatNonResultCovarianceAsInvariant,
5113-
/*canBeCovariantResult=*/true, skipParamIndex);
5092+
TypePosition::Covariant, /*canBeCovariantResult=*/true,
5093+
skipParamIndex);
51145094
}
51155095

5116-
return ::findGenericParameterReferences(sig, genericParam, type,
5117-
TypePosition::Covariant,
5118-
treatNonResultCovarianceAsInvariant,
5119-
/*canBeCovariantResult=*/true);
5096+
return ::findGenericParameterReferencesRec(sig, genericParam, type,
5097+
TypePosition::Covariant,
5098+
/*canBeCovariantResult=*/true);
51205099
}
51215100

51225101
GenericParameterReferenceInfo ValueDecl::findExistentialSelfReferences(
5123-
Type baseTy, bool treatNonResultCovariantSelfAsInvariant) const {
5102+
Type baseTy) const {
51245103
assert(baseTy->isExistentialType());
51255104
assert(!baseTy->hasTypeParameter());
51265105

@@ -5139,9 +5118,7 @@ GenericParameterReferenceInfo ValueDecl::findExistentialSelfReferences(
51395118
GenericSignature());
51405119

51415120
auto genericParam = sig.getGenericParams().front();
5142-
return findGenericParameterReferences(this, sig, genericParam,
5143-
treatNonResultCovariantSelfAsInvariant,
5144-
std::nullopt);
5121+
return findGenericParameterReferences(this, sig, genericParam, std::nullopt);
51455122
}
51465123

51475124
TypeDecl::CanBeInvertible::Result

lib/Sema/CSSimplify.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1608,7 +1608,6 @@ shouldOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
16081608
// because it won't match anywhere else.
16091609
auto referenceInfo = findGenericParameterReferences(
16101610
callee, genericSig, genericParam,
1611-
/*treatNonResultCovarianceAsInvariant=*/false,
16121611
/*skipParamIdx=*/paramIdx);
16131612
if (referenceInfo.selfRef > TypePosition::Covariant ||
16141613
referenceInfo.assocTypeRef > TypePosition::Covariant)

lib/Sema/ConstraintSystem.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7548,9 +7548,7 @@ bool ConstraintSystem::isMemberAvailableOnExistential(
75487548
// N.B. We pass the module context because this check does not care about the
75497549
// the actual signature of the opened archetype in context, rather it cares
75507550
// about whether you can "hold" `baseTy.member` properly in the abstract.
7551-
const auto info = member->findExistentialSelfReferences(
7552-
baseTy,
7553-
/*treatNonResultCovariantSelfAsInvariant=*/false);
7551+
const auto info = member->findExistentialSelfReferences(baseTy);
75547552
if (info.selfRef > TypePosition::Covariant ||
75557553
info.assocTypeRef > TypePosition::Covariant) {
75567554
return false;

lib/Sema/TypeCheckDecl.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,8 +734,7 @@ bool HasSelfOrAssociatedTypeRequirementsRequest::evaluate(
734734
// For value members, look at their type signatures.
735735
if (auto valueMember = dyn_cast<ValueDecl>(member)) {
736736
const auto info = valueMember->findExistentialSelfReferences(
737-
decl->getDeclaredInterfaceType(),
738-
/*treatNonResultCovariantSelfAsInvariant=*/false);
737+
decl->getDeclaredInterfaceType());
739738
if (info.selfRef > TypePosition::Covariant || info.assocTypeRef) {
740739
return true;
741740
}

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,8 +1133,7 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache,
11331133
// the default witness for 'Collection.Iterator', which is defined
11341134
// as 'IndexingIterator<Self>'.
11351135
const auto selfRefInfo = req->findExistentialSelfReferences(
1136-
proto->getDeclaredInterfaceType(),
1137-
/*treatNonResultCovariantSelfAsInvariant=*/true);
1136+
proto->getDeclaredInterfaceType());
11381137
if (!selfRefInfo.assocTypeRef) {
11391138
covariantSelf = classDecl;
11401139
}
@@ -4037,10 +4036,11 @@ void ConformanceChecker::checkNonFinalClassWitness(ValueDecl *requirement,
40374036
// Check whether this requirement uses Self in a way that might
40384037
// prevent conformance from succeeding.
40394038
const auto selfRefInfo = requirement->findExistentialSelfReferences(
4040-
Proto->getDeclaredInterfaceType(),
4041-
/*treatNonResultCovariantSelfAsInvariant=*/true);
4039+
Proto->getDeclaredInterfaceType());
40424040

4043-
if (selfRefInfo.selfRef == TypePosition::Invariant) {
4041+
if (selfRefInfo.selfRef == TypePosition::Invariant ||
4042+
(selfRefInfo.selfRef == TypePosition::Covariant &&
4043+
!selfRefInfo.hasCovariantSelfResult)) {
40444044
// References to Self in a position where subclasses cannot do
40454045
// the right thing. Complain if the adoptee is a non-final
40464046
// class.

0 commit comments

Comments
 (0)