Rollup merge of #100379 - davidtwco:triagebot-diag, r=Mark-Simulacrum
triagebot: add translation-related mention groups - Move some code around so that triagebot can ping relevant parties when translation logic is modified. - Add mention groups to triagebot for translation-related files/folders. - Auto-label pull requests with changes to translation-related files/folders with `A-translation`. r? `@Mark-Simulacrum`
This commit is contained in:
commit
989e4ffc7c
@ -15,7 +15,7 @@ use rustc_data_structures::profiling::TimingGuard;
|
|||||||
use rustc_data_structures::profiling::VerboseTimingGuard;
|
use rustc_data_structures::profiling::VerboseTimingGuard;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_errors::emitter::Emitter;
|
use rustc_errors::emitter::Emitter;
|
||||||
use rustc_errors::{DiagnosticId, FatalError, Handler, Level};
|
use rustc_errors::{translation::Translate, DiagnosticId, FatalError, Handler, Level};
|
||||||
use rustc_fs_util::link_or_copy;
|
use rustc_fs_util::link_or_copy;
|
||||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||||
use rustc_incremental::{
|
use rustc_incremental::{
|
||||||
@ -1740,6 +1740,16 @@ impl SharedEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Translate for SharedEmitter {
|
||||||
|
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||||
|
panic!("shared emitter attempted to translate a diagnostic");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Emitter for SharedEmitter {
|
impl Emitter for SharedEmitter {
|
||||||
fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) {
|
fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) {
|
||||||
let fluent_args = self.to_fluent_args(diag.args());
|
let fluent_args = self.to_fluent_args(diag.args());
|
||||||
@ -1761,14 +1771,6 @@ impl Emitter for SharedEmitter {
|
|||||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
|
||||||
panic!("shared emitter attempted to translate a diagnostic");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SharedEmitterMain {
|
impl SharedEmitterMain {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
use crate::emitter::FileWithAnnotatedLines;
|
use crate::emitter::FileWithAnnotatedLines;
|
||||||
use crate::snippet::Line;
|
use crate::snippet::Line;
|
||||||
|
use crate::translation::Translate;
|
||||||
use crate::{
|
use crate::{
|
||||||
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle,
|
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle,
|
||||||
LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic,
|
LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic,
|
||||||
@ -32,6 +33,16 @@ pub struct AnnotateSnippetEmitterWriter {
|
|||||||
macro_backtrace: bool,
|
macro_backtrace: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Translate for AnnotateSnippetEmitterWriter {
|
||||||
|
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||||
|
self.fluent_bundle.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||||
|
&**self.fallback_bundle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Emitter for AnnotateSnippetEmitterWriter {
|
impl Emitter for AnnotateSnippetEmitterWriter {
|
||||||
/// The entry point for the diagnostics generation
|
/// The entry point for the diagnostics generation
|
||||||
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
|
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
|
||||||
@ -63,14 +74,6 @@ impl Emitter for AnnotateSnippetEmitterWriter {
|
|||||||
self.source_map.as_ref()
|
self.source_map.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
|
||||||
self.fluent_bundle.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
|
||||||
&**self.fallback_bundle
|
|
||||||
}
|
|
||||||
|
|
||||||
fn should_show_explain(&self) -> bool {
|
fn should_show_explain(&self) -> bool {
|
||||||
!self.short_message
|
!self.short_message
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,10 @@ use rustc_span::{FileLines, SourceFile, Span};
|
|||||||
|
|
||||||
use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString};
|
use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString};
|
||||||
use crate::styled_buffer::StyledBuffer;
|
use crate::styled_buffer::StyledBuffer;
|
||||||
|
use crate::translation::Translate;
|
||||||
use crate::{
|
use crate::{
|
||||||
CodeSuggestion, Diagnostic, DiagnosticArg, DiagnosticId, DiagnosticMessage, FluentBundle,
|
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, FluentBundle, Handler,
|
||||||
Handler, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight,
|
LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight, SuggestionStyle,
|
||||||
SuggestionStyle,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use rustc_lint_defs::pluralize;
|
use rustc_lint_defs::pluralize;
|
||||||
@ -200,7 +200,7 @@ impl Margin {
|
|||||||
const ANONYMIZED_LINE_NUM: &str = "LL";
|
const ANONYMIZED_LINE_NUM: &str = "LL";
|
||||||
|
|
||||||
/// Emitter trait for emitting errors.
|
/// Emitter trait for emitting errors.
|
||||||
pub trait Emitter {
|
pub trait Emitter: Translate {
|
||||||
/// Emit a structured diagnostic.
|
/// Emit a structured diagnostic.
|
||||||
fn emit_diagnostic(&mut self, diag: &Diagnostic);
|
fn emit_diagnostic(&mut self, diag: &Diagnostic);
|
||||||
|
|
||||||
@ -231,102 +231,6 @@ pub trait Emitter {
|
|||||||
|
|
||||||
fn source_map(&self) -> Option<&Lrc<SourceMap>>;
|
fn source_map(&self) -> Option<&Lrc<SourceMap>>;
|
||||||
|
|
||||||
/// Return `FluentBundle` with localized diagnostics for the locale requested by the user. If no
|
|
||||||
/// language was requested by the user then this will be `None` and `fallback_fluent_bundle`
|
|
||||||
/// should be used.
|
|
||||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>>;
|
|
||||||
|
|
||||||
/// Return `FluentBundle` with localized diagnostics for the default locale of the compiler.
|
|
||||||
/// Used when the user has not requested a specific language or when a localized diagnostic is
|
|
||||||
/// unavailable for the requested locale.
|
|
||||||
fn fallback_fluent_bundle(&self) -> &FluentBundle;
|
|
||||||
|
|
||||||
/// Convert diagnostic arguments (a rustc internal type that exists to implement
|
|
||||||
/// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation.
|
|
||||||
///
|
|
||||||
/// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then
|
|
||||||
/// passed around as a reference thereafter.
|
|
||||||
fn to_fluent_args<'arg>(&self, args: &[DiagnosticArg<'arg>]) -> FluentArgs<'arg> {
|
|
||||||
FromIterator::from_iter(args.to_vec().drain(..))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert `DiagnosticMessage`s to a string, performing translation if necessary.
|
|
||||||
fn translate_messages(
|
|
||||||
&self,
|
|
||||||
messages: &[(DiagnosticMessage, Style)],
|
|
||||||
args: &FluentArgs<'_>,
|
|
||||||
) -> Cow<'_, str> {
|
|
||||||
Cow::Owned(
|
|
||||||
messages.iter().map(|(m, _)| self.translate_message(m, args)).collect::<String>(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert a `DiagnosticMessage` to a string, performing translation if necessary.
|
|
||||||
fn translate_message<'a>(
|
|
||||||
&'a self,
|
|
||||||
message: &'a DiagnosticMessage,
|
|
||||||
args: &'a FluentArgs<'_>,
|
|
||||||
) -> Cow<'_, str> {
|
|
||||||
trace!(?message, ?args);
|
|
||||||
let (identifier, attr) = match message {
|
|
||||||
DiagnosticMessage::Str(msg) => return Cow::Borrowed(&msg),
|
|
||||||
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
|
|
||||||
};
|
|
||||||
|
|
||||||
let translate_with_bundle = |bundle: &'a FluentBundle| -> Option<(Cow<'_, str>, Vec<_>)> {
|
|
||||||
let message = bundle.get_message(&identifier)?;
|
|
||||||
let value = match attr {
|
|
||||||
Some(attr) => message.get_attribute(attr)?.value(),
|
|
||||||
None => message.value()?,
|
|
||||||
};
|
|
||||||
debug!(?message, ?value);
|
|
||||||
|
|
||||||
let mut errs = vec![];
|
|
||||||
let translated = bundle.format_pattern(value, Some(&args), &mut errs);
|
|
||||||
debug!(?translated, ?errs);
|
|
||||||
Some((translated, errs))
|
|
||||||
};
|
|
||||||
|
|
||||||
self.fluent_bundle()
|
|
||||||
.and_then(|bundle| translate_with_bundle(bundle))
|
|
||||||
// If `translate_with_bundle` returns `None` with the primary bundle, this is likely
|
|
||||||
// just that the primary bundle doesn't contain the message being translated, so
|
|
||||||
// proceed to the fallback bundle.
|
|
||||||
//
|
|
||||||
// However, when errors are produced from translation, then that means the translation
|
|
||||||
// is broken (e.g. `{$foo}` exists in a translation but `foo` isn't provided).
|
|
||||||
//
|
|
||||||
// In debug builds, assert so that compiler devs can spot the broken translation and
|
|
||||||
// fix it..
|
|
||||||
.inspect(|(_, errs)| {
|
|
||||||
debug_assert!(
|
|
||||||
errs.is_empty(),
|
|
||||||
"identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}",
|
|
||||||
identifier,
|
|
||||||
attr,
|
|
||||||
args,
|
|
||||||
errs
|
|
||||||
);
|
|
||||||
})
|
|
||||||
// ..otherwise, for end users, an error about this wouldn't be useful or actionable, so
|
|
||||||
// just hide it and try with the fallback bundle.
|
|
||||||
.filter(|(_, errs)| errs.is_empty())
|
|
||||||
.or_else(|| translate_with_bundle(self.fallback_fluent_bundle()))
|
|
||||||
.map(|(translated, errs)| {
|
|
||||||
// Always bail out for errors with the fallback bundle.
|
|
||||||
assert!(
|
|
||||||
errs.is_empty(),
|
|
||||||
"identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}",
|
|
||||||
identifier,
|
|
||||||
attr,
|
|
||||||
args,
|
|
||||||
errs
|
|
||||||
);
|
|
||||||
translated
|
|
||||||
})
|
|
||||||
.expect("failed to find message in primary or fallback fluent bundles")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Formats the substitutions of the primary_span
|
/// Formats the substitutions of the primary_span
|
||||||
///
|
///
|
||||||
/// There are a lot of conditions to this method, but in short:
|
/// There are a lot of conditions to this method, but in short:
|
||||||
@ -616,11 +520,7 @@ pub trait Emitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Emitter for EmitterWriter {
|
impl Translate for EmitterWriter {
|
||||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
|
||||||
self.sm.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||||
self.fluent_bundle.as_ref()
|
self.fluent_bundle.as_ref()
|
||||||
}
|
}
|
||||||
@ -628,6 +528,12 @@ impl Emitter for EmitterWriter {
|
|||||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||||
&**self.fallback_bundle
|
&**self.fallback_bundle
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Emitter for EmitterWriter {
|
||||||
|
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||||
|
self.sm.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
|
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
|
||||||
let fluent_args = self.to_fluent_args(diag.args());
|
let fluent_args = self.to_fluent_args(diag.args());
|
||||||
@ -672,11 +578,7 @@ pub struct SilentEmitter {
|
|||||||
pub fatal_note: Option<String>,
|
pub fatal_note: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Emitter for SilentEmitter {
|
impl Translate for SilentEmitter {
|
||||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -684,6 +586,12 @@ impl Emitter for SilentEmitter {
|
|||||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||||
panic!("silent emitter attempted to translate message")
|
panic!("silent emitter attempted to translate message")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Emitter for SilentEmitter {
|
||||||
|
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_diagnostic(&mut self, d: &Diagnostic) {
|
fn emit_diagnostic(&mut self, d: &Diagnostic) {
|
||||||
if d.level == Level::Fatal {
|
if d.level == Level::Fatal {
|
||||||
|
@ -13,6 +13,7 @@ use rustc_span::source_map::{FilePathMapping, SourceMap};
|
|||||||
|
|
||||||
use crate::emitter::{Emitter, HumanReadableErrorType};
|
use crate::emitter::{Emitter, HumanReadableErrorType};
|
||||||
use crate::registry::Registry;
|
use crate::registry::Registry;
|
||||||
|
use crate::translation::Translate;
|
||||||
use crate::DiagnosticId;
|
use crate::DiagnosticId;
|
||||||
use crate::{
|
use crate::{
|
||||||
CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic,
|
CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic,
|
||||||
@ -122,6 +123,16 @@ impl JsonEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Translate for JsonEmitter {
|
||||||
|
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||||
|
self.fluent_bundle.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||||
|
&**self.fallback_bundle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Emitter for JsonEmitter {
|
impl Emitter for JsonEmitter {
|
||||||
fn emit_diagnostic(&mut self, diag: &crate::Diagnostic) {
|
fn emit_diagnostic(&mut self, diag: &crate::Diagnostic) {
|
||||||
let data = Diagnostic::from_errors_diagnostic(diag, self);
|
let data = Diagnostic::from_errors_diagnostic(diag, self);
|
||||||
@ -189,14 +200,6 @@ impl Emitter for JsonEmitter {
|
|||||||
Some(&self.sm)
|
Some(&self.sm)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
|
||||||
self.fluent_bundle.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
|
||||||
&**self.fallback_bundle
|
|
||||||
}
|
|
||||||
|
|
||||||
fn should_show_explain(&self) -> bool {
|
fn should_show_explain(&self) -> bool {
|
||||||
!matches!(self.json_rendered, HumanReadableErrorType::Short(_))
|
!matches!(self.json_rendered, HumanReadableErrorType::Short(_))
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,7 @@ mod lock;
|
|||||||
pub mod registry;
|
pub mod registry;
|
||||||
mod snippet;
|
mod snippet;
|
||||||
mod styled_buffer;
|
mod styled_buffer;
|
||||||
|
pub mod translation;
|
||||||
|
|
||||||
pub use snippet::Style;
|
pub use snippet::Style;
|
||||||
|
|
||||||
|
103
compiler/rustc_errors/src/translation.rs
Normal file
103
compiler/rustc_errors/src/translation.rs
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
use crate::snippet::Style;
|
||||||
|
use crate::{DiagnosticArg, DiagnosticMessage, FluentBundle};
|
||||||
|
use rustc_data_structures::sync::Lrc;
|
||||||
|
use rustc_error_messages::FluentArgs;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
pub trait Translate {
|
||||||
|
/// Return `FluentBundle` with localized diagnostics for the locale requested by the user. If no
|
||||||
|
/// language was requested by the user then this will be `None` and `fallback_fluent_bundle`
|
||||||
|
/// should be used.
|
||||||
|
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>>;
|
||||||
|
|
||||||
|
/// Return `FluentBundle` with localized diagnostics for the default locale of the compiler.
|
||||||
|
/// Used when the user has not requested a specific language or when a localized diagnostic is
|
||||||
|
/// unavailable for the requested locale.
|
||||||
|
fn fallback_fluent_bundle(&self) -> &FluentBundle;
|
||||||
|
|
||||||
|
/// Convert diagnostic arguments (a rustc internal type that exists to implement
|
||||||
|
/// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation.
|
||||||
|
///
|
||||||
|
/// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then
|
||||||
|
/// passed around as a reference thereafter.
|
||||||
|
fn to_fluent_args<'arg>(&self, args: &[DiagnosticArg<'arg>]) -> FluentArgs<'arg> {
|
||||||
|
FromIterator::from_iter(args.to_vec().drain(..))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert `DiagnosticMessage`s to a string, performing translation if necessary.
|
||||||
|
fn translate_messages(
|
||||||
|
&self,
|
||||||
|
messages: &[(DiagnosticMessage, Style)],
|
||||||
|
args: &FluentArgs<'_>,
|
||||||
|
) -> Cow<'_, str> {
|
||||||
|
Cow::Owned(
|
||||||
|
messages.iter().map(|(m, _)| self.translate_message(m, args)).collect::<String>(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a `DiagnosticMessage` to a string, performing translation if necessary.
|
||||||
|
fn translate_message<'a>(
|
||||||
|
&'a self,
|
||||||
|
message: &'a DiagnosticMessage,
|
||||||
|
args: &'a FluentArgs<'_>,
|
||||||
|
) -> Cow<'_, str> {
|
||||||
|
trace!(?message, ?args);
|
||||||
|
let (identifier, attr) = match message {
|
||||||
|
DiagnosticMessage::Str(msg) => return Cow::Borrowed(&msg),
|
||||||
|
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
|
||||||
|
};
|
||||||
|
|
||||||
|
let translate_with_bundle = |bundle: &'a FluentBundle| -> Option<(Cow<'_, str>, Vec<_>)> {
|
||||||
|
let message = bundle.get_message(&identifier)?;
|
||||||
|
let value = match attr {
|
||||||
|
Some(attr) => message.get_attribute(attr)?.value(),
|
||||||
|
None => message.value()?,
|
||||||
|
};
|
||||||
|
debug!(?message, ?value);
|
||||||
|
|
||||||
|
let mut errs = vec![];
|
||||||
|
let translated = bundle.format_pattern(value, Some(&args), &mut errs);
|
||||||
|
debug!(?translated, ?errs);
|
||||||
|
Some((translated, errs))
|
||||||
|
};
|
||||||
|
|
||||||
|
self.fluent_bundle()
|
||||||
|
.and_then(|bundle| translate_with_bundle(bundle))
|
||||||
|
// If `translate_with_bundle` returns `None` with the primary bundle, this is likely
|
||||||
|
// just that the primary bundle doesn't contain the message being translated, so
|
||||||
|
// proceed to the fallback bundle.
|
||||||
|
//
|
||||||
|
// However, when errors are produced from translation, then that means the translation
|
||||||
|
// is broken (e.g. `{$foo}` exists in a translation but `foo` isn't provided).
|
||||||
|
//
|
||||||
|
// In debug builds, assert so that compiler devs can spot the broken translation and
|
||||||
|
// fix it..
|
||||||
|
.inspect(|(_, errs)| {
|
||||||
|
debug_assert!(
|
||||||
|
errs.is_empty(),
|
||||||
|
"identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}",
|
||||||
|
identifier,
|
||||||
|
attr,
|
||||||
|
args,
|
||||||
|
errs
|
||||||
|
);
|
||||||
|
})
|
||||||
|
// ..otherwise, for end users, an error about this wouldn't be useful or actionable, so
|
||||||
|
// just hide it and try with the fallback bundle.
|
||||||
|
.filter(|(_, errs)| errs.is_empty())
|
||||||
|
.or_else(|| translate_with_bundle(self.fallback_fluent_bundle()))
|
||||||
|
.map(|(translated, errs)| {
|
||||||
|
// Always bail out for errors with the fallback bundle.
|
||||||
|
assert!(
|
||||||
|
errs.is_empty(),
|
||||||
|
"identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}",
|
||||||
|
identifier,
|
||||||
|
attr,
|
||||||
|
args,
|
||||||
|
errs
|
||||||
|
);
|
||||||
|
translated
|
||||||
|
})
|
||||||
|
.expect("failed to find message in primary or fallback fluent bundles")
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,8 @@
|
|||||||
//! Validates syntax inside Rust code blocks (\`\`\`rust).
|
//! Validates syntax inside Rust code blocks (\`\`\`rust).
|
||||||
use rustc_data_structures::sync::{Lock, Lrc};
|
use rustc_data_structures::sync::{Lock, Lrc};
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
emitter::Emitter, Applicability, Diagnostic, Handler, LazyFallbackBundle, LintDiagnosticBuilder,
|
emitter::Emitter, translation::Translate, Applicability, Diagnostic, Handler,
|
||||||
|
LazyFallbackBundle, LintDiagnosticBuilder,
|
||||||
};
|
};
|
||||||
use rustc_parse::parse_stream_from_source_str;
|
use rustc_parse::parse_stream_from_source_str;
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
@ -181,6 +182,16 @@ struct BufferEmitter {
|
|||||||
fallback_bundle: LazyFallbackBundle,
|
fallback_bundle: LazyFallbackBundle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Translate for BufferEmitter {
|
||||||
|
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||||
|
&**self.fallback_bundle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Emitter for BufferEmitter {
|
impl Emitter for BufferEmitter {
|
||||||
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
|
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
|
||||||
let mut buffer = self.buffer.borrow_mut();
|
let mut buffer = self.buffer.borrow_mut();
|
||||||
@ -194,12 +205,4 @@ impl Emitter for BufferEmitter {
|
|||||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
|
||||||
&**self.fallback_bundle
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
|||||||
|
|
||||||
use rustc_data_structures::sync::{Lrc, Send};
|
use rustc_data_structures::sync::{Lrc, Send};
|
||||||
use rustc_errors::emitter::{Emitter, EmitterWriter};
|
use rustc_errors::emitter::{Emitter, EmitterWriter};
|
||||||
|
use rustc_errors::translation::Translate;
|
||||||
use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel};
|
use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel};
|
||||||
use rustc_session::parse::ParseSess as RawParseSess;
|
use rustc_session::parse::ParseSess as RawParseSess;
|
||||||
use rustc_span::{
|
use rustc_span::{
|
||||||
@ -28,17 +29,22 @@ pub(crate) struct ParseSess {
|
|||||||
/// Emitter which discards every error.
|
/// Emitter which discards every error.
|
||||||
struct SilentEmitter;
|
struct SilentEmitter;
|
||||||
|
|
||||||
|
impl Translate for SilentEmitter {
|
||||||
|
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||||
|
panic!("silent emitter attempted to translate a diagnostic");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Emitter for SilentEmitter {
|
impl Emitter for SilentEmitter {
|
||||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_diagnostic(&mut self, _db: &Diagnostic) {}
|
fn emit_diagnostic(&mut self, _db: &Diagnostic) {}
|
||||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
|
||||||
panic!("silent emitter attempted to translate a diagnostic");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn silent_emitter() -> Box<dyn Emitter + Send> {
|
fn silent_emitter() -> Box<dyn Emitter + Send> {
|
||||||
@ -62,10 +68,21 @@ impl SilentOnIgnoredFilesEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Translate for SilentOnIgnoredFilesEmitter {
|
||||||
|
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||||
|
self.emitter.fluent_bundle()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||||
|
self.emitter.fallback_fluent_bundle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Emitter for SilentOnIgnoredFilesEmitter {
|
impl Emitter for SilentOnIgnoredFilesEmitter {
|
||||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_diagnostic(&mut self, db: &Diagnostic) {
|
fn emit_diagnostic(&mut self, db: &Diagnostic) {
|
||||||
if db.level() == DiagnosticLevel::Fatal {
|
if db.level() == DiagnosticLevel::Fatal {
|
||||||
return self.handle_non_ignoreable_error(db);
|
return self.handle_non_ignoreable_error(db);
|
||||||
@ -88,14 +105,6 @@ impl Emitter for SilentOnIgnoredFilesEmitter {
|
|||||||
}
|
}
|
||||||
self.handle_non_ignoreable_error(db);
|
self.handle_non_ignoreable_error(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
|
||||||
self.emitter.fluent_bundle()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
|
||||||
self.emitter.fallback_fluent_bundle()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_handler(
|
fn default_handler(
|
||||||
@ -340,19 +349,24 @@ mod tests {
|
|||||||
num_emitted_errors: Lrc<AtomicU32>,
|
num_emitted_errors: Lrc<AtomicU32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Translate for TestEmitter {
|
||||||
|
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||||
|
panic!("test emitter attempted to translate a diagnostic");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Emitter for TestEmitter {
|
impl Emitter for TestEmitter {
|
||||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_diagnostic(&mut self, _db: &Diagnostic) {
|
fn emit_diagnostic(&mut self, _db: &Diagnostic) {
|
||||||
self.num_emitted_errors.fetch_add(1, Ordering::Release);
|
self.num_emitted_errors.fetch_add(1, Ordering::Release);
|
||||||
}
|
}
|
||||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
|
||||||
panic!("test emitter attempted to translate a diagnostic");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_diagnostic(level: DiagnosticLevel, span: Option<MultiSpan>) -> Diagnostic {
|
fn build_diagnostic(level: DiagnosticLevel, span: Option<MultiSpan>) -> Diagnostic {
|
||||||
|
@ -178,6 +178,13 @@ trigger_files = [
|
|||||||
"src/tools/bump-stage0",
|
"src/tools/bump-stage0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[autolabel."A-translation"]
|
||||||
|
trigger_files = [
|
||||||
|
"compiler/rustc_error_messages",
|
||||||
|
"compiler/rustc_errors/src/translation.rs",
|
||||||
|
"compiler/rustc_macros/src/diagnostics"
|
||||||
|
]
|
||||||
|
|
||||||
[notify-zulip."I-prioritize"]
|
[notify-zulip."I-prioritize"]
|
||||||
zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
|
zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
|
||||||
topic = "#{number} {title}"
|
topic = "#{number} {title}"
|
||||||
@ -342,3 +349,15 @@ cc = ["@rust-lang/rustfmt"]
|
|||||||
[mentions."compiler/rustc_middle/src/mir/syntax.rs"]
|
[mentions."compiler/rustc_middle/src/mir/syntax.rs"]
|
||||||
message = "This PR changes MIR"
|
message = "This PR changes MIR"
|
||||||
cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco", "@celinval", "@vakaras"]
|
cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco", "@celinval", "@vakaras"]
|
||||||
|
|
||||||
|
[mentions."compiler/rustc_error_messages"]
|
||||||
|
message = "`rustc_error_messages` was changed"
|
||||||
|
cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank"]
|
||||||
|
|
||||||
|
[mentions."compiler/rustc_errors/src/translation.rs"]
|
||||||
|
message = "`rustc_errors::translation` was changed"
|
||||||
|
cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank"]
|
||||||
|
|
||||||
|
[mentions."compiler/rustc_macros/src/diagnostics"]
|
||||||
|
message = "`rustc_macros::diagnostics` was changed"
|
||||||
|
cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank"]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user