mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Strideable declares a default witness for Equatable and Comparable
extension Strideable {
@_inlineable
public static func < (x: Self, y: Self) -> Bool {
return x.distance(to: y) > 0
}
@_inlineable
public static func == (x: Self, y: Self) -> Bool {
return x.distance(to: y) == 0
}
}
This witness is implemented recursively because the expectation
is that Stride != Self. However, it is possible to implement
SignedNumeric and Strideable together and inherit this conformance
which will cause undefined behavior - usually a crash.
Provide an overload when Stride == Self and crash with custom message
that mentions that Equatable and Comparable have to be implemented
in this case.
- It's better than nothing.
44 lines
2.0 KiB
Swift
44 lines
2.0 KiB
Swift
// RUN: %empty-directory(%t)
|
|
// RUN: %target-build-swift -emit-executable -DTEST_EQUATABLE -o %t/InvalidStrideableEq %s
|
|
// RUN: ! %target-run %t/InvalidStrideableEq 2>&1 | %FileCheck %s --check-prefix=CHECK-EQUATABLE
|
|
// RUN: %target-build-swift -emit-executable -DTEST_COMPARABLE -o %t/InvalidStrideableCmp %s
|
|
// RUN: ! %target-run %t/InvalidStrideableCmp 2>&1 | %FileCheck %s --check-prefix=CHECK-COMPARABLE
|
|
// REQUIRES: executable_test
|
|
|
|
//
|
|
// Check that a circular Strideable inheriting witnesses from Stdlib crashes
|
|
// with a rich error message.
|
|
//
|
|
|
|
struct InvalidStrideable : Strideable, SignedNumeric {
|
|
typealias Magnitude = InvalidStrideable
|
|
init?<T>(exactly: T) where T : BinaryInteger { return nil }
|
|
var magnitude: InvalidStrideable { return self }
|
|
|
|
static func += (lhs: inout InvalidStrideable, rhs: InvalidStrideable) { }
|
|
static func -= (lhs: inout InvalidStrideable, rhs: InvalidStrideable) { }
|
|
static func *= (lhs: inout InvalidStrideable, rhs: InvalidStrideable) { }
|
|
|
|
static func + (lhs: InvalidStrideable, rhs: InvalidStrideable) -> InvalidStrideable { return rhs }
|
|
static func - (lhs: InvalidStrideable, rhs: InvalidStrideable) -> InvalidStrideable { return rhs }
|
|
static func * (lhs: InvalidStrideable, rhs: InvalidStrideable) -> InvalidStrideable { return rhs }
|
|
|
|
typealias IntegerLiteralType = Int
|
|
init(integerLiteral : Int) {}
|
|
|
|
typealias Stride = InvalidStrideable
|
|
|
|
init() {}
|
|
|
|
func distance(to rhs: InvalidStrideable) -> InvalidStrideable { return self }
|
|
func advanced(by n: InvalidStrideable) -> InvalidStrideable { return self }
|
|
}
|
|
|
|
#if TEST_EQUATABLE
|
|
// CHECK-EQUATABLE: fatal error: Strideable conformance where 'Stride == Self' requires user-defined implementation of the '==' operator
|
|
_ = InvalidStrideable() == InvalidStrideable()
|
|
#else
|
|
// CHECK-COMPARABLE: fatal error: Strideable conformance where 'Stride == Self' requires user-defined implementation of the '<' operator
|
|
_ = InvalidStrideable() < InvalidStrideable() // Will trap with error message
|
|
#endif
|