Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-12183] Compiler emits bad error when using implicit member expression for failable init #54608

Open
swift-ci opened this issue Feb 11, 2020 · 3 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself type checker Area → compiler: Semantic analysis

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-12183
Radar rdar://problem/59496041
Original Reporter jacob.weightman (JIRA User)
Type Bug
Environment

This bug was discovered in Xcode 11.3 using Swift 5.0.

Additional Detail from JIRA
Votes 1
Component/s Compiler
Labels Bug, TypeChecker
Assignee None
Priority Medium

md5: d0fe9e7a6a49f308f1c7ce1f5cc3bbf3

Issue Description:

Minimal example:

struct Foo {
  init?() {}
}

let a: Foo? = Foo()
let b: Foo? = .init() // ambiguous reference to member 'init'

This bug applies regardless of whether Foo is an enum, struct, or class.

@theblixguy
Copy link
Collaborator

Interesting, I get the same error on 5.2 as well.

@beccadax
Copy link
Contributor

@swift-ci create

@swift-ci
Copy link
Collaborator Author

Comment by Jacob Weightman (JIRA)

After thinking it over some more, it occurs to me that the type of b in that example really is Optional<Foo>, so it makes sense that it would be looking for a corresponding initializer on Optional rather than a failable initializer of Foo. The following is able to avoid this error:

enum Foo: FailableInitable {
     case a
     init?() { self = .a }
}

let a: Foo? = Foo()
let b: Foo? = .init()

protocol FailableInitable {
     init?()
}

extension Optional where Wrapped: FailableInitable {
     init() {
         self = Wrapped.init()
     }
}

I do, however, think that this is still a bug, or at least a missing feature, because static methods and ordinary initializers are "forwarded" through the Optional type. For instance, this code works just fine:

enum Foo {
    case a
    
    init() { self = .a }       // Note: not failable
    static func foo() -> Foo { return .a }
}

let a: Foo? = .init() 
let b: Foo? = .foo() 

Thus, it seems anomalous that failable initializers wouldn't be accessible in the same way. I wonder if the solution is to detect failable initializers on T as "regular" initializers on Optional<T>, though I'm not sure if that would cause too many problems in weird corner cases like initializers with the same arguments in both.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

3 participants