typealias-assignment in protocol-associated-type-declaration grammar... a mistake??

Swift 2 Programming Language (Swift 2 Prerelease) rev. 2015-06-08 > Language Reference > Protocol Associated Type Declaration

GRAMMAR OF A PROTOCOL ASSOCIATED TYPE DECLARATION

protocol-associated-type-declaration → typealias-headtype-inheritance-clause (opt) typealias-assignment (opt)

I'm leaning towards believing that the inclusion of typealias-assignment (opt) in this grammar production must have been a mistake - if not, can anybody give an example of how this might reasonably be used?

I don't think it's a bug, but the combination of a subtyping constraint and a type assignment is strange because the subtyping part (type-inheritance-clause_opt) is superfluous in this case.


Here's some code showing the various alternatives. Type alias assignments are most useful to instantiate abstract associated types.


protocol Buffer {
  typealias Element
  var value: Element { get }
}
protocol EquatableBuffer: Buffer, Equatable {  // Constraining Element type
  typealias Element: Equatable
}
protocol IntBuffer: Buffer {  // Instantiating Element type
  typealias Element = Int
}
protocol SuperfluousIntBuffer: Buffer, Equatable {  // Not sure about the usefulness of this
  typealias Element: Equatable = Int
}

"Type alias assignments are most useful to instantiate abstract associated types." <- I don't believe this is true. 😕


where you gave:


protocol Buffer { 
  typealias Element 
  var value: Element { get } 
} 

protocol IntBuffer: Buffer {  // Instantiating Element type 
  typealias Element = Int 
}


...the typealias assignment in IntBuffer is meaningless, and in conforming to IntBuffer I'm still required to assign the typealias in my conforming type.

Yes, this is correct. The assignment provides a default for the associated type requirement if the conforming type doesn't provide a type explicitly.


protocol A {
typealias Assoc = Int
}

struct X : A {}

print(X.Assoc())

(oops - edited code example, was not initially complete)


...this is interesting that the protocol typealias assignment can be used in this way (and maybe that's how it's meant to be used?)


but no, it does not as you state "provide a default for the associated type requirement if the conforming type doesn't provide a type explicitly" <- if this were true, then the following would work (which it doesn't):


protocol A {
  typealias Assoc = Int
  func returnSuccessor(someInt: Assoc) -> Assoc
}

struct X : A {
  func returnSuccessor(someInt: Assoc) -> Assoc { // Use of undeclared type 'Assoc'
    return someInt.successor()
  }
}

I consider this to be a bug in the current implementation. My understanding of associated type aliases is that it allows you to do things like this:


protocol Buffer {
  typealias Element
  var value: Element { get set }
}
protocol IntBuffer: Buffer {
  typealias Element = Int
}
func plusOne(buffer: IntBuffer) -> Int {
  return buffer.value + 1
}


Since protocols with abstract associated type members can't be used as types, this is the only way to turn (a specialization of) Buffer into a type. Otherwise, you would always have to write generic code like below, even in cases where this is total overkill:


func plusOne<A: Buffer where A.Element == Int>(buffer: A) -> Int {
  return buffer.value + 1
}
Accepted Answer

You cannot use associated types directly in an actual implementation of protocol, even if they have defaults.

(Such limitations are unclear and should be documented.)


But this works:

protocol A {
    typealias Assoc: ForwardIndexType = Int
    func returnSuccessor(someInt: Assoc) -> Assoc
}
extension A {
    func returnSuccessor(someInt: Assoc) -> Assoc {
        return someInt.successor()
    }
}
struct X: A {}
print(X.Assoc.self) //->Swift.Int

Ultimately this comment led to the understanding that I was seeking - thank you!

typealias-assignment in protocol-associated-type-declaration grammar... a mistake??
 
 
Q