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-11400] Error when nil coalessing multiple types with common protocol #53801

Open
CraigSiemens opened this issue Aug 30, 2019 · 8 comments
Open
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

@CraigSiemens
Copy link

Previous ID SR-11400
Radar rdar://problem/55046744
Original Reporter @CraigSiemens
Type Bug
Status Reopened
Resolution
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, TypeChecker
Assignee None
Priority Medium

md5: bd4fbe3801df07312c08103c2d7c0509

Issue Description:

I've got multiple types that conform to the same protocol and I'm trying to use the nil coalescing operator to get the first one where the failable initializer succeeds. Heres and example that shows it off in a playground.

protocol P {}
struct A: P { init?() { return nil } }
struct B: P { init?() { return nil } }
struct C: P {}

let value: P = A() ?? B() ?? C() // error

The full console output I get is

error: macOS.playground:247:20: error: value of optional type 'P?' must be unwrapped to a value of type 'P'
let value: P = A() ?? B() ?? C()
                   ^

macOS.playground:247:20: note: coalesce using '??' to provide a default when the optional value contains 'nil'
let value: P = A() ?? B() ?? C()
                   ^
               (                ) ?? <#default value#>

macOS.playground:247:20: note: force-unwrap using '!' to abort execution if the optional value contains 'nil'
let value: P = A() ?? B() ?? C()
                   ^
               (                )!

It feels like it should work but the compiler is complaining about it. The weird thing is there's a couple simple workarounds

let value: P = (A() ?? B()) ?? C() // works
let value: P = A() as P? ?? B() ?? C() // works
let value: P = A() ?? B() ?? C() as P // works
@belkadan
Copy link
Contributor

belkadan commented Sep 3, 2019

Possibly related to the existing hacks around ?? in the type checker. cc @hborla, @xedin

@xedin
Copy link
Member

xedin commented Sep 4, 2019

@swift-ci create

@xedin
Copy link
Member

xedin commented Sep 4, 2019

The problem here as correctly mentioned @CraigSiemens is related to the fact that we don't unify types by their protocol conformances unless that protocol is explicitly specified, that's why e.g. `A() ?? B()` can't be type-checked into ??<P>(A?, B?) because of that. This is expected behavior.

@belkadan
Copy link
Contributor

belkadan commented Sep 5, 2019

We have an explicitly-specified protocol: the result type.

@belkadan
Copy link
Contributor

belkadan commented Sep 5, 2019

For the simplest comparison, let value: P = B() ?? C() works.

@xedin
Copy link
Member

xedin commented Sep 5, 2019

@belkadan It might work for a single operator but not for linked operators, binding collections can't really propagate contextual type which means that bindings for arguments would never have `P` as a possible type. We have talked about attempting protocols before but it leads to other failures. Unfortunately we can't solve this without rework of how solver infers possible types for type variables.

@belkadan
Copy link
Contributor

belkadan commented Sep 5, 2019

I don't know what you mean by "linked operators" or "collections". There are no collection literals here and all of the working examples Craig provides show that this is clearly a bug. It may be hard to fix, but it's hardly invalid.

@xedin
Copy link
Member

xedin commented Sep 5, 2019

I mean expressions like "1 + 2 + 3" where result of one operator is an argument to another one. This is a problem which might always require specifying protocol explicitly because fixing it means a revamp of the solver.

@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