Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 389dda1

Browse files
authoredAug 26, 2022
Rollup merge of #100776 - Rejyr:diagnostic-migration-rustc-lint, r=davidtwco
Migrate `rustc_lint` errors to `SessionDiagnostic` Draft PR for migrating `rustc_lint` to `SessionDiagnostic`, as part of the [recent blog post](https://blog.rust-lang.org/inside-rust/2022/08/16/diagnostic-effort.html)
2 parents 93b2acd + 1693993 commit 389dda1

File tree

6 files changed

+297
-124
lines changed

6 files changed

+297
-124
lines changed
 

‎compiler/rustc_error_messages/locales/en-US/lint.ftl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,3 +393,37 @@ lint_builtin_deref_nullptr = dereferencing a null pointer
393393
.label = this code causes undefined behavior when executed
394394
395395
lint_builtin_asm_labels = avoid using named labels in inline assembly
396+
397+
lint_overruled_attribute = {$lint_level}({$lint_source}) incompatible with previous forbid
398+
.label = overruled by previous forbid
399+
400+
lint_default_source = `forbid` lint level is the default for {$id}
401+
402+
lint_node_source = `forbid` level set here
403+
.note = {$reason}
404+
405+
lint_command_line_source = `forbid` lint level was set on command line
406+
407+
lint_malformed_attribute = malformed lint attribute input
408+
409+
lint_bad_attribute_argument = bad attribute argument
410+
411+
lint_reason_must_be_string_literal = reason must be a string literal
412+
413+
lint_reason_must_come_last = reason in lint attribute must come last
414+
415+
lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
416+
.help = add `#![register_tool({$tool_name})]` to the crate root
417+
418+
lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
419+
420+
lint_requested_level = requested on the command line with `{$level} {$lint_name}`
421+
422+
lint_check_name_unknown = unknown lint: `{$lint_name}`
423+
.help = did you mean: `{$suggestion}`
424+
425+
lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
426+
427+
lint_check_name_warning = {$msg}
428+
429+
lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}

‎compiler/rustc_lint/src/builtin.rs

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
//! `late_lint_methods!` invocation in `lib.rs`.
2222
2323
use crate::{
24+
errors::BuiltinEllpisisInclusiveRangePatterns,
2425
types::{transparent_newtype_field, CItemKind},
2526
EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
2627
};
@@ -1760,18 +1761,11 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
17601761
None => format!("&(..={})", end),
17611762
};
17621763
if join.edition() >= Edition::Edition2021 {
1763-
let mut err = cx.sess().struct_span_err_with_code(
1764-
pat.span,
1765-
msg,
1766-
rustc_errors::error_code!(E0783),
1767-
);
1768-
err.span_suggestion(
1769-
pat.span,
1770-
suggestion,
1764+
cx.sess().emit_err(BuiltinEllpisisInclusiveRangePatterns {
1765+
span: pat.span,
1766+
suggestion: pat.span,
17711767
replace,
1772-
Applicability::MachineApplicable,
1773-
)
1774-
.emit();
1768+
});
17751769
} else {
17761770
cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, |lint| {
17771771
lint.build(msg)
@@ -1787,18 +1781,11 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
17871781
} else {
17881782
let replace = "..=";
17891783
if join.edition() >= Edition::Edition2021 {
1790-
let mut err = cx.sess().struct_span_err_with_code(
1791-
pat.span,
1792-
msg,
1793-
rustc_errors::error_code!(E0783),
1794-
);
1795-
err.span_suggestion_short(
1796-
join,
1797-
suggestion,
1798-
replace,
1799-
Applicability::MachineApplicable,
1800-
)
1801-
.emit();
1784+
cx.sess().emit_err(BuiltinEllpisisInclusiveRangePatterns {
1785+
span: pat.span,
1786+
suggestion: join,
1787+
replace: replace.to_string(),
1788+
});
18021789
} else {
18031790
cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, |lint| {
18041791
lint.build(msg)

‎compiler/rustc_lint/src/context.rs

Lines changed: 35 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@
1616
1717
use self::TargetLint::*;
1818

19+
use crate::errors::{
20+
CheckNameDeprecated, CheckNameUnknown, CheckNameUnknownTool, CheckNameWarning, RequestedLevel,
21+
UnsupportedGroup,
22+
};
1923
use crate::levels::LintLevelsBuilder;
2024
use crate::passes::{EarlyLintPassObject, LateLintPassObject};
2125
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
2226
use rustc_data_structures::fx::FxHashMap;
2327
use rustc_data_structures::sync;
24-
use rustc_errors::{add_elided_lifetime_in_path_suggestion, struct_span_err};
28+
use rustc_errors::add_elided_lifetime_in_path_suggestion;
2529
use rustc_errors::{
2630
Applicability, DecorateLint, LintDiagnosticBuilder, MultiSpan, SuggestionStyle,
2731
};
@@ -39,7 +43,7 @@ use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintI
3943
use rustc_session::Session;
4044
use rustc_span::lev_distance::find_best_match_for_name;
4145
use rustc_span::symbol::{sym, Ident, Symbol};
42-
use rustc_span::{BytePos, Span, DUMMY_SP};
46+
use rustc_span::{BytePos, Span};
4347
use rustc_target::abi;
4448
use tracing::debug;
4549

@@ -326,68 +330,41 @@ impl LintStore {
326330
) {
327331
let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name);
328332
if lint_name_only == crate::WARNINGS.name_lower() && matches!(level, Level::ForceWarn(_)) {
329-
struct_span_err!(
330-
sess,
331-
DUMMY_SP,
332-
E0602,
333-
"`{}` lint group is not supported with ´--force-warn´",
334-
crate::WARNINGS.name_lower()
335-
)
336-
.emit();
333+
sess.emit_err(UnsupportedGroup { lint_group: crate::WARNINGS.name_lower() });
337334
return;
338335
}
339-
let db = match self.check_lint_name(lint_name_only, tool_name, registered_tools) {
340-
CheckLintNameResult::Ok(_) => None,
341-
CheckLintNameResult::Warning(ref msg, _) => Some(sess.struct_warn(msg)),
336+
let lint_name = lint_name.to_string();
337+
match self.check_lint_name(lint_name_only, tool_name, registered_tools) {
338+
CheckLintNameResult::Warning(msg, _) => {
339+
sess.emit_warning(CheckNameWarning {
340+
msg,
341+
sub: RequestedLevel { level, lint_name },
342+
});
343+
}
342344
CheckLintNameResult::NoLint(suggestion) => {
343-
let mut err =
344-
struct_span_err!(sess, DUMMY_SP, E0602, "unknown lint: `{}`", lint_name);
345-
346-
if let Some(suggestion) = suggestion {
347-
err.help(&format!("did you mean: `{}`", suggestion));
345+
sess.emit_err(CheckNameUnknown {
346+
lint_name: lint_name.clone(),
347+
suggestion,
348+
sub: RequestedLevel { level, lint_name },
349+
});
350+
}
351+
CheckLintNameResult::Tool(result) => {
352+
if let Err((Some(_), new_name)) = result {
353+
sess.emit_warning(CheckNameDeprecated {
354+
lint_name: lint_name.clone(),
355+
new_name,
356+
sub: RequestedLevel { level, lint_name },
357+
});
348358
}
349-
350-
Some(err.forget_guarantee())
351359
}
352-
CheckLintNameResult::Tool(result) => match result {
353-
Err((Some(_), new_name)) => Some(sess.struct_warn(&format!(
354-
"lint name `{}` is deprecated \
355-
and does not have an effect anymore. \
356-
Use: {}",
357-
lint_name, new_name
358-
))),
359-
_ => None,
360-
},
361-
CheckLintNameResult::NoTool => Some(
362-
struct_span_err!(
363-
sess,
364-
DUMMY_SP,
365-
E0602,
366-
"unknown lint tool: `{}`",
367-
tool_name.unwrap()
368-
)
369-
.forget_guarantee(),
370-
),
360+
CheckLintNameResult::NoTool => {
361+
sess.emit_err(CheckNameUnknownTool {
362+
tool_name: tool_name.unwrap(),
363+
sub: RequestedLevel { level, lint_name },
364+
});
365+
}
366+
_ => {}
371367
};
372-
373-
if let Some(mut db) = db {
374-
let msg = format!(
375-
"requested on the command line with `{} {}`",
376-
match level {
377-
Level::Allow => "-A",
378-
Level::Warn => "-W",
379-
Level::ForceWarn(_) => "--force-warn",
380-
Level::Deny => "-D",
381-
Level::Forbid => "-F",
382-
Level::Expect(_) => {
383-
unreachable!("lints with the level of `expect` should not run this code");
384-
}
385-
},
386-
lint_name
387-
);
388-
db.note(&msg);
389-
db.emit();
390-
}
391368
}
392369

393370
/// True if this symbol represents a lint group name.

‎compiler/rustc_lint/src/errors.rs

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
use rustc_errors::{fluent, AddSubdiagnostic, ErrorGuaranteed};
2+
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
3+
use rustc_session::{lint::Level, parse::ParseSess, SessionDiagnostic};
4+
use rustc_span::{Span, Symbol};
5+
6+
#[derive(SessionDiagnostic)]
7+
#[diag(lint::overruled_attribute, code = "E0453")]
8+
pub struct OverruledAttribute {
9+
#[primary_span]
10+
pub span: Span,
11+
#[label]
12+
pub overruled: Span,
13+
pub lint_level: String,
14+
pub lint_source: Symbol,
15+
#[subdiagnostic]
16+
pub sub: OverruledAttributeSub,
17+
}
18+
//
19+
pub enum OverruledAttributeSub {
20+
DefaultSource { id: String },
21+
NodeSource { span: Span, reason: Option<Symbol> },
22+
CommandLineSource,
23+
}
24+
25+
impl AddSubdiagnostic for OverruledAttributeSub {
26+
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
27+
match self {
28+
OverruledAttributeSub::DefaultSource { id } => {
29+
diag.note(fluent::lint::default_source);
30+
diag.set_arg("id", id);
31+
}
32+
OverruledAttributeSub::NodeSource { span, reason } => {
33+
diag.span_label(span, fluent::lint::node_source);
34+
if let Some(rationale) = reason {
35+
diag.note(rationale.as_str());
36+
}
37+
}
38+
OverruledAttributeSub::CommandLineSource => {
39+
diag.note(fluent::lint::command_line_source);
40+
}
41+
}
42+
}
43+
}
44+
45+
#[derive(SessionDiagnostic)]
46+
#[diag(lint::malformed_attribute, code = "E0452")]
47+
pub struct MalformedAttribute {
48+
#[primary_span]
49+
pub span: Span,
50+
#[subdiagnostic]
51+
pub sub: MalformedAttributeSub,
52+
}
53+
54+
#[derive(SessionSubdiagnostic)]
55+
pub enum MalformedAttributeSub {
56+
#[label(lint::bad_attribute_argument)]
57+
BadAttributeArgument(#[primary_span] Span),
58+
#[label(lint::reason_must_be_string_literal)]
59+
ReasonMustBeStringLiteral(#[primary_span] Span),
60+
#[label(lint::reason_must_come_last)]
61+
ReasonMustComeLast(#[primary_span] Span),
62+
}
63+
64+
#[derive(SessionDiagnostic)]
65+
#[diag(lint::unknown_tool_in_scoped_lint, code = "E0710")]
66+
pub struct UnknownToolInScopedLint {
67+
#[primary_span]
68+
pub span: Option<Span>,
69+
pub tool_name: Symbol,
70+
pub lint_name: String,
71+
#[help]
72+
pub is_nightly_build: Option<()>,
73+
}
74+
75+
#[derive(SessionDiagnostic)]
76+
#[diag(lint::builtin_ellipsis_inclusive_range_patterns, code = "E0783")]
77+
pub struct BuiltinEllpisisInclusiveRangePatterns {
78+
#[primary_span]
79+
pub span: Span,
80+
#[suggestion_short(code = "{replace}", applicability = "machine-applicable")]
81+
pub suggestion: Span,
82+
pub replace: String,
83+
}
84+
85+
pub struct RequestedLevel {
86+
pub level: Level,
87+
pub lint_name: String,
88+
}
89+
90+
impl AddSubdiagnostic for RequestedLevel {
91+
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
92+
diag.note(fluent::lint::requested_level);
93+
diag.set_arg(
94+
"level",
95+
match self.level {
96+
Level::Allow => "-A",
97+
Level::Warn => "-W",
98+
Level::ForceWarn(_) => "--force-warn",
99+
Level::Deny => "-D",
100+
Level::Forbid => "-F",
101+
Level::Expect(_) => {
102+
unreachable!("lints with the level of `expect` should not run this code");
103+
}
104+
},
105+
);
106+
diag.set_arg("lint_name", self.lint_name);
107+
}
108+
}
109+
110+
#[derive(SessionDiagnostic)]
111+
#[diag(lint::unsupported_group, code = "E0602")]
112+
pub struct UnsupportedGroup {
113+
pub lint_group: String,
114+
}
115+
116+
pub struct CheckNameUnknown {
117+
pub lint_name: String,
118+
pub suggestion: Option<Symbol>,
119+
pub sub: RequestedLevel,
120+
}
121+
122+
impl SessionDiagnostic<'_> for CheckNameUnknown {
123+
fn into_diagnostic(
124+
self,
125+
sess: &ParseSess,
126+
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
127+
let mut diag = sess.struct_err(fluent::lint::check_name_unknown);
128+
diag.code(rustc_errors::error_code!(E0602));
129+
if let Some(suggestion) = self.suggestion {
130+
diag.help(fluent::lint::help);
131+
diag.set_arg("suggestion", suggestion);
132+
}
133+
diag.set_arg("lint_name", self.lint_name);
134+
diag.subdiagnostic(self.sub);
135+
diag
136+
}
137+
}
138+
139+
#[derive(SessionDiagnostic)]
140+
#[diag(lint::check_name_unknown_tool, code = "E0602")]
141+
pub struct CheckNameUnknownTool {
142+
pub tool_name: Symbol,
143+
#[subdiagnostic]
144+
pub sub: RequestedLevel,
145+
}
146+
147+
#[derive(SessionDiagnostic)]
148+
#[diag(lint::check_name_warning)]
149+
pub struct CheckNameWarning {
150+
pub msg: String,
151+
#[subdiagnostic]
152+
pub sub: RequestedLevel,
153+
}
154+
155+
#[derive(SessionDiagnostic)]
156+
#[diag(lint::check_name_deprecated)]
157+
pub struct CheckNameDeprecated {
158+
pub lint_name: String,
159+
pub new_name: String,
160+
#[subdiagnostic]
161+
pub sub: RequestedLevel,
162+
}

‎compiler/rustc_lint/src/levels.rs

Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::late::unerased_lint_store;
33
use rustc_ast as ast;
44
use rustc_ast_pretty::pprust;
55
use rustc_data_structures::fx::FxHashMap;
6-
use rustc_errors::{struct_span_err, Applicability, Diagnostic, LintDiagnosticBuilder, MultiSpan};
6+
use rustc_errors::{Applicability, Diagnostic, LintDiagnosticBuilder, MultiSpan};
77
use rustc_hir as hir;
88
use rustc_hir::{intravisit, HirId};
99
use rustc_middle::hir::nested_filter;
@@ -23,6 +23,11 @@ use rustc_span::symbol::{sym, Symbol};
2323
use rustc_span::{Span, DUMMY_SP};
2424
use tracing::debug;
2525

26+
use crate::errors::{
27+
MalformedAttribute, MalformedAttributeSub, OverruledAttribute, OverruledAttributeSub,
28+
UnknownToolInScopedLint,
29+
};
30+
2631
fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap {
2732
let store = unerased_lint_store(tcx);
2833
let levels =
@@ -186,16 +191,26 @@ impl<'s> LintLevelsBuilder<'s> {
186191
}
187192
};
188193
if !fcw_warning {
189-
let mut diag_builder = struct_span_err!(
190-
self.sess,
191-
src.span(),
192-
E0453,
193-
"{}({}) incompatible with previous forbid",
194-
level.as_str(),
195-
src.name(),
196-
);
197-
decorate_diag(&mut diag_builder);
198-
diag_builder.emit();
194+
self.sess.emit_err(OverruledAttribute {
195+
span: src.span(),
196+
overruled: src.span(),
197+
lint_level: level.as_str().to_string(),
198+
lint_source: src.name(),
199+
sub: match old_src {
200+
LintLevelSource::Default => {
201+
OverruledAttributeSub::DefaultSource { id: id.to_string() }
202+
}
203+
LintLevelSource::Node(_, forbid_source_span, reason) => {
204+
OverruledAttributeSub::NodeSource {
205+
span: forbid_source_span,
206+
reason,
207+
}
208+
}
209+
LintLevelSource::CommandLine(_, _) => {
210+
OverruledAttributeSub::CommandLineSource
211+
}
212+
},
213+
});
199214
} else {
200215
self.struct_lint(
201216
FORBIDDEN_LINT_GROUPS,
@@ -266,7 +281,6 @@ impl<'s> LintLevelsBuilder<'s> {
266281
self.cur = self.sets.list.push(LintSet { specs: FxHashMap::default(), parent: prev });
267282

268283
let sess = self.sess;
269-
let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input");
270284
for (attr_index, attr) in attrs.iter().enumerate() {
271285
if attr.has_name(sym::automatically_derived) {
272286
self.current_specs_mut().insert(
@@ -317,20 +331,27 @@ impl<'s> LintLevelsBuilder<'s> {
317331
}
318332
reason = Some(rationale);
319333
} else {
320-
bad_attr(name_value.span)
321-
.span_label(name_value.span, "reason must be a string literal")
322-
.emit();
334+
sess.emit_err(MalformedAttribute {
335+
span: name_value.span,
336+
sub: MalformedAttributeSub::ReasonMustBeStringLiteral(
337+
name_value.span,
338+
),
339+
});
323340
}
324341
// found reason, reslice meta list to exclude it
325342
metas.pop().unwrap();
326343
} else {
327-
bad_attr(item.span)
328-
.span_label(item.span, "bad attribute argument")
329-
.emit();
344+
sess.emit_err(MalformedAttribute {
345+
span: item.span,
346+
sub: MalformedAttributeSub::BadAttributeArgument(item.span),
347+
});
330348
}
331349
}
332350
ast::MetaItemKind::List(_) => {
333-
bad_attr(item.span).span_label(item.span, "bad attribute argument").emit();
351+
sess.emit_err(MalformedAttribute {
352+
span: item.span,
353+
sub: MalformedAttributeSub::BadAttributeArgument(item.span),
354+
});
334355
}
335356
}
336357
}
@@ -348,20 +369,21 @@ impl<'s> LintLevelsBuilder<'s> {
348369
let meta_item = match li {
349370
ast::NestedMetaItem::MetaItem(meta_item) if meta_item.is_word() => meta_item,
350371
_ => {
351-
let mut err = bad_attr(sp);
352-
let mut add_label = true;
353372
if let Some(item) = li.meta_item() {
354373
if let ast::MetaItemKind::NameValue(_) = item.kind {
355374
if item.path == sym::reason {
356-
err.span_label(sp, "reason in lint attribute must come last");
357-
add_label = false;
375+
sess.emit_err(MalformedAttribute {
376+
span: sp,
377+
sub: MalformedAttributeSub::ReasonMustComeLast(sp),
378+
});
379+
continue;
358380
}
359381
}
360382
}
361-
if add_label {
362-
err.span_label(sp, "bad attribute argument");
363-
}
364-
err.emit();
383+
sess.emit_err(MalformedAttribute {
384+
span: sp,
385+
sub: MalformedAttributeSub::BadAttributeArgument(sp),
386+
});
365387
continue;
366388
}
367389
};
@@ -485,22 +507,12 @@ impl<'s> LintLevelsBuilder<'s> {
485507
}
486508

487509
&CheckLintNameResult::NoTool => {
488-
let mut err = struct_span_err!(
489-
sess,
490-
tool_ident.map_or(DUMMY_SP, |ident| ident.span),
491-
E0710,
492-
"unknown tool name `{}` found in scoped lint: `{}::{}`",
493-
tool_name.unwrap(),
494-
tool_name.unwrap(),
495-
pprust::path_to_string(&meta_item.path),
496-
);
497-
if sess.is_nightly_build() {
498-
err.help(&format!(
499-
"add `#![register_tool({})]` to the crate root",
500-
tool_name.unwrap()
501-
));
502-
}
503-
err.emit();
510+
sess.emit_err(UnknownToolInScopedLint {
511+
span: tool_ident.map(|ident| ident.span),
512+
tool_name: tool_name.unwrap(),
513+
lint_name: pprust::path_to_string(&meta_item.path),
514+
is_nightly_build: sess.is_nightly_build().then_some(()),
515+
});
504516
continue;
505517
}
506518

‎compiler/rustc_lint/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub mod builtin;
4747
mod context;
4848
mod early;
4949
mod enum_intrinsics_non_enums;
50+
mod errors;
5051
mod expect;
5152
pub mod hidden_unicode_codepoints;
5253
mod internal;

0 commit comments

Comments
 (0)
Please sign in to comment.