1
- // RUN: %empty-directory(%t)
2
- // RUN: cp %s %t/main.swift
3
- // RUN: %target-swift-frontend -typecheck -verify -primary-file %t/main.swift %S/Inputs/enum_conformance_synthesis_other.swift -verify-ignore-unknown -swift-version 4
1
+ // RUN: %target-swift-frontend -typecheck -verify -primary-file %s %S/Inputs/enum_conformance_synthesis_other.swift -verify-ignore-unknown -swift-version 4
4
2
5
3
var hasher = Hasher ( )
6
4
7
5
enum Foo : CaseIterable {
8
6
case A, B
9
7
}
10
8
11
- if Foo . A == . B { }
12
- var aHash : Int = Foo . A. hashValue
13
- Foo . A. hash ( into: & hasher)
14
- _ = Foo . allCases
9
+ func foo( ) {
10
+ if Foo . A == . B { }
11
+ var _: Int = Foo . A. hashValue
12
+ Foo . A. hash ( into: & hasher)
13
+ _ = Foo . allCases
15
14
16
- Foo . A == Foo . B // expected-warning {{result of operator '==' is unused}}
15
+ Foo . A == Foo . B // expected-warning {{result of operator '==' is unused}}
16
+ }
17
17
18
18
enum Generic < T> : CaseIterable {
19
19
case A, B
@@ -25,10 +25,12 @@ enum Generic<T>: CaseIterable {
25
25
}
26
26
}
27
27
28
- if Generic< Foo> . A == . B { }
29
- var gaHash : Int = Generic < Foo > . A. hashValue
30
- Generic< Foo> . A. hash ( into: & hasher)
31
- _ = Generic< Foo> . allCases
28
+ func generic( ) {
29
+ if Generic< Foo> . A == . B { }
30
+ var _: Int = Generic < Foo > . A. hashValue
31
+ Generic< Foo> . A. hash ( into: & hasher)
32
+ _ = Generic< Foo> . allCases
33
+ }
32
34
33
35
func localEnum( ) -> Bool {
34
36
enum Local {
@@ -47,9 +49,11 @@ func ==(x: CustomHashable, y: CustomHashable) -> Bool { // expected-note 5 {{non
47
49
return true
48
50
}
49
51
50
- if CustomHashable . A == . B { }
51
- var custHash : Int = CustomHashable . A. hashValue
52
- CustomHashable . A. hash ( into: & hasher)
52
+ func customHashable( ) {
53
+ if CustomHashable . A == . B { }
54
+ var _: Int = CustomHashable . A. hashValue
55
+ CustomHashable . A. hash ( into: & hasher)
56
+ }
53
57
54
58
// We still synthesize conforming overloads of '==' and 'hashValue' if
55
59
// explicit definitions don't satisfy the protocol requirements. Probably
@@ -62,11 +66,14 @@ enum InvalidCustomHashable {
62
66
func == ( x: InvalidCustomHashable , y: InvalidCustomHashable ) -> String { // expected-note 5 {{non-matching type}}
63
67
return " "
64
68
}
65
- if InvalidCustomHashable . A == . B { }
66
- var s : String = InvalidCustomHashable . A == . B
67
- s = InvalidCustomHashable . A. hashValue
68
- var i : Int = InvalidCustomHashable . A. hashValue
69
- InvalidCustomHashable . A. hash ( into: & hasher)
69
+ func invalidCustomHashable( ) {
70
+ if InvalidCustomHashable . A == . B { }
71
+ var s : String = InvalidCustomHashable . A == . B
72
+ s = InvalidCustomHashable . A. hashValue
73
+ _ = s
74
+ var _: Int = InvalidCustomHashable . A. hashValue
75
+ InvalidCustomHashable . A. hash ( into: & hasher)
76
+ }
70
77
71
78
// Check use of an enum's synthesized members before the enum is actually declared.
72
79
struct UseEnumBeforeDeclaration {
@@ -77,25 +84,30 @@ enum EnumToUseBeforeDeclaration {
77
84
case A
78
85
}
79
86
80
- // Check enums from another file in the same module.
81
- if FromOtherFile . A == . A { }
82
- let _: Int = FromOtherFile . A. hashValue
83
-
84
87
func getFromOtherFile( ) -> AlsoFromOtherFile { return . A }
85
- if . A == getFromOtherFile ( ) { }
86
-
87
88
func overloadFromOtherFile( ) -> YetAnotherFromOtherFile { return . A }
88
89
func overloadFromOtherFile( ) -> Bool { return false }
89
- if . A == overloadFromOtherFile ( ) { }
90
+
91
+ func useEnumBeforeDeclaration( ) {
92
+ // Check enums from another file in the same module.
93
+ if FromOtherFile . A == . A { }
94
+ let _: Int = FromOtherFile . A. hashValue
95
+
96
+ if . A == getFromOtherFile ( ) { }
97
+
98
+ if . A == overloadFromOtherFile ( ) { }
99
+ }
90
100
91
101
// Complex enums are not automatically Equatable, Hashable, or CaseIterable.
92
102
enum Complex {
93
103
case A( Int )
94
104
case B
95
105
}
96
106
97
- if Complex . A ( 1 ) == . B { } // expected-error{{binary operator '==' cannot be applied to operands of type 'Complex' and '_'}}
98
- // expected-note @-1 {{overloads for '==' exist with these partially matching parameter lists: }}
107
+ func complex( ) {
108
+ if Complex . A ( 1 ) == . B { } // expected-error{{binary operator '==' cannot be applied to operands of type 'Complex' and '_'}}
109
+ // expected-note @-1 {{overloads for '==' exist with these partially matching parameter lists: }}
110
+ }
99
111
100
112
// Enums with equatable payloads are equatable if they explicitly conform.
101
113
enum EnumWithEquatablePayload : Equatable {
@@ -104,9 +116,11 @@ enum EnumWithEquatablePayload: Equatable {
104
116
case C
105
117
}
106
118
107
- if EnumWithEquatablePayload . A ( 1 ) == . B( " x " , 1 ) { }
108
- if EnumWithEquatablePayload . A ( 1 ) == . C { }
109
- if EnumWithEquatablePayload . B ( " x " , 1 ) == . C { }
119
+ func enumWithEquatablePayload( ) {
120
+ if EnumWithEquatablePayload . A ( 1 ) == . B( " x " , 1 ) { }
121
+ if EnumWithEquatablePayload . A ( 1 ) == . C { }
122
+ if EnumWithEquatablePayload . B ( " x " , 1 ) == . C { }
123
+ }
110
124
111
125
// Enums with hashable payloads are hashable if they explicitly conform.
112
126
enum EnumWithHashablePayload : Hashable {
@@ -115,18 +129,20 @@ enum EnumWithHashablePayload: Hashable {
115
129
case C
116
130
}
117
131
118
- _ = EnumWithHashablePayload . A ( 1 ) . hashValue
119
- _ = EnumWithHashablePayload . B ( " x " , 1 ) . hashValue
120
- _ = EnumWithHashablePayload . C. hashValue
132
+ func enumWithHashablePayload( ) {
133
+ _ = EnumWithHashablePayload . A ( 1 ) . hashValue
134
+ _ = EnumWithHashablePayload . B ( " x " , 1 ) . hashValue
135
+ _ = EnumWithHashablePayload . C. hashValue
121
136
122
- EnumWithHashablePayload . A ( 1 ) . hash ( into: & hasher)
123
- EnumWithHashablePayload . B ( " x " , 1 ) . hash ( into: & hasher)
124
- EnumWithHashablePayload . C. hash ( into: & hasher)
137
+ EnumWithHashablePayload . A ( 1 ) . hash ( into: & hasher)
138
+ EnumWithHashablePayload . B ( " x " , 1 ) . hash ( into: & hasher)
139
+ EnumWithHashablePayload . C. hash ( into: & hasher)
125
140
126
- // ...and they should also inherit equatability from Hashable.
127
- if EnumWithHashablePayload . A ( 1 ) == . B( " x " , 1 ) { }
128
- if EnumWithHashablePayload . A ( 1 ) == . C { }
129
- if EnumWithHashablePayload . B ( " x " , 1 ) == . C { }
141
+ // ...and they should also inherit equatability from Hashable.
142
+ if EnumWithHashablePayload . A ( 1 ) == . B( " x " , 1 ) { }
143
+ if EnumWithHashablePayload . A ( 1 ) == . C { }
144
+ if EnumWithHashablePayload . B ( " x " , 1 ) == . C { }
145
+ }
130
146
131
147
// Enums with non-hashable payloads don't derive conformance.
132
148
struct NotHashable { }
@@ -140,18 +156,22 @@ enum GenericHashable<T: Hashable>: Hashable {
140
156
case A( T )
141
157
case B
142
158
}
143
- if GenericHashable < String > . A ( " a " ) == . B { }
144
- var genericHashableHash : Int = GenericHashable < String > . A ( " a " ) . hashValue
159
+ func genericHashable( ) {
160
+ if GenericHashable < String > . A ( " a " ) == . B { }
161
+ var _: Int = GenericHashable < String > . A ( " a " ) . hashValue
162
+ }
145
163
146
164
// But it should be an error if the generic argument doesn't have the necessary
147
165
// constraints to satisfy the conditions for derivation.
148
166
enum GenericNotHashable < T: Equatable > : Hashable { // expected-error 2 {{does not conform to protocol 'Hashable'}}
149
167
case A( T )
150
168
case B
151
169
}
152
- if GenericNotHashable < String > . A ( " a " ) == . B { }
153
- let _: Int = GenericNotHashable < String > . A ( " a " ) . hashValue // No error. hashValue is always synthesized, even if Hashable derivation fails
154
- GenericNotHashable < String > . A ( " a " ) . hash ( into: & hasher) // expected-error {{value of type 'GenericNotHashable<String>' has no member 'hash'}}
170
+ func genericNotHashable( ) {
171
+ if GenericNotHashable < String > . A ( " a " ) == . B { }
172
+ let _: Int = GenericNotHashable < String > . A ( " a " ) . hashValue // No error. hashValue is always synthesized, even if Hashable derivation fails
173
+ GenericNotHashable < String > . A ( " a " ) . hash ( into: & hasher) // expected-error {{value of type 'GenericNotHashable<String>' has no member 'hash'}}
174
+ }
155
175
156
176
// An enum with no cases should not derive conformance.
157
177
enum NoCases : Hashable { } // expected-error 2 {{does not conform}}
@@ -193,13 +213,17 @@ public enum Medicine {
193
213
194
214
extension Medicine : Equatable { }
195
215
196
- public func == ( lhs: Medicine , rhs: Medicine ) -> Bool { // expected-note 4 {{non-matching type}}
216
+ public func == ( lhs: Medicine , rhs: Medicine ) -> Bool { // expected-note 5 {{non-matching type}}
197
217
return true
198
218
}
199
219
200
220
// No explicit conformance; but it can be derived, for the same-file cases.
201
- extension Complex : Hashable { }
202
- extension Complex : CaseIterable { } // expected-error {{type 'Complex' does not conform to protocol 'CaseIterable'}}
221
+ enum Complex2 {
222
+ case A( Int )
223
+ case B
224
+ }
225
+ extension Complex2 : Hashable { }
226
+ extension Complex2 : CaseIterable { } // expected-error {{type 'Complex2' does not conform to protocol 'CaseIterable'}}
203
227
extension FromOtherFile : CaseIterable { } // expected-error {{cannot be automatically synthesized in an extension in a different file to the type}} expected-error {{does not conform to protocol 'CaseIterable'}}
204
228
205
229
// No explicit conformance and it cannot be derived.
@@ -212,7 +236,7 @@ extension NotExplicitlyHashableAndCannotDerive : CaseIterable {} // expected-err
212
236
// Verify that conformance (albeit manually implemented) can still be added to
213
237
// a type in a different file.
214
238
extension OtherFileNonconforming : Hashable {
215
- static func == ( lhs: OtherFileNonconforming , rhs: OtherFileNonconforming ) -> Bool { // expected-note 4 {{non-matching type}}
239
+ static func == ( lhs: OtherFileNonconforming , rhs: OtherFileNonconforming ) -> Bool { // expected-note 5 {{non-matching type}}
216
240
return true
217
241
}
218
242
var hashValue : Int { return 0 }
@@ -290,6 +314,18 @@ extension UnusedGenericDeriveExtension: Hashable {}
290
314
extension GenericOtherFileNonconforming : Equatable where T: Equatable { }
291
315
// expected-error@-1{{implementation of 'Equatable' cannot be automatically synthesized in an extension in a different file to the type}}
292
316
317
+ // rdar://problem/41852654
318
+
319
+ // There is a conformance to Equatable (or at least, one that implies Equatable)
320
+ // in the same file as the type, so the synthesis is okay. Both orderings are
321
+ // tested, to catch choosing extensions based on the order of the files, etc.
322
+ protocol ImplierMain : Equatable { }
323
+ enum ImpliedMain : ImplierMain {
324
+ case a( Int )
325
+ }
326
+ extension ImpliedOther : ImplierMain { }
327
+
328
+
293
329
// FIXME: Remove -verify-ignore-unknown.
294
330
// <unknown>:0: error: unexpected error produced: invalid redeclaration of 'hashValue'
295
331
// <unknown>:0: error: unexpected note produced: candidate has non-matching type '(Foo, Foo) -> Bool'
0 commit comments