Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
writertest.swift:18:8: error: cannot invoke 'write' with an argument list of type '(T)'
impl.write(foo)
^
writertest.swift:18:8: note: expected an argument list of type '(T.WriterImplType.ValueType)'
impl.write(foo)
^
// Abstract base class for values that can be written:
protocol Value {
associatedtype WriterImplType: WriterImpl
}
// One concrete kind of value (e.g. a string):
class MyValue: Value {
typealias WriterImplType = MyWriterImpl
}
// Generic class for writing values of a certain type:
class Writer<T: Value> {
typealias WriterImplType = T.WriterImplType
let impl: WriterImplType = WriterImplType()
func write(_ foo: T) {
impl.write(foo)
}
}
// Abstract base class that actually does the writing of a given type for Writer:
protocol WriterImpl {
associatedtype ValueType: Value
init()
func write(_ foo: ValueType)
}
// Concrete writer subclass that Writer can call upon to write MyValue-type values:
class MyWriterImpl: WriterImpl {
typealias ValueType = MyValue
required init() {}
func write(_ foo: ValueType) {
}
}
// Create a value and tell the writer to write it:
let value = MyValue()
let writer = Writer<MyValue>()
writer.write(value)
@uliwitness

This comment has been minimized.

Copy link
Owner Author

commented May 6, 2019

Shouldn't T and T.MyWriterImpl.ValueType be the same type in this case? Why is Swift unhappy?

@uliwitness

This comment has been minimized.

Copy link
Owner Author

commented May 6, 2019

Hmm… changing to class Writer<T: Value> where T == T.WriterImplType.ValueType { makes this simplified example compile, but in my actual code, it then complains everywhere Writer is used that 'Writer' requires the types 'T' and 'T.WriterImplType.ValueType' be equivalent ... it doesn't tell me how they are not equivalent, though :/

@langford

This comment has been minimized.

Copy link

commented May 6, 2019

Does this work for you? It seems like it may avoid the error you're getting throughout your codebase from appearing.

protocol WritableValue{
  associatedtype WriterImplType:WriterImpl
}

protocol WriterImpl{
  func write<T:WritableValue>(_ value: T) where T.WriterImplType == Self
  init()
}

class MyValue: WritableValue{
  typealias WriterImplType = MyWriterImpl
}

// Generic class for writing values of a certain type:
class GenericWriter<T: WritableValue> {
  typealias WriterImplType = T.WriterImplType

  let impl: WriterImplType = WriterImplType()

  func write<T:WritableValue>(_ value: T) where T.WriterImplType == WriterImplType {
    impl.write(value)
  }
}

class MyWriterImpl: WriterImpl {

  func write< T : WritableValue>(_ value: T) where T.WriterImplType : MyWriterImpl {
    print("The Write:\(value)")
  }
  typealias ValueType = MyValue

  required init() {}

}

// Create a value and tell the writer to write it:
let value = MyValue()
let writer = GenericWriter<MyValue>()
writer.write(value)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.