Skip to content

Commit 9e3b844

Browse files
committed
make one single lint parser
1 parent 650c481 commit 9e3b844

25 files changed

Lines changed: 291 additions & 340 deletions

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,10 @@ impl<S: Stage> AttributeParser<S> for NakedParser {
269269
sym::should_panic,
270270
sym::bench,
271271
// diagnostics
272+
sym::allow,
273+
sym::warn,
274+
sym::deny,
275+
sym::forbid,
272276
sym::deprecated,
273277
sym::must_use,
274278
// abi, linking and FFI

compiler/rustc_attr_parsing/src/attributes/lint.rs

Lines changed: 77 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
use std::marker::PhantomData;
2+
3+
use rustc_ast::AttrStyle;
14
use rustc_hir::HashIgnoredAttrId;
25
use rustc_hir::attrs::{LintAttrIdsInformation, LintAttributeKind};
36
use rustc_hir::lints::{AttributeLintKind, RenamedLintSuggestion};
@@ -9,7 +12,9 @@ use super::prelude::*;
912
use crate::session_diagnostics::UnknownToolInScopedLint;
1013
use crate::target_checking::Policy;
1114

12-
const ALLOWED_TARGETS: &'static [Policy] = &[
15+
const ALLOWED_TARGETS: &'static [Policy] = {
16+
use super::prelude::{Allow, Warn};
17+
&[
1318
Allow(Target::ExternCrate),
1419
Allow(Target::Use),
1520
Allow(Target::Static),
@@ -45,49 +50,62 @@ const ALLOWED_TARGETS: &'static [Policy] = &[
4550
Allow(Target::Param),
4651
Allow(Target::PatField),
4752
Allow(Target::ExprField),
48-
Allow(Target::MacroCall),
4953
Allow(Target::Crate),
5054
Allow(Target::Delegation { mac: false }),
5155
Allow(Target::Delegation { mac: true }),
52-
]
56+
Warn(Target::MacroCall),
57+
]}
5358
;
5459

60+
61+
pub(crate) trait Lint {
62+
fn lint_level<S: Stage>(cx: &FinalizeContext<'_, '_, S>,) -> LintAttributeKind;
63+
const ATTR_SYMBOL: Symbol;
64+
}
65+
5566
#[derive(Default)]
56-
pub(crate) struct AllowParser {
67+
pub(crate) struct LintParser<T: Lint> {
5768
lint_ids: ThinVec<LintAttrIdsInformation>,
5869
reason: Option<Symbol>,
5970
errored: bool,
6071
attr_span: Option<Span>,
72+
attr_style: Option<AttrStyle>,
73+
phantom: PhantomData<T>,
6174
}
6275

63-
// Needs to be manually impl:ed as `AttributeParser`, because otherwise deduplication occurs
64-
impl<S: Stage> AttributeParser<S> for AllowParser {
76+
impl<S: Stage, T: Lint + 'static + Default> AttributeParser<S> for LintParser<T> {
6577
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
66-
&[sym::allow],
78+
&[T::ATTR_SYMBOL],
6779
template!(
6880
List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#],
6981
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
7082
),
7183
|this, cx, args| {
84+
*this = Self::default();
7285
this.attr_span = Some(cx.attr_span);
86+
this.attr_style = Some(cx.attr_style);
7387
validate_lint_attr(
7488
cx,
7589
args,
7690
&mut this.lint_ids,
7791
&mut this.errored,
7892
&mut this.reason,
79-
sym::allow,
93+
T::ATTR_SYMBOL,
8094
);
8195
},
8296
)];
8397

84-
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
85-
if !self.errored && !self.attr_span.is_none() {
98+
fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
99+
let (Some(attr_span), Some(attr_style)) = (self.attr_span, self.attr_style) else {
100+
return None;
101+
};
102+
if !self.errored {
86103
Some(AttributeKind::LintAttribute {
87104
lint_groups: self.lint_ids,
88105
reason: self.reason,
89-
kind: LintAttributeKind::Allow,
90-
attr_span: self.attr_span.unwrap(),
106+
kind: T::lint_level(cx),
107+
attr_span,
108+
attr_style,
91109
})
92110
} else {
93111
None
@@ -96,178 +114,63 @@ impl<S: Stage> AttributeParser<S> for AllowParser {
96114

97115
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALLOWED_TARGETS);
98116
}
99-
#[derive(Default)]
100-
pub(crate) struct DenyParser {
101-
lint_ids: ThinVec<LintAttrIdsInformation>,
102-
reason: Option<Symbol>,
103-
errored: bool,
104-
attr_span: Option<Span>,
105117

106-
}
107-
impl<S: Stage> AttributeParser<S> for DenyParser {
108-
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
109-
&[sym::deny],
110-
template!(
111-
List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#],
112-
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
113-
),
114-
|this, cx, args| {
115-
this.attr_span = Some(cx.attr_span);
116-
validate_lint_attr(
117-
cx,
118-
args,
119-
&mut this.lint_ids,
120-
&mut this.errored,
121-
&mut this.reason,
122-
sym::deny,
123-
);
124-
},
125-
)];
118+
#[derive(Default)]
119+
pub(crate) struct Expect;
120+
pub(crate) type ExpectParser = LintParser<Expect>;
126121

127-
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
128-
if !self.errored && !self.attr_span.is_none() {
129-
Some(AttributeKind::LintAttribute {
130-
lint_groups: self.lint_ids,
131-
reason: self.reason,
132-
kind: LintAttributeKind::Deny,attr_span: self.attr_span.unwrap(),
133-
})
134-
} else {
135-
None
136-
}
122+
impl Lint for Expect {
123+
fn lint_level<S:Stage>(cx: &FinalizeContext<'_, '_, S>) -> LintAttributeKind {
124+
LintAttributeKind::Expect(HashIgnoredAttrId { attr_id:cx.attr_id })
137125
}
138-
139-
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALLOWED_TARGETS);
140-
}
126+
const ATTR_SYMBOL: Symbol = sym::expect;
127+
}
141128

142129
#[derive(Default)]
143-
pub(crate) struct ForbidParser {
144-
lint_ids: ThinVec<LintAttrIdsInformation>,
145-
reason: Option<Symbol>,
146-
errored: bool,
147-
attr_span: Option<Span>,
130+
pub(crate) struct Allow;
131+
pub(crate) type AllowParser = LintParser<Allow>;
148132

149-
}
150-
impl<S: Stage> AttributeParser<S> for ForbidParser {
151-
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
152-
&[sym::forbid],
153-
template!(
154-
List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#],
155-
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
156-
),
157-
|this, cx, args| {
158-
this.attr_span = Some(cx.attr_span);
159-
validate_lint_attr(
160-
cx,
161-
args,
162-
&mut this.lint_ids,
163-
&mut this.errored,
164-
&mut this.reason,
165-
sym::forbid,
166-
);
167-
},
168-
)];
169-
170-
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
171-
if !self.errored {
172-
Some(AttributeKind::LintAttribute {
173-
lint_groups: self.lint_ids,
174-
reason: self.reason,
175-
kind: LintAttributeKind::Forbid,attr_span: self.attr_span.unwrap(),
176-
})
177-
} else {
178-
None
179-
}
133+
impl Lint for Allow {
134+
fn lint_level<S:Stage>(_cx: &FinalizeContext<'_, '_, S>) -> LintAttributeKind {
135+
LintAttributeKind::Allow
180136
}
137+
const ATTR_SYMBOL: Symbol = sym::allow;
138+
}
139+
#[derive(Default)]
140+
pub(crate) struct Warn;
141+
pub(crate) type WarnParser = LintParser<Warn>;
181142

182-
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALLOWED_TARGETS);
183-
}
143+
impl Lint for Warn {
144+
fn lint_level<S:Stage>(_cx: &FinalizeContext<'_, '_, S>) -> LintAttributeKind {
145+
LintAttributeKind::Warn
146+
}
147+
const ATTR_SYMBOL: Symbol = sym::warn;
148+
}
184149

185150
#[derive(Default)]
186-
pub(crate) struct WarnParser {
187-
lint_ids: ThinVec<LintAttrIdsInformation>,
188-
reason: Option<Symbol>,
189-
errored: bool,
190-
attr_span: Option<Span>,
191-
192-
}
193-
impl<S: Stage> AttributeParser<S> for WarnParser {
194-
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
195-
&[sym::warn],
196-
template!(
197-
List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#],
198-
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
199-
),
200-
|this, cx, args| {
201-
this.attr_span = Some(cx.attr_span);
202-
validate_lint_attr(
203-
cx,
204-
args,
205-
&mut this.lint_ids,
206-
&mut this.errored,
207-
&mut this.reason,
208-
sym::warn,
209-
);
210-
},
211-
)];
151+
pub(crate) struct Deny;
152+
pub(crate) type DenyParser = LintParser<Deny>;
212153

213-
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
214-
if !self.errored && !self.attr_span.is_none() {
215-
Some(AttributeKind::LintAttribute {
216-
lint_groups: self.lint_ids,
217-
reason: self.reason,
218-
kind: LintAttributeKind::Warn,attr_span: self.attr_span.unwrap(),
219-
})
220-
} else {
221-
None
222-
}
154+
impl Lint for Deny {
155+
fn lint_level<S:Stage>(_cx: &FinalizeContext<'_, '_, S>) -> LintAttributeKind {
156+
LintAttributeKind::Deny
223157
}
224-
225-
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALLOWED_TARGETS);
226-
}
158+
const ATTR_SYMBOL: Symbol = sym::deny;
159+
}
227160

228161
#[derive(Default)]
229-
pub(crate) struct ExpectParser {
230-
lint_ids: ThinVec<LintAttrIdsInformation>,
231-
reason: Option<Symbol>,
232-
errored: bool,
233-
attr_span: Option<Span>,
162+
pub(crate) struct Forbid;
163+
pub(crate) type ForbidParser = LintParser<Forbid>;
234164

235-
}
236-
impl<S: Stage> AttributeParser<S> for ExpectParser {
237-
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
238-
&[sym::expect],
239-
template!(
240-
List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#],
241-
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
242-
),
243-
|this, cx, args| {
244-
this.attr_span = Some(cx.attr_span);
245-
validate_lint_attr(
246-
cx,
247-
args,
248-
&mut this.lint_ids,
249-
&mut this.errored,
250-
&mut this.reason,
251-
sym::expect,
252-
);
253-
},
254-
)];
255-
256-
fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
257-
if !self.errored && !self.attr_span.is_none() {
258-
Some(AttributeKind::LintAttribute {
259-
lint_groups: self.lint_ids,
260-
reason: self.reason,
261-
kind: LintAttributeKind::Expect(HashIgnoredAttrId { attr_id:cx.attr_id}),
262-
attr_span: self.attr_span.unwrap(),
263-
})
264-
} else {
265-
None
266-
}
165+
impl Lint for Forbid {
166+
fn lint_level<S:Stage>(_cx: &FinalizeContext<'_, '_, S>) -> LintAttributeKind {
167+
LintAttributeKind::Forbid
267168
}
169+
const ATTR_SYMBOL: Symbol = sym::forbid;
170+
}
171+
172+
268173

269-
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALLOWED_TARGETS);
270-
}
271174

272175
#[inline(always)]
273176
fn validate_lint_attr<S: Stage>(
@@ -278,18 +181,18 @@ fn validate_lint_attr<S: Stage>(
278181
reason: &mut Option<Symbol>,
279182
attr_name: Symbol,
280183
) {
281-
let Some(list) = args.list().map(MetaItemListParser::mixed) else {
184+
185+
let Some(list) = args.list() else {
282186
cx.expected_list(cx.inner_span, args);
283187
return;
284188
};
285-
let mut list = list.peekable();
189+
let mut list = list.mixed().peekable();
286190

287-
let mut skip_empty_check = false;
288191
let mut lint_index = 0;
289-
192+
let mut skip_reason_check = false;
290193
while let Some(item) = list.next() {
291194
let Some(meta_item) = item.meta_item() else {
292-
cx.expected_string_literal(item.span(), item.lit());
195+
cx.expected_identifier(item.span());
293196
*errored = true;
294197
continue;
295198
};
@@ -343,14 +246,12 @@ fn validate_lint_attr<S: Stage>(
343246
{
344247
lint_ids.extend(ids);
345248
} else {
346-
// Since external tool lints aren't directly checked by rustc, we don't store these ids
347-
// inside the parsed attr, but this still means that something *does* exist in it, so we shouldn't warn
348-
skip_empty_check = true;
249+
skip_reason_check = true
349250
}
350251
lint_index += 1;
351252
}
352253
}
353-
if !skip_empty_check && !*errored && lint_ids.is_empty() {
254+
if !skip_reason_check && lint_ids.is_empty() {
354255
cx.warn_empty_attribute(cx.attr_span);
355256
}
356257
}

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,7 @@ pub enum AttributeKind {
994994
kind: LintAttributeKind,
995995
lint_groups: ThinVec<LintAttrIdsInformation>,
996996
attr_span: Span,
997+
attr_style: AttrStyle
997998
},
998999
/// Represents `#[loop_match]`.
9991000
LoopMatch(Span),

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl AttributeKind {
5555
LinkOrdinal { .. } => No,
5656
LinkSection { .. } => Yes, // Needed for rustdoc
5757
Linkage(..) => No,
58-
LintAttribute { .. } => Yes,
58+
LintAttribute { .. } => No,
5959
LoopMatch(..) => No,
6060
MacroEscape(..) => No,
6161
MacroExport { .. } => Yes,

0 commit comments

Comments
 (0)