mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Allow Comparable: ~Copyable (#85747)
Builds on #85746 which covers Equatable
This commit is contained in:
@@ -135,7 +135,7 @@
|
||||
/// (`FloatingPoint.nan`) compares as neither less than, greater than, nor
|
||||
/// equal to any normal floating-point value. Exceptional values need not
|
||||
/// take part in the strict total order.
|
||||
public protocol Comparable: Equatable {
|
||||
public protocol Comparable: Equatable, ~Copyable {
|
||||
/// Returns a Boolean value indicating whether the value of the first
|
||||
/// argument is less than that of the second argument.
|
||||
///
|
||||
@@ -146,7 +146,7 @@ public protocol Comparable: Equatable {
|
||||
/// - Parameters:
|
||||
/// - lhs: A value to compare.
|
||||
/// - rhs: Another value to compare.
|
||||
static func < (lhs: Self, rhs: Self) -> Bool
|
||||
static func < (lhs: borrowing Self, rhs: borrowing Self) -> Bool
|
||||
|
||||
/// Returns a Boolean value indicating whether the value of the first
|
||||
/// argument is less than or equal to that of the second argument.
|
||||
@@ -154,7 +154,7 @@ public protocol Comparable: Equatable {
|
||||
/// - Parameters:
|
||||
/// - lhs: A value to compare.
|
||||
/// - rhs: Another value to compare.
|
||||
static func <= (lhs: Self, rhs: Self) -> Bool
|
||||
static func <= (lhs: borrowing Self, rhs: borrowing Self) -> Bool
|
||||
|
||||
/// Returns a Boolean value indicating whether the value of the first
|
||||
/// argument is greater than or equal to that of the second argument.
|
||||
@@ -162,7 +162,7 @@ public protocol Comparable: Equatable {
|
||||
/// - Parameters:
|
||||
/// - lhs: A value to compare.
|
||||
/// - rhs: Another value to compare.
|
||||
static func >= (lhs: Self, rhs: Self) -> Bool
|
||||
static func >= (lhs: borrowing Self, rhs: borrowing Self) -> Bool
|
||||
|
||||
/// Returns a Boolean value indicating whether the value of the first
|
||||
/// argument is greater than that of the second argument.
|
||||
@@ -170,10 +170,10 @@ public protocol Comparable: Equatable {
|
||||
/// - Parameters:
|
||||
/// - lhs: A value to compare.
|
||||
/// - rhs: Another value to compare.
|
||||
static func > (lhs: Self, rhs: Self) -> Bool
|
||||
static func > (lhs: borrowing Self, rhs: borrowing Self) -> Bool
|
||||
}
|
||||
|
||||
extension Comparable {
|
||||
extension Comparable where Self: ~Copyable {
|
||||
/// Returns a Boolean value indicating whether the value of the first argument
|
||||
/// is greater than that of the second argument.
|
||||
///
|
||||
@@ -184,7 +184,8 @@ extension Comparable {
|
||||
/// - lhs: A value to compare.
|
||||
/// - rhs: Another value to compare.
|
||||
@inlinable
|
||||
public static func > (lhs: Self, rhs: Self) -> Bool {
|
||||
@_preInverseGenerics
|
||||
public static func > (lhs: borrowing Self, rhs: borrowing Self) -> Bool {
|
||||
return rhs < lhs
|
||||
}
|
||||
|
||||
@@ -198,7 +199,8 @@ extension Comparable {
|
||||
/// - lhs: A value to compare.
|
||||
/// - rhs: Another value to compare.
|
||||
@inlinable
|
||||
public static func <= (lhs: Self, rhs: Self) -> Bool {
|
||||
@_preInverseGenerics
|
||||
public static func <= (lhs: borrowing Self, rhs: borrowing Self) -> Bool {
|
||||
return !(rhs < lhs)
|
||||
}
|
||||
|
||||
@@ -214,7 +216,8 @@ extension Comparable {
|
||||
/// - Returns: `true` if `lhs` is greater than or equal to `rhs`; otherwise,
|
||||
/// `false`.
|
||||
@inlinable
|
||||
public static func >= (lhs: Self, rhs: Self) -> Bool {
|
||||
@_preInverseGenerics
|
||||
public static func >= (lhs: borrowing Self, rhs: borrowing Self) -> Bool {
|
||||
return !(lhs < rhs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1472,14 +1472,12 @@ func testUnwrapFixIts(x: Int?) throws {
|
||||
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{11-11=!}}
|
||||
foo(y: x ?? 0)
|
||||
|
||||
let _ = x < 2 // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
|
||||
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{12-12= ?? <#default value#>}}
|
||||
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{12-12=!}}
|
||||
let _ = x < 2 // expected-error {{binary operator '<' cannot be applied to operands of type 'Int?' and 'Int'}}
|
||||
// expected-note@-1 {{overloads for '<' exist with these partially matching parameter lists: (Int, Int)}}
|
||||
let _ = x ?? 0 < 2
|
||||
|
||||
let _ = 2 < x // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
|
||||
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{16-16= ?? <#default value#>}}
|
||||
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{16-16=!}}
|
||||
let _ = 2 < x // expected-error {{binary operator '<' cannot be applied to operands of type 'Int' and 'Int?'}}
|
||||
// expected-note@-1 {{overloads for '<' exist with these partially matching parameter lists: (Int, Int)}}
|
||||
let _ = 2 < x ?? 0
|
||||
|
||||
let _: Int = (.optionalIntMember) // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
|
||||
@@ -1497,9 +1495,8 @@ func testUnwrapFixIts(x: Int?) throws {
|
||||
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{36-36=!}}
|
||||
let _ = try (.optionalThrowsMember ?? 0) + 1
|
||||
|
||||
let _ = .optionalIntMember?.bitWidth > 0 // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
|
||||
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{39-39= ?? <#default value#>}}
|
||||
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{11-11=(}} {{39-39=)!}}
|
||||
let _ = .optionalIntMember?.bitWidth > 0 // expected-error {{binary operator '>' cannot be applied to operands of type 'Int?' and 'Int'}}
|
||||
// expected-note@-1 {{overloads for '>' exist with these partially matching parameter lists: (Int, Int)}}
|
||||
let _ = (.optionalIntMember?.bitWidth)! > 0
|
||||
let _ = .optionalIntMember?.bitWidth ?? 0 > 0
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ bb0:
|
||||
sil [no_allocation] [ossa] @deserialize_and_inline_after_devirtualize : $@convention(thin) (@in Int) -> () {
|
||||
bb0(%0 : $*Int):
|
||||
%1 = metatype $@thick Int.Type
|
||||
%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
|
||||
%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
|
||||
%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
|
||||
%4 = tuple()
|
||||
return %4 : $()
|
||||
@@ -124,7 +124,7 @@ bb0(%0 : $*Int, %1 : $*Int, %2 : $@thick Int.Type):
|
||||
|
||||
sil_witness_table public_external [serialized] Int: Comparable module Swift {
|
||||
base_protocol Equatable: Int: Equatable module Swift
|
||||
method #Comparable."<": <Self where Self : Comparable> (Self.Type) -> (Self, Self) -> Bool : @$sSiSLsSL1loiySbx_xtFZTW
|
||||
method #Comparable."<": <Self where Self : Comparable, Self : ~Copyable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool : @$sSiSLsSL1loiySbx_xtFZTW
|
||||
}
|
||||
|
||||
sil [ossa] @get_int_value : $@convention(thin) () -> Int32 {
|
||||
|
||||
@@ -71,7 +71,6 @@ Protocol CodingKey has added inherited protocol Copyable
|
||||
Protocol CodingKey has added inherited protocol Escapable
|
||||
Protocol Collection has added inherited protocol Copyable
|
||||
Protocol Collection has added inherited protocol Escapable
|
||||
Protocol Comparable has added inherited protocol Copyable
|
||||
Protocol Comparable has added inherited protocol Escapable
|
||||
Protocol CustomDebugStringConvertible has added inherited protocol Copyable
|
||||
Protocol CustomDebugStringConvertible has added inherited protocol Escapable
|
||||
@@ -387,3 +386,18 @@ Func Equatable.==(_:_:) has generic signature change from <Self where Self : Swi
|
||||
Func Equatable.==(_:_:) has parameter 0 changing from Default to Shared
|
||||
Func Equatable.==(_:_:) has parameter 1 changing from Default to Shared
|
||||
|
||||
// Comparable: ~Copyable
|
||||
Protocol Comparable has generic signature change from <Self : Swift.Equatable> to <Self : Swift.Equatable, Self : ~Copyable>
|
||||
Func Comparable.<(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
|
||||
Func Comparable.<(_:_:) has parameter 0 changing from Default to Shared
|
||||
Func Comparable.<(_:_:) has parameter 1 changing from Default to Shared
|
||||
Func Comparable.<=(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
|
||||
Func Comparable.<=(_:_:) has parameter 0 changing from Default to Shared
|
||||
Func Comparable.<=(_:_:) has parameter 1 changing from Default to Shared
|
||||
Func Comparable.>(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
|
||||
Func Comparable.>(_:_:) has parameter 0 changing from Default to Shared
|
||||
Func Comparable.>(_:_:) has parameter 1 changing from Default to Shared
|
||||
Func Comparable.>=(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
|
||||
Func Comparable.>=(_:_:) has parameter 0 changing from Default to Shared
|
||||
Func Comparable.>=(_:_:) has parameter 1 changing from Default to Shared
|
||||
|
||||
|
||||
@@ -189,7 +189,6 @@ Protocol CodingKey has added inherited protocol Copyable
|
||||
Protocol CodingKey has added inherited protocol Escapable
|
||||
Protocol Collection has added inherited protocol Copyable
|
||||
Protocol Collection has added inherited protocol Escapable
|
||||
Protocol Comparable has added inherited protocol Copyable
|
||||
Protocol Comparable has added inherited protocol Escapable
|
||||
Protocol CustomDebugStringConvertible has added inherited protocol Copyable
|
||||
Protocol CustomDebugStringConvertible has added inherited protocol Escapable
|
||||
@@ -892,4 +891,26 @@ Func Equatable.==(_:_:) has generic signature change from <Self where Self : Swi
|
||||
Func Equatable.==(_:_:) has parameter 0 changing from Default to Shared
|
||||
Func Equatable.==(_:_:) has parameter 1 changing from Default to Shared
|
||||
|
||||
// Comparable: ~Copyable
|
||||
Protocol Comparable has generic signature change from <Self : Swift.Equatable> to <Self : Swift.Equatable, Self : ~Copyable>
|
||||
Func Comparable.<(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
|
||||
Func Comparable.<(_:_:) has parameter 0 changing from Default to Shared
|
||||
Func Comparable.<(_:_:) has parameter 1 changing from Default to Shared
|
||||
Func Comparable.<=(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
|
||||
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'
|
||||
Func Comparable.<=(_:_:) has parameter 0 changing from Default to Shared
|
||||
Func Comparable.<=(_:_:) has parameter 1 changing from Default to Shared
|
||||
Func Comparable.<=(_:_:) is now with @_preInverseGenerics
|
||||
Func Comparable.>(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
|
||||
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'
|
||||
Func Comparable.>(_:_:) has parameter 0 changing from Default to Shared
|
||||
Func Comparable.>(_:_:) has parameter 1 changing from Default to Shared
|
||||
Func Comparable.>(_:_:) is now with @_preInverseGenerics
|
||||
Func Comparable.>=(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
|
||||
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'
|
||||
Func Comparable.>=(_:_:) has parameter 0 changing from Default to Shared
|
||||
Func Comparable.>=(_:_:) has parameter 1 changing from Default to Shared
|
||||
Func Comparable.>=(_:_:) is now with @_preInverseGenerics
|
||||
|
||||
|
||||
// *** DO NOT DISABLE OR XFAIL THIS TEST. *** (See comment above.)
|
||||
|
||||
85
test/stdlib/NoncopyableComparable.swift
Normal file
85
test/stdlib/NoncopyableComparable.swift
Normal file
@@ -0,0 +1,85 @@
|
||||
//===--- NoncopyableComparable.swift - tests for Comparable: ~Copyable -------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// RUN: %target-run-simple-swift
|
||||
// REQUIRES: executable_test
|
||||
|
||||
import StdlibUnittest
|
||||
|
||||
let NoncopyableComparableTests = TestSuite("NoncopyableComparable")
|
||||
|
||||
struct Noncopyable<Wrapped: ~Copyable>: ~Copyable {
|
||||
var wrapped: Wrapped
|
||||
}
|
||||
|
||||
extension Noncopyable: Equatable where Wrapped: Equatable & ~Copyable { }
|
||||
|
||||
extension Noncopyable: Comparable where Wrapped: Comparable & ~Copyable {
|
||||
static func < (lhs: borrowing Self, rhs: borrowing Self) -> Bool { lhs.wrapped < rhs.wrapped }
|
||||
}
|
||||
|
||||
extension Comparable where Self: ~Copyable {
|
||||
func isLessThan(_ other: borrowing Self) -> Bool {
|
||||
self < other
|
||||
}
|
||||
}
|
||||
|
||||
func isLessOrEqual<T: Comparable & ~Copyable>(_ lhs: borrowing T, _ rhs: borrowing T) -> Bool {
|
||||
lhs <= rhs
|
||||
}
|
||||
|
||||
@available(SwiftStdlib 6.2, *)
|
||||
extension InlineArray where Element: Comparable & ~Copyable {
|
||||
func minIndex() -> Int? {
|
||||
indices.min { self[$0] < self[$1] }
|
||||
}
|
||||
|
||||
func inReverseOrder() -> Bool {
|
||||
for i in indices.dropFirst() {
|
||||
if self[i] > self[i-1] { return false }
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
NoncopyableComparableTests.test("comparing noncopyables") {
|
||||
let a = Noncopyable(wrapped: 0)
|
||||
let b = Noncopyable(wrapped: 1)
|
||||
let c = Noncopyable(wrapped: 2)
|
||||
|
||||
expectTrue(a < b)
|
||||
expectTrue(c > a)
|
||||
expectFalse(a < a)
|
||||
expectFalse(a > c)
|
||||
expectFalse(c <= a)
|
||||
expectTrue(a <= a)
|
||||
expectTrue(a < b && b < c)
|
||||
|
||||
expectTrue(a.isLessThan(b))
|
||||
expectTrue(isLessOrEqual(a,b))
|
||||
expectFalse(b.isLessThan(a))
|
||||
|
||||
let nc2 = Noncopyable(wrapped: Noncopyable(wrapped: "1"))
|
||||
expectFalse(nc2 < nc2)
|
||||
expectFalse(nc2 > nc2)
|
||||
expectTrue(nc2 >= nc2)
|
||||
expectTrue(nc2 < .init(wrapped: .init(wrapped: "2")))
|
||||
|
||||
guard #available(SwiftStdlib 6.2, *) else { return }
|
||||
|
||||
var array: [3 of Noncopyable] = [c,b,a]
|
||||
expectTrue(array.minIndex() == 2)
|
||||
expectTrue(array.inReverseOrder())
|
||||
array.swapAt(1, 2)
|
||||
expectFalse(array.inReverseOrder())
|
||||
}
|
||||
|
||||
runAllTests()
|
||||
@@ -34,14 +34,18 @@ func testAmbiguousStringComparisons(s: String) {
|
||||
let nsString = s as NSString
|
||||
let a1 = s as NSString == nsString
|
||||
let a2 = s as NSString != nsString
|
||||
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}}
|
||||
let a3 = s < nsString
|
||||
// expected-error@-1{{binary operator '<' cannot be applied to operands of type 'String' and 'NSString'}}
|
||||
// expected-note@-2{{overloads for '<' exist with these partially matching parameter lists: (String, String)}}
|
||||
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}}
|
||||
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}}
|
||||
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}}
|
||||
// now the other way
|
||||
let a7 = nsString == s as NSString
|
||||
let a8 = nsString != s as NSString
|
||||
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}}
|
||||
let a9 = nsString < s
|
||||
// expected-error@-1{{binary operator '<' cannot be applied to operands of type 'NSString' and 'String'}}
|
||||
// expected-note@-2{{overloads for '<' exist with these partially matching parameter lists: (String, String)}}
|
||||
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}}
|
||||
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}}
|
||||
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}}
|
||||
|
||||
Reference in New Issue
Block a user