Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 8c68456

Browse files
committed
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 <david.wood@huawei.com>
1 parent a22cf2a commit 8c68456

File tree

10 files changed

+79
-43
lines changed

10 files changed

+79
-43
lines changed

compiler/rustc_codegen_ssa/src/back/write.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,13 +1708,13 @@ impl SharedEmitter {
17081708
impl Emitter for SharedEmitter {
17091709
fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) {
17101710
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
1711-
msg: diag.message(),
1711+
msg: diag.message().to_string(),
17121712
code: diag.code.clone(),
17131713
lvl: diag.level(),
17141714
})));
17151715
for child in &diag.children {
17161716
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
1717-
msg: child.message(),
1717+
msg: child.message().to_string(),
17181718
code: None,
17191719
lvl: child.level,
17201720
})));

compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ impl Emitter for AnnotateSnippetEmitterWriter {
4141

4242
self.emit_messages_default(
4343
&diag.level,
44-
diag.message(),
44+
diag.message().to_string(),
4545
&diag.code,
4646
&primary_span,
4747
&children,

compiler/rustc_errors/src/diagnostic.rs

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,42 @@ use std::hash::{Hash, Hasher};
1818
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
1919
pub struct SuggestionsDisabled;
2020

21+
/// Abstraction over a message in a diagnostic to support both translatable and non-translatable
22+
/// diagnostic messages.
23+
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
24+
pub enum DiagnosticMessage {
25+
/// Non-translatable diagnostic message.
26+
Str(String),
27+
/// Identifier for a Fluent message corresponding to the diagnostic message.
28+
FluentIdentifier(String),
29+
}
30+
31+
impl DiagnosticMessage {
32+
/// Convert `DiagnosticMessage` to a `&str`.
33+
pub fn as_str(&self) -> &str {
34+
match self {
35+
DiagnosticMessage::Str(msg) => msg,
36+
DiagnosticMessage::FluentIdentifier(..) => unimplemented!(),
37+
}
38+
}
39+
40+
/// Convert `DiagnosticMessage` to an owned `String`.
41+
pub fn to_string(self) -> String {
42+
match self {
43+
DiagnosticMessage::Str(msg) => msg,
44+
DiagnosticMessage::FluentIdentifier(..) => unimplemented!(),
45+
}
46+
}
47+
}
48+
2149
#[must_use]
2250
#[derive(Clone, Debug, Encodable, Decodable)]
2351
pub struct Diagnostic {
2452
// NOTE(eddyb) this is private to disallow arbitrary after-the-fact changes,
2553
// outside of what methods in this crate themselves allow.
2654
crate level: Level,
2755

28-
pub message: Vec<(String, Style)>,
56+
pub message: Vec<(DiagnosticMessage, Style)>,
2957
pub code: Option<DiagnosticId>,
3058
pub span: MultiSpan,
3159
pub children: Vec<SubDiagnostic>,
@@ -52,7 +80,7 @@ pub enum DiagnosticId {
5280
#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
5381
pub struct SubDiagnostic {
5482
pub level: Level,
55-
pub message: Vec<(String, Style)>,
83+
pub message: Vec<(DiagnosticMessage, Style)>,
5684
pub span: MultiSpan,
5785
pub render_span: Option<MultiSpan>,
5886
}
@@ -112,7 +140,7 @@ impl Diagnostic {
112140
pub fn new_with_code(level: Level, code: Option<DiagnosticId>, message: &str) -> Self {
113141
Diagnostic {
114142
level,
115-
message: vec![(message.to_owned(), Style::NoStyle)],
143+
message: vec![(DiagnosticMessage::Str(message.to_owned()), Style::NoStyle)],
116144
code,
117145
span: MultiSpan::new(),
118146
children: vec![],
@@ -465,7 +493,7 @@ impl Diagnostic {
465493
.map(|(span, snippet)| SubstitutionPart { snippet, span })
466494
.collect(),
467495
}],
468-
msg: msg.to_owned(),
496+
msg: DiagnosticMessage::Str(msg.to_owned()),
469497
style,
470498
applicability,
471499
tool_metadata: Default::default(),
@@ -493,7 +521,7 @@ impl Diagnostic {
493521
.map(|(span, snippet)| SubstitutionPart { snippet, span })
494522
.collect(),
495523
}],
496-
msg: msg.to_owned(),
524+
msg: DiagnosticMessage::Str(msg.to_owned()),
497525
style: SuggestionStyle::CompletelyHidden,
498526
applicability,
499527
tool_metadata: Default::default(),
@@ -548,7 +576,7 @@ impl Diagnostic {
548576
substitutions: vec![Substitution {
549577
parts: vec![SubstitutionPart { snippet: suggestion, span: sp }],
550578
}],
551-
msg: msg.to_owned(),
579+
msg: DiagnosticMessage::Str(msg.to_owned()),
552580
style,
553581
applicability,
554582
tool_metadata: Default::default(),
@@ -591,7 +619,7 @@ impl Diagnostic {
591619
.collect();
592620
self.push_suggestion(CodeSuggestion {
593621
substitutions,
594-
msg: msg.to_owned(),
622+
msg: DiagnosticMessage::Str(msg.to_owned()),
595623
style: SuggestionStyle::ShowCode,
596624
applicability,
597625
tool_metadata: Default::default(),
@@ -616,7 +644,7 @@ impl Diagnostic {
616644
.collect(),
617645
})
618646
.collect(),
619-
msg: msg.to_owned(),
647+
msg: DiagnosticMessage::Str(msg.to_owned()),
620648
style: SuggestionStyle::ShowCode,
621649
applicability,
622650
tool_metadata: Default::default(),
@@ -698,7 +726,7 @@ impl Diagnostic {
698726
) {
699727
self.push_suggestion(CodeSuggestion {
700728
substitutions: vec![],
701-
msg: msg.to_owned(),
729+
msg: DiagnosticMessage::Str(msg.to_owned()),
702730
style: SuggestionStyle::CompletelyHidden,
703731
applicability,
704732
tool_metadata: ToolMetadata::new(tool_metadata),
@@ -733,15 +761,15 @@ impl Diagnostic {
733761
}
734762

735763
pub fn set_primary_message<M: Into<String>>(&mut self, msg: M) -> &mut Self {
736-
self.message[0] = (msg.into(), Style::NoStyle);
764+
self.message[0] = (DiagnosticMessage::Str(msg.into()), Style::NoStyle);
737765
self
738766
}
739767

740-
pub fn message(&self) -> String {
741-
self.message.iter().map(|i| i.0.as_str()).collect::<String>()
768+
pub fn message(&self) -> DiagnosticMessage {
769+
DiagnosticMessage::Str(self.message.iter().map(|i| i.0.as_str()).collect::<String>())
742770
}
743771

744-
pub fn styled_message(&self) -> &Vec<(String, Style)> {
772+
pub fn styled_message(&self) -> &Vec<(DiagnosticMessage, Style)> {
745773
&self.message
746774
}
747775

@@ -758,7 +786,7 @@ impl Diagnostic {
758786
) {
759787
let sub = SubDiagnostic {
760788
level,
761-
message: vec![(message.to_owned(), Style::NoStyle)],
789+
message: vec![(DiagnosticMessage::Str(message.to_owned()), Style::NoStyle)],
762790
span,
763791
render_span,
764792
};
@@ -770,10 +798,11 @@ impl Diagnostic {
770798
fn sub_with_highlights(
771799
&mut self,
772800
level: Level,
773-
message: Vec<(String, Style)>,
801+
mut message: Vec<(String, Style)>,
774802
span: MultiSpan,
775803
render_span: Option<MultiSpan>,
776804
) {
805+
let message = message.drain(..).map(|m| (DiagnosticMessage::Str(m.0), m.1)).collect();
777806
let sub = SubDiagnostic { level, message, span, render_span };
778807
self.children.push(sub);
779808
}
@@ -783,7 +812,7 @@ impl Diagnostic {
783812
&self,
784813
) -> (
785814
&Level,
786-
&Vec<(String, Style)>,
815+
&Vec<(DiagnosticMessage, Style)>,
787816
&Option<DiagnosticId>,
788817
&MultiSpan,
789818
&Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
@@ -816,11 +845,11 @@ impl PartialEq for Diagnostic {
816845
}
817846

818847
impl SubDiagnostic {
819-
pub fn message(&self) -> String {
820-
self.message.iter().map(|i| i.0.as_str()).collect::<String>()
848+
pub fn message(&self) -> DiagnosticMessage {
849+
DiagnosticMessage::Str(self.message.iter().map(|i| i.0.as_str()).collect::<String>())
821850
}
822851

823-
pub fn styled_message(&self) -> &Vec<(String, Style)> {
852+
pub fn styled_message(&self) -> &Vec<(DiagnosticMessage, Style)> {
824853
&self.message
825854
}
826855
}

compiler/rustc_errors/src/emitter.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use rustc_span::{MultiSpan, SourceFile, Span};
1515
use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString};
1616
use crate::styled_buffer::StyledBuffer;
1717
use crate::{
18-
CodeSuggestion, Diagnostic, DiagnosticId, Handler, Level, SubDiagnostic, SubstitutionHighlight,
19-
SuggestionStyle,
18+
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Handler, Level, SubDiagnostic,
19+
SubstitutionHighlight, SuggestionStyle,
2020
};
2121

2222
use rustc_lint_defs::pluralize;
@@ -236,7 +236,7 @@ pub trait Emitter {
236236
// don't display multipart suggestions as labels
237237
sugg.substitutions[0].parts.len() == 1 &&
238238
// don't display long messages as labels
239-
sugg.msg.split_whitespace().count() < 10 &&
239+
sugg.msg.as_str().split_whitespace().count() < 10 &&
240240
// don't display multiline suggestions as labels
241241
!sugg.substitutions[0].parts[0].snippet.contains('\n') &&
242242
![
@@ -252,12 +252,12 @@ pub trait Emitter {
252252
let msg = if substitution.is_empty() || sugg.style.hide_inline() {
253253
// This substitution is only removal OR we explicitly don't want to show the
254254
// code inline (`hide_inline`). Therefore, we don't show the substitution.
255-
format!("help: {}", sugg.msg)
255+
format!("help: {}", sugg.msg.as_str())
256256
} else {
257257
// Show the default suggestion text with the substitution
258258
format!(
259259
"help: {}{}: `{}`",
260-
sugg.msg,
260+
sugg.msg.as_str(),
261261
if self
262262
.source_map()
263263
.map(|sm| is_case_difference(
@@ -333,7 +333,7 @@ pub trait Emitter {
333333

334334
children.push(SubDiagnostic {
335335
level: Level::Note,
336-
message: vec![(msg, Style::NoStyle)],
336+
message: vec![(DiagnosticMessage::Str(msg), Style::NoStyle)],
337337
span: MultiSpan::new(),
338338
render_span: None,
339339
});
@@ -1176,7 +1176,7 @@ impl EmitterWriter {
11761176
fn msg_to_buffer(
11771177
&self,
11781178
buffer: &mut StyledBuffer,
1179-
msg: &[(String, Style)],
1179+
msg: &[(DiagnosticMessage, Style)],
11801180
padding: usize,
11811181
label: &str,
11821182
override_style: Option<Style>,
@@ -1229,6 +1229,7 @@ impl EmitterWriter {
12291229
// very *weird* formats
12301230
// see?
12311231
for &(ref text, ref style) in msg.iter() {
1232+
let text = text.as_str();
12321233
let lines = text.split('\n').collect::<Vec<_>>();
12331234
if lines.len() > 1 {
12341235
for (i, line) in lines.iter().enumerate() {
@@ -1247,7 +1248,7 @@ impl EmitterWriter {
12471248
fn emit_message_default(
12481249
&mut self,
12491250
msp: &MultiSpan,
1250-
msg: &[(String, Style)],
1251+
msg: &[(DiagnosticMessage, Style)],
12511252
code: &Option<DiagnosticId>,
12521253
level: &Level,
12531254
max_line_num_len: usize,
@@ -1287,6 +1288,7 @@ impl EmitterWriter {
12871288
label_width += 2;
12881289
}
12891290
for &(ref text, _) in msg.iter() {
1291+
let text = text.as_str();
12901292
// Account for newlines to align output to its label.
12911293
for (line, text) in normalize_whitespace(text).lines().enumerate() {
12921294
buffer.append(
@@ -1852,7 +1854,7 @@ impl EmitterWriter {
18521854
fn emit_messages_default(
18531855
&mut self,
18541856
level: &Level,
1855-
message: &[(String, Style)],
1857+
message: &[(DiagnosticMessage, Style)],
18561858
code: &Option<DiagnosticId>,
18571859
span: &MultiSpan,
18581860
children: &[SubDiagnostic],

compiler/rustc_errors/src/json.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ struct UnusedExterns<'a, 'b, 'c> {
346346
impl Diagnostic {
347347
fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnostic {
348348
let sugg = diag.suggestions.iter().flatten().map(|sugg| Diagnostic {
349-
message: sugg.msg.clone(),
349+
message: sugg.msg.clone().to_string(),
350350
code: None,
351351
level: "help",
352352
spans: DiagnosticSpan::from_suggestion(sugg, je),
@@ -385,7 +385,7 @@ impl Diagnostic {
385385
let output = String::from_utf8(output).unwrap();
386386

387387
Diagnostic {
388-
message: diag.message(),
388+
message: diag.message().to_string(),
389389
code: DiagnosticCode::map_opt_string(diag.code.clone(), je),
390390
level: diag.level.to_str(),
391391
spans: DiagnosticSpan::from_multispan(&diag.span, je),
@@ -402,7 +402,7 @@ impl Diagnostic {
402402

403403
fn from_sub_diagnostic(diag: &SubDiagnostic, je: &JsonEmitter) -> Diagnostic {
404404
Diagnostic {
405-
message: diag.message(),
405+
message: diag.message().to_string(),
406406
code: None,
407407
level: diag.level.to_str(),
408408
spans: diag

compiler/rustc_errors/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ pub struct CodeSuggestion {
145145
/// ]
146146
/// ```
147147
pub substitutions: Vec<Substitution>,
148-
pub msg: String,
148+
pub msg: DiagnosticMessage,
149149
/// Visual representation of this suggestion.
150150
pub style: SuggestionStyle,
151151
/// Whether or not the suggestion is approximate
@@ -400,7 +400,9 @@ impl fmt::Display for ExplicitBug {
400400

401401
impl error::Error for ExplicitBug {}
402402

403-
pub use diagnostic::{Diagnostic, DiagnosticId, DiagnosticStyledString, SubDiagnostic};
403+
pub use diagnostic::{
404+
Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, SubDiagnostic,
405+
};
404406
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee};
405407
use std::backtrace::Backtrace;
406408

compiler/rustc_expand/src/mbe/macro_rules.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,18 @@ fn emit_frag_parse_err(
6868
arm_span: Span,
6969
kind: AstFragmentKind,
7070
) {
71-
if parser.token == token::Eof && e.message().ends_with(", found `<eof>`") {
71+
// FIXME(davidtwco): avoid depending on the error message text
72+
if parser.token == token::Eof && e.message().as_str().ends_with(", found `<eof>`") {
7273
if !e.span.is_dummy() {
7374
// early end of macro arm (#52866)
7475
e.replace_span_with(parser.sess.source_map().next_point(parser.token.span));
7576
}
7677
let msg = &e.message[0];
7778
e.message[0] = (
78-
format!(
79+
rustc_errors::DiagnosticMessage::Str(format!(
7980
"macro expansion ends with an incomplete expression: {}",
80-
msg.0.replace(", found `<eof>`", ""),
81-
),
81+
msg.0.as_str().replace(", found `<eof>`", ""),
82+
)),
8283
msg.1,
8384
);
8485
}

compiler/rustc_parse/src/parser/item.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1010,7 +1010,8 @@ impl<'a> Parser<'a> {
10101010
let current_qual_sp = self.prev_token.span;
10111011
let current_qual_sp = current_qual_sp.to(sp_start);
10121012
if let Ok(current_qual) = self.span_to_snippet(current_qual_sp) {
1013-
if err.message() == "expected `{`, found keyword `unsafe`" {
1013+
// FIXME(davidtwco): avoid depending on the error message text
1014+
if err.message().as_str() == "expected `{`, found keyword `unsafe`" {
10141015
let invalid_qual_sp = self.token.uninterpolated_span();
10151016
let invalid_qual = self.span_to_snippet(invalid_qual_sp).unwrap();
10161017

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
780780
if has_custom_message {
781781
err.note(&msg);
782782
} else {
783-
err.message = vec![(msg, Style::NoStyle)];
783+
err.message =
784+
vec![(rustc_errors::DiagnosticMessage::Str(msg), Style::NoStyle)];
784785
}
785786
if snippet.starts_with('&') {
786787
// This is already a literal borrow and the obligation is failing

src/librustdoc/passes/check_code_block_syntax.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ struct BufferEmitter {
176176
impl Emitter for BufferEmitter {
177177
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
178178
let mut buffer = self.buffer.borrow_mut();
179-
buffer.messages.push(format!("error from rustc: {}", diag.message[0].0));
179+
buffer.messages.push(format!("error from rustc: {}", diag.message[0].0.as_str()));
180180
if diag.is_error() {
181181
buffer.has_errors = true;
182182
}

0 commit comments

Comments
 (0)