Skip to content

Commit 88ccda0

Browse files
committed
Allow Comparable: ~Copyable
1 parent 8547d98 commit 88ccda0

File tree

7 files changed

+87
-25
lines changed

7 files changed

+87
-25
lines changed

stdlib/public/core/Comparable.swift

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@
135135
/// (`FloatingPoint.nan`) compares as neither less than, greater than, nor
136136
/// equal to any normal floating-point value. Exceptional values need not
137137
/// take part in the strict total order.
138-
public protocol Comparable: Equatable {
138+
public protocol Comparable: Equatable, ~Copyable {
139139
/// Returns a Boolean value indicating whether the value of the first
140140
/// argument is less than that of the second argument.
141141
///
@@ -146,34 +146,34 @@ public protocol Comparable: Equatable {
146146
/// - Parameters:
147147
/// - lhs: A value to compare.
148148
/// - rhs: Another value to compare.
149-
static func < (lhs: Self, rhs: Self) -> Bool
149+
static func < (lhs: borrowing Self, rhs: borrowing Self) -> Bool
150150

151151
/// Returns a Boolean value indicating whether the value of the first
152152
/// argument is less than or equal to that of the second argument.
153153
///
154154
/// - Parameters:
155155
/// - lhs: A value to compare.
156156
/// - rhs: Another value to compare.
157-
static func <= (lhs: Self, rhs: Self) -> Bool
157+
static func <= (lhs: borrowing Self, rhs: borrowing Self) -> Bool
158158

159159
/// Returns a Boolean value indicating whether the value of the first
160160
/// argument is greater than or equal to that of the second argument.
161161
///
162162
/// - Parameters:
163163
/// - lhs: A value to compare.
164164
/// - rhs: Another value to compare.
165-
static func >= (lhs: Self, rhs: Self) -> Bool
165+
static func >= (lhs: borrowing Self, rhs: borrowing Self) -> Bool
166166

167167
/// Returns a Boolean value indicating whether the value of the first
168168
/// argument is greater than that of the second argument.
169169
///
170170
/// - Parameters:
171171
/// - lhs: A value to compare.
172172
/// - rhs: Another value to compare.
173-
static func > (lhs: Self, rhs: Self) -> Bool
173+
static func > (lhs: borrowing Self, rhs: borrowing Self) -> Bool
174174
}
175175

176-
extension Comparable {
176+
extension Comparable where Self: ~Copyable {
177177
/// Returns a Boolean value indicating whether the value of the first argument
178178
/// is greater than that of the second argument.
179179
///
@@ -184,7 +184,8 @@ extension Comparable {
184184
/// - lhs: A value to compare.
185185
/// - rhs: Another value to compare.
186186
@inlinable
187-
public static func > (lhs: Self, rhs: Self) -> Bool {
187+
@_preInverseGenerics
188+
public static func > (lhs: borrowing Self, rhs: borrowing Self) -> Bool {
188189
return rhs < lhs
189190
}
190191

@@ -198,7 +199,8 @@ extension Comparable {
198199
/// - lhs: A value to compare.
199200
/// - rhs: Another value to compare.
200201
@inlinable
201-
public static func <= (lhs: Self, rhs: Self) -> Bool {
202+
@_preInverseGenerics
203+
public static func <= (lhs: borrowing Self, rhs: borrowing Self) -> Bool {
202204
return !(rhs < lhs)
203205
}
204206

@@ -214,7 +216,8 @@ extension Comparable {
214216
/// - Returns: `true` if `lhs` is greater than or equal to `rhs`; otherwise,
215217
/// `false`.
216218
@inlinable
217-
public static func >= (lhs: Self, rhs: Self) -> Bool {
219+
@_preInverseGenerics
220+
public static func >= (lhs: borrowing Self, rhs: borrowing Self) -> Bool {
218221
return !(lhs < rhs)
219222
}
220223
}

test/Constraints/diagnostics.swift

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,14 +1470,12 @@ func testUnwrapFixIts(x: Int?) throws {
14701470
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{11-11=!}}
14711471
foo(y: x ?? 0)
14721472

1473-
let _ = x < 2 // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
1474-
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{12-12= ?? <#default value#>}}
1475-
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{12-12=!}}
1473+
let _ = x < 2 // expected-error {{binary operator '<' cannot be applied to operands of type 'Int?' and 'Int'}}
1474+
// expected-note@-1 {{overloads for '<' exist with these partially matching parameter lists: (Int, Int)}}
14761475
let _ = x ?? 0 < 2
14771476

1478-
let _ = 2 < x // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
1479-
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{16-16= ?? <#default value#>}}
1480-
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{16-16=!}}
1477+
let _ = 2 < x // expected-error {{binary operator '<' cannot be applied to operands of type 'Int' and 'Int?'}}
1478+
// expected-note@-1 {{overloads for '<' exist with these partially matching parameter lists: (Int, Int)}}
14811479
let _ = 2 < x ?? 0
14821480

14831481
let _: Int = (.optionalIntMember) // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
@@ -1495,9 +1493,8 @@ func testUnwrapFixIts(x: Int?) throws {
14951493
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{36-36=!}}
14961494
let _ = try (.optionalThrowsMember ?? 0) + 1
14971495

1498-
let _ = .optionalIntMember?.bitWidth > 0 // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
1499-
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{39-39= ?? <#default value#>}}
1500-
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{11-11=(}} {{39-39=)!}}
1496+
let _ = .optionalIntMember?.bitWidth > 0 // expected-error {{binary operator '>' cannot be applied to operands of type 'Int?' and 'Int'}}
1497+
// expected-note@-1 {{overloads for '>' exist with these partially matching parameter lists: (Int, Int)}}
15011498
let _ = (.optionalIntMember?.bitWidth)! > 0
15021499
let _ = .optionalIntMember?.bitWidth ?? 0 > 0
15031500

test/SILOptimizer/mandatory_performance_optimizations.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ bb0:
8484
sil [no_allocation] [ossa] @deserialize_and_inline_after_devirtualize : $@convention(thin) (@in Int) -> () {
8585
bb0(%0 : $*Int):
8686
%1 = metatype $@thick Int.Type
87-
%2 = witness_method $Int, #Comparable."<" : <Self where Self : Comparable> (Self.Type) -> (Self, Self) -> Bool : $@convention(witness_method: Comparable) <τ_0_0 where τ_0_0 : Comparable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
87+
%2 = witness_method $Int, #Comparable."<" : <Self where Self : Comparable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool : $@convention(witness_method: Comparable) <τ_0_0 where τ_0_0 : Comparable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
8888
%3 = apply %2<Int>(%0, %0, %1) : $@convention(witness_method: Comparable) <τ_0_0 where τ_0_0 : Comparable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool
8989
%4 = tuple()
9090
return %4 : $()
@@ -124,7 +124,7 @@ bb0(%0 : $*Int, %1 : $*Int, %2 : $@thick Int.Type):
124124

125125
sil_witness_table public_external [serialized] Int: Comparable module Swift {
126126
base_protocol Equatable: Int: Equatable module Swift
127-
method #Comparable."<": <Self where Self : Comparable> (Self.Type) -> (Self, Self) -> Bool : @$sSiSLsSL1loiySbx_xtFZTW
127+
method #Comparable."<": <Self where Self : Comparable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool : @$sSiSLsSL1loiySbx_xtFZTW
128128
}
129129

130130
sil [ossa] @get_int_value : $@convention(thin) () -> Int32 {

test/api-digester/Outputs/stability-stdlib-source-base.swift.expected

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ Protocol CodingKey has added inherited protocol Copyable
7171
Protocol CodingKey has added inherited protocol Escapable
7272
Protocol Collection has added inherited protocol Copyable
7373
Protocol Collection has added inherited protocol Escapable
74-
Protocol Comparable has added inherited protocol Copyable
7574
Protocol Comparable has added inherited protocol Escapable
75+
Protocol Comparable has generic signature change from <Self : Swift.Equatable> to <Self : Swift.Equatable, Self : ~Copyable>
7676
Protocol CustomDebugStringConvertible has added inherited protocol Copyable
7777
Protocol CustomDebugStringConvertible has added inherited protocol Escapable
7878
Protocol CustomLeafReflectable has added inherited protocol Copyable
@@ -246,6 +246,18 @@ Func Equatable.!=(_:_:) has parameter 1 changing from Default to Shared
246246
Func Equatable.==(_:_:) has generic signature change from <Self where Self : Swift.Equatable> to <Self where Self : Swift.Equatable, Self : ~Copyable>
247247
Func Equatable.==(_:_:) has parameter 0 changing from Default to Shared
248248
Func Equatable.==(_:_:) has parameter 1 changing from Default to Shared
249+
Func Comparable.<(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
250+
Func Comparable.<(_:_:) has parameter 0 changing from Default to Shared
251+
Func Comparable.<(_:_:) has parameter 1 changing from Default to Shared
252+
Func Comparable.<=(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
253+
Func Comparable.<=(_:_:) has parameter 0 changing from Default to Shared
254+
Func Comparable.<=(_:_:) has parameter 1 changing from Default to Shared
255+
Func Comparable.>(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
256+
Func Comparable.>(_:_:) has parameter 0 changing from Default to Shared
257+
Func Comparable.>(_:_:) has parameter 1 changing from Default to Shared
258+
Func Comparable.>=(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
259+
Func Comparable.>=(_:_:) has parameter 0 changing from Default to Shared
260+
Func Comparable.>=(_:_:) has parameter 1 changing from Default to Shared
249261
Func ManagedBuffer.create(minimumCapacity:makingHeaderWith:) has generic signature change from <Header, Element> to <Header, Element where Element : ~Copyable>
250262
Func ManagedBufferPointer.isUniqueReference() has generic signature change from <Header, Element> to <Header, Element where Element : ~Copyable>
251263
Func MemoryLayout.alignment(ofValue:) has generic signature change from <T> to <T where T : ~Copyable, T : ~Escapable>

test/api-digester/stability-stdlib-abi-without-asserts.test

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,8 @@ Protocol CodingKey has added inherited protocol Copyable
189189
Protocol CodingKey has added inherited protocol Escapable
190190
Protocol Collection has added inherited protocol Copyable
191191
Protocol Collection has added inherited protocol Escapable
192-
Protocol Comparable has added inherited protocol Copyable
193192
Protocol Comparable has added inherited protocol Escapable
193+
Protocol Comparable has generic signature change from <Self : Swift.Equatable> to <Self : Swift.Equatable, Self : ~Copyable>
194194
Protocol CustomDebugStringConvertible has added inherited protocol Copyable
195195
Protocol CustomDebugStringConvertible has added inherited protocol Escapable
196196
Protocol CustomLeafReflectable has added inherited protocol Copyable
@@ -546,6 +546,24 @@ Func Equatable.!=(_:_:) is now with @_preInverseGenerics
546546
Func Equatable.==(_:_:) has generic signature change from <Self where Self : Swift.Equatable> to <Self where Self : Swift.Equatable, Self : ~Copyable>
547547
Func Equatable.==(_:_:) has parameter 0 changing from Default to Shared
548548
Func Equatable.==(_:_:) has parameter 1 changing from Default to Shared
549+
Func Comparable.<(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
550+
Func Comparable.<(_:_:) has parameter 0 changing from Default to Shared
551+
Func Comparable.<(_:_:) has parameter 1 changing from Default to Shared
552+
Func Comparable.<=(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
553+
Func Comparable.<=(_:_:) has mangled name changing from 'static (extension in Swift):Swift.Comparable.<= infix(A, A) -> Swift.Bool' to 'static (extension in Swift):Swift.Comparable< where A: ~Swift.Copyable>.<= infix(A, A) -> Swift.Bool'
554+
Func Comparable.<=(_:_:) has parameter 0 changing from Default to Shared
555+
Func Comparable.<=(_:_:) has parameter 1 changing from Default to Shared
556+
Func Comparable.<=(_:_:) is now with @_preInverseGenerics
557+
Func Comparable.>(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
558+
Func Comparable.>(_:_:) has mangled name changing from 'static (extension in Swift):Swift.Comparable.> infix(A, A) -> Swift.Bool' to 'static (extension in Swift):Swift.Comparable< where A: ~Swift.Copyable>.> infix(A, A) -> Swift.Bool'
559+
Func Comparable.>(_:_:) has parameter 0 changing from Default to Shared
560+
Func Comparable.>(_:_:) has parameter 1 changing from Default to Shared
561+
Func Comparable.>(_:_:) is now with @_preInverseGenerics
562+
Func Comparable.>=(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
563+
Func Comparable.>=(_:_:) has mangled name changing from 'static (extension in Swift):Swift.Comparable.>= infix(A, A) -> Swift.Bool' to 'static (extension in Swift):Swift.Comparable< where A: ~Swift.Copyable>.>= infix(A, A) -> Swift.Bool'
564+
Func Comparable.>=(_:_:) has parameter 0 changing from Default to Shared
565+
Func Comparable.>=(_:_:) has parameter 1 changing from Default to Shared
566+
Func Comparable.>=(_:_:) is now with @_preInverseGenerics
549567
Func ManagedBuffer.create(minimumCapacity:makingHeaderWith:) has generic signature change from <Header, Element> to <Header, Element where Element : ~Copyable>
550568
Func ManagedBuffer.create(minimumCapacity:makingHeaderWith:) has mangled name changing from 'static Swift.ManagedBuffer.create(minimumCapacity: Swift.Int, makingHeaderWith: (Swift.ManagedBuffer<A, B>) throws -> A) throws -> Swift.ManagedBuffer<A, B>' to 'static (extension in Swift):Swift.ManagedBuffer< where B: ~Swift.Copyable>.create(minimumCapacity: Swift.Int, makingHeaderWith: (Swift.ManagedBuffer<A, B>) throws -> A) throws -> Swift.ManagedBuffer<A, B>'
551569
Func ManagedBuffer.create(minimumCapacity:makingHeaderWith:) is now with @_preInverseGenerics

test/stdlib/NoncopyableEquatable.swift

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,13 @@ func isNotSame<T: Equatable & ~Copyable>(_ lhs: borrowing T, _ rhs: borrowing T)
3232
lhs != rhs
3333
}
3434

35-
NoncopyableEquatableTests.test("comparing noncopyables") {
35+
extension Noncopyable: Comparable {
36+
static func <(lhs: borrowing Self, rhs: borrowing Self) -> Bool {
37+
lhs.i < rhs.i
38+
}
39+
}
40+
41+
NoncopyableEquatableTests.test("equating noncopyables") {
3642
let a = Noncopyable(i: 1)
3743
let b = Noncopyable(i: 2)
3844
let c = Noncopyable(i: 1)
@@ -43,4 +49,26 @@ NoncopyableEquatableTests.test("comparing noncopyables") {
4349
expectTrue(isNotSame(a,b))
4450
}
4551

52+
@available(SwiftStdlib 6.2, *)
53+
extension InlineArray where Element: Comparable & ~Copyable {
54+
func minIndex() -> Int? {
55+
indices.min { self[$0] < self[$1] }
56+
}
57+
}
58+
59+
NoncopyableEquatableTests.test("comparing noncopyables") {
60+
61+
guard #available(SwiftStdlib 6.2, *) else { return }
62+
63+
let a = Noncopyable(i: 1)
64+
let b = Noncopyable(i: 2)
65+
let c = Noncopyable(i: 0)
66+
67+
expectTrue(a > c)
68+
expectFalse(a <= c)
69+
70+
let array: [3 of Noncopyable] = [a,b,c]
71+
expectTrue(array.minIndex() == 2)
72+
}
73+
4674
runAllTests()

test/stdlib/StringDiagnostics.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,18 @@ func testAmbiguousStringComparisons(s: String) {
3434
let nsString = s as NSString
3535
let a1 = s as NSString == nsString
3636
let a2 = s as NSString != nsString
37-
let a3 = s < nsString // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{24-24= as String}}
37+
let a3 = s < nsString
38+
// expected-error@-1{{binary operator '<' cannot be applied to operands of type 'String' and 'NSString'}}
39+
// expected-note@-2{{overloads for '<' exist with these partially matching parameter lists: (String, String)}}
3840
let a4 = s <= nsString // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{25-25= as String}}
3941
let a5 = s >= nsString // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{25-25= as String}}
4042
let a6 = s > nsString // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{24-24= as String}}
4143
// now the other way
4244
let a7 = nsString == s as NSString
4345
let a8 = nsString != s as NSString
44-
let a9 = nsString < s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{20-20= as String}}
46+
let a9 = nsString < s
47+
// expected-error@-1{{binary operator '<' cannot be applied to operands of type 'NSString' and 'String'}}
48+
// expected-note@-2{{overloads for '<' exist with these partially matching parameter lists: (String, String)}}
4549
let a10 = nsString <= s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}
4650
let a11 = nsString >= s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}
4751
let a12 = nsString > s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}

0 commit comments

Comments
 (0)