Skip to content

Commit 36683a8

Browse files
committed
AST: Handle missing cases in findGenericParameterReferencesRec()
1 parent 56cefdc commit 36683a8

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

lib/AST/Decl.cpp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4904,7 +4904,7 @@ findGenericParameterReferencesRec(CanGenericSignature genericSig,
49044904
TypePosition position,
49054905
bool canBeCovariantResult) {
49064906
// If there are no type parameters, we're done.
4907-
if (!type->hasTypeParameter())
4907+
if (!type->getCanonicalType()->hasTypeParameter())
49084908
return GenericParameterReferenceInfo();
49094909

49104910
// Tuples preserve variance.
@@ -4954,7 +4954,7 @@ findGenericParameterReferencesRec(CanGenericSignature genericSig,
49544954
// Don't forget to look in the parent.
49554955
if (const auto parent = nominal->getParent()) {
49564956
info |= findGenericParameterReferencesRec(
4957-
genericSig, genericParam, parent, position,
4957+
genericSig, genericParam, parent, TypePosition::Invariant,
49584958
/*canBeCovariantResult=*/false);
49594959
}
49604960

@@ -5033,10 +5033,40 @@ findGenericParameterReferencesRec(CanGenericSignature genericSig,
50335033
return info;
50345034
}
50355035

5036-
if (!type->isTypeParameter()) {
5036+
// Packs are invariant.
5037+
if (auto *pack = type->getAs<PackType>()) {
5038+
auto info = GenericParameterReferenceInfo();
5039+
5040+
for (auto arg : pack->getElementTypes()) {
5041+
info |= findGenericParameterReferencesRec(
5042+
genericSig, genericParam, arg,
5043+
TypePosition::Invariant, /*canBeCovariantResult=*/false);
5044+
}
5045+
5046+
return info;
5047+
}
5048+
5049+
// Pack expansions are invariant.
5050+
if (auto *expansion = type->getAs<PackExpansionType>()) {
5051+
return findGenericParameterReferencesRec(
5052+
genericSig, genericParam, expansion->getPatternType(),
5053+
TypePosition::Invariant, /*canBeCovariantResult=*/false);
5054+
}
5055+
5056+
// Specifically ignore parameterized protocols and existential
5057+
// metatypes because we can erase them to the upper bound.
5058+
if (type->is<ParameterizedProtocolType>() ||
5059+
type->is<ExistentialMetatypeType>()) {
50375060
return GenericParameterReferenceInfo();
50385061
}
50395062

5063+
// Everything else should be a type parameter.
5064+
if (!type->isTypeParameter()) {
5065+
llvm::errs() << "Unhandled type:\n";
5066+
type->dump(llvm::errs());
5067+
abort();
5068+
}
5069+
50405070
Type selfTy(genericParam);
50415071
if (!type->getRootGenericParam()->isEqual(selfTy)) {
50425072
return GenericParameterReferenceInfo();

test/decl/protocol/existential_member_accesses_self_assoctype.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,10 @@ do {
10251025
let _: Dictionary<String, any Class2Base & CovariantAssocTypeErasureDerived> = exist.method12()
10261026
}
10271027

1028+
///
1029+
/// Interactions between opening and parameter packs
1030+
///
1031+
10281032
// Same-shape requirements
10291033
protocol HasSameShape {
10301034
func foo<each T, each U>(t: repeat each T, u: repeat each U) -> (repeat (each T, each U))
@@ -1033,3 +1037,29 @@ protocol HasSameShape {
10331037
func bar(a: any HasSameShape) -> (Int, String) {
10341038
a.foo(t: 1, u: "hi")
10351039
}
1040+
1041+
// Make sure we look through a pack type when evaluating the variance of the result
1042+
struct Variadic<each A> {}
1043+
1044+
protocol VariadicResult {
1045+
associatedtype A
1046+
func foo() -> Variadic<A>
1047+
}
1048+
1049+
func variadicResult(a: any VariadicResult) {
1050+
a.foo()
1051+
// expected-error@-1 {{member 'foo' cannot be used on value of type 'any VariadicResult'; consider using a generic constraint instead}}
1052+
}
1053+
1054+
// Pack expansions are invariant
1055+
struct Pair<X, Y> {}
1056+
1057+
protocol PackExpansionResult {
1058+
associatedtype A
1059+
func foo<each T>(t: repeat each T) -> (repeat Pair<each T, A>)
1060+
}
1061+
1062+
func packExpansionResult(p: any PackExpansionResult) {
1063+
p.foo(t: 1, "hi")
1064+
// expected-error@-1 {{member 'foo' cannot be used on value of type 'any PackExpansionResult'; consider using a generic constraint instead}}
1065+
}

0 commit comments

Comments
 (0)