Skip to content

Commit 74f02ad

Browse files
authored
Merge pull request #11623 from CodaFi/fundef
[stdlib]Custom message for recursive Strideable witness
2 parents c3300bc + d0bc2a8 commit 74f02ad

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

stdlib/public/core/Stride.swift.gyb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
}%
2424
/// Conforming types are notionally continuous, one-dimensional
2525
/// values that can be offset and measured.
26+
///
27+
/// - Important: The `Strideable` protocol provides default implementations for
28+
/// the equal-to (`==`) and less-than (`<`) operators that depend on the
29+
/// `Stride` type's implementations. If a type conforming to `Strideable`
30+
/// is its own `Stride` type, it must provide concrete implementations of
31+
/// the two operators to avoid infinite recursion.
2632
public protocol ${Self} : ${Conformance} {
2733
% if Self == '_Strideable':
2834
/// A type that represents the distance between two values of `Self`.
@@ -55,6 +61,24 @@ public protocol ${Self} : ${Conformance} {
5561

5662
% end
5763

64+
extension Strideable where Stride == Self {
65+
@available(*, deprecated, message: "Strideable conformance where 'Stride == Self' requires user-defined implementation of the '<' operator")
66+
public static func < (x: Self, y: Self) -> Bool {
67+
fatalError("""
68+
Strideable conformance where 'Stride == Self' requires user-defined \
69+
implementation of the '<' operator
70+
""")
71+
}
72+
73+
@available(*, deprecated, message: "Strideable conformance where 'Stride == Self' requires user-defined implementation of the '==' operator")
74+
public static func == (x: Self, y: Self) -> Bool {
75+
fatalError("""
76+
Strideable conformance where 'Stride == Self' requires user-defined \
77+
implementation of the '==' operator
78+
""")
79+
}
80+
}
81+
5882
extension Strideable {
5983
@_inlineable
6084
public static func < (x: Self, y: Self) -> Bool {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -emit-executable -DTEST_EQUATABLE -o %t/InvalidStrideableEq %s
3+
// RUN: ! %target-run %t/InvalidStrideableEq 2>&1 | %FileCheck %s --check-prefix=CHECK-EQUATABLE
4+
// RUN: %target-build-swift -emit-executable -DTEST_COMPARABLE -o %t/InvalidStrideableCmp %s
5+
// RUN: ! %target-run %t/InvalidStrideableCmp 2>&1 | %FileCheck %s --check-prefix=CHECK-COMPARABLE
6+
// REQUIRES: executable_test
7+
8+
//
9+
// Check that a circular Strideable inheriting witnesses from Stdlib crashes
10+
// with a rich error message.
11+
//
12+
13+
struct InvalidStrideable : Strideable, SignedNumeric {
14+
typealias Magnitude = InvalidStrideable
15+
init?<T>(exactly: T) where T : BinaryInteger { return nil }
16+
var magnitude: InvalidStrideable { return self }
17+
18+
static func += (lhs: inout InvalidStrideable, rhs: InvalidStrideable) { }
19+
static func -= (lhs: inout InvalidStrideable, rhs: InvalidStrideable) { }
20+
static func *= (lhs: inout InvalidStrideable, rhs: InvalidStrideable) { }
21+
22+
static func + (lhs: InvalidStrideable, rhs: InvalidStrideable) -> InvalidStrideable { return rhs }
23+
static func - (lhs: InvalidStrideable, rhs: InvalidStrideable) -> InvalidStrideable { return rhs }
24+
static func * (lhs: InvalidStrideable, rhs: InvalidStrideable) -> InvalidStrideable { return rhs }
25+
26+
typealias IntegerLiteralType = Int
27+
init(integerLiteral : Int) {}
28+
29+
typealias Stride = InvalidStrideable
30+
31+
init() {}
32+
33+
func distance(to rhs: InvalidStrideable) -> InvalidStrideable { return self }
34+
func advanced(by n: InvalidStrideable) -> InvalidStrideable { return self }
35+
}
36+
37+
#if TEST_EQUATABLE
38+
// CHECK-EQUATABLE: fatal error: Strideable conformance where 'Stride == Self' requires user-defined implementation of the '==' operator
39+
_ = InvalidStrideable() == InvalidStrideable()
40+
#else
41+
// CHECK-COMPARABLE: fatal error: Strideable conformance where 'Stride == Self' requires user-defined implementation of the '<' operator
42+
_ = InvalidStrideable() < InvalidStrideable() // Will trap with error message
43+
#endif

0 commit comments

Comments
 (0)