Skip to content

Commit df55233

Browse files
committed
disallow in statement position
1 parent 467a2d2 commit df55233

3 files changed

Lines changed: 35 additions & 18 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_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: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +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, EiiDecl, EiiImpl, ItemKind, MetaItem, Path, Stmt, StmtKind,
5-
Visibility, ast,
4+
Attribute, DUMMY_NODE_ID, EiiDecl, EiiImpl, ItemKind, MetaItem, Path, StmtKind, Visibility, ast,
65
};
76
use rustc_ast_pretty::pprust::path_to_string;
87
use rustc_expand::base::{Annotatable, ExtCtxt};
@@ -12,6 +11,7 @@ use thin_vec::{ThinVec, thin_vec};
1211
use crate::errors::{
1312
EiiExternTargetExpectedList, EiiExternTargetExpectedMacro, EiiExternTargetExpectedUnsafe,
1413
EiiMacroExpectedMaxOneArgument, EiiOnlyOnce, EiiSharedMacroExpectedFunction,
14+
EiiSharedMacroInStatementPosition,
1515
};
1616

1717
/// ```rust
@@ -55,29 +55,29 @@ fn eii_(
5555
ecx: &mut ExtCtxt<'_>,
5656
eii_attr_span: Span,
5757
meta_item: &ast::MetaItem,
58-
item: Annotatable,
58+
orig_item: Annotatable,
5959
impl_unsafe: bool,
6060
) -> Vec<Annotatable> {
6161
let eii_attr_span = ecx.with_def_site_ctxt(eii_attr_span);
6262

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
63+
let item = if let Annotatable::Item(item) = orig_item {
64+
item
65+
} else if let Annotatable::Stmt(ref stmt) = orig_item
6666
&& let StmtKind::Item(ref item) = stmt.kind
67+
&& let ItemKind::Fn(ref f) = item.kind
6768
{
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-
})
69+
ecx.dcx().emit_err(EiiSharedMacroInStatementPosition {
70+
span: eii_attr_span.to(item.span),
71+
name: path_to_string(&meta_item.path),
72+
item_span: f.ident.span,
73+
});
74+
return vec![orig_item];
7575
} else {
7676
ecx.dcx().emit_err(EiiSharedMacroExpectedFunction {
7777
span: eii_attr_span,
7878
name: path_to_string(&meta_item.path),
7979
});
80-
return vec![item];
80+
return vec![orig_item];
8181
};
8282

8383
let ast::Item { attrs, id: _, span: _, vis, kind: ItemKind::Fn(func), tokens: _ } =
@@ -87,7 +87,7 @@ fn eii_(
8787
span: eii_attr_span,
8888
name: path_to_string(&meta_item.path),
8989
});
90-
return vec![wrap_item(item)];
90+
return vec![Annotatable::Item(item)];
9191
};
9292
// only clone what we need
9393
let attrs = attrs.clone();
@@ -98,7 +98,9 @@ fn eii_(
9898
filter_attrs_for_multiple_eii_attr(ecx, attrs, eii_attr_span, &meta_item.path);
9999

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

104106
// span of the declaring item without attributes
@@ -136,7 +138,9 @@ fn eii_(
136138
&attrs_from_decl,
137139
));
138140

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

142146
/// Decide on the name of the macro that can be used to implement the EII.
@@ -213,7 +217,8 @@ fn generate_default_impl(
213217
known_eii_macro_resolution: Some(ast::EiiDecl {
214218
foreign_item: ecx.path(
215219
foreign_item_name.span,
216-
// prefix super to explicitly escape the const block generated below
220+
// prefix self to explicitly escape the const block generated below
221+
// NOTE: this is why EIIs can't be used on statements
217222
vec![Ident::from_str_and_span("self", foreign_item_name.span), foreign_item_name],
218223
),
219224
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_in_statement_position)]
1044+
pub(crate) struct EiiSharedMacroInStatementPosition {
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)