I have a type conforming to both RawRepresentable and CustomStringConvertible, but something strange happens when I introduce the latter conformance โ apart from the expected init(rawValue:) and init(stringLiteral:) it seems to gain a non-failable init(_:String) which calls init(stringLiteral:).
This even overrides any init with anonymous argument defined explicitly for that type; but not if that init is called explicitly with S.init("bla") as opposed to S("bla").
struct S: RawRepresentable {
var rawValue: String
init?(rawValue: String) {
guard rawValue.count > 3 else { return nil }
self.rawValue = rawValue
}
}
extension S {
init(_ value: String) {
self.rawValue = "Called from extra non-failable init with anonymous argument."
}
}
extension S: ExpressibleByStringLiteral {
init(stringLiteral value: RawValue.StringLiteralType) {
self.rawValue = .init(stringLiteral: value)
}
}
extension S: CustomStringConvertible {
var description: String { rawValue }
}
let tooShort = S(rawValue: "abc") // nil
let longEnough = S(rawValue: "abcdef") // "abcdef"
let fromStringLiteral: S = "abc123" // "abc123"
let what = S("What?") // "What?"
let extra = S.init("Hmm") // "Called from extra non-failable init with anonymous argument."
Where does this behaviour come from โ and why?