Skip to content

Commit e98914a

Browse files
committed
Update the logic based on a RFC
1 parent 2342f8e commit e98914a

File tree

6 files changed

+188
-69
lines changed

6 files changed

+188
-69
lines changed

compiler/rustc_passes/messages.ftl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ passes_attr_crate_level =
4949
passes_attr_only_in_functions =
5050
`{$attr}` attribute can only be used on functions
5151
52+
passes_attribute_not_allowed =
53+
The `[instruction_set]` attribute contains an invalid argument
54+
.label = Invalid argument in the `[instruction_set]` attribute
55+
5256
passes_autodiff_attr =
5357
`#[autodiff]` should be applied to a function
5458
.label = not a function
@@ -412,6 +416,10 @@ passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]
412416
413417
passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
414418
419+
passes_invalid_target_for_instruction_set =
420+
The `[instruction_set]` attribute is only allowed on functions
421+
.label = Invalid target for the `[instruction_set]` attribute
422+
415423
passes_lang_item_fn = {$name ->
416424
[panic_impl] `#[panic_handler]`
417425
*[other] `{$name}` lang item

compiler/rustc_passes/src/check_attr.rs

Lines changed: 100 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ use std::collections::hash_map::Entry;
1010
use rustc_ast::token::TokenKind;
1111
use rustc_ast::tokenstream::TokenTree;
1212
use rustc_ast::{
13-
AttrKind, AttrStyle, Attribute, LitKind, MetaItemInner, MetaItemKind, MetaItemLit, ast,
13+
ast, AttrKind, AttrStyle, Attribute, LitKind, MetaItemInner, MetaItemKind, MetaItemLit,
1414
};
1515
use rustc_data_structures::fx::FxHashMap;
1616
use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
17-
use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
17+
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
1818
use rustc_hir::def_id::LocalModDefId;
1919
use rustc_hir::intravisit::{self, Visitor};
2020
use rustc_hir::{
21-
self as hir, self, AssocItemKind, CRATE_HIR_ID, CRATE_OWNER_ID, FnSig, ForeignItem, HirId,
22-
Item, ItemKind, MethodKind, Safety, Target, TraitItem,
21+
self, self as hir, AssocItemKind, FnSig, FnSig, ForeignItem, ForeignItem, HirId, Item,
22+
ItemKind, MethodKind, Safety, Target, Target, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID,
2323
};
2424
use rustc_macros::LintDiagnostic;
2525
use rustc_middle::hir::nested_filter;
@@ -34,8 +34,8 @@ use rustc_session::lint::builtin::{
3434
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
3535
};
3636
use rustc_session::parse::feature_err;
37-
use rustc_span::symbol::{Symbol, kw, sym};
38-
use rustc_span::{BytePos, DUMMY_SP, Span};
37+
use rustc_span::symbol::{kw, sym, Symbol};
38+
use rustc_span::{BytePos, Span, DUMMY_SP};
3939
use rustc_target::abi::Size;
4040
use rustc_target::spec::abi::Abi;
4141
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
@@ -352,8 +352,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
352352
}
353353

354354
fn inline_attr_str_error_without_macro_def(&self, hir_id: HirId, attr: &Attribute, sym: &str) {
355-
self.tcx
356-
.emit_node_span_lint(UNUSED_ATTRIBUTES, hir_id, attr.span, errors::IgnoredAttr { sym });
355+
self.tcx.emit_node_span_lint(
356+
UNUSED_ATTRIBUTES,
357+
hir_id,
358+
attr.span,
359+
errors::IgnoredAttr { sym },
360+
);
357361
}
358362

359363
/// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl.
@@ -1420,10 +1424,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
14201424
_ => {
14211425
// FIXME: #[cold] was previously allowed on non-functions and some crates used
14221426
// this, so only emit a warning.
1423-
self.tcx.emit_node_span_lint(UNUSED_ATTRIBUTES, hir_id, attr.span, errors::Cold {
1424-
span,
1425-
on_crate: hir_id == CRATE_HIR_ID,
1426-
});
1427+
self.tcx.emit_node_span_lint(
1428+
UNUSED_ATTRIBUTES,
1429+
hir_id,
1430+
attr.span,
1431+
errors::Cold { span, on_crate: hir_id == CRATE_HIR_ID },
1432+
);
14271433
}
14281434
}
14291435
}
@@ -1438,9 +1444,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
14381444
return;
14391445
}
14401446

1441-
self.tcx.emit_node_span_lint(UNUSED_ATTRIBUTES, hir_id, attr.span, errors::Link {
1442-
span: (target != Target::ForeignMod).then_some(span),
1443-
});
1447+
self.tcx.emit_node_span_lint(
1448+
UNUSED_ATTRIBUTES,
1449+
hir_id,
1450+
attr.span,
1451+
errors::Link { span: (target != Target::ForeignMod).then_some(span) },
1452+
);
14441453
}
14451454

14461455
/// Checks if `#[link_name]` is applied to an item other than a foreign function or static.
@@ -1910,7 +1919,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
19101919
|| (int_reprs == 1
19111920
&& is_c
19121921
&& item.is_some_and(|item| {
1913-
if let ItemLike::Item(item) = item { is_c_like_enum(item) } else { false }
1922+
if let ItemLike::Item(item) = item {
1923+
is_c_like_enum(item)
1924+
} else {
1925+
false
1926+
}
19141927
}))
19151928
{
19161929
self.tcx.emit_node_span_lint(
@@ -2250,10 +2263,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
22502263
return;
22512264
};
22522265

2253-
self.tcx.emit_node_span_lint(UNUSED_ATTRIBUTES, hir_id, attr.span, errors::Unused {
2254-
attr_span: attr.span,
2255-
note,
2256-
});
2266+
self.tcx.emit_node_span_lint(
2267+
UNUSED_ATTRIBUTES,
2268+
hir_id,
2269+
attr.span,
2270+
errors::Unused { attr_span: attr.span, note },
2271+
);
22572272
}
22582273

22592274
/// A best effort attempt to create an error for a mismatching proc macro signature.
@@ -2409,40 +2424,75 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
24092424
}
24102425
}
24112426

2412-
fn check_instruction_set(&self, attr: &Attribute, _item: Option<ItemLike<'_>>) {
2413-
if let AttrKind::Normal(ref p) = attr.kind {
2414-
let inner_tokens = p.item.args.inner_tokens();
2415-
let mut tokens = inner_tokens.trees();
2416-
2417-
// Valid item for `instruction_set()` is:
2418-
// - arm::a32
2419-
// - arm::t32
2420-
match (tokens.next(), tokens.next(), tokens.next()) {
2421-
(
2422-
Some(TokenTree::Token(first_token, _)),
2423-
Some(TokenTree::Token(second_token, _)),
2424-
Some(TokenTree::Token(third_token, _)),
2425-
) => match (first_token.ident(), second_token.kind.clone(), third_token.ident()) {
2426-
(Some(first_ident), TokenKind::PathSep, Some(third_ident))
2427-
if first_ident.0.name == sym::arm =>
2428-
{
2429-
if third_ident.0.name == sym::a32 || third_ident.0.name == sym::t32 {
2430-
return;
2431-
} else {
2432-
self.dcx().emit_err(errors::InvalidInstructionSet { span: attr.span });
2433-
}
2434-
}
2435-
_ => {
2436-
self.dcx().emit_err(errors::InvalidInstructionSet { span: attr.span });
2427+
fn check_instruction_set(&self, attr: &Attribute, item: Option<ItemLike<'_>>) {
2428+
// Ensure the attribute is applied to a function or closure
2429+
match item {
2430+
Some(ItemLike::Item(inner_item)) => match inner_item.kind {
2431+
ItemKind::Fn(_, _, _) => {
2432+
// Validate the tokens for `instruction_set()` attribute
2433+
if let AttrKind::Normal(ref p) = attr.kind {
2434+
let inner_tokens = p.item.args.inner_tokens();
2435+
let mut tokens = inner_tokens.trees();
2436+
2437+
match (tokens.next(), tokens.next(), tokens.next()) {
2438+
(
2439+
Some(TokenTree::Token(first_token, _)),
2440+
Some(TokenTree::Token(second_token, _)),
2441+
Some(TokenTree::Token(third_token, _)),
2442+
) => match (
2443+
first_token.ident(),
2444+
second_token.kind.clone(),
2445+
third_token.ident(),
2446+
) {
2447+
(Some(first_ident), TokenKind::PathSep, Some(third_ident))
2448+
if first_ident.0.name == sym::arm =>
2449+
{
2450+
if third_ident.0.name == sym::a32
2451+
|| third_ident.0.name == sym::t32
2452+
{
2453+
return;
2454+
} else {
2455+
self.dcx().emit_err(errors::InvalidInstructionSet {
2456+
span: attr.span,
2457+
});
2458+
}
2459+
}
2460+
_ => {
2461+
self.dcx().emit_err(errors::InvalidInstructionSet {
2462+
span: attr.span,
2463+
});
2464+
}
2465+
},
2466+
(None, None, None) => {
2467+
self.dcx()
2468+
.emit_err(errors::EmptyInstructionSet { span: attr.span });
2469+
}
2470+
_ => {
2471+
self.dcx()
2472+
.emit_err(errors::InvalidInstructionSet { span: attr.span });
2473+
}
2474+
};
24372475
}
2438-
},
2439-
(None, None, None) => {
2440-
self.dcx().emit_err(errors::EmptyInstructionSet { span: attr.span });
24412476
}
24422477
_ => {
2443-
self.dcx().emit_err(errors::InvalidInstructionSet { span: attr.span });
2478+
self.dcx().emit_err(errors::InvalidTargetForInstructionSet {
2479+
span: attr.span,
2480+
item_kind: inner_item.kind.descr(),
2481+
});
2482+
return;
24442483
}
2445-
};
2484+
},
2485+
Some(ItemLike::ForeignItem) => {
2486+
self.dcx().emit_err(errors::InvalidTargetForInstructionSet {
2487+
span: attr.span,
2488+
item_kind: "foreign item",
2489+
});
2490+
return;
2491+
}
2492+
None => {
2493+
self.dcx().emit_err(errors::AttributeNotAllowed { span: attr.span });
2494+
return;
2495+
}
24462496
}
24472497
}
24482498
}

compiler/rustc_passes/src/errors.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,13 +697,28 @@ pub(crate) struct Linkage {
697697
pub span: Span,
698698
}
699699

700+
#[derive(Diagnostic)]
701+
#[diag(passes_attribute_not_allowed)]
702+
pub(crate) struct AttributeNotAllowed {
703+
#[primary_span]
704+
pub span: Span,
705+
}
706+
700707
#[derive(Diagnostic)]
701708
#[diag(passes_invalid_instruction_set)]
702709
pub(crate) struct InvalidInstructionSet {
703710
#[primary_span]
704711
pub span: Span,
705712
}
706713

714+
#[derive(Diagnostic)]
715+
#[diag(passes_invalid_target_for_instruction_set)]
716+
pub(crate) struct InvalidTargetForInstructionSet {
717+
#[primary_span]
718+
pub span: Span,
719+
pub item_kind: &'static str,
720+
}
721+
707722
#[derive(Diagnostic)]
708723
#[diag(passes_empty_instruction_set)]
709724
pub(crate) struct EmptyInstructionSet {
Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,49 @@
11
#![feature(stmt_expr_attributes)]
22

3+
#[cfg(target_arch = "arm")] // OK
34
#[instruction_set(arm::a32)]
4-
type ValidA = ();
5+
fn valid_a() {}
56

7+
#[cfg(target_arch = "arm")] // OK
68
#[instruction_set(arm::t32)]
7-
type ValidB = ();
9+
fn valid_b() {}
810

9-
#[instruction_set(asdfasdf)] //~ ERROR `[instruction_set]` attribute argument should be valid
11+
#[cfg(target_arch = "arm")] // OK
12+
struct MyStruct;
13+
14+
#[cfg(target_arch = "arm")]
15+
impl MyStruct {
16+
#[instruction_set(arm::a32)] // OK
17+
fn inherent_method(&self) {}
18+
}
19+
20+
trait MyTrait {
21+
#[cfg(target_arch = "arm")]
22+
#[instruction_set(arm::a32)] // OK
23+
fn trait_method() {
24+
println!("Trait method default implementation");
25+
}
26+
}
27+
28+
struct A;
29+
impl MyTrait for A {
30+
#[cfg(target_arch = "arm")]
31+
#[instruction_set(arm::t32)] // OK
32+
fn trait_method() {
33+
println!("Trait impl method");
34+
}
35+
}
36+
37+
#[instruction_set(asdfasdf)] //~ ERROR The `[instruction_set]` attribute is only allowed on functions
1038
type InvalidA = ();
1139

12-
#[instruction_set(asdfasdf)] //~ ERROR `[instruction_set]` attribute argument should be valid
40+
#[instruction_set(asdfasdf)] //~ ERROR The `[instruction_set]` attribute is only allowed on functions
1341
mod InvalidB {}
1442

15-
#[instruction_set(asdfasdf)] //~ ERROR `[instruction_set]` attribute argument should be valid
43+
#[instruction_set(asdfasdf)] //~ ERROR The `[instruction_set]` attribute is only allowed on functions
1644
struct InvalidC;
1745

1846
#[instruction_set(asdfasdf)] //~ ERROR `[instruction_set]` attribute argument should be valid
19-
impl InvalidC {}
47+
fn invalid_d() {}
2048

2149
fn main() {}

tests/ui/attributes/instruction-set.stderr

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
error: `[instruction_set]` attribute argument should be valid
2-
--> $DIR/instruction-set.rs:9:1
1+
error: The `[instruction_set]` attribute is only allowed on functions
2+
--> $DIR/instruction-set.rs:37:1
33
|
44
LL | #[instruction_set(asdfasdf)]
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66

7-
error: `[instruction_set]` attribute argument should be valid
8-
--> $DIR/instruction-set.rs:12:1
7+
error: The `[instruction_set]` attribute is only allowed on functions
8+
--> $DIR/instruction-set.rs:40:1
99
|
1010
LL | #[instruction_set(asdfasdf)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

13-
error: `[instruction_set]` attribute argument should be valid
14-
--> $DIR/instruction-set.rs:15:1
13+
error: The `[instruction_set]` attribute is only allowed on functions
14+
--> $DIR/instruction-set.rs:43:1
1515
|
1616
LL | #[instruction_set(asdfasdf)]
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1818

1919
error: `[instruction_set]` attribute argument should be valid
20-
--> $DIR/instruction-set.rs:18:1
20+
--> $DIR/instruction-set.rs:46:1
2121
|
2222
LL | #[instruction_set(asdfasdf)]
2323
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)