mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #121129 - nnethercote:codegen-Diags, r=estebank
Improve codegen diagnostic handling Clarify the workings of the temporary `Diagnostic` type used to send diagnostics from codegen threads to the main thread. r? `@estebank`
This commit is contained in:
commit
f70f19fef4
@ -103,8 +103,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_
|
|||||||
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
|
||||||
let diag: DiagnosticBuilder<'_, G> = self.0.into_diagnostic(dcx, level);
|
let diag: DiagnosticBuilder<'_, G> = self.0.into_diagnostic(dcx, level);
|
||||||
let (message, _) = diag.messages.first().expect("`LlvmError` with no message");
|
let (message, _) = diag.messages.first().expect("`LlvmError` with no message");
|
||||||
let message = dcx.eagerly_translate_to_string(message.clone(), diag.args());
|
let message = dcx.eagerly_translate_to_string(message.clone(), diag.args.iter());
|
||||||
|
|
||||||
DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config)
|
DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config)
|
||||||
.with_arg("error", message)
|
.with_arg("error", message)
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@ use rustc_data_structures::sync::Lrc;
|
|||||||
use rustc_errors::emitter::Emitter;
|
use rustc_errors::emitter::Emitter;
|
||||||
use rustc_errors::translation::Translate;
|
use rustc_errors::translation::Translate;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
DiagCtxt, DiagnosticArgName, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, ErrCode,
|
DiagCtxt, DiagnosticArgMap, DiagnosticBuilder, DiagnosticMessage, ErrCode, FatalError,
|
||||||
FatalError, FluentBundle, Level, Style,
|
FluentBundle, Level, MultiSpan, Style,
|
||||||
};
|
};
|
||||||
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};
|
||||||
@ -999,11 +999,29 @@ pub(crate) enum Message<B: WriteBackendMethods> {
|
|||||||
/// process another codegen unit.
|
/// process another codegen unit.
|
||||||
pub struct CguMessage;
|
pub struct CguMessage;
|
||||||
|
|
||||||
|
// A cut-down version of `rustc_errors::Diagnostic` that impls `Send`, which
|
||||||
|
// can be used to send diagnostics from codegen threads to the main thread.
|
||||||
|
// It's missing the following fields from `rustc_errors::Diagnostic`.
|
||||||
|
// - `span`: it doesn't impl `Send`.
|
||||||
|
// - `suggestions`: it doesn't impl `Send`, and isn't used for codegen
|
||||||
|
// diagnostics.
|
||||||
|
// - `sort_span`: it doesn't impl `Send`.
|
||||||
|
// - `is_lint`: lints aren't relevant during codegen.
|
||||||
|
// - `emitted_at`: not used for codegen diagnostics.
|
||||||
struct Diagnostic {
|
struct Diagnostic {
|
||||||
msgs: Vec<(DiagnosticMessage, Style)>,
|
level: Level,
|
||||||
args: FxIndexMap<DiagnosticArgName, DiagnosticArgValue>,
|
messages: Vec<(DiagnosticMessage, Style)>,
|
||||||
code: Option<ErrCode>,
|
code: Option<ErrCode>,
|
||||||
lvl: Level,
|
children: Vec<Subdiagnostic>,
|
||||||
|
args: DiagnosticArgMap,
|
||||||
|
}
|
||||||
|
|
||||||
|
// A cut-down version of `rustc_errors::SubDiagnostic` that impls `Send`. It's
|
||||||
|
// missing the following fields from `rustc_errors::SubDiagnostic`.
|
||||||
|
// - `span`: it doesn't impl `Send`.
|
||||||
|
pub struct Subdiagnostic {
|
||||||
|
level: Level,
|
||||||
|
messages: Vec<(DiagnosticMessage, Style)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy, Debug)]
|
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||||
@ -1766,7 +1784,6 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
|
|||||||
enum SharedEmitterMessage {
|
enum SharedEmitterMessage {
|
||||||
Diagnostic(Diagnostic),
|
Diagnostic(Diagnostic),
|
||||||
InlineAsmError(u32, String, Level, Option<(String, Vec<InnerSpan>)>),
|
InlineAsmError(u32, String, Level, Option<(String, Vec<InnerSpan>)>),
|
||||||
AbortIfErrors,
|
|
||||||
Fatal(String),
|
Fatal(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1812,24 +1829,29 @@ impl Translate for SharedEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Emitter for SharedEmitter {
|
impl Emitter for SharedEmitter {
|
||||||
fn emit_diagnostic(&mut self, diag: rustc_errors::Diagnostic) {
|
fn emit_diagnostic(&mut self, mut diag: rustc_errors::Diagnostic) {
|
||||||
let args: FxIndexMap<DiagnosticArgName, DiagnosticArgValue> =
|
// Check that we aren't missing anything interesting when converting to
|
||||||
diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect();
|
// the cut-down local `Diagnostic`.
|
||||||
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
|
assert_eq!(diag.span, MultiSpan::new());
|
||||||
msgs: diag.messages.clone(),
|
assert_eq!(diag.suggestions, Ok(vec![]));
|
||||||
args: args.clone(),
|
assert_eq!(diag.sort_span, rustc_span::DUMMY_SP);
|
||||||
|
assert_eq!(diag.is_lint, None);
|
||||||
|
// No sensible check for `diag.emitted_at`.
|
||||||
|
|
||||||
|
let args = mem::replace(&mut diag.args, DiagnosticArgMap::default());
|
||||||
|
drop(
|
||||||
|
self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
|
||||||
|
level: diag.level(),
|
||||||
|
messages: diag.messages,
|
||||||
code: diag.code,
|
code: diag.code,
|
||||||
lvl: diag.level(),
|
children: diag
|
||||||
})));
|
.children
|
||||||
for child in &diag.children {
|
.into_iter()
|
||||||
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
|
.map(|child| Subdiagnostic { level: child.level, messages: child.messages })
|
||||||
msgs: child.messages.clone(),
|
.collect(),
|
||||||
args: args.clone(),
|
args,
|
||||||
code: None,
|
})),
|
||||||
lvl: child.level,
|
);
|
||||||
})));
|
|
||||||
}
|
|
||||||
drop(self.sender.send(SharedEmitterMessage::AbortIfErrors));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||||
@ -1854,11 +1876,24 @@ impl SharedEmitterMain {
|
|||||||
|
|
||||||
match message {
|
match message {
|
||||||
Ok(SharedEmitterMessage::Diagnostic(diag)) => {
|
Ok(SharedEmitterMessage::Diagnostic(diag)) => {
|
||||||
|
// The diagnostic has been received on the main thread.
|
||||||
|
// Convert it back to a full `Diagnostic` and emit.
|
||||||
let dcx = sess.dcx();
|
let dcx = sess.dcx();
|
||||||
let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msgs);
|
let mut d =
|
||||||
|
rustc_errors::Diagnostic::new_with_messages(diag.level, diag.messages);
|
||||||
d.code = diag.code; // may be `None`, that's ok
|
d.code = diag.code; // may be `None`, that's ok
|
||||||
d.replace_args(diag.args);
|
d.children = diag
|
||||||
|
.children
|
||||||
|
.into_iter()
|
||||||
|
.map(|sub| rustc_errors::SubDiagnostic {
|
||||||
|
level: sub.level,
|
||||||
|
messages: sub.messages,
|
||||||
|
span: MultiSpan::new(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
d.args = diag.args;
|
||||||
dcx.emit_diagnostic(d);
|
dcx.emit_diagnostic(d);
|
||||||
|
sess.dcx().abort_if_errors();
|
||||||
}
|
}
|
||||||
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
|
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
|
||||||
assert!(matches!(level, Level::Error | Level::Warning | Level::Note));
|
assert!(matches!(level, Level::Error | Level::Warning | Level::Note));
|
||||||
@ -1891,9 +1926,6 @@ impl SharedEmitterMain {
|
|||||||
|
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
Ok(SharedEmitterMessage::AbortIfErrors) => {
|
|
||||||
sess.dcx().abort_if_errors();
|
|
||||||
}
|
|
||||||
Ok(SharedEmitterMessage::Fatal(msg)) => {
|
Ok(SharedEmitterMessage::Fatal(msg)) => {
|
||||||
sess.dcx().fatal(msg);
|
sess.dcx().fatal(msg);
|
||||||
}
|
}
|
||||||
|
@ -437,7 +437,7 @@ pub trait ReportErrorExt {
|
|||||||
let mut diag = dcx.struct_allow(DiagnosticMessage::Str(String::new().into()));
|
let mut diag = dcx.struct_allow(DiagnosticMessage::Str(String::new().into()));
|
||||||
let message = self.diagnostic_message();
|
let message = self.diagnostic_message();
|
||||||
self.add_args(&mut diag);
|
self.add_args(&mut diag);
|
||||||
let s = dcx.eagerly_translate_to_string(message, diag.args());
|
let s = dcx.eagerly_translate_to_string(message, diag.args.iter());
|
||||||
diag.cancel();
|
diag.cancel();
|
||||||
s
|
s
|
||||||
})
|
})
|
||||||
@ -864,7 +864,7 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
|
|||||||
let dummy_level = Level::Bug;
|
let dummy_level = Level::Bug;
|
||||||
let dummy_diag: DiagnosticBuilder<'_, ()> =
|
let dummy_diag: DiagnosticBuilder<'_, ()> =
|
||||||
e.into_diagnostic().into_diagnostic(diag.dcx, dummy_level);
|
e.into_diagnostic().into_diagnostic(diag.dcx, dummy_level);
|
||||||
for (name, val) in dummy_diag.args() {
|
for (name, val) in dummy_diag.args.iter() {
|
||||||
diag.arg(name.clone(), val.clone());
|
diag.arg(name.clone(), val.clone());
|
||||||
}
|
}
|
||||||
dummy_diag.cancel();
|
dummy_diag.cancel();
|
||||||
|
@ -446,7 +446,7 @@ pub fn format_interp_error<'tcx>(dcx: &DiagCtxt, e: InterpErrorInfo<'tcx>) -> St
|
|||||||
let mut diag = dcx.struct_allow("");
|
let mut diag = dcx.struct_allow("");
|
||||||
let msg = e.diagnostic_message();
|
let msg = e.diagnostic_message();
|
||||||
e.add_args(&mut diag);
|
e.add_args(&mut diag);
|
||||||
let s = dcx.eagerly_translate_to_string(msg, diag.args());
|
let s = dcx.eagerly_translate_to_string(msg, diag.args.iter());
|
||||||
diag.cancel();
|
diag.cancel();
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ impl Translate for AnnotateSnippetEmitter {
|
|||||||
impl Emitter for AnnotateSnippetEmitter {
|
impl Emitter for AnnotateSnippetEmitter {
|
||||||
/// The entry point for the diagnostics generation
|
/// The entry point for the diagnostics generation
|
||||||
fn emit_diagnostic(&mut self, mut diag: Diagnostic) {
|
fn emit_diagnostic(&mut self, mut diag: Diagnostic) {
|
||||||
let fluent_args = to_fluent_args(diag.args());
|
let fluent_args = to_fluent_args(diag.args.iter());
|
||||||
|
|
||||||
let mut suggestions = diag.suggestions.unwrap_or(vec![]);
|
let mut suggestions = diag.suggestions.unwrap_or(vec![]);
|
||||||
self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args);
|
self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args);
|
||||||
|
@ -43,6 +43,8 @@ pub enum DiagnosticArgValue {
|
|||||||
StrListSepByAnd(Vec<Cow<'static, str>>),
|
StrListSepByAnd(Vec<Cow<'static, str>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type DiagnosticArgMap = FxIndexMap<DiagnosticArgName, DiagnosticArgValue>;
|
||||||
|
|
||||||
/// Trait for types that `DiagnosticBuilder::emit` can return as a "guarantee"
|
/// Trait for types that `DiagnosticBuilder::emit` can return as a "guarantee"
|
||||||
/// (or "proof") token that the emission happened.
|
/// (or "proof") token that the emission happened.
|
||||||
pub trait EmissionGuarantee: Sized {
|
pub trait EmissionGuarantee: Sized {
|
||||||
@ -275,7 +277,7 @@ pub struct Diagnostic {
|
|||||||
pub span: MultiSpan,
|
pub span: MultiSpan,
|
||||||
pub children: Vec<SubDiagnostic>,
|
pub children: Vec<SubDiagnostic>,
|
||||||
pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
|
pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
|
||||||
args: FxIndexMap<DiagnosticArgName, DiagnosticArgValue>,
|
pub args: DiagnosticArgMap,
|
||||||
|
|
||||||
/// This is not used for highlighting or rendering any error message. Rather, it can be used
|
/// This is not used for highlighting or rendering any error message. Rather, it can be used
|
||||||
/// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of
|
/// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of
|
||||||
@ -403,14 +405,6 @@ impl Diagnostic {
|
|||||||
self.args.insert(name.into(), arg.into_diagnostic_arg());
|
self.args.insert(name.into(), arg.into_diagnostic_arg());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn args(&self) -> impl Iterator<Item = DiagnosticArg<'_>> {
|
|
||||||
self.args.iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn replace_args(&mut self, args: FxIndexMap<DiagnosticArgName, DiagnosticArgValue>) {
|
|
||||||
self.args = args;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fields used for Hash, and PartialEq trait.
|
/// Fields used for Hash, and PartialEq trait.
|
||||||
fn keys(
|
fn keys(
|
||||||
&self,
|
&self,
|
||||||
@ -431,7 +425,7 @@ impl Diagnostic {
|
|||||||
&self.span,
|
&self.span,
|
||||||
&self.children,
|
&self.children,
|
||||||
&self.suggestions,
|
&self.suggestions,
|
||||||
self.args().collect(),
|
self.args.iter().collect(),
|
||||||
// omit self.sort_span
|
// omit self.sort_span
|
||||||
&self.is_lint,
|
&self.is_lint,
|
||||||
// omit self.emitted_at
|
// omit self.emitted_at
|
||||||
@ -1165,7 +1159,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
|||||||
subdiagnostic: impl AddToDiagnostic,
|
subdiagnostic: impl AddToDiagnostic,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
subdiagnostic.add_to_diagnostic_with(self, |diag, msg| {
|
subdiagnostic.add_to_diagnostic_with(self, |diag, msg| {
|
||||||
let args = diag.args();
|
let args = diag.args.iter();
|
||||||
let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
|
let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
|
||||||
dcx.eagerly_translate(msg, args)
|
dcx.eagerly_translate(msg, args)
|
||||||
});
|
});
|
||||||
|
@ -519,7 +519,7 @@ impl Emitter for HumanEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn emit_diagnostic(&mut self, mut diag: Diagnostic) {
|
fn emit_diagnostic(&mut self, mut diag: Diagnostic) {
|
||||||
let fluent_args = to_fluent_args(diag.args());
|
let fluent_args = to_fluent_args(diag.args.iter());
|
||||||
|
|
||||||
let mut suggestions = diag.suggestions.unwrap_or(vec![]);
|
let mut suggestions = diag.suggestions.unwrap_or(vec![]);
|
||||||
self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args);
|
self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args);
|
||||||
|
@ -341,7 +341,7 @@ struct UnusedExterns<'a, 'b, 'c> {
|
|||||||
|
|
||||||
impl Diagnostic {
|
impl Diagnostic {
|
||||||
fn from_errors_diagnostic(diag: crate::Diagnostic, je: &JsonEmitter) -> Diagnostic {
|
fn from_errors_diagnostic(diag: crate::Diagnostic, je: &JsonEmitter) -> Diagnostic {
|
||||||
let args = to_fluent_args(diag.args());
|
let args = to_fluent_args(diag.args.iter());
|
||||||
let sugg = diag.suggestions.iter().flatten().map(|sugg| {
|
let sugg = diag.suggestions.iter().flatten().map(|sugg| {
|
||||||
let translated_message =
|
let translated_message =
|
||||||
je.translate_message(&sugg.msg, &args).map_err(Report::new).unwrap();
|
je.translate_message(&sugg.msg, &args).map_err(Report::new).unwrap();
|
||||||
|
@ -37,9 +37,10 @@ extern crate self as rustc_errors;
|
|||||||
|
|
||||||
pub use codes::*;
|
pub use codes::*;
|
||||||
pub use diagnostic::{
|
pub use diagnostic::{
|
||||||
AddToDiagnostic, BugAbort, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgName,
|
AddToDiagnostic, BugAbort, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgMap,
|
||||||
DiagnosticArgValue, DiagnosticBuilder, DiagnosticStyledString, EmissionGuarantee, FatalAbort,
|
DiagnosticArgName, DiagnosticArgValue, DiagnosticBuilder, DiagnosticStyledString,
|
||||||
IntoDiagnostic, IntoDiagnosticArg, StringPart, SubDiagnostic, SubdiagnosticMessageOp,
|
EmissionGuarantee, FatalAbort, IntoDiagnostic, IntoDiagnosticArg, StringPart, SubDiagnostic,
|
||||||
|
SubdiagnosticMessageOp,
|
||||||
};
|
};
|
||||||
pub use diagnostic_impls::{
|
pub use diagnostic_impls::{
|
||||||
DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter,
|
DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter,
|
||||||
@ -1496,9 +1497,8 @@ impl DiagCtxtInner {
|
|||||||
diag: &Diagnostic,
|
diag: &Diagnostic,
|
||||||
msg: impl Into<SubdiagnosticMessage>,
|
msg: impl Into<SubdiagnosticMessage>,
|
||||||
) -> SubdiagnosticMessage {
|
) -> SubdiagnosticMessage {
|
||||||
let args = diag.args();
|
|
||||||
let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
|
let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
|
||||||
self.eagerly_translate(msg, args)
|
self.eagerly_translate(msg, diag.args.iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush_delayed(&mut self) {
|
fn flush_delayed(&mut self) {
|
||||||
|
@ -159,7 +159,7 @@ 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();
|
||||||
|
|
||||||
let fluent_args = to_fluent_args(diag.args());
|
let fluent_args = to_fluent_args(diag.args.iter());
|
||||||
let translated_main_message = self
|
let translated_main_message = self
|
||||||
.translate_message(&diag.messages[0].0, &fluent_args)
|
.translate_message(&diag.messages[0].0, &fluent_args)
|
||||||
.unwrap_or_else(|e| panic!("{e}"));
|
.unwrap_or_else(|e| panic!("{e}"));
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
error: cannot prefer dynamic linking when performing LTO
|
error: cannot prefer dynamic linking when performing LTO
|
||||||
|
|
|
||||||
note: only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
|
= note: only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user