Skip to content

Commit c316c05

Browse files
committed
refactor how eii expansion is wrapped fixing 149980
1 parent 897e88c commit c316c05

File tree

3 files changed

+38
-25
lines changed

3 files changed

+38
-25
lines changed

compiler/rustc_builtin_macros/src/eii.rs

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,18 @@ fn eii_(
6060
) -> Vec<Annotatable> {
6161
let eii_attr_span = ecx.with_def_site_ctxt(eii_attr_span);
6262

63-
let (item, stmt) = if let Annotatable::Item(item) = item {
64-
(item, false)
63+
let (item, wrap_item): (_, &dyn Fn(_) -> _) = if let Annotatable::Item(item) = item {
64+
(item, &Annotatable::Item)
6565
} else if let Annotatable::Stmt(ref stmt) = item
6666
&& let StmtKind::Item(ref item) = stmt.kind
6767
{
68-
(item.clone(), true)
68+
(item.clone(), &|item| {
69+
Annotatable::Stmt(Box::new(Stmt {
70+
id: DUMMY_NODE_ID,
71+
kind: StmtKind::Item(item),
72+
span: eii_attr_span,
73+
}))
74+
})
6975
} else {
7076
ecx.dcx().emit_err(EiiSharedMacroExpectedFunction {
7177
span: eii_attr_span,
@@ -74,23 +80,25 @@ fn eii_(
7480
return vec![item];
7581
};
7682

77-
let orig_item = item.clone();
78-
79-
let item = *item;
80-
81-
let ast::Item { attrs, id: _, span: _, vis, kind: ItemKind::Fn(func), tokens: _ } = item else {
83+
let ast::Item { attrs, id: _, span: _, vis, kind: ItemKind::Fn(func), tokens: _ } =
84+
item.as_ref()
85+
else {
8286
ecx.dcx().emit_err(EiiSharedMacroExpectedFunction {
8387
span: eii_attr_span,
8488
name: path_to_string(&meta_item.path),
8589
});
86-
return vec![Annotatable::Item(Box::new(item))];
90+
return vec![wrap_item(item)];
8791
};
92+
// only clone what we need
93+
let attrs = attrs.clone();
94+
let func = (**func).clone();
95+
let vis = vis.clone();
8896

8997
let attrs_from_decl =
9098
filter_attrs_for_multiple_eii_attr(ecx, attrs, eii_attr_span, &meta_item.path);
9199

92100
let Ok(macro_name) = name_for_impl_macro(ecx, &func, &meta_item) else {
93-
return vec![Annotatable::Item(orig_item)];
101+
return vec![wrap_item(item)];
94102
};
95103

96104
// span of the declaring item without attributes
@@ -115,7 +123,7 @@ fn eii_(
115123
ecx,
116124
eii_attr_span,
117125
item_span,
118-
*func,
126+
func,
119127
vis,
120128
&attrs_from_decl,
121129
)));
@@ -128,20 +136,7 @@ fn eii_(
128136
decl_span,
129137
)));
130138

131-
if stmt {
132-
return_items
133-
.into_iter()
134-
.map(|i| {
135-
Annotatable::Stmt(Box::new(Stmt {
136-
id: DUMMY_NODE_ID,
137-
kind: StmtKind::Item(i),
138-
span: eii_attr_span,
139-
}))
140-
})
141-
.collect()
142-
} else {
143-
return_items.into_iter().map(|i| Annotatable::Item(i)).collect()
144-
}
139+
return_items.into_iter().map(wrap_item).collect()
145140
}
146141

147142
/// Decide on the name of the macro that can be used to implement the EII.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
#![feature(extern_item_impls)]
2+
// EIIs can, despite not being super useful, be declared in statement position
3+
// nested inside items. Items in statement position, when expanded as part of a macro,
4+
// need to be wrapped slightly differently (in an `ast::Statement`).
5+
// We did this on the happy path (no errors), but when there was an error, we'd
6+
// replace it with *just* an `ast::Item` not wrapped in an `ast::Statement`.
7+
// This caused an ICE (https://github.com/rust-lang/rust/issues/149980).
8+
// this test fails to build, but demonstrates that no ICE is produced.
29

310
fn main() {
11+
struct Bar;
12+
413
#[eii]
14+
//~^ ERROR `#[eii]` is only valid on functions
515
impl Bar {}
616
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: `#[eii]` is only valid on functions
2+
--> $DIR/error_statement_position.rs:13:5
3+
|
4+
LL | #[eii]
5+
| ^^^^^^
6+
7+
error: aborting due to 1 previous error
8+

0 commit comments

Comments
 (0)