Take a look at the below code:
enum EnumX {
case foo
case bar
}
protocol ProtocolX: RawRepresentable {
init(rawValue: RawValue)
}
struct Foo: ProtocolX {
typealias RawValue = Int
var rawValue: RawValue
init(rawValue: RawValue) {
self.rawValue = rawValue
}
}
struct Bar: ProtocolX {
typealias RawValue = String
var rawValue: RawValue
init(rawValue: RawValue) {
self.rawValue = rawValue
}
}
struct SubscriptX {
static subscript(_ enumX: EnumX) -> any ProtocolX.Type {
switch enumX {
case .foo: Foo.self
case .bar: Bar.self
}
}
}
func deserializerX(type: (some ProtocolX).Type, pointer: UnsafeRawPointer) -> some ProtocolX {
let rawValue = pointer.load(as: type.RawValue.self)
return type.init(rawValue: rawValue)
}
let pointer = UnsafeRawPointer(bitPattern: 0x7f7f_7f7f_7f7f_7f7f)!
let type = SubscriptX[.foo]
// typed as `any ProtocolX`
let instance1 = deserializerX(type: type, pointer: pointer)
// typed as `some ProtocolX`
let instance2 = deserializerX(type: Foo.self, pointer: pointer)
// inline attempt
let type_ = SubscriptX[.foo]
let rawValue = pointer.load(as: type_.RawValue.self) // Type of expression is ambiguous without a type annotation
let instance3 = type_.init(rawValue: rawValue) // Member 'init' cannot be used on value of type 'any ProtocolX.Type'; consider using a generic constraint instead
The seralizerX
function works just fine, albeit returning any ProtocolX
instead of some ProtocolX
when SubscriptX[.foo]
is passed in, but I think that might just be by design. However, attempting to inline it (as seen on the bottom) causes multiple compiler errors.
Attempting to cast type_
as some
instead of any
like so:
let type_: (some ProtocolX).Type = SubscriptX[.foo]
gives the compiler error:
Cannot convert value of type 'any ProtocolX.Type' to specified type '(τ_0_0).Type'
Is inlining the behavior of deserializerX
possible, or can this sort of interplay between some
and any
only be done with a helper function?