AST: Handle missing cases in findGenericParameterReferencesRec()

This commit is contained in:
Slava Pestov
2024-09-02 16:12:50 -04:00
parent 56cefdc83f
commit 36683a804c
2 changed files with 63 additions and 3 deletions

View File

@@ -4904,7 +4904,7 @@ findGenericParameterReferencesRec(CanGenericSignature genericSig,
TypePosition position,
bool canBeCovariantResult) {
// If there are no type parameters, we're done.
if (!type->hasTypeParameter())
if (!type->getCanonicalType()->hasTypeParameter())
return GenericParameterReferenceInfo();
// Tuples preserve variance.
@@ -4954,7 +4954,7 @@ findGenericParameterReferencesRec(CanGenericSignature genericSig,
// Don't forget to look in the parent.
if (const auto parent = nominal->getParent()) {
info |= findGenericParameterReferencesRec(
genericSig, genericParam, parent, position,
genericSig, genericParam, parent, TypePosition::Invariant,
/*canBeCovariantResult=*/false);
}
@@ -5033,10 +5033,40 @@ findGenericParameterReferencesRec(CanGenericSignature genericSig,
return info;
}
if (!type->isTypeParameter()) {
// Packs are invariant.
if (auto *pack = type->getAs<PackType>()) {
auto info = GenericParameterReferenceInfo();
for (auto arg : pack->getElementTypes()) {
info |= findGenericParameterReferencesRec(
genericSig, genericParam, arg,
TypePosition::Invariant, /*canBeCovariantResult=*/false);
}
return info;
}
// Pack expansions are invariant.
if (auto *expansion = type->getAs<PackExpansionType>()) {
return findGenericParameterReferencesRec(
genericSig, genericParam, expansion->getPatternType(),
TypePosition::Invariant, /*canBeCovariantResult=*/false);
}
// Specifically ignore parameterized protocols and existential
// metatypes because we can erase them to the upper bound.
if (type->is<ParameterizedProtocolType>() ||
type->is<ExistentialMetatypeType>()) {
return GenericParameterReferenceInfo();
}
// Everything else should be a type parameter.
if (!type->isTypeParameter()) {
llvm::errs() << "Unhandled type:\n";
type->dump(llvm::errs());
abort();
}
Type selfTy(genericParam);
if (!type->getRootGenericParam()->isEqual(selfTy)) {
return GenericParameterReferenceInfo();

View File

@@ -1025,6 +1025,10 @@ do {
let _: Dictionary<String, any Class2Base & CovariantAssocTypeErasureDerived> = exist.method12()
}
///
/// Interactions between opening and parameter packs
///
// Same-shape requirements
protocol HasSameShape {
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 {
func bar(a: any HasSameShape) -> (Int, String) {
a.foo(t: 1, u: "hi")
}
// Make sure we look through a pack type when evaluating the variance of the result
struct Variadic<each A> {}
protocol VariadicResult {
associatedtype A
func foo() -> Variadic<A>
}
func variadicResult(a: any VariadicResult) {
a.foo()
// expected-error@-1 {{member 'foo' cannot be used on value of type 'any VariadicResult'; consider using a generic constraint instead}}
}
// Pack expansions are invariant
struct Pair<X, Y> {}
protocol PackExpansionResult {
associatedtype A
func foo<each T>(t: repeat each T) -> (repeat Pair<each T, A>)
}
func packExpansionResult(p: any PackExpansionResult) {
p.foo(t: 1, "hi")
// expected-error@-1 {{member 'foo' cannot be used on value of type 'any PackExpansionResult'; consider using a generic constraint instead}}
}