Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate rustc_lint errors to SessionDiagnostic #100776

Merged
merged 10 commits into from
Aug 27, 2022
34 changes: 34 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/lint.ftl
Original file line number Diff line number Diff line change
@@ -393,3 +393,37 @@ lint_builtin_deref_nullptr = dereferencing a null pointer
.label = this code causes undefined behavior when executed

lint_builtin_asm_labels = avoid using named labels in inline assembly

lint_overruled_attribute = {$lint_level}({$lint_source}) incompatible with previous forbid
.label = overruled by previous forbid

lint_default_source = `forbid` lint level is the default for {$id}

lint_node_source = `forbid` level set here
.note = {$reason}

lint_command_line_source = `forbid` lint level was set on command line

lint_malformed_attribute = malformed lint attribute input

lint_bad_attribute_argument = bad attribute argument

lint_reason_must_be_string_literal = reason must be a string literal

lint_reason_must_come_last = reason in lint attribute must come last

lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
.help = add `#![register_tool({$tool_name})]` to the crate root

lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´

lint_requested_level = requested on the command line with `{$level} {$lint_name}`

lint_check_name_unknown = unknown lint: `{$lint_name}`
.help = did you mean: `{$suggestion}`

lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`

lint_check_name_warning = {$msg}

lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
36 changes: 13 additions & 23 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// #![deny(rustc::diagnostic_outside_of_impl)]
// #![deny(rustc::untranslatable_diagnostic)]
//
//! Lints in the Rust compiler.
//!
//! This contains lints which can feasibly be implemented as their own
@@ -21,6 +24,7 @@
//! `late_lint_methods!` invocation in `lib.rs`.

use crate::{
errors::BuiltinEllpisisInclusiveRangePatterns,
types::{transparent_newtype_field, CItemKind},
EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
};
@@ -1760,18 +1764,11 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
None => format!("&(..={})", end),
};
if join.edition() >= Edition::Edition2021 {
let mut err = cx.sess().struct_span_err_with_code(
pat.span,
msg,
rustc_errors::error_code!(E0783),
);
err.span_suggestion(
pat.span,
suggestion,
cx.sess().emit_err(BuiltinEllpisisInclusiveRangePatterns {
span: pat.span,
suggestion: pat.span,
replace,
Applicability::MachineApplicable,
)
.emit();
});
} else {
cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, |lint| {
lint.build(msg)
@@ -1787,18 +1784,11 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
} else {
let replace = "..=";
if join.edition() >= Edition::Edition2021 {
let mut err = cx.sess().struct_span_err_with_code(
pat.span,
msg,
rustc_errors::error_code!(E0783),
);
err.span_suggestion_short(
join,
suggestion,
replace,
Applicability::MachineApplicable,
)
.emit();
cx.sess().emit_err(BuiltinEllpisisInclusiveRangePatterns {
span: pat.span,
suggestion: join,
replace: replace.to_string(),
});
} else {
cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, |lint| {
lint.build(msg)
96 changes: 38 additions & 58 deletions compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// #![deny(rustc::diagnostic_outside_of_impl)]
// #![deny(rustc::untranslatable_diagnostic)]
//
//! Implementation of lint checking.
//!
//! The lint checking is mostly consolidated into one pass which runs
@@ -16,12 +19,16 @@

use self::TargetLint::*;

use crate::errors::{
CheckNameDeprecated, CheckNameUnknown, CheckNameUnknownTool, CheckNameWarning, RequestedLevel,
UnsupportedGroup,
};
use crate::levels::LintLevelsBuilder;
use crate::passes::{EarlyLintPassObject, LateLintPassObject};
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync;
use rustc_errors::{add_elided_lifetime_in_path_suggestion, struct_span_err};
use rustc_errors::add_elided_lifetime_in_path_suggestion;
use rustc_errors::{
Applicability, DecorateLint, LintDiagnosticBuilder, MultiSpan, SuggestionStyle,
};
@@ -39,7 +46,7 @@ use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintI
use rustc_session::Session;
use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{BytePos, Span, DUMMY_SP};
use rustc_span::{BytePos, Span};
use rustc_target::abi;
use tracing::debug;

@@ -326,68 +333,41 @@ impl LintStore {
) {
let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name);
if lint_name_only == crate::WARNINGS.name_lower() && matches!(level, Level::ForceWarn(_)) {
struct_span_err!(
sess,
DUMMY_SP,
E0602,
"`{}` lint group is not supported with ´--force-warn´",
crate::WARNINGS.name_lower()
)
.emit();
sess.emit_err(UnsupportedGroup { lint_group: crate::WARNINGS.name_lower() });
return;
}
let db = match self.check_lint_name(lint_name_only, tool_name, registered_tools) {
CheckLintNameResult::Ok(_) => None,
CheckLintNameResult::Warning(ref msg, _) => Some(sess.struct_warn(msg)),
let lint_name = lint_name.to_string();
match self.check_lint_name(lint_name_only, tool_name, registered_tools) {
CheckLintNameResult::Warning(msg, _) => {
sess.emit_warning(CheckNameWarning {
msg,
sub: RequestedLevel { level, lint_name },
});
}
CheckLintNameResult::NoLint(suggestion) => {
let mut err =
struct_span_err!(sess, DUMMY_SP, E0602, "unknown lint: `{}`", lint_name);

if let Some(suggestion) = suggestion {
err.help(&format!("did you mean: `{}`", suggestion));
sess.emit_err(CheckNameUnknown {
lint_name: lint_name.clone(),
suggestion,
sub: RequestedLevel { level, lint_name },
});
}
CheckLintNameResult::Tool(result) => {
if let Err((Some(_), new_name)) = result {
sess.emit_warning(CheckNameDeprecated {
lint_name: lint_name.clone(),
new_name,
sub: RequestedLevel { level, lint_name },
});
}

Some(err.forget_guarantee())
}
CheckLintNameResult::Tool(result) => match result {
Err((Some(_), new_name)) => Some(sess.struct_warn(&format!(
"lint name `{}` is deprecated \
and does not have an effect anymore. \
Use: {}",
lint_name, new_name
))),
_ => None,
},
CheckLintNameResult::NoTool => Some(
struct_span_err!(
sess,
DUMMY_SP,
E0602,
"unknown lint tool: `{}`",
tool_name.unwrap()
)
.forget_guarantee(),
),
CheckLintNameResult::NoTool => {
sess.emit_err(CheckNameUnknownTool {
tool_name: tool_name.unwrap(),
sub: RequestedLevel { level, lint_name },
});
}
_ => {}
};

if let Some(mut db) = db {
let msg = format!(
"requested on the command line with `{} {}`",
match level {
Level::Allow => "-A",
Level::Warn => "-W",
Level::ForceWarn(_) => "--force-warn",
Level::Deny => "-D",
Level::Forbid => "-F",
Level::Expect(_) => {
unreachable!("lints with the level of `expect` should not run this code");
}
},
lint_name
);
db.note(&msg);
db.emit();
}
}

/// True if this symbol represents a lint group name.
162 changes: 162 additions & 0 deletions compiler/rustc_lint/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
use rustc_errors::{fluent, AddSubdiagnostic, ErrorGuaranteed};
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
use rustc_session::{lint::Level, parse::ParseSess, SessionDiagnostic};
use rustc_span::{Span, Symbol};

#[derive(SessionDiagnostic)]
#[diag(lint::overruled_attribute, code = "E0453")]
pub struct OverruledAttribute {
#[primary_span]
pub span: Span,
#[label]
pub overruled: Span,
pub lint_level: String,
pub lint_source: Symbol,
#[subdiagnostic]
pub sub: OverruledAttributeSub,
}
//
pub enum OverruledAttributeSub {
davidtwco marked this conversation as resolved.
Show resolved Hide resolved
DefaultSource { id: String },
NodeSource { span: Span, reason: Option<Symbol> },
CommandLineSource,
}

impl AddSubdiagnostic for OverruledAttributeSub {
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
match self {
OverruledAttributeSub::DefaultSource { id } => {
diag.note(fluent::lint::default_source);
diag.set_arg("id", id);
}
OverruledAttributeSub::NodeSource { span, reason } => {
diag.span_label(span, fluent::lint::node_source);
if let Some(rationale) = reason {
diag.note(rationale.as_str());
}
}
OverruledAttributeSub::CommandLineSource => {
diag.note(fluent::lint::command_line_source);
}
}
}
}

#[derive(SessionDiagnostic)]
#[diag(lint::malformed_attribute, code = "E0452")]
pub struct MalformedAttribute {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub sub: MalformedAttributeSub,
}

#[derive(SessionSubdiagnostic)]
pub enum MalformedAttributeSub {
#[label(lint::bad_attribute_argument)]
BadAttributeArgument(#[primary_span] Span),
#[label(lint::reason_must_be_string_literal)]
ReasonMustBeStringLiteral(#[primary_span] Span),
#[label(lint::reason_must_come_last)]
ReasonMustComeLast(#[primary_span] Span),
}

#[derive(SessionDiagnostic)]
#[diag(lint::unknown_tool_in_scoped_lint, code = "E0710")]
pub struct UnknownToolInScopedLint {
#[primary_span]
pub span: Option<Span>,
pub tool_name: Symbol,
pub lint_name: String,
#[help]
pub is_nightly_build: Option<()>,
}

#[derive(SessionDiagnostic)]
#[diag(lint::builtin_ellipsis_inclusive_range_patterns, code = "E0783")]
pub struct BuiltinEllpisisInclusiveRangePatterns {
#[primary_span]
pub span: Span,
#[suggestion_short(code = "{replace}", applicability = "machine-applicable")]
pub suggestion: Span,
pub replace: String,
}

pub struct RequestedLevel {
pub level: Level,
davidtwco marked this conversation as resolved.
Show resolved Hide resolved
pub lint_name: String,
}

impl AddSubdiagnostic for RequestedLevel {
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
diag.note(fluent::lint::requested_level);
diag.set_arg(
"level",
match self.level {
Level::Allow => "-A",
Level::Warn => "-W",
Level::ForceWarn(_) => "--force-warn",
Level::Deny => "-D",
Level::Forbid => "-F",
Level::Expect(_) => {
unreachable!("lints with the level of `expect` should not run this code");
}
},
);
diag.set_arg("lint_name", self.lint_name);
}
}

#[derive(SessionDiagnostic)]
#[diag(lint::unsupported_group, code = "E0602")]
pub struct UnsupportedGroup {
pub lint_group: String,
}

pub struct CheckNameUnknown {
pub lint_name: String,
pub suggestion: Option<Symbol>,
pub sub: RequestedLevel,
}

impl SessionDiagnostic<'_> for CheckNameUnknown {
fn into_diagnostic(
self,
sess: &ParseSess,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
let mut diag = sess.struct_err(fluent::lint::check_name_unknown);
diag.code(rustc_errors::error_code!(E0602));
if let Some(suggestion) = self.suggestion {
diag.help(fluent::lint::help);
diag.set_arg("suggestion", suggestion);
}
diag.set_arg("lint_name", self.lint_name);
diag.subdiagnostic(self.sub);
diag
}
}

#[derive(SessionDiagnostic)]
#[diag(lint::check_name_unknown_tool, code = "E0602")]
pub struct CheckNameUnknownTool {
pub tool_name: Symbol,
#[subdiagnostic]
pub sub: RequestedLevel,
}

#[derive(SessionDiagnostic)]
#[diag(lint::check_name_warning)]
pub struct CheckNameWarning {
pub msg: String,
#[subdiagnostic]
pub sub: RequestedLevel,
}

#[derive(SessionDiagnostic)]
#[diag(lint::check_name_deprecated)]
pub struct CheckNameDeprecated {
pub lint_name: String,
pub new_name: String,
#[subdiagnostic]
pub sub: RequestedLevel,
}
Loading