Skip to content

Commit 18840b0

Browse files
committed
Auto merge of #87296 - Aaron1011:inert-warn, r=petrochenkov
Warn on inert attributes used on bang macro invocation These attributes are currently discarded. This may change in the future (see #63221), but for now, placing inert attributes on a macro invocation does nothing, so we should warn users about it. Technically, it's possible for there to be attribute macro on the same macro invocation (or at a higher scope), which inspects the inert attribute. For example: ```rust #[look_for_inline_attr] #[inline] my_macro!() #[look_for_nested_inline] mod foo { #[inline] my_macro!() } ``` However, this would be a very strange thing to do. Anyone running into this can manually suppress the warning.
2 parents f9b95f9 + b41672e commit 18840b0

File tree

7 files changed

+115
-24
lines changed

7 files changed

+115
-24
lines changed

compiler/rustc_expand/src/expand.rs

+33-16
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_ast::ptr::P;
1212
use rustc_ast::token;
1313
use rustc_ast::tokenstream::TokenStream;
1414
use rustc_ast::visit::{self, AssocCtxt, Visitor};
15-
use rustc_ast::{AstLike, Block, Inline, ItemKind, Local, MacArgs};
15+
use rustc_ast::{AstLike, Block, Inline, ItemKind, Local, MacArgs, MacCall};
1616
use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
1717
use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
1818
use rustc_ast_pretty::pprust;
@@ -26,7 +26,7 @@ use rustc_parse::parser::{
2626
AttemptLocalParseRecovery, ForceCollect, Parser, RecoverColon, RecoverComma,
2727
};
2828
use rustc_parse::validate_attr;
29-
use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
29+
use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
3030
use rustc_session::lint::BuiltinLintDiagnostics;
3131
use rustc_session::parse::{feature_err, ParseSess};
3232
use rustc_session::Limit;
@@ -1070,7 +1070,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
10701070

10711071
// Detect use of feature-gated or invalid attributes on macro invocations
10721072
// since they will not be detected after macro expansion.
1073-
fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
1073+
fn check_attributes(&mut self, attrs: &[ast::Attribute], call: &MacCall) {
10741074
let features = self.cx.ecfg.features.unwrap();
10751075
let mut attrs = attrs.iter().peekable();
10761076
let mut span: Option<Span> = None;
@@ -1085,14 +1085,31 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
10851085
continue;
10861086
}
10871087

1088-
if attr.doc_str().is_some() {
1088+
if attr.is_doc_comment() {
10891089
self.cx.sess.parse_sess.buffer_lint_with_diagnostic(
10901090
&UNUSED_DOC_COMMENTS,
10911091
current_span,
1092-
ast::CRATE_NODE_ID,
1092+
self.cx.current_expansion.lint_node_id,
10931093
"unused doc comment",
10941094
BuiltinLintDiagnostics::UnusedDocComment(attr.span),
10951095
);
1096+
} else if rustc_attr::is_builtin_attr(attr) {
1097+
let attr_name = attr.ident().unwrap().name;
1098+
// `#[cfg]` and `#[cfg_attr]` are special - they are
1099+
// eagerly evaluated.
1100+
if attr_name != sym::cfg && attr_name != sym::cfg_attr {
1101+
self.cx.sess.parse_sess.buffer_lint_with_diagnostic(
1102+
&UNUSED_ATTRIBUTES,
1103+
attr.span,
1104+
self.cx.current_expansion.lint_node_id,
1105+
&format!("unused attribute `{}`", attr_name),
1106+
BuiltinLintDiagnostics::UnusedBuiltinAttribute {
1107+
attr_name,
1108+
macro_name: pprust::path_to_string(&call.path),
1109+
invoc_span: call.path.span,
1110+
},
1111+
);
1112+
}
10961113
}
10971114
}
10981115
}
@@ -1152,7 +1169,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11521169
}
11531170

11541171
if let ast::ExprKind::MacCall(mac) = expr.kind {
1155-
self.check_attributes(&expr.attrs);
1172+
self.check_attributes(&expr.attrs, &mac);
11561173
self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner()
11571174
} else {
11581175
assign_id!(self, &mut expr.id, || {
@@ -1253,7 +1270,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12531270
}
12541271

12551272
if let ast::ExprKind::MacCall(mac) = expr.kind {
1256-
self.check_attributes(&expr.attrs);
1273+
self.check_attributes(&expr.attrs, &mac);
12571274
self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr)
12581275
.make_opt_expr()
12591276
.map(|expr| expr.into_inner())
@@ -1296,7 +1313,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12961313

12971314
if let StmtKind::MacCall(mac) = stmt.kind {
12981315
let MacCallStmt { mac, style, attrs, tokens: _ } = mac.into_inner();
1299-
self.check_attributes(&attrs);
1316+
self.check_attributes(&attrs, &mac);
13001317
let mut placeholder =
13011318
self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts).make_stmts();
13021319

@@ -1344,9 +1361,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
13441361
let span = item.span;
13451362

13461363
match item.kind {
1347-
ast::ItemKind::MacCall(..) => {
1364+
ast::ItemKind::MacCall(ref mac) => {
1365+
self.check_attributes(&attrs, &mac);
13481366
item.attrs = attrs;
1349-
self.check_attributes(&item.attrs);
13501367
item.and_then(|item| match item.kind {
13511368
ItemKind::MacCall(mac) => {
13521369
self.collect_bang(mac, span, AstFragmentKind::Items).make_items()
@@ -1455,8 +1472,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
14551472
}
14561473

14571474
match item.kind {
1458-
ast::AssocItemKind::MacCall(..) => {
1459-
self.check_attributes(&item.attrs);
1475+
ast::AssocItemKind::MacCall(ref mac) => {
1476+
self.check_attributes(&item.attrs, &mac);
14601477
item.and_then(|item| match item.kind {
14611478
ast::AssocItemKind::MacCall(mac) => self
14621479
.collect_bang(mac, item.span, AstFragmentKind::TraitItems)
@@ -1480,8 +1497,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
14801497
}
14811498

14821499
match item.kind {
1483-
ast::AssocItemKind::MacCall(..) => {
1484-
self.check_attributes(&item.attrs);
1500+
ast::AssocItemKind::MacCall(ref mac) => {
1501+
self.check_attributes(&item.attrs, &mac);
14851502
item.and_then(|item| match item.kind {
14861503
ast::AssocItemKind::MacCall(mac) => self
14871504
.collect_bang(mac, item.span, AstFragmentKind::ImplItems)
@@ -1526,8 +1543,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
15261543
}
15271544

15281545
match foreign_item.kind {
1529-
ast::ForeignItemKind::MacCall(..) => {
1530-
self.check_attributes(&foreign_item.attrs);
1546+
ast::ForeignItemKind::MacCall(ref mac) => {
1547+
self.check_attributes(&foreign_item.attrs, &mac);
15311548
foreign_item.and_then(|item| match item.kind {
15321549
ast::ForeignItemKind::MacCall(mac) => self
15331550
.collect_bang(mac, item.span, AstFragmentKind::ForeignItems)

compiler/rustc_lint/src/context.rs

+10
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,16 @@ pub trait LintContext: Sized {
734734
Applicability::MachineApplicable,
735735
);
736736
}
737+
BuiltinLintDiagnostics::UnusedBuiltinAttribute {
738+
attr_name,
739+
macro_name,
740+
invoc_span
741+
} => {
742+
db.span_note(
743+
invoc_span,
744+
&format!("the built-in attribute `{attr_name}` will be ignored, since it's applied to the macro invocation `{macro_name}`")
745+
);
746+
}
737747
}
738748
// Rewrap `db`, and pass control to the user.
739749
decorate(LintDiagnosticBuilder::new(db));

compiler/rustc_lint/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#![feature(box_syntax)]
3333
#![feature(box_patterns)]
3434
#![feature(crate_visibility_modifier)]
35+
#![feature(format_args_capture)]
3536
#![feature(iter_order_by)]
3637
#![feature(iter_zip)]
3738
#![feature(never_type)]

compiler/rustc_lint_defs/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ pub enum BuiltinLintDiagnostics {
296296
DeprecatedMacro(Option<Symbol>, Span),
297297
MissingAbi(Span, Abi),
298298
UnusedDocComment(Span),
299+
UnusedBuiltinAttribute { attr_name: Symbol, macro_name: String, invoc_span: Span },
299300
PatternsInFnsWithoutBody(Span, Ident),
300301
LegacyDeriveHelpers(Span),
301302
ExternDepSpec(String, ExternDepSpec),

src/test/ui/lint/inert-attr-macro.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// check-pass
2+
3+
#![warn(unused)]
4+
5+
macro_rules! foo {
6+
() => {}
7+
}
8+
9+
fn main() {
10+
#[inline] foo!(); //~ WARN unused attribute `inline`
11+
12+
// This does nothing, since `#[allow(warnings)]` is itself
13+
// an inert attribute on a macro call
14+
#[allow(warnings)] #[inline] foo!(); //~ WARN unused attribute `allow`
15+
//~^ WARN unused attribute `inline`
16+
17+
// This does work, since the attribute is on a parent
18+
// of the macro invocation.
19+
#[allow(warnings)] { #[inline] foo!(); }
20+
}
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
warning: unused attribute `inline`
2+
--> $DIR/inert-attr-macro.rs:10:5
3+
|
4+
LL | #[inline] foo!();
5+
| ^^^^^^^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/inert-attr-macro.rs:3:9
9+
|
10+
LL | #![warn(unused)]
11+
| ^^^^^^
12+
= note: `#[warn(unused_attributes)]` implied by `#[warn(unused)]`
13+
note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo`
14+
--> $DIR/inert-attr-macro.rs:10:15
15+
|
16+
LL | #[inline] foo!();
17+
| ^^^
18+
19+
warning: unused attribute `allow`
20+
--> $DIR/inert-attr-macro.rs:14:5
21+
|
22+
LL | #[allow(warnings)] #[inline] foo!();
23+
| ^^^^^^^^^^^^^^^^^^
24+
|
25+
note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `foo`
26+
--> $DIR/inert-attr-macro.rs:14:34
27+
|
28+
LL | #[allow(warnings)] #[inline] foo!();
29+
| ^^^
30+
31+
warning: unused attribute `inline`
32+
--> $DIR/inert-attr-macro.rs:14:24
33+
|
34+
LL | #[allow(warnings)] #[inline] foo!();
35+
| ^^^^^^^^^
36+
|
37+
note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo`
38+
--> $DIR/inert-attr-macro.rs:14:34
39+
|
40+
LL | #[allow(warnings)] #[inline] foo!();
41+
| ^^^
42+
43+
warning: 3 warnings emitted
44+

src/test/ui/repr/repr-no-niche.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ mod enum_inline {
7373
// general; this test is relying on that.)
7474
two_fifty_six_variant_enum!(Visible2, N8);
7575

76-
#[repr(no_niche)]
77-
two_fifty_six_variant_enum!(Cloaked2, N8);
76+
two_fifty_six_variant_enum!(#[repr(no_niche)] Cloaked2, N8);
7877
}
7978

8079
mod enum_param {
@@ -96,8 +95,7 @@ mod enum_param {
9695
// here as above (assuming `T` is instantiated with `NonZeroU8`).
9796
two_fifty_six_variant_enum!(Visible2<T>);
9897

99-
#[repr(no_niche)]
100-
two_fifty_six_variant_enum!(Cloaked2<T>);
98+
two_fifty_six_variant_enum!(#[repr(no_niche)] Cloaked2<T>);
10199
}
102100

103101
fn main() {
@@ -157,8 +155,8 @@ fn main() {
157155
}
158156

159157
macro two_fifty_six_variant_enum {
160-
($name:ident<$param:ident>) => {
161-
#[derive(Debug)]
158+
($(#[$attr:meta])* $name:ident<$param:ident>) => {
159+
#[derive(Debug)] $(#[$attr])*
162160
pub enum $name<$param> {
163161
_V00($param, u16), _V01(u16, $param), _V02($param, u16), _V03(u16, $param),
164162
_V04($param, u16), _V05(u16, $param), _V06($param, u16), _V07(u16, $param),
@@ -242,8 +240,8 @@ macro two_fifty_six_variant_enum {
242240
}
243241
},
244242

245-
($name:ident, $param:ty) => {
246-
#[derive(Debug)]
243+
($(#[$attr:meta])* $name:ident, $param:ty) => {
244+
#[derive(Debug)] $(#[$attr])*
247245
pub enum $name {
248246
_V00($param, u16), _V01(u16, $param), _V02($param, u16), _V03(u16, $param),
249247
_V04($param, u16), _V05(u16, $param), _V06($param, u16), _V07(u16, $param),

0 commit comments

Comments
 (0)