While reading libsyntax code, I came across this piece of code: ``` rust 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: ``` rust #[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: ``` rust #![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.)