Skip to content

Commit 97847f0

Browse files
committed
Update the logic based on a RFC
1 parent fba7787 commit 97847f0

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;
@@ -349,8 +349,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
349349
}
350350

351351
fn inline_attr_str_error_without_macro_def(&self, hir_id: HirId, attr: &Attribute, sym: &str) {
352-
self.tcx
353-
.emit_node_span_lint(UNUSED_ATTRIBUTES, hir_id, attr.span, errors::IgnoredAttr { sym });
352+
self.tcx.emit_node_span_lint(
353+
UNUSED_ATTRIBUTES,
354+
hir_id,
355+
attr.span,
356+
errors::IgnoredAttr { sym },
357+
);
354358
}
355359

356360
/// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl.
@@ -1417,10 +1421,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
14171421
_ => {
14181422
// FIXME: #[cold] was previously allowed on non-functions and some crates used
14191423
// this, so only emit a warning.
1420-
self.tcx.emit_node_span_lint(UNUSED_ATTRIBUTES, hir_id, attr.span, errors::Cold {
1421-
span,
1422-
on_crate: hir_id == CRATE_HIR_ID,
1423-
});
1424+
self.tcx.emit_node_span_lint(
1425+
UNUSED_ATTRIBUTES,
1426+
hir_id,
1427+
attr.span,
1428+
errors::Cold { span, on_crate: hir_id == CRATE_HIR_ID },
1429+
);
14241430
}
14251431
}
14261432
}
@@ -1435,9 +1441,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
14351441
return;
14361442
}
14371443

1438-
self.tcx.emit_node_span_lint(UNUSED_ATTRIBUTES, hir_id, attr.span, errors::Link {
1439-
span: (target != Target::ForeignMod).then_some(span),
1440-
});
1444+
self.tcx.emit_node_span_lint(
1445+
UNUSED_ATTRIBUTES,
1446+
hir_id,
1447+
attr.span,
1448+
errors::Link { span: (target != Target::ForeignMod).then_some(span) },
1449+
);
14411450
}
14421451

14431452
/// Checks if `#[link_name]` is applied to an item other than a foreign function or static.
@@ -1907,7 +1916,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
19071916
|| (int_reprs == 1
19081917
&& is_c
19091918
&& item.is_some_and(|item| {
1910-
if let ItemLike::Item(item) = item { is_c_like_enum(item) } else { false }
1919+
if let ItemLike::Item(item) = item {
1920+
is_c_like_enum(item)
1921+
} else {
1922+
false
1923+
}
19111924
}))
19121925
{
19131926
self.tcx.emit_node_span_lint(
@@ -2247,10 +2260,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
22472260
return;
22482261
};
22492262

2250-
self.tcx.emit_node_span_lint(UNUSED_ATTRIBUTES, hir_id, attr.span, errors::Unused {
2251-
attr_span: attr.span,
2252-
note,
2253-
});
2263+
self.tcx.emit_node_span_lint(
2264+
UNUSED_ATTRIBUTES,
2265+
hir_id,
2266+
attr.span,
2267+
errors::Unused { attr_span: attr.span, note },
2268+
);
22542269
}
22552270

22562271
/// A best effort attempt to create an error for a mismatching proc macro signature.
@@ -2406,40 +2421,75 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
24062421
}
24072422
}
24082423

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

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)