I have encountered a weird behaviour, not sure if I am misusing this feature, or is it not fully working as intended.
I want to add general ExpressibleByLiteral
conformances to Optionals. Let's take ExpressibleByIntegerLiteral
as an example:
extension Optional: ExpressibleByIntegerLiteral where Wrapped: ExpressibleByIntegerLiteral {
public typealias IntegerLiteralType = Wrapped.IntegerLiteralType
public init(integerLiteral value: IntegerLiteralType) {
self = .some(Wrapped.init(integerLiteral: value))
}
}
The reason for that is that I am using an enum in my mocking library, like following, :
// Simplified for the sake of example
enum Parameter<Value> {
case any
case value(Value)
}
extension Parameter: ExpressibleByIntegerLiteral where Value: ExpressibleByIntegerLiteral {
// ... conformance etc.
}
extension Parameter: ExpressibleByNilLiteral where Value: ExpressibleByNilLiteral {
// ... conformance etc.
}
The conformance above (for my Parameter
enum) is the reason I need Optional do declare it as well.
And it works very well, and I can do something like:
func foo(_ p: Parameter<Int?>) { /* ... */ }
foo(.any)
foo(.value(nil))
foo(.value(1))
foo(1)
foo(2)
foo(nil)
...
But it has one very weird side effect, whenever I create/use type like Any?
:
// This does not work:
let bar1: Any? = 1
// Error: Value of protocol type 'Any' cannot conform to 'ExpressibleByIntegerLiteral'; only struct/enum/class types can conform to protocols
// This actually works
let bar2: Any? = 1 as Any
// This works as well
let bar3: Any? = .init(1)
My question is, why does it behave like that?
I assume that I broke some "magic" that allowed to initialise Optionals using literals, event if they did not declared conformance to ExpressibleBySomethingLiteral (happens for all other literals except nil as well).
Shouldn't Optional utilise this conditional conformance by default?