Skip to content

using inner tool attributes in crate root induces compiler error on intra-crate macro use #74087

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
bcantrill opened this issue Jul 6, 2020 · 6 comments
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`) A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) A-resolve Area: Name/path resolution done by `rustc_resolve` specifically C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@bcantrill
Copy link

Take a crate that has the following foo.rs, that contains a macro, foomacro()!:

#[macro_export]
macro_rules! foomacro {
    ($f:expr) => ({
        println!("foomacro: {}", $f);
    });
}

This macro is used in bar.rs:

use crate::foomacro;

pub fn bar() {
    foomacro!("bar");
}

Finally, here is the root of the crate and main.rs:

#![feature(custom_inner_attributes)]

// Setting any inner tool attribute here causes a compiler error on bar's use of
// foomacro!():
//
//   error: macro-expanded `macro_export` macros from the current crate cannot
//   be referred to by absolute paths
//
// To see this, uncomment either of the following lines:
//
// #![clippy::cyclomatic_complexity = "100"]
// #![rustfmt::skip]

mod foo;
mod bar;

fn main() {
    foomacro!("foo");
    bar::bar();
}

As the comment there indicates, as written, this compiles and runs as expected:

$ cargo run
   Compiling modmac v0.1.0 (/home/bmc/modmac)
    Finished dev [unoptimized + debuginfo] target(s) in 0.18s
     Running `target/debug/modmac`
foomacro: foo
foomacro: bar

If, however, either of the inner tool attributes is uncommented, the code fails on compiling bar.rs, complaining about its use of foomacro()!

$ cargo run
   Compiling modmac v0.1.0 (/home/bmc/modmac)
error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
 --> src/bar.rs:2:5
  |
2 | use crate::foomacro;
  |     ^^^^^^^^^^^^^^^
  |
  = note: `#[deny(macro_expanded_macro_exports_accessed_by_absolute_paths)]` on by default
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #52234 <https://github.com/rust-lang/rust/issues/52234>
note: the macro is defined here
 --> src/foo.rs:2:1
  |
2 | / macro_rules! foomacro {
3 | |     ($f:expr) => ({
4 | |         println!("foomacro: {}", $f);
5 | |     });
6 | | }
  | |_^

error: aborting due to previous error

error: could not compile `modmac`.

This behavior seems surprising, especially because tool attributes are generally thought to only be relevant to the specified tool:

When a tool is not in use, the tool's attributes are accepted without a warning. When the tool is in use, the tool is responsible for processing and interpretation of its attributes.

Thanks in advance for any consideration of this issue -- and apologies if this is an elaborate form of pilot error!

@bcantrill bcantrill added the C-bug Category: This is a bug. label Jul 6, 2020
@jonas-schievink jonas-schievink added A-attributes Area: Attributes (`#[…]`, `#![…]`) A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) A-resolve Area: Name/path resolution done by `rustc_resolve` specifically T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 6, 2020
@Kestrer
Copy link
Contributor

Kestrer commented Oct 28, 2020

I created a smaller example that reproduces the bug:

#[macro_export]
#[rustfmt::skip]
macro_rules! m {
    () => {};
}

#[macro_export]
macro_rules! other {
    () => {
        $crate::m!();
    }
}

other!();

@jonas-schievink
Copy link
Contributor

@petrochenkov might know what's going on there

@petrochenkov
Copy link
Contributor

custom_inner_attributes are happening, #54726 has an explanation of issues with them.
Custom attributes at crate level are a particularly tricky case.

@Kestrer
Copy link
Contributor

Kestrer commented Oct 28, 2020

This problem is actually unrelated to custom inner attributes, my example above reproduced it using only outer attributes.

@petrochenkov
Copy link
Contributor

petrochenkov commented Oct 28, 2020

Ah, I see, then it's #52234 (comment).

#[rustfmt::skip] is considered "potentially a macro" (because we need to resolve it to figure out whether it's a macro invocation or not), and it's enough to mark macro_rules! m { () => {}; } from the example above as "potentially macro-expanded" and trigger the condition.

@PoignardAzur
Copy link
Contributor

I've hit this problem recently and it's nasty.

A minimal example:

// Uncomment the following to trigger a compile error.
//#[rustfmt::skip]
mod my_macro {
    #[macro_export]
    macro_rules! my_macro {
        () => {
            "Hello world"
        };
    }
}

fn main() {
    println!(crate::my_macro!());
}

tamasfe added a commit to rhaiscript/lsp that referenced this issue Jun 30, 2022
I intended to keep it, however it's impossible to apply rustfmt::skip to it, causing diff issues.

related: rust-lang/rust#74087
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`) A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) A-resolve Area: Name/path resolution done by `rustc_resolve` specifically C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants