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

match expression falling through? #26251

Closed
jrvidal opened this Issue Jun 12, 2015 · 11 comments

Comments

Projects
None yet
9 participants
@jrvidal
Copy link
Contributor

jrvidal commented Jun 12, 2015

I tried this code:

fn main() {
    let x = 'a';

    match x {
            'a'...'b' if false => {
                println!("one");
            },

            'a' => {
                println!("two");
            },

            'a'...'b' => {
                println!("three");
            },

            _ => panic!("what?")
    }
}

I expected to get two but I get three. Is this the expected semantics?

Meta

rustc --version --verbose:

rustc 1.1.0-beta (cd7d89a 2015-05-16) (built 2015-05-16)
binary: rustc
commit-hash: cd7d89a
commit-date: 2015-05-16
build-date: 2015-05-16
host: x86_64-unknown-linux-gnu
release: 1.1.0-beta

@shepmaster

This comment has been minimized.

Copy link
Member

shepmaster commented Jun 12, 2015

If you increase the first range to 'a'...'c', then the second match arm is triggered. If you comment out either match arm with a range, then the expected match arm is triggered. Pure speculation, I wonder if there is an optimization that is reordering the match arms with the same check but different guard clauses.

With modified range

fn main() {
    let x = 'a';

    match x {
        'a'...'c' if false => {
            println!("one");
        },

        'a' => {
            println!("two");
        },

        'a'...'b' => {
            println!("three");
        },

        _ => panic!("what?")
    }
}

With commented-out following match arm

fn main() {
    let x = 'a';

    match x {
        'a'...'b' if false => {
            println!("one");
        },

        'a' => {
            println!("two");
        },

/*
        'a'...'b' => {
            println!("three");
        },
*/

        _ => panic!("what?")
    }
}
@Stebalien

This comment has been minimized.

Copy link
Contributor

Stebalien commented Jun 12, 2015

#18060 is similar but doesn't have guards. IMO, these should both be marked P-high, I-wrong.

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Jun 12, 2015

triage: I-nominated

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Jun 17, 2015

cc @jakub-

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Jun 17, 2015

I agree this is totally bogus... seems like the chance of someone relying on this behavior is... low but not non-trivial?

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Jun 17, 2015

triage: P-high

@rust-highfive rust-highfive added P-high and removed I-nominated labels Jun 17, 2015

@Stebalien

This comment has been minimized.

Copy link
Contributor

Stebalien commented Jun 17, 2015

jrvidal ran across this in the wild so it can't be that low.

@jrvidal

This comment has been minimized.

Copy link
Contributor Author

jrvidal commented Jun 17, 2015

FWIW, here is a simplified version of my use case, where I try to parse a number literal:

loop {
    match c {
        // ...
        '0'...'9' | 'a'...'f' if valid_digit(c, radix) => {/* parse digit */},
        'e' | 'f' | 's' | 'd' | 'l' if is_decimal_literal() => {/* parse exponential marker */},
        '0'...'9' | 'a'...'f' => {/* return error, bad digit */},
        _ => break
    }
}
@ghost

This comment has been minimized.

Copy link

ghost commented Jun 20, 2015

The root problem is the same as #18060.

I've gotta say that I'm convinced the trans bits for match expressions are desperate for a rewrite that I've always hoped to take on and that I've heard @eddyb beg for as well. Sadly, time is extremely scarce for me right now so I can't promise much (oh, the bus factors…).

This, however, is extremely worrisome in that it can lead to really nasty bugs in user code.

eefriedman added a commit to eefriedman/rust that referenced this issue Jul 15, 2015

Rewrite the pattern matching code in trans.
The old code was not well structured, difficult to understand,
and buggy.

The new implementation is completely naive, so there may be a slight
runtime performance loss. That said, adding optimizations on top of
a clear and correct implementation seems easier than trying to
fix the old mess.

Fixes issue rust-lang#19064.
Fixes issue rust-lang#26989.
Fixes issue rust-lang#26251.
Fixes issue rust-lang#18060.
Fixes issue rust-lang#24875.
Fixes issue rust-lang#23311.
Fixes issue rust-lang#20046.

@nikomatsakis nikomatsakis self-assigned this Oct 1, 2015

@nrc

This comment has been minimized.

Copy link
Member

nrc commented Nov 19, 2015

triage: P-medium

also mir, apparently

@rust-highfive rust-highfive added P-medium and removed P-high labels Nov 19, 2015

@nrc nrc added A-mir and removed P-medium labels Nov 19, 2015

@jrvidal

This comment has been minimized.

Copy link
Contributor Author

jrvidal commented Aug 12, 2016

I just compiled with the latest nightly and it seems to be working!

rustc 1.12.0-nightly (0ef24eed2 2016-08-10)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.