Description
While reading libsyntax code, I came across this piece of code:
impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
fn visit_mac(&mut self, mac: &ast::Mac) {
let path = &mac.node.path;
let name = path.segments.last().unwrap().identifier.name.as_str();
// Issue 22234: If you add a new case here, make sure to also
// add code to catch the macro during or after expansion.
//
// We still keep this MacroVisitor (rather than *solely*
// relying on catching cases during or after expansion) to
// catch uses of these macros within conditionally-compiled
// code, e.g. `#[cfg]`-guarded functions.
// [...]
}
// [...]
}
The comment clearly states that this visitor (MacroVisitor, called by the driver using syntax::feature_gate::check_macros
) is there only to check use of such macros inside #[cfg]
-guarded code.
Except that this is not the case:
#[cfg(foo)]
fn pwet() { asm!() }
fn main() {}
This compiles on both stable and nightly. The reason for that is that the call to check_crate_macros
occur after the call to strip_unconfigured_items
. If we still want to catch those invocations, it should be the opposite, although this may have other implications (a comment above the call to strip_unconfigured_items
states that this must come before anything else because of #[cfg_attr]
, I'm not sure if this is relevant for feature-gate checking).
Otherwise, if we want to allow them, then this whole piece of code is useless and should be removed.
I think a lot of crates use #[cfg]
to differenciate between stable and nightly builds, especially crates using syntax extensions. For example, we might want to allow this:
#![cfg_attr(nightly, feature(asm))]
#[cfg(nightly)] fn main() { unsafe { asm!("") } }
#[cfg(not(nightly))] fn main() {}
(I took asm!()
as example here because it's one of the feature-gated macros but others might be more relevant I guess.)
(cc @pnkfelix: This is the weird thing I told you about earlier.)