Skip to content

Commit b6c01a0

Browse files
committed
Rework klint attribute parsing
1 parent fb020a9 commit b6c01a0

4 files changed

Lines changed: 94 additions & 94 deletions

File tree

flake.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/attribute.rs

Lines changed: 88 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::sync::Arc;
66

77
use rustc_ast::tokenstream::{self, TokenTree};
88
use rustc_ast::{DelimArgs, LitKind, MetaItemLit, token};
9-
use rustc_errors::{Diag, ErrorGuaranteed};
9+
use rustc_errors::ErrorGuaranteed;
1010
use rustc_hir::{AttrArgs, AttrItem, Attribute, HirId};
1111
use rustc_middle::ty::TyCtxt;
1212
use rustc_span::symbol::Ident;
@@ -43,6 +43,37 @@ pub enum KlintAttribute {
4343
DiagnosticItem(Symbol),
4444
}
4545

46+
#[derive(Diagnostic)]
47+
#[diag("incorrect usage of `#[kint::preempt_count]`")]
48+
#[help("{$help}")]
49+
struct InvalidPreemptCountAttribute {
50+
#[primary_span]
51+
pub span: Span,
52+
pub help: &'static str,
53+
}
54+
55+
#[derive(Diagnostic)]
56+
#[diag("unrecognized klint attribute")]
57+
struct UnknownAttribute {
58+
#[primary_span]
59+
pub span: Span,
60+
}
61+
62+
#[derive(Diagnostic)]
63+
#[diag("invalid klint attribute")]
64+
struct InvalidAttribute {
65+
#[primary_span]
66+
pub span: Span,
67+
}
68+
69+
#[derive(Diagnostic)]
70+
#[diag("incorrect usage of `#[kint::diagnostic_item]`")]
71+
#[help(r#"correct usage looks like `#[kint::diagnostic_item = "name"]`"#)]
72+
struct InvalidDiagnosticItem {
73+
#[primary_span]
74+
pub span: Span,
75+
}
76+
4677
struct Cursor<'a> {
4778
eof: TokenTree,
4879
cursor: tokenstream::TokenStreamIter<'a>,
@@ -75,26 +106,9 @@ impl<'a> Cursor<'a> {
75106

76107
struct AttrParser<'tcx> {
77108
tcx: TyCtxt<'tcx>,
78-
hir_id: HirId,
79109
}
80110

81111
impl<'tcx> AttrParser<'tcx> {
82-
fn error(
83-
&self,
84-
span: Span,
85-
decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
86-
) -> Result<!, ErrorGuaranteed> {
87-
self.tcx
88-
.node_span_lint(crate::INCORRECT_ATTRIBUTE, self.hir_id, span, |lint| {
89-
lint.primary_message("incorrect usage of `#[kint::preempt_count]`");
90-
decorate(lint);
91-
});
92-
Err(self
93-
.tcx
94-
.dcx()
95-
.span_delayed_bug(span, "incorrect usage of `#[kint::preempt_count]`"))
96-
}
97-
98112
fn parse_comma_delimited(
99113
&self,
100114
mut cursor: Cursor<'_>,
@@ -123,9 +137,10 @@ impl<'tcx> AttrParser<'tcx> {
123137
_
124138
)
125139
) {
126-
self.error(comma.span(), |diag| {
127-
diag.help("`,` expected between property values");
128-
})?;
140+
Err(self.tcx.dcx().emit_err(InvalidPreemptCountAttribute {
141+
span: comma.span(),
142+
help: "`,` expected between property values",
143+
}))?
129144
}
130145
}
131146
}
@@ -137,17 +152,18 @@ impl<'tcx> AttrParser<'tcx> {
137152
f: impl FnOnce(Ident, Cursor<'a>) -> Result<Cursor<'a>, ErrorGuaranteed>,
138153
) -> Result<Cursor<'a>, ErrorGuaranteed> {
139154
let prop = cursor.next();
140-
let invalid_prop = |span| {
141-
self.error(span, |diag| {
142-
diag.help("identifier expected");
143-
})?;
144-
};
145155

146156
let TokenTree::Token(token, _) = prop else {
147-
return invalid_prop(prop.span());
157+
Err(self.tcx.dcx().emit_err(InvalidPreemptCountAttribute {
158+
span: prop.span(),
159+
help: "identifier expected",
160+
}))?
148161
};
149162
let Some((name, _)) = token.ident() else {
150-
return invalid_prop(token.span);
163+
Err(self.tcx.dcx().emit_err(InvalidPreemptCountAttribute {
164+
span: token.span,
165+
help: "identifier expected",
166+
}))?
151167
};
152168

153169
let need_eq = need_eq(name)?;
@@ -165,14 +181,16 @@ impl<'tcx> AttrParser<'tcx> {
165181
)
166182
);
167183
if need_eq && !is_eq {
168-
self.error(eq.span(), |diag| {
169-
diag.help("`=` expected after property name");
170-
})?;
184+
Err(self.tcx.dcx().emit_err(InvalidPreemptCountAttribute {
185+
span: eq.span(),
186+
help: "`=` expected after property name",
187+
}))?
171188
}
172189
if !need_eq && is_eq {
173-
self.error(eq.span(), |diag| {
174-
diag.help("unexpected `=` after property name");
175-
})?;
190+
Err(self.tcx.dcx().emit_err(InvalidPreemptCountAttribute {
191+
span: eq.span(),
192+
help: "unexpected `=` after property name",
193+
}))?
176194
}
177195

178196
if is_eq {
@@ -186,9 +204,10 @@ impl<'tcx> AttrParser<'tcx> {
186204

187205
fn parse_i32<'a>(&self, mut cursor: Cursor<'a>) -> Result<(i32, Cursor<'a>), ErrorGuaranteed> {
188206
let expect_int = |span| {
189-
self.error(span, |diag| {
190-
diag.help("an integer expected");
191-
})
207+
Err(self.tcx.dcx().emit_err(InvalidPreemptCountAttribute {
208+
span,
209+
help: "an integer expected",
210+
}))
192211
};
193212

194213
let negative = if matches!(
@@ -234,9 +253,10 @@ impl<'tcx> AttrParser<'tcx> {
234253
mut cursor: Cursor<'a>,
235254
) -> Result<((u32, Option<u32>), Cursor<'a>), ErrorGuaranteed> {
236255
let expect_range = |span| {
237-
self.error(span, |diag| {
238-
diag.help("a range expected");
239-
})
256+
Err(self.tcx.dcx().emit_err(InvalidPreemptCountAttribute {
257+
span,
258+
help: "a range expected",
259+
}))
240260
};
241261

242262
let start_span = cursor.peek().span();
@@ -332,9 +352,10 @@ impl<'tcx> AttrParser<'tcx> {
332352
if end.is_some() && end.unwrap() <= start {
333353
let end_span = cursor.next().span();
334354

335-
self.error(start_span.until(end_span), |diag| {
336-
diag.help("the preemption count expectation range must be non-empty");
337-
})?;
355+
Err(self.tcx.dcx().emit_err(InvalidPreemptCountAttribute {
356+
span: start_span.until(end_span),
357+
help: "the preemption count expectation range must be non-empty",
358+
}))?
338359
}
339360

340361
Ok(((start, end), cursor))
@@ -355,9 +376,10 @@ impl<'tcx> AttrParser<'tcx> {
355376
..
356377
}) = &item.args
357378
else {
358-
self.error(attr.span(), |diag| {
359-
diag.help("correct usage looks like `#[kint::preempt_count(...)]`");
360-
})?;
379+
Err(self.tcx.dcx().emit_err(InvalidPreemptCountAttribute {
380+
span: attr.span(),
381+
help: "correct usage looks like `#[kint::preempt_count(...)]`",
382+
}))?
361383
};
362384

363385
self.parse_comma_delimited(Cursor::new(tts.iter(), delim_span.close), |cursor| {
@@ -367,13 +389,10 @@ impl<'tcx> AttrParser<'tcx> {
367389
Ok(match name.name {
368390
crate::symbol::adjust | sym::expect => true,
369391
crate::symbol::unchecked => false,
370-
_ => {
371-
self.error(name.span, |diag| {
372-
diag.help(
373-
"unknown property, expected `adjust`, `expect` or `unchecked`",
374-
);
375-
})?;
376-
}
392+
_ => Err(self.tcx.dcx().emit_err(InvalidPreemptCountAttribute {
393+
span: name.span,
394+
help: "unknown property, expected `adjust`, `expect` or `unchecked`",
395+
}))?,
377396
})
378397
},
379398
|name, mut cursor| {
@@ -400,9 +419,10 @@ impl<'tcx> AttrParser<'tcx> {
400419
})?;
401420

402421
if adjustment.is_none() && expectation.is_none() {
403-
self.error(delim_span.entire(), |diag| {
404-
diag.help("at least one of `adjust` or `expect` property must be specified");
405-
})?;
422+
Err(self.tcx.dcx().emit_err(InvalidPreemptCountAttribute {
423+
span: delim_span.entire(),
424+
help: "at least one of `adjust` or `expect` property must be specified",
425+
}))?
406426
}
407427

408428
Ok(PreemptionCount {
@@ -421,9 +441,8 @@ impl<'tcx> AttrParser<'tcx> {
421441
};
422442
if item.path.segments.len() != 2 {
423443
self.tcx
424-
.node_span_lint(crate::INCORRECT_ATTRIBUTE, self.hir_id, item.span, |lint| {
425-
lint.primary_message("invalid klint attribute");
426-
});
444+
.dcx()
445+
.emit_err(InvalidAttribute { span: item.span });
427446
return None;
428447
}
429448
match item.path.segments[1] {
@@ -468,37 +487,26 @@ impl<'tcx> AttrParser<'tcx> {
468487
},
469488
} = item.args
470489
else {
471-
self.error(attr.span(), |diag| {
472-
diag.help(
473-
r#"correct usage looks like `#[kint::diagnostic_item = "name"]`"#,
474-
);
475-
})
476-
.ok()?;
490+
self.tcx
491+
.dcx()
492+
.emit_err(InvalidDiagnosticItem { span: attr.span() });
493+
None?
477494
};
478495

479496
Some(KlintAttribute::DiagnosticItem(value))
480497
}
481498
_ => {
482-
self.tcx.node_span_lint(
483-
crate::INCORRECT_ATTRIBUTE,
484-
self.hir_id,
485-
item.path.span,
486-
|lint| {
487-
lint.primary_message("unrecognized klint attribute");
488-
},
489-
);
499+
self.tcx.dcx().emit_err(UnknownAttribute {
500+
span: item.path.span,
501+
});
490502
None
491503
}
492504
}
493505
}
494506
}
495507

496-
pub fn parse_klint_attribute(
497-
tcx: TyCtxt<'_>,
498-
hir_id: HirId,
499-
attr: &Attribute,
500-
) -> Option<KlintAttribute> {
501-
AttrParser { tcx, hir_id }.parse(attr)
508+
pub fn parse_klint_attribute(tcx: TyCtxt<'_>, attr: &Attribute) -> Option<KlintAttribute> {
509+
AttrParser { tcx }.parse(attr)
502510
}
503511

504512
memoize!(
@@ -508,7 +516,7 @@ memoize!(
508516
) -> Arc<Vec<KlintAttribute>> {
509517
let mut v = Vec::new();
510518
for attr in cx.hir_attrs(hir_id) {
511-
let Some(attr) = crate::attribute::parse_klint_attribute(cx.tcx, hir_id, attr) else {
519+
let Some(attr) = crate::attribute::parse_klint_attribute(cx.tcx, attr) else {
512520
continue;
513521
};
514522
v.push(attr);

src/main.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,6 @@ mod symbol;
7373
mod util;
7474
mod utils;
7575

76-
rustc_session::declare_tool_lint! {
77-
pub klint::INCORRECT_ATTRIBUTE,
78-
Forbid,
79-
"Incorrect usage of klint attributes"
80-
}
81-
8276
struct MyCallbacks;
8377

8478
impl Callbacks for MyCallbacks {
@@ -113,7 +107,6 @@ impl Callbacks for MyCallbacks {
113107
});
114108
config.register_lints = Some(Box::new(move |_, lint_store| {
115109
lint_store.register_lints(&[
116-
INCORRECT_ATTRIBUTE,
117110
infallible_allocation::INFALLIBLE_ALLOCATION,
118111
atomic_context::ATOMIC_CONTEXT,
119112
binary_analysis::stack_size::STACK_FRAME_TOO_LARGE,

tests/ui/annotation.stderr

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ error: incorrect usage of `#[kint::preempt_count]`
55
| ^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= help: correct usage looks like `#[kint::preempt_count(...)]`
8-
= note: `#[forbid(klint::incorrect_attribute)]` on by default
98

109
error: incorrect usage of `#[kint::preempt_count]`
1110
--> $DIR/annotation.rs:8:23

0 commit comments

Comments
 (0)