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

regression 1.49: macro_rules unexpected tokens #79908

Closed
Mark-Simulacrum opened this issue Dec 10, 2020 · 22 comments · Fixed by #80135
Closed

regression 1.49: macro_rules unexpected tokens #79908

Mark-Simulacrum opened this issue Dec 10, 2020 · 22 comments · Fixed by #80135
Assignees
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) A-parser Area: The parsing of Rust source code to an AST ICEBreaker-Cleanup-Crew Helping to "clean up" bugs with minimal examples and bisections P-critical Critical priority regression-from-stable-to-beta Performance or correctness regression from stable to beta. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Milestone

Comments

@Mark-Simulacrum
Copy link
Member

Unclear on the extent to which these are the same problem:

cc @petrochenkov @Aaron1011

@Mark-Simulacrum Mark-Simulacrum added A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) regression-from-stable-to-beta Performance or correctness regression from stable to beta. labels Dec 10, 2020
@Mark-Simulacrum Mark-Simulacrum added this to the 1.49.0 milestone Dec 10, 2020
@rustbot rustbot added the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Dec 10, 2020
@Aaron1011
Copy link
Member

The fourier error looks like an old bug that was fixed by calebzulawski/fourier#17

@Mark-Simulacrum
Copy link
Member Author

https://crates.io/crates/fourier only lists 0.1.0 so we should probably nag @calebzulawski about a point release one more time :)

@calebzulawski
Copy link
Member

Whoops, looks like I half-fixed it. One of my dependencies is too strict. It does look like the same error so probably not a regression...

@Mark-Simulacrum
Copy link
Member Author

cc @petrochenkov

@Mark-Simulacrum Mark-Simulacrum added E-needs-bisection Call for participation: This issue needs bisection: https://github.com/rust-lang/cargo-bisect-rustc E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example labels Dec 11, 2020
@camelid camelid added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Dec 11, 2020
@camelid
Copy link
Member

camelid commented Dec 16, 2020

@apiraino and I both feel unclear about this: Is this a Rust regression or a regression in a library that was then picked up by Crater?

@Mark-Simulacrum
Copy link
Member Author

This is a regression in the Rust compiler.

@camelid
Copy link
Member

camelid commented Dec 16, 2020

The tiger error seems to me like fallout from implementing inline_const. I'm guessing the issue is that it's expecting a block but immediately gets a literal. Not sure how this is supposed to behave though.


Reposting the error here:

[INFO] [stdout] error: expected expression, found keyword `const`
[INFO] [stdout]    --> src/ir.rs:481:23
[INFO] [stdout]     |
[INFO] [stdout] 347 |     (exp $e:expr) => {
[INFO] [stdout]     |          ------- while parsing argument for this `expr` macro fragment
[INFO] [stdout] ...
[INFO] [stdout] 481 |             stmt!(exp const 1);
[INFO] [stdout]     |                       ^^^^^ expected expression
[INFO] [stdout] 
[INFO] [stdout] 
[INFO] [stdout] error: expected expression, found keyword `const`
[INFO] [stdout]    --> src/ir.rs:482:23
[INFO] [stdout]     |
[INFO] [stdout] 347 |     (exp $e:expr) => {
[INFO] [stdout]     |          ------- while parsing argument for this `expr` macro fragment
[INFO] [stdout] ...
[INFO] [stdout] 482 |             stmt!(exp const 2);
[INFO] [stdout]     |                       ^^^^^ expected expression
[INFO] [stdout] 
[INFO] [stdout] 
[INFO] [stdout] error: expected expression, found keyword `const`
[INFO] [stdout]    --> src/ir.rs:483:23
[INFO] [stdout]     |
[INFO] [stdout] 347 |     (exp $e:expr) => {
[INFO] [stdout]     |          ------- while parsing argument for this `expr` macro fragment
[INFO] [stdout] ...
[INFO] [stdout] 483 |             stmt!(exp const 3);
[INFO] [stdout]     |                       ^^^^^ expected expression
[INFO] [stdout] 
[INFO] [stdout] 
[INFO] [stdout] error: aborting due to 3 previous errors

@camelid
Copy link
Member

camelid commented Dec 16, 2020

But I'm not quite sure; the span seems potentially wrong.

@spastorino
Copy link
Member

@rustbot ping cleanup

would be nice to get an MCVE

@rustbot rustbot added the ICEBreaker-Cleanup-Crew Helping to "clean up" bugs with minimal examples and bisections label Dec 16, 2020
@rustbot
Copy link
Collaborator

rustbot commented Dec 16, 2020

Hey Cleanup Crew ICE-breakers! This bug has been identified as a good
"Cleanup ICE-breaking candidate". In case it's useful, here are some
instructions for tackling these sorts of bugs. Maybe take a look?
Thanks! <3

cc @AminArria @camelid @chrissimpkins @contrun @DutchGhost @elshize @ethanboxx @h-michael @HallerPatrick @hdhoang @hellow554 @imtsuki @JamesPatrickGill @kanru @KarlK90 @LeSeulArtichaut @MAdrianMattocks @matheus-consoli @mental32 @nmccarty @Noah-Kennedy @pard68 @PeytonT @pierreN @Redblueflame @RobbieClarken @RobertoSnap @robjtede @SarthakSingh31 @shekohex @sinato @smmalis37 @steffahn @Stupremee @tamuhey @turboladen @woshilapin @yerke

@camelid
Copy link
Member

camelid commented Dec 16, 2020

Somewhat minimized (playground):

macro_rules! exp {
    (const $n:expr) => {
        Box::new(Exp::Const($n))
    };
}

macro_rules! stmt {
    (exp $e:expr) => {
        Box::new(Stmt::Exp($e))
    };
    (exp $($t:tt)+) => {
        Box::new(Stmt::Exp(exp!($($t)+)))
    };
}

macro_rules! seq {
    ($stmt1:expr; $stmt2:expr $(;)?) => {
        Box::new(Stmt::Seq($stmt1, $stmt2))
    };
    ($stmt1:expr; $stmt2:expr; $($stmt:expr);+ $(;)?) => {
        seq!(seq!($stmt1; $stmt2); $($stmt);+)
    };
}

fn main() {
    let seq = seq!(
        stmt!(exp const 1);
        stmt!(exp const 2);
        stmt!(exp const 3);
    );
}

On stable, it produces a bunch of semantic errors (which make sense since I removed a lot of type definitions), but on beta it produces:

error: expected expression, found keyword `const`
  --> src/main.rs:99:19
   |
47 |     (exp $e:expr) => {
   |          ------- while parsing argument for this `expr` macro fragment
...
99 |         stmt!(exp const 1);
   |                   ^^^^^ expected expression

error: expected expression, found keyword `const`
   --> src/main.rs:100:19
    |
47  |     (exp $e:expr) => {
    |          ------- while parsing argument for this `expr` macro fragment
...
100 |         stmt!(exp const 2);
    |                   ^^^^^ expected expression

error: expected expression, found keyword `const`
   --> src/main.rs:101:19
    |
47  |     (exp $e:expr) => {
    |          ------- while parsing argument for this `expr` macro fragment
...
101 |         stmt!(exp const 3);
    |                   ^^^^^ expected expression

@spastorino
Copy link
Member

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

@spastorino spastorino added P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Dec 16, 2020
@camelid
Copy link
Member

camelid commented Dec 16, 2020

Much more minimized:

macro_rules! exp {
    (const $n:expr) => {
        $n
    };
}

macro_rules! stmt {
    (exp $e:expr) => {
        $e
    };
    (exp $($t:tt)+) => {
        exp!($($t)+)
    };
}

fn main() {
    stmt!(exp const 1);
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error: expected expression, found keyword `const`
  --> src/main.rs:17:15
   |
8  |     (exp $e:expr) => {
   |          ------- while parsing argument for this `expr` macro fragment
...
17 |     stmt!(exp const 1);
   |               ^^^^^ expected expression

warning: unused macro definition
 --> src/main.rs:1:1
  |
1 | / macro_rules! exp {
2 | |     (const $n:expr) => {
3 | |         $n
4 | |     };
5 | | }
  | |_^
  |
  = note: `#[warn(unused_macros)]` on by default

error: aborting due to previous error; 1 warning emitted

error: could not compile `playground`

To learn more, run the command again with --verbose.

@camelid camelid removed the E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example label Dec 16, 2020
@camelid
Copy link
Member

camelid commented Dec 16, 2020

Here's the code again:

macro_rules! exp {
    (const $n:expr) => {
        $n
    };
}

macro_rules! stmt {
    (exp $e:expr) => {
        $e
    };
    (exp $($t:tt)+) => {
        exp!($($t)+)
    };
}

fn main() {
    stmt!(exp const 1);
}

I think the issue is that on beta the compiler thinks the const in the macro invocation is starting an expression because of the new inline_const feature – thus it thinks it's using the first rule in the macro. But then when doing macro expansion, it realizes that it's actually not a valid expression because it's missing braces.

On stable this is not an issue because the compiler never thinks that const is starting an expression.

I think the fix might be to not treat const as the start of an expression if it is not immediately followed by braces.


See the original inline_const PR: #77124.

cc @spastorino who has been implementing inline_const

@camelid
Copy link
Member

camelid commented Dec 16, 2020

My bisection is in line with my diagnosis:

searched nightlies: from nightly-2020-10-15 to nightly-2020-10-19
regressed nightly: nightly-2020-10-18
searched commits: from e3051d8 to 043eca7
regressed commit: 6af9846

bisected with cargo-bisect-rustc v0.6.0

Host triple: x86_64-apple-darwin
Reproduce with:

cargo bisect-rustc --preserve --regress=error --start=2020-10-15 --end=2020-10-19 

@camelid camelid removed the E-needs-bisection Call for participation: This issue needs bisection: https://github.com/rust-lang/cargo-bisect-rustc label Dec 16, 2020
@camelid camelid self-assigned this Dec 16, 2020
@camelid
Copy link
Member

camelid commented Dec 16, 2020

I'm going to try working on this. If I get stuck I'll release my assignment since this is P-high!

@camelid camelid added the A-parser Area: The parsing of Rust source code to an AST label Dec 16, 2020
@pnkfelix pnkfelix added P-critical Critical priority and removed P-high High priority labels Dec 17, 2020
@camelid
Copy link
Member

camelid commented Dec 17, 2020

So I'm trying to figure out which code is the culprit here. The inline_const PR is the one that introduced the regression, but looking at its changes I don't know if it's actual the underlying cause. I think the issue might be in the macro expansion code, but I'm not familiar with it at all.

Since this issue is P-critical and potentially a release blocker, I'm going to release my assignment so that someone more experienced can take it over. Though I'm happy to help if there's some way to do that!

@camelid camelid removed their assignment Dec 17, 2020
@camelid
Copy link
Member

camelid commented Dec 17, 2020

Actually, I just noticed that petrochenkov responded to my message asking for help finding the code 😄

@camelid camelid self-assigned this Dec 17, 2020
RalfJung added a commit to RalfJung/rust that referenced this issue Dec 18, 2020
@bors bors closed this as completed in 9269995 Dec 18, 2020
@camelid
Copy link
Member

camelid commented Dec 18, 2020

This should be fixed on the next nightly.

@Mark-Simulacrum
Copy link
Member Author

Reopening to track beta fix.

@Mark-Simulacrum
Copy link
Member Author

Should be backported to beta as part of #80417.

@camelid
Copy link
Member

camelid commented Dec 29, 2020

I think this can be closed as #80417 has been merged?

lf- added a commit to lf-/rust that referenced this issue Apr 26, 2021
This makes it possible to use `inline_const` (rust-lang#76001) and `let_chains`
(rust-lang#53667) inside macros' `expr` patterns in a future edition by
bifurcating the `expr` nonterminal in a similar way to `pat2021` to
remove some backwards compatibility exceptions that disallow
`const`/`let` at the beginning of an `expr` match.

Fixes rust-lang#84155 and relaxes the backward compat restriction from rust-lang#80135 for
a future edition. This is not intended to go into 2021 as it I don't
think it's simple to write an automatic fix, and certainly not now that
it's past the soft deadline for inclusion in 2021 by a long shot.

Here is a pathological case of rust-lang#79908 that forces this to be an edition
change:

```rust
macro_rules! evil {
    ($e:expr) => {
        // or something else
        const {$e-1}
    };
    (const $b:block) => {
        const {$b}
    }
}
fn main() {
    let x = 5;
    match x {
        evil!(const { 5 }) => panic!("oh no"),
        _ => (),
    };
}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) A-parser Area: The parsing of Rust source code to an AST ICEBreaker-Cleanup-Crew Helping to "clean up" bugs with minimal examples and bisections P-critical Critical priority regression-from-stable-to-beta Performance or correctness regression from stable to beta. 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.

8 participants