-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Process cfg_attr during expansion #22250
Comments
I can't answer whether it's something people often run into in practice, but I have run into this bug myself. |
Interesting; can you tell me more about the circumstances? |
I'm using the bitflags macro which generates a struct and allows me to declare decorators for that struct. Decorators such as #[cfg_attr(not(test), derive(Debug))]. |
Fails because of rust-lang/rust#22250
I've just run into this. I'm writing some FFI bindings that involve gating pretty much every function and type. As such, I wrote the following to attach attributes to groups of items: macro_rules! attr_block {
($(#[$attrs:meta])* {}) => {};
(
$(#[$attrs:meta])* {
$it:item $($tail:tt)*
}
) => {
$(#[$attrs])*
$it
attr_block! { $(#[$attrs])* {$($tail)*} }
};
} All is well until I started adding |
This also means that |
I have run into this in practice as well, I was trying to write a similar macro to @DanielKeep. I settled on making an inner module, but it's not a perfect solution in many ways. It would come up with crates like cfg-if as well. One really vexing thing about this bug is it's a silent failure. At least rustc should output a warning when it drops a cfg/cfg_attr without interpreting it. |
I'm currently looking into how to possibly fix this - it would likely involve restructuring how the compiler processes the config and expansion phases. |
cc @nrc |
I just ran into this issue. Here is basically what I was trying to do: macro_rules! foo {
() => {
#[cfg(feature = "nightly")]
const fn bar() {}
#[cfg(not(feature = "nightly"))]
fn bar() {}
};
}
foo!(); This fails with |
@Amanieu just hit the same issue. |
Hm, totally forgot that I was working on this at some point... If anyone had been waiting on me, I think I'd have to start work on this from scratch. |
This was fixed in #33706. |
Awesome, I didn't expect this to actually get fixed!
|
Nice! |
Shall this issue be closed? |
error_chain uses attributes on statements, stablized in Rust 1.13. Factor them out of functions in the non-backtrace codepath, making it possible to build a crate that uses error_chain with Rust 1.10. The backtrace feature still requires Rust 1.13 for attributes on statements, due to the impl_extract_backtrace macro, which needs to emit a function with one block for each linked error type, some of which may have attributes on them. And any code using compile-time conditionals in attributes on variants within an error_chain! invocation (which includes many of the tests and examples) will produce an error due to rust-lang/rust#22250 (fixed in Rust 1.11). But a crate using error_chain with default-features = false and avoiding such compile-time conditionals will now compile.
- Avoid using attributes on statements; use them on items instead. - Change a test to use std::env::VarError instead of std::fmt::Error, because the latter didn't impl Error until Rust 1.11. - Add an empty block after invocations of `error_chain!` inside functions, to work around rust-lang/rust#34436 (fixed in Rust 1.11). - Replace a single instance of `?` with `try!`. This still fails to work with 1.10 due to rust-lang/rust#22250 . Because of that issue, an invocation of `#[derive(Debug)]` inside a macro doesn't take cfg(...) attributes into account, and fails to compile due to referencing enum variants that don't exist. Posted for reference only.
- Avoid using attributes on statements; use them on items instead. - Change a test to use std::env::VarError instead of std::fmt::Error, because the latter didn't impl Error until Rust 1.11. - Add an empty block after invocations of `error_chain!` inside functions, to work around rust-lang/rust#34436 (fixed in Rust 1.11). - Replace a single instance of `?` with `try!`. This still fails to work with 1.10 due to rust-lang/rust#22250 . Because of that issue, an invocation of `#[derive(Debug)]` inside a macro doesn't take cfg(...) attributes into account, and fails to compile due to referencing enum variants that don't exist. Posted for reference only.
produces
I think what happens is the following:
# [ cfg_attr ( not ( test ) ...
means.derive
attribute, which matches aDecorator
in the syntax environment, so that extension also runs. There's no extension namedcfg_attr
so that attribute has no effect on expansion.#[derive(Debug)]
but not in time for syntax expansion to notice it.Previously,
cfg_attr
was a syntax extension, which had numerous drawbacks, but handled this case correctly.The somewhat obvious fix is to re-run
cfg_attr
processing on the AST subtree produced by every macro expansion, but I'd like to think about this more. I'd also like to know whether it's something people often run into in practice.Was mentioned on #19372. cc @sfackler, @SergioBenitez
The text was updated successfully, but these errors were encountered: