Skip to content

Commit cd2177f

Browse files
committed
expand: Stop derive expansion un unexpected targets early
Collect derive placeholders using `collect` instead of `push`
1 parent ec54720 commit cd2177f

9 files changed

+41
-88
lines changed

compiler/rustc_expand/src/expand.rs

+35-25
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
492492
self.cx.force_mode = force;
493493

494494
// FIXME(jseyfried): Refactor out the following logic
495+
let fragment_kind = invoc.fragment_kind;
495496
let (expanded_fragment, new_invocations) = match res {
496497
InvocationRes::Single(ext) => match self.expand_invoc(invoc, &ext.kind) {
497498
ExpandResult::Ready(fragment) => self.collect_invocations(fragment, &[]),
@@ -512,36 +513,45 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
512513
InvocationRes::DeriveContainer(_exts) => {
513514
// FIXME: Consider using the derive resolutions (`_exts`) immediately,
514515
// instead of enqueuing the derives to be resolved again later.
515-
let (derives, item) = match invoc.kind {
516+
let (derives, mut item) = match invoc.kind {
516517
InvocationKind::DeriveContainer { derives, item } => (derives, item),
517518
_ => unreachable!(),
518519
};
519-
if !item.derive_allowed() {
520+
let (item, derive_placeholders) = if !item.derive_allowed() {
520521
self.error_derive_forbidden_on_non_adt(&derives, &item);
521-
}
522+
item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));
523+
(item, Vec::new())
524+
} else {
525+
let mut item = StripUnconfigured {
526+
sess: self.cx.sess,
527+
features: self.cx.ecfg.features,
528+
}
529+
.fully_configure(item);
530+
item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));
531+
532+
invocations.reserve(derives.len());
533+
let derive_placeholders = derives
534+
.into_iter()
535+
.map(|path| {
536+
let expn_id = ExpnId::fresh(None);
537+
invocations.push((
538+
Invocation {
539+
kind: InvocationKind::Derive { path, item: item.clone() },
540+
fragment_kind,
541+
expansion_data: ExpansionData {
542+
id: expn_id,
543+
..self.cx.current_expansion.clone()
544+
},
545+
},
546+
None,
547+
));
548+
NodeId::placeholder_from_expn_id(expn_id)
549+
})
550+
.collect::<Vec<_>>();
551+
(item, derive_placeholders)
552+
};
522553

523-
let mut item = self.fully_configure(item);
524-
item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));
525-
526-
let mut derive_placeholders = Vec::with_capacity(derives.len());
527-
invocations.reserve(derives.len());
528-
for path in derives {
529-
let expn_id = ExpnId::fresh(None);
530-
derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id));
531-
invocations.push((
532-
Invocation {
533-
kind: InvocationKind::Derive { path, item: item.clone() },
534-
fragment_kind: invoc.fragment_kind,
535-
expansion_data: ExpansionData {
536-
id: expn_id,
537-
..invoc.expansion_data.clone()
538-
},
539-
},
540-
None,
541-
));
542-
}
543-
let fragment =
544-
invoc.fragment_kind.expect_from_annotatables(::std::iter::once(item));
554+
let fragment = fragment_kind.expect_from_annotatables(::std::iter::once(item));
545555
self.collect_invocations(fragment, &derive_placeholders)
546556
}
547557
};

src/test/ui/issues/issue-36617.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
22
//~| ERROR cannot determine resolution for the derive macro `Copy`
3-
//~| ERROR cannot determine resolution for the derive macro `Copy`
43

54
fn main() {}

src/test/ui/issues/issue-36617.stderr

+1-9
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,6 @@ LL | #![derive(Copy)]
1212
|
1313
= note: import resolution is stuck, try simplifying macro imports
1414

15-
error: cannot determine resolution for the derive macro `Copy`
16-
--> $DIR/issue-36617.rs:1:11
17-
|
18-
LL | #![derive(Copy)]
19-
| ^^^^
20-
|
21-
= note: import resolution is stuck, try simplifying macro imports
22-
23-
error: aborting due to 3 previous errors
15+
error: aborting due to 2 previous errors
2416

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

src/test/ui/issues/issue-49934-errors.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
fn foo<#[derive(Debug)] T>() {
22
//~^ ERROR `derive` may only be applied to structs, enums and unions
3-
//~| ERROR expected an inert attribute, found a derive macro
43
match 0 {
54
#[derive(Debug)]
65
//~^ ERROR `derive` may only be applied to structs, enums and unions
7-
//~| ERROR expected an inert attribute, found a derive macro
86
_ => (),
97
}
108
}

src/test/ui/issues/issue-49934-errors.stderr

+2-14
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,12 @@ error[E0774]: `derive` may only be applied to structs, enums and unions
44
LL | fn foo<#[derive(Debug)] T>() {
55
| ^^^^^^^^^^^^^^^^
66

7-
error: expected an inert attribute, found a derive macro
8-
--> $DIR/issue-49934-errors.rs:1:17
9-
|
10-
LL | fn foo<#[derive(Debug)] T>() {
11-
| ^^^^^
12-
137
error[E0774]: `derive` may only be applied to structs, enums and unions
14-
--> $DIR/issue-49934-errors.rs:5:9
8+
--> $DIR/issue-49934-errors.rs:4:9
159
|
1610
LL | #[derive(Debug)]
1711
| ^^^^^^^^^^^^^^^^
1812

19-
error: expected an inert attribute, found a derive macro
20-
--> $DIR/issue-49934-errors.rs:5:18
21-
|
22-
LL | #[derive(Debug)]
23-
| ^^^^^
24-
25-
error: aborting due to 4 previous errors
13+
error: aborting due to 2 previous errors
2614

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

src/test/ui/malformed/issue-69341-malformed-derive-inert.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ struct CLI {
44
#[derive(parse())]
55
//~^ ERROR traits in `#[derive(...)]` don't accept arguments
66
//~| ERROR cannot find derive macro `parse` in this scope
7-
//~| ERROR cannot find derive macro `parse` in this scope
87
path: (),
98
//~^ ERROR `derive` may only be applied to structs, enums and unions
109
}

src/test/ui/malformed/issue-69341-malformed-derive-inert.stderr

+2-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | #[derive(parse())]
55
| ^^ help: remove the arguments
66

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

19-
error: cannot find derive macro `parse` in this scope
20-
--> $DIR/issue-69341-malformed-derive-inert.rs:4:14
21-
|
22-
LL | #[derive(parse())]
23-
| ^^^^^
24-
25-
error: aborting due to 4 previous errors
19+
error: aborting due to 3 previous errors
2620

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

src/test/ui/span/issue-43927-non-ADT-derive.rs

-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
//~| ERROR cannot determine resolution for the derive macro `Debug`
66
//~| ERROR cannot determine resolution for the derive macro `PartialEq`
77
//~| ERROR cannot determine resolution for the derive macro `Eq`
8-
//~| ERROR cannot determine resolution for the derive macro `Debug`
9-
//~| ERROR cannot determine resolution for the derive macro `PartialEq`
10-
//~| ERROR cannot determine resolution for the derive macro `Eq`
118
struct DerivedOn;
129

1310
fn main() {}

src/test/ui/span/issue-43927-non-ADT-derive.stderr

+1-25
Original file line numberDiff line numberDiff line change
@@ -28,30 +28,6 @@ LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
2828
|
2929
= note: import resolution is stuck, try simplifying macro imports
3030

31-
error: cannot determine resolution for the derive macro `Eq`
32-
--> $DIR/issue-43927-non-ADT-derive.rs:3:29
33-
|
34-
LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
35-
| ^^
36-
|
37-
= note: import resolution is stuck, try simplifying macro imports
38-
39-
error: cannot determine resolution for the derive macro `PartialEq`
40-
--> $DIR/issue-43927-non-ADT-derive.rs:3:18
41-
|
42-
LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
43-
| ^^^^^^^^^
44-
|
45-
= note: import resolution is stuck, try simplifying macro imports
46-
47-
error: cannot determine resolution for the derive macro `Debug`
48-
--> $DIR/issue-43927-non-ADT-derive.rs:3:11
49-
|
50-
LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
51-
| ^^^^^
52-
|
53-
= note: import resolution is stuck, try simplifying macro imports
54-
55-
error: aborting due to 7 previous errors
31+
error: aborting due to 4 previous errors
5632

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

0 commit comments

Comments
 (0)