|
| 1 | +// RUN: %target-typecheck-verify-swift -target %target-swift-5.9-abi-triple |
| 2 | + |
| 3 | +class Class<T> {} |
| 4 | + |
| 5 | +// A protocol member accessed with an existential value might have generic |
| 6 | +// constraints that require the ability to spell an opened archetype in order |
| 7 | +// to be satisfied. Such are |
| 8 | +// - superclass requirements, when the object is a non-'Self'-rooted type |
| 9 | +// parameter, and the subject is dependent on 'Self', e.g. U : G<Self.A> |
| 10 | +// - same-type requirements, when one side is dependent on 'Self', and the |
| 11 | +// other is a non-'Self'-rooted type parameter, e.g. U.Element == Self. |
| 12 | +// |
| 13 | +// Because opened archetypes are not part of the surface language, these |
| 14 | +// constraints render the member inaccessible. |
| 15 | +// |
| 16 | +// Note: 'Self'-rooted type parameters that are invalid in the context of the |
| 17 | +// existential base type are ignored -- the underlying requirement failure is |
| 18 | +// considered a more pressing issue. |
| 19 | +protocol UnfulfillableGenericRequirements { |
| 20 | + associatedtype A |
| 21 | +} |
| 22 | +extension UnfulfillableGenericRequirements { |
| 23 | + func method1() where A : Class<Self> {} |
| 24 | + func method2() where A: Sequence, A.Element == Self {} |
| 25 | + func method3<U>(_: U) -> U {} |
| 26 | + func method4<U>(_: U) where U : Class<Self.A> {} |
| 27 | + // expected-note@-1 3 {{where 'U' = 'Bool'}} |
| 28 | + func method5<U>(_: U) where U: Sequence, Self == U.Element {} |
| 29 | + // expected-note@-1 {{where 'U' = 'Bool'}} |
| 30 | + |
| 31 | + // expected-note@+1 2 {{where 'U' = 'Bool'}} |
| 32 | + func method6<U>(_: U) where U: UnfulfillableGenericRequirements, |
| 33 | + A: Sequence, A.Element: Sequence, |
| 34 | + U.A == A.Element.Element {} |
| 35 | + func method7<U>(_: U) where U: UnfulfillableGenericRequirements & Class<Self> {} |
| 36 | + |
| 37 | + func method8<U>(_: U) where U == Self.A {} |
| 38 | +} |
| 39 | +do { |
| 40 | + let exist: any UnfulfillableGenericRequirements |
| 41 | + |
| 42 | + exist.method1() // expected-error {{instance method 'method1()' requires that 'Self.A' inherit from 'Class<Self>'}} |
| 43 | + exist.method2() |
| 44 | + // expected-error@-1 {{instance method 'method2()' requires the types 'Self' and 'Self.A.Element' be equivalent}} |
| 45 | + // expected-error@-2 {{instance method 'method2()' requires that 'Self.A' conform to 'Sequence'}} |
| 46 | + _ = exist.method3(false) // ok |
| 47 | + exist.method4(false) |
| 48 | + // expected-error@-1 {{instance method 'method4' requires that 'Bool' inherit from 'Class<Self.A>'}} |
| 49 | + // expected-error@-2 {{member 'method4' cannot be used on value of type 'any UnfulfillableGenericRequirements'; consider using a generic constraint instead}} |
| 50 | + exist.method5(false) |
| 51 | + // expected-error@-1 {{instance method 'method5' requires that 'Bool' conform to 'Sequence'}} |
| 52 | + // expected-error@-2 {{member 'method5' cannot be used on value of type 'any UnfulfillableGenericRequirements'; consider using a generic constraint instead}} |
| 53 | + |
| 54 | + exist.method7(false) |
| 55 | + // expected-error@-1 {{instance method 'method7' requires that 'U' conform to 'UnfulfillableGenericRequirements'}} |
| 56 | + // expected-error@-2 {{member 'method7' cannot be used on value of type 'any UnfulfillableGenericRequirements'; consider using a generic constraint instead}} |
| 57 | + |
| 58 | + exist.method8(false) |
| 59 | + // expected-error@-1 {{member 'method8' cannot be used on value of type 'any UnfulfillableGenericRequirements'; consider using a generic constraint instead}} |
| 60 | +} |
| 61 | + |
| 62 | +// Make sure this also works in a generic context! |
| 63 | +struct G<X, Y, Z> { |
| 64 | + func doIt() { |
| 65 | + let exist: any UnfulfillableGenericRequirements |
| 66 | + |
| 67 | + exist.method8(false) |
| 68 | + // expected-error@-1 {{member 'method8' cannot be used on value of type 'any UnfulfillableGenericRequirements'; consider using a generic constraint instead}} |
| 69 | + } |
| 70 | +} |
| 71 | +protocol UnfulfillableGenericRequirementsDerived1: UnfulfillableGenericRequirements where A == Bool {} |
| 72 | +protocol UnfulfillableGenericRequirementsDerived2: UnfulfillableGenericRequirements where A == Class<Self> {} |
| 73 | +do { |
| 74 | + // Test that 'Self' dependencies are computed relative to the base type. |
| 75 | + let exist1: any UnfulfillableGenericRequirementsDerived1 |
| 76 | + let exist2: any UnfulfillableGenericRequirementsDerived2 |
| 77 | + |
| 78 | + exist1.method4(false) |
| 79 | + // expected-error@-1 {{instance method 'method4' requires that 'Bool' inherit from 'Class<Self.A>}} |
| 80 | + exist2.method4(false) |
| 81 | + // expected-error@-1 {{member 'method4' cannot be used on value of type 'any UnfulfillableGenericRequirementsDerived2'; consider using a generic constraint instead}} |
| 82 | + // expected-error@-2 {{instance method 'method4' requires that 'Bool' inherit from 'Class<Self.A>'}} |
| 83 | +} |
| 84 | +protocol UnfulfillableGenericRequirementsDerived3: UnfulfillableGenericRequirements where A: Sequence, A.Element: Sequence {} |
| 85 | +do { |
| 86 | + // Test that 'Self'-rooted type parameters that are invalid in the context of |
| 87 | + // the existential base type are ignored. |
| 88 | + let exist1: any UnfulfillableGenericRequirements |
| 89 | + let exist2: any UnfulfillableGenericRequirementsDerived3 |
| 90 | + |
| 91 | + exist1.method6(false) |
| 92 | + // expected-error@-1 {{instance method 'method6' requires that 'Self.A.Element' conform to 'Sequence'}} |
| 93 | + // expected-error@-2 {{instance method 'method6' requires that 'Self.A' conform to 'Sequence'}} |
| 94 | + // expected-error@-3 {{instance method 'method6' requires that 'Bool' conform to 'UnfulfillableGenericRequirements'}} |
| 95 | + exist2.method6(false) |
| 96 | + // expected-error@-1 {{member 'method6' cannot be used on value of type 'any UnfulfillableGenericRequirementsDerived3'; consider using a generic constraint instead}} |
| 97 | + // expected-error@-2 {{instance method 'method6' requires that 'Bool' conform to 'UnfulfillableGenericRequirements'}} |
| 98 | +} |
| 99 | + |
| 100 | +// Test that we don't determine existential availability based on type |
| 101 | +// parameters that are invalid in the context of the existential base type -- |
| 102 | +// the requirement failure is a more pressing issue. |
| 103 | +protocol InvalidTypeParameters { |
| 104 | + associatedtype A |
| 105 | +} |
| 106 | +extension InvalidTypeParameters { |
| 107 | + func method1() -> A.A where A: InvalidTypeParameters {} |
| 108 | + func method2(_: A.A) where A: InvalidTypeParameters {} |
| 109 | + func method3(_: A.A, _: A) where A: InvalidTypeParameters {} |
| 110 | +} |
| 111 | +do { |
| 112 | + let exist: any InvalidTypeParameters |
| 113 | + |
| 114 | + exist.method1() // expected-error {{instance method 'method1()' requires that 'Self.A' conform to 'InvalidTypeParameters'}} |
| 115 | + exist.method2(false) // expected-error {{instance method 'method2' requires that 'Self.A' conform to 'InvalidTypeParameters'}} |
| 116 | + exist.method3(false, false) // expected-error {{instance method 'method3' requires that 'Self.A' conform to 'InvalidTypeParameters'}} |
| 117 | + // expected-error@-1 {{member 'method3' cannot be used on value of type 'any InvalidTypeParameters'; consider using a generic constraint instead}} |
| 118 | +} |
| 119 | + |
| 120 | +protocol GenericRequirementFailures { |
| 121 | + associatedtype A |
| 122 | +} |
| 123 | +extension GenericRequirementFailures where A == Never { |
| 124 | + func method1() {} |
| 125 | + func method2() -> Self {} |
| 126 | + func method3(_: A) {} |
| 127 | +} |
| 128 | +extension GenericRequirementFailures where A: GenericRequirementFailures { |
| 129 | + func method4() {} |
| 130 | +} |
| 131 | +do { |
| 132 | + let exist: any GenericRequirementFailures |
| 133 | + |
| 134 | + exist.method1() // expected-error {{referencing instance method 'method1()' on 'GenericRequirementFailures' requires the types 'Self.A' and 'Never' be equivalent}} |
| 135 | + exist.method2() // expected-error {{referencing instance method 'method2()' on 'GenericRequirementFailures' requires the types 'Self.A' and 'Never' be equivalent}} |
| 136 | + exist.method3(false) // expected-error {{referencing instance method 'method3' on 'GenericRequirementFailures' requires the types 'Self.A' and 'Never' be equivalent}} |
| 137 | + // expected-error@-1 {{member 'method3' cannot be used on value of type 'any GenericRequirementFailures'; consider using a generic constraint instead}} |
| 138 | + exist.method4() // expected-error {{referencing instance method 'method4()' on 'GenericRequirementFailures' requires that 'Self.A' conform to 'GenericRequirementFailures'}} |
| 139 | +} |
| 140 | +protocol GenericRequirementFailuresDerived: GenericRequirementFailures where A: GenericRequirementFailures {} |
| 141 | +do { |
| 142 | + let exist: any GenericRequirementFailuresDerived |
| 143 | + exist.method4() // ok |
| 144 | +} |
0 commit comments