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-11159] Typechecker crash on overloaded enum case #53556

Open
tayloraswift opened this issue Jul 19, 2019 · 12 comments
Open

[SR-11159] Typechecker crash on overloaded enum case #53556

tayloraswift opened this issue Jul 19, 2019 · 12 comments
Labels
compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software good first issue Good for newcomers

Comments

@tayloraswift
Copy link
Contributor

Previous ID SR-11159
Radar rdar://problem/53312911
Original Reporter @Kelvin13
Type Sub-task
Environment

$ swift --version
Swift version 5.1-dev (LLVM 200186e28b, Swift 75a5496)
Target: x86_64-unknown-linux-gnu

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Sub-task, CompilerCrash, StarterBug
Assignee AndrewLitteken (JIRA)
Priority Medium

md5: 045414bcf57bf8b343a071693e9843bc

Parent-Task:

is blocked by:

  • SR-15925 Overloaded enum cases break the compiler

relates to:

  • SR-11357 Weird behavior when defining enum cases with the same name
  • SR-11496 Enum with same name/different number of associated values: allowed, but crashes at runtime

Issue Description:

enum Foo 
{
    case a(x:Int)
    case a(y:Int)
}

func switcher(_ foo:Foo) 
{
    switch foo 
    {
    case .a(x:):
        break 
    case .a(y:):
        break 
    }
}


$ swift enumoverload.swift 
swift: /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-18_04/swift/lib/Sema/TypeCheckPattern.cpp:96: swift::EnumElementDecl *filterForEnumElement(swift::TypeChecker &, swift::DeclContext *, swift::SourceLoc, bool, swift::LookupResult): Assertion `!foundElement && "ambiguity in enum case name lookup?!"' failed.
Stack dump:
0.  Program arguments: /home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift -frontend -interpret enumoverload.swift -disable-objc-interop -color-diagnostics -module-name enumoverload 
1.  Swift version 5.1-dev (LLVM 200186e28b, Swift 75a5496bc1)
2.  While evaluating request TypeCheckFunctionBodyRequest(enumoverload.(file).switcher@enumoverload.swift:7:6)
3.  While type-checking 'switcher(_:)' (at enumoverload.swift:7:1)
4.  While type-checking statement at [enumoverload.swift:8:1 - line:16:1] RangeText="{
    switch foo 
    {
    case .a(x:):
        break 
    case .a(y:):
        break 
    }
"
5.  While type-checking statement at [enumoverload.swift:9:5 - line:15:5] RangeText="switch foo 
    {
    case .a(x:):
        break 
    case .a(y:):
        break 
    "
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0x45212a4]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0x451eefe]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0x45216b8]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x12890)[0x7fd7cf1a8890]
/lib/x86_64-linux-gnu/libc.so.6(gsignal+0xc7)[0x7fd7cd60be97]
/lib/x86_64-linux-gnu/libc.so.6(abort+0x141)[0x7fd7cd60d801]
/lib/x86_64-linux-gnu/libc.so.6(+0x3039a)[0x7fd7cd5fd39a]
/lib/x86_64-linux-gnu/libc.so.6(+0x30412)[0x7fd7cd5fd412]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xf7bafc]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xf7b4d7]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xf78f14]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfc1859]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfbe738]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfc14f7]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfbd8b9]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfbcad7]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfbb257]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfbc111]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfb9e1c]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfc3940]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfc3418]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfc27ca]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfbbe1d]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfbbdfa]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfde34b]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0xfdec5b]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0x7427da]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0x74174a]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0x740db1]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0x4d2f24]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0x4d1a93]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0x473d40]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x7fd7cd5eeb97]
/home/klossy/.swiftenv/versions/DEVELOPMENT-SNAPSHOT-2019-07-11-a/usr/bin/swift[0x47398a]
Aborted (core dumped)
@belkadan
Copy link
Contributor

Mac backtrace from near-master:

7  swift                    0x0000000104cc3401 filterForEnumElement(swift::TypeChecker&, swift::DeclContext*, swift::SourceLoc, bool, swift::LookupResult) (.cold.9) + 33
8  swift                    0x0000000101b02291 filterForEnumElement(swift::TypeChecker&, swift::DeclContext*, swift::SourceLoc, bool, swift::LookupResult) + 801
9  swift                    0x0000000101b01d67 lookupEnumMemberElement(swift::TypeChecker&, swift::DeclContext*, swift::Type, swift::Identifier, swift::SourceLoc) + 167
10 swift                    0x0000000101aff9fb swift::TypeChecker::coercePatternToType(swift::Pattern*&, swift::TypeResolution, swift::Type, swift::TypeResolutionOptions, swift::TypeLoc) + 267
11 swift                    0x0000000101b44e81 (anonymous namespace)::StmtChecker::checkCaseLabelItemPattern(swift::CaseStmt*, swift::CaseLabelItem&, bool&, swift::Type, llvm::SmallVectorImpl<swift::VarDecl*>**, llvm::SmallVectorImpl<swift::VarDecl*>**) + 177
12 swift                    0x0000000101b4213e swift::ASTVisitor<(anonymous namespace)::StmtChecker, void, swift::Stmt*, void, void, void, void>::visit(swift::Stmt*) + 4046

@swift-ci create

@belkadan
Copy link
Contributor

I think this is probably StarterBug-simple: lookupEnumMemberElement should take a DeclName instead of just an Identifier.

@swift-ci
Copy link
Collaborator

Comment by Andrew Litteken (JIRA)

I'd like to take a try at figuring out this bug. I did a little bit of work on this and it seems like this is not the only problem. Based on an assertion that is thrown, there is a collision between the two enum cases and not having the information of the parameter list on-hand to figure this out. Is this something that would be contained in a DeclName?

@belkadan
Copy link
Contributor

Yeah, a DeclName is a base name (an Identifier) plus argument labels (several more Identifiers). My hope is that by doing a full-name lookup instead of a base-name lookup we won't ever find multiple enum cases except if the user types a plain let .a.

cc also CodaFi (JIRA User)

@swift-ci
Copy link
Collaborator

Comment by Andrew Litteken (JIRA)

Maybe I'm missing something, but I'm not sure the parser is picking up the arguments for use in this situation when used as a case in the switch statement.

The reasoning behind this that I'm trying to get access to the parameters in `TypeChecker::coercePatternToType` before we call `lookupEnumMemberElement` to create a DeclName since I can't extract it from the EnumElementPattern as the it contains an UnresolvedMemberExpr rather an EnumElementDecl. However, when I use `hasArguments()` on the Expr, it returns false. Additionally, when examining the AST visitor for these EnumElement, the no arguments are not registered at that stage either.

Potentially related, this example works

enum Foo 
{
    case a(y:Int)
}
func switcher(_ foo:Foo) 
{
    switch foo 
    {   
    case .a(x:):
        print("here")
        break 
    }   
}

But seems like it shouldn't based on my understanding of the expected solution to this bug. It seems like it should fail based on the different argument names in the enum member.

@belkadan
Copy link
Contributor

hasArguments checks for actual arguments, not just argument labels. What does the DeclName inside the UnresolvedMemberExpr look like?

@swift-ci
Copy link
Collaborator

Comment by Andrew Litteken (JIRA)

The DeclNames do have the arguments, and once a NameDecl is passed, the assertion failure doesn't happen. But with the given test case the warning `warning: case is already handled by previous patterns; consider removing it` is thrown. Is this the expected behavior for this?

@swift-ci
Copy link
Collaborator

Comment by Andrew Litteken (JIRA)

I have some additional examples that I'm not sure should be covered by this bug or not, but seem releated:

Contrary to the last comment if you have:

enum Foo 
{   
    case a(x:Int)
}
func switcher(_ foo:Foo) 
{
    switch foo
    {
    case .a(y:):
        break 
    }   
}   

You get the error:

error: type 'Foo' has no member 'a(y:)' case .a(y:):

Which seems like they are in contradiction with one another. But I can see where the original version throwing the "case is already handled by previous patterns" warning is more focusing on the type and not the name of the variable.

With the code:

enum Foo 
{
    case a(x:Int)
    case a(y:Float)
}


func switcher(_ foo:Foo) 
{
    switch foo 
    {   
    case .a(x:Int):
        break 
    case .a(y:Float):
        break 
    }   
}

There is a similar error to the initial bug, where the assertion about ambiguity in the enum is thrown. In these tests. In this case when the string of the DeclName is asked for, where (I think) it should contain something like a(x:Int), for the case statement it only shows a and then random characters following.

@belkadan
Copy link
Contributor

I mean, it's true that Foo has no member a(y:) in that new example. But yeah, we need to treat a(x:) and a(y:) as different cases, and the exhaustivity checking logic probably isn't doing that yet either. Still, maybe that can just be plumbed through by changing the Identifier in the Space class to a DeclName as well (and then fixing up all the call sites, of course).

@swift-ci
Copy link
Collaborator

swift-ci commented Aug 2, 2019

Comment by Andrew Litteken (JIRA)

I tried doing this, and just using DeclNames in the Space class doesn't clear that up. But, before I get into the exhaustiveness checking, I'm trying to clear up some ambiguities when parsing the enums.

I have made some progress in recognizing when there are arguments. I have added to the pattern building s that when arguments are specified, they are added and matched correctly (although still with some exhaustiveness errors). Previously, they were just being matched against the .a, but now they, using the original as an example, they check for .a(x: ) or .a(y: ), avoiding the ambiguity case. However, when we have cases like:

enum Foo 
{   
    case a(x:Int)
    case a(y:Int)
}

func switcher(_ foo:Foo) 
{
    switch foo
    {
    case .a(let x):
        break
    }   
}

There are ambiguities in which case to take and crash the compiler currently. What should happen here? I feel like it should match something, but I'm not sure what.

This is a problem for other Patterns, like the Typed and Is patterns.

Edit: formatting

@belkadan
Copy link
Contributor

belkadan commented Aug 2, 2019

The document to reference here is SE-0155, which introduced enum elements with the same base name. That document describes what should happen in cases like the one you've brought up here.

@swift-ci
Copy link
Collaborator

swift-ci commented Aug 2, 2019

Comment by Andrew Litteken (JIRA)

Thank you, I think that clears up most of my questions. What's the best way to get the error messages right for these?

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@AnthonyLatsis AnthonyLatsis added the crash Bug: A crash, i.e., an abnormal termination of software label Dec 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

4 participants