Associatedtype not inferred?

On Xcode13beta3, BigSur 11.5:

protocol MyProtocol {
    associatedtype T: SignedNumeric & Comparable
    
    var prop: T { get }
    func myMax(x: T, y: T) -> T
    func myAbs(x: T) -> T
}

struct MyStruct: MyProtocol {    
    var prop: Int
    func myMax(x: T, y: T) -> T { x < y ? y : x }
    func myAbs(x: T) -> T { x < 0 ? -x : x }
}

for myAbs(x:) Xcode first complains of the return T, "Reference to invalid associated type 'T' of type 'MyStruct'". If I change the return T to Int and cast the return value to Int, then it makes the same complain about the parameter type T.

Two workarounds:

  1. Change both Ts in myAbs(x:) to Int:
struct MyStruct: MyProtocol {    
    var prop: Int
    func myMax(x: T, y: T) -> T { x < y ? y : x }
    func myAbs(x: Int) -> Int { x < 0 ? -x : x }
}

or

  1. add typealias T = Int in MyStruct:
struct MyStruct: MyProtocol { 
    typealias T = Int
    var prop: T
    func myMax(x: T, y: T) -> T { x < y ? y : x }
    func myAbs(x: T) -> T { x < 0 ? -x : x }
}

My question is whether it is expected behavior that the two Ts in myAbs(x:) cannot be inferred or am I doing something wrong?

Also, if I swap the ordering of myAbs(x:) and myMax(x:y:) in MyStruct, Xcode happily accepts myAbs(x:) and complains about the Ts in myMax(x:y:) instead.

Of the five threads this topic is similar to, three asked about why an associatedtype inference succeeded, one was a pitch to remove associatedtype inference, only one asked about associatedtype not inferred. My case seems to be much simpler than the one reported in the last thread.

Thanks.

This looks like a bug, and it's in Xcode 12.5.1 (12E507) too, ie:

protocol P {
  associatedtype T
  var p: T { get }
  func foo(x: T)
  func bar(x: T)
}

struct S: P {
  var p: Int
  func foo(x: T) {}
  func bar(x: T) {} // ERROR: Reference to invalid associated type 'T' of type 'S'
}

Here's a variation without a property, which compiles with two methods, but not with three:

protocol P {
  associatedtype T
  func foo(x: T)
  func bar(x: T)
  func baz(x: T)
}

struct S: P {
  func foo(x: Int) {}
  func bar(x: T) {}
  func baz(x: T) {} // ERROR: Reference to invalid associated type 'T' of type 'S'
}
1 Like

Thanks for looking into it.

Apparently even with one method it won't compile if the method returns T:

protocol P {
  associatedtype T
  func foo(x: T) -> T
}

struct S: P {
  func foo(x: Int) -> T { return 0 } // ERROR: Reference to invalid associated type 'T' of type 'S'
}
1 Like

Filed SR-15027