4
votes

This is the strangest problem I've had in swift and its driving me crazy trying to figure it out.

I have a struct called Algorithm that conforms to LosslessStringConvertible, so it has a failable init. Just to test it, it always returns nil:

init?(_ description: String) {
    return nil
}

Algorithm also conforms to ExpressibleByStringLiteral, using the previous init:

extension Algorithm: ExpressibleByStringLiteral {
    init(stringLiteral value: String) {
        self.init(value)!
    }
}

But when I create an instance of Algorithm from the first init, I can see in Xcode that its not an optional

let a = Algorithm("test")
a // a: Algorithm

And then I run the above code, it crashes on the line self.init(value)!, from the ExpressibleByStringLiteral init.

I can't for the life of me figure out why this is happening. Im calling one initializer, and a completely different one is being run.

Any ideas why this is happening?

Thanks!

1
Reproduced. The interesting part is that Algorithm.init("test") or Algorithm(String("test")) will fix the problem. I guess it's something to do how ExpressibleByStringLiteral is implemented by the compiler. - Sulthan

1 Answers

4
votes

The issue has been already reported in SR-10259 and it seems this is expected behavior coming from Literal initialization via coercion (SE-0213)

Possible workarounds:

Algorithm.init("test") // don't coerce, call initializer
Algorithm(String("test")) // convert literal to a `String` first