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-7799] Matching optional enums against non-optional values #50338

Closed
martinr448 opened this issue May 29, 2018 · 7 comments
Closed

[SR-7799] Matching optional enums against non-optional values #50338

martinr448 opened this issue May 29, 2018 · 7 comments
Assignees

Comments

@martinr448
Copy link

martinr448 commented May 29, 2018

Previous ID SR-7799
Radar rdar://problem/41494702
Original Reporter @martinr448
Type Bug
Status Closed
Resolution Done
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee @theblixguy
Priority Medium

md5: 866262f404c0af00426fbd898e2b0060

Issue Description:

We can match an optional Int against a non-optional value:

let x: Int? = 1

switch x {
case 1: print("one")
default: print("default")
}

But the same does not compile with an optional enum:

enum MyEnum { case a, b }
let e: MyEnum? = .a

switch e {
case .a: print("a") // error: Enum case 'a' not found in type 'MyEnum?'
case .some(.a): print("some a") // OK
default: print("default")
}

Tested with Xcode 9.3.1, with both the default toolchain and the Swift 4.2 snapshot from May 20, 2018.

Related discussion in the Swift forum: Matching optionals in a switch statement, where Joe Groff said:

It ought to compile as well. That's a bug.

@belkadan
Copy link
Contributor

belkadan commented Jun 26, 2018

@swift-ci create

@theblixguy
Copy link
Collaborator

theblixguy commented Feb 8, 2019

@slavapestov @jckarter I have made a change in the type checker to look through optionals when checking an `EnumElementPattern`, however it seems like I need to handle it in SIL as well. For example, at the moment, SILVerification throws an error:

SIL verification failed: switch_enum dispatches on enum element that is not part of its type: elt->getDeclContext() == uDecl

for

enum Foo { case bar}
let foo: Foo? = .bar
switch foo { case .bar: print("bar") default: print("default") }

This makes sense, because we're switching over Foo? rather than Foo, so the emitted SIL looks like:

alloc_global @$s12testmetatype3fooAA3FooOSgvp   // id: %2
%3 = global_addr @$s12testmetatype3fooAA3FooOSgvp : $*Optional<Foo> // users: %8, %7
%4 = metatype $@thin Foo.Type
%5 = enum $Foo, #Foo.bar!enumelt                // user: %6
%6 = enum $Optional<Foo>, #Optional.some!enumelt.1, %5 : $Foo // user: %7
store %6 to [trivial] %3 : $*Optional<Foo>      // id: %7
%8 = load [trivial] %3 : $*Optional<Foo>        // user: %9
switch_enum %8 : $Optional<Foo>, case #Foo.bar!enumelt: bb1 // id: %9

What would be the best approach here? Do we switch over Foo instead, or do we wrap the case in `.some()`?

@theblixguy
Copy link
Collaborator

theblixguy commented Feb 8, 2019

Or should we re-write the element in the type checker to wrap it in `.some()` so we don't have to make changes to SIL?

@theblixguy
Copy link
Collaborator

theblixguy commented Feb 8, 2019

PR: #22486

@theblixguy
Copy link
Collaborator

theblixguy commented Mar 4, 2019

Fixed on master, this will be available in the next Swift release!

@AnnaZaks
Copy link
Mannequin

AnnaZaks mannequin commented Aug 9, 2019

@martinr448, Could you verify if the problem is fixed and if so move the JIRA to "Closed"?

Thanks!
Anna

@martinr448
Copy link
Author

martinr448 commented Aug 9, 2019

This compiles now, and `case .a:` matches the `Optional(MyEnum.a)`:

enum MyEnum { case a, b }
let e = Optional(MyEnum.a)

switch e {
case .a: print("a")
default: print("default")
}

Tested with Xcode 11.0 beta 5 (11M382q).

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants