ylorn
1
I was trying to provide different implementations for a struct if its generic type is satisfied with different conditions.
Here is a demo example to illustrate my problem:
public protocol FooProtocol {
/// `Bar` is my own type, using `String` here for demo purpose
typealias Bar = String
func to() -> [Bar]
init?<C: Collection>(collection: C) where C == C.SubSequence, C.Element == Bar
}
public struct Foo<Value> {
let value: Value
}
extension Foo: FooProtocol where Value: Numeric {
public func to() -> [Bar] {
return ["\(self.value)"]
}
public init?<C: Collection>(collection: C) where C == C.SubSequence, C.Element == Bar {
return nil
}
}
extension Foo where Value: RangeReplaceableCollection, Value.Element: FooProtocol {
public func to() -> [Bar] {
return self.value.reduce(into: []) { $0 += $1.to() }
}
public init?<C: Collection>(collection: C) where C == C.SubSequence, C.Element == Bar {
self.value = .init()
}
}
And when I do following:
let intFoo: Foo<Int> = .init(value: .max) /// give me instance of Foo<Int>
let intTo = intFoo.to() /// give me value of ["9223372036854775807"]
let intBack = Foo<Int>(collection: intTo)?.value
/// Should give me `nil`, however...
/// error: expression type 'Foo<Int>?' is ambiguous without more context
So why is the ambiguity? The generic type is Int, which means it should use the initializer in the first extension where the Value is a Numeric, unless the Int is actually a RangeReplaceableCollection at the same time?
Here's what I get on master:
/Users/suyashsrijan/Desktop/test.swift:34:15: error: initializer 'init(collection:)' requires the types '[String]' and 'ArraySlice<String>' be equivalent
let intBack = Foo<Int>(collection: intTo)?.value
^
/Users/suyashsrijan/Desktop/test.swift:17:12: note: where 'C' = '[String]', 'C.SubSequence' = 'ArraySlice<String>'
public init?<C: Collection>(collection: C) where C == C.SubSequence, C.Element == Bar {
1 Like
ylorn
3
Thanks a lot!!
Seems removing that C == C.SubSequence constraint is the fix.
But I do think Collection needs that constraint to perform func removeFirst(_:), and Array has that function, so why is Array’s SubSequence not equal to itself?
ylorn
4
OK.... it seems Array has its own implementation of that function.