Description
Thanks to Yandros (@danielhenrymantilla) and Kestrer on the Rust community server for finding this.
I tried this code:
fn main () {
fn f() -> i32 { 27 }
let _x = 0;
let f = || -> i32 { 42 };
let a = m!();
macro_rules! m {() => ( f() )} use m;
let b = m!();
assert_eq!(a, b);
}
I expected to see this happen: Compliation succeeds, no runtime output, runtime terminates successfully. Alternative, Compilation fails.
Instead, this happened: Compilation succeeds, assertion failure.
Meta
rustc --version --verbose
:
Tested on playground (https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=657f705b289bcd927a2f8a6407ae3dad) using stable (1.59), beta (1.60-beta.5), and nightly (1.61 (8d860b 2022-03-19)).
I have been unsuccessful in replicating this locally, including with the same stable, and another nightly from the same day (though not the same nightly: 3b348d9). Update, it reproduces locally in stable, beta, 8d860b nightly, and latest nightly, with --edition=2021
. Would probably help if I didn't use edition 2018 features w/o a --edition
flag.
Hygiene information was extracted using the playground nightly:
#![feature /* 602#0 */(prelude_import)]
#[prelude_import /* 990#1 */]
use std /* 1276#1 */::prelude /* 989#1 */::rust_2021 /* 1088#1 */::*;
#[macro_use /* 791#1 */]
extern crate std /* 1276#1 */;
fn main /* 794#0 */() {
fn f /* 592#0 */() -> i32 /* 688#0 */ { 27 }
let _x /* 1495#0 */ = 0;
let f /* 592#0 */ = || -> i32 /* 688#0 */ { 42 };
let a /* 1497#0 */ = f /* 592#4 */();
macro_rules! m /* 1498#0 */ { () => (f()) }
use m
/*
1498#0
*/;
let b /* 1499#0 */ = f /* 592#5 */();
}
/*
Expansions:
crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "m")
crate0::{{expn3}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "m")
crate1::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
crate1::{{expn450}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include")
crate1::{{expn451}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include")
crate2::{{expn579}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive")
crate2::{{expn603}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive")
SyntaxContexts:
#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque)
#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
#3: parent: #0, outer_mark: (crate1::{{expn1}}, Opaque)
#4: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
#5: parent: #0, outer_mark: (crate0::{{expn3}}, SemiTransparent)
*/
As instructed by the clean hygiene thread on the rust community discord, I attach the following meme to illustrate the bug: