Skip to content

Commit 3431f73

Browse files
committed
llint attr stuff
1 parent 9e3b844 commit 3431f73

8 files changed

Lines changed: 172 additions & 195 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/lint.rs

Lines changed: 66 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use std::marker::PhantomData;
22

3-
use rustc_ast::AttrStyle;
43
use rustc_hir::HashIgnoredAttrId;
5-
use rustc_hir::attrs::{LintAttrIdsInformation, LintAttributeKind};
4+
use rustc_hir::attrs::{LintAttrIdsInformation, LintAttrInfo, LintAttributeKind};
65
use rustc_hir::lints::{AttributeLintKind, RenamedLintSuggestion};
76
use rustc_middle::bug;
87
use rustc_session::lint::CheckLintNameResult;
@@ -54,59 +53,38 @@ const ALLOWED_TARGETS: &'static [Policy] = {
5453
Allow(Target::Delegation { mac: false }),
5554
Allow(Target::Delegation { mac: true }),
5655
Warn(Target::MacroCall),
57-
]}
58-
;
59-
56+
]
57+
};
6058

6159
pub(crate) trait Lint {
62-
fn lint_level<S: Stage>(cx: &FinalizeContext<'_, '_, S>,) -> LintAttributeKind;
60+
const KIND: LintAttributeKind;
6361
const ATTR_SYMBOL: Symbol;
6462
}
6563

6664
#[derive(Default)]
6765
pub(crate) struct LintParser<T: Lint> {
68-
lint_ids: ThinVec<LintAttrIdsInformation>,
69-
reason: Option<Symbol>,
70-
errored: bool,
71-
attr_span: Option<Span>,
72-
attr_style: Option<AttrStyle>,
66+
lint_attrs: ThinVec<LintAttrInfo>,
67+
lint_index: usize,
7368
phantom: PhantomData<T>,
7469
}
7570

76-
impl<S: Stage, T: Lint + 'static + Default> AttributeParser<S> for LintParser<T> {
71+
impl<S: Stage, T: Lint + 'static + Default> AttributeParser<S> for LintParser<T> {
7772
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
7873
&[T::ATTR_SYMBOL],
7974
template!(
8075
List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#],
8176
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
8277
),
8378
|this, cx, args| {
84-
*this = Self::default();
85-
this.attr_span = Some(cx.attr_span);
86-
this.attr_style = Some(cx.attr_style);
87-
validate_lint_attr(
88-
cx,
89-
args,
90-
&mut this.lint_ids,
91-
&mut this.errored,
92-
&mut this.reason,
93-
T::ATTR_SYMBOL,
94-
);
79+
if let Some(lint_attr) = validate_lint_attr(cx, args, T::ATTR_SYMBOL, &mut this.lint_index) {
80+
this.lint_attrs.push(lint_attr);
81+
}
9582
},
9683
)];
9784

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 {
103-
Some(AttributeKind::LintAttribute {
104-
lint_groups: self.lint_ids,
105-
reason: self.reason,
106-
kind: T::lint_level(cx),
107-
attr_span,
108-
attr_style,
109-
})
85+
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
86+
if !self.lint_attrs.is_empty() {
87+
Some(AttributeKind::LintAttribute { sub_attrs: self.lint_attrs, kind: T::KIND })
11088
} else {
11189
None
11290
}
@@ -120,105 +98,95 @@ pub(crate) struct Expect;
12098
pub(crate) type ExpectParser = LintParser<Expect>;
12199

122100
impl Lint for Expect {
123-
fn lint_level<S:Stage>(cx: &FinalizeContext<'_, '_, S>) -> LintAttributeKind {
124-
LintAttributeKind::Expect(HashIgnoredAttrId { attr_id:cx.attr_id })
125-
}
101+
const KIND: LintAttributeKind = LintAttributeKind::Expect;
126102
const ATTR_SYMBOL: Symbol = sym::expect;
127-
}
103+
}
128104

129105
#[derive(Default)]
130106
pub(crate) struct Allow;
131107
pub(crate) type AllowParser = LintParser<Allow>;
132108

133109
impl Lint for Allow {
134-
fn lint_level<S:Stage>(_cx: &FinalizeContext<'_, '_, S>) -> LintAttributeKind {
135-
LintAttributeKind::Allow
136-
}
110+
const KIND: LintAttributeKind = LintAttributeKind::Allow;
137111
const ATTR_SYMBOL: Symbol = sym::allow;
138-
}
112+
}
139113
#[derive(Default)]
140114
pub(crate) struct Warn;
141115
pub(crate) type WarnParser = LintParser<Warn>;
142116

143117
impl Lint for Warn {
144-
fn lint_level<S:Stage>(_cx: &FinalizeContext<'_, '_, S>) -> LintAttributeKind {
145-
LintAttributeKind::Warn
146-
}
118+
const KIND: LintAttributeKind = LintAttributeKind::Warn;
119+
147120
const ATTR_SYMBOL: Symbol = sym::warn;
148-
}
121+
}
149122

150123
#[derive(Default)]
151124
pub(crate) struct Deny;
152125
pub(crate) type DenyParser = LintParser<Deny>;
153126

154127
impl Lint for Deny {
155-
fn lint_level<S:Stage>(_cx: &FinalizeContext<'_, '_, S>) -> LintAttributeKind {
156-
LintAttributeKind::Deny
157-
}
128+
const KIND: LintAttributeKind = LintAttributeKind::Deny;
129+
158130
const ATTR_SYMBOL: Symbol = sym::deny;
159-
}
131+
}
160132

161133
#[derive(Default)]
162134
pub(crate) struct Forbid;
163135
pub(crate) type ForbidParser = LintParser<Forbid>;
164136

165137
impl Lint for Forbid {
166-
fn lint_level<S:Stage>(_cx: &FinalizeContext<'_, '_, S>) -> LintAttributeKind {
167-
LintAttributeKind::Forbid
168-
}
169-
const ATTR_SYMBOL: Symbol = sym::forbid;
170-
}
171-
172-
138+
const KIND: LintAttributeKind = LintAttributeKind::Forbid;
173139

140+
const ATTR_SYMBOL: Symbol = sym::forbid;
141+
}
174142

175143
#[inline(always)]
176144
fn validate_lint_attr<S: Stage>(
177145
cx: &mut AcceptContext<'_, '_, S>,
178146
args: &ArgParser,
179-
lint_ids: &mut ThinVec<LintAttrIdsInformation>,
180-
errored: &mut bool,
181-
reason: &mut Option<Symbol>,
182147
attr_name: Symbol,
183-
) {
184-
148+
lint_index: &mut usize
149+
) -> Option<LintAttrInfo> {
185150
let Some(list) = args.list() else {
186151
cx.expected_list(cx.inner_span, args);
187-
return;
152+
return None;
188153
};
189154
let mut list = list.mixed().peekable();
190155

191-
let mut lint_index = 0;
192156
let mut skip_reason_check = false;
157+
let mut errored = false;
158+
let mut reason = None;
159+
let mut lint_ids = ThinVec::new();
160+
193161
while let Some(item) = list.next() {
194162
let Some(meta_item) = item.meta_item() else {
195163
cx.expected_identifier(item.span());
196-
*errored = true;
164+
errored = true;
197165
continue;
198166
};
199167

200168
if let Some(args) = meta_item.word_is(sym::reason) {
201169
if reason.is_some() {
202170
// TODO check if this check is already present
203171
cx.duplicate_key(meta_item.span(), sym::reason);
204-
*errored = true;
172+
errored = true;
205173
}
206174
let ArgParser::NameValue(nv) = args else {
207175
cx.expected_name_value(meta_item.span(), Some(sym::reason));
208-
*errored = true;
176+
errored = true;
209177
continue;
210178
};
211179
if list.peek().is_some() {
212180
cx.expected_nv_as_last_argument(nv.args_span(), attr_name, sym::reason);
213-
*errored = true;
181+
errored = true;
214182
continue;
215183
}
216184
let Some(s) = nv.value_as_str() else {
217185
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
218-
*errored = true;
186+
errored = true;
219187
continue;
220188
};
221-
*reason = Some(s);
189+
reason = Some(s);
222190
} else {
223191
let mut segments = meta_item.path().segments();
224192

@@ -241,19 +209,33 @@ fn validate_lint_attr<S: Stage>(
241209
&tool_name.map(|tool| format!("{tool}::{}", &name)).unwrap_or(name.clone()),
242210
);
243211

244-
if let Some(ids) =
245-
check_lint(cx, original_name, &name, tool_name, tool_span, meta_item.span(),lint_index )
246-
{
212+
if let Some(ids) = check_lint(
213+
cx,
214+
original_name,
215+
&name,
216+
tool_name,
217+
tool_span,
218+
meta_item.span(),
219+
*lint_index,
220+
) {
247221
lint_ids.extend(ids);
248222
} else {
249223
skip_reason_check = true
250224
}
251-
lint_index += 1;
225+
*lint_index += 1;
252226
}
253227
}
254228
if !skip_reason_check && lint_ids.is_empty() {
255229
cx.warn_empty_attribute(cx.attr_span);
256230
}
231+
232+
(!errored).then_some(LintAttrInfo {
233+
reason,
234+
lint_groups: lint_ids,
235+
attr_span: cx.attr_span,
236+
attr_style: cx.attr_style,
237+
attr_id: HashIgnoredAttrId { attr_id: cx.attr_id },
238+
})
257239
}
258240

259241
fn check_lint<S: Stage>(
@@ -263,7 +245,7 @@ fn check_lint<S: Stage>(
263245
tool_name: Option<Symbol>,
264246
tool_span: Option<Span>,
265247
span: Span,
266-
lint_index: usize
248+
lint_index: usize,
267249
) -> Option<Vec<LintAttrIdsInformation>> {
268250
let Some(lint_store) = &cx.sess.lint_store else {
269251
bug!("lint_store required while parsing attributes");
@@ -304,7 +286,7 @@ fn check_lint<S: Stage>(
304286
original_name,
305287
span,
306288
tool_name,
307-
lint_index
289+
lint_index,
308290
});
309291
}
310292
}
@@ -351,7 +333,13 @@ fn check_lint<S: Stage>(
351333

352334
for id in ids {
353335
let name = Symbol::intern(&id.to_string());
354-
lint_ids.push(LintAttrIdsInformation { name, original_name, span, tool_name, lint_index});
336+
lint_ids.push(LintAttrIdsInformation {
337+
name,
338+
original_name,
339+
span,
340+
tool_name,
341+
lint_index,
342+
});
355343
}
356344
}
357345

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,8 @@ pub struct AcceptContext<'f, 'sess, S: Stage> {
422422

423423
/// The name of the attribute we're currently accepting.
424424
pub(crate) attr_path: AttrPath,
425+
426+
pub(crate) attr_id: AttrId,
425427
}
426428

427429
impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
@@ -738,8 +740,6 @@ pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
738740
/// Usually, you should use normal attribute parsing logic instead,
739741
/// especially when making a *denylist* of other attributes.
740742
pub(crate) all_attrs: &'p [RefPathParser<'p>],
741-
742-
pub(crate) attr_id: AttrId,
743743
}
744744

745745
impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> {

compiler/rustc_attr_parsing/src/interface.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ impl<'sess> AttributeParser<'sess, Early> {
216216
if let Some(safety) = attr_safety {
217217
parser.check_attribute_safety(&attr_path, inner_span, safety, &mut emit_lint)
218218
}
219+
let attr_id = sess.psess.attr_id_generator.mk_attr_id();
219220
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
220221
shared: SharedContext {
221222
cx: &mut parser,
@@ -229,6 +230,7 @@ impl<'sess> AttributeParser<'sess, Early> {
229230
parsed_description,
230231
template,
231232
attr_path,
233+
attr_id,
232234
};
233235
parse_fn(&mut cx, args)
234236
}
@@ -388,9 +390,9 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
388390
parsed_description: ParsedDescription::Attribute,
389391
template: &accept.template,
390392
attr_path: attr_path.clone(),
393+
attr_id: attr.id,
391394
};
392395

393-
394396
(accept.accept_fn)(&mut cx, &args);
395397
finalizers.push(&accept.finalizer);
396398

@@ -428,11 +430,9 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
428430

429431
early_parsed_state.finalize_early_parsed_attributes(&mut attributes);
430432
for f in &finalizers {
431-
let attr_id = self.sess.psess.attr_id_generator.mk_attr_id();
432433
if let Some(attr) = f(&mut FinalizeContext {
433434
shared: SharedContext { cx: self, target_span, target, emit_lint: &mut emit_lint },
434435
all_attrs: &attr_paths,
435-
attr_id,
436436
}) {
437437
attributes.push(Attribute::Parsed(attr));
438438
}

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -794,13 +794,22 @@ pub struct RustcCleanQueries {
794794
pub span: Span,
795795
}
796796

797+
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
798+
pub struct LintAttrInfo {
799+
pub lint_groups: ThinVec<LintAttrIdsInformation>,
800+
pub attr_span: Span,
801+
pub reason: Option<Symbol>,
802+
pub attr_style: AttrStyle,
803+
pub attr_id: HashIgnoredAttrId,
804+
}
805+
797806
#[derive(Debug, Clone, PrintAttribute, Encodable, Decodable, HashStable_Generic)]
798807
pub struct LintAttrIdsInformation {
799808
pub name: Symbol,
800809
pub span: Span,
801810
pub original_name: Symbol,
802811
pub tool_name: Option<Symbol>,
803-
pub lint_index: usize
812+
pub lint_index: usize,
804813
}
805814

806815
#[derive(Clone, Copy, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
@@ -809,7 +818,7 @@ pub enum LintAttributeKind {
809818
Warn,
810819
Deny,
811820
Forbid,
812-
Expect(HashIgnoredAttrId),
821+
Expect,
813822
}
814823

815824
/// Represents parsed *built-in* inert attributes.
@@ -989,13 +998,7 @@ pub enum AttributeKind {
989998
Linkage(Linkage, Span),
990999

9911000
/// Represents `#[allow]`, `#[expect]`, `#[warn]`, `#[deny]`, `#[forbid]`
992-
LintAttribute {
993-
reason: Option<Symbol>,
994-
kind: LintAttributeKind,
995-
lint_groups: ThinVec<LintAttrIdsInformation>,
996-
attr_span: Span,
997-
attr_style: AttrStyle
998-
},
1001+
LintAttribute { kind: LintAttributeKind, sub_attrs: ThinVec<LintAttrInfo> },
9991002
/// Represents `#[loop_match]`.
10001003
LoopMatch(Span),
10011004

0 commit comments

Comments
 (0)