diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_error_messages/src/lib.rs | 72 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic.rs | 86 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic_builder.rs | 47 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/lib.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_macros/src/diagnostics/diagnostic.rs | 36 | ||||
| -rw-r--r-- | compiler/rustc_macros/src/diagnostics/fluent.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_macros/src/diagnostics/subdiagnostic.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/errors.rs | 11 |
9 files changed, 175 insertions, 113 deletions
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 7faf14a2472..02d076c95ca 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -234,6 +234,48 @@ pub fn fallback_fluent_bundle( /// Identifier for the Fluent message/attribute corresponding to a diagnostic message. type FluentId = Cow<'static, str>; +/// Abstraction over a message in a subdiagnostic (i.e. label, note, help, etc) to support both +/// translatable and non-translatable diagnostic messages. +/// +/// Translatable messages for subdiagnostics are typically attributes attached to a larger Fluent +/// message so messages of this type must be combined with a `DiagnosticMessage` (using +/// `DiagnosticMessage::with_subdiagnostic_message`) before rendering. However, subdiagnostics from +/// the `SessionSubdiagnostic` derive refer to Fluent identifiers directly. +pub enum SubdiagnosticMessage { + /// Non-translatable diagnostic message. + // FIXME(davidtwco): can a `Cow<'static, str>` be used here? + Str(String), + /// Identifier of a Fluent message. Instances of this variant are generated by the + /// `SessionSubdiagnostic` derive. + FluentIdentifier(FluentId), + /// Attribute of a Fluent message. Needs to be combined with a Fluent identifier to produce an + /// actual translated message. Instances of this variant are generated by the `fluent_messages` + /// macro. + /// + /// <https://projectfluent.org/fluent/guide/attributes.html> + FluentAttr(FluentId), +} + +impl SubdiagnosticMessage { + /// Create a `SubdiagnosticMessage` for the provided Fluent attribute. + pub fn attr(id: impl Into<FluentId>) -> Self { + SubdiagnosticMessage::FluentAttr(id.into()) + } + + /// Create a `SubdiagnosticMessage` for the provided Fluent identifier. + pub fn message(id: impl Into<FluentId>) -> Self { + SubdiagnosticMessage::FluentIdentifier(id.into()) + } +} + +/// `From` impl that enables existing diagnostic calls to functions which now take +/// `impl Into<SubdiagnosticMessage>` to continue to work as before. +impl<S: Into<String>> From<S> for SubdiagnosticMessage { + fn from(s: S) -> Self { + SubdiagnosticMessage::Str(s.into()) + } +} + /// Abstraction over a message in a diagnostic to support both translatable and non-translatable /// diagnostic messages. /// @@ -252,6 +294,29 @@ pub enum DiagnosticMessage { } impl DiagnosticMessage { + /// Given a `SubdiagnosticMessage` which may contain a Fluent attribute, create a new + /// `DiagnosticMessage` that combines that attribute with the Fluent identifier of `self`. + /// + /// - If the `SubdiagnosticMessage` is non-translatable then return the message as a + /// `DiagnosticMessage`. + /// - If `self` is non-translatable then return `self`'s message. + pub fn with_subdiagnostic_message(&self, sub: SubdiagnosticMessage) -> Self { + let attr = match sub { + SubdiagnosticMessage::Str(s) => return DiagnosticMessage::Str(s.clone()), + SubdiagnosticMessage::FluentIdentifier(id) => { + return DiagnosticMessage::FluentIdentifier(id, None); + } + SubdiagnosticMessage::FluentAttr(attr) => attr, + }; + + match self { + DiagnosticMessage::Str(s) => DiagnosticMessage::Str(s.clone()), + DiagnosticMessage::FluentIdentifier(id, _) => { + DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr)) + } + } + } + /// Returns the `String` contained within the `DiagnosticMessage::Str` variant, assuming that /// this diagnostic message is of the legacy, non-translatable variety. Panics if this /// assumption does not hold. @@ -266,14 +331,9 @@ impl DiagnosticMessage { } /// Create a `DiagnosticMessage` for the provided Fluent identifier. - pub fn fluent(id: impl Into<FluentId>) -> Self { + pub fn new(id: impl Into<FluentId>) -> Self { DiagnosticMessage::FluentIdentifier(id.into(), None) } - - /// Create a `DiagnosticMessage` for the provided Fluent identifier and attribute. - pub fn fluent_attr(id: impl Into<FluentId>, attr: impl Into<FluentId>) -> Self { - DiagnosticMessage::FluentIdentifier(id.into(), Some(attr.into())) - } } /// `From` impl that enables existing diagnostic calls to functions which now take diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index f130b5aa9a6..643f3c12134 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1,7 +1,7 @@ use crate::snippet::Style; use crate::{ - CodeSuggestion, DiagnosticMessage, Level, MultiSpan, Substitution, SubstitutionPart, - SuggestionStyle, + CodeSuggestion, DiagnosticMessage, Level, MultiSpan, SubdiagnosticMessage, Substitution, + SubstitutionPart, SuggestionStyle, }; use rustc_data_structures::stable_map::FxHashMap; use rustc_error_messages::FluentValue; @@ -283,8 +283,8 @@ impl Diagnostic { /// /// This span is *not* considered a ["primary span"][`MultiSpan`]; only /// the `Span` supplied when creating the diagnostic is primary. - pub fn span_label(&mut self, span: Span, label: impl Into<DiagnosticMessage>) -> &mut Self { - self.span.push_span_label(span, label.into()); + pub fn span_label(&mut self, span: Span, label: impl Into<SubdiagnosticMessage>) -> &mut Self { + self.span.push_span_label(span, self.subdiagnostic_message_to_diagnostic_message(label)); self } @@ -401,12 +401,12 @@ impl Diagnostic { } /// Add a note attached to this diagnostic. - pub fn note(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self { + pub fn note(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { self.sub(Level::Note, msg, MultiSpan::new(), None); self } - pub fn highlighted_note<M: Into<DiagnosticMessage>>( + pub fn highlighted_note<M: Into<SubdiagnosticMessage>>( &mut self, msg: Vec<(M, Style)>, ) -> &mut Self { @@ -416,7 +416,7 @@ impl Diagnostic { /// Prints the span with a note above it. /// This is like [`Diagnostic::note()`], but it gets its own span. - pub fn note_once(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self { + pub fn note_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { self.sub(Level::OnceNote, msg, MultiSpan::new(), None); self } @@ -426,7 +426,7 @@ impl Diagnostic { pub fn span_note<S: Into<MultiSpan>>( &mut self, sp: S, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self { self.sub(Level::Note, msg, sp.into(), None); self @@ -437,14 +437,14 @@ impl Diagnostic { pub fn span_note_once<S: Into<MultiSpan>>( &mut self, sp: S, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self { self.sub(Level::OnceNote, msg, sp.into(), None); self } /// Add a warning attached to this diagnostic. - pub fn warn(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self { + pub fn warn(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { self.sub(Level::Warning, msg, MultiSpan::new(), None); self } @@ -454,14 +454,14 @@ impl Diagnostic { pub fn span_warn<S: Into<MultiSpan>>( &mut self, sp: S, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self { self.sub(Level::Warning, msg, sp.into(), None); self } /// Add a help message attached to this diagnostic. - pub fn help(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self { + pub fn help(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { self.sub(Level::Help, msg, MultiSpan::new(), None); self } @@ -477,7 +477,7 @@ impl Diagnostic { pub fn span_help<S: Into<MultiSpan>>( &mut self, sp: S, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self { self.sub(Level::Help, msg, sp.into(), None); self @@ -514,7 +514,7 @@ impl Diagnostic { /// In other words, multiple changes need to be applied as part of this suggestion. pub fn multipart_suggestion( &mut self, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -530,7 +530,7 @@ impl Diagnostic { /// In other words, multiple changes need to be applied as part of this suggestion. pub fn multipart_suggestion_verbose( &mut self, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -544,7 +544,7 @@ impl Diagnostic { /// [`Diagnostic::multipart_suggestion()`] but you can set the [`SuggestionStyle`]. pub fn multipart_suggestion_with_style( &mut self, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: Vec<(Span, String)>, applicability: Applicability, style: SuggestionStyle, @@ -557,7 +557,7 @@ impl Diagnostic { .map(|(span, snippet)| SubstitutionPart { snippet, span }) .collect(), }], - msg: msg.into(), + msg: self.subdiagnostic_message_to_diagnostic_message(msg), style, applicability, }); @@ -572,7 +572,7 @@ impl Diagnostic { /// improve understandability. pub fn tool_only_multipart_suggestion( &mut self, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -584,7 +584,7 @@ impl Diagnostic { .map(|(span, snippet)| SubstitutionPart { snippet, span }) .collect(), }], - msg: msg.into(), + msg: self.subdiagnostic_message_to_diagnostic_message(msg), style: SuggestionStyle::CompletelyHidden, applicability, }); @@ -611,7 +611,7 @@ impl Diagnostic { pub fn span_suggestion( &mut self, sp: Span, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -629,7 +629,7 @@ impl Diagnostic { pub fn span_suggestion_with_style( &mut self, sp: Span, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: impl ToString, applicability: Applicability, style: SuggestionStyle, @@ -638,7 +638,7 @@ impl Diagnostic { substitutions: vec![Substitution { parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }], }], - msg: msg.into(), + msg: self.subdiagnostic_message_to_diagnostic_message(msg), style, applicability, }); @@ -649,7 +649,7 @@ impl Diagnostic { pub fn span_suggestion_verbose( &mut self, sp: Span, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -668,7 +668,7 @@ impl Diagnostic { pub fn span_suggestions( &mut self, sp: Span, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestions: impl Iterator<Item = String>, applicability: Applicability, ) -> &mut Self { @@ -680,7 +680,7 @@ impl Diagnostic { .collect(); self.push_suggestion(CodeSuggestion { substitutions, - msg: msg.into(), + msg: self.subdiagnostic_message_to_diagnostic_message(msg), style: SuggestionStyle::ShowCode, applicability, }); @@ -691,7 +691,7 @@ impl Diagnostic { /// See also [`Diagnostic::span_suggestion()`]. pub fn multipart_suggestions( &mut self, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestions: impl Iterator<Item = Vec<(Span, String)>>, applicability: Applicability, ) -> &mut Self { @@ -704,7 +704,7 @@ impl Diagnostic { .collect(), }) .collect(), - msg: msg.into(), + msg: self.subdiagnostic_message_to_diagnostic_message(msg), style: SuggestionStyle::ShowCode, applicability, }); @@ -717,7 +717,7 @@ impl Diagnostic { pub fn span_suggestion_short( &mut self, sp: Span, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -740,7 +740,7 @@ impl Diagnostic { pub fn span_suggestion_hidden( &mut self, sp: Span, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -761,7 +761,7 @@ impl Diagnostic { pub fn tool_only_span_suggestion( &mut self, sp: Span, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -831,6 +831,18 @@ impl Diagnostic { &self.message } + /// 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). + fn subdiagnostic_message_to_diagnostic_message( + &self, + attr: impl Into<SubdiagnosticMessage>, + ) -> DiagnosticMessage { + let msg = + self.message.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages"); + msg.with_subdiagnostic_message(attr.into()) + } + /// Convenience function for internal use, clients should use one of the /// public methods above. /// @@ -838,13 +850,16 @@ impl Diagnostic { pub fn sub( &mut self, level: Level, - message: impl Into<DiagnosticMessage>, + message: impl Into<SubdiagnosticMessage>, span: MultiSpan, render_span: Option<MultiSpan>, ) { let sub = SubDiagnostic { level, - message: vec![(message.into(), Style::NoStyle)], + message: vec![( + self.subdiagnostic_message_to_diagnostic_message(message), + Style::NoStyle, + )], span, render_span, }; @@ -853,14 +868,17 @@ impl Diagnostic { /// Convenience function for internal use, clients should use one of the /// public methods above. - fn sub_with_highlights<M: Into<DiagnosticMessage>>( + fn sub_with_highlights<M: Into<SubdiagnosticMessage>>( &mut self, level: Level, mut message: Vec<(M, Style)>, span: MultiSpan, render_span: Option<MultiSpan>, ) { - let message = message.drain(..).map(|m| (m.0.into(), m.1)).collect(); + let message = message + .drain(..) + .map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.0), m.1)) + .collect(); let sub = SubDiagnostic { level, message, span, render_span }; self.children.push(sub); } diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 6ef2c832c65..9e0a99849a3 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -1,5 +1,8 @@ use crate::diagnostic::IntoDiagnosticArg; -use crate::{Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed}; +use crate::{ + Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, + SubdiagnosticMessage, +}; use crate::{Handler, Level, MultiSpan, StashKey}; use rustc_lint_defs::Applicability; @@ -395,7 +398,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// the diagnostic was constructed. However, the label span is *not* considered a /// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is /// primary. - pub fn span_label(&mut self, span: Span, label: impl Into<DiagnosticMessage>) -> &mut Self); + pub fn span_label(&mut self, span: Span, label: impl Into<SubdiagnosticMessage>) -> &mut Self); forward!( /// Labels all the given spans with the provided label. @@ -430,25 +433,29 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { found: DiagnosticStyledString, ) -> &mut Self); - forward!(pub fn note(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self); - forward!(pub fn note_once(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self); + forward!(pub fn note(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self); + forward!(pub fn note_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self); forward!(pub fn span_note( &mut self, sp: impl Into<MultiSpan>, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self); forward!(pub fn span_note_once( &mut self, sp: impl Into<MultiSpan>, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self); - forward!(pub fn warn(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self); - forward!(pub fn span_warn(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> &mut Self); - forward!(pub fn help(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self); + forward!(pub fn warn(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self); + forward!(pub fn span_warn( + &mut self, + sp: impl Into<MultiSpan>, + msg: impl Into<SubdiagnosticMessage>, + ) -> &mut Self); + forward!(pub fn help(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self); forward!(pub fn span_help( &mut self, sp: impl Into<MultiSpan>, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self); forward!(pub fn help_use_latest_edition(&mut self,) -> &mut Self); forward!(pub fn set_is_lint(&mut self,) -> &mut Self); @@ -457,67 +464,67 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { forward!(pub fn multipart_suggestion( &mut self, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self); forward!(pub fn multipart_suggestion_verbose( &mut self, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self); forward!(pub fn tool_only_multipart_suggestion( &mut self, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self); forward!(pub fn span_suggestion( &mut self, sp: Span, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self); forward!(pub fn span_suggestions( &mut self, sp: Span, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestions: impl Iterator<Item = String>, applicability: Applicability, ) -> &mut Self); forward!(pub fn multipart_suggestions( &mut self, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestions: impl Iterator<Item = Vec<(Span, String)>>, applicability: Applicability, ) -> &mut Self); forward!(pub fn span_suggestion_short( &mut self, sp: Span, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self); forward!(pub fn span_suggestion_verbose( &mut self, sp: Span, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self); forward!(pub fn span_suggestion_hidden( &mut self, sp: Span, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self); forward!(pub fn tool_only_span_suggestion( &mut self, sp: Span, - msg: impl Into<DiagnosticMessage>, + msg: impl Into<SubdiagnosticMessage>, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 5b9b65da343..fb02f1d68eb 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -32,7 +32,8 @@ use rustc_data_structures::sync::{self, Lock, Lrc}; use rustc_data_structures::AtomicRef; pub use rustc_error_messages::{ fallback_fluent_bundle, fluent, fluent_bundle, DiagnosticMessage, FluentBundle, - LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, DEFAULT_LOCALE_RESOURCES, + LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage, + DEFAULT_LOCALE_RESOURCES, }; pub use rustc_lint_defs::{pluralize, Applicability}; use rustc_span::source_map::SourceMap; diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index d7daee64d79..95ee0d4a060 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -126,14 +126,14 @@ impl<'a> SessionDiagnosticDerive<'a> { (Some((SessionDiagnosticKind::Error, _)), Some((slug, _))) => { quote! { let mut #diag = #sess.struct_err( - rustc_errors::DiagnosticMessage::fluent(#slug), + rustc_errors::DiagnosticMessage::new(#slug), ); } } (Some((SessionDiagnosticKind::Warn, _)), Some((slug, _))) => { quote! { let mut #diag = #sess.struct_warn( - rustc_errors::DiagnosticMessage::fluent(#slug), + rustc_errors::DiagnosticMessage::new(#slug), ); } } @@ -254,21 +254,6 @@ impl SessionDiagnosticDeriveBuilder { if matches!(name, "help" | "note") && matches!(meta, Meta::Path(_) | Meta::NameValue(_)) { let diag = &self.diag; - let slug = match &self.slug { - Some((slug, _)) => slug.as_str(), - None => throw_span_err!( - span, - &format!( - "`#[{}{}]` must come after `#[error(..)]` or `#[warn(..)]`", - name, - match meta { - Meta::Path(_) => "", - Meta::NameValue(_) => " = ...", - _ => unreachable!(), - } - ) - ), - }; let id = match meta { Meta::Path(..) => quote! { #name }, Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => { @@ -279,7 +264,7 @@ impl SessionDiagnosticDeriveBuilder { let fn_name = proc_macro2::Ident::new(name, attr.span()); return Ok(quote! { - #diag.#fn_name(rustc_errors::DiagnosticMessage::fluent_attr(#slug, #id)); + #diag.#fn_name(rustc_errors::SubdiagnosticMessage::attr(#id)); }); } @@ -525,13 +510,8 @@ impl SessionDiagnosticDeriveBuilder { let method = format_ident!("span_{}", name); - let slug = self - .slug - .as_ref() - .map(|(slug, _)| slug.as_str()) - .unwrap_or_else(|| "missing-slug"); let msg = msg.as_deref().unwrap_or("suggestion"); - let msg = quote! { rustc_errors::DiagnosticMessage::fluent_attr(#slug, #msg) }; + let msg = quote! { rustc_errors::SubdiagnosticMessage::attr(#msg) }; let code = code.unwrap_or_else(|| quote! { String::new() }); Ok(quote! { #diag.#method(#span_field, #msg, #code, #applicability); }) @@ -549,14 +529,11 @@ impl SessionDiagnosticDeriveBuilder { fluent_attr_identifier: &str, ) -> TokenStream { let diag = &self.diag; - - let slug = - self.slug.as_ref().map(|(slug, _)| slug.as_str()).unwrap_or_else(|| "missing-slug"); let fn_name = format_ident!("span_{}", kind); quote! { #diag.#fn_name( #field_binding, - rustc_errors::DiagnosticMessage::fluent_attr(#slug, #fluent_attr_identifier) + rustc_errors::SubdiagnosticMessage::attr(#fluent_attr_identifier) ); } } @@ -565,9 +542,8 @@ impl SessionDiagnosticDeriveBuilder { /// and `fluent_attr_identifier`. fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: &str) -> TokenStream { let diag = &self.diag; - let slug = self.slug.as_ref().map(|(slug, _)| slug.as_str()).unwrap_or("missing-slug"); quote! { - #diag.#kind(rustc_errors::DiagnosticMessage::fluent_attr(#slug, #fluent_attr_identifier)); + #diag.#kind(rustc_errors::SubdiagnosticMessage::attr(#fluent_attr_identifier)); } } diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs index 8523d7fa9f9..42a9bf477a4 100644 --- a/compiler/rustc_macros/src/diagnostics/fluent.rs +++ b/compiler/rustc_macros/src/diagnostics/fluent.rs @@ -11,7 +11,7 @@ use proc_macro::{Diagnostic, Level, Span}; use proc_macro2::TokenStream; use quote::quote; use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, fs::File, io::Read, path::{Path, PathBuf}, @@ -100,6 +100,10 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok let ident_span = res.ident.span().unwrap(); let path_span = res.resource.span().unwrap(); + // Set of Fluent attribute names already output, to avoid duplicate type errors - any given + // constant created for a given attribute is the same. + let mut previous_attrs = HashSet::new(); + let relative_ftl_path = res.resource.value(); let absolute_ftl_path = invocation_relative_path_to_absolute(ident_span, &relative_ftl_path); @@ -199,13 +203,15 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok }); for Attribute { id: Identifier { name: attr_name }, .. } in attributes { - let attr_snake_name = attr_name.replace("-", "_"); - let snake_name = Ident::new(&format!("{snake_name}_{attr_snake_name}"), span); + let snake_name = Ident::new(&attr_name.replace("-", "_"), span); + if !previous_attrs.insert(snake_name.clone()) { + continue; + } + constants.extend(quote! { - pub const #snake_name: crate::DiagnosticMessage = - crate::DiagnosticMessage::FluentIdentifier( - std::borrow::Cow::Borrowed(#name), - Some(std::borrow::Cow::Borrowed(#attr_name)) + pub const #snake_name: crate::SubdiagnosticMessage = + crate::SubdiagnosticMessage::FluentAttr( + std::borrow::Cow::Borrowed(#attr_name) ); }); } diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index df01419c82a..9aeb484bfd5 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -397,7 +397,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { let diag = &self.diag; let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); - let message = quote! { rustc_errors::DiagnosticMessage::fluent(#slug) }; + let message = quote! { rustc_errors::SubdiagnosticMessage::message(#slug) }; let call = if matches!(kind, SubdiagnosticKind::Suggestion(..)) { if let Some(span) = span_field { quote! { #diag.#name(#span, #message, #code, #applicability); } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c9da58aae5c..12302315e90 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -17,10 +17,10 @@ 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, DiagnosticMessage, Handler, MultiSpan, PResult, + fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult, }; +use rustc_errors::{pluralize, struct_span_err, Diagnostic, EmissionGuarantee, ErrorGuaranteed}; use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, Ident}; @@ -658,13 +658,10 @@ impl<'a> Parser<'a> { err.delay_as_bug(); self.struct_span_err( expr.span, - DiagnosticMessage::fluent("parser-struct-literal-body-without-path"), + fluent::parser::struct_literal_body_without_path, ) .multipart_suggestion( - DiagnosticMessage::fluent_attr( - "parser-struct-literal-body-without-path", - "suggestion", - ), + fluent::parser::suggestion, vec