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

Cannot use => inside the body of a macro_rules for defining match arms #113766

Closed
TapGhoul opened this issue Jul 16, 2023 · 3 comments · Fixed by #113999
Closed

Cannot use => inside the body of a macro_rules for defining match arms #113766

TapGhoul opened this issue Jul 16, 2023 · 3 comments · Fixed by #113999
Labels
A-diagnostics Area: Messages for errors, warnings, and lints 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 D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@TapGhoul
Copy link

TapGhoul commented Jul 16, 2023

I tried this code:

enum MyEnum {
    A(i32),
    B(i32),
    C(i32)
}

macro_rules! broken {
    ($n:ident) => { MyEnum::$n(n) => n }
}

fn main() {
    let e = MyEnum::A(1);
    
    match e {
        broken!(A),
        broken!(B),
        broken!(C),
    }
}
Cargo expand output
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
enum MyEnum {
    A(i32),
    B(i32),
    C(i32),
}
fn main() {
    let e = MyEnum::A(1);
    match e {}
}

I expected to see this happen: It compiles successfully, generating my match arms.

Instead, this happened: Match arms are eaten in macro expansion (according to intellij-rust, as cargo-expand doesn't even show anything) - if I wrap the arm in () within the macro definition (i.e. (a => b)), it works, but this is not a valid match arm.

My understanding is that the macro is getting confused with the pattern:

macro_rules! my_macro {
    () => { () => {} }
}

It appears to see ) => { ( as a pattern

Meta

rustc --version --verbose:

rustc 1.71.0 (8ede3aae2 2023-07-12)
binary: rustc
commit-hash: 8ede3aae28fe6e4d52b38157d7bfe0d3bceef225
commit-date: 2023-07-12
host: x86_64-unknown-linux-gnu
release: 1.71.0
LLVM version: 16.0.5
Backtrace

❯ RUST_BACKTRACE=1 cargo build
   Compiling qwe v0.1.0 (/home/silvea/qwe)
error: unexpected `,` in pattern
  --> src/main.rs:15:19
   |
15 |         broken!(A),
   |                   ^
   |
help: try adding parentheses to match on a tuple...
   |
15 ~         (broken!(A),
16 |         broken!(B),
17 ~         broken!(C),)
   |
help: ...or a vertical bar to match on multiple alternatives
   |
15 ~         broken!(A) |
16 +         broken!(B) |
17 +         broken!(C) |
   |

warning: unused macro definition: `broken`
 --> src/main.rs:7:14
  |
7 | macro_rules! broken {
  |              ^^^^^^
  |
  = note: `#[warn(unused_macros)]` on by default

warning: `qwe` (bin "qwe") generated 1 warning
error: could not compile `qwe` (bin "qwe") due to previous error; 1 warning emitted

@TapGhoul TapGhoul added the C-bug Category: This is a bug. label Jul 16, 2023
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jul 16, 2023
@PatchMixolydic
Copy link
Contributor

PatchMixolydic commented Jul 16, 2023

Relevant output:

error: unexpected `,` in pattern
  --> src/lib.rs:19:55
   |
19 |         config_opt!(DoubleWaterfall, double_waterfall),
   |                                                       ^
   |
help: try adding parentheses to match on a tuple...
   |
19 ~         (config_opt!(DoubleWaterfall, double_waterfall),
20 ~         config_opt!(RoundRobin, round_robin),)
   |
help: ...or a vertical bar to match on multiple alternatives
   |
19 ~         config_opt!(DoubleWaterfall | double_waterfall) |
20 +         config_opt!(RoundRobin | round_robin) |
   |

According to the Rust Reference, macros are not permitted to expand to match arms, but they are allowed to expand to patterns. Therefore, while parsing this match expression:

match config {
    LoadBalancerConfig::BlackHole => Self::BlackHole,
    config_opt!(DoubleWaterfall, double_waterfall),
    config_opt!(RoundRobin, round_robin),
}

... the parser interprets the first config_opt! call as a pattern, then tries to consume either |, if, or =>. Since it finds none of those, it emits a diagnostic.

There should probably be a targeted diagnostic for macro invocation patterns followed by a comma in match expressions:

error: unexpected `,` in pattern
  --> src/lib.rs:19:55
   |
19 |         config_opt!(DoubleWaterfall, double_waterfall),
   |                                                       ^
   |
   = note: macros cannot expand to match arms

@TapGhoul
Copy link
Author

Ah, balls, my bad. I'll leave the issue open for the purpose of a diagnostic.

@fmease
Copy link
Member

fmease commented Jul 16, 2023

@rustbot label -needs-triage -C-bug T-compiler A-parser A-diagnostics A-macros D-terse

@rustbot rustbot added A-diagnostics Area: Messages for errors, warnings, and lints 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 D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. C-bug Category: This is a bug. labels Jul 16, 2023
@bors bors closed this as completed in 1f076fe Aug 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints 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 D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. 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.

4 participants