Skip to content

Commit 7ecfbb3

Browse files
committed
disallow in statement position
1 parent 40bd698 commit 7ecfbb3

3 files changed

Lines changed: 34 additions & 16 deletions

File tree

compiler/rustc_builtin_macros/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ builtin_macros_eii_only_once = `#[{$name}]` can only be specified once
161161
162162
builtin_macros_eii_shared_macro_expected_function = `#[{$name}]` is only valid on functions
163163
builtin_macros_eii_shared_macro_expected_max_one_argument = `#[{$name}]` expected no arguments or a single argument: `#[{$name}(default)]`
164+
builtin_macros_eii_shared_macro_not_in_statement_position = `#[{$name}]` can only be used on functions inside a module
165+
.label = `#[{$name}]` is used on this item, which is part of another item's local scope
164166
165167
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
166168
.cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead

compiler/rustc_builtin_macros/src/eii.rs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use rustc_ast::token::{Delimiter, TokenKind};
22
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
33
use rustc_ast::{
4-
Attribute, DUMMY_NODE_ID, EiiExternTarget, EiiImpl, ItemKind, MetaItem, Path, Stmt, StmtKind,
4+
Attribute, DUMMY_NODE_ID, EiiExternTarget, EiiImpl, ItemKind, MetaItem, Path, StmtKind,
55
Visibility, ast,
66
};
77
use rustc_ast_pretty::pprust::path_to_string;
@@ -12,6 +12,7 @@ use thin_vec::{ThinVec, thin_vec};
1212
use crate::errors::{
1313
EiiExternTargetExpectedList, EiiExternTargetExpectedMacro, EiiExternTargetExpectedUnsafe,
1414
EiiMacroExpectedMaxOneArgument, EiiOnlyOnce, EiiSharedMacroExpectedFunction,
15+
EiiSharedMacroNotInStatementPosition,
1516
};
1617

1718
/// ```rust
@@ -55,29 +56,29 @@ fn eii_(
5556
ecx: &mut ExtCtxt<'_>,
5657
eii_attr_span: Span,
5758
meta_item: &ast::MetaItem,
58-
item: Annotatable,
59+
orig_item: Annotatable,
5960
impl_unsafe: bool,
6061
) -> Vec<Annotatable> {
6162
let eii_attr_span = ecx.with_def_site_ctxt(eii_attr_span);
6263

63-
let (item, wrap_item): (_, &dyn Fn(_) -> _) = if let Annotatable::Item(item) = item {
64-
(item, &Annotatable::Item)
65-
} else if let Annotatable::Stmt(ref stmt) = item
64+
let item = if let Annotatable::Item(item) = orig_item {
65+
item
66+
} else if let Annotatable::Stmt(ref stmt) = orig_item
6667
&& let StmtKind::Item(ref item) = stmt.kind
68+
&& let ItemKind::Fn(ref f) = item.kind
6769
{
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-
})
70+
ecx.dcx().emit_err(EiiSharedMacroNotInStatementPosition {
71+
span: eii_attr_span.to(item.span),
72+
name: path_to_string(&meta_item.path),
73+
item_span: f.ident.span,
74+
});
75+
return vec![orig_item];
7576
} else {
7677
ecx.dcx().emit_err(EiiSharedMacroExpectedFunction {
7778
span: eii_attr_span,
7879
name: path_to_string(&meta_item.path),
7980
});
80-
return vec![item];
81+
return vec![orig_item];
8182
};
8283

8384
let ast::Item { attrs, id: _, span: _, vis, kind: ItemKind::Fn(func), tokens: _ } =
@@ -87,7 +88,7 @@ fn eii_(
8788
span: eii_attr_span,
8889
name: path_to_string(&meta_item.path),
8990
});
90-
return vec![wrap_item(item)];
91+
return vec![Annotatable::Item(item)];
9192
};
9293
// only clone what we need
9394
let attrs = attrs.clone();
@@ -98,7 +99,9 @@ fn eii_(
9899
filter_attrs_for_multiple_eii_attr(ecx, attrs, eii_attr_span, &meta_item.path);
99100

100101
let Ok(macro_name) = name_for_impl_macro(ecx, &func, &meta_item) else {
101-
return vec![wrap_item(item)];
102+
// we don't need to wrap in Annotatable::Stmt conditionally since
103+
// EII can't be used on items in statement position
104+
return vec![Annotatable::Item(item)];
102105
};
103106

104107
// span of the declaring item without attributes
@@ -136,7 +139,9 @@ fn eii_(
136139
&attrs_from_decl,
137140
));
138141

139-
module_items.into_iter().map(wrap_item).collect()
142+
// we don't need to wrap in Annotatable::Stmt conditionally since
143+
// EII can't be used on items in statement position
144+
module_items.into_iter().map(Annotatable::Item).collect()
140145
}
141146

142147
/// Decide on the name of the macro that can be used to implement the EII.
@@ -214,6 +219,7 @@ fn generate_default_impl(
214219
extern_item_path: ecx.path(
215220
foreign_item_name.span,
216221
// prefix super to explicitly escape the const block generated below
222+
// NOTE: this is why EIIs can't be used on statements
217223
vec![Ident::from_str_and_span("self", foreign_item_name.span), foreign_item_name],
218224
),
219225
impl_unsafe,

compiler/rustc_builtin_macros/src/errors.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,16 @@ pub(crate) struct EiiSharedMacroExpectedFunction {
10391039
pub name: String,
10401040
}
10411041

1042+
#[derive(Diagnostic)]
1043+
#[diag(builtin_macros_eii_shared_macro_not_in_statement_position)]
1044+
pub(crate) struct EiiSharedMacroNotInStatementPosition {
1045+
#[primary_span]
1046+
pub span: Span,
1047+
pub name: String,
1048+
#[label]
1049+
pub item_span: Span,
1050+
}
1051+
10421052
#[derive(Diagnostic)]
10431053
#[diag(builtin_macros_eii_only_once)]
10441054
pub(crate) struct EiiOnlyOnce {

0 commit comments

Comments
 (0)