Skip to content

Commit a737217

Browse files
committed
test attr misuse
1 parent 0923d9a commit a737217

File tree

6 files changed

+242
-12
lines changed

6 files changed

+242
-12
lines changed

compiler/rustc_builtin_macros/messages.ftl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,13 @@ builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept a
150150
builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
151151
.suggestion = remove the value
152152
153+
builtin_macros_eii_macro_expected_function = `#[{$name}]` is only valid on functions
154+
builtin_macros_eii_macro_for_expected_list = `#[eii_macro_for(...)]` expects a list of one or two elements
155+
builtin_macros_eii_macro_for_expected_macro = `#[eii_macro_for(...)]` is only valid on macros
156+
builtin_macros_eii_macro_for_expected_max_one_argument = `#[{$name}]` expected no arguments or a single argument: `#[{$name}(default)]`
157+
builtin_macros_eii_macro_for_expected_unsafe = expected this argument to be "unsafe".
158+
.note = the second argument is optional
159+
153160
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
154161
.cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
155162
.custom = use `std::env::var({$var_expr})` to read the variable at run time

compiler/rustc_builtin_macros/src/eii.rs

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,50 @@
11
use rustc_ast::{DUMMY_NODE_ID, EIIImpl, EiiMacroFor, ItemKind, ast};
2+
use rustc_ast_pretty::pprust::path_to_string;
23
use rustc_expand::base::{Annotatable, ExtCtxt};
34
use rustc_span::{Span, kw};
45

6+
use crate::errors::{
7+
EIIMacroExpectedFunction, EIIMacroExpectedMaxOneArgument, EIIMacroForExpectedList,
8+
EIIMacroForExpectedMacro, EIIMacroForExpectedUnsafe,
9+
};
10+
511
pub(crate) fn eii_macro_for(
612
ecx: &mut ExtCtxt<'_>,
7-
_span: Span,
13+
span: Span,
814
meta_item: &ast::MetaItem,
915
mut item: Annotatable,
1016
) -> Vec<Annotatable> {
11-
let Annotatable::Item(i) = &mut item else { panic!("expected item") };
12-
let ItemKind::MacroDef(_, d) = &mut i.kind else { panic!("expected macro def") };
17+
let Annotatable::Item(i) = &mut item else {
18+
ecx.dcx().emit_err(EIIMacroForExpectedMacro { span });
19+
return vec![item];
20+
};
21+
let ItemKind::MacroDef(_, d) = &mut i.kind else {
22+
ecx.dcx().emit_err(EIIMacroForExpectedMacro { span });
23+
return vec![item];
24+
};
25+
26+
let Some(list) = meta_item.meta_item_list() else {
27+
ecx.dcx().emit_err(EIIMacroForExpectedList { span: meta_item.span });
28+
return vec![item];
29+
};
1330

14-
let Some(list) = meta_item.meta_item_list() else { panic!("expected list") };
31+
if list.len() > 2 {
32+
ecx.dcx().emit_err(EIIMacroForExpectedList { span: meta_item.span });
33+
return vec![item];
34+
}
1535

1636
let Some(extern_item_path) = list.get(0).and_then(|i| i.meta_item()).map(|i| i.path.clone())
1737
else {
18-
panic!("expected a path to an `extern` item");
38+
ecx.dcx().emit_err(EIIMacroForExpectedList { span: meta_item.span });
39+
return vec![item];
1940
};
2041

2142
let impl_unsafe = if let Some(i) = list.get(1) {
2243
if i.lit().and_then(|i| i.kind.str()).is_some_and(|i| i == kw::Unsafe) {
2344
true
2445
} else {
25-
panic!("expected the string `\"unsafe\"` here or no other arguments");
46+
ecx.dcx().emit_err(EIIMacroForExpectedUnsafe { span: i.span() });
47+
return vec![item];
2648
}
2749
} else {
2850
false
@@ -40,11 +62,32 @@ pub(crate) fn eii_macro(
4062
meta_item: &ast::MetaItem,
4163
mut item: Annotatable,
4264
) -> Vec<Annotatable> {
43-
let Annotatable::Item(i) = &mut item else { panic!("expected item") };
65+
let Annotatable::Item(i) = &mut item else {
66+
ecx.dcx()
67+
.emit_err(EIIMacroExpectedFunction { span, name: path_to_string(&meta_item.path) });
68+
return vec![item];
69+
};
4470

45-
let ItemKind::Fn(f) = &mut i.kind else { panic!("expected function") };
71+
let ItemKind::Fn(f) = &mut i.kind else {
72+
ecx.dcx()
73+
.emit_err(EIIMacroExpectedFunction { span, name: path_to_string(&meta_item.path) });
74+
return vec![item];
75+
};
4676

47-
assert!(meta_item.is_word());
77+
let is_default = if meta_item.is_word() {
78+
false
79+
} else if let Some([first]) = meta_item.meta_item_list()
80+
&& let Some(m) = first.meta_item()
81+
&& m.path.segments.len() == 1
82+
{
83+
m.path.segments[0].ident.name == kw::Default
84+
} else {
85+
ecx.dcx().emit_err(EIIMacroExpectedMaxOneArgument {
86+
span: meta_item.span,
87+
name: path_to_string(&meta_item.path),
88+
});
89+
return vec![item];
90+
};
4891

4992
f.eii_impl.push(EIIImpl {
5093
node_id: DUMMY_NODE_ID,

compiler/rustc_builtin_macros/src/errors.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,3 +1027,41 @@ pub(crate) struct NonGenericPointee {
10271027
#[primary_span]
10281028
pub span: Span,
10291029
}
1030+
1031+
#[derive(Diagnostic)]
1032+
#[diag(builtin_macros_eii_macro_for_expected_macro)]
1033+
pub(crate) struct EIIMacroForExpectedMacro {
1034+
#[primary_span]
1035+
pub span: Span,
1036+
}
1037+
1038+
#[derive(Diagnostic)]
1039+
#[diag(builtin_macros_eii_macro_for_expected_list)]
1040+
pub(crate) struct EIIMacroForExpectedList {
1041+
#[primary_span]
1042+
pub span: Span,
1043+
}
1044+
1045+
#[derive(Diagnostic)]
1046+
#[diag(builtin_macros_eii_macro_for_expected_unsafe)]
1047+
pub(crate) struct EIIMacroForExpectedUnsafe {
1048+
#[primary_span]
1049+
#[note]
1050+
pub span: Span,
1051+
}
1052+
1053+
#[derive(Diagnostic)]
1054+
#[diag(builtin_macros_eii_macro_expected_function)]
1055+
pub(crate) struct EIIMacroExpectedFunction {
1056+
#[primary_span]
1057+
pub span: Span,
1058+
pub name: String,
1059+
}
1060+
1061+
#[derive(Diagnostic)]
1062+
#[diag(builtin_macros_eii_macro_for_expected_max_one_argument)]
1063+
pub(crate) struct EIIMacroExpectedMaxOneArgument {
1064+
#[primary_span]
1065+
pub span: Span,
1066+
pub name: String,
1067+
}

compiler/rustc_hir_analysis/src/check/compare_eii.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use std::iter;
33

44
use rustc_data_structures::fx::FxIndexSet;
55
use rustc_errors::{
6-
Applicability, Applicability, E0050, E0053, E0053, E0053, struct_span_code_err,
7-
struct_span_code_err, struct_span_code_err,
6+
Applicability, E0050, E0053, E0053, E0053, struct_span_code_err, struct_span_code_err,
7+
struct_span_code_err,
88
};
99
use rustc_hir::def_id::{DefId, LocalDefId};
1010
use rustc_hir::{
@@ -14,7 +14,7 @@ use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
1414
use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
1515
use rustc_middle::ty;
1616
use rustc_middle::ty::TyCtxt;
17-
use rustc_middle::ty::error::{ExpectedFound, ExpectedFound, TypeError, TypeError, TypeError};
17+
use rustc_middle::ty::error::{ExpectedFound, TypeError, TypeError, TypeError};
1818
use rustc_span::{ErrorGuaranteed, Ident, Span};
1919
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
2020
use rustc_trait_selection::regions::InferCtxtRegionExt;

tests/ui/eii/errors.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//@ compile-flags: --crate-type rlib
2+
#![feature(eii)]
3+
#![feature(decl_macro)]
4+
#![feature(rustc_attrs)]
5+
#![feature(eii_internals)]
6+
7+
#[core::eii_macro_for(bar)] //~ ERROR `#[eii_macro_for(...)]` is only valid on macros
8+
fn hello() {
9+
#[core::eii_macro_for(bar)] //~ ERROR `#[eii_macro_for(...)]` is only valid on macros
10+
let x = 3 + 3;
11+
}
12+
13+
#[core::eii_macro_for] //~ ERROR `#[eii_macro_for(...)]` expects a list of one or two elements
14+
#[core::eii_macro_for()] //~ ERROR `#[eii_macro_for(...)]` expects a list of one or two elements
15+
#[core::eii_macro_for(bar, hello)] //~ ERROR expected this argument to be "unsafe"
16+
#[core::eii_macro_for(bar, "unsafe", hello)] //~ ERROR `#[eii_macro_for(...)]` expects a list of one or two elements
17+
#[core::eii_macro_for(bar, hello, "unsafe")] //~ ERROR `#[eii_macro_for(...)]` expects a list of one or two elements
18+
#[core::eii_macro_for = "unsafe"] //~ ERROR `#[eii_macro_for(...)]` expects a list of one or two elements
19+
#[core::eii_macro_for(bar)]
20+
#[rustc_builtin_macro(eii_macro)]
21+
macro foo() {}
22+
23+
unsafe extern "Rust" {
24+
safe fn bar(x: u64) -> u64;
25+
}
26+
27+
#[foo] //~ ERROR `#[foo]` is only valid on functions
28+
static X: u64 = 4;
29+
#[foo] //~ ERROR `#[foo]` is only valid on functions
30+
const Y: u64 = 4;
31+
#[foo] //~ ERROR `#[foo]` is only valid on functions
32+
macro bar() {}
33+
34+
#[foo()]
35+
//~^ ERROR `#[foo]` expected no arguments or a single argument: `#[foo(default)]`
36+
#[foo(default, bar)]
37+
//~^ ERROR `#[foo]` expected no arguments or a single argument: `#[foo(default)]`
38+
#[foo("default")]
39+
//~^ ERROR `#[foo]` expected no arguments or a single argument: `#[foo(default)]`
40+
#[foo = "default"]
41+
//~^ ERROR `#[foo]` expected no arguments or a single argument: `#[foo(default)]`
42+
fn other(x: u64) -> u64 {
43+
x
44+
}

tests/ui/eii/errors.stderr

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
error: `#[eii_macro_for(...)]` is only valid on macros
2+
--> $DIR/errors.rs:7:1
3+
|
4+
LL | #[core::eii_macro_for(bar)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: `#[eii_macro_for(...)]` is only valid on macros
8+
--> $DIR/errors.rs:9:5
9+
|
10+
LL | #[core::eii_macro_for(bar)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: `#[eii_macro_for(...)]` expects a list of one or two elements
14+
--> $DIR/errors.rs:13:1
15+
|
16+
LL | #[core::eii_macro_for]
17+
| ^^^^^^^^^^^^^^^^^^^^^^
18+
19+
error: `#[eii_macro_for(...)]` expects a list of one or two elements
20+
--> $DIR/errors.rs:14:1
21+
|
22+
LL | #[core::eii_macro_for()]
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^
24+
25+
error: expected this argument to be "unsafe".
26+
--> $DIR/errors.rs:15:28
27+
|
28+
LL | #[core::eii_macro_for(bar, hello)]
29+
| ^^^^^
30+
|
31+
note: the second argument is optional
32+
--> $DIR/errors.rs:15:28
33+
|
34+
LL | #[core::eii_macro_for(bar, hello)]
35+
| ^^^^^
36+
37+
error: `#[eii_macro_for(...)]` expects a list of one or two elements
38+
--> $DIR/errors.rs:16:1
39+
|
40+
LL | #[core::eii_macro_for(bar, "unsafe", hello)]
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42+
43+
error: `#[eii_macro_for(...)]` expects a list of one or two elements
44+
--> $DIR/errors.rs:17:1
45+
|
46+
LL | #[core::eii_macro_for(bar, hello, "unsafe")]
47+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
48+
49+
error: `#[eii_macro_for(...)]` expects a list of one or two elements
50+
--> $DIR/errors.rs:18:1
51+
|
52+
LL | #[core::eii_macro_for = "unsafe"]
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
54+
55+
error: `#[foo]` is only valid on functions
56+
--> $DIR/errors.rs:27:1
57+
|
58+
LL | #[foo]
59+
| ^^^^^^
60+
61+
error: `#[foo]` is only valid on functions
62+
--> $DIR/errors.rs:29:1
63+
|
64+
LL | #[foo]
65+
| ^^^^^^
66+
67+
error: `#[foo]` is only valid on functions
68+
--> $DIR/errors.rs:31:1
69+
|
70+
LL | #[foo]
71+
| ^^^^^^
72+
73+
error: `#[foo]` expected no arguments or a single argument: `#[foo(default)]`
74+
--> $DIR/errors.rs:34:1
75+
|
76+
LL | #[foo()]
77+
| ^^^^^^^^
78+
79+
error: `#[foo]` expected no arguments or a single argument: `#[foo(default)]`
80+
--> $DIR/errors.rs:36:1
81+
|
82+
LL | #[foo(default, bar)]
83+
| ^^^^^^^^^^^^^^^^^^^^
84+
85+
error: `#[foo]` expected no arguments or a single argument: `#[foo(default)]`
86+
--> $DIR/errors.rs:38:1
87+
|
88+
LL | #[foo("default")]
89+
| ^^^^^^^^^^^^^^^^^
90+
91+
error: `#[foo]` expected no arguments or a single argument: `#[foo(default)]`
92+
--> $DIR/errors.rs:40:1
93+
|
94+
LL | #[foo = "default"]
95+
| ^^^^^^^^^^^^^^^^^^
96+
97+
error: aborting due to 15 previous errors
98+

0 commit comments

Comments
 (0)