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 expression in guard-0.3.1, Rust 1.15 #38977

Closed
brson opened this Issue Jan 11, 2017 · 16 comments

Comments

Projects
None yet
6 participants
@brson
Copy link
Contributor

brson commented Jan 11, 2017

https://github.com/durka/guard 8f9753302f549826800820dc4a34ad8d01dccd66

Not on stable.

101 brian@ip-10-145-43-250:~/dev/guard⟫ rustc +beta -Vv
rustc 1.15.0-beta.3 (a035041ba 2017-01-07)
binary: rustc
commit-hash: a035041ba450ce3061d78a2bdb9c446eb5321d0d
commit-date: 2017-01-07
host: x86_64-unknown-linux-gnu
release: 1.15.0-beta.3
LLVM version: 3.9

Many errors like this:

error: unreachable expression
   --> src/lib.rs:111:56
    |
111 |                                                        match _x {}
    |                                                        ^^^^^^^^^^^
...
467 |         guard!(let Some((a, b)) else { panic!() } = if false { opt } else { opt }); println!("{} {}", a, b);
    |         --------------------------------------------------------------------------- in this macro invocation

error: unreachable expression
   --> src/lib.rs:105:60
    |
105 |                                                            match _x {}
    |                                                            ^^^^^^^^^^^
...
468 |         guard!(let Some((a, b)) if b > 0 else { panic!() } = opt);                  println!("{} {}", a, b);
    |         ---------------------------------------------------------- in this macro invocation

error: unreachable expression
   --> src/lib.rs:111:56
    |
111 |                                                        match _x {}
    |                                                        ^^^^^^^^^^^
...
468 |         guard!(let Some((a, b)) if b > 0 else { panic!() } = opt);                  println!("{} {}", a, b);
    |         ---------------------------------------------------------- in this macro invocation

error: aborting due to 52 previous errors

cc @durka

@durka

This comment has been minimized.

Copy link
Contributor

durka commented Jan 11, 2017

The root cause is that this code

    let x = if true {
        42
    } else {
        [panic!()]
    };

typechecks on beta and nightly but not stable. In my macro I am trying to make sure the code before match _x {} diverges. In stable, I have to put in the empty match to satisfy the typechecker, but in newer compilers the diverging code itself is enough. I believe this is due to improvements by @canndrew. Previously this was handled by the crate's "nightly" feature, but now that it has reached beta it is a problem.

cc @eddyb

@durka

This comment has been minimized.

Copy link
Contributor

durka commented Jan 11, 2017

That being said, I brought this upon myself with #![cfg_attr(test, deny(warnings))]. Allowing unreachable-code warnings fixes the build at the price of a few warnings.

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Jan 11, 2017

@nikomatsakis Is there a good reason for denying/allowing that code?

@durka

This comment has been minimized.

Copy link
Contributor

durka commented Jan 11, 2017

@eddyb remember this?

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Jan 11, 2017

Yes, and I relaxed it afterwards by doing the checking in typeck, in a principled fashion.
That said, I thought I limited unreachable expressions to !.

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Jan 11, 2017

@eddyb I am somewhat surprised to learn that this type-checks, although I can imagine how it might come about.

@canndrew

This comment has been minimized.

Copy link
Contributor

canndrew commented Jan 11, 2017

Well, part of the promise of the ! was RFC was always better dead code detection. We don't make any promises about not breaking code with deny(warnings).

Is there a good reason for denying/allowing that code?

The fact that we can allow it seems like a good reason to allow it.

@durka

This comment has been minimized.

Copy link
Contributor

durka commented Jan 11, 2017

We don't make any promises about not breaking code with deny(warnings).

Yes, I agree. It's annoying that there's no way to write code that is warning-free on all channels but it doesn't count as a regression.

@arielb1

This comment has been minimized.

Copy link
Contributor

arielb1 commented Jan 11, 2017

@durka

#[allow(unknown_lints, unreachable_patterns)] is your friend.

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Jan 11, 2017

Oh the rule is that an expected type can't differ unless it's !. But there's no expected type here.
And the else block ends up having an diverging variable as its type. Which is needed for compatibility.
At least I seem to recall we can't avoid that (and if we do it, this code compiles).

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Jan 11, 2017

To be clear, while I was somewhat surprised, I also think it's ok and makes sense. We've traditionally not considered regressions due to lints triggering as being "real regressions" -- since we cap lints on dependencies they don't affect anyone downstream, to be sure. I think that same policy should apply here, hence no action needed (as long as we're satisfied with how the code is behaving).

@durka

This comment has been minimized.

Copy link
Contributor

durka commented Jan 11, 2017

@arielb1 #![allow] doesn't really count since the macro can't output that into the client crate. It will when stmt_expr_attributes stabilizes, though lint controls from those are still ignored.

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Jan 11, 2017

Ah, interesting, this is kind of a corner case where the macro is injecting code that generates the lint into its client! Fascinating.

@brson

This comment has been minimized.

Copy link
Contributor Author

brson commented Jan 11, 2017

Ah, interesting, this is kind of a corner case where the macro is injecting code that generates the lint into its client! Fascinating.

I've seen a few such reports lately where changes to lints break crates during expansion of other people's macros.

@brson

This comment has been minimized.

Copy link
Contributor Author

brson commented Jan 12, 2017

This is expected behavior. We'll need to update guard! for now, and I'll file an issue about macro expansion and lints.

@brson brson closed this Jan 12, 2017

@durka

This comment has been minimized.

Copy link
Contributor

durka commented Jan 12, 2017

Published a new version of guard with passing tests. Users (if there were any) were not affected unless they also had #![deny(unreachable_code)] in their crate.

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.