Skip to content

Commit

Permalink
expand: Stop derive expansion un unexpected targets early
Browse files Browse the repository at this point in the history
Collect derive placeholders using `collect` instead of `push`
  • Loading branch information
petrochenkov committed Nov 19, 2020
1 parent ec54720 commit cd2177f
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 88 deletions.
60 changes: 35 additions & 25 deletions compiler/rustc_expand/src/expand.rs
Expand Up @@ -492,6 +492,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
self.cx.force_mode = force;

// FIXME(jseyfried): Refactor out the following logic
let fragment_kind = invoc.fragment_kind;
let (expanded_fragment, new_invocations) = match res {
InvocationRes::Single(ext) => match self.expand_invoc(invoc, &ext.kind) {
ExpandResult::Ready(fragment) => self.collect_invocations(fragment, &[]),
Expand All @@ -512,36 +513,45 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
InvocationRes::DeriveContainer(_exts) => {
// FIXME: Consider using the derive resolutions (`_exts`) immediately,
// instead of enqueuing the derives to be resolved again later.
let (derives, item) = match invoc.kind {
let (derives, mut item) = match invoc.kind {
InvocationKind::DeriveContainer { derives, item } => (derives, item),
_ => unreachable!(),
};
if !item.derive_allowed() {
let (item, derive_placeholders) = if !item.derive_allowed() {
self.error_derive_forbidden_on_non_adt(&derives, &item);
}
item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));
(item, Vec::new())
} else {
let mut item = StripUnconfigured {
sess: self.cx.sess,
features: self.cx.ecfg.features,
}
.fully_configure(item);
item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));

invocations.reserve(derives.len());
let derive_placeholders = derives
.into_iter()
.map(|path| {
let expn_id = ExpnId::fresh(None);
invocations.push((
Invocation {
kind: InvocationKind::Derive { path, item: item.clone() },
fragment_kind,
expansion_data: ExpansionData {
id: expn_id,
..self.cx.current_expansion.clone()
},
},
None,
));
NodeId::placeholder_from_expn_id(expn_id)
})
.collect::<Vec<_>>();
(item, derive_placeholders)
};

let mut item = self.fully_configure(item);
item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));

let mut derive_placeholders = Vec::with_capacity(derives.len());
invocations.reserve(derives.len());
for path in derives {
let expn_id = ExpnId::fresh(None);
derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id));
invocations.push((
Invocation {
kind: InvocationKind::Derive { path, item: item.clone() },
fragment_kind: invoc.fragment_kind,
expansion_data: ExpansionData {
id: expn_id,
..invoc.expansion_data.clone()
},
},
None,
));
}
let fragment =
invoc.fragment_kind.expect_from_annotatables(::std::iter::once(item));
let fragment = fragment_kind.expect_from_annotatables(::std::iter::once(item));
self.collect_invocations(fragment, &derive_placeholders)
}
};
Expand Down
1 change: 0 additions & 1 deletion src/test/ui/issues/issue-36617.rs
@@ -1,5 +1,4 @@
#![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
//~| ERROR cannot determine resolution for the derive macro `Copy`
//~| ERROR cannot determine resolution for the derive macro `Copy`

fn main() {}
10 changes: 1 addition & 9 deletions src/test/ui/issues/issue-36617.stderr
Expand Up @@ -12,14 +12,6 @@ LL | #![derive(Copy)]
|
= note: import resolution is stuck, try simplifying macro imports

error: cannot determine resolution for the derive macro `Copy`
--> $DIR/issue-36617.rs:1:11
|
LL | #![derive(Copy)]
| ^^^^
|
= note: import resolution is stuck, try simplifying macro imports

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0774`.
2 changes: 0 additions & 2 deletions src/test/ui/issues/issue-49934-errors.rs
@@ -1,10 +1,8 @@
fn foo<#[derive(Debug)] T>() {
//~^ ERROR `derive` may only be applied to structs, enums and unions
//~| ERROR expected an inert attribute, found a derive macro
match 0 {
#[derive(Debug)]
//~^ ERROR `derive` may only be applied to structs, enums and unions
//~| ERROR expected an inert attribute, found a derive macro
_ => (),
}
}
Expand Down
16 changes: 2 additions & 14 deletions src/test/ui/issues/issue-49934-errors.stderr
Expand Up @@ -4,24 +4,12 @@ error[E0774]: `derive` may only be applied to structs, enums and unions
LL | fn foo<#[derive(Debug)] T>() {
| ^^^^^^^^^^^^^^^^

error: expected an inert attribute, found a derive macro
--> $DIR/issue-49934-errors.rs:1:17
|
LL | fn foo<#[derive(Debug)] T>() {
| ^^^^^

error[E0774]: `derive` may only be applied to structs, enums and unions
--> $DIR/issue-49934-errors.rs:5:9
--> $DIR/issue-49934-errors.rs:4:9
|
LL | #[derive(Debug)]
| ^^^^^^^^^^^^^^^^

error: expected an inert attribute, found a derive macro
--> $DIR/issue-49934-errors.rs:5:18
|
LL | #[derive(Debug)]
| ^^^^^

error: aborting due to 4 previous errors
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0774`.
Expand Up @@ -4,7 +4,6 @@ struct CLI {
#[derive(parse())]
//~^ ERROR traits in `#[derive(...)]` don't accept arguments
//~| ERROR cannot find derive macro `parse` in this scope
//~| ERROR cannot find derive macro `parse` in this scope
path: (),
//~^ ERROR `derive` may only be applied to structs, enums and unions
}
10 changes: 2 additions & 8 deletions src/test/ui/malformed/issue-69341-malformed-derive-inert.stderr
Expand Up @@ -5,7 +5,7 @@ LL | #[derive(parse())]
| ^^ help: remove the arguments

error[E0774]: `derive` may only be applied to structs, enums and unions
--> $DIR/issue-69341-malformed-derive-inert.rs:8:5
--> $DIR/issue-69341-malformed-derive-inert.rs:7:5
|
LL | path: (),
| ^^^^^^^^
Expand All @@ -16,12 +16,6 @@ error: cannot find derive macro `parse` in this scope
LL | #[derive(parse())]
| ^^^^^

error: cannot find derive macro `parse` in this scope
--> $DIR/issue-69341-malformed-derive-inert.rs:4:14
|
LL | #[derive(parse())]
| ^^^^^

error: aborting due to 4 previous errors
error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0774`.
3 changes: 0 additions & 3 deletions src/test/ui/span/issue-43927-non-ADT-derive.rs
Expand Up @@ -5,9 +5,6 @@
//~| ERROR cannot determine resolution for the derive macro `Debug`
//~| ERROR cannot determine resolution for the derive macro `PartialEq`
//~| ERROR cannot determine resolution for the derive macro `Eq`
//~| ERROR cannot determine resolution for the derive macro `Debug`
//~| ERROR cannot determine resolution for the derive macro `PartialEq`
//~| ERROR cannot determine resolution for the derive macro `Eq`
struct DerivedOn;

fn main() {}
26 changes: 1 addition & 25 deletions src/test/ui/span/issue-43927-non-ADT-derive.stderr
Expand Up @@ -28,30 +28,6 @@ LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
|
= note: import resolution is stuck, try simplifying macro imports

error: cannot determine resolution for the derive macro `Eq`
--> $DIR/issue-43927-non-ADT-derive.rs:3:29
|
LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
| ^^
|
= note: import resolution is stuck, try simplifying macro imports

error: cannot determine resolution for the derive macro `PartialEq`
--> $DIR/issue-43927-non-ADT-derive.rs:3:18
|
LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
| ^^^^^^^^^
|
= note: import resolution is stuck, try simplifying macro imports

error: cannot determine resolution for the derive macro `Debug`
--> $DIR/issue-43927-non-ADT-derive.rs:3:11
|
LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
| ^^^^^
|
= note: import resolution is stuck, try simplifying macro imports

error: aborting due to 7 previous errors
error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0774`.

0 comments on commit cd2177f

Please sign in to comment.