Skip to content

Commit a577ea0

Browse files
Rewrite empty attribute lint
Signed-off-by: Jonathan Brouwer <jonathantbrouwer@gmail.com>
1 parent 1b61d43 commit a577ea0

File tree

27 files changed

+194
-190
lines changed

27 files changed

+194
-190
lines changed

compiler/rustc_attr_data_structures/src/attributes.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@ pub enum ReprAttr {
6767
ReprSimd,
6868
ReprTransparent,
6969
ReprAlign(Align),
70-
// this one is just so we can emit a lint for it
71-
ReprEmpty,
7270
}
7371
pub use ReprAttr::*;
7472

@@ -291,7 +289,7 @@ pub enum AttributeKind {
291289
PubTransparent(Span),
292290

293291
/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
294-
Repr(ThinVec<(ReprAttr, Span)>),
292+
Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span },
295293

296294
/// Represents `#[rustc_layout_scalar_valid_range_end]`.
297295
RustcLayoutScalarValidRangeEnd(Box<u128>, Span),

compiler/rustc_attr_data_structures/src/encode_cross_crate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ impl AttributeKind {
2626
Inline(..) => No,
2727
LinkSection { .. } => No,
2828
MacroTransparency(..) => Yes,
29-
Repr(..) => No,
29+
Repr { .. } => No,
3030
Stability { .. } => Yes,
3131
Cold(..) => No,
3232
ConstContinue(..) => No,

compiler/rustc_attr_data_structures/src/lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ pub struct AttributeLint<Id> {
1212
pub enum AttributeLintKind {
1313
UnusedDuplicate { this: Span, other: Span, warning: bool },
1414
IllFormedAttributeInput { suggestions: Vec<String> },
15+
EmptyAttribute { first_span: Span },
1516
}

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ attr_parsing_deprecated_item_suggestion =
66
.help = add `#![feature(deprecated_suggestion)]` to the crate root
77
.note = see #94785 for more details
88
9+
attr_parsing_empty_attribute =
10+
unused attribute
11+
.suggestion = remove this attribute
12+
913
attr_parsing_empty_confusables =
1014
expected at least one confusable name
1115
attr_parsing_expected_one_cfg_pattern =

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,10 @@ impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser {
298298
cx.expected_list(cx.attr_span);
299299
return features;
300300
};
301+
if list.is_empty() {
302+
cx.warn_empty_attribute(cx.attr_span);
303+
return features;
304+
}
301305
for item in list.mixed() {
302306
let Some(name_value) = item.meta_item() else {
303307
cx.expected_name_value(item.span(), Some(sym::enable));

compiler/rustc_attr_parsing/src/attributes/repr.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ pub(crate) struct ReprParser;
2323
impl<S: Stage> CombineAttributeParser<S> for ReprParser {
2424
type Item = (ReprAttr, Span);
2525
const PATH: &[Symbol] = &[sym::repr];
26-
const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::Repr(items);
26+
const CONVERT: ConvertFn<Self::Item> =
27+
|items, first_span| AttributeKind::Repr { reprs: items, first_span };
2728
// FIXME(jdonszelmann): never used
2829
const TEMPLATE: AttributeTemplate =
2930
template!(List: "C | Rust | align(...) | packed(...) | <integer type> | transparent");
@@ -40,8 +41,8 @@ impl<S: Stage> CombineAttributeParser<S> for ReprParser {
4041
};
4142

4243
if list.is_empty() {
43-
// this is so validation can emit a lint
44-
reprs.push((ReprAttr::ReprEmpty, cx.attr_span));
44+
cx.warn_empty_attribute(cx.attr_span);
45+
return reprs;
4546
}
4647

4748
for param in list.mixed() {

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ mod private {
160160
#[allow(private_interfaces)]
161161
pub trait Stage: Sized + 'static + Sealed {
162162
type Id: Copy;
163+
const SHOULD_EMIT_LINTS: bool;
163164

164165
fn parsers() -> &'static group_type!(Self);
165166

@@ -170,6 +171,7 @@ pub trait Stage: Sized + 'static + Sealed {
170171
#[allow(private_interfaces)]
171172
impl Stage for Early {
172173
type Id = NodeId;
174+
const SHOULD_EMIT_LINTS: bool = false;
173175

174176
fn parsers() -> &'static group_type!(Self) {
175177
&early::ATTRIBUTE_PARSERS
@@ -183,6 +185,7 @@ impl Stage for Early {
183185
#[allow(private_interfaces)]
184186
impl Stage for Late {
185187
type Id = HirId;
188+
const SHOULD_EMIT_LINTS: bool = true;
186189

187190
fn parsers() -> &'static group_type!(Self) {
188191
&late::ATTRIBUTE_PARSERS
@@ -223,6 +226,9 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
223226
/// must be delayed until after HIR is built. This method will take care of the details of
224227
/// that.
225228
pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
229+
if !S::SHOULD_EMIT_LINTS {
230+
return;
231+
}
226232
let id = self.target_id;
227233
(self.emit_lint)(AttributeLint { id, span, kind: lint });
228234
}
@@ -404,6 +410,10 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
404410
},
405411
})
406412
}
413+
414+
pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
415+
self.emit_lint(AttributeLintKind::EmptyAttribute { first_span: span }, span);
416+
}
407417
}
408418

409419
impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {

compiler/rustc_attr_parsing/src/lints.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,11 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi
2828
},
2929
);
3030
}
31+
AttributeLintKind::EmptyAttribute { first_span } => lint_emitter.emit_node_span_lint(
32+
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
33+
*id,
34+
*first_span,
35+
session_diagnostics::EmptyAttributeList { attr_span: *first_span },
36+
),
3137
}
3238
}

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,13 @@ pub(crate) struct EmptyConfusables {
473473
pub span: Span,
474474
}
475475

476+
#[derive(LintDiagnostic)]
477+
#[diag(attr_parsing_empty_attribute)]
478+
pub(crate) struct EmptyAttributeList {
479+
#[suggestion(code = "", applicability = "machine-applicable")]
480+
pub attr_span: Span,
481+
}
482+
476483
#[derive(Diagnostic)]
477484
#[diag(attr_parsing_invalid_alignment_value, code = E0589)]
478485
pub(crate) struct InvalidAlignmentValue {

compiler/rustc_builtin_macros/src/deriving/generic/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ impl<'a> TraitDef<'a> {
485485
Annotatable::Item(item) => {
486486
let is_packed = matches!(
487487
AttributeParser::parse_limited(cx.sess, &item.attrs, sym::repr, item.span, item.id),
488-
Some(Attribute::Parsed(AttributeKind::Repr(r))) if r.iter().any(|(x, _)| matches!(x, ReprPacked(..)))
488+
Some(Attribute::Parsed(AttributeKind::Repr { reprs, .. })) if reprs.iter().any(|(x, _)| matches!(x, ReprPacked(..)))
489489
);
490490

491491
let newitem = match &item.kind {

0 commit comments

Comments
 (0)