Repository navigation
proc_macro_attribute doesn't work on extern functions #48747
Description
Activity
I'm guessing that it's more like proc_macro_attribute doesn't work inside
extern {}blocks. I'd expect it to work on extern functions with Rust bodies:#[nop_attribute] pub extern fn foo() { // ... }But not on other item types inside
extern {}blocks:extern { #[nop_attribute] static mut FOO: u32; }My guess is that
InvocationCollectorisn't stepping intoextern {}blocks but I'll have to look at it.cc #38356
Yep, this
matchblock is missing a case forItemKind::ForeignMod: https://github.com/rust-lang/rust/blob/master/src/libsyntax/ext/expand.rs#L961-L1033@petrochenkov @nrc I can fix this one but it seems like a good mentoring bug since it might be that trivial or it might not be. I'm willing to mentor someone on it.
If you're willing to mentor, I'm willing to take this one and be the mentee. I've been wanting to contribute to Rust but the compiler is so big and complex that I haven't been sure how to break into it.
Sure, I've been wanting to mentor for a while now. I don't have a great grasp on the overall compiler architecture but I like to think I know my way around this bit of the frontend.
The
matchblock I linked is the likely culprit; this is the bit of the macros code that walks the syntax tree looking for invocations (bang!()and#[attribute]). It currently appears to be ignoringextern {}blocks (ast::ItemKind::ForeignMod) so a case for that needs to be added. It might be as simple as copying the case forItemKind::Modulebut I'm not sure; it's probably the best place to start though.If you need more active help we can meet up on IRC or something, I guess.
In fact it should be much simpler than
ItemKind::Modas you only need to fold over the individual items; you don't have to touch anything else that theModcase does because it has to worry about resolution scopes and whether the module is declared inline or in another file.- addedA-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)C-bugCategory: This is a bug.Category: This is a bug.
on Mar 6, 2018 Thanks for those tips. I've been fiddling with this code for the past few days, trying to better understand how it works and what's needed. Unfortunately, with the long build times and my complete lack of experience in the Rust codebase, this is proving to be a bigger time commitment than I'm currently able to embrace. I'll let someone else take this issue.
@nrc Working on this, would we consider this a discrepancy in where macro attributes are allowed (insta-stable) or a new unstable usage?
After doing more digging, my concern right now is that it appears
libsyntaxisn't setup to accept macro expansions insideextern {}blocks at all, so I'm wondering if we even want to expand attribute macros there. I've got some WIP code at abonander@3e20e2f and it's a lot further-reaching than I'd like it to be but that's about the bare minimum to make attributes inextern {}blocks work.@petrochenkov perhaps you'd like to weigh in
Working on this, would we consider this a discrepancy in where macro attributes are allowed (insta-stable) or a new unstable usage?
I think this should be behind a flag since I'm sure it's the kind of thing with unforeseen bugs that crop up. Ideally we can just put it behind the proc_macro feature, rather than creating a new one.
Why are extern blocks different to other blocks? I'd really hope that that sort of thing Just Works :-(
Why are extern blocks different to other blocks?
Presumably because they only support a subset of all item kinds.
ForeignItemvsItem. That would have to be enforced in parsing the macro output.In the process of enabling proc_macros here it wouldn't be a stretch to enable other macros as well, maybe all behind a
macros_in_externfeature?@petrochenkov What do you think of the previous comment?
Let me know if there's anyone else I should pull in on issues like this, I'm looking to knock out a bunch of them in quick succession.
If
mod m { call_macro!(); },trait Tr { call_macro!(); },impl [Tr for] Type { call_macro!(); }all work I see no reasons forextern "ABI" { call_macro!(); }not to work.I suspect it's not implemented yet just because the demand wasn't high enough.
So if I do enable all macros in
extern {}blocks should I put it behind a feature? The primary issue is that the kinds of items that macros can emit in this context are restricted, and that might surprise some people.So if I do enable all macros in extern {} blocks should I put it behind a feature?
Citing nikomatsakis, "Basically every time I've skipped a feature gate I've
regretted it."The primary issue is that the kinds of items that macros can emit in this context are restricted, and that might surprise some people.
This is equivalent to something that already exist:
macro make_struct() { struct S; } trait Tr { make_struct!(); // ERROR expected one of `const`, `extern`, `fn`, `type`, or `unsafe`, found `struct` } fn main() {}
Also see #48137 about how treatment of module/trait/impl/foreign items in macros can be made more uniform.
- added a commit that references this issue
on Apr 5, 2018
Given a
proc-macrocrate named demo_macros, which contains a singlenop_attributeprocedural macro:Given a lib crate named demo, which attempts to use the
nop_attributeprocedural macro on a function within anexternblock:Attempting to
cargo +nightly buildthis results in the following error:If I delete the
externblock and change the code to just be#[nop_attribute] pub fn fabs(_: f64) -> f64 { 0.0 }then it compiles just fine. For some reason, attempting to apply a procedural macro attribute to anexternfunction doesn't work.My
rustc --version:You can fully reproduce the issue by executing the following sequence of shell commands: