From 21e6cc19fe3740d4e8d45866b053e774fc010209 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 8 Apr 2021 21:35:24 -0400 Subject: [PATCH] Expand derive invocations in left-to-right order While derives were being collected in left-to-order order, the corresponding `Invocation`s were being pushed in the wrong order. --- compiler/rustc_expand/src/expand.rs | 12 +++-- .../ui/macros/builtin-std-paths-fail.stderr | 40 ++++++++-------- .../proc-macro/attribute-after-derive.stdout | 32 ++++++------- .../proc-macro/auxiliary/multiple-derives.rs | 22 +++++++++ src/test/ui/proc-macro/derive-expand-order.rs | 14 ++++++ .../ui/proc-macro/derive-expand-order.stdout | 5 ++ src/test/ui/proc-macro/issue-36935.stderr | 16 +++---- src/test/ui/union/union-derive.stderr | 48 +++++++++---------- 8 files changed, 118 insertions(+), 71 deletions(-) create mode 100644 src/test/ui/proc-macro/auxiliary/multiple-derives.rs create mode 100644 src/test/ui/proc-macro/derive-expand-order.rs create mode 100644 src/test/ui/proc-macro/derive-expand-order.stdout diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 0f4441d020b..27274f706e1 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -491,6 +491,7 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm let fragment_kind = invoc.fragment_kind; let (expanded_fragment, new_invocations) = match self.expand_invoc(invoc, &ext.kind) { ExpandResult::Ready(fragment) => { + let mut derive_invocations = Vec::new(); let derive_placeholders = self .cx .resolver @@ -512,14 +513,14 @@ enum AnnotatableRef<'a> { _ => unreachable!(), }; - invocations.reserve(derives.len()); + derive_invocations.reserve(derives.len()); derives .into_iter() .map(|(path, _exts)| { // FIXME: Consider using the derive resolutions (`_exts`) // instead of enqueuing the derives to be resolved again later. let expn_id = ExpnId::fresh(None); - invocations.push(( + derive_invocations.push(( Invocation { kind: InvocationKind::Derive { path, @@ -546,7 +547,12 @@ enum AnnotatableRef<'a> { }) .unwrap_or_default(); - self.collect_invocations(fragment, &derive_placeholders) + let (fragment, collected_invocations) = + self.collect_invocations(fragment, &derive_placeholders); + // We choose to expand any derive invocations associated with this macro invocation + // *before* any macro invocations collected from the output fragment + derive_invocations.extend(collected_invocations); + (fragment, derive_invocations) } ExpandResult::Retry(invoc) => { if force { diff --git a/src/test/ui/macros/builtin-std-paths-fail.stderr b/src/test/ui/macros/builtin-std-paths-fail.stderr index 4f1a76b0d6e..ba626101190 100644 --- a/src/test/ui/macros/builtin-std-paths-fail.stderr +++ b/src/test/ui/macros/builtin-std-paths-fail.stderr @@ -10,6 +10,18 @@ error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` LL | core::RustcDecodable, | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` +error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` + --> $DIR/builtin-std-paths-fail.rs:2:11 + | +LL | core::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` + +error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` + --> $DIR/builtin-std-paths-fail.rs:4:11 + | +LL | core::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` + error[E0433]: failed to resolve: could not find `bench` in `core` --> $DIR/builtin-std-paths-fail.rs:7:9 | @@ -34,17 +46,17 @@ error[E0433]: failed to resolve: could not find `test` in `core` LL | #[core::test] | ^^^^ could not find `test` in `core` -error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` - --> $DIR/builtin-std-paths-fail.rs:4:11 +error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` + --> $DIR/builtin-std-paths-fail.rs:14:10 | -LL | core::RustcDecodable, - | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` +LL | std::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` -error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` - --> $DIR/builtin-std-paths-fail.rs:2:11 +error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` + --> $DIR/builtin-std-paths-fail.rs:16:10 | -LL | core::RustcDecodable, - | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` +LL | std::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` --> $DIR/builtin-std-paths-fail.rs:14:10 @@ -82,18 +94,6 @@ error[E0433]: failed to resolve: could not find `test` in `std` LL | #[std::test] | ^^^^ could not find `test` in `std` -error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` - --> $DIR/builtin-std-paths-fail.rs:16:10 - | -LL | std::RustcDecodable, - | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` - -error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` - --> $DIR/builtin-std-paths-fail.rs:14:10 - | -LL | std::RustcDecodable, - | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` - error: aborting due to 16 previous errors For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/proc-macro/attribute-after-derive.stdout b/src/test/ui/proc-macro/attribute-after-derive.stdout index 11f49235327..d0b66551919 100644 --- a/src/test/ui/proc-macro/attribute-after-derive.stdout +++ b/src/test/ui/proc-macro/attribute-after-derive.stdout @@ -99,22 +99,6 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ span: $DIR/attribute-after-derive.rs:18:1: 21:2 (#0), }, ] -PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { } -PRINT-ATTR INPUT (DEBUG): TokenStream [ - Ident { - ident: "struct", - span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), - }, - Ident { - ident: "DeriveAttribute", - span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), - }, - Group { - delimiter: Brace, - stream: TokenStream [], - span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), - }, -] PRINT-DERIVE INPUT (DISPLAY): #[print_attr] struct DeriveAttribute { } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { @@ -146,3 +130,19 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), }, ] +PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), + }, + Ident { + ident: "DeriveAttribute", + span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), + }, +] diff --git a/src/test/ui/proc-macro/auxiliary/multiple-derives.rs b/src/test/ui/proc-macro/auxiliary/multiple-derives.rs new file mode 100644 index 00000000000..e3f6607b2ae --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/multiple-derives.rs @@ -0,0 +1,22 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +macro_rules! make_derives { + ($($name:ident),*) => { + $( + #[proc_macro_derive($name)] + pub fn $name(input: TokenStream) -> TokenStream { + println!("Derive {}: {}", stringify!($name), input); + TokenStream::new() + } + )* + } +} + +make_derives!(First, Second, Third, Fourth, Fifth); diff --git a/src/test/ui/proc-macro/derive-expand-order.rs b/src/test/ui/proc-macro/derive-expand-order.rs new file mode 100644 index 00000000000..0cf1ceb91de --- /dev/null +++ b/src/test/ui/proc-macro/derive-expand-order.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:multiple-derives.rs + +extern crate multiple_derives; + +use multiple_derives::*; + +#[derive(First)] +#[derive(Second)] +#[derive(Third, Fourth)] +#[derive(Fifth)] +pub struct Foo {} + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-expand-order.stdout b/src/test/ui/proc-macro/derive-expand-order.stdout new file mode 100644 index 00000000000..3ac1adf92c2 --- /dev/null +++ b/src/test/ui/proc-macro/derive-expand-order.stdout @@ -0,0 +1,5 @@ +Derive First: #[derive(Second)] #[derive(Third, Fourth)] #[derive(Fifth)] pub struct Foo { } +Derive Second: #[derive(Third, Fourth)] #[derive(Fifth)] pub struct Foo { } +Derive Third: #[derive(Fifth)] pub struct Foo { } +Derive Fourth: #[derive(Fifth)] pub struct Foo { } +Derive Fifth: pub struct Foo { } diff --git a/src/test/ui/proc-macro/issue-36935.stderr b/src/test/ui/proc-macro/issue-36935.stderr index 2b2e28fdb2f..079e134c6f8 100644 --- a/src/test/ui/proc-macro/issue-36935.stderr +++ b/src/test/ui/proc-macro/issue-36935.stderr @@ -1,11 +1,3 @@ -error: proc-macro derive panicked - --> $DIR/issue-36935.rs:6:20 - | -LL | #[derive(Identity, Panic)] - | ^^^^^ - | - = help: message: panic-derive - error[E0428]: the name `Baz` is defined multiple times --> $DIR/issue-36935.rs:7:1 | @@ -17,6 +9,14 @@ LL | struct Baz { | = note: `Baz` must be defined only once in the type namespace of this module +error: proc-macro derive panicked + --> $DIR/issue-36935.rs:6:20 + | +LL | #[derive(Identity, Panic)] + | ^^^^^ + | + = help: message: panic-derive + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/union/union-derive.stderr b/src/test/ui/union/union-derive.stderr index 919c6d5ceda..6ef72c901a5 100644 --- a/src/test/ui/union/union-derive.stderr +++ b/src/test/ui/union/union-derive.stderr @@ -1,26 +1,8 @@ error: this trait cannot be derived for unions - --> $DIR/union-derive.rs:9:5 + --> $DIR/union-derive.rs:4:5 | -LL | Debug, - | ^^^^^ - -error: this trait cannot be derived for unions - --> $DIR/union-derive.rs:8:5 - | -LL | Default, - | ^^^^^^^ - -error: this trait cannot be derived for unions - --> $DIR/union-derive.rs:7:5 - | -LL | Hash, - | ^^^^ - -error: this trait cannot be derived for unions - --> $DIR/union-derive.rs:6:5 - | -LL | Ord, - | ^^^ +LL | PartialEq, + | ^^^^^^^^^ error: this trait cannot be derived for unions --> $DIR/union-derive.rs:5:5 @@ -29,10 +11,28 @@ LL | PartialOrd, | ^^^^^^^^^^ error: this trait cannot be derived for unions - --> $DIR/union-derive.rs:4:5 + --> $DIR/union-derive.rs:6:5 | -LL | PartialEq, - | ^^^^^^^^^ +LL | Ord, + | ^^^ + +error: this trait cannot be derived for unions + --> $DIR/union-derive.rs:7:5 + | +LL | Hash, + | ^^^^ + +error: this trait cannot be derived for unions + --> $DIR/union-derive.rs:8:5 + | +LL | Default, + | ^^^^^^^ + +error: this trait cannot be derived for unions + --> $DIR/union-derive.rs:9:5 + | +LL | Debug, + | ^^^^^ error: aborting due to 6 previous errors