Why do generic constraints not work for literals here?

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!

  1. The let c = b/a fails, let c=1/2 fails–defined in the struct,
  2. The let c = b/a succeeds, let c=1/2 fails–defined as a constrained extension, or
  3. 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/

I just ran into this yesterday and was still puzzled. Thank you for the information.