Is this a bug or intended behavior?
protocol P {
associatedtype X
func f() -> X
}
protocol Q: P {
func g() -> X
}
extension Q {
func f() -> X { return g() }
}
// ⚠️ Type 'A' does not conform to protocol 'P'
class A: Q {
// 'P.X' is not inferred
// typealias X = Int
func g() -> Int { return 0 }
}
You need to define the type for X
:
class A: Q {
typealias X = Int
func g() -> Int { return 0 }
}
We already defined the type in the signature of g: () -> Int
. X
should be inferred from g()
, just like f()
did.
class A: P {
// Okay
func f() -> Int { return 0 }
}
class B: Q {
// Error!
func g() -> Int { return 0 }
}
1 Like
Oh, I see.
@jrose @Slava_Pestov do you think X
should be inferred here?
Dig in further and now it more like a bug:
Redeclare (shadow?) the associated type can fix the error somehow.
public protocol CFMutableCopying {
associatedtype MutableCopyType
func mutableCopy(allocator: CFAllocator) -> MutableCopyType
}
public protocol CFMutableCopyingWithCapacity: CFMutableCopying {
// redeclare here
associatedtype MutableCopyType
func mutableCopy(allocator: CFAllocator, capacity: CFIndex) -> MutableCopyType
}
public extension CFMutableCopyingWithCapacity {
@inlinable func mutableCopy(allocator: CFAllocator) -> MutableCopyType {
return mutableCopy(allocator: allocator, capacity: 0)
}
}
extension CFString: CFMutableCopyingWithCapacity {
// Okay
@inlinable public func mutableCopy(allocator: CFAllocator, capacity: CFIndex) -> CFMutableString {
return CFStringCreateMutableCopy(allocator, capacity, self)
}
}
Extend derived protocol with restriction can also fix the error.
protocol R {
associatedtype X
// not work if `x` is a function.
var x: X { get }
}
protocol S: R {
var y: X { get }
}
extension S /* add restriction here */ where X == Int {
var x: X { y }
}
class C: S {
// Okay
let y = 0
}
Thanks, I see, associated type inference is intentionally limited.
But this?
// Type 'CFBinaryHeap' does not conform to protocol 'CFMutableCopying'
extension CFBinaryHeap: CFMutableType, CFMutableCopyingWithCapacity {
// ...
}
// Okay! Just adjusted the order.
extension CFBinaryHeap: CFMutableCopyingWithCapacity, CFMutableType {
// ...
}
I understand it's about how associated type is inferred, but it really blows up my mind.
1 Like