I have a type constraint on a generic that works fine in one context, but not another---and I don't understand why.
public struct Real<T> where T:Strideable, T.Stride == T {
public var raw : T
}
extension Real : ExpressibleByIntegerLiteral {
public init(integerLiteral value: T.IntegerLiteralType) {
self.raw = T.init(integerLiteral: value)
}
}
extension Real where T == Int {
public static func / (lhs: Real, rhs: Real) -> Double {
return Double(lhs.raw)/Double(rhs.raw)
}
}
typealias IntegerLiteralType = Real<Int>
let a = 1
let b = 2
let c = a/b // This works fine
let d = 1 / 2 // Error: ambiguous use of operator '/'
Why does let d = 1 / 2 not work? The weird thing is that if I add,
public func / (lhs: Real<Int>, rhs: Real<Int>) -> Double {
return Double(lhs.raw)/Double(rhs.raw)
}
then everything works fine. What's the distinction here?
Thanks in advance
1 Like
You're catching a bug. Likely related to “Ambiguous” operators when conditionally conforming to Numeric
This is slightly different but shows that the issue doesn't originate from conditional conformances or literals.
struct Foo<T> where T: Strideable, T.Stride == T {
var raw : T
static func / (lhs: Foo<Int>, rhs: Foo<Int>) -> Double {
return Double(lhs.raw)/Double(rhs.raw)
}
}
let a1 = Foo<Int>(raw: 1)
let b1 = Foo<Int>(raw: 1)
let c1 = a1/b1 // Expression type '(Foo<Int>, Foo<Int>) -> Double' is ambiguous without more context
The workaround is to pull out the operator to global scope.
2 Likes
Thanks!
That's a super confusing bug because there are actually three different results, depending on where you define the division operator!
- The
let c = b/a fails, let c=1/2 fails–defined in the struct,
- The
let c = b/a succeeds, let c=1/2 fails–defined as a constrained extension, or
- The
let c = b/a succeeds, let c=1/2 succeeds–defined in global scope.
I'll file a bug report.
Just in case, best to file at https://bugs.swift.org/
hooman
(Hooman Mehr)
5
I just ran into this yesterday and was still puzzled. Thank you for the information.