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

unreachable pattern not warned when used in sufficiently complex macro / procmacro hack #78234

Closed
drahnr opened this issue Oct 22, 2020 · 8 comments · Fixed by rust-lang/futures-rs#2243
Labels
A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. A-patterns Relating to patterns and pattern matching C-bug Category: This is a bug. P-low Low priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@drahnr
Copy link
Contributor

drahnr commented Oct 22, 2020

I tried this code:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=49f774bfbf796f141b31e716fba52820

with expansion:

https://gist.github.com/bkchr/92b754ec82efcc115637ab5533e79ff4

use futures::{future, select}; // 0.3.6

pub enum Foo {
    Bar,
    Baz,
}

/* this function does produce warnings
fn match_foo(foo: Foo) -> i32 {
    match foo {
       x => 1,
        _ => unreachable!("why you do this rust?"),
    }
}
*/

pub async fn foo(foo: Foo) {
    let mut a = future::ready(4);
    
    use Foo::Bar;
    let res = select! {
        // but this doesn't        
        a_res = a => match foo {
            Bar => 1,
            _ => 4,
            _ => unreachable!("why you do this rust?"),
        },
    };

    assert_eq!(res, 4, "oh");
}


fn main() {
    futures::executor::block_on(async move {
        foo(Foo::Baz).await
    });
}

I expected to see this happen:

Be warned about the unreachable pattern / enum variant.

Instead, this happened:

No warning was displayed despite an unreachable pattern being present.

Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.79s
     Running `target/debug/playground`
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `1`,
 right: `4`: oh', src/main.rs:29:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Meta

rustc --version --verbose:

rustc 1.47.0 (18bf6b4f0 2020-10-07)
binary: rustc
commit-hash: 18bf6b4f01a6feaf7259ba7cdae58031af1b7b39
commit-date: 2020-10-07
host: x86_64-unknown-linux-gnu
release: 1.47.0
LLVM version: 11.0

Credit for example @ordian , initial finding by @coriolinus

@tesuji
Copy link
Contributor

tesuji commented Oct 22, 2020

Can confirm the warning[E0170] doesn't trigger for the code above.
The code could be simplify more by remove unused assert:

use futures::{future, select}; // 0.3.6

pub enum Foo {
    Bar,
    Baz,
}

/* this function does produce warnings
fn match_foo(foo: Foo) -> i32 {
    match foo {
       Bar => 1,
        _ => unreachable!("why you do this rust?"),
    }
}
*/

pub async fn asdf(foo: Foo) {
    let mut a = future::ready(4);

    select! {
        // but this doesn't
        a_res = a => match foo {
            Bar => 1,
            _ => 4,
            // _ => unreachable!("why you do this rust?"),
        },
    };
}

fn main() {
    futures::executor::block_on(asdf(Foo::Baz));
}

@rustbot prioritize

@rustbot rustbot added A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. A-patterns Relating to patterns and pattern matching T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Oct 22, 2020
@camelid
Copy link
Member

camelid commented Oct 22, 2020

@drahnr By the way, not sure if you realized this but matching on Bar treats Bar as a variable not the enum variant Foo::Bar.

@Aaron1011
Copy link
Member

This appears to be due to the select! macro using proc-macro-hack. As the name would suggest, proc-macro-hack does a number of hacky things, which appears to include sending input tokens through a generated macro_rules! macro. This applies a mark to the token spans, causing the lint to be suppressed by this check:

if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) {
// Any suggestions made here are likely to be incorrect, so anything we
// emit shouldn't be automatically fixed by rustfix.
err.allow_suggestions(false);
// If this is a future incompatible lint it'll become a hard error, so
// we have to emit *something*. Also, if this lint occurs in the
// expansion of a macro from an external crate, allow individual lints
// to opt-out from being reported.
if future_incompatible.is_none() && !lint.report_in_external_macro {
err.cancel();
// Don't continue further, since we don't want to have
// `diag_span_note_once` called for a diagnostic that isn't emitted.
return;
}
}

This should be fixed when dtolnay/proc-macro-hack#62 is implemented. I don't think there's anything that can be done on the rustc side.

@drahnr
Copy link
Contributor Author

drahnr commented Oct 23, 2020

@drahnr By the way, not sure if you realized this but matching on Bar treats Bar as a variable not the enum variant Foo::Bar.

I think that was a result of minimization removing a use Foo::Bar; from the scope. Doesn't really change much for the repro.

@apiraino
Copy link
Contributor

Assigning P-low as discussed as part of the Prioritization Working Group procedure and removing I-prioritize.

@apiraino apiraino added P-low Low priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Oct 28, 2020
@ordian
Copy link

ordian commented Oct 28, 2020

This should be fixed when dtolnay/proc-macro-hack#62 is implemented. I don't think there's anything that can be done on the rustc side.

According to this comment, this should have been fixed by dtolnay/proc-macro-hack#66, which was released in 0.5.19.
But with

❯ cargo update -p proc-macro-hack 
    Updating crates.io index
    Updating proc-macro-hack v0.5.18 -> v0.5.19

I am still not getting the warnings.

@Aaron1011
Copy link
Member

It looks like that change requires explicit opt-in via #[proc_macro_hack(only_hack_old_rustc)] in the proc macro crate.

@Aaron1011
Copy link
Member

This now produces a warning if you change the Cargo.toml dependency to futures = { git = "https://github.com/rust-lang/futures-rs" }:

warning: unreachable pattern
  --> src/main.rs:26:13
   |
26 |             _ => unreachable!("why you do this rust?"),
   |             ^
   |
   = note: `#[warn(unreachable_patterns)]` on by default

warning: unused variable: `a_res`
  --> src/main.rs:23:9
   |
23 |         a_res = a => match foo {
   |         ^^^^^ help: if this is intentional, prefix it with an underscore: `_a_res`
   |
   = note: `#[warn(unused_variables)]` on by default

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. A-patterns Relating to patterns and pattern matching C-bug Category: This is a bug. P-low Low priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants