Type inference and failable initializer compilation error

I'm curious to understand why the following code fails to build (and provides a seemingly incorrect error message):

struct Foo {
    init?(a: Int) { return nil }
}

let f1: Foo? = Foo.init(a: 1) //works
let f2: Foo? = .init(a: 1) // error: Value of optional type 'Foo?' must be unwrapped to a value of type 'Foo'
1 Like

That last line is equivalent to writing let f2 = Optional<Foo>.init(a: 1). Notice how that isn’t equivalent to the line precedes it.

Since there is no such initializer, the compiler appears to be looking through the optional to find your initializer, then assuming the result (of type Foo?) will be wrapped in another layer of optionality, which would then need to be unwrapped to produce a result of the desired type. The diagnostic message, as far as I can tell, is bogus, but the error isn’t.

Technically, the compiler is allowed to look "through" optionals at the base of an implicit member expression, so the following is fine:

struct Foo {
  static var foo: Foo? { Foo() }
}

let f1: Foo? = .foo

The issue here is that if you try to access a member which also exists on Optional (such as init), then the compiler assumes that you meant to access a member on Optional<Foo>, not Foo itself. (And, as @xwu notes, the ultimate error message you get is nonsense).

This is filed as SR-13815 and was fixed by #34715. The fix should ship in the next release of the Swift compiler.

3 Likes
Terms of Service

Privacy Policy

Cookie Policy