Rollup merge of #82419 - petrochenkov:inertord, r=Aaron1011
expand: Preserve order of inert attributes during expansion Fixes https://github.com/rust-lang/rust/issues/67839 Fixes https://github.com/rust-lang/rust/issues/81871 r? `````@Aaron1011`````
This commit is contained in:
commit
76b40d27e2
@ -301,6 +301,8 @@ pub enum InvocationKind {
|
||||
},
|
||||
Attr {
|
||||
attr: ast::Attribute,
|
||||
// Re-insertion position for inert attributes.
|
||||
pos: usize,
|
||||
item: Annotatable,
|
||||
// Required for resolving derive helper attributes.
|
||||
derives: Vec<Path>,
|
||||
@ -690,7 +692,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
InvocationKind::Attr { attr, mut item, derives } => match ext {
|
||||
InvocationKind::Attr { attr, pos, mut item, derives } => match ext {
|
||||
SyntaxExtensionKind::Attr(expander) => {
|
||||
self.gate_proc_macro_input(&item);
|
||||
self.gate_proc_macro_attr_item(span, &item);
|
||||
@ -721,7 +723,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
ExpandResult::Retry(item) => {
|
||||
// Reassemble the original invocation for retrying.
|
||||
return ExpandResult::Retry(Invocation {
|
||||
kind: InvocationKind::Attr { attr, item, derives },
|
||||
kind: InvocationKind::Attr { attr, pos, item, derives },
|
||||
..invoc
|
||||
});
|
||||
}
|
||||
@ -739,7 +741,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
if *mark_used {
|
||||
self.cx.sess.mark_attr_used(&attr);
|
||||
}
|
||||
item.visit_attrs(|attrs| attrs.push(attr));
|
||||
item.visit_attrs(|attrs| attrs.insert(pos, attr));
|
||||
fragment_kind.expect_from_annotatables(iter::once(item))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
@ -1000,17 +1002,20 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||
|
||||
fn collect_attr(
|
||||
&mut self,
|
||||
(attr, derives): (ast::Attribute, Vec<Path>),
|
||||
(attr, pos, derives): (ast::Attribute, usize, Vec<Path>),
|
||||
item: Annotatable,
|
||||
kind: AstFragmentKind,
|
||||
) -> AstFragment {
|
||||
self.collect(kind, InvocationKind::Attr { attr, item, derives })
|
||||
self.collect(kind, InvocationKind::Attr { attr, pos, item, derives })
|
||||
}
|
||||
|
||||
/// If `item` is an attribute invocation, remove the attribute and return it together with
|
||||
/// derives following it. We have to collect the derives in order to resolve legacy derive
|
||||
/// helpers (helpers written before derives that introduce them).
|
||||
fn take_first_attr(&mut self, item: &mut impl HasAttrs) -> Option<(ast::Attribute, Vec<Path>)> {
|
||||
/// its position and derives following it. We have to collect the derives in order to resolve
|
||||
/// legacy derive helpers (helpers written before derives that introduce them).
|
||||
fn take_first_attr(
|
||||
&mut self,
|
||||
item: &mut impl HasAttrs,
|
||||
) -> Option<(ast::Attribute, usize, Vec<Path>)> {
|
||||
let mut attr = None;
|
||||
|
||||
item.visit_attrs(|attrs| {
|
||||
@ -1033,7 +1038,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||
})
|
||||
.collect();
|
||||
|
||||
(attr, following_derives)
|
||||
(attr, attr_pos, following_derives)
|
||||
})
|
||||
});
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#![crate_type = "proc-macro"]
|
||||
|
||||
extern crate proc_macro;
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro::{TokenStream, TokenTree};
|
||||
|
||||
// Macro that return empty token stream.
|
||||
|
||||
@ -80,6 +80,10 @@ pub fn recollect_derive(input: TokenStream) -> TokenStream {
|
||||
// Macros that print their input in the original and re-collected forms (if they differ).
|
||||
|
||||
fn print_helper(input: TokenStream, kind: &str) -> TokenStream {
|
||||
print_helper_ext(input, kind, true)
|
||||
}
|
||||
|
||||
fn print_helper_ext(input: TokenStream, kind: &str, debug: bool) -> TokenStream {
|
||||
let input_display = format!("{}", input);
|
||||
let input_debug = format!("{:#?}", input);
|
||||
let recollected = input.into_iter().collect();
|
||||
@ -89,9 +93,11 @@ fn print_helper(input: TokenStream, kind: &str) -> TokenStream {
|
||||
if recollected_display != input_display {
|
||||
println!("PRINT-{} RE-COLLECTED (DISPLAY): {}", kind, recollected_display);
|
||||
}
|
||||
println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug);
|
||||
if recollected_debug != input_debug {
|
||||
println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug);
|
||||
if debug {
|
||||
println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug);
|
||||
if recollected_debug != input_debug {
|
||||
println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug);
|
||||
}
|
||||
}
|
||||
recollected
|
||||
}
|
||||
@ -108,8 +114,12 @@ pub fn print_bang_consume(input: TokenStream) -> TokenStream {
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn print_attr(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||
print_helper(input, "ATTR")
|
||||
pub fn print_attr(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let debug = match &args.into_iter().collect::<Vec<_>>()[..] {
|
||||
[TokenTree::Ident(ident)] if ident.to_string() == "nodebug" => false,
|
||||
_ => true,
|
||||
};
|
||||
print_helper_ext(input, "ATTR", debug)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
|
12
src/test/ui/proc-macro/derive-helper-legacy-spurious.rs
Normal file
12
src/test/ui/proc-macro/derive-helper-legacy-spurious.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// aux-build:test-macros.rs
|
||||
|
||||
#![dummy] //~ ERROR cannot find attribute `dummy` in this scope
|
||||
|
||||
#[macro_use]
|
||||
extern crate test_macros;
|
||||
|
||||
#[derive(Empty)] //~ ERROR cannot determine resolution for the attribute macro `derive`
|
||||
#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope
|
||||
struct Foo {}
|
||||
|
||||
fn main() {}
|
22
src/test/ui/proc-macro/derive-helper-legacy-spurious.stderr
Normal file
22
src/test/ui/proc-macro/derive-helper-legacy-spurious.stderr
Normal file
@ -0,0 +1,22 @@
|
||||
error: cannot find attribute `dummy` in this scope
|
||||
--> $DIR/derive-helper-legacy-spurious.rs:3:4
|
||||
|
|
||||
LL | #![dummy]
|
||||
| ^^^^^
|
||||
|
||||
error: cannot determine resolution for the attribute macro `derive`
|
||||
--> $DIR/derive-helper-legacy-spurious.rs:8:3
|
||||
|
|
||||
LL | #[derive(Empty)]
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: import resolution is stuck, try simplifying macro imports
|
||||
|
||||
error: cannot find attribute `empty_helper` in this scope
|
||||
--> $DIR/derive-helper-legacy-spurious.rs:9:3
|
||||
|
|
||||
LL | #[empty_helper]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
23
src/test/ui/proc-macro/inert-attribute-order.rs
Normal file
23
src/test/ui/proc-macro/inert-attribute-order.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// Order of inert attributes, both built-in and custom is preserved during expansion.
|
||||
|
||||
// check-pass
|
||||
// compile-flags: -Z span-debug
|
||||
// aux-build:test-macros.rs
|
||||
|
||||
#![no_std] // Don't load unnecessary hygiene information from std
|
||||
extern crate std;
|
||||
|
||||
#[macro_use]
|
||||
extern crate test_macros;
|
||||
|
||||
/// 1
|
||||
#[rustfmt::attr2]
|
||||
#[doc = "3"]
|
||||
#[print_attr(nodebug)]
|
||||
#[doc = "4"]
|
||||
#[rustfmt::attr5]
|
||||
/// 6
|
||||
#[print_attr(nodebug)]
|
||||
struct S;
|
||||
|
||||
fn main() {}
|
7
src/test/ui/proc-macro/inert-attribute-order.stdout
Normal file
7
src/test/ui/proc-macro/inert-attribute-order.stdout
Normal file
@ -0,0 +1,7 @@
|
||||
PRINT-ATTR INPUT (DISPLAY): /// 1
|
||||
#[rustfmt :: attr2] #[doc = "3"] #[doc = "4"] #[rustfmt :: attr5] /// 6
|
||||
#[print_attr(nodebug)] struct S ;
|
||||
PRINT-ATTR RE-COLLECTED (DISPLAY): #[doc = " 1"] #[rustfmt :: attr2] #[doc = "3"] #[doc = "4"]
|
||||
#[rustfmt :: attr5] #[doc = " 6"] #[print_attr(nodebug)] struct S ;
|
||||
PRINT-ATTR INPUT (DISPLAY): #[doc = " 1"] #[rustfmt :: attr2] #[doc = "3"] #[doc = "4"]
|
||||
#[rustfmt :: attr5] #[doc = " 6"] struct S ;
|
@ -1,4 +1,4 @@
|
||||
PRINT-ATTR INPUT (DISPLAY): #[allow(dead_code)] #[derive(Print)] #[print_helper(b)] #[print_helper(a)]
|
||||
PRINT-ATTR INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[derive(Print)] #[print_helper(b)]
|
||||
struct Foo < #[cfg(FALSE)] A, B >
|
||||
{
|
||||
#[cfg(FALSE)] first : String, #[cfg_attr(FALSE, deny(warnings))] second :
|
||||
@ -23,6 +23,31 @@ struct Foo < #[cfg(FALSE)] A, B >
|
||||
}], #[print_helper(d)] fourth : B
|
||||
}
|
||||
PRINT-ATTR INPUT (DEBUG): TokenStream [
|
||||
Punct {
|
||||
ch: '#',
|
||||
spacing: Alone,
|
||||
span: $DIR/issue-75930-derive-cfg.rs:16:1: 16:2 (#0),
|
||||
},
|
||||
Group {
|
||||
delimiter: Bracket,
|
||||
stream: TokenStream [
|
||||
Ident {
|
||||
ident: "print_helper",
|
||||
span: $DIR/issue-75930-derive-cfg.rs:16:3: 16:15 (#0),
|
||||
},
|
||||
Group {
|
||||
delimiter: Parenthesis,
|
||||
stream: TokenStream [
|
||||
Ident {
|
||||
ident: "a",
|
||||
span: $DIR/issue-75930-derive-cfg.rs:16:16: 16:17 (#0),
|
||||
},
|
||||
],
|
||||
span: $DIR/issue-75930-derive-cfg.rs:16:15: 16:18 (#0),
|
||||
},
|
||||
],
|
||||
span: $DIR/issue-75930-derive-cfg.rs:16:2: 16:19 (#0),
|
||||
},
|
||||
Punct {
|
||||
ch: '#',
|
||||
spacing: Alone,
|
||||
@ -98,31 +123,6 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
|
||||
],
|
||||
span: $DIR/issue-75930-derive-cfg.rs:21:2: 21:19 (#0),
|
||||
},
|
||||
Punct {
|
||||
ch: '#',
|
||||
spacing: Alone,
|
||||
span: $DIR/issue-75930-derive-cfg.rs:16:1: 16:2 (#0),
|
||||
},
|
||||
Group {
|
||||
delimiter: Bracket,
|
||||
stream: TokenStream [
|
||||
Ident {
|
||||
ident: "print_helper",
|
||||
span: $DIR/issue-75930-derive-cfg.rs:16:3: 16:15 (#0),
|
||||
},
|
||||
Group {
|
||||
delimiter: Parenthesis,
|
||||
stream: TokenStream [
|
||||
Ident {
|
||||
ident: "a",
|
||||
span: $DIR/issue-75930-derive-cfg.rs:16:16: 16:17 (#0),
|
||||
},
|
||||
],
|
||||
span: $DIR/issue-75930-derive-cfg.rs:16:15: 16:18 (#0),
|
||||
},
|
||||
],
|
||||
span: $DIR/issue-75930-derive-cfg.rs:16:2: 16:19 (#0),
|
||||
},
|
||||
Ident {
|
||||
ident: "struct",
|
||||
span: $DIR/issue-75930-derive-cfg.rs:22:1: 22:7 (#0),
|
||||
@ -1194,7 +1194,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
|
||||
span: $DIR/issue-75930-derive-cfg.rs:22:32: 65:2 (#0),
|
||||
},
|
||||
]
|
||||
PRINT-DERIVE INPUT (DISPLAY): #[allow(dead_code)] #[print_helper(b)] #[print_helper(a)] struct Foo < B >
|
||||
PRINT-DERIVE INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[print_helper(b)] struct Foo < B >
|
||||
{
|
||||
second : bool, third :
|
||||
[u8 ;
|
||||
@ -1208,6 +1208,31 @@ PRINT-DERIVE INPUT (DISPLAY): #[allow(dead_code)] #[print_helper(b)] #[print_hel
|
||||
}], #[print_helper(d)] fourth : B,
|
||||
}
|
||||
PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
||||
Punct {
|
||||
ch: '#',
|
||||
spacing: Alone,
|
||||
span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0),
|
||||
},
|
||||
Group {
|
||||
delimiter: Bracket,
|
||||
stream: TokenStream [
|
||||
Ident {
|
||||
ident: "print_helper",
|
||||
span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0),
|
||||
},
|
||||
Group {
|
||||
delimiter: Parenthesis,
|
||||
stream: TokenStream [
|
||||
Ident {
|
||||
ident: "a",
|
||||
span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0),
|
||||
},
|
||||
],
|
||||
span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0),
|
||||
},
|
||||
],
|
||||
span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0),
|
||||
},
|
||||
Punct {
|
||||
ch: '#',
|
||||
spacing: Alone,
|
||||
@ -1258,31 +1283,6 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
||||
],
|
||||
span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0),
|
||||
},
|
||||
Punct {
|
||||
ch: '#',
|
||||
spacing: Alone,
|
||||
span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0),
|
||||
},
|
||||
Group {
|
||||
delimiter: Bracket,
|
||||
stream: TokenStream [
|
||||
Ident {
|
||||
ident: "print_helper",
|
||||
span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0),
|
||||
},
|
||||
Group {
|
||||
delimiter: Parenthesis,
|
||||
stream: TokenStream [
|
||||
Ident {
|
||||
ident: "a",
|
||||
span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0),
|
||||
},
|
||||
],
|
||||
span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0),
|
||||
},
|
||||
],
|
||||
span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0),
|
||||
},
|
||||
Ident {
|
||||
ident: "struct",
|
||||
span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0),
|
||||
|
Loading…
x
Reference in New Issue
Block a user