Skip to content

Hygiene of used macro item is weird. #95237

@chorman0773

Description

@chorman0773

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:
prescribed_meme

Metadata

Metadata

Assignees

Labels

A-hygieneArea: Macro hygieneA-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-resolveArea: Name/path resolution done by `rustc_resolve` specificallyC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions