Skip to content
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

Attributes are reordered before they are passed to a proc-macro #67839

Closed
Luro02 opened this issue Jan 3, 2020 · 5 comments · Fixed by #82419
Closed

Attributes are reordered before they are passed to a proc-macro #67839

Luro02 opened this issue Jan 3, 2020 · 5 comments · Fixed by #82419
Assignees
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`) A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Luro02
Copy link
Contributor

Luro02 commented Jan 3, 2020

I am working on a proc-macro, where I would like to give the user the option, to decide, which attributes (and doc comments) should be forwarded.

For example

use shorthand::ShortHand;

#[derive(ShortHand)]
#[shorthand(enable(forward(doc)))]
/// This should be in the output
#[shorthand(disable(forward(doc)))]
/// This line should not.
#[shorthand(enable(forward(doc)))]
/// This should be in the output
struct Example {
    value: String,
}

as you can see in the above case, the order of the attributes is very important.
Sadly the rust compiler (or the proc_macro crate) does reorder the attributes, before passing them to the function as a TokenStream.

#![feature(prelude_import)]
#[prelude_import]                                                               
use std::prelude::v1::*;                                                        
#[macro_use]                                                                    
extern crate std;                                                               
use shorthand::ShortHand;                                                       
/// This should be in the output
/// This line should not.                                                       
/// This should be in the output                                                
#[shorthand(enable(forward(doc)))]
#[shorthand(disable(forward(doc)))]                                             
#[shorthand(enable(forward(doc)))]
struct Example {
    value: String,
}
#[allow(dead_code)]
impl Example {
    #[inline(always)]
    pub fn value(&self) -> &String {
        &self.value
    }
    #[inline(always)]
    pub fn set_value(&mut self, value: String) -> &mut Self {
        self.value = value;
        self
    }
}
#[allow(dead_code)]
fn main() {}
#[main]
pub fn main() -> () {
    extern crate test;
    test::test_main_static(&[])
}

(this is the output of cargo expand, the proc-macro gets a similar TokenStream, where the order is not preserved either)

I think this should not happen and the order should be preserved! Are there any good reasons for reordering them?

related to #36211

@Luro02 Luro02 changed the title Struct attributes are reordered before they are passed to a proc-macro Attributes are reordered before they are passed to a proc-macro Jan 3, 2020
@petrochenkov petrochenkov self-assigned this Jan 3, 2020
@petrochenkov
Copy link
Contributor

I agree that the relative order of inert attributes should be kept.
The reordering happens because built-in attributes (like doc comments) and non-builtin attributes are treated differently by macro expansion infrastructure.

I plan to fix this during the upcoming macro invocation collector rewrite (#54727 (comment)), unless someone gets to it earlier (this should be doable without rewriting the invocation collector entirely).

cc #63221

@Luro02
Copy link
Contributor Author

Luro02 commented Jan 3, 2020

I think this change can wait, until the new macro system is implemented, becuse this would be a breaking change either way. (for example the code given above would have different output, if a macro relies on the current order of attributes)

@jonas-schievink jonas-schievink added A-attributes Area: Attributes (`#[…]`, `#![…]`) A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 3, 2020
@pksunkara
Copy link
Contributor

Would this issue also include the proposal of ordering from rust-lang/reference#565 (comment)? If I currently write,

#[foo]
#[derive(Bar)]

As far as I observed: foo proc macro doesn't seem to get derive attribute because it looks like derive is expanded before it.

@petrochenkov
Copy link
Contributor

Fixed in #82419.

@pksunkara
I think your case is different, but it was recently addressed by #79078.

@pksunkara
Copy link
Contributor

@petrochenkov Really appreciate your hard work in fixing both the issues. I have reworked some of my APIs to not run into this, but I am happy that I can now pick the best ergonomics for my proc-macro libraries instead of trying to navigate these issues.

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Feb 24, 2021
expand: Preserve order of inert attributes during expansion

Fixes rust-lang#67839
Fixes rust-lang#81871
r? `@Aaron1011`
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Feb 24, 2021
expand: Preserve order of inert attributes during expansion

Fixes rust-lang#67839
Fixes rust-lang#81871
r? ``@Aaron1011``
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Feb 26, 2021
expand: Preserve order of inert attributes during expansion

Fixes rust-lang#67839
Fixes rust-lang#81871
r? ```@Aaron1011```
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Feb 27, 2021
expand: Preserve order of inert attributes during expansion

Fixes rust-lang#67839
Fixes rust-lang#81871
r? ````@Aaron1011````
@bors bors closed this as completed in 76b40d2 Feb 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`) A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants