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

Rework how diagnostic lints are stored. #119922

Merged
merged 2 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
use rustc_data_structures::sync::Lrc;
use rustc_errors::emitter::Emitter;
use rustc_errors::{translation::Translate, DiagCtxt, DiagnosticId, FatalError, Level};
use rustc_errors::{translation::Translate, DiagCtxt, FatalError, Level};
use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, Style};
use rustc_fs_util::link_or_copy;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
Expand Down Expand Up @@ -1000,7 +1000,7 @@ type DiagnosticArgName<'source> = Cow<'source, str>;
struct Diagnostic {
msgs: Vec<(DiagnosticMessage, Style)>,
args: FxHashMap<DiagnosticArgName<'static>, rustc_errors::DiagnosticArgValue<'static>>,
code: Option<DiagnosticId>,
code: Option<String>,
lvl: Level,
}

Expand Down
12 changes: 4 additions & 8 deletions compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use crate::emitter::FileWithAnnotatedLines;
use crate::snippet::Line;
use crate::translation::{to_fluent_args, Translate};
use crate::{
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle,
LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic,
CodeSuggestion, Diagnostic, DiagnosticMessage, Emitter, FluentBundle, LazyFallbackBundle,
Level, MultiSpan, Style, SubDiagnostic,
};
use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
use rustc_data_structures::sync::Lrc;
Expand Down Expand Up @@ -127,7 +127,7 @@ impl AnnotateSnippetEmitter {
level: &Level,
messages: &[(DiagnosticMessage, Style)],
args: &FluentArgs<'_>,
code: &Option<DiagnosticId>,
code: &Option<String>,
msp: &MultiSpan,
_children: &[SubDiagnostic],
_suggestions: &[CodeSuggestion],
Expand Down Expand Up @@ -181,11 +181,7 @@ impl AnnotateSnippetEmitter {
let snippet = Snippet {
title: Some(Annotation {
label: Some(&message),
id: code.as_ref().map(|c| match c {
DiagnosticId::Error(val) | DiagnosticId::Lint { name: val, .. } => {
val.as_str()
}
}),
id: code.as_deref(),
annotation_type: annotation_type_for_level(*level),
}),
footer: vec![],
Expand Down
45 changes: 21 additions & 24 deletions compiler/rustc_errors/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub struct Diagnostic {
pub(crate) level: Level,

pub messages: Vec<(DiagnosticMessage, Style)>,
pub code: Option<DiagnosticId>,
pub code: Option<String>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to store an integer instead of a string here? An ErrorCode type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! You're going to love #119972, which I just finished :)

pub span: MultiSpan,
pub children: Vec<SubDiagnostic>,
pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
Expand All @@ -115,9 +115,9 @@ pub struct Diagnostic {
/// `span` if there is one. Otherwise, it is `DUMMY_SP`.
pub sort_span: Span,

/// If diagnostic is from Lint, custom hash function ignores notes
/// otherwise hash is based on the all the fields
pub is_lint: bool,
/// If diagnostic is from Lint, custom hash function ignores children.
/// Otherwise hash is based on the all the fields.
pub is_lint: Option<IsLint>,

/// With `-Ztrack_diagnostics` enabled,
/// we print where in rustc this error was emitted.
Expand Down Expand Up @@ -146,13 +146,11 @@ impl fmt::Display for DiagnosticLocation {
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
pub enum DiagnosticId {
Error(String),
Lint {
name: String,
/// Indicates whether this lint should show up in cargo's future breakage report.
has_future_breakage: bool,
},
pub struct IsLint {
/// The lint name.
pub(crate) name: String,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this use the &Lint? Or is there an issue with crate dependency order?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting idea. Crate dependencies shouldn't be a problem. This struct has two fields:

  • name, which is equivalent to Lint::lower_name().
  • has_future_breakage, which is a combination of Lint::future_incompatible, Lint::default_level, and sess.opts.unstable_opts.future_incompat_test. Adding a sess argument to Diagnostic::has_future_breakage() is awkward.

So I think keeping IsLint is probably best.

/// Indicates whether this lint should show up in cargo's future breakage report.
has_future_breakage: bool,
}

/// A "sub"-diagnostic attached to a parent diagnostic.
Expand Down Expand Up @@ -231,7 +229,7 @@ impl Diagnostic {
suggestions: Ok(vec![]),
args: Default::default(),
sort_span: DUMMY_SP,
is_lint: false,
is_lint: None,
emitted_at: DiagnosticLocation::caller(),
}
}
Expand Down Expand Up @@ -288,16 +286,13 @@ impl Diagnostic {

/// Indicates whether this diagnostic should show up in cargo's future breakage report.
pub(crate) fn has_future_breakage(&self) -> bool {
match self.code {
Some(DiagnosticId::Lint { has_future_breakage, .. }) => has_future_breakage,
_ => false,
}
matches!(self.is_lint, Some(IsLint { has_future_breakage: true, .. }))
}

pub(crate) fn is_force_warn(&self) -> bool {
match self.level {
Level::ForceWarning(_) => {
assert!(self.is_lint);
assert!(self.is_lint.is_some());
true
}
_ => false,
Expand Down Expand Up @@ -893,12 +888,12 @@ impl Diagnostic {
self
}

pub fn is_lint(&mut self) -> &mut Self {
self.is_lint = true;
pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self {
self.is_lint = Some(IsLint { name, has_future_breakage });
self
}

pub fn code(&mut self, s: DiagnosticId) -> &mut Self {
pub fn code(&mut self, s: String) -> &mut Self {
self.code = Some(s);
self
}
Expand All @@ -908,8 +903,8 @@ impl Diagnostic {
self
}

pub fn get_code(&self) -> Option<DiagnosticId> {
self.code.clone()
pub fn get_code(&self) -> Option<&str> {
self.code.as_deref()
}

pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self {
Expand Down Expand Up @@ -995,7 +990,8 @@ impl Diagnostic {
&Level,
&[(DiagnosticMessage, Style)],
Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>,
&Option<DiagnosticId>,
&Option<String>,
&Option<IsLint>,
&MultiSpan,
&Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
Option<&[SubDiagnostic]>,
Expand All @@ -1005,9 +1001,10 @@ impl Diagnostic {
&self.messages,
self.args().collect(),
&self.code,
&self.is_lint,
&self.span,
&self.suggestions,
(if self.is_lint { None } else { Some(&self.children) }),
(if self.is_lint.is_some() { None } else { Some(&self.children) }),
)
}
}
Expand Down
17 changes: 8 additions & 9 deletions compiler/rustc_errors/src/diagnostic_builder.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::diagnostic::IntoDiagnosticArg;
use crate::{DiagCtxt, Level, MultiSpan, StashKey};
use crate::{
Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed,
ExplicitBug, SubdiagnosticMessage,
Diagnostic, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, ExplicitBug,
SubdiagnosticMessage,
};
use rustc_lint_defs::Applicability;
use rustc_span::source_map::Spanned;
Expand Down Expand Up @@ -395,8 +395,11 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
forward!((span, with_span)(
sp: impl Into<MultiSpan>,
));
forward!((is_lint, with_is_lint)(
name: String, has_future_breakage: bool,
));
forward!((code, with_code)(
s: DiagnosticId,
s: String,
));
forward!((arg, with_arg)(
name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg,
Expand Down Expand Up @@ -437,15 +440,11 @@ impl<G: EmissionGuarantee> Drop for DiagnosticBuilder<'_, G> {
#[macro_export]
macro_rules! struct_span_code_err {
($dcx:expr, $span:expr, $code:ident, $($message:tt)*) => ({
$dcx.struct_span_err(
$span,
format!($($message)*),
)
.with_code($crate::error_code!($code))
$dcx.struct_span_err($span, format!($($message)*)).with_code($crate::error_code!($code))
})
}

#[macro_export]
macro_rules! error_code {
($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }};
($code:ident) => {{ stringify!($code).to_owned() }};
}
17 changes: 8 additions & 9 deletions compiler/rustc_errors/src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use crate::snippet::{
use crate::styled_buffer::StyledBuffer;
use crate::translation::{to_fluent_args, Translate};
use crate::{
diagnostic::DiagnosticLocation, CodeSuggestion, DiagCtxt, Diagnostic, DiagnosticId,
DiagnosticMessage, FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic,
SubstitutionHighlight, SuggestionStyle, TerminalUrl,
diagnostic::DiagnosticLocation, CodeSuggestion, DiagCtxt, Diagnostic, DiagnosticMessage,
FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight,
SuggestionStyle, TerminalUrl,
};
use rustc_lint_defs::pluralize;

Expand Down Expand Up @@ -1309,7 +1309,7 @@ impl HumanEmitter {
msp: &MultiSpan,
msgs: &[(DiagnosticMessage, Style)],
args: &FluentArgs<'_>,
code: &Option<DiagnosticId>,
code: &Option<String>,
level: &Level,
max_line_num_len: usize,
is_secondary: bool,
Expand All @@ -1336,14 +1336,13 @@ impl HumanEmitter {
buffer.append(0, level.to_str(), Style::Level(*level));
label_width += level.to_str().len();
}
// only render error codes, not lint codes
if let Some(DiagnosticId::Error(ref code)) = *code {
if let Some(code) = code {
buffer.append(0, "[", Style::Level(*level));
let code = if let TerminalUrl::Yes = self.terminal_url {
let path = "https://doc.rust-lang.org/error_codes";
format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07")
Cow::Owned(format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07"))
} else {
code.clone()
Cow::Borrowed(code)
};
buffer.append(0, &code, Style::Level(*level));
buffer.append(0, "]", Style::Level(*level));
Expand Down Expand Up @@ -2077,7 +2076,7 @@ impl HumanEmitter {
level: &Level,
messages: &[(DiagnosticMessage, Style)],
args: &FluentArgs<'_>,
code: &Option<DiagnosticId>,
code: &Option<String>,
span: &MultiSpan,
children: &[SubDiagnostic],
suggestions: &[CodeSuggestion],
Expand Down
37 changes: 17 additions & 20 deletions compiler/rustc_errors/src/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ use termcolor::{ColorSpec, WriteColor};
use crate::emitter::{should_show_source_code, Emitter, HumanReadableErrorType};
use crate::registry::Registry;
use crate::translation::{to_fluent_args, Translate};
use crate::DiagnosticId;
use crate::{
CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic,
TerminalUrl,
diagnostic::IsLint, CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel,
SubDiagnostic, TerminalUrl,
};
use rustc_lint_defs::Applicability;

Expand Down Expand Up @@ -301,7 +300,8 @@ struct DiagnosticSpanMacroExpansion {

#[derive(Serialize)]
struct DiagnosticCode {
/// The code itself.
/// The error code (e.g. "E1234"), if the diagnostic has one. Or the lint
/// name, if it's a lint without an error code.
code: String,
/// An explanation for the code.
explanation: Option<&'static str>,
Expand Down Expand Up @@ -399,9 +399,21 @@ impl Diagnostic {
let output = String::from_utf8(output).unwrap();

let translated_message = je.translate_messages(&diag.messages, &args);

let code = if let Some(code) = &diag.code {
Some(DiagnosticCode {
code: code.to_string(),
explanation: je.registry.as_ref().unwrap().try_find_description(&code).ok(),
})
} else if let Some(IsLint { name, .. }) = &diag.is_lint {
Some(DiagnosticCode { code: name.to_string(), explanation: None })
} else {
None
};

Diagnostic {
message: translated_message.to_string(),
code: DiagnosticCode::map_opt_string(diag.code.clone(), je),
code,
level: diag.level.to_str(),
spans: DiagnosticSpan::from_multispan(&diag.span, &args, je),
children: diag
Expand Down Expand Up @@ -592,18 +604,3 @@ impl DiagnosticSpanLine {
.unwrap_or_else(|_| vec![])
}
}

impl DiagnosticCode {
fn map_opt_string(s: Option<DiagnosticId>, je: &JsonEmitter) -> Option<DiagnosticCode> {
s.map(|s| {
let s = match s {
DiagnosticId::Error(s) => s,
DiagnosticId::Lint { name, .. } => name,
};
let je_result =
je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap();

DiagnosticCode { code: s, explanation: je_result.ok() }
})
}
}
Loading
Loading