diff options
| author | bors <bors@rust-lang.org> | 2024-02-20 12:05:09 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-02-20 12:05:09 +0000 |
| commit | 29f87ade9d78d233e85ef6ca2d6153d0d4fd38d6 (patch) | |
| tree | 6224d184fc8bb6bb02ef7ef2838d4114169ddb60 /compiler/rustc_errors | |
| parent | cce6a6e22e715bd74455f2560a956ab920c3a914 (diff) | |
| parent | f6f87798439e2ce7861da761b444fe0978335ed9 (diff) | |
| download | rust-29f87ade9d78d233e85ef6ca2d6153d0d4fd38d6.tar.gz rust-29f87ade9d78d233e85ef6ca2d6153d0d4fd38d6.zip | |
Auto merge of #120576 - nnethercote:merge-Diagnostic-DiagnosticBuilder, r=davidtwco
Overhaul `Diagnostic` and `DiagnosticBuilder` Implements the first part of https://github.com/rust-lang/compiler-team/issues/722, which moves functionality and use away from `Diagnostic`, onto `DiagnosticBuilder`. Likely follow-ups: - Move things around, because this PR was written to minimize diff size, so some things end up in sub-optimal places. E.g. `DiagnosticBuilder` has impls in both `diagnostic.rs` and `diagnostic_builder.rs`. - Rename `Diagnostic` as `DiagInner` and `DiagnosticBuilder` as `Diag`. r? `@davidtwco`
Diffstat (limited to 'compiler/rustc_errors')
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic.rs | 212 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic_builder.rs | 191 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic_impls.rs | 30 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/emitter.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/lib.rs | 86 |
5 files changed, 213 insertions, 308 deletions
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 034636bea48..57610635ee6 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -12,6 +12,7 @@ use rustc_span::{Span, DUMMY_SP}; use std::borrow::Cow; use std::fmt::{self, Debug}; use std::hash::{Hash, Hasher}; +use std::ops::{Deref, DerefMut}; use std::panic::Location; /// Error type for `Diagnostic`'s `suggestions` field, indicating that @@ -71,17 +72,21 @@ where Self: Sized, { /// Add a subdiagnostic to an existing diagnostic. - fn add_to_diagnostic(self, diag: &mut Diagnostic) { + fn add_to_diagnostic<G: EmissionGuarantee>(self, diag: &mut DiagnosticBuilder<'_, G>) { self.add_to_diagnostic_with(diag, |_, m| m); } /// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used /// (to optionally perform eager translation). - fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F); + fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + f: F, + ); } -pub trait SubdiagnosticMessageOp = - Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage; +pub trait SubdiagnosticMessageOp<G> = + Fn(&mut DiagnosticBuilder<'_, G>, SubdiagnosticMessage) -> SubdiagnosticMessage; /// Trait implemented by lint types. This should not be implemented manually. Instead, use /// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic]. @@ -93,6 +98,10 @@ pub trait DecorateLint<'a, G: EmissionGuarantee> { fn msg(&self) -> DiagnosticMessage; } +/// The main part of a diagnostic. Note that `DiagnosticBuilder`, which wraps +/// this type, is used for most operations, and should be used instead whenever +/// possible. This type should only be used when `DiagnosticBuilder`'s lifetime +/// causes difficulties, e.g. when storing diagnostics within `DiagCtxt`. #[must_use] #[derive(Clone, Debug, Encodable, Decodable)] pub struct Diagnostic { @@ -289,6 +298,90 @@ impl Diagnostic { } } + // See comment on `DiagnosticBuilder::subdiagnostic_message_to_diagnostic_message`. + pub(crate) fn subdiagnostic_message_to_diagnostic_message( + &self, + attr: impl Into<SubdiagnosticMessage>, + ) -> DiagnosticMessage { + let msg = + self.messages.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages"); + msg.with_subdiagnostic_message(attr.into()) + } + + pub(crate) fn sub( + &mut self, + level: Level, + message: impl Into<SubdiagnosticMessage>, + span: MultiSpan, + ) { + let sub = SubDiagnostic { + level, + messages: vec![( + self.subdiagnostic_message_to_diagnostic_message(message), + Style::NoStyle, + )], + span, + }; + self.children.push(sub); + } + + pub(crate) fn arg(&mut self, name: impl Into<DiagnosticArgName>, arg: impl IntoDiagnosticArg) { + self.args.insert(name.into(), arg.into_diagnostic_arg()); + } + + pub fn args(&self) -> impl Iterator<Item = DiagnosticArg<'_>> { + self.args.iter() + } + + pub fn replace_args(&mut self, args: FxIndexMap<DiagnosticArgName, DiagnosticArgValue>) { + self.args = args; + } +} + +/// `DiagnosticBuilder` impls many `&mut self -> &mut Self` methods. Each one +/// modifies an existing diagnostic, either in a standalone fashion, e.g. +/// `err.code(code);`, or in a chained fashion to make multiple modifications, +/// e.g. `err.code(code).span(span);`. +/// +/// This macro creates an equivalent `self -> Self` method, with a `with_` +/// prefix. This can be used in a chained fashion when making a new diagnostic, +/// e.g. `let err = struct_err(msg).with_code(code);`, or emitting a new +/// diagnostic, e.g. `struct_err(msg).with_code(code).emit();`. +/// +/// Although the latter method can be used to modify an existing diagnostic, +/// e.g. `err = err.with_code(code);`, this should be avoided because the former +/// method gives shorter code, e.g. `err.code(code);`. +/// +/// Note: the `with_` methods are added only when needed. If you want to use +/// one and it's not defined, feel free to add it. +/// +/// Note: any doc comments must be within the `with_fn!` call. +macro_rules! with_fn { + { + $with_f:ident, + $(#[$attrs:meta])* + pub fn $f:ident(&mut $self:ident, $($name:ident: $ty:ty),* $(,)?) -> &mut Self { + $($body:tt)* + } + } => { + // The original function. + $(#[$attrs])* + #[doc = concat!("See [`DiagnosticBuilder::", stringify!($f), "()`].")] + pub fn $f(&mut $self, $($name: $ty),*) -> &mut Self { + $($body)* + } + + // The `with_*` variant. + $(#[$attrs])* + #[doc = concat!("See [`DiagnosticBuilder::", stringify!($f), "()`].")] + pub fn $with_f(mut $self, $($name: $ty),*) -> Self { + $self.$f($($name),*); + $self + } + }; +} + +impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Delay emission of this diagnostic as a bug. /// /// This can be useful in contexts where an error indicates a bug but @@ -309,6 +402,7 @@ impl Diagnostic { self.level = Level::DelayedBug; } + with_fn! { with_span_label, /// Appends a labeled span to the diagnostic. /// /// Labels are used to convey additional context for the diagnostic's primary span. They will @@ -323,10 +417,12 @@ impl Diagnostic { /// primary. #[rustc_lint_diagnostics] pub fn span_label(&mut self, span: Span, label: impl Into<SubdiagnosticMessage>) -> &mut Self { - self.span.push_span_label(span, self.subdiagnostic_message_to_diagnostic_message(label)); + let msg = self.subdiagnostic_message_to_diagnostic_message(label); + self.span.push_span_label(span, msg); self - } + } } + with_fn! { with_span_labels, /// Labels all the given spans with the provided label. /// See [`Self::span_label()`] for more information. pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self { @@ -334,7 +430,7 @@ impl Diagnostic { self.span_label(span, label.to_string()); } self - } + } } pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self { let before = self.span.clone(); @@ -412,39 +508,40 @@ impl Diagnostic { self } + with_fn! { with_note, /// Add a note attached to this diagnostic. #[rustc_lint_diagnostics] pub fn note(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { self.sub(Level::Note, msg, MultiSpan::new()); self - } + } } fn highlighted_note(&mut self, msg: Vec<StringPart>) -> &mut Self { self.sub_with_highlights(Level::Note, msg, MultiSpan::new()); self } - /// Prints the span with a note above it. - /// This is like [`Diagnostic::note()`], but it gets its own span. + /// This is like [`DiagnosticBuilder::note()`], but it's only printed once. pub fn note_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { self.sub(Level::OnceNote, msg, MultiSpan::new()); self } + with_fn! { with_span_note, /// Prints the span with a note above it. - /// This is like [`Diagnostic::note()`], but it gets its own span. + /// This is like [`DiagnosticBuilder::note()`], but it gets its own span. #[rustc_lint_diagnostics] - pub fn span_note<S: Into<MultiSpan>>( + pub fn span_note( &mut self, - sp: S, + sp: impl Into<MultiSpan>, msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self { self.sub(Level::Note, msg, sp.into()); self - } + } } /// Prints the span with a note above it. - /// This is like [`Diagnostic::note()`], but it gets its own span. + /// This is like [`DiagnosticBuilder::note_once()`], but it gets its own span. pub fn span_note_once<S: Into<MultiSpan>>( &mut self, sp: S, @@ -454,15 +551,16 @@ impl Diagnostic { self } + with_fn! { with_warn, /// Add a warning attached to this diagnostic. #[rustc_lint_diagnostics] pub fn warn(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { self.sub(Level::Warning, msg, MultiSpan::new()); self - } + } } /// Prints the span with a warning above it. - /// This is like [`Diagnostic::warn()`], but it gets its own span. + /// This is like [`DiagnosticBuilder::warn()`], but it gets its own span. #[rustc_lint_diagnostics] pub fn span_warn<S: Into<MultiSpan>>( &mut self, @@ -473,15 +571,15 @@ impl Diagnostic { self } + with_fn! { with_help, /// Add a help message attached to this diagnostic. #[rustc_lint_diagnostics] pub fn help(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { self.sub(Level::Help, msg, MultiSpan::new()); self - } + } } - /// Prints the span with a help above it. - /// This is like [`Diagnostic::help()`], but it gets its own span. + /// This is like [`DiagnosticBuilder::help()`], but it's only printed once. pub fn help_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { self.sub(Level::OnceHelp, msg, MultiSpan::new()); self @@ -494,7 +592,7 @@ impl Diagnostic { } /// Prints the span with some help above it. - /// This is like [`Diagnostic::help()`], but it gets its own span. + /// This is like [`DiagnosticBuilder::help()`], but it gets its own span. #[rustc_lint_diagnostics] pub fn span_help<S: Into<MultiSpan>>( &mut self, @@ -531,6 +629,7 @@ impl Diagnostic { } } + with_fn! { with_multipart_suggestion, /// Show a suggestion that has multiple parts to it. /// In other words, multiple changes need to be applied as part of this suggestion. pub fn multipart_suggestion( @@ -545,7 +644,7 @@ impl Diagnostic { applicability, SuggestionStyle::ShowCode, ) - } + } } /// Show a suggestion that has multiple parts to it, always as it's own subdiagnostic. /// In other words, multiple changes need to be applied as part of this suggestion. @@ -562,7 +661,8 @@ impl Diagnostic { SuggestionStyle::ShowAlways, ) } - /// [`Diagnostic::multipart_suggestion()`] but you can set the [`SuggestionStyle`]. + + /// [`DiagnosticBuilder::multipart_suggestion()`] but you can set the [`SuggestionStyle`]. pub fn multipart_suggestion_with_style( &mut self, msg: impl Into<SubdiagnosticMessage>, @@ -619,6 +719,7 @@ impl Diagnostic { ) } + with_fn! { with_span_suggestion, /// Prints out a message with a suggested edit of the code. /// /// In case of short messages and a simple suggestion, rustc displays it as a label: @@ -651,9 +752,9 @@ impl Diagnostic { SuggestionStyle::ShowCode, ); self - } + } } - /// [`Diagnostic::span_suggestion()`] but you can set the [`SuggestionStyle`]. + /// [`DiagnosticBuilder::span_suggestion()`] but you can set the [`SuggestionStyle`]. pub fn span_suggestion_with_style( &mut self, sp: Span, @@ -677,6 +778,7 @@ impl Diagnostic { self } + with_fn! { with_span_suggestion_verbose, /// Always show the suggested change. pub fn span_suggestion_verbose( &mut self, @@ -693,10 +795,11 @@ impl Diagnostic { SuggestionStyle::ShowAlways, ); self - } + } } + with_fn! { with_span_suggestions, /// Prints out a message with multiple suggested edits of the code. - /// See also [`Diagnostic::span_suggestion()`]. + /// See also [`DiagnosticBuilder::span_suggestion()`]. pub fn span_suggestions( &mut self, sp: Span, @@ -711,9 +814,8 @@ impl Diagnostic { applicability, SuggestionStyle::ShowCode, ) - } + } } - /// [`Diagnostic::span_suggestions()`] but you can set the [`SuggestionStyle`]. pub fn span_suggestions_with_style( &mut self, sp: Span, @@ -743,7 +845,7 @@ impl Diagnostic { /// Prints out a message with multiple suggested edits of the code, where each edit consists of /// multiple parts. - /// See also [`Diagnostic::multipart_suggestion()`]. + /// See also [`DiagnosticBuilder::multipart_suggestion()`]. pub fn multipart_suggestions( &mut self, msg: impl Into<SubdiagnosticMessage>, @@ -785,6 +887,7 @@ impl Diagnostic { self } + with_fn! { with_span_suggestion_short, /// Prints out a message with a suggested edit of the code. If the suggestion is presented /// inline, it will only show the message and not the suggestion. /// @@ -804,7 +907,7 @@ impl Diagnostic { SuggestionStyle::HideCodeInline, ); self - } + } } /// Prints out a message for a suggestion without showing the suggested code. /// @@ -829,6 +932,7 @@ impl Diagnostic { self } + with_fn! { with_tool_only_span_suggestion, /// Adds a suggestion to the JSON output that will not be shown in the CLI. /// /// This is intended to be used for suggestions that are *very* obvious in what the changes @@ -849,7 +953,7 @@ impl Diagnostic { SuggestionStyle::CompletelyHidden, ); self - } + } } /// Add a subdiagnostic from a type that implements `Subdiagnostic` (see /// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages @@ -868,45 +972,45 @@ impl Diagnostic { self } - pub fn span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self { + with_fn! { with_span, + /// Add a span. + pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self { self.span = sp.into(); if let Some(span) = self.span.primary_span() { self.sort_span = span; } self - } + } } pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self { self.is_lint = Some(IsLint { name, has_future_breakage }); self } + with_fn! { with_code, + /// Add an error code. pub fn code(&mut self, code: ErrCode) -> &mut Self { self.code = Some(code); self - } + } } + with_fn! { with_primary_message, + /// Add a primary message. pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self { self.messages[0] = (msg.into(), Style::NoStyle); self - } - - pub fn args(&self) -> impl Iterator<Item = DiagnosticArg<'_>> { - self.args.iter() - } + } } + with_fn! { with_arg, + /// Add an argument. pub fn arg( &mut self, name: impl Into<DiagnosticArgName>, arg: impl IntoDiagnosticArg, ) -> &mut Self { - self.args.insert(name.into(), arg.into_diagnostic_arg()); + self.deref_mut().arg(name, arg); self - } - - pub fn replace_args(&mut self, args: FxIndexMap<DiagnosticArgName, DiagnosticArgValue>) { - self.args = args; - } + } } /// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by /// combining it with the primary message of the diagnostic (if translatable, otherwise it just @@ -915,9 +1019,7 @@ impl Diagnostic { &self, attr: impl Into<SubdiagnosticMessage>, ) -> DiagnosticMessage { - let msg = - self.messages.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages"); - msg.with_subdiagnostic_message(attr.into()) + self.deref().subdiagnostic_message_to_diagnostic_message(attr) } /// Convenience function for internal use, clients should use one of the @@ -925,15 +1027,7 @@ impl Diagnostic { /// /// Used by `proc_macro_server` for implementing `server::Diagnostic`. pub fn sub(&mut self, level: Level, message: impl Into<SubdiagnosticMessage>, span: MultiSpan) { - let sub = SubDiagnostic { - level, - messages: vec![( - self.subdiagnostic_message_to_diagnostic_message(message), - Style::NoStyle, - )], - span, - }; - self.children.push(sub); + self.deref_mut().sub(level, message, span); } /// Convenience function for internal use, clients should use one of the @@ -946,7 +1040,9 @@ impl Diagnostic { let sub = SubDiagnostic { level, messages, span }; self.children.push(sub); } +} +impl Diagnostic { /// Fields used for Hash, and PartialEq trait fn keys( &self, diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 0572df69ca9..3a6a494af95 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -1,14 +1,8 @@ -use crate::diagnostic::IntoDiagnosticArg; -use crate::{DiagCtxt, Level, MultiSpan, StashKey}; use crate::{ - Diagnostic, DiagnosticMessage, DiagnosticStyledString, ErrCode, ErrorGuaranteed, ExplicitBug, - SubdiagnosticMessage, + DiagCtxt, Diagnostic, DiagnosticMessage, ErrorGuaranteed, ExplicitBug, Level, StashKey, }; -use rustc_lint_defs::Applicability; use rustc_span::source_map::Spanned; - use rustc_span::Span; -use std::borrow::Cow; use std::fmt::{self, Debug}; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; @@ -35,6 +29,11 @@ where } /// Used for emitting structured error messages and other diagnostic information. +/// Wraps a `Diagnostic`, adding some useful things. +/// - The `dcx` field, allowing it to (a) emit itself, and (b) do a drop check +/// that it has been emitted or cancelled. +/// - The `EmissionGuarantee`, which determines the type returned from `emit`. +/// /// Each constructed `DiagnosticBuilder` must be consumed by a function such as /// `emit`, `cancel`, `delay_as_bug`, or `into_diagnostic`. A panic occurrs if a /// `DiagnosticBuilder` is dropped without being consumed by one of these @@ -56,9 +55,11 @@ pub struct DiagnosticBuilder<'a, G: EmissionGuarantee = ErrorGuaranteed> { /// often used as a return value, especially within the frequently-used /// `PResult` type. In theory, return value optimization (RVO) should avoid /// unnecessary copying. In practice, it does not (at the time of writing). - diag: Option<Box<Diagnostic>>, + // FIXME(nnethercote) Make private once this moves to diagnostic.rs. + pub(crate) diag: Option<Box<Diagnostic>>, - _marker: PhantomData<G>, + // FIXME(nnethercote) Make private once this moves to diagnostic.rs. + pub(crate) _marker: PhantomData<G>, } // Cloning a `DiagnosticBuilder` is a recipe for a diagnostic being emitted @@ -88,18 +89,21 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Takes the diagnostic. For use by methods that consume the /// DiagnosticBuilder: `emit`, `cancel`, etc. Afterwards, `drop` is the /// only code that will be run on `self`. - fn take_diag(&mut self) -> Diagnostic { + // FIXME(nnethercote) Make private once this moves to diagnostic.rs. + pub(crate) fn take_diag(&mut self) -> Diagnostic { Box::into_inner(self.diag.take().unwrap()) } /// Most `emit_producing_guarantee` functions use this as a starting point. - fn emit_producing_nothing(mut self) { + // FIXME(nnethercote) Make private once this moves to diagnostic.rs. + pub(crate) fn emit_producing_nothing(mut self) { let diag = self.take_diag(); self.dcx.emit_diagnostic(diag); } /// `ErrorGuaranteed::emit_producing_guarantee` uses this. - fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed { + // FIXME(nnethercote) Make private once this moves to diagnostic.rs. + pub(crate) fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed { let diag = self.take_diag(); // The only error levels that produce `ErrorGuaranteed` are @@ -168,40 +172,6 @@ impl EmissionGuarantee for rustc_span::fatal_error::FatalError { } } -/// `DiagnosticBuilder` impls `DerefMut`, which allows access to the fields and -/// methods of the embedded `Diagnostic`. However, that doesn't allow method -/// chaining at the `DiagnosticBuilder` level. Each use of this macro defines -/// two builder methods at that level, both of which wrap the equivalent method -/// in `Diagnostic`. -/// - A `&mut self -> &mut Self` method, with the same name as the underlying -/// `Diagnostic` method. It is mostly to modify existing diagnostics, either -/// in a standalone fashion, e.g. `err.code(code)`, or in a chained fashion -/// to make multiple modifications, e.g. `err.code(code).span(span)`. -/// - A `self -> Self` method, which has a `with_` prefix added. -/// It is mostly used in a chained fashion when producing a new diagnostic, -/// e.g. `let err = struct_err(msg).with_code(code)`, or when emitting a new -/// diagnostic , e.g. `struct_err(msg).with_code(code).emit()`. -/// -/// Although the latter method can be used to modify an existing diagnostic, -/// e.g. `err = err.with_code(code)`, this should be avoided because the former -/// method gives shorter code, e.g. `err.code(code)`. -macro_rules! forward { - ( - ($f:ident, $with_f:ident)($($name:ident: $ty:ty),* $(,)?) - ) => { - #[doc = concat!("See [`Diagnostic::", stringify!($f), "()`].")] - pub fn $f(&mut self, $($name: $ty),*) -> &mut Self { - self.diag.as_mut().unwrap().$f($($name),*); - self - } - #[doc = concat!("See [`Diagnostic::", stringify!($f), "()`].")] - pub fn $with_f(mut self, $($name: $ty),*) -> Self { - self.diag.as_mut().unwrap().$f($($name),*); - self - } - }; -} - impl<G: EmissionGuarantee> Deref for DiagnosticBuilder<'_, G> { type Target = Diagnostic; @@ -278,135 +248,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { self.downgrade_to_delayed_bug(); self.emit() } - - forward!((span_label, with_span_label)( - span: Span, - label: impl Into<SubdiagnosticMessage>, - )); - forward!((span_labels, with_span_labels)( - spans: impl IntoIterator<Item = Span>, - label: &str, - )); - forward!((note_expected_found, with_note_expected_found)( - expected_label: &dyn fmt::Display, - expected: DiagnosticStyledString, - found_label: &dyn fmt::Display, - found: DiagnosticStyledString, - )); - forward!((note_expected_found_extra, with_note_expected_found_extra)( - expected_label: &dyn fmt::Display, - expected: DiagnosticStyledString, - found_label: &dyn fmt::Display, - found: DiagnosticStyledString, - expected_extra: &dyn fmt::Display, - found_extra: &dyn fmt::Display, - )); - forward!((note, with_note)( - msg: impl Into<SubdiagnosticMessage>, - )); - forward!((note_once, with_note_once)( - msg: impl Into<SubdiagnosticMessage>, - )); - forward!((span_note, with_span_note)( - sp: impl Into<MultiSpan>, - msg: impl Into<SubdiagnosticMessage>, - )); - forward!((span_note_once, with_span_note_once)( - sp: impl Into<MultiSpan>, - msg: impl Into<SubdiagnosticMessage>, - )); - forward!((warn, with_warn)( - msg: impl Into<SubdiagnosticMessage>, - )); - forward!((span_warn, with_span_warn)( - sp: impl Into<MultiSpan>, - msg: impl Into<SubdiagnosticMessage>, - )); - forward!((help, with_help)( - msg: impl Into<SubdiagnosticMessage>, - )); - forward!((help_once, with_help_once)( - msg: impl Into<SubdiagnosticMessage>, - )); - forward!((span_help, with_span_help_once)( - sp: impl Into<MultiSpan>, - msg: impl Into<SubdiagnosticMessage>, - )); - forward!((multipart_suggestion, with_multipart_suggestion)( - msg: impl Into<SubdiagnosticMessage>, - suggestion: Vec<(Span, String)>, - applicability: Applicability, - )); - forward!((multipart_suggestion_verbose, with_multipart_suggestion_verbose)( - msg: impl Into<SubdiagnosticMessage>, - suggestion: Vec<(Span, String)>, - applicability: Applicability, - )); - forward!((tool_only_multipart_suggestion, with_tool_only_multipart_suggestion)( - msg: impl Into<SubdiagnosticMessage>, - suggestion: Vec<(Span, String)>, - applicability: Applicability, - )); - forward!((span_suggestion, with_span_suggestion)( - sp: Span, - msg: impl Into<SubdiagnosticMessage>, - suggestion: impl ToString, - applicability: Applicability, - )); - forward!((span_suggestions, with_span_suggestions)( - sp: Span, - msg: impl Into<SubdiagnosticMessage>, - suggestions: impl IntoIterator<Item = String>, - applicability: Applicability, - )); - forward!((multipart_suggestions, with_multipart_suggestions)( - msg: impl Into<SubdiagnosticMessage>, - suggestions: impl IntoIterator<Item = Vec<(Span, String)>>, - applicability: Applicability, - )); - forward!((span_suggestion_short, with_span_suggestion_short)( - sp: Span, - msg: impl Into<SubdiagnosticMessage>, - suggestion: impl ToString, - applicability: Applicability, - )); - forward!((span_suggestion_verbose, with_span_suggestion_verbose)( - sp: Span, - msg: impl Into<SubdiagnosticMessage>, - suggestion: impl ToString, - applicability: Applicability, - )); - forward!((span_suggestion_hidden, with_span_suggestion_hidden)( - sp: Span, - msg: impl Into<SubdiagnosticMessage>, - suggestion: impl ToString, - applicability: Applicability, - )); - forward!((tool_only_span_suggestion, with_tool_only_span_suggestion)( - sp: Span, - msg: impl Into<SubdiagnosticMessage>, - suggestion: impl ToString, - applicability: Applicability, - )); - forward!((primary_message, with_primary_message)( - msg: impl Into<DiagnosticMessage>, - )); - forward!((span, with_span)( - sp: impl Into<MultiSpan>, - )); - forward!((is_lint, with_is_lint)( - name: String, has_future_breakage: bool, - )); - forward!((code, with_code)( - code: ErrCode, - )); - forward!((arg, with_arg)( - name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg, - )); - forward!((subdiagnostic, with_subdiagnostic)( - dcx: &DiagCtxt, - subdiagnostic: impl crate::AddToDiagnostic, - )); } impl<G: EmissionGuarantee> Debug for DiagnosticBuilder<'_, G> { diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index eaf75539f59..bc1e81642ff 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -299,7 +299,11 @@ pub struct SingleLabelManySpans { pub label: &'static str, } impl AddToDiagnostic for SingleLabelManySpans { - fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut crate::Diagnostic, _: F) { + fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _: F, + ) { diag.span_labels(self.spans, self.label); } } @@ -312,23 +316,6 @@ pub struct ExpectedLifetimeParameter { pub count: usize, } -#[derive(Subdiagnostic)] -#[note(errors_delayed_at_with_newline)] -pub struct DelayedAtWithNewline { - #[primary_span] - pub span: Span, - pub emitted_at: DiagnosticLocation, - pub note: Backtrace, -} -#[derive(Subdiagnostic)] -#[note(errors_delayed_at_without_newline)] -pub struct DelayedAtWithoutNewline { - #[primary_span] - pub span: Span, - pub emitted_at: DiagnosticLocation, - pub note: Backtrace, -} - impl IntoDiagnosticArg for DiagnosticLocation { fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::from(self.to_string())) @@ -341,13 +328,6 @@ impl IntoDiagnosticArg for Backtrace { } } -#[derive(Subdiagnostic)] -#[note(errors_invalid_flushed_delayed_diagnostic_level)] -pub struct InvalidFlushedDelayedDiagnosticLevel { - #[primary_span] - pub span: Span, - pub level: Level, -} impl IntoDiagnosticArg for Level { fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str(Cow::from(self.to_string())) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index e09c041c1d0..df94b69004b 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -599,7 +599,7 @@ impl Emitter for SilentEmitter { fn emit_diagnostic(&mut self, mut diag: Diagnostic) { if diag.level == Level::Fatal { - diag.note(self.fatal_note.clone()); + diag.sub(Level::Note, self.fatal_note.clone(), MultiSpan::new()); self.fatal_dcx.emit_diagnostic(diag); } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 064ea8d7516..73cda64f1cc 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -46,7 +46,7 @@ pub use diagnostic_builder::{ }; pub use diagnostic_impls::{ DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter, - IndicateAnonymousLifetime, InvalidFlushedDelayedDiagnosticLevel, SingleLabelManySpans, + IndicateAnonymousLifetime, SingleLabelManySpans, }; pub use emitter::ColorConfig; pub use rustc_error_messages::{ @@ -62,7 +62,6 @@ pub use snippet::Style; // See https://github.com/rust-lang/rust/pull/115393. pub use termcolor::{Color, ColorSpec, WriteColor}; -use crate::diagnostic_impls::{DelayedAtWithNewline, DelayedAtWithoutNewline}; use emitter::{is_case_difference, DynEmitter, Emitter, HumanEmitter}; use registry::Registry; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; @@ -1395,9 +1394,8 @@ impl DiagCtxtInner { }; diagnostic.children.extract_if(already_emitted_sub).for_each(|_| {}); if already_emitted { - diagnostic.note( - "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`", - ); + let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`"; + diagnostic.sub(Level::Note, msg, MultiSpan::new()); } if is_error { @@ -1483,6 +1481,16 @@ impl DiagCtxtInner { self.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string() } + fn eagerly_translate_for_subdiag( + &self, + diag: &Diagnostic, + msg: impl Into<SubdiagnosticMessage>, + ) -> SubdiagnosticMessage { + let args = diag.args(); + let msg = diag.subdiagnostic_message_to_diagnostic_message(msg); + self.eagerly_translate(msg, args) + } + fn flush_delayed(&mut self) { if self.delayed_bugs.is_empty() { return; @@ -1527,17 +1535,14 @@ impl DiagCtxtInner { if bug.level != DelayedBug { // NOTE(eddyb) not panicking here because we're already producing // an ICE, and the more information the merrier. - let subdiag = InvalidFlushedDelayedDiagnosticLevel { - span: bug.span.primary_span().unwrap(), - level: bug.level, - }; - // FIXME: Cannot use `Diagnostic::subdiagnostic` which takes `DiagCtxt`, but it - // just uses `DiagCtxtInner` functions. - subdiag.add_to_diagnostic_with(&mut bug, |diag, msg| { - let args = diag.args(); - let msg = diag.subdiagnostic_message_to_diagnostic_message(msg); - self.eagerly_translate(msg, args) - }); + // + // We are at the `Diagnostic`/`DiagCtxtInner` level rather than + // the usual `DiagnosticBuilder`/`DiagCtxt` level, so we must + // augment `bug` in a lower-level fashion. + bug.arg("level", bug.level); + let msg = crate::fluent_generated::errors_invalid_flushed_delayed_diagnostic_level; + let msg = self.eagerly_translate_for_subdiag(&bug, msg); // after the `arg` call + bug.sub(Level::Note, msg, bug.span.primary_span().unwrap().into()); } bug.level = Bug; @@ -1571,39 +1576,22 @@ impl DelayedDiagnostic { DelayedDiagnostic { inner: diagnostic, note: backtrace } } - fn decorate(mut self, dcx: &DiagCtxtInner) -> Diagnostic { - // FIXME: Cannot use `Diagnostic::subdiagnostic` which takes `DiagCtxt`, but it - // just uses `DiagCtxtInner` functions. - let subdiag_with = |diag: &mut Diagnostic, msg| { - let args = diag.args(); - let msg = diag.subdiagnostic_message_to_diagnostic_message(msg); - dcx.eagerly_translate(msg, args) - }; - - match self.note.status() { - BacktraceStatus::Captured => { - let inner = &self.inner; - let subdiag = DelayedAtWithNewline { - span: inner.span.primary_span().unwrap_or(DUMMY_SP), - emitted_at: inner.emitted_at.clone(), - note: self.note, - }; - subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with); - } + fn decorate(self, dcx: &DiagCtxtInner) -> Diagnostic { + // We are at the `Diagnostic`/`DiagCtxtInner` level rather than the + // usual `DiagnosticBuilder`/`DiagCtxt` level, so we must construct + // `diag` in a lower-level fashion. + let mut diag = self.inner; + let msg = match self.note.status() { + BacktraceStatus::Captured => crate::fluent_generated::errors_delayed_at_with_newline, // Avoid the needless newline when no backtrace has been captured, // the display impl should just be a single line. - _ => { - let inner = &self.inner; - let subdiag = DelayedAtWithoutNewline { - span: inner.span.primary_span().unwrap_or(DUMMY_SP), - emitted_at: inner.emitted_at.clone(), - note: self.note, - }; - subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with); - } - } - - self.inner + _ => crate::fluent_generated::errors_delayed_at_without_newline, + }; + diag.arg("emitted_at", diag.emitted_at.clone()); + diag.arg("note", self.note); + let msg = dcx.eagerly_translate_for_subdiag(&diag, msg); // after the `arg` calls + diag.sub(Level::Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into()); + diag } } @@ -1745,9 +1733,9 @@ impl Level { } // FIXME(eddyb) this doesn't belong here AFAICT, should be moved to callsite. -pub fn add_elided_lifetime_in_path_suggestion<E: EmissionGuarantee>( +pub fn add_elided_lifetime_in_path_suggestion<G: EmissionGuarantee>( source_map: &SourceMap, - diag: &mut DiagnosticBuilder<'_, E>, + diag: &mut DiagnosticBuilder<'_, G>, n: usize, path_span: Span, incl_angl_brckt: bool, |
