Typealias overriding associated type not, in fact, better expressed as same-type constraint

Code:
https://gist.github.com/GeorgeLyon/d713e730924cb55f285b53903f67882f

In the example, I use use a typealias to override an associated type instead of a type constraint. It allows me to omit the typealias in the concrete type conforming to the protocol (the last declaration). If I use a same-type constraint as the warning suggests, then I have to explicitly declare the typealias in the concrete type, otherwise the compiler will complain that SpecificEndpoint doesn't implement StandardEndpoint.

  1. I think this is a valid use-case, am I missing anything?
  2. If it is, indeed, a valid use-case, is there anything I can do to silence the warning?
  3. Should the compiler infer the typealias when using a same-type constraint?

What you want is expressible in two ways:

protocol P { associatedtype A }

protocol P1: P {  // first example
    associatedtype A = Int
}  
// or
protocol P1: P where A == Int {...} // second example

You won't have to explicitly declare A in conforming types.

However, the first example is a defaulting act – A is Int by default, but you can yet override it with a different type when conforming to a type:

class Foo: P1 {
    typealias A = Bool
}

or default it to a different type when refining a protocol it inherits from:

protocol P2: P1 {
    associatedtype A = String
}

The second example is an act of refining semantics (a same-type constraint), similar to how a read-only requirement inherited by a protocol can be redefined to be { get set }. Semantic refinements are irreversible (you can't revert the refinement in an inheriting protocol). A will be further constrained to Int. It is almost the same as using typealias A = Int.

However, even though a same-type constraint is supposed to define A once and for all, at present you can still default A to another type in an inheriting protocol. This seems to be a relatively serious semantic bug, since a second same-type constraint will naturally not be allowed by the compiler anywhere A appears down the hierarchy. SR-7336

2 Likes

Ah, thank you. I wasn't aware of these semantics.

P.S.

By doing this

protocol P { associatedtype A }

protocol P1: P {
   func foo(_ arg: A)
}

extension P1 {
   typealias A = Int
}

You are either overriding or shadowing A. In foo(_ arg: A), A will now be Int. This shouldn't be allowed and shadows the whole point of having an associated type and, moreover, is source breaking through retroactive extensions. In other words, it's a bug. Thanks for bringing up this topic!

Doesn’t this syntax only specify a default for the associatedtype?

Yes, in a sense. Why do you ask?

Nothing, I completed misread the topic :sweat_smile: sorry

1 Like

Thanks by the way, I see what you meant. I might have slightly mislead the author of this topic – corrected my answer. @George