Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Raw fluent diagnostic structs #121334

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use rustc_errors::{
codes::*, AddToDiagnostic, Diagnostic, DiagnosticArgFromDisplay, SubdiagnosticMessageOp,
};
use rustc_errors::{codes::*, AddToDiagnostic, DiagCtxt, Diagnostic, DiagnosticArgFromDisplay};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{symbol::Ident, Span, Symbol};

Expand Down Expand Up @@ -40,8 +38,8 @@ pub struct InvalidAbi {

pub struct InvalidAbiReason(pub &'static str);

impl AddToDiagnostic for InvalidAbiReason {
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
impl<'a> AddToDiagnostic<'a> for InvalidAbiReason {
fn add_to_diagnostic(self, _: &'a DiagCtxt, diag: &mut Diagnostic) {
#[allow(rustc::untranslatable_diagnostic)]
diag.note(self.0);
}
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Errors emitted by ast_passes.

use rustc_ast::ParamKindOrd;
use rustc_errors::{codes::*, AddToDiagnostic, Applicability, Diagnostic, SubdiagnosticMessageOp};
use rustc_errors::{codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{symbol::Ident, Span, Symbol};

Expand Down Expand Up @@ -371,8 +371,8 @@ pub struct ArgsBeforeConstraint {
pub struct EmptyLabelManySpans(pub Vec<Span>);

// The derive for `Vec<Span>` does multiple calls to `span_label`, adding commas between each
impl AddToDiagnostic for EmptyLabelManySpans {
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
impl<'a> AddToDiagnostic<'a> for EmptyLabelManySpans {
fn add_to_diagnostic(self, _: &'a DiagCtxt, diag: &mut Diagnostic) {
diag.span_labels(self.0, "");
}
}
Expand Down Expand Up @@ -728,8 +728,8 @@ pub struct StableFeature {
pub since: Symbol,
}

impl AddToDiagnostic for StableFeature {
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
impl<'a> AddToDiagnostic<'a> for StableFeature {
fn add_to_diagnostic(self, _: &'a DiagCtxt, diag: &mut Diagnostic) {
diag.arg("name", self.name);
diag.arg("since", self.since);
diag.help(fluent::ast_passes_stable_since);
Expand Down
13 changes: 8 additions & 5 deletions compiler/rustc_builtin_macros/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc_errors::{
codes::*, AddToDiagnostic, DiagCtxt, Diagnostic, DiagnosticBuilder, EmissionGuarantee,
IntoDiagnostic, Level, MultiSpan, SingleLabelManySpans, SubdiagnosticMessageOp,
IntoDiagnostic, Level, MultiSpan, SingleLabelManySpans,
};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{symbol::Ident, Span, Symbol};
Expand Down Expand Up @@ -610,11 +610,14 @@ 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<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F) {
impl<'a> AddToDiagnostic<'a> for FormatUnusedArg {
fn add_to_diagnostic(self, dcx: &'a DiagCtxt, diag: &mut Diagnostic) {
diag.arg("named", self.named);
let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into());
diag.span_label(self.span, msg);
let message = dcx.eagerly_translate(
crate::fluent_generated::builtin_macros_format_unused_arg,
diag.args(),
);
diag.span_label(self.span, message);
}
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_error_messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ pub type FluentBundle =
IntoDynSyncSend<fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>>;

#[cfg(not(parallel_compiler))]
fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle {
pub fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle {
IntoDynSyncSend(fluent_bundle::bundle::FluentBundle::new(locales))
}

#[cfg(parallel_compiler)]
fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle {
pub fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle {
IntoDynSyncSend(fluent_bundle::bundle::FluentBundle::new_concurrent(locales))
}

Expand Down
28 changes: 9 additions & 19 deletions compiler/rustc_errors/src/diagnostic.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::snippet::Style;
use crate::{
CodeSuggestion, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, ErrCode, Level,
MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
CodeSuggestion, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, ErrCode,
Level, MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
};
use rustc_data_structures::fx::FxIndexMap;
use rustc_error_messages::fluent_value_from_str_list_sep_by_and;
Expand Down Expand Up @@ -66,18 +66,12 @@ impl Into<FluentValue<'static>> for DiagnosticArgValue {
/// Trait implemented by error types. This should not be implemented manually. Instead, use
/// `#[derive(Subdiagnostic)]` -- see [rustc_macros::Subdiagnostic].
#[rustc_diagnostic_item = "AddToDiagnostic"]
pub trait AddToDiagnostic
pub trait AddToDiagnostic<'a>
where
Self: Sized,
{
/// Add a subdiagnostic to an existing diagnostic.
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
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(self, dcx: &'a DiagCtxt, diag: &mut Diagnostic);
}

pub trait SubdiagnosticMessageOp =
Expand Down Expand Up @@ -855,16 +849,12 @@ impl Diagnostic {
/// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages
/// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of
/// interpolated variables).
pub fn subdiagnostic(
pub fn subdiagnostic<'a>(
&mut self,
dcx: &crate::DiagCtxt,
subdiagnostic: impl AddToDiagnostic,
dcx: &'a crate::DiagCtxt,
subdiagnostic: impl AddToDiagnostic<'a>,
) -> &mut Self {
subdiagnostic.add_to_diagnostic_with(self, |diag, msg| {
let args = diag.args();
let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
dcx.eagerly_translate(msg, args)
});
subdiagnostic.add_to_diagnostic(dcx, self);
self
}

Expand Down Expand Up @@ -911,7 +901,7 @@ impl Diagnostic {
/// 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
/// passes the user's string along).
pub(crate) fn subdiagnostic_message_to_diagnostic_message(
pub fn subdiagnostic_message_to_diagnostic_message(
&self,
attr: impl Into<SubdiagnosticMessage>,
) -> DiagnosticMessage {
Expand Down
23 changes: 19 additions & 4 deletions compiler/rustc_errors/src/diagnostic_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,10 +403,25 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
forward!((arg, with_arg)(
name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg,
));
forward!((subdiagnostic, with_subdiagnostic)(
dcx: &DiagCtxt,
subdiagnostic: impl crate::AddToDiagnostic,
));

/// See [`Diagnostic::subdiagnostic()`].
pub fn subdiagnostic(
&mut self,
dcx: &'a DiagCtxt,
subdiagnostic: impl crate::AddToDiagnostic<'a>,
) -> &mut Self {
self.diag.as_mut().unwrap().subdiagnostic(dcx, subdiagnostic);
self
}
/// See [`Diagnostic::subdiagnostic()`].
pub fn with_subdiagnostic(
mut self,
dcx: &'a DiagCtxt,
subdiagnostic: impl crate::AddToDiagnostic<'a>,
) -> Self {
self.diag.as_mut().unwrap().subdiagnostic(dcx, subdiagnostic);
self
}
}

impl<G: EmissionGuarantee> Debug for DiagnosticBuilder<'_, G> {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_errors/src/diagnostic_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::diagnostic::DiagnosticLocation;
use crate::{fluent_generated as fluent, AddToDiagnostic};
use crate::{
DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, ErrCode, IntoDiagnostic,
IntoDiagnosticArg, Level, SubdiagnosticMessageOp,
IntoDiagnosticArg, Level,
};
use rustc_ast as ast;
use rustc_ast_pretty::pprust;
Expand Down Expand Up @@ -298,8 +298,8 @@ pub struct SingleLabelManySpans {
pub spans: Vec<Span>,
pub label: &'static str,
}
impl AddToDiagnostic for SingleLabelManySpans {
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut crate::Diagnostic, _: F) {
impl<'a> AddToDiagnostic<'a> for SingleLabelManySpans {
fn add_to_diagnostic(self, _: &'a DiagCtxt, diag: &mut crate::Diagnostic) {
diag.span_labels(self.spans, self.label);
}
}
Expand Down
84 changes: 54 additions & 30 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#![feature(error_reporter)]
#![feature(extract_if)]
#![feature(generic_nonzero)]
#![feature(lazy_cell)]
#![feature(let_chains)]
#![feature(negative_impls)]
#![feature(never_type)]
Expand Down Expand Up @@ -657,6 +658,17 @@ impl DiagCtxt {
inner.eagerly_translate_to_string(message, args)
}

pub fn raw_translate<'a>(
&self,
slug: &str,
raw: &str,
args: impl Iterator<Item = DiagnosticArg<'a>>,
) -> String {
let inner = self.inner.borrow();
let args = crate::translation::to_fluent_args(args);
inner.emitter.raw_translate_message(slug, raw, &args)
}

// This is here to not allow mutation of flags;
// as of this writing it's used in Session::consider_optimizing and
// in tests in rustc_interface.
Expand Down Expand Up @@ -1520,26 +1532,46 @@ impl DiagCtxtInner {
self.emit_diagnostic(Diagnostic::new(Note, note2));
}

let mut bug =
if backtrace || self.ice_file.is_none() { bug.decorate(self) } else { bug.inner };
// This is a bit gnarly, but the `AddToDiagnostic` type uses a `DiagCtxt` to trigger
// translation. It could take an emitter or a `DiagCtxtInner` but it would make
// every other use of `AddToDiagnostic` more complex. This function is only invoked
// during the `Drop` of `DiagCtxtInner`, so we temporarily get a `T` from the `&mut T`
// here so we can put this back into a lock and back into a `DiagCtxt` to call the
// functions from `AddToDiagnostic`.
//
// FIXME(davidtwco): `AddToDiagnostic` should eventually be merged with
// `IntoDiagnostic`, and then the context determined by an associated type, depending
// on the needs of the specific diagnostic - once this is done, we can make these
// specific diagnostics take an emitter directly.
let bug = unsafe {
let old_dcx = std::ptr::read(self);
let (new_dcx, bug) = std::panic::catch_unwind(panic::AssertUnwindSafe(|| {
let dcx = DiagCtxt { inner: Lock::new(old_dcx) };

let mut bug = if backtrace || self.ice_file.is_none() {
bug.decorate(&dcx)
} else {
bug.inner
};

// "Undelay" the delayed bugs (into plain `Bug`s).
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,
};
subdiag.add_to_diagnostic(&dcx, &mut bug);
}
bug.level = Bug;

// "Undelay" the delayed bugs (into plain `Bug`s).
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)
});
}
bug.level = Bug;
(dcx.inner.into_inner(), bug)
}))
.unwrap_or_else(|_| std::process::abort());
std::ptr::write(self, new_dcx);
bug
};

self.emit_diagnostic(bug);
}
Expand Down Expand Up @@ -1571,15 +1603,7 @@ 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)
};

fn decorate(mut self, dcx: &DiagCtxt) -> Diagnostic {
match self.note.status() {
BacktraceStatus::Captured => {
let inner = &self.inner;
Expand All @@ -1588,7 +1612,7 @@ impl DelayedDiagnostic {
emitted_at: inner.emitted_at.clone(),
note: self.note,
};
subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with);
subdiag.add_to_diagnostic(dcx, &mut self.inner);
}
// Avoid the needless newline when no backtrace has been captured,
// the display impl should just be a single line.
Expand All @@ -1599,7 +1623,7 @@ impl DelayedDiagnostic {
emitted_at: inner.emitted_at.clone(),
note: self.note,
};
subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with);
subdiag.add_to_diagnostic(dcx, &mut self.inner);
}
}

Expand Down
Loading
Loading