Skip to content

Commit 650c481

Browse files
committed
almost all tests pass
1 parent bde5d6a commit 650c481

16 files changed

Lines changed: 353 additions & 381 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/lint.rs

Lines changed: 129 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,63 @@
1-
use rustc_hir::attrs::LintAttrIdsInformation;
1+
use rustc_hir::HashIgnoredAttrId;
2+
use rustc_hir::attrs::{LintAttrIdsInformation, LintAttributeKind};
23
use rustc_hir::lints::{AttributeLintKind, RenamedLintSuggestion};
34
use rustc_middle::bug;
45
use rustc_session::lint::CheckLintNameResult;
56
use rustc_session::lint::builtin::{RENAMED_AND_REMOVED_LINTS, UNKNOWN_LINTS};
7+
68
use super::prelude::*;
79
use crate::session_diagnostics::UnknownToolInScopedLint;
10+
use crate::target_checking::Policy;
11+
12+
const ALLOWED_TARGETS: &'static [Policy] = &[
13+
Allow(Target::ExternCrate),
14+
Allow(Target::Use),
15+
Allow(Target::Static),
16+
Allow(Target::Const),
17+
Allow(Target::Fn),
18+
Allow(Target::Closure),
19+
Allow(Target::Mod),
20+
Allow(Target::ForeignMod),
21+
Allow(Target::GlobalAsm),
22+
Allow(Target::TyAlias),
23+
Allow(Target::Enum),
24+
Allow(Target::Variant),
25+
Allow(Target::Struct),
26+
Allow(Target::Field),
27+
Allow(Target::Union),
28+
Allow(Target::Trait),
29+
Allow(Target::TraitAlias),
30+
Allow(Target::Impl { of_trait: false }),
31+
Allow(Target::Impl { of_trait: true }),
32+
Allow(Target::Expression),
33+
Allow(Target::Statement),
34+
Allow(Target::Arm),
35+
Allow(Target::AssocConst),
36+
Allow(Target::Method(MethodKind::Inherent)),
37+
Allow(Target::Method(MethodKind::Trait { body: false })),
38+
Allow(Target::Method(MethodKind::Trait { body: true })),
39+
Allow(Target::Method(MethodKind::TraitImpl)),
40+
Allow(Target::AssocTy),
41+
Allow(Target::ForeignFn),
42+
Allow(Target::ForeignStatic),
43+
Allow(Target::ForeignTy),
44+
Allow(Target::MacroDef),
45+
Allow(Target::Param),
46+
Allow(Target::PatField),
47+
Allow(Target::ExprField),
48+
Allow(Target::MacroCall),
49+
Allow(Target::Crate),
50+
Allow(Target::Delegation { mac: false }),
51+
Allow(Target::Delegation { mac: true }),
52+
]
53+
;
854

955
#[derive(Default)]
1056
pub(crate) struct AllowParser {
1157
lint_ids: ThinVec<LintAttrIdsInformation>,
1258
reason: Option<Symbol>,
1359
errored: bool,
60+
attr_span: Option<Span>,
1461
}
1562

1663
// Needs to be manually impl:ed as `AttributeParser`, because otherwise deduplication occurs
@@ -22,6 +69,7 @@ impl<S: Stage> AttributeParser<S> for AllowParser {
2269
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
2370
),
2471
|this, cx, args| {
72+
this.attr_span = Some(cx.attr_span);
2573
validate_lint_attr(
2674
cx,
2775
args,
@@ -34,20 +82,27 @@ impl<S: Stage> AttributeParser<S> for AllowParser {
3482
)];
3583

3684
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
37-
if !self.errored {
38-
Some(AttributeKind::Allow { lint_ids: self.lint_ids, reason: self.reason })
85+
if !self.errored && !self.attr_span.is_none() {
86+
Some(AttributeKind::LintAttribute {
87+
lint_groups: self.lint_ids,
88+
reason: self.reason,
89+
kind: LintAttributeKind::Allow,
90+
attr_span: self.attr_span.unwrap(),
91+
})
3992
} else {
4093
None
4194
}
4295
}
4396

44-
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
97+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALLOWED_TARGETS);
4598
}
4699
#[derive(Default)]
47100
pub(crate) struct DenyParser {
48101
lint_ids: ThinVec<LintAttrIdsInformation>,
49102
reason: Option<Symbol>,
50103
errored: bool,
104+
attr_span: Option<Span>,
105+
51106
}
52107
impl<S: Stage> AttributeParser<S> for DenyParser {
53108
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
@@ -57,6 +112,7 @@ impl<S: Stage> AttributeParser<S> for DenyParser {
57112
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
58113
),
59114
|this, cx, args| {
115+
this.attr_span = Some(cx.attr_span);
60116
validate_lint_attr(
61117
cx,
62118
args,
@@ -69,21 +125,27 @@ impl<S: Stage> AttributeParser<S> for DenyParser {
69125
)];
70126

71127
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
72-
if !self.errored {
73-
Some(AttributeKind::Deny { lint_ids: self.lint_ids, reason: self.reason })
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+
})
74134
} else {
75135
None
76136
}
77137
}
78138

79-
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
139+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALLOWED_TARGETS);
80140
}
81141

82142
#[derive(Default)]
83143
pub(crate) struct ForbidParser {
84144
lint_ids: ThinVec<LintAttrIdsInformation>,
85145
reason: Option<Symbol>,
86146
errored: bool,
147+
attr_span: Option<Span>,
148+
87149
}
88150
impl<S: Stage> AttributeParser<S> for ForbidParser {
89151
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
@@ -93,6 +155,7 @@ impl<S: Stage> AttributeParser<S> for ForbidParser {
93155
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
94156
),
95157
|this, cx, args| {
158+
this.attr_span = Some(cx.attr_span);
96159
validate_lint_attr(
97160
cx,
98161
args,
@@ -106,21 +169,26 @@ impl<S: Stage> AttributeParser<S> for ForbidParser {
106169

107170
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
108171
if !self.errored {
109-
Some(AttributeKind::Forbid { lint_ids: self.lint_ids, reason: self.reason })
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+
})
110177
} else {
111178
None
112179
}
113180
}
114181

115-
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
182+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALLOWED_TARGETS);
116183
}
117184

118-
119185
#[derive(Default)]
120186
pub(crate) struct WarnParser {
121187
lint_ids: ThinVec<LintAttrIdsInformation>,
122188
reason: Option<Symbol>,
123189
errored: bool,
190+
attr_span: Option<Span>,
191+
124192
}
125193
impl<S: Stage> AttributeParser<S> for WarnParser {
126194
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
@@ -130,6 +198,7 @@ impl<S: Stage> AttributeParser<S> for WarnParser {
130198
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
131199
),
132200
|this, cx, args| {
201+
this.attr_span = Some(cx.attr_span);
133202
validate_lint_attr(
134203
cx,
135204
args,
@@ -142,21 +211,27 @@ impl<S: Stage> AttributeParser<S> for WarnParser {
142211
)];
143212

144213
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
145-
if !self.errored {
146-
Some(AttributeKind::Warn { lint_ids: self.lint_ids, reason: self.reason })
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+
})
147220
} else {
148221
None
149222
}
150223
}
151224

152-
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
225+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALLOWED_TARGETS);
153226
}
154227

155228
#[derive(Default)]
156229
pub(crate) struct ExpectParser {
157230
lint_ids: ThinVec<LintAttrIdsInformation>,
158231
reason: Option<Symbol>,
159232
errored: bool,
233+
attr_span: Option<Span>,
234+
160235
}
161236
impl<S: Stage> AttributeParser<S> for ExpectParser {
162237
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
@@ -166,6 +241,7 @@ impl<S: Stage> AttributeParser<S> for ExpectParser {
166241
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
167242
),
168243
|this, cx, args| {
244+
this.attr_span = Some(cx.attr_span);
169245
validate_lint_attr(
170246
cx,
171247
args,
@@ -177,17 +253,23 @@ impl<S: Stage> AttributeParser<S> for ExpectParser {
177253
},
178254
)];
179255

180-
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
181-
if !self.errored {
182-
Some(AttributeKind::Expect { lint_ids: self.lint_ids, reason: self.reason, })
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+
})
183264
} else {
184265
None
185266
}
186267
}
187268

188-
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
269+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALLOWED_TARGETS);
189270
}
190271

272+
#[inline(always)]
191273
fn validate_lint_attr<S: Stage>(
192274
cx: &mut AcceptContext<'_, '_, S>,
193275
args: &ArgParser,
@@ -196,23 +278,25 @@ fn validate_lint_attr<S: Stage>(
196278
reason: &mut Option<Symbol>,
197279
attr_name: Symbol,
198280
) {
199-
200281
let Some(list) = args.list().map(MetaItemListParser::mixed) else {
201282
cx.expected_list(cx.inner_span, args);
202283
return;
203284
};
204285
let mut list = list.peekable();
205286

206287
let mut skip_empty_check = false;
288+
let mut lint_index = 0;
289+
207290
while let Some(item) = list.next() {
208291
let Some(meta_item) = item.meta_item() else {
209292
cx.expected_string_literal(item.span(), item.lit());
210293
*errored = true;
211294
continue;
212295
};
296+
213297
if let Some(args) = meta_item.word_is(sym::reason) {
214298
if reason.is_some() {
215-
// TODO check if this check is already present
299+
// TODO check if this check is already present
216300
cx.duplicate_key(meta_item.span(), sym::reason);
217301
*errored = true;
218302
}
@@ -250,18 +334,23 @@ fn validate_lint_attr<S: Stage>(
250334
rest.into_iter().map(|ident| ident.to_string()).collect::<Vec<_>>().join("::");
251335
(Some(tool.name), Some(tool.span), name)
252336
};
253-
let original_name = Symbol::intern(&tool_name.map(|tool|format!("{tool}::{}", &name)).unwrap_or(name.clone()));
254-
255-
if let Some(ids) = check_lint(cx, original_name, &name, tool_name, tool_span, meta_item.span()) {
337+
let original_name = Symbol::intern(
338+
&tool_name.map(|tool| format!("{tool}::{}", &name)).unwrap_or(name.clone()),
339+
);
340+
341+
if let Some(ids) =
342+
check_lint(cx, original_name, &name, tool_name, tool_span, meta_item.span(),lint_index )
343+
{
256344
lint_ids.extend(ids);
257345
} else {
258346
// Since external tool lints aren't directly checked by rustc, we don't store these ids
259347
// inside the parsed attr, but this still means that something *does* exist in it, so we shouldn't warn
260348
skip_empty_check = true;
261349
}
350+
lint_index += 1;
262351
}
263352
}
264-
if !skip_empty_check && lint_ids.is_empty() {
353+
if !skip_empty_check && !*errored && lint_ids.is_empty() {
265354
cx.warn_empty_attribute(cx.attr_span);
266355
}
267356
}
@@ -273,6 +362,7 @@ fn check_lint<S: Stage>(
273362
tool_name: Option<Symbol>,
274363
tool_span: Option<Span>,
275364
span: Span,
365+
lint_index: usize
276366
) -> Option<Vec<LintAttrIdsInformation>> {
277367
let Some(lint_store) = &cx.sess.lint_store else {
278368
bug!("lint_store required while parsing attributes");
@@ -281,14 +371,18 @@ fn check_lint<S: Stage>(
281371
match lint_store.check_lint_name(lint_name, tool_name, &cx.tools) {
282372
CheckLintNameResult::Ok(ids) => {
283373
for id in ids {
284-
lint_ids.push(LintAttrIdsInformation {name: Symbol::intern(&id.to_string()), original_name, span, tool_name});
374+
lint_ids.push(LintAttrIdsInformation {
375+
name: Symbol::intern(&id.to_string()),
376+
original_name,
377+
span,
378+
tool_name,
379+
lint_index,
380+
});
285381
}
286382
}
287383
CheckLintNameResult::Tool(ids, new_lint_name) => {
288384
let _name = match new_lint_name {
289-
None => {
290-
original_name
291-
}
385+
None => original_name,
292386
Some(new_lint_name) => {
293387
let new_lint_name = Symbol::intern(&new_lint_name);
294388
cx.emit_lint(
@@ -304,7 +398,13 @@ fn check_lint<S: Stage>(
304398
}
305399
};
306400
for id in ids {
307-
lint_ids.push(LintAttrIdsInformation {name: Symbol::intern(&id.to_string()), original_name, span, tool_name});
401+
lint_ids.push(LintAttrIdsInformation {
402+
name: Symbol::intern(&id.to_string()),
403+
original_name,
404+
span,
405+
tool_name,
406+
lint_index
407+
});
308408
}
309409
}
310410

@@ -317,7 +417,6 @@ fn check_lint<S: Stage>(
317417
}
318418

319419
CheckLintNameResult::NoTool => {
320-
dbg!(&cx.tools);
321420
cx.emit_err(UnknownToolInScopedLint {
322421
span: tool_span,
323422
tool_name: tool_name.unwrap(),
@@ -351,7 +450,7 @@ fn check_lint<S: Stage>(
351450

352451
for id in ids {
353452
let name = Symbol::intern(&id.to_string());
354-
lint_ids.push(LintAttrIdsInformation {name, original_name, span, tool_name});
453+
lint_ids.push(LintAttrIdsInformation { name, original_name, span, tool_name, lint_index});
355454
}
356455
}
357456

0 commit comments

Comments
 (0)