Type understanding

The other situation you might call an "inexact match" is when the witness is more generic than the requirement. The specific condition where it works if there's a fixed set of concrete substitutions that can apply to the witness to make it satisfy the signature of the requirement. For example:

protocol P {
  func f1(_: Int)
  func f2<T: Equatable>(_: T)
}

struct S: P {
  func f1<T>(_: T) {} // T is always Int
  func f2<T>(_: T) {} // T happens to be Equatable but it's not needed
}

The reason that we don't allow arbitrary function subtype conversions is that associated type inference relies on exact matching. Subtype conversions would introduce ambiguity that requires new forms of reasoning to sort out:

protocol P {
  associatedtype A
  func f() -> A
  func g() -> A
}

struct S: P {
  // this is the most specific type that works for both:
  // typealias A = NSObject?
  func f() -> NSString? {}
  func g() -> NSObject {}
}
1 Like