Skip to content

Commit 75953d2

Browse files
committed
OpenedExistentials: Do not attempt to erase existential metatypes with invariant Self
The non-metatype case was never supported. The same should hold for the existential metatype case, which used to miscompile and now crashes because the invariant reference is deemed OK but the erasure expectedly fails to handle it: ```swift class C<T> {} protocol P { associatedtype A func f() -> any P & C<A> func fMeta() -> any (P & C<A>).Type } do { let p: any P let _ = p.f() // error let _ = p.fMeta() // crash } ```
1 parent b31b90d commit 75953d2

File tree

3 files changed

+24
-5
lines changed

3 files changed

+24
-5
lines changed

lib/Sema/OpenedExistentials.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ findGenericParameterReferencesRec(CanGenericSignature genericSig,
147147
}
148148

149149
// Metatypes preserve variance.
150-
if (auto metaTy = type->getAs<MetatypeType>()) {
150+
if (auto metaTy = type->getAs<AnyMetatypeType>()) {
151151
return findGenericParameterReferencesRec(genericSig, origParam, openedParam,
152152
metaTy->getInstanceType(),
153153
position, canBeCovariantResult);
@@ -272,10 +272,9 @@ findGenericParameterReferencesRec(CanGenericSignature genericSig,
272272
TypePosition::Invariant, /*canBeCovariantResult=*/false);
273273
}
274274

275-
// Specifically ignore parameterized protocols and existential
276-
// metatypes because we can erase them to the upper bound.
277-
if (type->is<ParameterizedProtocolType>() ||
278-
type->is<ExistentialMetatypeType>()) {
275+
// Specifically ignore parameterized protocols because we can erase them to
276+
// the upper bound.
277+
if (type->is<ParameterizedProtocolType>()) {
279278
return GenericParameterReferenceInfo();
280279
}
281280

test/Constraints/opened_existentials.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,20 @@ do {
484484
nestedMetatypeCallee(t)
485485
}
486486

487+
do {
488+
class C<T> {}
489+
protocol P {}
490+
491+
func f<T: P>(_: T, _: (() -> any (P & C<T>).Type)? = nil) {}
492+
// expected-note@-1 {{required by local function 'f' where 'T' = 'any P'}}
493+
494+
let p: any P
495+
// CHECK-NOT: open_existential_expr {{.*}} location={{.*}}:[[@LINE+1]]:{{[0-9]+}} range=
496+
f(p)
497+
// expected-error@-1 {{type 'any P' cannot conform to 'P'}}
498+
// expected-note@-2 {{only concrete types such as structs, enums and classes can conform to protocols}}
499+
}
500+
487501
do {
488502
protocol P {}
489503

test/decl/protocol/existential_member_access/basic.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,7 @@ do {
510510
// expected-error@+1 {{non-protocol, non-class type 'Sequence<${type}>' cannot be used within a protocol-constrained type}}
511511
func invariant13() -> any P & Sequence<${type}>
512512
func invariant14() -> (any Sequence<${type}>).Type
513+
func invariant15() -> any (P & Class<${type}>).Type
513514

514515

515516
var invariantProp1: (inout ${type}) -> Void { get }
@@ -523,6 +524,7 @@ do {
523524
var invariantProp9: (Struct<() -> ${type}>) -> Void { get }
524525
var invariantProp10: (any P & Class<${type}>) -> Void { get }
525526
var invariantProp11: Struct<${type}>.InnerGeneric<Void> { get }
527+
var invariantProp15: any (P & Class<${type}>).Type { get }
526528

527529
subscript(invariantSubscript1 _: Struct<${type}>) -> Void { get }
528530
subscript(invariantSubscript2 _: Void) -> Struct<${type}> { get }
@@ -532,6 +534,7 @@ do {
532534
subscript(invariantSubscript6 _: Struct<() -> ${type}>) -> Void { get }
533535
subscript(invariantSubscript7 _: any P & Class<${type}>) -> Void { get }
534536
subscript(invariantSubscript8 _: Void) -> Struct<${type}>.InnerGeneric<Void> { get }
537+
subscript(invariantSubscript15 _: Void) -> any (P & Class<${type}>).Type { get }
535538
}
536539

537540
let exist: any P
@@ -561,6 +564,7 @@ do {
561564
var types = SwiftTypePair(typeOf: exist.invariant14(), type2: SwiftType<(any Sequence).Type>.self)
562565
types.assertTypesAreEqual()
563566
}
567+
exist.invariant15() // expected-error {{member 'invariant15' cannot be used on value of type 'any P'; consider using a generic constraint instead}}
564568

565569
exist.invariantProp1 // expected-error {{member 'invariantProp1' cannot be used on value of type 'any P'; consider using a generic constraint instead}}
566570
exist.invariantProp2 // expected-error {{member 'invariantProp2' cannot be used on value of type 'any P'; consider using a generic constraint instead}}
@@ -573,6 +577,7 @@ do {
573577
exist.invariantProp9 // expected-error {{member 'invariantProp9' cannot be used on value of type 'any P'; consider using a generic constraint instead}}
574578
exist.invariantProp10 // expected-error {{member 'invariantProp10' cannot be used on value of type 'any P'; consider using a generic constraint instead}}
575579
exist.invariantProp11 // expected-error {{member 'invariantProp11' cannot be used on value of type 'any P'; consider using a generic constraint instead}}
580+
exist.invariantProp15 // expected-error {{member 'invariantProp15' cannot be used on value of type 'any P'; consider using a generic constraint instead}}
576581

577582
exist[invariantSubscript1: 0] // expected-error {{member 'subscript' cannot be used on value of type 'any P'; consider using a generic constraint instead}}
578583
exist[invariantSubscript2: ()] // expected-error {{member 'subscript' cannot be used on value of type 'any P'; consider using a generic constraint instead}}
@@ -582,4 +587,5 @@ do {
582587
exist[invariantSubscript6: 0] // expected-error {{member 'subscript' cannot be used on value of type 'any P'; consider using a generic constraint instead}}
583588
exist[invariantSubscript7: 0] // expected-error {{member 'subscript' cannot be used on value of type 'any P'; consider using a generic constraint instead}}
584589
exist[invariantSubscript8: ()] // expected-error {{member 'subscript' cannot be used on value of type 'any P'; consider using a generic constraint instead}}
590+
exist[invariantSubscript15: ()] // expected-error {{member 'subscript' cannot be used on value of type 'any P'; consider using a generic constraint instead}}
585591
}

0 commit comments

Comments
 (0)