Skip to content

Commit

Permalink
Expand derive invocations in left-to-right order
Browse files Browse the repository at this point in the history
While derives were being collected in left-to-order order, the
corresponding `Invocation`s were being pushed in the wrong order.
  • Loading branch information
Aaron1011 committed Apr 10, 2021
1 parent 2e495d2 commit 21e6cc1
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 65 deletions.
12 changes: 9 additions & 3 deletions compiler/rustc_expand/src/expand.rs
Expand Up @@ -491,6 +491,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
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
Expand All @@ -512,14 +513,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
_ => 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,
Expand All @@ -546,7 +547,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
})
.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 {
Expand Down
40 changes: 20 additions & 20 deletions src/test/ui/macros/builtin-std-paths-fail.stderr
Expand Up @@ -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
|
Expand All @@ -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
Expand Down Expand Up @@ -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`.
32 changes: 16 additions & 16 deletions src/test/ui/proc-macro/attribute-after-derive.stdout
Expand Up @@ -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 {
Expand Down Expand Up @@ -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),
},
]
22 changes: 22 additions & 0 deletions 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);
14 changes: 14 additions & 0 deletions 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() {}
5 changes: 5 additions & 0 deletions 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 { }
16 changes: 8 additions & 8 deletions 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
|
Expand All @@ -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`.
36 changes: 18 additions & 18 deletions src/test/ui/union/union-derive.stderr
@@ -1,20 +1,14 @@
error: this trait cannot be derived for unions
--> $DIR/union-derive.rs:9:5
|
LL | Debug,
| ^^^^^

error: this trait cannot be derived for unions
--> $DIR/union-derive.rs:8:5
--> $DIR/union-derive.rs:4:5
|
LL | Default,
| ^^^^^^^
LL | PartialEq,
| ^^^^^^^^^

error: this trait cannot be derived for unions
--> $DIR/union-derive.rs:7:5
--> $DIR/union-derive.rs:5:5
|
LL | Hash,
| ^^^^
LL | PartialOrd,
| ^^^^^^^^^^

error: this trait cannot be derived for unions
--> $DIR/union-derive.rs:6:5
Expand All @@ -23,16 +17,22 @@ LL | Ord,
| ^^^

error: this trait cannot be derived for unions
--> $DIR/union-derive.rs:5:5
--> $DIR/union-derive.rs:7:5
|
LL | PartialOrd,
| ^^^^^^^^^^
LL | Hash,
| ^^^^

error: this trait cannot be derived for unions
--> $DIR/union-derive.rs:4:5
--> $DIR/union-derive.rs:8:5
|
LL | PartialEq,
| ^^^^^^^^^
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

0 comments on commit 21e6cc1

Please sign in to comment.