Skip to content

Instantly share code, notes, and snippets.

@uliwitness
Created May 6, 2019 14:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save uliwitness/d17abaf383538ec40a5f0936ee6d5836 to your computer and use it in GitHub Desktop.
Save uliwitness/d17abaf383538ec40a5f0936ee6d5836 to your computer and use it in GitHub Desktop.
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
Copy link
Author

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

@uliwitness
Copy link
Author

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
Copy link

langford 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