1
Fork 0

errors: implement fallback diagnostic translation

This commit updates the signatures of all diagnostic functions to accept
types that can be converted into a `DiagnosticMessage`. This enables
existing diagnostic calls to continue to work as before and Fluent
identifiers to be provided. The `SessionDiagnostic` derive just
generates normal diagnostic calls, so these APIs had to be modified to
accept Fluent identifiers.

In addition, loading of the "fallback" Fluent bundle, which contains the
built-in English messages, has been implemented.

Each diagnostic now has "arguments" which correspond to variables in the
Fluent messages (necessary to render a Fluent message) but no API for
adding arguments has been added yet. Therefore, diagnostics (that do not
require interpolation) can be converted to use Fluent identifiers and
will be output as before.
This commit is contained in:
David Wood 2022-03-26 07:27:43 +00:00
parent c45f29595d
commit 7f91697b50
46 changed files with 919 additions and 293 deletions

View file

@ -18,7 +18,9 @@ use rustc_ast::{
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, struct_span_err, Diagnostic, EmissionGuarantee, ErrorGuaranteed};
use rustc_errors::{Applicability, DiagnosticBuilder, Handler, MultiSpan, PResult};
use rustc_errors::{
Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult,
};
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, Ident};
use rustc_span::{Span, SpanSnippetError, DUMMY_SP};
@ -273,12 +275,12 @@ impl<'a> Parser<'a> {
pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,
m: &str,
m: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
self.sess.span_diagnostic.struct_span_err(sp, m)
}
pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> ! {
pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: impl Into<DiagnosticMessage>) -> ! {
self.sess.span_diagnostic.span_bug(sp, m)
}
@ -584,16 +586,22 @@ impl<'a> Parser<'a> {
// field: value,
// } }
err.delay_as_bug();
self.struct_span_err(expr.span, "struct literal body without path")
.multipart_suggestion(
"you might have forgotten to add the struct literal inside the block",
vec![
(expr.span.shrink_to_lo(), "{ SomeStruct ".to_string()),
(expr.span.shrink_to_hi(), " }".to_string()),
],
Applicability::MaybeIncorrect,
)
.emit();
self.struct_span_err(
expr.span,
DiagnosticMessage::fluent("parser-struct-literal-body-without-path"),
)
.multipart_suggestion(
DiagnosticMessage::fluent_attr(
"parser-struct-literal-body-without-path",
"suggestion",
),
vec![
(expr.span.shrink_to_lo(), "{ SomeStruct ".to_string()),
(expr.span.shrink_to_hi(), " }".to_string()),
],
Applicability::MaybeIncorrect,
)
.emit();
self.restore_snapshot(snapshot);
let mut tail = self.mk_block(
vec![self.mk_stmt_err(expr.span)],
@ -1752,7 +1760,7 @@ impl<'a> Parser<'a> {
let mut primary_span: MultiSpan = primary_span.into();
for span_label in err.span.span_labels() {
if let Some(label) = span_label.label {
primary_span.push_span_message(span_label.span, label);
primary_span.push_span_label(span_label.span, label);
}
}
err.set_span(primary_span);

View file

@ -1703,7 +1703,7 @@ impl<'a> Parser<'a> {
if matches!(expr.kind, ExprKind::Err) {
let mut err = self
.diagnostic()
.struct_span_err(self.token.span, &"invalid interpolated expression");
.struct_span_err(self.token.span, "invalid interpolated expression");
err.downgrade_to_delayed_bug();
return err;
}
@ -1820,7 +1820,7 @@ impl<'a> Parser<'a> {
} else if let Some(fixed) = fix_base_capitalisation(suf) {
let msg = "invalid base prefix for number literal";
self.struct_span_err(span, &msg)
self.struct_span_err(span, msg)
.note("base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase")
.span_suggestion(
span,

View file

@ -1011,7 +1011,7 @@ impl<'a> Parser<'a> {
let current_qual_sp = current_qual_sp.to(sp_start);
if let Ok(current_qual) = self.span_to_snippet(current_qual_sp) {
// FIXME(davidtwco): avoid depending on the error message text
if err.message().as_str() == "expected `{`, found keyword `unsafe`" {
if err.message[0].0.expect_str() == "expected `{`, found keyword `unsafe`" {
let invalid_qual_sp = self.token.uninterpolated_span();
let invalid_qual = self.span_to_snippet(invalid_qual_sp).unwrap();