From 8c684563a59900d96a4fcadd41e5e92074c13df1 Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 23 Mar 2022 07:34:20 +0000 Subject: [PATCH 01/23] errors: introduce `DiagnosticMessage` Introduce a `DiagnosticMessage` type that will enable diagnostic messages to be simple strings or Fluent identifiers. `DiagnosticMessage` is now used in the implementation of the standard `DiagnosticBuilder` APIs. Signed-off-by: David Wood --- compiler/rustc_codegen_ssa/src/back/write.rs | 4 +- .../src/annotate_snippet_emitter_writer.rs | 2 +- compiler/rustc_errors/src/diagnostic.rs | 67 +++++++++++++------ compiler/rustc_errors/src/emitter.rs | 20 +++--- compiler/rustc_errors/src/json.rs | 6 +- compiler/rustc_errors/src/lib.rs | 6 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 9 +-- compiler/rustc_parse/src/parser/item.rs | 3 +- .../src/traits/error_reporting/suggestions.rs | 3 +- .../passes/check_code_block_syntax.rs | 2 +- 10 files changed, 79 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 9417874ffb40b..8aa18b8e37ce2 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1708,13 +1708,13 @@ impl SharedEmitter { impl Emitter for SharedEmitter { fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) { drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { - msg: diag.message(), + msg: diag.message().to_string(), code: diag.code.clone(), lvl: diag.level(), }))); for child in &diag.children { drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { - msg: child.message(), + msg: child.message().to_string(), code: None, lvl: child.level, }))); diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 5f59eba23f8e9..76c8396cf9179 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -41,7 +41,7 @@ impl Emitter for AnnotateSnippetEmitterWriter { self.emit_messages_default( &diag.level, - diag.message(), + diag.message().to_string(), &diag.code, &primary_span, &children, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 32c52a6a8a6d9..d31593a132bc8 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -18,6 +18,34 @@ use std::hash::{Hash, Hasher}; #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] pub struct SuggestionsDisabled; +/// Abstraction over a message in a diagnostic to support both translatable and non-translatable +/// diagnostic messages. +#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] +pub enum DiagnosticMessage { + /// Non-translatable diagnostic message. + Str(String), + /// Identifier for a Fluent message corresponding to the diagnostic message. + FluentIdentifier(String), +} + +impl DiagnosticMessage { + /// Convert `DiagnosticMessage` to a `&str`. + pub fn as_str(&self) -> &str { + match self { + DiagnosticMessage::Str(msg) => msg, + DiagnosticMessage::FluentIdentifier(..) => unimplemented!(), + } + } + + /// Convert `DiagnosticMessage` to an owned `String`. + pub fn to_string(self) -> String { + match self { + DiagnosticMessage::Str(msg) => msg, + DiagnosticMessage::FluentIdentifier(..) => unimplemented!(), + } + } +} + #[must_use] #[derive(Clone, Debug, Encodable, Decodable)] pub struct Diagnostic { @@ -25,7 +53,7 @@ pub struct Diagnostic { // outside of what methods in this crate themselves allow. crate level: Level, - pub message: Vec<(String, Style)>, + pub message: Vec<(DiagnosticMessage, Style)>, pub code: Option, pub span: MultiSpan, pub children: Vec, @@ -52,7 +80,7 @@ pub enum DiagnosticId { #[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)] pub struct SubDiagnostic { pub level: Level, - pub message: Vec<(String, Style)>, + pub message: Vec<(DiagnosticMessage, Style)>, pub span: MultiSpan, pub render_span: Option, } @@ -112,7 +140,7 @@ impl Diagnostic { pub fn new_with_code(level: Level, code: Option, message: &str) -> Self { Diagnostic { level, - message: vec![(message.to_owned(), Style::NoStyle)], + message: vec![(DiagnosticMessage::Str(message.to_owned()), Style::NoStyle)], code, span: MultiSpan::new(), children: vec![], @@ -465,7 +493,7 @@ impl Diagnostic { .map(|(span, snippet)| SubstitutionPart { snippet, span }) .collect(), }], - msg: msg.to_owned(), + msg: DiagnosticMessage::Str(msg.to_owned()), style, applicability, tool_metadata: Default::default(), @@ -493,7 +521,7 @@ impl Diagnostic { .map(|(span, snippet)| SubstitutionPart { snippet, span }) .collect(), }], - msg: msg.to_owned(), + msg: DiagnosticMessage::Str(msg.to_owned()), style: SuggestionStyle::CompletelyHidden, applicability, tool_metadata: Default::default(), @@ -548,7 +576,7 @@ impl Diagnostic { substitutions: vec![Substitution { parts: vec![SubstitutionPart { snippet: suggestion, span: sp }], }], - msg: msg.to_owned(), + msg: DiagnosticMessage::Str(msg.to_owned()), style, applicability, tool_metadata: Default::default(), @@ -591,7 +619,7 @@ impl Diagnostic { .collect(); self.push_suggestion(CodeSuggestion { substitutions, - msg: msg.to_owned(), + msg: DiagnosticMessage::Str(msg.to_owned()), style: SuggestionStyle::ShowCode, applicability, tool_metadata: Default::default(), @@ -616,7 +644,7 @@ impl Diagnostic { .collect(), }) .collect(), - msg: msg.to_owned(), + msg: DiagnosticMessage::Str(msg.to_owned()), style: SuggestionStyle::ShowCode, applicability, tool_metadata: Default::default(), @@ -698,7 +726,7 @@ impl Diagnostic { ) { self.push_suggestion(CodeSuggestion { substitutions: vec![], - msg: msg.to_owned(), + msg: DiagnosticMessage::Str(msg.to_owned()), style: SuggestionStyle::CompletelyHidden, applicability, tool_metadata: ToolMetadata::new(tool_metadata), @@ -733,15 +761,15 @@ impl Diagnostic { } pub fn set_primary_message>(&mut self, msg: M) -> &mut Self { - self.message[0] = (msg.into(), Style::NoStyle); + self.message[0] = (DiagnosticMessage::Str(msg.into()), Style::NoStyle); self } - pub fn message(&self) -> String { - self.message.iter().map(|i| i.0.as_str()).collect::() + pub fn message(&self) -> DiagnosticMessage { + DiagnosticMessage::Str(self.message.iter().map(|i| i.0.as_str()).collect::()) } - pub fn styled_message(&self) -> &Vec<(String, Style)> { + pub fn styled_message(&self) -> &Vec<(DiagnosticMessage, Style)> { &self.message } @@ -758,7 +786,7 @@ impl Diagnostic { ) { let sub = SubDiagnostic { level, - message: vec![(message.to_owned(), Style::NoStyle)], + message: vec![(DiagnosticMessage::Str(message.to_owned()), Style::NoStyle)], span, render_span, }; @@ -770,10 +798,11 @@ impl Diagnostic { fn sub_with_highlights( &mut self, level: Level, - message: Vec<(String, Style)>, + mut message: Vec<(String, Style)>, span: MultiSpan, render_span: Option, ) { + let message = message.drain(..).map(|m| (DiagnosticMessage::Str(m.0), m.1)).collect(); let sub = SubDiagnostic { level, message, span, render_span }; self.children.push(sub); } @@ -783,7 +812,7 @@ impl Diagnostic { &self, ) -> ( &Level, - &Vec<(String, Style)>, + &Vec<(DiagnosticMessage, Style)>, &Option, &MultiSpan, &Result, SuggestionsDisabled>, @@ -816,11 +845,11 @@ impl PartialEq for Diagnostic { } impl SubDiagnostic { - pub fn message(&self) -> String { - self.message.iter().map(|i| i.0.as_str()).collect::() + pub fn message(&self) -> DiagnosticMessage { + DiagnosticMessage::Str(self.message.iter().map(|i| i.0.as_str()).collect::()) } - pub fn styled_message(&self) -> &Vec<(String, Style)> { + pub fn styled_message(&self) -> &Vec<(DiagnosticMessage, Style)> { &self.message } } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 93b7201023a49..1f26b002f6a65 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -15,8 +15,8 @@ use rustc_span::{MultiSpan, SourceFile, Span}; use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString}; use crate::styled_buffer::StyledBuffer; use crate::{ - CodeSuggestion, Diagnostic, DiagnosticId, Handler, Level, SubDiagnostic, SubstitutionHighlight, - SuggestionStyle, + CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Handler, Level, SubDiagnostic, + SubstitutionHighlight, SuggestionStyle, }; use rustc_lint_defs::pluralize; @@ -236,7 +236,7 @@ pub trait Emitter { // don't display multipart suggestions as labels sugg.substitutions[0].parts.len() == 1 && // don't display long messages as labels - sugg.msg.split_whitespace().count() < 10 && + sugg.msg.as_str().split_whitespace().count() < 10 && // don't display multiline suggestions as labels !sugg.substitutions[0].parts[0].snippet.contains('\n') && ![ @@ -252,12 +252,12 @@ pub trait Emitter { let msg = if substitution.is_empty() || sugg.style.hide_inline() { // This substitution is only removal OR we explicitly don't want to show the // code inline (`hide_inline`). Therefore, we don't show the substitution. - format!("help: {}", sugg.msg) + format!("help: {}", sugg.msg.as_str()) } else { // Show the default suggestion text with the substitution format!( "help: {}{}: `{}`", - sugg.msg, + sugg.msg.as_str(), if self .source_map() .map(|sm| is_case_difference( @@ -333,7 +333,7 @@ pub trait Emitter { children.push(SubDiagnostic { level: Level::Note, - message: vec![(msg, Style::NoStyle)], + message: vec![(DiagnosticMessage::Str(msg), Style::NoStyle)], span: MultiSpan::new(), render_span: None, }); @@ -1176,7 +1176,7 @@ impl EmitterWriter { fn msg_to_buffer( &self, buffer: &mut StyledBuffer, - msg: &[(String, Style)], + msg: &[(DiagnosticMessage, Style)], padding: usize, label: &str, override_style: Option