From f6f87798439e2ce7861da761b444fe0978335ed9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 6 Feb 2024 16:44:30 +1100 Subject: [PATCH] Reduce capabilities of `Diagnostic`. Currently many diagnostic modifier methods are available on both `Diagnostic` and `DiagnosticBuilder`. This commit removes most of them from `Diagnostic`. To minimize the diff size, it keeps them within `diagnostic.rs` but changes the surrounding `impl Diagnostic` block to `impl DiagnosticBuilder`. (I intend to move things around later, to give a more sensible code layout.) `Diagnostic` keeps a few methods that it still needs, like `sub`, `arg`, and `replace_args`. The `forward!` macro, which defined two additional methods per call (e.g. `note` and `with_note`), is replaced by the `with_fn!` macro, which defines one additional method per call (e.g. `with_note`). It's now also only used when necessary -- not all modifier methods currently need a `with_*` form. (New ones can be easily added as necessary.) All this also requires changing `trait AddToDiagnostic` so its methods take `DiagnosticBuilder` instead of `Diagnostic`, which leads to many mechanical changes. `SubdiagnosticMessageOp` gains a type parameter `G`. There are three subdiagnostics -- `DelayedAtWithoutNewline`, `DelayedAtWithNewline`, and `InvalidFlushedDelayedDiagnosticLevel` -- that are created within the diagnostics machinery and appended to external diagnostics. These are handled at the `Diagnostic` level, which means it's now hard to construct them via `derive(Diagnostic)`, so instead we construct them by hand. This has no effect on what they look like when printed. There are lots of new `allow` markers for `untranslatable_diagnostics` and `diagnostics_outside_of_impl`. This is because `#[rustc_lint_diagnostics]` annotations were present on the `Diagnostic` modifier methods, but missing from the `DiagnosticBuilder` modifier methods. They're now present. --- compiler/rustc_ast_lowering/src/errors.rs | 9 +- compiler/rustc_ast_passes/src/errors.rs | 17 +- compiler/rustc_ast_passes/src/feature_gate.rs | 3 + .../src/diagnostics/region_errors.rs | 15 ++ compiler/rustc_borrowck/src/lib.rs | 2 + compiler/rustc_builtin_macros/src/errors.rs | 10 +- compiler/rustc_codegen_ssa/src/back/write.rs | 4 +- .../src/transform/check_consts/ops.rs | 7 + compiler/rustc_errors/src/diagnostic.rs | 212 +++++++++++++----- .../rustc_errors/src/diagnostic_builder.rs | 191 ++-------------- compiler/rustc_errors/src/diagnostic_impls.rs | 30 +-- compiler/rustc_errors/src/emitter.rs | 2 +- compiler/rustc_errors/src/lib.rs | 82 +++---- compiler/rustc_expand/src/base.rs | 2 + compiler/rustc_expand/src/config.rs | 1 + .../rustc_expand/src/proc_macro_server.rs | 9 +- compiler/rustc_hir_typeck/src/errors.rs | 24 +- compiler/rustc_infer/src/errors/mod.rs | 59 ++++- .../src/errors/note_and_explain.rs | 11 +- .../rustc_lint/src/context/diagnostics.rs | 3 + compiler/rustc_lint/src/errors.rs | 10 +- compiler/rustc_lint/src/levels.rs | 3 + compiler/rustc_lint/src/lints.rs | 66 ++++-- .../src/diagnostics/subdiagnostic.rs | 10 +- compiler/rustc_metadata/src/errors.rs | 4 + compiler/rustc_mir_build/src/errors.rs | 14 +- compiler/rustc_mir_transform/src/errors.rs | 3 + compiler/rustc_monomorphize/src/errors.rs | 1 + compiler/rustc_parse/src/errors.rs | 8 +- compiler/rustc_passes/src/check_const.rs | 9 +- compiler/rustc_passes/src/errors.rs | 11 +- compiler/rustc_pattern_analysis/src/errors.rs | 8 +- compiler/rustc_session/src/config.rs | 3 + compiler/rustc_trait_selection/src/errors.rs | 10 +- src/tools/clippy/clippy_utils/src/sugg.rs | 4 +- .../ui-fulldeps/internal-lints/diagnostics.rs | 13 +- .../internal-lints/diagnostics.stderr | 8 +- ...diagnostic-derive-doc-comment-field.stderr | 9 +- .../session-diagnostic/diagnostic-derive.rs | 4 +- .../diagnostic-derive.stderr | 6 +- 40 files changed, 502 insertions(+), 395 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 274e6b7458c61..834409da6750a 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -1,5 +1,6 @@ use rustc_errors::{ - codes::*, AddToDiagnostic, Diagnostic, DiagnosticArgFromDisplay, SubdiagnosticMessageOp, + codes::*, AddToDiagnostic, DiagnosticArgFromDisplay, DiagnosticBuilder, EmissionGuarantee, + SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -41,7 +42,11 @@ pub struct InvalidAbi { pub struct InvalidAbiReason(pub &'static str); impl AddToDiagnostic for InvalidAbiReason { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _: F, + ) { #[allow(rustc::untranslatable_diagnostic)] diag.note(self.0); } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 9662c73ca8532..e5153c8979039 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -1,7 +1,10 @@ //! Errors emitted by ast_passes. use rustc_ast::ParamKindOrd; -use rustc_errors::{codes::*, AddToDiagnostic, Applicability, Diagnostic, SubdiagnosticMessageOp}; +use rustc_errors::{ + codes::*, AddToDiagnostic, Applicability, DiagnosticBuilder, EmissionGuarantee, + SubdiagnosticMessageOp, +}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -372,7 +375,11 @@ pub struct EmptyLabelManySpans(pub Vec); // The derive for `Vec` does multiple calls to `span_label`, adding commas between each impl AddToDiagnostic for EmptyLabelManySpans { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _: F, + ) { diag.span_labels(self.0, ""); } } @@ -729,7 +736,11 @@ pub struct StableFeature { } impl AddToDiagnostic for StableFeature { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _: F, + ) { diag.arg("name", self.name); diag.arg("since", self.since); diag.help(fluent::ast_passes_stable_since); diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 409aef9185d92..1b0dd9acc3782 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -22,6 +22,9 @@ macro_rules! gate { }}; ($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{ if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) { + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] feature_err(&$visitor.sess, sym::$feature, $span, $explain).with_help($help).emit(); } }}; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 1b88d5046d94e..50d22881c3e61 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -251,6 +251,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { hrtb_bounds.iter().for_each(|bound| { let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else { return; }; + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] diag.span_note( *trait_span, "due to current limitations in the borrow checker, this implies a `'static` lifetime" @@ -421,6 +424,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// ``` /// /// Here we would be invoked with `fr = 'a` and `outlived_fr = 'b`. + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] pub(crate) fn report_region_error( &mut self, fr: RegionVid, @@ -685,12 +691,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { borrowck_errors::borrowed_data_escapes_closure(self.infcx.tcx, *span, escapes_from); if let Some((Some(outlived_fr_name), outlived_fr_span)) = outlived_fr_name_and_span { + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] diag.span_label( outlived_fr_span, format!("`{outlived_fr_name}` declared here, outside of the {escapes_from} body",), ); } + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] if let Some((Some(fr_name), fr_span)) = fr_name_and_span { diag.span_label( fr_span, @@ -714,6 +726,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let outlived_fr_region_name = self.give_region_a_name(errci.outlived_fr).unwrap(); outlived_fr_region_name.highlight_region_name(&mut diag); + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] diag.span_label( *span, format!( diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 6c2a511538d51..dbaa9e5bcfab0 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2497,6 +2497,8 @@ mod diags { } for (_, (mut diag, count)) in std::mem::take(&mut self.diags.buffered_mut_errors) { if count > 10 { + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] diag.note(format!("...and {} other attempted mutable borrows", count - 10)); } self.diags.buffered_diags.push(BufferedDiag::Error(diag)); diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 8d2e06bf30dac..f304a37be854b 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ - codes::*, AddToDiagnostic, DiagCtxt, Diagnostic, DiagnosticBuilder, EmissionGuarantee, - IntoDiagnostic, Level, MultiSpan, SingleLabelManySpans, SubdiagnosticMessageOp, + codes::*, AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + Level, MultiSpan, SingleLabelManySpans, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -611,7 +611,11 @@ pub(crate) struct FormatUnusedArg { // Allow the singular form to be a subdiagnostic of the multiple-unused // form of diagnostic. impl AddToDiagnostic for FormatUnusedArg { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + f: F, + ) { diag.arg("named", self.named); let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into()); diag.span_label(self.span, msg); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 24fdd01350926..7a981217b525f 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1856,9 +1856,7 @@ impl SharedEmitterMain { Ok(SharedEmitterMessage::Diagnostic(diag)) => { let dcx = sess.dcx(); let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msgs); - if let Some(code) = diag.code { - d.code(code); - } + d.code = diag.code; // may be `None`, that's ok d.replace_args(diag.args); dcx.emit_diagnostic(d); } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 25ddd5e85f9f3..5b4bbf8510b60 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -93,6 +93,9 @@ pub struct FnCallNonConst<'tcx> { } impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> DiagnosticBuilder<'tcx> { let FnCallNonConst { caller, callee, args, span, call_source, feature } = *self; let ConstCx { tcx, param_env, .. } = *ccx; @@ -321,6 +324,8 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable { .dcx() .create_err(errors::UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) }); + // FIXME: make this translatable + #[allow(rustc::untranslatable_diagnostic)] if ccx.is_const_stable_const_fn() { err.help("const-stable functions can only call other const-stable functions"); } else if ccx.tcx.sess.is_nightly_build() { @@ -591,6 +596,8 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess { span, format!("referencing statics in {}s is unstable", ccx.const_kind(),), ); + // FIXME: make this translatable + #[allow(rustc::untranslatable_diagnostic)] err .note("`static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable.") .help("to fix this, the value can be extracted to a `const` and then used."); diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 034636bea4818..57610635ee69c 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(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(self, diag: &mut Diagnostic, f: F); + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + f: F, + ); } -pub trait SubdiagnosticMessageOp = - Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage; +pub trait SubdiagnosticMessageOp = + 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, + ) -> 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, + 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, arg: impl IntoDiagnosticArg) { + self.args.insert(name.into(), arg.into_diagnostic_arg()); + } + + pub fn args(&self) -> impl Iterator> { + self.args.iter() + } + + pub fn replace_args(&mut self, args: FxIndexMap) { + 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) -> &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, 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) -> &mut Self { self.sub(Level::Note, msg, MultiSpan::new()); self - } + } } fn highlighted_note(&mut self, msg: Vec) -> &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) -> &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>( + pub fn span_note( &mut self, - sp: S, + sp: impl Into, msg: impl Into, ) -> &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>( &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) -> &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>( &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) -> &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) -> &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>( &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, @@ -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, @@ -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>(&mut self, sp: S) -> &mut Self { + with_fn! { with_span, + /// Add a span. + pub fn span(&mut self, sp: impl Into) -> &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) -> &mut Self { self.messages[0] = (msg.into(), Style::NoStyle); self - } - - pub fn args(&self) -> impl Iterator> { - self.args.iter() - } + } } + with_fn! { with_arg, + /// Add an argument. pub fn arg( &mut self, name: impl Into, 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) { - 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, ) -> 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, 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 0572df69ca947..3a6a494af95b9 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>, + // FIXME(nnethercote) Make private once this moves to diagnostic.rs. + pub(crate) diag: Option>, - _marker: PhantomData, + // FIXME(nnethercote) Make private once this moves to diagnostic.rs. + pub(crate) _marker: PhantomData, } // 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 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, - )); - forward!((span_labels, with_span_labels)( - spans: impl IntoIterator, - 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, - )); - forward!((note_once, with_note_once)( - msg: impl Into, - )); - forward!((span_note, with_span_note)( - sp: impl Into, - msg: impl Into, - )); - forward!((span_note_once, with_span_note_once)( - sp: impl Into, - msg: impl Into, - )); - forward!((warn, with_warn)( - msg: impl Into, - )); - forward!((span_warn, with_span_warn)( - sp: impl Into, - msg: impl Into, - )); - forward!((help, with_help)( - msg: impl Into, - )); - forward!((help_once, with_help_once)( - msg: impl Into, - )); - forward!((span_help, with_span_help_once)( - sp: impl Into, - msg: impl Into, - )); - forward!((multipart_suggestion, with_multipart_suggestion)( - msg: impl Into, - suggestion: Vec<(Span, String)>, - applicability: Applicability, - )); - forward!((multipart_suggestion_verbose, with_multipart_suggestion_verbose)( - msg: impl Into, - suggestion: Vec<(Span, String)>, - applicability: Applicability, - )); - forward!((tool_only_multipart_suggestion, with_tool_only_multipart_suggestion)( - msg: impl Into, - suggestion: Vec<(Span, String)>, - applicability: Applicability, - )); - forward!((span_suggestion, with_span_suggestion)( - sp: Span, - msg: impl Into, - suggestion: impl ToString, - applicability: Applicability, - )); - forward!((span_suggestions, with_span_suggestions)( - sp: Span, - msg: impl Into, - suggestions: impl IntoIterator, - applicability: Applicability, - )); - forward!((multipart_suggestions, with_multipart_suggestions)( - msg: impl Into, - suggestions: impl IntoIterator>, - applicability: Applicability, - )); - forward!((span_suggestion_short, with_span_suggestion_short)( - sp: Span, - msg: impl Into, - suggestion: impl ToString, - applicability: Applicability, - )); - forward!((span_suggestion_verbose, with_span_suggestion_verbose)( - sp: Span, - msg: impl Into, - suggestion: impl ToString, - applicability: Applicability, - )); - forward!((span_suggestion_hidden, with_span_suggestion_hidden)( - sp: Span, - msg: impl Into, - suggestion: impl ToString, - applicability: Applicability, - )); - forward!((tool_only_span_suggestion, with_tool_only_span_suggestion)( - sp: Span, - msg: impl Into, - suggestion: impl ToString, - applicability: Applicability, - )); - forward!((primary_message, with_primary_message)( - msg: impl Into, - )); - forward!((span, with_span)( - sp: impl Into, - )); - 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>, arg: impl IntoDiagnosticArg, - )); - forward!((subdiagnostic, with_subdiagnostic)( - dcx: &DiagCtxt, - subdiagnostic: impl crate::AddToDiagnostic, - )); } impl Debug for DiagnosticBuilder<'_, G> { diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index eaf75539f59b9..bc1e81642ff26 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(self, diag: &mut crate::Diagnostic, _: F) { + fn add_to_diagnostic_with>( + 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 e09c041c1d063..df94b69004b74 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 8643596b446c0..73cda64f1cc6a 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 { + 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 } } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 0914452365856..3226362ad10d6 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1176,6 +1176,8 @@ impl<'a> ExtCtxt<'a> { for (span, notes) in self.expansions.iter() { let mut db = self.dcx().create_note(errors::TraceMacro { span: *span }); for note in notes { + // FIXME: make this translatable + #[allow(rustc::untranslatable_diagnostic)] db.note(note.clone()); } db.emit(); diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 781186764fa32..435135d195989 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -384,6 +384,7 @@ impl<'a> StripUnconfigured<'a> { ); if attr.is_doc_comment() { + #[allow(rustc::untranslatable_diagnostic)] err.help("`///` is for documentation comments. For a plain comment, use `//`."); } diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 8f31b5801da7f..b80ecbc9c659c 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -10,7 +10,7 @@ use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_errors::{ErrorGuaranteed, MultiSpan, PResult}; +use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, MultiSpan, PResult}; use rustc_parse::lexer::nfc_normalize; use rustc_parse::parse_stream_from_source_str; use rustc_session::parse::ParseSess; @@ -509,13 +509,14 @@ impl server::FreeFunctions for Rustc<'_, '_> { } fn emit_diagnostic(&mut self, diagnostic: Diagnostic) { - let mut diag = - rustc_errors::Diagnostic::new(diagnostic.level.to_internal(), diagnostic.message); + let message = rustc_errors::DiagnosticMessage::from(diagnostic.message); + let mut diag: DiagnosticBuilder<'_, rustc_errors::ErrorGuaranteed> = + DiagnosticBuilder::new(&self.sess().dcx, diagnostic.level.to_internal(), message); diag.span(MultiSpan::from_spans(diagnostic.spans)); for child in diagnostic.children { diag.sub(child.level.to_internal(), child.message, MultiSpan::from_spans(child.spans)); } - self.sess().dcx.emit_diagnostic(diag); + diag.emit(); } } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 1af0b75bd23c0..f609d0f7e8f5d 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -3,8 +3,8 @@ use std::borrow::Cow; use crate::fluent_generated as fluent; use rustc_errors::{ - codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg, - MultiSpan, SubdiagnosticMessageOp, + codes::*, AddToDiagnostic, Applicability, DiagnosticArgValue, DiagnosticBuilder, + EmissionGuarantee, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; @@ -195,7 +195,11 @@ pub struct TypeMismatchFruTypo { } impl AddToDiagnostic for TypeMismatchFruTypo { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { diag.arg("expr", self.expr.as_deref().unwrap_or("NONE")); // Only explain that `a ..b` is a range if it's split up @@ -370,7 +374,11 @@ pub struct RemoveSemiForCoerce { } impl AddToDiagnostic for RemoveSemiForCoerce { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { let mut multispan: MultiSpan = self.semi.into(); multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr); multispan.push_span_label(self.ret, fluent::hir_typeck_remove_semi_for_coerce_ret); @@ -541,8 +549,12 @@ pub enum CastUnknownPointerSub { From(Span), } -impl AddToDiagnostic for CastUnknownPointerSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { +impl rustc_errors::AddToDiagnostic for CastUnknownPointerSub { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + f: F, + ) { match self { CastUnknownPointerSub::To(span) => { let msg = f(diag, crate::fluent_generated::hir_typeck_label_to); diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 8bfc05d6a96db..f29ba70be9838 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -1,7 +1,8 @@ use hir::GenericParamKind; use rustc_errors::{ - codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, - DiagnosticStyledString, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessageOp, + codes::*, AddToDiagnostic, Applicability, DiagnosticBuilder, DiagnosticMessage, + DiagnosticStyledString, EmissionGuarantee, IntoDiagnosticArg, MultiSpan, + SubdiagnosticMessageOp, }; use rustc_hir as hir; use rustc_hir::FnRetTy; @@ -225,7 +226,11 @@ pub enum RegionOriginNote<'a> { } impl AddToDiagnostic for RegionOriginNote<'_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { let mut label_or_note = |span, msg: DiagnosticMessage| { let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); @@ -286,7 +291,11 @@ pub enum LifetimeMismatchLabels { } impl AddToDiagnostic for LifetimeMismatchLabels { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { match self { LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { diag.span_label(param_span, fluent::infer_declared_different); @@ -330,7 +339,11 @@ pub struct AddLifetimeParamsSuggestion<'a> { } impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { let mut mk_suggestion = || { let ( hir::Ty { kind: hir::TyKind::Ref(lifetime_sub, _), .. }, @@ -428,7 +441,11 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq { } impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { - fn add_to_diagnostic_with(mut self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + mut self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { self.unmet_requirements .push_span_label(self.binding_span, fluent::infer_msl_introduces_static); diag.span_note(self.unmet_requirements, fluent::infer_msl_unmet_req); @@ -743,7 +760,11 @@ pub struct ConsiderBorrowingParamHelp { } impl AddToDiagnostic for ConsiderBorrowingParamHelp { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + f: F, + ) { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { // Seems like we can't call f() here as Into is required @@ -784,7 +805,11 @@ pub struct DynTraitConstraintSuggestion { } impl AddToDiagnostic for DynTraitConstraintSuggestion { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + f: F, + ) { let mut multi_span: MultiSpan = vec![self.span].into(); multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label); multi_span.push_span_label(self.ident.span, fluent::infer_dtcs_introduces_requirement); @@ -827,7 +852,11 @@ pub struct ReqIntroducedLocations { } impl AddToDiagnostic for ReqIntroducedLocations { - fn add_to_diagnostic_with(mut self, diag: &mut Diagnostic, f: F) { + fn add_to_diagnostic_with>( + mut self, + diag: &mut DiagnosticBuilder<'_, G>, + f: F, + ) { for sp in self.spans { self.span.push_span_label(sp, fluent::infer_ril_introduced_here); } @@ -846,7 +875,11 @@ pub struct MoreTargeted { } impl AddToDiagnostic for MoreTargeted { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _f: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { diag.code(E0772); diag.primary_message(fluent::infer_more_targeted); diag.arg("ident", self.ident); @@ -1265,7 +1298,11 @@ pub struct SuggestTuplePatternMany { } impl AddToDiagnostic for SuggestTuplePatternMany { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + f: F, + ) { diag.arg("path", self.path); let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into()); diag.multipart_suggestions( diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index a59a4df77296d..c272aa63b08ea 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -1,6 +1,9 @@ use crate::fluent_generated as fluent; use crate::infer::error_reporting::nice_region_error::find_anon_type; -use rustc_errors::{AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessageOp}; +use rustc_errors::{ + AddToDiagnostic, DiagnosticBuilder, EmissionGuarantee, IntoDiagnosticArg, + SubdiagnosticMessageOp, +}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{symbol::kw, Span}; @@ -160,7 +163,11 @@ impl RegionExplanation<'_> { } impl AddToDiagnostic for RegionExplanation<'_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + f: F, + ) { diag.arg("pref_kind", self.prefix); diag.arg("suff_kind", self.suffix); diag.arg("desc_kind", self.desc.kind); diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 5af2b6daec185..86434002e2c66 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -1,3 +1,6 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; use rustc_errors::{add_elided_lifetime_in_path_suggestion, DiagnosticBuilder}; use rustc_errors::{Applicability, SuggestionStyle}; diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 21d4b6fa65b5b..bcff20fc26043 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -1,5 +1,7 @@ use crate::fluent_generated as fluent; -use rustc_errors::{codes::*, AddToDiagnostic, Diagnostic, SubdiagnosticMessageOp}; +use rustc_errors::{ + codes::*, AddToDiagnostic, DiagnosticBuilder, EmissionGuarantee, SubdiagnosticMessageOp, +}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::lint::Level; use rustc_span::{Span, Symbol}; @@ -24,7 +26,11 @@ pub enum OverruledAttributeSub { } impl AddToDiagnostic for OverruledAttributeSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { match self { OverruledAttributeSub::DefaultSource { id } => { diag.note(fluent::lint_default_source); diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 40fb12b21070b..c1a083bde8d4d 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -1062,6 +1062,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if self.lint_added_lints { let lint = builtin::UNKNOWN_LINTS; let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS); + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] lint_level( self.sess, lint, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index c204c67fc1f7c..e4a7eb1d9531d 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -5,8 +5,8 @@ use std::num::NonZero; use crate::errors::RequestedLevel; use crate::fluent_generated as fluent; use rustc_errors::{ - codes::*, AddToDiagnostic, Applicability, DecorateLint, Diagnostic, DiagnosticBuilder, - DiagnosticMessage, DiagnosticStyledString, SubdiagnosticMessageOp, SuggestionStyle, + codes::*, AddToDiagnostic, Applicability, DecorateLint, DiagnosticBuilder, DiagnosticMessage, + DiagnosticStyledString, EmissionGuarantee, SubdiagnosticMessageOp, SuggestionStyle, }; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; @@ -267,17 +267,21 @@ pub struct SuggestChangingAssocTypes<'a, 'b> { pub ty: &'a rustc_hir::Ty<'b>, } -impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { +impl<'a, 'b> AddToDiagnostic for SuggestChangingAssocTypes<'a, 'b> { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { // Access to associates types should use `::Assoc`, which does not need a // bound. Let's see if this type does that. // We use a HIR visitor to walk the type. use rustc_hir::intravisit::{self, Visitor}; - struct WalkAssocTypes<'a> { - err: &'a mut Diagnostic, + struct WalkAssocTypes<'a, 'b, G: EmissionGuarantee> { + err: &'a mut DiagnosticBuilder<'b, G>, } - impl Visitor<'_> for WalkAssocTypes<'_> { + impl<'a, 'b, G: EmissionGuarantee> Visitor<'_> for WalkAssocTypes<'a, 'b, G> { fn visit_qpath( &mut self, qpath: &rustc_hir::QPath<'_>, @@ -320,7 +324,11 @@ pub struct BuiltinTypeAliasGenericBoundsSuggestion { } impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { diag.multipart_suggestion( fluent::lint_suggestion, self.suggestions, @@ -437,7 +445,11 @@ pub struct BuiltinUnpermittedTypeInitSub { } impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { let mut err = self.err; loop { if let Some(span) = err.span { @@ -488,7 +500,11 @@ pub struct BuiltinClashingExternSub<'a> { } impl AddToDiagnostic for BuiltinClashingExternSub<'_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { let mut expected_str = DiagnosticStyledString::new(); expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); let mut found_str = DiagnosticStyledString::new(); @@ -766,7 +782,11 @@ pub struct HiddenUnicodeCodepointsDiagLabels { } impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { for (c, span) in self.spans { diag.span_label(span, format!("{c:?}")); } @@ -780,7 +800,11 @@ pub enum HiddenUnicodeCodepointsDiagSub { // Used because of multiple multipart_suggestion and note impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { match self { HiddenUnicodeCodepointsDiagSub::Escape { spans } => { diag.multipart_suggestion_with_style( @@ -928,7 +952,11 @@ pub struct NonBindingLetSub { } impl AddToDiagnostic for NonBindingLetSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar; if can_suggest_binding { @@ -1208,7 +1236,11 @@ pub enum NonSnakeCaseDiagSub { } impl AddToDiagnostic for NonSnakeCaseDiagSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { match self { NonSnakeCaseDiagSub::Label { span } => { diag.span_label(span, fluent::lint_label); @@ -1401,7 +1433,11 @@ pub enum OverflowingBinHexSign { } impl AddToDiagnostic for OverflowingBinHexSign { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { match self { OverflowingBinHexSign::Positive => { diag.note(fluent::lint_positive_note); diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 3a5f289559e6a..323614c222f2e 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -87,9 +87,13 @@ impl SubdiagnosticDeriveBuilder { let f = &self.f; let ret = structure.gen_impl(quote! { gen impl rustc_errors::AddToDiagnostic for @Self { - fn add_to_diagnostic_with<__F>(self, #diag: &mut rustc_errors::Diagnostic, #f: __F) - where - __F: rustc_errors::SubdiagnosticMessageOp, + fn add_to_diagnostic_with<__G, __F>( + self, + #diag: &mut rustc_errors::DiagnosticBuilder<'_, __G>, + #f: __F + ) where + __G: rustc_errors::EmissionGuarantee, + __F: rustc_errors::SubdiagnosticMessageOp<__G>, { #implementation } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index d17bf0cf708f6..7e0a4fb72d45c 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -505,6 +505,8 @@ impl IntoDiagnostic<'_, G> for MultipleCandidates { diag.code(E0464); diag.span(self.span); for (i, candidate) in self.candidates.iter().enumerate() { + // FIXME: make this translatable + #[allow(rustc::untranslatable_diagnostic)] diag.note(format!("candidate #{}: {}", i + 1, candidate.display())); } diag @@ -601,6 +603,8 @@ impl IntoDiagnostic<'_, G> for InvalidMetadataFiles { diag.code(E0786); diag.span(self.span); for crate_rejection in self.crate_rejections { + // FIXME: make this translatable + #[allow(rustc::untranslatable_diagnostic)] diag.note(crate_rejection); } diag diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 0bc5fe6ef89ac..2a42dae289b11 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1,7 +1,7 @@ use crate::fluent_generated as fluent; use rustc_errors::DiagnosticArgValue; use rustc_errors::{ - codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, + codes::*, AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -420,7 +420,11 @@ pub struct UnsafeNotInheritedLintNote { } impl AddToDiagnostic for UnsafeNotInheritedLintNote { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body); let body_start = self.body_span.shrink_to_lo(); let body_end = self.body_span.shrink_to_hi(); @@ -863,7 +867,11 @@ pub struct Variant { } impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { diag.arg("ty", self.ty); let mut spans = MultiSpan::from(self.adt_def_span); diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index ff4918df9a262..af2d7d4946fc7 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -87,6 +87,9 @@ pub(crate) struct RequiresUnsafeDetail { } impl RequiresUnsafeDetail { + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] fn add_subdiagnostics(&self, diag: &mut DiagnosticBuilder<'_, G>) { use UnsafetyViolationDetails::*; match self.violation { diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index bd89874b5cc48..e4c306791462d 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -56,6 +56,7 @@ impl IntoDiagnostic<'_, G> for UnusedGenericParamsHint { // FIXME: I can figure out how to do a label with a fluent string with a fixed message, // or a label with a dynamic value in a hard-coded string, but I haven't figured out // how to combine the two. 😢 + #[allow(rustc::untranslatable_diagnostic)] diag.span_label(span, format!("generic parameter `{name}` is unused")); } diag diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 674f7218ea6d0..fde67ac089aa3 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use rustc_ast::token::Token; use rustc_ast::{Path, Visibility}; use rustc_errors::{ - codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, + codes::*, AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; @@ -1475,7 +1475,11 @@ pub(crate) struct FnTraitMissingParen { } impl AddToDiagnostic for FnTraitMissingParen { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _: F, + ) { diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren); let applicability = if self.machine_applicable { Applicability::MachineApplicable diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 3676eb92a3f7d..02792491f5ed0 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -156,9 +156,12 @@ impl<'tcx> CheckConstVisitor<'tcx> { // is a pretty narrow case, however. if tcx.sess.is_nightly_build() { for gate in missing_secondary { - let note = - format!("add `#![feature({gate})]` to the crate attributes to enable",); - err.help(note); + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] + err.help(format!( + "add `#![feature({gate})]` to the crate attributes to enable" + )); } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index a732bdbca5115..982def54d3077 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -6,9 +6,8 @@ use std::{ use crate::fluent_generated as fluent; use rustc_ast::Label; use rustc_errors::{ - codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, - DiagnosticSymbolList, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan, - SubdiagnosticMessageOp, + codes::*, AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, DiagnosticSymbolList, + EmissionGuarantee, IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessageOp, }; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -1754,7 +1753,11 @@ pub struct UnusedVariableStringInterp { } impl AddToDiagnostic for UnusedVariableStringInterp { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation); diag.multipart_suggestion( crate::fluent_generated::passes_string_interpolation_only_works, diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs index 2dffdc9846c22..27619b74a665b 100644 --- a/compiler/rustc_pattern_analysis/src/errors.rs +++ b/compiler/rustc_pattern_analysis/src/errors.rs @@ -1,4 +1,4 @@ -use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessageOp}; +use rustc_errors::{AddToDiagnostic, DiagnosticBuilder, EmissionGuarantee, SubdiagnosticMessageOp}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::thir::Pat; use rustc_middle::ty::Ty; @@ -62,7 +62,11 @@ pub struct Overlap<'tcx> { } impl<'tcx> AddToDiagnostic for Overlap<'tcx> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _: F, + ) { let Overlap { span, range } = self; // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]` diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index ef0512bf6862c..0a330da87b0cd 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2468,6 +2468,9 @@ pub fn parse_externs( )); let adjusted_name = name.replace('-', "_"); if is_ascii_ident(&adjusted_name) { + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] error.help(format!( "consider replacing the dashes with underscores: `{adjusted_name}`" )); diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 407fff03e1588..10911c0d002b8 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1,7 +1,7 @@ use crate::fluent_generated as fluent; use rustc_errors::{ - codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, - EmissionGuarantee, IntoDiagnostic, Level, SubdiagnosticMessageOp, + codes::*, AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, + IntoDiagnostic, Level, SubdiagnosticMessageOp, }; use rustc_macros::Diagnostic; use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty}; @@ -102,7 +102,11 @@ pub enum AdjustSignatureBorrow { } impl AddToDiagnostic for AdjustSignatureBorrow { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + _f: F, + ) { match self { AdjustSignatureBorrow::Borrow { to_borrow } => { diag.arg("len", to_borrow.len()); diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index c86362c427ce2..b355e66b7b12a 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -683,7 +683,7 @@ fn indentation(cx: &T, span: Span) -> Option { }) } -/// Convenience extension trait for `Diagnostic`. +/// Convenience extension trait for `DiagnosticBuilder`. pub trait DiagnosticExt { /// Suggests to add an attribute to an item. /// @@ -731,7 +731,7 @@ pub trait DiagnosticExt { fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability); } -impl DiagnosticExt for rustc_errors::Diagnostic { +impl DiagnosticExt for rustc_errors::DiagnosticBuilder<'_, ()> { fn suggest_item_with_attr( &mut self, cx: &T, diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index 5a2099865d6a7..dcf948d2a88f8 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.rs +++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs @@ -55,8 +55,11 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for TranslatableInIntoDiagn pub struct UntranslatableInAddToDiagnostic; impl AddToDiagnostic for UntranslatableInAddToDiagnostic { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + f: F, + ) { diag.note("untranslatable diagnostic"); //~^ ERROR diagnostics should be created using translatable messages } @@ -65,7 +68,11 @@ impl AddToDiagnostic for UntranslatableInAddToDiagnostic { pub struct TranslatableInAddToDiagnostic; impl AddToDiagnostic for TranslatableInAddToDiagnostic { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with>( + self, + diag: &mut DiagnosticBuilder<'_, G>, + f: F, + ) { diag.note(crate::fluent_generated::no_crate_note); } } diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr index 108b7c8ea9cbb..a69a71bf50efc 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr +++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr @@ -11,13 +11,13 @@ LL | #![deny(rustc::untranslatable_diagnostic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:60:14 + --> $DIR/diagnostics.rs:63:14 | LL | diag.note("untranslatable diagnostic"); | ^^^^ error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls - --> $DIR/diagnostics.rs:74:21 + --> $DIR/diagnostics.rs:81:21 | LL | let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example); | ^^^^^^^^^^ @@ -29,13 +29,13 @@ LL | #![deny(rustc::diagnostic_outside_of_impl)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls - --> $DIR/diagnostics.rs:77:21 + --> $DIR/diagnostics.rs:84:21 | LL | let _diag = dcx.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:77:21 + --> $DIR/diagnostics.rs:84:21 | LL | let _diag = dcx.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr index f07b69326b0cf..0d61e15b0f142 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr @@ -8,9 +8,9 @@ LL | arg: NotIntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `NotIntoDiagnosticArg` | = help: normalized in stderr -note: required by a bound in `DiagnosticBuilder::<'a, G>::arg` - --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC - = note: this error originates in the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info) +note: required by a bound in `rustc_errors::diagnostic::>::arg` + --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC + = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied --> $DIR/diagnostic-derive-doc-comment-field.rs:46:10 @@ -22,8 +22,9 @@ LL | arg: NotIntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `NotIntoDiagnosticArg` | = help: normalized in stderr -note: required by a bound in `Diagnostic::arg` +note: required by a bound in `rustc_errors::diagnostic::>::arg` --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC + = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 6cc6fdfc0eb2b..856f32fafa02b 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -1,8 +1,8 @@ // check-fail // Tests error conditions for specifying diagnostics using #[derive(Diagnostic)] - // normalize-stderr-test "the following other types implement trait `IntoDiagnosticArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr" -// normalize-stderr-test "diagnostic_builder\.rs:[0-9]+:[0-9]+" -> "diagnostic_builder.rs:LL:CC" +// normalize-stderr-test "(COMPILER_DIR/.*\.rs):[0-9]+:[0-9]+" -> "$1:LL:CC" + // The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly, // changing the output of this test. Since Diagnostic is strictly internal to the compiler // the test is just ignored on stable and beta: diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index f2dbc718c7627..ddbb3c6df268c 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -628,9 +628,9 @@ LL | other: Hello, | ^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello` | = help: normalized in stderr -note: required by a bound in `DiagnosticBuilder::<'a, G>::arg` - --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC - = note: this error originates in the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info) +note: required by a bound in `rustc_errors::diagnostic::>::arg` + --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC + = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 86 previous errors