Skip to content

Commit 8547d98

Browse files
committed
Allow Equatable: ~Copyable
1 parent 09fec7d commit 8547d98

23 files changed

+1715
-1479
lines changed

stdlib/public/core/Equatable.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@
164164
/// let c = a
165165
/// print(c === a, c === b, separator: ", ")
166166
/// // Prints "true, false"
167-
public protocol Equatable {
167+
public protocol Equatable: ~Copyable {
168168
/// Returns a Boolean value indicating whether two values are equal.
169169
///
170170
/// Equality is the inverse of inequality. For any values `a` and `b`,
@@ -173,10 +173,10 @@ public protocol Equatable {
173173
/// - Parameters:
174174
/// - lhs: A value to compare.
175175
/// - rhs: Another value to compare.
176-
static func == (lhs: Self, rhs: Self) -> Bool
176+
static func == (lhs: borrowing Self, rhs: borrowing Self) -> Bool
177177
}
178178

179-
extension Equatable {
179+
extension Equatable where Self: ~Copyable {
180180
/// Returns a Boolean value indicating whether two values are not equal.
181181
///
182182
/// Inequality is the inverse of equality. For any values `a` and `b`, `a != b`
@@ -190,8 +190,9 @@ extension Equatable {
190190
/// - rhs: Another value to compare.
191191
// transparent because sometimes types that use this generate compile-time
192192
// warnings, e.g. that an expression always evaluates to true
193+
@_preInverseGenerics
193194
@_transparent
194-
public static func != (lhs: Self, rhs: Self) -> Bool {
195+
public static func != (lhs: borrowing Self, rhs: borrowing Self) -> Bool {
195196
return !(lhs == rhs)
196197
}
197198
}

test/Concurrency/member_operator_adjustment.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
// CHECK: (func_decl decl_context={{.*}} range={{.*}} "test(v:)"
44
func test<T: Equatable>(v: T) {
5-
// CHECK: (function_conversion_expr implicit type="@Sendable (T.Type) -> (T, T) -> Bool"
5+
// CHECK: (function_conversion_expr implicit type="@Sendable (T.Type) -> (borrowing T, borrowing T) -> Bool"
66
_ = v == v
77
}

test/Constraints/anyhashable_and_operator_filtering.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ func test(arr: [any P]) {
2626
// CHECK: sil private [ossa] @$s34anyhashable_and_operator_filtering4test3arrySayAA1P_pG_tFyAaD_pXEfU_
2727
// CHECK: [[LHS_ARG:%.*]] = alloc_stack $E
2828
// CHECK: [[RHS_ARG:%.*]] = alloc_stack $E
29-
// CHECK: [[GENERIC_OP:%.*]] = witness_method $E, #Equatable."==" : <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool
29+
// CHECK: [[GENERIC_OP:%.*]] = witness_method $E, #Equatable."==" : <Self where Self : Equatable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool
3030
// CHECK-NEXT: apply [[GENERIC_OP]]<E>([[LHS_ARG]], [[RHS_ARG]], {{.*}})

test/Constraints/rdar158063151.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ struct Value: Equatable, ExpressibleByNilLiteral {
88
}
99

1010
// CHECK-LABEL: sil hidden [ossa] @$s13rdar1580631514test1vyAA5ValueV_tF : $@convention(thin) (Value) -> ()
11-
// CHECK: [[EQUALS_REF:%.*]] = witness_method $Value, #Equatable."==" : <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool
11+
// CHECK: [[EQUALS_REF:%.*]] = witness_method $Value, #Equatable."==" : <Self where Self : Equatable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool
1212
// CHECK-NEXT: apply [[EQUALS_REF]]<Value>({{.*}})
1313
func test(v: Value) {
1414
_ = v == nil

test/Generics/tuple-conformances.swift

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,37 @@ func useConformance() {
9393

9494
////
9595

96-
extension Tuple: Equatable where repeat each Element: Equatable {
96+
97+
// Tuples cannot yet have conformances conditional on more than one thing,
98+
// and ~Copyable packs aren't yet supported, so redefining these protocols
99+
// as copyable-only versions
100+
101+
public protocol CopyableEquatable {
102+
static func ==(lhs: Self, rhs: Self) -> Bool
103+
}
104+
105+
public protocol CopyableComparable: CopyableEquatable {
106+
static func <(lhs: Self, rhs: Self) -> Bool
107+
}
108+
109+
public protocol CopyableHashable: CopyableEquatable {
110+
func hash(into hasher: inout Hasher)
111+
}
112+
113+
public extension CopyableEquatable {
114+
static func !=(lhs: Self, rhs: Self) -> Bool {
115+
!(lhs == rhs)
116+
}
117+
}
118+
119+
extension CopyableComparable {
120+
static func >(lhs: Self, rhs: Self) -> Bool {
121+
!(lhs > rhs) && lhs != rhs
122+
}
123+
}
124+
125+
126+
extension Tuple: CopyableEquatable where repeat each Element: CopyableEquatable {
97127
// FIXME: Hack
98128
@_disfavoredOverload
99129
public static func ==(lhs: Self, rhs: Self) -> Bool {
@@ -104,15 +134,15 @@ extension Tuple: Equatable where repeat each Element: Equatable {
104134
}
105135
}
106136

107-
extension Tuple: Hashable where repeat each Element: Hashable {
137+
extension Tuple: CopyableHashable where repeat each Element: CopyableHashable {
108138
public func hash(into hasher: inout Hasher) {
109139
for elt in repeat each self {
110140
elt.hash(into: &hasher)
111141
}
112142
}
113143
}
114144

115-
extension Tuple: Comparable where repeat each Element: Comparable {
145+
extension Tuple: CopyableComparable where repeat each Element: CopyableComparable {
116146
// FIXME: Hack
117147
@_disfavoredOverload
118148
public static func <(lhs: Self, rhs: Self) -> Bool {

test/IRGen/async/run-call-genericEquatable-x2-to-bool.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ sil public_external @printBool : $@convention(thin) (Bool) -> ()
2525
sil hidden @genericEquatableAndGenericEquatableToBool : $@async @convention(thin) <T where T : Equatable> (@in_guaranteed T, @in_guaranteed T) -> Bool {
2626
bb0(%0 : $*T, %1 : $*T):
2727
%4 = metatype $@thick T.Type
28-
%5 = witness_method $T, #Equatable."==" : <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool : $@convention(witness_method: Equatable) <τ_0_0 where τ_0_0 : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
28+
%5 = witness_method $T, #Equatable."==" : <Self where Self : Equatable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool : $@convention(witness_method: Equatable) <τ_0_0 where τ_0_0 : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
2929
%6 = apply %5<T>(%0, %1, %4) : $@convention(witness_method: Equatable) <τ_0_0 where τ_0_0 : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
3030
return %6 : $Bool
3131
}

test/Parse/inverses.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func more() {
1919
let _: ~AnyObject // expected-error {{type 'AnyObject' cannot be suppressed}}
2020
}
2121

22-
struct S4: ~(Copyable & Equatable) {} // expected-error {{conformance to 'Equatable' cannot be suppressed}}
22+
struct S4: ~(Copyable & Equatable) {} // expected-error {{type 'Copyable & Equatable' cannot be suppressed}}
2323

2424
func blah<T>(_ t: borrowing T) where T: ~Copyable,
2525
T: ~Hashable {} // expected-error@:41 {{type 'Hashable' cannot be suppressed}}

test/SILGen/enum_equatable_witness.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,15 @@ public enum Alphabet : String {
4848

4949
// CHECK-LABEL: sil [ossa] @$s4main14check_alphabetySiAA8AlphabetOF : $@convention(thin) (Alphabet) -> Int {
5050
public func check_alphabet(_ state : Alphabet) -> Int {
51-
// FRAGILE: witness_method $Alphabet, #Equatable."==" : <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool
52-
// RESILIENT: witness_method $Alphabet, #Equatable."==" : <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool
51+
// FRAGILE: witness_method $Alphabet, #Equatable."==" : <Self where Self : Equatable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool
52+
// RESILIENT: witness_method $Alphabet, #Equatable."==" : <Self where Self : Equatable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool
5353
return state == .E ? 1 : 0
5454
}
5555

5656
// CHECK-LABEL: sil [ossa] @$s4main9compareItySbAA8AlphabetO_ADtF : $@convention(thin) (Alphabet, Alphabet) -> Bool {
5757
public func compareIt(_ state : Alphabet, _ rhs: Alphabet) -> Bool {
58-
// FRAGILE: witness_method $Alphabet, #Equatable."==" : <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool
59-
// RESILIENT: witness_method $Alphabet, #Equatable."==" : <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool
58+
// FRAGILE: witness_method $Alphabet, #Equatable."==" : <Self where Self : Equatable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool
59+
// RESILIENT: witness_method $Alphabet, #Equatable."==" : <Self where Self : Equatable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool
6060
return state == rhs
6161
}
6262

@@ -67,14 +67,14 @@ public enum AlphabetInt : Int {
6767

6868
// CHECK-LABEL: sil [ossa] @$s4main18check_alphabet_intySiAA11AlphabetIntOF : $@convention(thin) (AlphabetInt) -> Int {
6969
public func check_alphabet_int(_ state : AlphabetInt) -> Int {
70-
// FRAGILE: witness_method $AlphabetInt, #Equatable."==" : <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool
71-
// RESILIENT: witness_method $AlphabetInt, #Equatable."==" : <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool
70+
// FRAGILE: witness_method $AlphabetInt, #Equatable."==" : <Self where Self : Equatable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool
71+
// RESILIENT: witness_method $AlphabetInt, #Equatable."==" : <Self where Self : Equatable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool
7272
return state == .E ? 1 : 0
7373
}
7474

7575
// CHECK-LABEL: sil [ossa] @$s4main9compareItySbAA11AlphabetIntO_ADtF : $@convention(thin) (AlphabetInt, AlphabetInt) -> Bool {
7676
public func compareIt(_ state : AlphabetInt, _ rhs: AlphabetInt) -> Bool {
77-
// FRAGILE: witness_method $AlphabetInt, #Equatable."==" : <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool
78-
// RESILIENT: witness_method $AlphabetInt, #Equatable."==" : <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool
77+
// FRAGILE: witness_method $AlphabetInt, #Equatable."==" : <Self where Self : Equatable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool
78+
// RESILIENT: witness_method $AlphabetInt, #Equatable."==" : <Self where Self : Equatable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool
7979
return state == rhs
8080
}

test/SILGen/pack_iteration.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ func iterateTrivial<each Element>(over element: repeat each Element) {
8585
// CHECK: tuple_pack_element_addr [[DYN_PACK_IDX]] of [[STACK1]] : $*(repeat each Element) as $*@pack_element("[[UUID]]") each Element
8686
// CHECK: tuple_pack_element_addr [[DYN_PACK_IDX]] of [[STACK2]] : $*(repeat each Element) as $*@pack_element("[[UUID]]") each Element
8787
// CHECK: [[METATYPE:%.*]] = metatype $@thick (@pack_element("[[UUID]]") each Element).Type
88-
// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $@pack_element("[[UUID]]") each Element, #Equatable."==" : <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool, [[OPEN_PACK_ELT]] : $Builtin.SILToken : $@convention(witness_method: Equatable) <τ_0_0 where τ_0_0 : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
89-
// CHECK: apply [[WITNESS_METHOD]]<@pack_element("[[UUID]]") each Element>([[STACK_LEFT]], [[STACK_RIGHT]], [[METATYPE]]) : $@convention(witness_method: Equatable) <τ_0_0 where τ_0_0 : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
88+
// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $@pack_element("[[UUID]]") each Element, #Equatable."==" : <Self where Self : Equatable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool, [[OPEN_PACK_ELT]] : $Builtin.SILToken : $@convention(witness_method: Equatable) <τ_0_0 where τ_0_0 : Equatable, τ_0_0 : ~Copyable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
89+
// CHECK: apply [[WITNESS_METHOD]]<@pack_element("[[UUID]]") each Element>([[STACK_LEFT]], [[STACK_RIGHT]], [[METATYPE]]) : $@convention(witness_method: Equatable) <τ_0_0 where τ_0_0 : Equatable, τ_0_0 : ~Copyable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
9090
//
9191
// CHECK: } // end sil function '$s14pack_iteration11equalTuples3lhs3rhsSbxxQp_t_xxQp_ttRvzSQRzlF'
9292
func equalTuples<each Element: Equatable>(lhs: (repeat each Element), rhs: (repeat each Element)) -> Bool {

test/SILGen/synthesized_conformance_enum.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ extension NoValues: Codable {}
7777
// Witness tables for Enum
7878

7979
// CHECK-LABEL: sil_witness_table hidden <T where T : Equatable> Enum<T>: Equatable module synthesized_conformance_enum {
80-
// CHECK-NEXT: method #Equatable."==": <Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool : @$s28synthesized_conformance_enum4EnumOyxGSQAASQRzlSQ2eeoiySbx_xtFZTW // protocol witness for static Equatable.== infix(_:_:) in conformance <A> Enum<A>
80+
// CHECK-NEXT: method #Equatable."==": <Self where Self : Equatable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool : @$s28synthesized_conformance_enum4EnumOyxGSQAASQRzlSQ2eeoiySbx_xtFZTW // protocol witness for static Equatable.== infix(_:_:) in conformance <A> Enum<A>
8181
// CHECK-NEXT: conditional_conformance (T: Equatable): dependent
8282
// CHECK-NEXT: }
8383

0 commit comments

Comments
 (0)