Skip to content

Commit 65460c2

Browse files
authored
Unrolled build for #157312
Rollup merge of #157312 - jdonszelmann:reject-attrs-eii, r=JonathanBrouwer disallow most attrs on eiis Most attributes do not make sense on EIIs. Whether they're copied to the macro, default, or foreign item is also highly dependent per attribute. I was thinking of ways to configure this, though I don't think we need that kind of complexity rn. For now I just reject them all, except for ones that obviously make sense or are necessary for current usage in std. user attr macros are blanket-rejected with this too, which seems good, it seems cursed to present expanded eiis to them. r? @JonathanBrouwer
2 parents 48f976c + a492d4f commit 65460c2

6 files changed

Lines changed: 120 additions & 43 deletions

File tree

compiler/rustc_builtin_macros/src/eii.rs

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
1010
use thin_vec::{ThinVec, thin_vec};
1111

1212
use crate::errors::{
13-
EiiExternTargetExpectedList, EiiExternTargetExpectedMacro, EiiExternTargetExpectedUnsafe,
14-
EiiMacroExpectedMaxOneArgument, EiiOnlyOnce, EiiSharedMacroInStatementPosition,
15-
EiiSharedMacroTarget, EiiStaticArgumentRequired, EiiStaticDefault,
16-
EiiStaticMultipleImplementations, EiiStaticMutable,
13+
EiiAttributeNotSupported, EiiExternTargetExpectedList, EiiExternTargetExpectedMacro,
14+
EiiExternTargetExpectedUnsafe, EiiMacroExpectedMaxOneArgument, EiiOnlyOnce,
15+
EiiSharedMacroInStatementPosition, EiiSharedMacroTarget, EiiStaticArgumentRequired,
16+
EiiStaticDefault, EiiStaticMultipleImplementations, EiiStaticMutable,
1717
};
1818

1919
/// ```rust
@@ -128,6 +128,8 @@ fn eii_(
128128

129129
let attrs_from_decl =
130130
filter_attrs_for_multiple_eii_attr(ecx, attrs, eii_attr_span, &meta_item.path);
131+
let (macro_attrs, foreign_item_attrs, default_func_attrs) =
132+
split_attrs(ecx, item_span, attrs_from_decl);
131133

132134
let Ok(macro_name) = name_for_impl_macro(ecx, foreign_item_name, &meta_item) else {
133135
// we don't need to wrap in Annotatable::Stmt conditionally since
@@ -148,6 +150,7 @@ fn eii_(
148150
eii_attr_span,
149151
item_span,
150152
foreign_item_name,
153+
default_func_attrs,
151154
))
152155
}
153156

@@ -157,22 +160,65 @@ fn eii_(
157160
item_span,
158161
kind,
159162
vis,
160-
&attrs_from_decl,
163+
foreign_item_attrs,
161164
));
162165
module_items.push(generate_attribute_macro_to_implement(
163166
ecx,
164167
eii_attr_span,
165168
macro_name,
166169
foreign_item_name,
167170
impl_unsafe,
168-
&attrs_from_decl,
171+
macro_attrs,
169172
));
170173

171174
// we don't need to wrap in Annotatable::Stmt conditionally since
172175
// EII can't be used on items in statement position
173176
module_items.into_iter().map(Annotatable::Item).collect()
174177
}
175178

179+
fn split_attrs(
180+
ecx: &mut ExtCtxt<'_>,
181+
span: Span,
182+
attrs: ThinVec<Attribute>,
183+
) -> (ThinVec<Attribute>, ThinVec<Attribute>, ThinVec<Attribute>) {
184+
let mut macro_attributes = ThinVec::new();
185+
let mut foreign_item_attributes = ThinVec::new();
186+
let mut default_attributes = ThinVec::new();
187+
188+
for attr in attrs {
189+
match attr.name() {
190+
// Inline only matters for the default function being inlined into callsites
191+
Some(sym::inline) => default_attributes.push(attr),
192+
// If an eii is marked a lang item, that's because we want to call its declaration, so
193+
// mark the foreign item as the lang item
194+
Some(sym::lang) => foreign_item_attributes.push(attr),
195+
// Deprecating an eii means deprecating the macro and the foreign item
196+
Some(sym::deprecated) => {
197+
foreign_item_attributes.push(attr.clone());
198+
macro_attributes.push(attr);
199+
}
200+
// The stability of an EII affects the usage of the macro and calling the foreign item
201+
Some(sym::stable) | Some(sym::unstable) => {
202+
foreign_item_attributes.push(attr.clone());
203+
macro_attributes.push(attr);
204+
}
205+
// Doc attributes should be forwarded to the macro and the foreign item, since those are
206+
// the two items you interact with as a user.
207+
// FIXME: idk yet how EIIs show up in docs, might want to customize
208+
_ if attr.is_doc_comment() => {
209+
foreign_item_attributes.push(attr.clone());
210+
macro_attributes.push(attr);
211+
}
212+
Some(sym::eii) => unreachable!("should already be filtered out"),
213+
_ => {
214+
ecx.dcx().emit_err(EiiAttributeNotSupported { span, attr_span: attr.span() });
215+
}
216+
}
217+
}
218+
219+
(macro_attributes, foreign_item_attributes, default_attributes)
220+
}
221+
176222
/// Decide on the name of the macro that can be used to implement the EII.
177223
/// This is either an explicitly given name, or the name of the item in the
178224
/// declaration of the EII.
@@ -228,10 +274,8 @@ fn generate_default_func_impl(
228274
eii_attr_span: Span,
229275
item_span: Span,
230276
foreign_item_name: Ident,
277+
attrs: ThinVec<Attribute>,
231278
) -> Box<ast::Item> {
232-
// FIXME: re-add some original attrs
233-
let attrs = ThinVec::new();
234-
235279
let mut default_func = func.clone();
236280
default_func.eii_impls.push(EiiImpl {
237281
node_id: DUMMY_NODE_ID,
@@ -289,10 +333,9 @@ fn generate_foreign_item(
289333
item_span: Span,
290334
item_kind: &ItemKind,
291335
vis: Visibility,
292-
attrs_from_decl: &[Attribute],
336+
attrs_from_decl: ThinVec<Attribute>,
293337
) -> Box<ast::Item> {
294-
let mut foreign_item_attrs = ThinVec::new();
295-
foreign_item_attrs.extend_from_slice(attrs_from_decl);
338+
let mut foreign_item_attrs = attrs_from_decl;
296339

297340
// Add the rustc_eii_foreign_item on the foreign item. Usually, foreign items are mangled.
298341
// This attribute makes sure that we later know that this foreign item's symbol should not be.
@@ -381,13 +424,9 @@ fn generate_attribute_macro_to_implement(
381424
macro_name: Ident,
382425
foreign_item_name: Ident,
383426
impl_unsafe: bool,
384-
attrs_from_decl: &[Attribute],
427+
attrs_from_decl: ThinVec<Attribute>,
385428
) -> Box<ast::Item> {
386-
let mut macro_attrs = ThinVec::new();
387-
388-
// To avoid e.g. `error: attribute macro has missing stability attribute`
389-
// errors for eii's in std.
390-
macro_attrs.extend_from_slice(attrs_from_decl);
429+
let mut macro_attrs = attrs_from_decl;
391430

392431
// Avoid "missing stability attribute" errors for eiis in std. See #146993.
393432
macro_attrs.push(ecx.attr_name_value_str(sym::rustc_macro_transparency, sym::semiopaque, span));

compiler/rustc_builtin_macros/src/errors.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,6 +1186,15 @@ pub(crate) struct EiiMacroExpectedMaxOneArgument {
11861186
pub name: String,
11871187
}
11881188

1189+
#[derive(Diagnostic)]
1190+
#[diag("only a small subset of attributes are supported on externally implementable items")]
1191+
pub(crate) struct EiiAttributeNotSupported {
1192+
#[primary_span]
1193+
pub span: Span,
1194+
#[note("this attribute is not supported")]
1195+
pub attr_span: Span,
1196+
}
1197+
11891198
#[derive(Diagnostic)]
11901199
#[diag("named argument `{$named_arg_name}` is not used by name")]
11911200
pub(crate) struct NamedArgumentUsedPositionally {

tests/ui/eii/attrs.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#![feature(extern_item_impls)]
2+
#![deny(deprecated)] //~ NOTE:
3+
4+
// makes no sense on functions, nor on the macro generated (it's a macrov2).
5+
#[macro_export] //~ NOTE: this attribute is not supported
6+
// makes sense, as long as we only forward it onto the function,
7+
// so we allow and this shouln't cause errors for being on a "wrong target".
8+
#[inline]
9+
// makes sense, should be allowed, and forwarded on both the function and the macro
10+
#[deprecated = "foo"]
11+
#[eii]
12+
fn example() {}
13+
//~^ ERROR only a small subset of attributes are supported on externally implementable items
14+
15+
// check that both are deprecated vvvv
16+
#[example]
17+
//~^ ERROR use of deprecated macro
18+
fn explicit_impl() {}
19+
fn main() {
20+
example()
21+
//~^ ERROR use of deprecated function
22+
}

tests/ui/eii/attrs.stderr

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error: only a small subset of attributes are supported on externally implementable items
2+
--> $DIR/attrs.rs:12:1
3+
|
4+
LL | fn example() {}
5+
| ^^^^^^^^^^^^
6+
|
7+
note: this attribute is not supported
8+
--> $DIR/attrs.rs:5:1
9+
|
10+
LL | #[macro_export]
11+
| ^^^^^^^^^^^^^^^
12+
13+
error: use of deprecated macro `example`: foo
14+
--> $DIR/attrs.rs:16:3
15+
|
16+
LL | #[example]
17+
| ^^^^^^^
18+
|
19+
note: the lint level is defined here
20+
--> $DIR/attrs.rs:2:9
21+
|
22+
LL | #![deny(deprecated)]
23+
| ^^^^^^^^^^
24+
25+
error: use of deprecated function `example`: foo
26+
--> $DIR/attrs.rs:20:5
27+
|
28+
LL | example()
29+
| ^^^^^^^
30+
31+
error: aborting due to 3 previous errors
32+

tests/ui/eii/ice_contract_attr_on_eii_generated_item.rs

Lines changed: 0 additions & 11 deletions
This file was deleted.

tests/ui/eii/ice_contract_attr_on_eii_generated_item.stderr

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)