Skip to content

Commit 09b5fbd

Browse files
authored
Unrolled build for #145792
Rollup merge of #145792 - scrabsha:push-umpytyxunpxq, r=jdonszelmann Use attribute name in message for "outer attr used as inner attr" errors
2 parents 160e762 + a8e9ca1 commit 09b5fbd

22 files changed

+691
-213
lines changed

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ attr_parsing_invalid_repr_hint_no_value =
8686
attr_parsing_invalid_since =
8787
'since' must be a Rust version number, such as "1.31.0"
8888
89+
attr_parsing_invalid_style = {$is_used_as_inner ->
90+
[false] crate-level attribute should be an inner attribute: add an exclamation mark: `#![{$name}]`
91+
*[other] the `#![{$name}]` attribute can only be used at the crate root
92+
}
93+
.note = This attribute does not have an `!`, which means it is applied to this {$target}
94+
8995
attr_parsing_link_ordinal_out_of_range = ordinal value in `link_ordinal` is too large: `{$ordinal}`
9096
.note = the value may not exceed `u16::MAX`
9197

compiler/rustc_attr_parsing/src/attributes/crate_level.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use rustc_feature::AttributeType;
2+
13
use super::prelude::*;
24

35
pub(crate) struct CrateNameParser;
@@ -7,6 +9,7 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
79
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
810
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
911
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
12+
const TYPE: AttributeType = AttributeType::CrateLevel;
1013

1114
// FIXME: crate name is allowed on all targets and ignored,
1215
// even though it should only be valid on crates of course

compiler/rustc_attr_parsing/src/attributes/mod.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@
1212
//! - [`CombineAttributeParser`](crate::attributes::CombineAttributeParser): makes it easy to implement an attribute which should combine the
1313
//! contents of attributes, if an attribute appear multiple times in a list
1414
//!
15+
//! By default, attributes are allowed anywhere. When adding an attribute that should only be used
16+
//! at the crate root, consider setting the `TYPE` in the parser trait to
17+
//! [`AttributeType::CrateLevel`](rustc_feature::AttributeType::CrateLevel).
18+
//!
1519
//! Attributes should be added to `crate::context::ATTRIBUTE_PARSERS` to be parsed.
1620
1721
use std::marker::PhantomData;
1822

19-
use rustc_feature::{AttributeTemplate, template};
23+
use rustc_feature::{AttributeTemplate, AttributeType, template};
2024
use rustc_hir::attrs::AttributeKind;
2125
use rustc_span::{Span, Symbol};
2226
use thin_vec::ThinVec;
@@ -88,6 +92,8 @@ pub(crate) trait AttributeParser<S: Stage>: Default + 'static {
8892

8993
const ALLOWED_TARGETS: AllowedTargets;
9094

95+
const TYPE: AttributeType = AttributeType::Normal;
96+
9197
/// The parser has gotten a chance to accept the attributes on an item,
9298
/// here it can produce an attribute.
9399
///
@@ -129,6 +135,8 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
129135
/// The template this attribute parser should implement. Used for diagnostics.
130136
const TEMPLATE: AttributeTemplate;
131137

138+
const TYPE: AttributeType = AttributeType::Normal;
139+
132140
/// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
133141
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind>;
134142
}
@@ -175,6 +183,8 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
175183
)];
176184
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
177185

186+
const TYPE: AttributeType = T::TYPE;
187+
178188
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
179189
Some(self.1?.0)
180190
}
@@ -259,6 +269,7 @@ pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static {
259269
const PATH: &[Symbol];
260270
const ON_DUPLICATE: OnDuplicate<S>;
261271
const ALLOWED_TARGETS: AllowedTargets;
272+
const TYPE: AttributeType = AttributeType::Normal;
262273

263274
/// Create the [`AttributeKind`] given attribute's [`Span`].
264275
const CREATE: fn(Span) -> AttributeKind;
@@ -278,6 +289,7 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for Without
278289
const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
279290
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
280291
const TEMPLATE: AttributeTemplate = template!(Word);
292+
const TYPE: AttributeType = T::TYPE;
281293

282294
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
283295
if let Err(span) = args.no_args() {
@@ -311,6 +323,8 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
311323
/// The template this attribute parser should implement. Used for diagnostics.
312324
const TEMPLATE: AttributeTemplate;
313325

326+
const TYPE: AttributeType = AttributeType::Normal;
327+
314328
/// Converts a single syntactical attribute to a number of elements of the semantic attribute, or [`AttributeKind`]
315329
fn extend<'c>(
316330
cx: &'c mut AcceptContext<'_, '_, S>,
@@ -346,6 +360,7 @@ impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S
346360
group.items.extend(T::extend(cx, args))
347361
})];
348362
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
363+
const TYPE: AttributeType = T::TYPE;
349364

350365
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
351366
if let Some(first_span) = self.first_span {

compiler/rustc_attr_parsing/src/attributes/traits.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use std::mem;
22

3+
use rustc_feature::AttributeType;
4+
35
use super::prelude::*;
46
use crate::attributes::{
57
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
@@ -154,6 +156,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for CoherenceIsCoreParser {
154156
const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
155157
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
156158
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
159+
const TYPE: AttributeType = AttributeType::CrateLevel;
157160
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore;
158161
}
159162

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use std::ops::{Deref, DerefMut};
44
use std::sync::LazyLock;
55

66
use private::Sealed;
7-
use rustc_ast::{AttrStyle, MetaItemLit, NodeId};
7+
use rustc_ast::{AttrStyle, CRATE_NODE_ID, MetaItemLit, NodeId};
88
use rustc_errors::{Diag, Diagnostic, Level};
9-
use rustc_feature::AttributeTemplate;
9+
use rustc_feature::{AttributeTemplate, AttributeType};
1010
use rustc_hir::attrs::AttributeKind;
1111
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
12-
use rustc_hir::{AttrPath, HirId};
12+
use rustc_hir::{AttrPath, CRATE_HIR_ID, HirId};
1313
use rustc_session::Session;
1414
use rustc_span::{ErrorGuaranteed, Span, Symbol};
1515

@@ -80,6 +80,7 @@ pub(super) struct GroupTypeInnerAccept<S: Stage> {
8080
pub(super) template: AttributeTemplate,
8181
pub(super) accept_fn: AcceptFn<S>,
8282
pub(super) allowed_targets: AllowedTargets,
83+
pub(super) attribute_type: AttributeType,
8384
}
8485

8586
type AcceptFn<S> =
@@ -129,6 +130,7 @@ macro_rules! attribute_parsers {
129130
})
130131
}),
131132
allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
133+
attribute_type: <$names as crate::attributes::AttributeParser<$stage>>::TYPE,
132134
});
133135
}
134136

@@ -250,6 +252,8 @@ pub trait Stage: Sized + 'static + Sealed {
250252
) -> ErrorGuaranteed;
251253

252254
fn should_emit(&self) -> ShouldEmit;
255+
256+
fn id_is_crate_root(id: Self::Id) -> bool;
253257
}
254258

255259
// allow because it's a sealed trait
@@ -271,6 +275,10 @@ impl Stage for Early {
271275
fn should_emit(&self) -> ShouldEmit {
272276
self.emit_errors
273277
}
278+
279+
fn id_is_crate_root(id: Self::Id) -> bool {
280+
id == CRATE_NODE_ID
281+
}
274282
}
275283

276284
// allow because it's a sealed trait
@@ -292,6 +300,10 @@ impl Stage for Late {
292300
fn should_emit(&self) -> ShouldEmit {
293301
ShouldEmit::ErrorsAndLints
294302
}
303+
304+
fn id_is_crate_root(id: Self::Id) -> bool {
305+
id == CRATE_HIR_ID
306+
}
295307
}
296308

297309
/// used when parsing attributes for miscellaneous things *before* ast lowering

compiler/rustc_attr_parsing/src/interface.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
271271
};
272272

273273
(accept.accept_fn)(&mut cx, args);
274-
275-
if !matches!(self.stage.should_emit(), ShouldEmit::Nothing) {
274+
if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
275+
Self::check_type(accept.attribute_type, target, &mut cx);
276276
self.check_target(
277277
path.get_attribute_path(),
278278
attr.span,

compiler/rustc_attr_parsing/src/lints.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,19 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<L::Id>, lint_emi
6666
attr_span: *span,
6767
},
6868
),
69+
70+
&AttributeLintKind::InvalidStyle { ref name, is_used_as_inner, target, target_span } => {
71+
lint_emitter.emit_node_span_lint(
72+
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
73+
*id,
74+
*span,
75+
session_diagnostics::InvalidAttrStyle {
76+
name: name.clone(),
77+
is_used_as_inner,
78+
target_span: (!is_used_as_inner).then_some(target_span),
79+
target,
80+
},
81+
)
82+
}
6983
}
7084
}

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_errors::{
66
Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
77
};
88
use rustc_feature::AttributeTemplate;
9-
use rustc_hir::AttrPath;
9+
use rustc_hir::{AttrPath, Target};
1010
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
1111
use rustc_span::{Span, Symbol};
1212

@@ -826,3 +826,13 @@ pub(crate) struct SuffixedLiteralInAttribute {
826826
#[primary_span]
827827
pub span: Span,
828828
}
829+
830+
#[derive(LintDiagnostic)]
831+
#[diag(attr_parsing_invalid_style)]
832+
pub(crate) struct InvalidAttrStyle {
833+
pub name: AttrPath,
834+
pub is_used_as_inner: bool,
835+
#[note]
836+
pub target_span: Option<Span>,
837+
pub target: Target,
838+
}

compiler/rustc_attr_parsing/src/target_checking.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use std::borrow::Cow;
22

3+
use rustc_ast::AttrStyle;
34
use rustc_errors::DiagArgValue;
4-
use rustc_feature::Features;
5+
use rustc_feature::{AttributeType, Features};
56
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
67
use rustc_hir::{AttrPath, MethodKind, Target};
78
use rustc_span::Span;
89

910
use crate::AttributeParser;
10-
use crate::context::Stage;
11+
use crate::context::{AcceptContext, Stage};
1112
use crate::session_diagnostics::InvalidTarget;
1213

1314
#[derive(Debug)]
@@ -68,7 +69,7 @@ pub(crate) enum Policy {
6869
Error(Target),
6970
}
7071

71-
impl<S: Stage> AttributeParser<'_, S> {
72+
impl<'sess, S: Stage> AttributeParser<'sess, S> {
7273
pub(crate) fn check_target(
7374
&self,
7475
attr_name: AttrPath,
@@ -111,6 +112,32 @@ impl<S: Stage> AttributeParser<'_, S> {
111112
}
112113
}
113114
}
115+
116+
pub(crate) fn check_type(
117+
attribute_type: AttributeType,
118+
target: Target,
119+
cx: &mut AcceptContext<'_, 'sess, S>,
120+
) {
121+
let is_crate_root = S::id_is_crate_root(cx.target_id);
122+
123+
if is_crate_root {
124+
return;
125+
}
126+
127+
if attribute_type != AttributeType::CrateLevel {
128+
return;
129+
}
130+
131+
let lint = AttributeLintKind::InvalidStyle {
132+
name: cx.attr_path.clone(),
133+
is_used_as_inner: cx.attr_style == AttrStyle::Inner,
134+
target,
135+
target_span: cx.target_span,
136+
};
137+
let attr_span = cx.attr_span;
138+
139+
cx.emit_lint(lint, attr_span);
140+
}
114141
}
115142

116143
/// Takes a list of `allowed_targets` for an attribute, and the `target` the attribute was applied to.

compiler/rustc_hir/src/lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,5 @@ pub enum AttributeLintKind {
3535
IllFormedAttributeInput { suggestions: Vec<String> },
3636
EmptyAttribute { first_span: Span },
3737
InvalidTarget { name: AttrPath, target: Target, applied: Vec<String>, only: &'static str },
38+
InvalidStyle { name: AttrPath, is_used_as_inner: bool, target: Target, target_span: Span },
3839
}

0 commit comments

Comments
 (0)