diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index ce8e04defb2d1..fd2b08668673c 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -2,7 +2,8 @@ use std::num::IntErrorKind; use rustc_ast as ast; use rustc_errors::{ - error_code, Applicability, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, + error_code, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + Level, }; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; @@ -50,14 +51,12 @@ pub(crate) struct UnknownMetaItem<'a> { } // Manual implementation to be able to format `expected` items correctly. -impl<'a> IntoDiagnostic<'a> for UnknownMetaItem<'_> { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::>(); - let mut diag = dcx.struct_span_err_with_code( - self.span, - fluent::attr_unknown_meta_item, - error_code!(E0541), - ); + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item); + diag.set_span(self.span); + diag.code(error_code!(E0541)); diag.set_arg("item", self.item); diag.set_arg("expected", expected.join(", ")); diag.span_label(self.span, fluent::attr_label); @@ -200,10 +199,11 @@ pub(crate) struct UnsupportedLiteral { pub start_point_span: Span, } -impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - self.span, +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, match self.reason { UnsupportedLiteralReason::Generic => fluent::attr_unsupported_literal_generic, UnsupportedLiteralReason::CfgString => fluent::attr_unsupported_literal_cfg_string, @@ -214,8 +214,9 @@ impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral { fluent::attr_unsupported_literal_deprecated_kv_pair } }, - error_code!(E0565), ); + diag.set_span(self.span); + diag.code(error_code!(E0565)); if self.is_bytestr { diag.span_suggestion( self.start_point_span, diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 6ffeb401453b0..e07eb2e490b71 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ - AddToDiagnostic, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, - SingleLabelManySpans, + AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level, + MultiSpan, SingleLabelManySpans, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -446,14 +446,14 @@ pub(crate) struct EnvNotDefinedWithUserMessage { } // Hand-written implementation to support custom user messages. -impl<'a> IntoDiagnostic<'a> for EnvNotDefinedWithUserMessage { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefinedWithUserMessage { #[track_caller] - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { #[expect( rustc::untranslatable_diagnostic, reason = "cannot translate user-provided messages" )] - let mut diag = dcx.struct_err(self.msg_from_user.to_string()); + let mut diag = DiagnosticBuilder::new(dcx, level, self.msg_from_user.to_string()); diag.set_span(self.span); diag } @@ -801,9 +801,13 @@ pub(crate) struct AsmClobberNoReg { pub(crate) clobbers: Vec, } -impl<'a> IntoDiagnostic<'a> for AsmClobberNoReg { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut diag = dcx.struct_err(crate::fluent_generated::builtin_macros_asm_clobber_no_reg); +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for AsmClobberNoReg { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, + crate::fluent_generated::builtin_macros_asm_clobber_no_reg, + ); diag.set_span(self.spans.clone()); // eager translation as `span_labels` takes `AsRef` let lbl1 = dcx.eagerly_translate_to_string( diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 766d90cf72407..1b1ed0b411c71 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ - DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, - IntoDiagnosticArg, + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + IntoDiagnosticArg, Level, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -111,9 +111,13 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { #[help(codegen_gcc_missing_features)] pub(crate) struct MissingFeatures; -impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { - fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::codegen_gcc_target_feature_disable_or_enable); +impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, + fluent::codegen_gcc_target_feature_disable_or_enable + ); if let Some(span) = self.span { diag.set_span(span); }; diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 671a225259a26..6b7e38a6cb125 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -4,9 +4,7 @@ use std::path::Path; use crate::fluent_generated as fluent; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_errors::{ - DiagCtxt, DiagnosticBuilder, EmissionGuarantee, ErrorGuaranteed, FatalError, IntoDiagnostic, -}; +use rustc_errors::{DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -101,13 +99,14 @@ pub(crate) struct DynamicLinkingWithLTO; pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>); -impl IntoDiagnostic<'_, FatalError> for ParseTargetMachineConfig<'_> { - fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, FatalError> { - let diag: DiagnosticBuilder<'_, FatalError> = self.0.into_diagnostic(dcx); +impl IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_> { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let diag: DiagnosticBuilder<'_, G> = self.0.into_diagnostic(dcx, level); let (message, _) = diag.styled_message().first().expect("`LlvmError` with no message"); let message = dcx.eagerly_translate_to_string(message.clone(), diag.args()); - let mut diag = dcx.struct_almost_fatal(fluent::codegen_llvm_parse_target_machine_config); + let mut diag = + DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config); diag.set_arg("error", message); diag } @@ -123,9 +122,13 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { #[help(codegen_llvm_missing_features)] pub(crate) struct MissingFeatures; -impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { - fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable); +impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, + fluent::codegen_llvm_target_feature_disable_or_enable, + ); if let Some(span) = self.span { diag.set_span(span); }; @@ -184,7 +187,7 @@ pub enum LlvmError<'a> { pub(crate) struct WithLlvmError<'a>(pub LlvmError<'a>, pub String); impl IntoDiagnostic<'_, G> for WithLlvmError<'_> { - fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, G> { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { use LlvmError::*; let msg_with_llvm_err = match &self.0 { WriteOutput { .. } => fluent::codegen_llvm_write_output_with_llvm_err, @@ -201,7 +204,7 @@ impl IntoDiagnostic<'_, G> for WithLlvmError<'_> { PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err, ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err, }; - let mut diag = self.0.into_diagnostic(dcx); + let mut diag = self.0.into_diagnostic(dcx, level); diag.set_primary_message(msg_with_llvm_err); diag.set_arg("llvm_err", self.1); diag diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 668d39afbda74..2b628d2aa69b7 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -4,8 +4,8 @@ use crate::assert_module_sources::CguReuse; use crate::back::command::Command; use crate::fluent_generated as fluent; use rustc_errors::{ - DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, - IntoDiagnosticArg, + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + IntoDiagnosticArg, Level, }; use rustc_macros::Diagnostic; use rustc_middle::ty::layout::LayoutError; @@ -209,192 +209,193 @@ pub enum LinkRlibError { pub struct ThorinErrorWrapper(pub thorin::Error); -impl IntoDiagnostic<'_> for ThorinErrorWrapper { - fn into_diagnostic(self, dcx: &DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { +impl IntoDiagnostic<'_, G> for ThorinErrorWrapper { + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let build = |msg| DiagnosticBuilder::new(dcx, level, msg); let mut diag; match self.0 { thorin::Error::ReadInput(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_read_input_failure); + diag = build(fluent::codegen_ssa_thorin_read_input_failure); diag } thorin::Error::ParseFileKind(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_file_kind); + diag = build(fluent::codegen_ssa_thorin_parse_input_file_kind); diag } thorin::Error::ParseObjectFile(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_object_file); + diag = build(fluent::codegen_ssa_thorin_parse_input_object_file); diag } thorin::Error::ParseArchiveFile(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_archive_file); + diag = build(fluent::codegen_ssa_thorin_parse_input_archive_file); diag } thorin::Error::ParseArchiveMember(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_archive_member); + diag = build(fluent::codegen_ssa_thorin_parse_archive_member); diag } thorin::Error::InvalidInputKind => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_invalid_input_kind); + diag = build(fluent::codegen_ssa_thorin_invalid_input_kind); diag } thorin::Error::DecompressData(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_decompress_data); + diag = build(fluent::codegen_ssa_thorin_decompress_data); diag } thorin::Error::NamelessSection(_, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_section_without_name); + diag = build(fluent::codegen_ssa_thorin_section_without_name); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::RelocationWithInvalidSymbol(section, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol); + diag = build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol); diag.set_arg("section", section); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::MultipleRelocations(section, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_relocations); + diag = build(fluent::codegen_ssa_thorin_multiple_relocations); diag.set_arg("section", section); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::UnsupportedRelocation(section, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_unsupported_relocation); + diag = build(fluent::codegen_ssa_thorin_unsupported_relocation); diag.set_arg("section", section); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::MissingDwoName(id) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_dwo_name); + diag = build(fluent::codegen_ssa_thorin_missing_dwo_name); diag.set_arg("id", format!("0x{id:08x}")); diag } thorin::Error::NoCompilationUnits => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_no_compilation_units); + diag = build(fluent::codegen_ssa_thorin_no_compilation_units); diag } thorin::Error::NoDie => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_no_die); + diag = build(fluent::codegen_ssa_thorin_no_die); diag } thorin::Error::TopLevelDieNotUnit => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_top_level_die_not_unit); + diag = build(fluent::codegen_ssa_thorin_top_level_die_not_unit); diag } thorin::Error::MissingRequiredSection(section) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_required_section); + diag = build(fluent::codegen_ssa_thorin_missing_required_section); diag.set_arg("section", section); diag } thorin::Error::ParseUnitAbbreviations(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_abbreviations); + diag = build(fluent::codegen_ssa_thorin_parse_unit_abbreviations); diag } thorin::Error::ParseUnitAttribute(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_attribute); + diag = build(fluent::codegen_ssa_thorin_parse_unit_attribute); diag } thorin::Error::ParseUnitHeader(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_header); + diag = build(fluent::codegen_ssa_thorin_parse_unit_header); diag } thorin::Error::ParseUnit(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit); + diag = build(fluent::codegen_ssa_thorin_parse_unit); diag } thorin::Error::IncompatibleIndexVersion(section, format, actual) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_incompatible_index_version); + diag = build(fluent::codegen_ssa_thorin_incompatible_index_version); diag.set_arg("section", section); diag.set_arg("actual", actual); diag.set_arg("format", format); diag } thorin::Error::OffsetAtIndex(_, index) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_offset_at_index); + diag = build(fluent::codegen_ssa_thorin_offset_at_index); diag.set_arg("index", index); diag } thorin::Error::StrAtOffset(_, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_str_at_offset); + diag = build(fluent::codegen_ssa_thorin_str_at_offset); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::ParseIndex(_, section) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_index); + diag = build(fluent::codegen_ssa_thorin_parse_index); diag.set_arg("section", section); diag } thorin::Error::UnitNotInIndex(unit) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_unit_not_in_index); + diag = build(fluent::codegen_ssa_thorin_unit_not_in_index); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::RowNotInIndex(_, row) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_row_not_in_index); + diag = build(fluent::codegen_ssa_thorin_row_not_in_index); diag.set_arg("row", row); diag } thorin::Error::SectionNotInRow => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_section_not_in_row); + diag = build(fluent::codegen_ssa_thorin_section_not_in_row); diag } thorin::Error::EmptyUnit(unit) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_empty_unit); + diag = build(fluent::codegen_ssa_thorin_empty_unit); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::MultipleDebugInfoSection => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_debug_info_section); + diag = build(fluent::codegen_ssa_thorin_multiple_debug_info_section); diag } thorin::Error::MultipleDebugTypesSection => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_debug_types_section); + diag = build(fluent::codegen_ssa_thorin_multiple_debug_types_section); diag } thorin::Error::NotSplitUnit => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_not_split_unit); + diag = build(fluent::codegen_ssa_thorin_not_split_unit); diag } thorin::Error::DuplicateUnit(unit) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_duplicate_unit); + diag = build(fluent::codegen_ssa_thorin_duplicate_unit); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::MissingReferencedUnit(unit) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_referenced_unit); + diag = build(fluent::codegen_ssa_thorin_missing_referenced_unit); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::NoOutputObjectCreated => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_not_output_object_created); + diag = build(fluent::codegen_ssa_thorin_not_output_object_created); diag } thorin::Error::MixedInputEncodings => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_mixed_input_encodings); + diag = build(fluent::codegen_ssa_thorin_mixed_input_encodings); diag } thorin::Error::Io(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_io); + diag = build(fluent::codegen_ssa_thorin_io); diag.set_arg("error", format!("{e}")); diag } thorin::Error::ObjectRead(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_object_read); + diag = build(fluent::codegen_ssa_thorin_object_read); diag.set_arg("error", format!("{e}")); diag } thorin::Error::ObjectWrite(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_object_write); + diag = build(fluent::codegen_ssa_thorin_object_write); diag.set_arg("error", format!("{e}")); diag } thorin::Error::GimliRead(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_gimli_read); + diag = build(fluent::codegen_ssa_thorin_gimli_read); diag.set_arg("error", format!("{e}")); diag } thorin::Error::GimliWrite(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_gimli_write); + diag = build(fluent::codegen_ssa_thorin_gimli_write); diag.set_arg("error", format!("{e}")); diag } @@ -410,9 +411,9 @@ pub struct LinkingFailed<'a> { pub escaped_output: String, } -impl IntoDiagnostic<'_> for LinkingFailed<'_> { - fn into_diagnostic(self, dcx: &DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::codegen_ssa_linking_failed); +impl IntoDiagnostic<'_, G> for LinkingFailed<'_> { + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::codegen_ssa_linking_failed); diag.set_arg("linker_path", format!("{}", self.linker_path.display())); diag.set_arg("exit_status", format!("{}", self.exit_status)); diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index adce1f5430f4f..eb9bf52676aa5 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, - IntoDiagnostic, + IntoDiagnostic, Level, }; use rustc_hir::ConstContext; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -875,7 +875,10 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { | InvalidProgramInfo::AlreadyReported(_) | InvalidProgramInfo::ConstPropNonsense => {} InvalidProgramInfo::Layout(e) => { - let diag: DiagnosticBuilder<'_, ()> = e.into_diagnostic().into_diagnostic(dcx); + // The level doesn't matter, `diag` is consumed without it being used. + let dummy_level = Level::Bug; + let diag: DiagnosticBuilder<'_, ()> = + e.into_diagnostic().into_diagnostic(dcx, dummy_level); for (name, val) in diag.args() { builder.set_arg(name.clone(), val.clone()); } diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 3f66af1fcff27..828560ec452cf 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -21,7 +21,7 @@ use std::thread::panicking; pub trait IntoDiagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> { /// Write out as a diagnostic out of `DiagCtxt`. #[must_use] - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, G>; + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G>; } impl<'a, T, G> IntoDiagnostic<'a, G> for Spanned @@ -29,8 +29,8 @@ where T: IntoDiagnostic<'a, G>, G: EmissionGuarantee, { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, G> { - let mut diag = self.node.into_diagnostic(dcx); + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = self.node.into_diagnostic(dcx, level); diag.set_span(self.span); diag } @@ -101,18 +101,31 @@ rustc_data_structures::static_assert_size!( /// Trait for types that `DiagnosticBuilder::emit` can return as a "guarantee" /// (or "proof") token that the emission happened. pub trait EmissionGuarantee: Sized { + /// This exists so that bugs and fatal errors can both result in `!` (an + /// abort) when emitted, but have different aborting behaviour. + type EmitResult = Self; + /// Implementation of `DiagnosticBuilder::emit`, fully controlled by each /// `impl` of `EmissionGuarantee`, to make it impossible to create a value - /// of `Self` without actually performing the emission. + /// of `Self::EmitResult` without actually performing the emission. #[track_caller] - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self; + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult; +} - /// Creates a new `DiagnosticBuilder` that will return this type of guarantee. - #[track_caller] - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into, - ) -> DiagnosticBuilder<'_, Self>; +impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { + /// Most `emit_producing_guarantee` functions use this as a starting point. + fn emit_producing_nothing(&mut self) { + match self.inner.state { + // First `.emit()` call, the `&DiagCtxt` is still available. + DiagnosticBuilderState::Emittable(dcx) => { + self.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + + dcx.emit_diagnostic_without_consuming(&mut self.inner.diagnostic); + } + // `.emit()` was previously called, disallowed from repeating it. + DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} + } + } } impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> { @@ -126,7 +139,8 @@ impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> { // FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`. impl EmissionGuarantee for ErrorGuaranteed { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + // Contrast this with `emit_producing_nothing`. match db.inner.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { @@ -163,142 +177,48 @@ impl EmissionGuarantee for ErrorGuaranteed { } } } - - #[track_caller] - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Error { lint: false }, msg) - } } // FIXME(eddyb) should there be a `Option` impl as well? impl EmissionGuarantee for () { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - } - - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Warning(None), msg) - } -} - -/// Marker type which enables implementation of `create_note` and `emit_note` functions for -/// note-without-error struct diagnostics. -#[derive(Copy, Clone)] -pub struct Noted; - -impl EmissionGuarantee for Noted { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - - Noted - } - - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Note, msg) + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + db.emit_producing_nothing(); } } /// Marker type which enables implementation of `create_bug` and `emit_bug` functions for -/// bug struct diagnostics. +/// bug diagnostics. #[derive(Copy, Clone)] -pub struct Bug; +pub struct BugAbort; -impl EmissionGuarantee for Bug { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; +impl EmissionGuarantee for BugAbort { + type EmitResult = !; - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - // Then panic. No need to return the marker type. + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + db.emit_producing_nothing(); panic::panic_any(ExplicitBug); } - - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Bug, msg) - } } -impl EmissionGuarantee for ! { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; +/// Marker type which enables implementation of `create_fatal` and `emit_fatal` functions for +/// fatal diagnostics. +#[derive(Copy, Clone)] +pub struct FatalAbort; - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - // Then fatally error, returning `!` - crate::FatalError.raise() - } +impl EmissionGuarantee for FatalAbort { + type EmitResult = !; - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Fatal, msg) + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + db.emit_producing_nothing(); + crate::FatalError.raise() } } impl EmissionGuarantee for rustc_span::fatal_error::FatalError { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - // Then fatally error.. + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + db.emit_producing_nothing(); rustc_span::fatal_error::FatalError } - - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Fatal, msg) - } } /// In general, the `DiagnosticBuilder` uses deref to allow access to @@ -339,16 +259,10 @@ impl DerefMut for DiagnosticBuilder<'_, G> { } impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { - /// Convenience function for internal use, clients should use one of the - /// `struct_*` methods on [`DiagCtxt`]. + #[rustc_lint_diagnostics] #[track_caller] - pub(crate) fn new>( - dcx: &'a DiagCtxt, - level: Level, - message: M, - ) -> Self { - let diagnostic = Diagnostic::new(level, message); - Self::new_diagnostic(dcx, diagnostic) + pub fn new>(dcx: &'a DiagCtxt, level: Level, message: M) -> Self { + Self::new_diagnostic(dcx, Diagnostic::new(level, message)) } /// Creates a new `DiagnosticBuilder` with an already constructed @@ -369,8 +283,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// but there are various places that rely on continuing to use `self` /// after calling `emit`. #[track_caller] - pub fn emit(&mut self) -> G { - G::diagnostic_builder_emit_producing_guarantee(self) + pub fn emit(&mut self) -> G::EmitResult { + G::emit_producing_guarantee(self) } /// Emit the diagnostic unless `delay` is true, @@ -378,7 +292,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// /// See `emit` and `delay_as_bug` for details. #[track_caller] - pub fn emit_unless(&mut self, delay: bool) -> G { + pub fn emit_unless(&mut self, delay: bool) -> G::EmitResult { if delay { self.downgrade_to_delayed_bug(); } @@ -400,15 +314,15 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// later stage of the compiler. The diagnostic can be accessed with /// the provided `span` and `key` through [`DiagCtxt::steal_diagnostic()`]. /// - /// As with `buffer`, this is unless the handler has disabled such buffering. + /// As with `buffer`, this is unless the dcx has disabled such buffering. pub fn stash(self, span: Span, key: StashKey) { - if let Some((diag, handler)) = self.into_diagnostic() { - handler.stash_diagnostic(span, key, diag); + if let Some((diag, dcx)) = self.into_diagnostic() { + dcx.stash_diagnostic(span, key, diag); } } /// Converts the builder to a `Diagnostic` for later emission, - /// unless handler has disabled such buffering, or `.emit()` was called. + /// unless dcx has disabled such buffering, or `.emit()` was called. pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> { let dcx = match self.inner.state { // No `.emit()` calls, the `&DiagCtxt` is still available. @@ -449,7 +363,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { } /// Buffers the diagnostic for later emission, - /// unless handler has disabled such buffering. + /// unless dcx has disabled such buffering. pub fn buffer(self, buffered_diagnostics: &mut Vec) { buffered_diagnostics.extend(self.into_diagnostic().map(|(diag, _)| diag)); } @@ -465,7 +379,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// In the meantime, though, callsites are required to deal with the "bug" /// locally in whichever way makes the most sense. #[track_caller] - pub fn delay_as_bug(&mut self) -> G { + pub fn delay_as_bug(&mut self) -> G::EmitResult { self.downgrade_to_delayed_bug(); self.emit() } diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 3e4b3ee758a87..ccc951543d8e6 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -1,10 +1,12 @@ use crate::diagnostic::DiagnosticLocation; use crate::{fluent_generated as fluent, AddToDiagnostic}; -use crate::{DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, IntoDiagnostic, IntoDiagnosticArg}; +use crate::{ + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + IntoDiagnosticArg, Level, +}; use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_hir as hir; -use rustc_lint_defs::Level; use rustc_span::edition::Edition; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol}; use rustc_span::Span; @@ -216,7 +218,7 @@ impl IntoDiagnosticArg for ast::Visibility { } } -impl IntoDiagnosticArg for Level { +impl IntoDiagnosticArg for rustc_lint_defs::Level { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::Borrowed(self.to_cmd_flag())) } @@ -245,19 +247,20 @@ impl IntoDiagnosticArg for hir::def::Res { } } -impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> { - fn into_diagnostic(self, dcx: &DiagCtxt) -> DiagnosticBuilder<'_, !> { +impl IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_> { + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let mut diag; match self { TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => { - diag = dcx.struct_fatal(fluent::errors_target_invalid_address_space); + diag = + DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_address_space); diag.set_arg("addr_space", addr_space); diag.set_arg("cause", cause); diag.set_arg("err", err); diag } TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => { - diag = dcx.struct_fatal(fluent::errors_target_invalid_bits); + diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits); diag.set_arg("kind", kind); diag.set_arg("bit", bit); diag.set_arg("cause", cause); @@ -265,31 +268,39 @@ impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> { diag } TargetDataLayoutErrors::MissingAlignment { cause } => { - diag = dcx.struct_fatal(fluent::errors_target_missing_alignment); + diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_missing_alignment); diag.set_arg("cause", cause); diag } TargetDataLayoutErrors::InvalidAlignment { cause, err } => { - diag = dcx.struct_fatal(fluent::errors_target_invalid_alignment); + diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_alignment); diag.set_arg("cause", cause); diag.set_arg("err_kind", err.diag_ident()); diag.set_arg("align", err.align()); diag } TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => { - diag = dcx.struct_fatal(fluent::errors_target_inconsistent_architecture); + diag = DiagnosticBuilder::new( + dcx, + level, + fluent::errors_target_inconsistent_architecture, + ); diag.set_arg("dl", dl); diag.set_arg("target", target); diag } TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => { - diag = dcx.struct_fatal(fluent::errors_target_inconsistent_pointer_width); + diag = DiagnosticBuilder::new( + dcx, + level, + fluent::errors_target_inconsistent_pointer_width, + ); diag.set_arg("pointer_size", pointer_size); diag.set_arg("target", target); diag } TargetDataLayoutErrors::InvalidBitsSize { err } => { - diag = dcx.struct_fatal(fluent::errors_target_invalid_bits_size); + diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits_size); diag.set_arg("err", err); diag } @@ -362,9 +373,9 @@ impl IntoDiagnosticArg for Backtrace { pub struct InvalidFlushedDelayedDiagnosticLevel { #[primary_span] pub span: Span, - pub level: rustc_errors::Level, + pub level: Level, } -impl IntoDiagnosticArg for rustc_errors::Level { +impl IntoDiagnosticArg for Level { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::from(self.to_string())) } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 959e26fec70fb..518a2ddb71dd9 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -6,6 +6,7 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![feature(array_windows)] +#![feature(associated_type_defaults)] #![feature(extract_if)] #![feature(if_let_guard)] #![feature(let_chains)] @@ -401,7 +402,7 @@ pub use diagnostic::{ AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, }; -pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted}; +pub use diagnostic_builder::{BugAbort, DiagnosticBuilder, EmissionGuarantee, FatalAbort}; pub use diagnostic_impls::{ DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter, IndicateAnonymousLifetime, InvalidFlushedDelayedDiagnosticLevel, LabelKind, @@ -722,21 +723,6 @@ impl DiagCtxt { self.inner.borrow_mut().emit_stashed_diagnostics() } - /// Construct a builder with the `msg` at the level appropriate for the - /// specific `EmissionGuarantee`. - /// - /// Note: this is necessary for `derive(Diagnostic)`, but shouldn't be used - /// outside of that. Instead use `struct_err`, `struct_warn`, etc., which - /// make the diagnostic kind clearer. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_diagnostic( - &self, - msg: impl Into, - ) -> DiagnosticBuilder<'_, G> { - G::make_diagnostic_builder(self, msg) - } - /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. /// /// Attempting to `.emit()` the builder will only emit if either: @@ -922,7 +908,7 @@ impl DiagCtxt { &self, span: impl Into, msg: impl Into, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { let mut result = self.struct_fatal(msg); result.set_span(span); result @@ -936,7 +922,7 @@ impl DiagCtxt { span: impl Into, msg: impl Into, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { let mut result = self.struct_span_fatal(span, msg); result.code(code); result @@ -945,7 +931,10 @@ impl DiagCtxt { /// Construct a builder at the `Fatal` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_fatal(&self, msg: impl Into) -> DiagnosticBuilder<'_, !> { + pub fn struct_fatal( + &self, + msg: impl Into, + ) -> DiagnosticBuilder<'_, FatalAbort> { DiagnosticBuilder::new(self, Level::Fatal, msg) } @@ -972,6 +961,26 @@ impl DiagCtxt { DiagnosticBuilder::new(self, Level::Note, msg) } + /// Construct a builder at the `Bug` level with the `msg`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_bug(&self, msg: impl Into) -> DiagnosticBuilder<'_, BugAbort> { + DiagnosticBuilder::new(self, Level::Bug, msg) + } + + /// Construct a builder at the `Bug` level at the given `span` with the `msg`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_span_bug( + &self, + span: impl Into, + msg: impl Into, + ) -> DiagnosticBuilder<'_, BugAbort> { + let mut result = self.struct_bug(msg); + result.set_span(span); + result + } + #[rustc_lint_diagnostics] #[track_caller] pub fn span_fatal(&self, span: impl Into, msg: impl Into) -> ! { @@ -1070,13 +1079,6 @@ impl DiagCtxt { inner.good_path_delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); } - #[track_caller] - pub fn span_bug_no_panic(&self, span: impl Into, msg: impl Into) { - let mut diag = Diagnostic::new(Bug, msg); - diag.set_span(span); - self.emit_diagnostic(diag); - } - #[track_caller] #[rustc_lint_diagnostics] pub fn span_note(&self, span: impl Into, msg: impl Into) { @@ -1115,9 +1117,9 @@ impl DiagCtxt { self.struct_note(msg).emit() } + #[rustc_lint_diagnostics] pub fn bug(&self, msg: impl Into) -> ! { - DiagnosticBuilder::::new(self, Bug, msg).emit(); - panic::panic_any(ExplicitBug); + self.struct_bug(msg).emit() } #[inline] @@ -1274,18 +1276,19 @@ impl DiagCtxt { self.create_err(err).emit() } + #[track_caller] pub fn create_err<'a>( &'a self, err: impl IntoDiagnostic<'a>, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - err.into_diagnostic(self) + err.into_diagnostic(self, Level::Error { lint: false }) } pub fn create_warning<'a>( &'a self, warning: impl IntoDiagnostic<'a, ()>, ) -> DiagnosticBuilder<'a, ()> { - warning.into_diagnostic(self) + warning.into_diagnostic(self, Level::Warning(None)) } pub fn emit_warning<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) { @@ -1296,7 +1299,7 @@ impl DiagCtxt { &'a self, fatal: impl IntoDiagnostic<'a, FatalError>, ) -> DiagnosticBuilder<'a, FatalError> { - fatal.into_diagnostic(self) + fatal.into_diagnostic(self, Level::Fatal) } pub fn emit_almost_fatal<'a>( @@ -1308,38 +1311,35 @@ impl DiagCtxt { pub fn create_fatal<'a>( &'a self, - fatal: impl IntoDiagnostic<'a, !>, - ) -> DiagnosticBuilder<'a, !> { - fatal.into_diagnostic(self) + fatal: impl IntoDiagnostic<'a, FatalAbort>, + ) -> DiagnosticBuilder<'a, FatalAbort> { + fatal.into_diagnostic(self, Level::Fatal) } - pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! { + pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, FatalAbort>) -> ! { self.create_fatal(fatal).emit() } pub fn create_bug<'a>( &'a self, - bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>, - ) -> DiagnosticBuilder<'a, diagnostic_builder::Bug> { - bug.into_diagnostic(self) + bug: impl IntoDiagnostic<'a, BugAbort>, + ) -> DiagnosticBuilder<'a, BugAbort> { + bug.into_diagnostic(self, Level::Bug) } - pub fn emit_bug<'a>( - &'a self, - bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>, - ) -> diagnostic_builder::Bug { + pub fn emit_bug<'a>(&'a self, bug: impl IntoDiagnostic<'a, BugAbort>) -> ! { self.create_bug(bug).emit() } - pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted { + pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) { self.create_note(note).emit() } pub fn create_note<'a>( &'a self, - note: impl IntoDiagnostic<'a, Noted>, - ) -> DiagnosticBuilder<'a, Noted> { - note.into_diagnostic(self) + note: impl IntoDiagnostic<'a, ()>, + ) -> DiagnosticBuilder<'a, ()> { + note.into_diagnostic(self, Level::Note) } pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index b63609c48e912..ee0b10edfda04 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1159,6 +1159,7 @@ impl<'a> ExtCtxt<'a> { // Fixme: does this result in errors? self.expansions.clear(); } + #[rustc_lint_diagnostics] pub fn bug(&self, msg: &'static str) -> ! { self.sess.dcx().bug(msg); } @@ -1204,11 +1205,10 @@ pub fn resolve_path( .expect("attempting to resolve a file path in an external file"), FileName::DocTest(path, _) => path, other => { - return Err(errors::ResolveRelativePath { + return Err(parse_sess.dcx.create_err(errors::ResolveRelativePath { span, path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(), - } - .into_diagnostic(&parse_sess.dcx)); + })); } }; result.pop(); diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index f461b6a94eced..41f30057902b6 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -2,8 +2,8 @@ use crate::fluent_generated as fluent; use rustc_errors::{ - error_code, Applicability, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, - MultiSpan, + error_code, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + Level, MultiSpan, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; @@ -315,14 +315,12 @@ pub struct MissingTypeParams { } // Manual implementation of `IntoDiagnostic` to be able to call `span_to_snippet`. -impl<'a> IntoDiagnostic<'a> for MissingTypeParams { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for MissingTypeParams { #[track_caller] - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut err = dcx.struct_span_err_with_code( - self.span, - fluent::hir_analysis_missing_type_params, - error_code!(E0393), - ); + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut err = DiagnosticBuilder::new(dcx, level, fluent::hir_analysis_missing_type_params); + err.set_span(self.span); + err.code(error_code!(E0393)); err.set_arg("parameterCount", self.missing_type_params.len()); err.set_arg( "parameters", diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7bd2c3f8b6b74..5d5b5f39ccfc8 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -722,7 +722,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let [segment] = path.segments && segment.ident.name == sym::rust { - fatally_break_rust(self.tcx); + fatally_break_rust(self.tcx, expr.span); } } } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 13a2494861138..c6d7650f74592 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -52,7 +52,7 @@ use crate::expectation::Expectation; use crate::fn_ctxt::RawTy; use crate::gather_locals::GatherLocalsVisitor; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{struct_span_err, DiagnosticId, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{struct_span_err, DiagnosticId, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; @@ -412,24 +412,25 @@ enum TupleArgumentsFlag { TupleArguments, } -fn fatally_break_rust(tcx: TyCtxt<'_>) { +fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! { let dcx = tcx.sess.dcx(); - dcx.span_bug_no_panic( - MultiSpan::new(), + let mut diag = dcx.struct_span_bug( + span, "It looks like you're trying to break rust; would you like some ICE?", ); - dcx.note("the compiler expectedly panicked. this is a feature."); - dcx.note( + diag.note("the compiler expectedly panicked. this is a feature."); + diag.note( "we would appreciate a joke overview: \ https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675", ); - dcx.note(format!("rustc {} running on {}", tcx.sess.cfg_version, config::host_triple(),)); + diag.note(format!("rustc {} running on {}", tcx.sess.cfg_version, config::host_triple(),)); if let Some((flags, excluded_cargo_defaults)) = rustc_session::utils::extra_compiler_flags() { - dcx.note(format!("compiler flags: {}", flags.join(" "))); + diag.note(format!("compiler flags: {}", flags.join(" "))); if excluded_cargo_defaults { - dcx.note("some of the compiler flags provided by cargo are hidden"); + diag.note("some of the compiler flags provided by cargo are hidden"); } } + diag.emit() } /// `expected` here is the expected number of explicit generic arguments on the trait. diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 817a4451dd132..700fb5d35109e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -5,7 +5,6 @@ use crate::errors::{ use crate::infer::error_reporting::TypeErrCtxt; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::InferCtxt; -use rustc_errors::IntoDiagnostic; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_hir as hir; use rustc_hir::def::Res; @@ -367,7 +366,7 @@ impl<'tcx> InferCtxt<'tcx> { let multi_suggestions = Vec::new(); let bad_label = Some(arg_data.make_bad_error(span)); match error_code { - TypeAnnotationNeeded::E0282 => AnnotationRequired { + TypeAnnotationNeeded::E0282 => self.tcx.sess.dcx().create_err(AnnotationRequired { span, source_kind, source_name, @@ -375,9 +374,8 @@ impl<'tcx> InferCtxt<'tcx> { infer_subdiags, multi_suggestions, bad_label, - } - .into_diagnostic(self.tcx.sess.dcx()), - TypeAnnotationNeeded::E0283 => AmbiguousImpl { + }), + TypeAnnotationNeeded::E0283 => self.tcx.sess.dcx().create_err(AmbiguousImpl { span, source_kind, source_name, @@ -385,9 +383,8 @@ impl<'tcx> InferCtxt<'tcx> { infer_subdiags, multi_suggestions, bad_label, - } - .into_diagnostic(self.tcx.sess.dcx()), - TypeAnnotationNeeded::E0284 => AmbiguousReturn { + }), + TypeAnnotationNeeded::E0284 => self.tcx.sess.dcx().create_err(AmbiguousReturn { span, source_kind, source_name, @@ -395,8 +392,7 @@ impl<'tcx> InferCtxt<'tcx> { infer_subdiags, multi_suggestions, bad_label, - } - .into_diagnostic(self.tcx.sess.dcx()), + }), } } } @@ -574,7 +570,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } match error_code { - TypeAnnotationNeeded::E0282 => AnnotationRequired { + TypeAnnotationNeeded::E0282 => self.tcx.sess.dcx().create_err(AnnotationRequired { span, source_kind, source_name: &name, @@ -582,9 +578,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, - } - .into_diagnostic(self.tcx.sess.dcx()), - TypeAnnotationNeeded::E0283 => AmbiguousImpl { + }), + TypeAnnotationNeeded::E0283 => self.tcx.sess.dcx().create_err(AmbiguousImpl { span, source_kind, source_name: &name, @@ -592,9 +587,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, - } - .into_diagnostic(self.tcx.sess.dcx()), - TypeAnnotationNeeded::E0284 => AmbiguousReturn { + }), + TypeAnnotationNeeded::E0284 => self.tcx.sess.dcx().create_err(AmbiguousReturn { span, source_kind, source_name: &name, @@ -602,8 +596,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, - } - .into_diagnostic(self.tcx.sess.dcx()), + }), } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 859c10ef14208..1f1c2bc20e2e0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -5,9 +5,7 @@ use crate::errors::{ use crate::fluent_generated as fluent; use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt}; use crate::infer::{self, SubregionOrigin}; -use rustc_errors::{ - AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, -}; +use rustc_errors::{AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; @@ -136,11 +134,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::ContentValidFor, note_and_explain::SuffixKind::Empty, ); - OutlivesContent { + self.tcx.sess.dcx().create_err(OutlivesContent { span, notes: reference_valid.into_iter().chain(content_valid).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } infer::RelateObjectBound(span) => { let object_valid = note_and_explain::RegionExplanation::new( @@ -157,11 +154,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::SourcePointerValidFor, note_and_explain::SuffixKind::Empty, ); - OutlivesBound { + self.tcx.sess.dcx().create_err(OutlivesBound { span, notes: object_valid.into_iter().chain(pointer_valid).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } infer::RelateParamBound(span, ty, opt_span) => { let prefix = match *sub { @@ -176,8 +172,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let note = note_and_explain::RegionExplanation::new( self.tcx, sub, opt_span, prefix, suffix, ); - FulfillReqLifetime { span, ty: self.resolve_vars_if_possible(ty), note } - .into_diagnostic(self.tcx.sess.dcx()) + self.tcx.sess.dcx().create_err(FulfillReqLifetime { + span, + ty: self.resolve_vars_if_possible(ty), + note, + }) } infer::RelateRegionParamBound(span) => { let param_instantiated = note_and_explain::RegionExplanation::new( @@ -194,11 +193,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::LfParamMustOutlive, note_and_explain::SuffixKind::Empty, ); - LfBoundNotSatisfied { + self.tcx.sess.dcx().create_err(LfBoundNotSatisfied { span, notes: param_instantiated.into_iter().chain(param_must_outlive).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } infer::ReferenceOutlivesReferent(ty, span) => { let pointer_valid = note_and_explain::RegionExplanation::new( @@ -215,12 +213,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::DataValidFor, note_and_explain::SuffixKind::Empty, ); - RefLongerThanData { + self.tcx.sess.dcx().create_err(RefLongerThanData { span, ty: self.resolve_vars_if_possible(ty), notes: pointer_valid.into_iter().chain(data_valid).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => { let mut err = self.report_extra_impl_obligation( @@ -277,11 +274,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::LfMustOutlive, note_and_explain::SuffixKind::Empty, ); - LfBoundNotSatisfied { + self.tcx.sess.dcx().create_err(LfBoundNotSatisfied { span, notes: instantiated.into_iter().chain(must_outlive).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } }; if sub.is_error() || sup.is_error() { diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 5de0203fc1db0..027c97330b117 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; -use crate::diagnostics::diagnostic_builder::{DiagnosticDeriveBuilder, DiagnosticDeriveKind}; +use crate::diagnostics::diagnostic_builder::DiagnosticDeriveKind; use crate::diagnostics::error::{span_err, DiagnosticDeriveError}; use crate::diagnostics::utils::SetOnce; use proc_macro2::TokenStream; @@ -13,32 +13,21 @@ use synstructure::Structure; /// The central struct for constructing the `into_diagnostic` method from an annotated struct. pub(crate) struct DiagnosticDerive<'a> { structure: Structure<'a>, - builder: DiagnosticDeriveBuilder, } impl<'a> DiagnosticDerive<'a> { - pub(crate) fn new(diag: syn::Ident, dcx: syn::Ident, structure: Structure<'a>) -> Self { - Self { - builder: DiagnosticDeriveBuilder { - diag, - kind: DiagnosticDeriveKind::Diagnostic { dcx }, - }, - structure, - } + pub(crate) fn new(structure: Structure<'a>) -> Self { + Self { structure } } pub(crate) fn into_tokens(self) -> TokenStream { - let DiagnosticDerive { mut structure, mut builder } = self; - + let DiagnosticDerive { mut structure } = self; + let kind = DiagnosticDeriveKind::Diagnostic; let slugs = RefCell::new(Vec::new()); - let implementation = builder.each_variant(&mut structure, |mut builder, variant| { + let implementation = kind.each_variant(&mut structure, |mut builder, variant| { let preamble = builder.preamble(variant); let body = builder.body(variant); - let diag = &builder.parent.diag; - let DiagnosticDeriveKind::Diagnostic { dcx } = &builder.parent.kind else { - unreachable!() - }; let init = match builder.slug.value_ref() { None => { span_err(builder.span, "diagnostic slug not specified") @@ -62,7 +51,11 @@ impl<'a> DiagnosticDerive<'a> { Some(slug) => { slugs.borrow_mut().push(slug.clone()); quote! { - let mut #diag = #dcx.struct_diagnostic(crate::fluent_generated::#slug); + let mut diag = rustc_errors::DiagnosticBuilder::new( + dcx, + level, + crate::fluent_generated::#slug + ); } } }; @@ -73,12 +66,10 @@ impl<'a> DiagnosticDerive<'a> { #formatting_init #preamble #body - #diag + diag } }); - let DiagnosticDeriveKind::Diagnostic { dcx } = &builder.kind else { unreachable!() }; - // A lifetime of `'a` causes conflicts, but `_sess` is fine. let mut imp = structure.gen_impl(quote! { gen impl<'_sess, G> @@ -90,9 +81,9 @@ impl<'a> DiagnosticDerive<'a> { #[track_caller] fn into_diagnostic( self, - #dcx: &'_sess rustc_errors::DiagCtxt + dcx: &'_sess rustc_errors::DiagCtxt, + level: rustc_errors::Level ) -> rustc_errors::DiagnosticBuilder<'_sess, G> { - use rustc_errors::IntoDiagnosticArg; #implementation } } @@ -107,36 +98,31 @@ impl<'a> DiagnosticDerive<'a> { /// The central struct for constructing the `decorate_lint` method from an annotated struct. pub(crate) struct LintDiagnosticDerive<'a> { structure: Structure<'a>, - builder: DiagnosticDeriveBuilder, } impl<'a> LintDiagnosticDerive<'a> { - pub(crate) fn new(diag: syn::Ident, structure: Structure<'a>) -> Self { - Self { - builder: DiagnosticDeriveBuilder { diag, kind: DiagnosticDeriveKind::LintDiagnostic }, - structure, - } + pub(crate) fn new(structure: Structure<'a>) -> Self { + Self { structure } } pub(crate) fn into_tokens(self) -> TokenStream { - let LintDiagnosticDerive { mut structure, mut builder } = self; - - let implementation = builder.each_variant(&mut structure, |mut builder, variant| { + let LintDiagnosticDerive { mut structure } = self; + let kind = DiagnosticDeriveKind::LintDiagnostic; + let implementation = kind.each_variant(&mut structure, |mut builder, variant| { let preamble = builder.preamble(variant); let body = builder.body(variant); - let diag = &builder.parent.diag; let formatting_init = &builder.formatting_init; quote! { #preamble #formatting_init #body - #diag + diag } }); let slugs = RefCell::new(Vec::new()); - let msg = builder.each_variant(&mut structure, |mut builder, variant| { + let msg = kind.each_variant(&mut structure, |mut builder, variant| { // Collect the slug by generating the preamble. let _ = builder.preamble(variant); @@ -169,15 +155,13 @@ impl<'a> LintDiagnosticDerive<'a> { } }); - let diag = &builder.diag; let mut imp = structure.gen_impl(quote! { gen impl<'__a> rustc_errors::DecorateLint<'__a, ()> for @Self { #[track_caller] fn decorate_lint<'__b>( self, - #diag: &'__b mut rustc_errors::DiagnosticBuilder<'__a, ()> + diag: &'__b mut rustc_errors::DiagnosticBuilder<'__a, ()> ) { - use rustc_errors::IntoDiagnosticArg; #implementation; } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 511654d994992..f3e98d68b6040 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -17,28 +17,18 @@ use synstructure::{BindingInfo, Structure, VariantInfo}; use super::utils::SubdiagnosticVariant; /// What kind of diagnostic is being derived - a fatal/error/warning or a lint? -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, Copy, PartialEq, Eq)] pub(crate) enum DiagnosticDeriveKind { - Diagnostic { dcx: syn::Ident }, + Diagnostic, LintDiagnostic, } -/// Tracks persistent information required for the entire type when building up individual calls to -/// diagnostic methods for generated diagnostic derives - both `Diagnostic` for -/// fatal/errors/warnings and `LintDiagnostic` for lints. -pub(crate) struct DiagnosticDeriveBuilder { - /// The identifier to use for the generated `DiagnosticBuilder` instance. - pub diag: syn::Ident, - /// Kind of diagnostic that should be derived. - pub kind: DiagnosticDeriveKind, -} - /// Tracks persistent information required for a specific variant when building up individual calls /// to diagnostic methods for generated diagnostic derives - both `Diagnostic` for /// fatal/errors/warnings and `LintDiagnostic` for lints. -pub(crate) struct DiagnosticDeriveVariantBuilder<'parent> { - /// The parent builder for the entire type. - pub parent: &'parent DiagnosticDeriveBuilder, +pub(crate) struct DiagnosticDeriveVariantBuilder { + /// The kind for the entire type. + pub kind: DiagnosticDeriveKind, /// Initialization of format strings for code suggestions. pub formatting_init: TokenStream, @@ -59,19 +49,19 @@ pub(crate) struct DiagnosticDeriveVariantBuilder<'parent> { pub code: SpannedOption<()>, } -impl<'a> HasFieldMap for DiagnosticDeriveVariantBuilder<'a> { +impl HasFieldMap for DiagnosticDeriveVariantBuilder { fn get_field_binding(&self, field: &String) -> Option<&TokenStream> { self.field_map.get(field) } } -impl DiagnosticDeriveBuilder { +impl DiagnosticDeriveKind { /// Call `f` for the struct or for each variant of the enum, returning a `TokenStream` with the /// tokens from `f` wrapped in an `match` expression. Emits errors for use of derive on unions /// or attributes on the type itself when input is an enum. - pub(crate) fn each_variant<'s, F>(&mut self, structure: &mut Structure<'s>, f: F) -> TokenStream + pub(crate) fn each_variant<'s, F>(self, structure: &mut Structure<'s>, f: F) -> TokenStream where - F: for<'a, 'v> Fn(DiagnosticDeriveVariantBuilder<'a>, &VariantInfo<'v>) -> TokenStream, + F: for<'v> Fn(DiagnosticDeriveVariantBuilder, &VariantInfo<'v>) -> TokenStream, { let ast = structure.ast(); let span = ast.span().unwrap(); @@ -101,7 +91,7 @@ impl DiagnosticDeriveBuilder { _ => variant.ast().ident.span().unwrap(), }; let builder = DiagnosticDeriveVariantBuilder { - parent: self, + kind: self, span, field_map: build_field_mapping(variant), formatting_init: TokenStream::new(), @@ -119,7 +109,7 @@ impl DiagnosticDeriveBuilder { } } -impl<'a> DiagnosticDeriveVariantBuilder<'a> { +impl DiagnosticDeriveVariantBuilder { /// Generates calls to `code` and similar functions based on the attributes on the type or /// variant. pub(crate) fn preamble(&mut self, variant: &VariantInfo<'_>) -> TokenStream { @@ -184,8 +174,6 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { &mut self, attr: &Attribute, ) -> Result { - let diag = &self.parent.diag; - // Always allow documentation comments. if is_doc_comment(attr) { return Ok(quote! {}); @@ -223,7 +211,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { let code = nested.parse::()?; tokens.extend(quote! { - #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); + diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); }); } else { span_err(path.span().unwrap(), "unknown argument") @@ -257,8 +245,6 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { } fn generate_field_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { - let diag = &self.parent.diag; - let field = binding_info.ast(); let mut field_binding = binding_info.binding.clone(); field_binding.set_span(field.ty.span()); @@ -267,7 +253,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { let ident = format_ident!("{}", ident); // strip `r#` prefix, if present quote! { - #diag.set_arg( + diag.set_arg( stringify!(#ident), #field_binding ); @@ -322,8 +308,6 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { info: FieldInfo<'_>, binding: TokenStream, ) -> Result { - let diag = &self.parent.diag; - let ident = &attr.path().segments.last().unwrap().ident; let name = ident.to_string(); match (&attr.meta, name.as_str()) { @@ -331,12 +315,12 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { // `set_arg` call will not be generated. (Meta::Path(_), "skip_arg") => return Ok(quote! {}), (Meta::Path(_), "primary_span") => { - match self.parent.kind { - DiagnosticDeriveKind::Diagnostic { .. } => { + match self.kind { + DiagnosticDeriveKind::Diagnostic => { report_error_if_not_applied_to_span(attr, &info)?; return Ok(quote! { - #diag.set_span(#binding); + diag.set_span(#binding); }); } DiagnosticDeriveKind::LintDiagnostic => { @@ -348,13 +332,13 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { } (Meta::Path(_), "subdiagnostic") => { if FieldInnerTy::from_type(&info.binding.ast().ty).will_iterate() { - let DiagnosticDeriveKind::Diagnostic { dcx } = &self.parent.kind else { + let DiagnosticDeriveKind::Diagnostic = self.kind else { // No eager translation for lints. - return Ok(quote! { #diag.subdiagnostic(#binding); }); + return Ok(quote! { diag.subdiagnostic(#binding); }); }; - return Ok(quote! { #diag.eager_subdiagnostic(#dcx, #binding); }); + return Ok(quote! { diag.eager_subdiagnostic(dcx, #binding); }); } else { - return Ok(quote! { #diag.subdiagnostic(#binding); }); + return Ok(quote! { diag.subdiagnostic(#binding); }); } } (Meta::List(meta_list), "subdiagnostic") => { @@ -376,15 +360,15 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { return Ok(quote! {}); } - let dcx = match &self.parent.kind { - DiagnosticDeriveKind::Diagnostic { dcx } => dcx, + match &self.kind { + DiagnosticDeriveKind::Diagnostic => {} DiagnosticDeriveKind::LintDiagnostic => { throw_invalid_attr!(attr, |diag| { diag.help("eager subdiagnostics are not supported on lints") }) } }; - return Ok(quote! { #diag.eager_subdiagnostic(#dcx, #binding); }); + return Ok(quote! { diag.eager_subdiagnostic(dcx, #binding); }); } _ => (), } @@ -442,7 +426,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { self.formatting_init.extend(code_init); Ok(quote! { - #diag.span_suggestions_with_style( + diag.span_suggestions_with_style( #span_field, crate::fluent_generated::#slug, #code_field, @@ -463,10 +447,9 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { kind: &Ident, fluent_attr_identifier: Path, ) -> TokenStream { - let diag = &self.parent.diag; let fn_name = format_ident!("span_{}", kind); quote! { - #diag.#fn_name( + diag.#fn_name( #field_binding, crate::fluent_generated::#fluent_attr_identifier ); @@ -476,9 +459,8 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug /// and `fluent_attr_identifier`. fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream { - let diag = &self.parent.diag; quote! { - #diag.#kind(crate::fluent_generated::#fluent_attr_identifier); + diag.#kind(crate::fluent_generated::#fluent_attr_identifier); } } diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index a536eb3b04e69..d3a4e7ba7d191 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -6,7 +6,6 @@ mod utils; use diagnostic::{DiagnosticDerive, LintDiagnosticDerive}; use proc_macro2::TokenStream; -use quote::format_ident; use subdiagnostic::SubdiagnosticDeriveBuilder; use synstructure::Structure; @@ -57,7 +56,7 @@ use synstructure::Structure; /// See rustc dev guide for more examples on using the `#[derive(Diagnostic)]`: /// pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream { - DiagnosticDerive::new(format_ident!("diag"), format_ident!("handler"), s).into_tokens() + DiagnosticDerive::new(s).into_tokens() } /// Implements `#[derive(LintDiagnostic)]`, which allows for lints to be specified as a struct, @@ -103,7 +102,7 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream { /// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`: /// pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream { - LintDiagnosticDerive::new(format_ident!("diag"), s).into_tokens() + LintDiagnosticDerive::new(s).into_tokens() } /// Implements `#[derive(Subdiagnostic)]`, which allows for labels, notes, helps and diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 0f9e68cdc5018..663abecb67c6e 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -94,7 +94,6 @@ impl SubdiagnosticDeriveBuilder { rustc_errors::SubdiagnosticMessage ) -> rustc_errors::SubdiagnosticMessage, { - use rustc_errors::{Applicability, IntoDiagnosticArg}; #implementation } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 206c15edd78fa..e13068cb6f9e4 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -3,7 +3,9 @@ use std::{ path::{Path, PathBuf}, }; -use rustc_errors::{error_code, ErrorGuaranteed, IntoDiagnostic}; +use rustc_errors::{ + error_code, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level, +}; use rustc_macros::Diagnostic; use rustc_session::config; use rustc_span::{sym, Span, Symbol}; @@ -495,12 +497,9 @@ pub(crate) struct MultipleCandidates { pub candidates: Vec, } -impl IntoDiagnostic<'_> for MultipleCandidates { - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::metadata_multiple_candidates); +impl IntoDiagnostic<'_, G> for MultipleCandidates { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_multiple_candidates); diag.set_arg("crate_name", self.crate_name); diag.set_arg("flavor", self.flavor); diag.code(error_code!(E0464)); @@ -593,13 +592,10 @@ pub struct InvalidMetadataFiles { pub crate_rejections: Vec, } -impl IntoDiagnostic<'_> for InvalidMetadataFiles { +impl IntoDiagnostic<'_, G> for InvalidMetadataFiles { #[track_caller] - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::metadata_invalid_meta_files); + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_invalid_meta_files); diag.set_arg("crate_name", self.crate_name); diag.set_arg("add_info", self.add_info); diag.code(error_code!(E0786)); @@ -623,13 +619,10 @@ pub struct CannotFindCrate { pub is_ui_testing: bool, } -impl IntoDiagnostic<'_> for CannotFindCrate { +impl IntoDiagnostic<'_, G> for CannotFindCrate { #[track_caller] - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::metadata_cannot_find_crate); + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_cannot_find_crate); diag.set_arg("crate_name", self.crate_name); diag.set_arg("current_crate", self.current_crate); diag.set_arg("add_info", self.add_info); diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 225dd217807db..5ae758edfa337 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -5,7 +5,8 @@ use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::{self, ConstKind, Ty, TyCtxt, TypeVisitableExt}; use rustc_error_messages::DiagnosticMessage; use rustc_errors::{ - DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, IntoDiagnostic, IntoDiagnosticArg, + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + IntoDiagnosticArg, Level, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -1272,14 +1273,14 @@ pub enum FnAbiError<'tcx> { AdjustForForeignAbi(call::AdjustForForeignAbiError), } -impl<'a, 'b> IntoDiagnostic<'a, !> for FnAbiError<'b> { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, !> { +impl<'a, 'b, G: EmissionGuarantee> IntoDiagnostic<'a, G> for FnAbiError<'b> { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { match self { - Self::Layout(e) => e.into_diagnostic().into_diagnostic(dcx), + Self::Layout(e) => e.into_diagnostic().into_diagnostic(dcx, level), Self::AdjustForForeignAbi(call::AdjustForForeignAbiError::Unsupported { arch, abi, - }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diagnostic(dcx), + }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diagnostic(dcx, level), } } } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index c66687330dc4f..22d0a66548910 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -2,7 +2,7 @@ use crate::fluent_generated as fluent; use rustc_errors::DiagnosticArgValue; use rustc_errors::{ error_code, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, - ErrorGuaranteed, IntoDiagnostic, MultiSpan, SubdiagnosticMessage, + ErrorGuaranteed, IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessage, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -461,13 +461,18 @@ pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { } impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - self.span, + fn into_diagnostic( + self, + dcx: &'a DiagCtxt, + level: Level, + ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, fluent::mir_build_non_exhaustive_patterns_type_not_empty, - error_code!(E0004), ); - + diag.set_span(self.span); + diag.code(error_code!(E0004)); let peeled_ty = self.ty.peel_refs(); diag.set_arg("ty", self.ty); diag.set_arg("peeled_ty", peeled_ty); diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index fd4af31501c3e..17916e16daf46 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use rustc_errors::{ Applicability, DecorateLint, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, - DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed, IntoDiagnostic, + DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, Level, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::mir::{AssertKind, UnsafetyViolationDetails}; @@ -62,10 +62,10 @@ pub(crate) struct RequiresUnsafe { // so we need to eagerly translate the label here, which isn't supported by the derive API // We could also exhaustively list out the primary messages for all unsafe violations, // but this would result in a lot of duplication. -impl<'sess> IntoDiagnostic<'sess> for RequiresUnsafe { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe { #[track_caller] - fn into_diagnostic(self, dcx: &'sess DiagCtxt) -> DiagnosticBuilder<'sess, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::mir_transform_requires_unsafe); + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::mir_transform_requires_unsafe); diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string())); diag.set_span(self.span); diag.span_label(self.span, self.details.label()); diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 247b224558395..592e71251b8ba 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -1,8 +1,7 @@ use std::path::PathBuf; use crate::fluent_generated as fluent; -use rustc_errors::ErrorGuaranteed; -use rustc_errors::IntoDiagnostic; +use rustc_errors::{DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level}; use rustc_macros::{Diagnostic, LintDiagnostic}; use rustc_span::{Span, Symbol}; @@ -47,13 +46,11 @@ pub struct UnusedGenericParamsHint { pub param_names: Vec, } -impl IntoDiagnostic<'_> for UnusedGenericParamsHint { +impl IntoDiagnostic<'_, G> for UnusedGenericParamsHint { #[track_caller] - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::monomorphize_unused_generic_params); + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = + DiagnosticBuilder::new(dcx, level, fluent::monomorphize_unused_generic_params); diag.set_span(self.span); for (span, name) in self.param_spans.into_iter().zip(self.param_names) { // FIXME: I can figure out how to do a label with a fluent string with a fixed message, diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 008adcc83d0ea..8ccfcb625a626 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2,7 +2,10 @@ use std::borrow::Cow; use rustc_ast::token::Token; use rustc_ast::{Path, Visibility}; -use rustc_errors::{AddToDiagnostic, Applicability, ErrorGuaranteed, IntoDiagnostic}; +use rustc_errors::{ + AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, + Level, SubdiagnosticMessage, +}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; @@ -1042,23 +1045,30 @@ impl<'a> IntoDiagnostic<'a> for ExpectedIdentifier { #[track_caller] fn into_diagnostic( self, - dcx: &'a rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { + dcx: &'a DiagCtxt, + level: Level, + ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { let token_descr = TokenDescription::from_token(&self.token); - let mut diag = dcx.struct_err(match token_descr { - Some(TokenDescription::ReservedIdentifier) => { - fluent::parse_expected_identifier_found_reserved_identifier_str - } - Some(TokenDescription::Keyword) => fluent::parse_expected_identifier_found_keyword_str, - Some(TokenDescription::ReservedKeyword) => { - fluent::parse_expected_identifier_found_reserved_keyword_str - } - Some(TokenDescription::DocComment) => { - fluent::parse_expected_identifier_found_doc_comment_str - } - None => fluent::parse_expected_identifier_found_str, - }); + let mut diag = DiagnosticBuilder::new( + dcx, + level, + match token_descr { + Some(TokenDescription::ReservedIdentifier) => { + fluent::parse_expected_identifier_found_reserved_identifier_str + } + Some(TokenDescription::Keyword) => { + fluent::parse_expected_identifier_found_keyword_str + } + Some(TokenDescription::ReservedKeyword) => { + fluent::parse_expected_identifier_found_reserved_keyword_str + } + Some(TokenDescription::DocComment) => { + fluent::parse_expected_identifier_found_doc_comment_str + } + None => fluent::parse_expected_identifier_found_str, + }, + ); diag.set_span(self.span); diag.set_arg("token", self.token); @@ -1099,21 +1109,28 @@ impl<'a> IntoDiagnostic<'a> for ExpectedSemi { #[track_caller] fn into_diagnostic( self, - dcx: &'a rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { + dcx: &'a DiagCtxt, + level: Level, + ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { let token_descr = TokenDescription::from_token(&self.token); - let mut diag = dcx.struct_err(match token_descr { - Some(TokenDescription::ReservedIdentifier) => { - fluent::parse_expected_semi_found_reserved_identifier_str - } - Some(TokenDescription::Keyword) => fluent::parse_expected_semi_found_keyword_str, - Some(TokenDescription::ReservedKeyword) => { - fluent::parse_expected_semi_found_reserved_keyword_str - } - Some(TokenDescription::DocComment) => fluent::parse_expected_semi_found_doc_comment_str, - None => fluent::parse_expected_semi_found_str, - }); + let mut diag = DiagnosticBuilder::new( + dcx, + level, + match token_descr { + Some(TokenDescription::ReservedIdentifier) => { + fluent::parse_expected_semi_found_reserved_identifier_str + } + Some(TokenDescription::Keyword) => fluent::parse_expected_semi_found_keyword_str, + Some(TokenDescription::ReservedKeyword) => { + fluent::parse_expected_semi_found_reserved_keyword_str + } + Some(TokenDescription::DocComment) => { + fluent::parse_expected_semi_found_doc_comment_str + } + None => fluent::parse_expected_semi_found_str, + }, + ); diag.set_span(self.span); diag.set_arg("token", self.token); @@ -1436,10 +1453,7 @@ pub(crate) struct FnTraitMissingParen { impl AddToDiagnostic for FnTraitMissingParen { fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut rustc_errors::Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren); let applicability = if self.machine_applicable { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index c158edaac2554..59bc0eeb1c5b6 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -7,7 +7,9 @@ use rustc_ast::ast::{self, AttrStyle}; use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::contains_text_flow_control_chars; -use rustc_errors::{error_code, Applicability, Diagnostic, DiagnosticBuilder, StashKey}; +use rustc_errors::{ + error_code, Applicability, Diagnostic, DiagnosticBuilder, FatalAbort, StashKey, +}; use rustc_lexer::unescape::{self, EscapeError, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; use rustc_lexer::{Cursor, LiteralKind}; @@ -344,7 +346,7 @@ impl<'a> StringReader<'a> { to_pos: BytePos, m: &str, c: char, - ) -> DiagnosticBuilder<'a, !> { + ) -> DiagnosticBuilder<'a, FatalAbort> { self.sess .dcx .struct_span_fatal(self.mk_sp(from_pos, to_pos), format!("{}: {}", m, escaped_char(c))) diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 56e52baf98b0c..53b29eccc2cd5 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -5,7 +5,7 @@ use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle use rustc_ast as ast; use rustc_ast::attr; use rustc_ast::token::{self, Delimiter, Nonterminal}; -use rustc_errors::{error_code, Diagnostic, IntoDiagnostic, PResult}; +use rustc_errors::{error_code, Diagnostic, PResult}; use rustc_span::{sym, BytePos, Span}; use thin_vec::ThinVec; use tracing::debug; @@ -416,8 +416,9 @@ impl<'a> Parser<'a> { Err(err) => err.cancel(), } - Err(InvalidMetaItem { span: self.token.span, token: self.token.clone() } - .into_diagnostic(self.dcx())) + Err(self + .dcx() + .create_err(InvalidMetaItem { span: self.token.span, token: self.token.clone() })) } } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c077e0a83a1ba..f19d420bb49b9 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -35,7 +35,7 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ pluralize, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, - DiagnosticMessage, ErrorGuaranteed, FatalError, IntoDiagnostic, MultiSpan, PResult, + DiagnosticMessage, ErrorGuaranteed, FatalError, MultiSpan, PResult, }; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; @@ -280,11 +280,10 @@ impl<'a> Parser<'a> { recover: bool, ) -> PResult<'a, (Ident, /* is_raw */ bool)> { if let TokenKind::DocComment(..) = self.prev_token.kind { - return Err(DocCommentDoesNotDocumentAnything { + return Err(self.dcx().create_err(DocCommentDoesNotDocumentAnything { span: self.prev_token.span, missing_comma: None, - } - .into_diagnostic(self.dcx())); + })); } let valid_follow = &[ @@ -347,7 +346,7 @@ impl<'a> Parser<'a> { suggest_remove_comma, help_cannot_start_number, }; - let mut err = err.into_diagnostic(self.dcx()); + let mut err = self.dcx().create_err(err); // if the token we have is a `<` // it *might* be a misplaced generic @@ -1432,7 +1431,7 @@ impl<'a> Parser<'a> { // Not entirely sure now, but we bubble the error up with the // suggestion. self.restore_snapshot(snapshot); - Err(err.into_diagnostic(self.dcx())) + Err(self.dcx().create_err(err)) } } } else if token::OpenDelim(Delimiter::Parenthesis) == self.token.kind { @@ -1447,7 +1446,7 @@ impl<'a> Parser<'a> { } // Consume the fn call arguments. match self.consume_fn_args() { - Err(()) => Err(err.into_diagnostic(self.dcx())), + Err(()) => Err(self.dcx().create_err(err)), Ok(()) => { self.sess.emit_err(err); // FIXME: actually check that the two expressions in the binop are @@ -1473,7 +1472,7 @@ impl<'a> Parser<'a> { mk_err_expr(self, inner_op.span.to(self.prev_token.span)) } else { // These cases cause too many knock-down errors, bail out (#61329). - Err(err.into_diagnostic(self.dcx())) + Err(self.dcx().create_err(err)) } }; } @@ -2561,7 +2560,7 @@ impl<'a> Parser<'a> { Ok(Some(GenericArg::Const(self.parse_const_arg()?))) } else { let after_kw_const = self.token.span; - self.recover_const_arg(after_kw_const, err.into_diagnostic(self.dcx())).map(Some) + self.recover_const_arg(after_kw_const, self.dcx().create_err(err)).map(Some) } } @@ -2915,11 +2914,10 @@ impl<'a> Parser<'a> { let (a_span, b_span) = (a.span(), b.span()); let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo()); if self.span_to_snippet(between_span).as_deref() == Ok(":: ") { - return Err(DoubleColonInBound { + return Err(self.dcx().create_err(DoubleColonInBound { span: path.span.shrink_to_hi(), between: between_span, - } - .into_diagnostic(self.dcx())); + })); } } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index cd3e8b92f2f9e..a21a153384801 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -26,8 +26,8 @@ use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ - AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, - PResult, StashKey, + AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult, + StashKey, }; use rustc_macros::Subdiagnostic; use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded}; @@ -1255,21 +1255,21 @@ impl<'a> Parser<'a> { // that of the open delim in `TokenTreesReader::parse_token_tree`, even if they are different. self.span_to_snippet(close_paren).is_ok_and(|snippet| snippet == ")") { - let mut replacement_err = errors::ParenthesesWithStructFields { - span, - r#type: path, - braces_for_struct: errors::BracesForStructLiteral { - first: open_paren, - second: close_paren, - }, - no_fields_for_fn: errors::NoFieldsForFnCall { - fields: fields - .into_iter() - .map(|field| field.span.until(field.expr.span)) - .collect(), - }, - } - .into_diagnostic(self.dcx()); + let mut replacement_err = + self.dcx().create_err(errors::ParenthesesWithStructFields { + span, + r#type: path, + braces_for_struct: errors::BracesForStructLiteral { + first: open_paren, + second: close_paren, + }, + no_fields_for_fn: errors::NoFieldsForFnCall { + fields: fields + .into_iter() + .map(|field| field.span.until(field.expr.span)) + .collect(), + }, + }); replacement_err.emit(); let old_err = mem::replace(err, replacement_err); @@ -1883,8 +1883,7 @@ impl<'a> Parser<'a> { self.bump(); // `#` let Some((ident, false)) = self.token.ident() else { - let err = - errors::ExpectedBuiltinIdent { span: self.token.span }.into_diagnostic(self.dcx()); + let err = self.dcx().create_err(errors::ExpectedBuiltinIdent { span: self.token.span }); return Err(err); }; self.sess.gated_spans.gate(sym::builtin_syntax, ident.span); @@ -1894,8 +1893,10 @@ impl<'a> Parser<'a> { let ret = if let Some(res) = parse(self, lo, ident)? { Ok(res) } else { - let err = errors::UnknownBuiltinConstruct { span: lo.to(ident.span), name: ident.name } - .into_diagnostic(self.dcx()); + let err = self.dcx().create_err(errors::UnknownBuiltinConstruct { + span: lo.to(ident.span), + name: ident.name, + }); return Err(err); }; self.expect(&TokenKind::CloseDelim(Delimiter::Parenthesis))?; @@ -1958,8 +1959,9 @@ impl<'a> Parser<'a> { && let token::NtExpr(e) | token::NtLiteral(e) = &nt.0 && matches!(e.kind, ExprKind::Err) { - let mut err = errors::InvalidInterpolatedExpression { span: self.token.span } - .into_diagnostic(self.dcx()); + let mut err = self + .dcx() + .create_err(errors::InvalidInterpolatedExpression { span: self.token.span }); err.downgrade_to_delayed_bug(); return Err(err); } @@ -2168,10 +2170,10 @@ impl<'a> Parser<'a> { .span_to_snippet(snapshot.token.span) .is_ok_and(|snippet| snippet == "]") => { - return Err(errors::MissingSemicolonBeforeArray { + return Err(self.dcx().create_err(errors::MissingSemicolonBeforeArray { open_delim: open_delim_span, semicolon: prev_span.shrink_to_hi(), - }.into_diagnostic(self.dcx())); + })); } Ok(_) => (), Err(err) => err.cancel(), @@ -2318,8 +2320,9 @@ impl<'a> Parser<'a> { // Check for `move async` and recover if self.check_keyword(kw::Async) { let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo); - Err(errors::AsyncMoveOrderIncorrect { span: move_async_span } - .into_diagnostic(self.dcx())) + Err(self + .dcx() + .create_err(errors::AsyncMoveOrderIncorrect { span: move_async_span })) } else { Ok(CaptureBy::Value { move_kw: move_kw_span }) } @@ -2509,7 +2512,7 @@ impl<'a> Parser<'a> { }; if self.prev_token.kind == token::BinOp(token::Or) { // This was part of a closure, the that part of the parser recover. - return Err(err.into_diagnostic(self.dcx())); + return Err(self.dcx().create_err(err)); } else { Some(self.sess.emit_err(err)) } @@ -3193,7 +3196,7 @@ impl<'a> Parser<'a> { fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P> { let (attrs, body) = self.parse_inner_attrs_and_block()?; if self.eat_keyword(kw::Catch) { - Err(errors::CatchAfterTry { span: self.prev_token.span }.into_diagnostic(self.dcx())) + Err(self.dcx().create_err(errors::CatchAfterTry { span: self.prev_token.span })) } else { let span = span_lo.to(body.span); self.sess.gated_spans.gate(sym::try_blocks, span); @@ -3530,12 +3533,11 @@ impl<'a> Parser<'a> { || t == &token::CloseDelim(Delimiter::Parenthesis) }); if is_wrong { - return Err(errors::ExpectedStructField { + return Err(this.dcx().create_err(errors::ExpectedStructField { span: this.look_ahead(1, |t| t.span), ident_span: this.token.span, token: this.look_ahead(1, |t| t.clone()), - } - .into_diagnostic(&self.sess.dcx)); + })); } let (ident, expr) = if is_shorthand { // Mimic `x: x` for the `x` field shorthand. diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 09ee042ef6b4e..051f19f5a9d2a 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -10,10 +10,7 @@ use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::util::case::Case; use rustc_ast::{self as ast}; use rustc_ast_pretty::pprust; -use rustc_errors::{ - struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult, - StashKey, -}; +use rustc_errors::{struct_span_err, Applicability, PResult, StashKey}; use rustc_span::edit_distance::edit_distance; use rustc_span::edition::Edition; use rustc_span::source_map; @@ -438,7 +435,7 @@ impl<'a> Parser<'a> { None }; - if let Some(err) = err { Err(err.into_diagnostic(self.dcx())) } else { Ok(()) } + if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) } } fn parse_item_builtin(&mut self) -> PResult<'a, Option> { @@ -1373,8 +1370,7 @@ impl<'a> Parser<'a> { }; let span = self.prev_token.span.shrink_to_hi(); - let err: DiagnosticBuilder<'_, ErrorGuaranteed> = - errors::MissingConstType { span, colon, kind }.into_diagnostic(self.dcx()); + let err = self.dcx().create_err(errors::MissingConstType { span, colon, kind }); err.stash(span, StashKey::ItemNoType); // The user intended that the type be inferred, @@ -1391,7 +1387,7 @@ impl<'a> Parser<'a> { self.bump(); self.sess.emit_err(err); } else { - return Err(err.into_diagnostic(self.dcx())); + return Err(self.dcx().create_err(err)); } } @@ -1591,7 +1587,7 @@ impl<'a> Parser<'a> { } else { let err = errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token.clone()); - return Err(err.into_diagnostic(self.dcx())); + return Err(self.dcx().create_err(err)); }; Ok((class_name, ItemKind::Struct(vdata, generics))) @@ -1787,7 +1783,7 @@ impl<'a> Parser<'a> { let sp = previous_span.shrink_to_hi(); err.missing_comma = Some(sp); } - return Err(err.into_diagnostic(self.dcx())); + return Err(self.dcx().create_err(err)); } } _ => { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index b91432f10c8fa..0ab2adb404afe 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -32,9 +32,7 @@ use rustc_ast::{HasAttrs, HasTokens, Unsafe, Visibility, VisibilityKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::PResult; -use rustc_errors::{ - Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, IntoDiagnostic, MultiSpan, -}; +use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, MultiSpan}; use rustc_session::parse::ParseSess; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -1500,14 +1498,13 @@ pub(crate) fn make_unclosed_delims_error( if let Some(sp) = unmatched.unclosed_span { spans.push(sp); }; - let err = MismatchedClosingDelimiter { + let err = sess.dcx.create_err(MismatchedClosingDelimiter { spans, delimiter: pprust::token_kind_to_string(&token::CloseDelim(found_delim)).to_string(), unmatched: unmatched.found_span, opening_candidate: unmatched.candidate_span, unclosed: unmatched.unclosed_span, - } - .into_diagnostic(&sess.dcx); + }); Some(err) } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 301a88cd07766..071d6b72f3b96 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -2,7 +2,6 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token}; use rustc_ast::HasTokens; use rustc_ast_pretty::pprust; -use rustc_errors::IntoDiagnostic; use rustc_errors::PResult; use rustc_span::symbol::{kw, Ident}; @@ -114,9 +113,9 @@ impl<'a> Parser<'a> { NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? { Some(item) => NtItem(item), None => { - return Err( - UnexpectedNonterminal::Item(self.token.span).into_diagnostic(self.dcx()) - ); + return Err(self + .dcx() + .create_err(UnexpectedNonterminal::Item(self.token.span))); } }, NonterminalKind::Block => { @@ -127,8 +126,9 @@ impl<'a> Parser<'a> { NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? { Some(s) => NtStmt(P(s)), None => { - return Err(UnexpectedNonterminal::Statement(self.token.span) - .into_diagnostic(self.dcx())); + return Err(self + .dcx() + .create_err(UnexpectedNonterminal::Statement(self.token.span))); } }, NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => { @@ -160,11 +160,10 @@ impl<'a> Parser<'a> { NtIdent(ident, is_raw) } NonterminalKind::Ident => { - return Err(UnexpectedNonterminal::Ident { + return Err(self.dcx().create_err(UnexpectedNonterminal::Ident { span: self.token.span, token: self.token.clone(), - } - .into_diagnostic(self.dcx())); + })); } NonterminalKind::Path => { NtPath(P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?)) @@ -178,11 +177,10 @@ impl<'a> Parser<'a> { if self.check_lifetime() { NtLifetime(self.expect_lifetime().ident) } else { - return Err(UnexpectedNonterminal::Lifetime { + return Err(self.dcx().create_err(UnexpectedNonterminal::Lifetime { span: self.token.span, token: self.token.clone(), - } - .into_diagnostic(self.dcx())); + })); } } }; diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 80233eddb9b7f..d32582fd43d3d 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -18,7 +18,7 @@ use rustc_ast::{ PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax, }; use rustc_ast_pretty::pprust; -use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult}; +use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident}; @@ -872,8 +872,9 @@ impl<'a> Parser<'a> { // binding mode then we do not end up here, because the lookahead // will direct us over to `parse_enum_variant()`. if self.token == token::OpenDelim(Delimiter::Parenthesis) { - return Err(EnumPatternInsteadOfIdentifier { span: self.prev_token.span } - .into_diagnostic(self.dcx())); + return Err(self + .dcx() + .create_err(EnumPatternInsteadOfIdentifier { span: self.prev_token.span })); } Ok(PatKind::Ident(binding_annotation, ident, sub)) @@ -986,8 +987,8 @@ impl<'a> Parser<'a> { // check that a comma comes after every field if !ate_comma { - let mut err = ExpectedCommaAfterPatternField { span: self.token.span } - .into_diagnostic(self.dcx()); + let mut err = + self.dcx().create_err(ExpectedCommaAfterPatternField { span: self.token.span }); if let Some(mut delayed) = delayed_err { delayed.emit(); } diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 3b92a91198356..8970a99f1b7d6 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -9,7 +9,7 @@ use rustc_ast::{ AssocConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs, Path, PathSegment, QSelf, }; -use rustc_errors::{Applicability, IntoDiagnostic, PResult}; +use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, Span}; use std::mem; @@ -318,15 +318,14 @@ impl<'a> Parser<'a> { }) { err.cancel(); - err = PathSingleColon { + err = self.dcx().create_err(PathSingleColon { span: self.token.span, type_ascription: self .sess .unstable_features .is_nightly_build() .then_some(()), - } - .into_diagnostic(self.dcx()); + }); } // Attempt to find places where a missing `>` might belong. else if let Some(arg) = args diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 8f8da211d312f..856256a064149 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -6,8 +6,8 @@ use std::{ use crate::fluent_generated as fluent; use rustc_ast::Label; use rustc_errors::{ - error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticSymbolList, ErrorGuaranteed, - IntoDiagnostic, MultiSpan, + error_code, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, + DiagnosticSymbolList, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan, }; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -863,13 +863,11 @@ pub struct ItemFollowingInnerAttr { pub kind: &'static str, } -impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel { +impl IntoDiagnostic<'_, G> for InvalidAttrAtCrateLevel { #[track_caller] - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::passes_invalid_attr_at_crate_level); + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = + DiagnosticBuilder::new(dcx, level, fluent::passes_invalid_attr_at_crate_level); diag.set_span(self.span); diag.set_arg("name", self.name); // Only emit an error with a suggestion if we can create a string out @@ -879,7 +877,7 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel { span, fluent::passes_suggestion, String::new(), - rustc_errors::Applicability::MachineApplicable, + Applicability::MachineApplicable, ); } if let Some(item) = self.item { @@ -1016,17 +1014,12 @@ pub struct BreakNonLoop<'a> { pub break_expr_span: Span, } -impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> { #[track_caller] - fn into_diagnostic( - self, - dcx: &rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - self.span, - fluent::passes_break_non_loop, - error_code!(E0571), - ); + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_break_non_loop); + diag.set_span(self.span); + diag.code(error_code!(E0571)); diag.set_arg("kind", self.kind); diag.span_label(self.span, fluent::passes_label); if let Some(head) = self.head { @@ -1165,17 +1158,12 @@ pub struct NakedFunctionsAsmBlock { pub non_asms: Vec, } -impl IntoDiagnostic<'_> for NakedFunctionsAsmBlock { +impl IntoDiagnostic<'_, G> for NakedFunctionsAsmBlock { #[track_caller] - fn into_diagnostic( - self, - dcx: &rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - self.span, - fluent::passes_naked_functions_asm_block, - error_code!(E0787), - ); + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_naked_functions_asm_block); + diag.set_span(self.span); + diag.code(error_code!(E0787)); for span in self.multiple_asms.iter() { diag.span_label(*span, fluent::passes_label_multiple_asm); } @@ -1281,17 +1269,12 @@ pub struct NoMainErr { pub add_teach_note: bool, } -impl<'a> IntoDiagnostic<'a> for NoMainErr { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for NoMainErr { #[track_caller] - fn into_diagnostic( - self, - dcx: &'a rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - DUMMY_SP, - fluent::passes_no_main_function, - error_code!(E0601), - ); + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_no_main_function); + diag.set_span(DUMMY_SP); + diag.code(error_code!(E0601)); diag.set_arg("crate_name", self.crate_name); diag.set_arg("filename", self.filename); diag.set_arg("has_filename", self.has_filename); @@ -1344,20 +1327,19 @@ pub struct DuplicateLangItem { pub(crate) duplicate: Duplicate, } -impl IntoDiagnostic<'_> for DuplicateLangItem { +impl IntoDiagnostic<'_, G> for DuplicateLangItem { #[track_caller] - fn into_diagnostic( - self, - dcx: &rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err_with_code( + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, match self.duplicate { Duplicate::Plain => fluent::passes_duplicate_lang_item, Duplicate::Crate => fluent::passes_duplicate_lang_item_crate, Duplicate::CrateDepends => fluent::passes_duplicate_lang_item_crate_depends, }, - error_code!(E0152), ); + diag.code(error_code!(E0152)); diag.set_arg("lang_item_name", self.lang_item_name); diag.set_arg("crate_name", self.crate_name); diag.set_arg("dependency_of", self.dependency_of); diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 2a34ffb75f2cd..0561fd147a919 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -4,9 +4,7 @@ use crate::query::plumbing::CycleError; use crate::query::DepKind; use crate::query::{QueryContext, QueryStackFrame}; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{ - DiagCtxt, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, Level, -}; +use rustc_errors::{DiagCtxt, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, Level}; use rustc_hir::def::DefKind; use rustc_session::Session; use rustc_span::Span; @@ -604,7 +602,7 @@ pub(crate) fn report_cycle<'a>( note_span: (), }; - cycle_diag.into_diagnostic(sess.dcx()) + sess.dcx().create_err(cycle_diag) } pub fn print_query_stack( diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index c3360815ac9f8..8ab31f6f3825d 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -3,7 +3,10 @@ use std::num::NonZeroU32; use crate::parse::ParseSess; use rustc_ast::token; use rustc_ast::util::literal::LitError; -use rustc_errors::{error_code, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic, MultiSpan}; +use rustc_errors::{ + error_code, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic, + Level, MultiSpan, +}; use rustc_macros::Diagnostic; use rustc_span::{BytePos, Span, Symbol}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; @@ -17,9 +20,10 @@ impl<'a> IntoDiagnostic<'a> for FeatureGateError { #[track_caller] fn into_diagnostic( self, - dcx: &'a rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut diag = dcx.struct_err(self.explain); + dcx: &'a DiagCtxt, + level: Level, + ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + let mut diag = DiagnosticBuilder::new(dcx, level, self.explain); diag.set_span(self.span); diag.code(error_code!(E0658)); diag diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 2cb47e3a9329c..b33cc83f9cf35 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -14,7 +14,7 @@ use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, DiagCtxt}; use rustc_errors::{ fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, - ErrorGuaranteed, IntoDiagnostic, MultiSpan, Noted, StashKey, + ErrorGuaranteed, FatalAbort, IntoDiagnostic, Level, MultiSpan, StashKey, }; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; use rustc_span::edition::Edition; @@ -322,7 +322,7 @@ impl ParseSess { &'a self, err: impl IntoDiagnostic<'a>, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - err.into_diagnostic(&self.dcx) + err.into_diagnostic(&self.dcx, Level::Error { lint: false }) } #[track_caller] @@ -335,7 +335,7 @@ impl ParseSess { &'a self, warning: impl IntoDiagnostic<'a, ()>, ) -> DiagnosticBuilder<'a, ()> { - warning.into_diagnostic(&self.dcx) + warning.into_diagnostic(&self.dcx, Level::Warning(None)) } #[track_caller] @@ -346,26 +346,26 @@ impl ParseSess { #[track_caller] pub fn create_note<'a>( &'a self, - note: impl IntoDiagnostic<'a, Noted>, - ) -> DiagnosticBuilder<'a, Noted> { - note.into_diagnostic(&self.dcx) + note: impl IntoDiagnostic<'a, ()>, + ) -> DiagnosticBuilder<'a, ()> { + note.into_diagnostic(&self.dcx, Level::Note) } #[track_caller] - pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted { + pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) { self.create_note(note).emit() } #[track_caller] pub fn create_fatal<'a>( &'a self, - fatal: impl IntoDiagnostic<'a, !>, - ) -> DiagnosticBuilder<'a, !> { - fatal.into_diagnostic(&self.dcx) + fatal: impl IntoDiagnostic<'a, FatalAbort>, + ) -> DiagnosticBuilder<'a, FatalAbort> { + fatal.into_diagnostic(&self.dcx, Level::Fatal) } #[track_caller] - pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! { + pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, FatalAbort>) -> ! { self.create_fatal(fatal).emit() } @@ -386,7 +386,10 @@ impl ParseSess { #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_fatal(&self, msg: impl Into) -> DiagnosticBuilder<'_, !> { + pub fn struct_fatal( + &self, + msg: impl Into, + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx.struct_fatal(msg) } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 7f168572f7da6..c9f0f74b0b21e 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -23,8 +23,8 @@ use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; use rustc_errors::{ error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticId, - DiagnosticMessage, ErrorGuaranteed, FluentBundle, IntoDiagnostic, LazyFallbackBundle, - MultiSpan, Noted, TerminalUrl, + DiagnosticMessage, ErrorGuaranteed, FatalAbort, FluentBundle, IntoDiagnostic, + LazyFallbackBundle, MultiSpan, TerminalUrl, }; use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; @@ -428,7 +428,7 @@ impl Session { &self, sp: S, msg: impl Into, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx().struct_span_fatal(sp, msg) } #[rustc_lint_diagnostics] @@ -437,11 +437,14 @@ impl Session { sp: S, msg: impl Into, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx().struct_span_fatal_with_code(sp, msg, code) } #[rustc_lint_diagnostics] - pub fn struct_fatal(&self, msg: impl Into) -> DiagnosticBuilder<'_, !> { + pub fn struct_fatal( + &self, + msg: impl Into, + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx().struct_fatal(msg) } @@ -525,23 +528,23 @@ impl Session { #[track_caller] pub fn create_note<'a>( &'a self, - note: impl IntoDiagnostic<'a, Noted>, - ) -> DiagnosticBuilder<'a, Noted> { + note: impl IntoDiagnostic<'a, ()>, + ) -> DiagnosticBuilder<'a, ()> { self.parse_sess.create_note(note) } #[track_caller] - pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted { + pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) { self.parse_sess.emit_note(note) } #[track_caller] pub fn create_fatal<'a>( &'a self, - fatal: impl IntoDiagnostic<'a, !>, - ) -> DiagnosticBuilder<'a, !> { + fatal: impl IntoDiagnostic<'a, FatalAbort>, + ) -> DiagnosticBuilder<'a, FatalAbort> { self.parse_sess.create_fatal(fatal) } #[track_caller] - pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! { + pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, FatalAbort>) -> ! { self.parse_sess.emit_fatal(fatal) } #[inline] @@ -1780,7 +1783,7 @@ impl EarlyDiagCtxt { pub fn early_struct_error( &self, msg: impl Into, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx.struct_fatal(msg) } diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs index ff253b6f46702..06a2b3ca9c4f3 100644 --- a/compiler/rustc_symbol_mangling/src/errors.rs +++ b/compiler/rustc_symbol_mangling/src/errors.rs @@ -1,6 +1,6 @@ //! Errors emitted by symbol_mangling. -use rustc_errors::{ErrorGuaranteed, IntoDiagnostic}; +use rustc_errors::{DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level}; use rustc_span::Span; use std::fmt; @@ -13,15 +13,12 @@ pub struct TestOutput { // This diagnostic doesn't need translation because (a) it doesn't contain any // natural language, and (b) it's only used in tests. So we construct it // manually and avoid the fluent machinery. -impl IntoDiagnostic<'_> for TestOutput { - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { +impl IntoDiagnostic<'_, G> for TestOutput { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let TestOutput { span, kind, content } = self; #[allow(rustc::untranslatable_diagnostic)] - let mut diag = dcx.struct_err(format!("{kind}({content})")); + let mut diag = DiagnosticBuilder::new(dcx, level, format!("{kind}({content})")); diag.set_span(span); diag } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index b0ec8b3a4fa82..bea6fbd6ac5cd 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1,7 +1,7 @@ use crate::fluent_generated as fluent; use rustc_errors::{ - AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, ErrorGuaranteed, IntoDiagnostic, - SubdiagnosticMessage, + AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, EmissionGuarantee, + IntoDiagnostic, Level, SubdiagnosticMessage, }; use rustc_macros::Diagnostic; use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty}; @@ -57,13 +57,15 @@ pub struct NegativePositiveConflict<'tcx> { pub positive_impl_span: Result, } -impl IntoDiagnostic<'_> for NegativePositiveConflict<'_> { +impl IntoDiagnostic<'_, G> for NegativePositiveConflict<'_> { #[track_caller] fn into_diagnostic( self, dcx: &DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::trait_selection_negative_positive_conflict); + level: Level, + ) -> rustc_errors::DiagnosticBuilder<'_, G> { + let mut diag = + DiagnosticBuilder::new(dcx, level, fluent::trait_selection_negative_positive_conflict); diag.set_arg("trait_desc", self.trait_desc.print_only_trait_path().to_string()); diag.set_arg( "self_desc", diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index 4b006151c64c6..ab42d3b8c1e4e 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.rs +++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs @@ -13,8 +13,8 @@ extern crate rustc_session; extern crate rustc_span; use rustc_errors::{ - AddToDiagnostic, DiagCtxt, Diagnostic, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, - IntoDiagnostic, SubdiagnosticMessage, + AddToDiagnostic, Diagnostic, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, DiagCtxt, + IntoDiagnostic, Level, SubdiagnosticMessage, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -37,18 +37,18 @@ struct Note { pub struct UntranslatableInIntoDiagnostic; -impl<'a> IntoDiagnostic<'a, ErrorGuaranteed> for UntranslatableInIntoDiagnostic { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - dcx.struct_err("untranslatable diagnostic") +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UntranslatableInIntoDiagnostic { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + DiagnosticBuilder::new(dcx, level, "untranslatable diagnostic") //~^ ERROR diagnostics should be created using translatable messages } } pub struct TranslatableInIntoDiagnostic; -impl<'a> IntoDiagnostic<'a, ErrorGuaranteed> for TranslatableInIntoDiagnostic { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - dcx.struct_err(crate::fluent_generated::no_crate_example) +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for TranslatableInIntoDiagnostic { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + DiagnosticBuilder::new(dcx, level, crate::fluent_generated::no_crate_example) } } diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr index d18db3cbbd37a..f70240ecf172a 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr +++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr @@ -1,8 +1,8 @@ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:42:13 + --> $DIR/diagnostics.rs:42:9 | -LL | dcx.struct_err("untranslatable diagnostic") - | ^^^^^^^^^^ +LL | DiagnosticBuilder::new(dcx, level, "untranslatable diagnostic") + | ^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/diagnostics.rs:6:9 diff --git a/tests/ui/track-diagnostics/track.rs b/tests/ui/track-diagnostics/track.rs index 97bd7789a6337..08f926610d7ce 100644 --- a/tests/ui/track-diagnostics/track.rs +++ b/tests/ui/track-diagnostics/track.rs @@ -1,5 +1,7 @@ // compile-flags: -Z track-diagnostics // error-pattern: created at +// rustc-env:RUST_BACKTRACE=0 +// failure-status: 101 // Normalize the emitted location so this doesn't need // updating everytime someone adds or removes a line. diff --git a/tests/ui/track-diagnostics/track.stderr b/tests/ui/track-diagnostics/track.stderr index 60254dc475be6..54b1ea2764a5f 100644 --- a/tests/ui/track-diagnostics/track.stderr +++ b/tests/ui/track-diagnostics/track.stderr @@ -13,15 +13,31 @@ LL | break rust -Ztrack-diagnostics: created at compiler/rustc_passes/src/loops.rs:LL:CC error: internal compiler error: It looks like you're trying to break rust; would you like some ICE? + --> $DIR/track.rs:LL:CC + | +LL | break rust + | ^^^^^^^^^^ +-Ztrack-diagnostics: created at compiler/rustc_hir_typeck/src/lib.rs:LL:CC + | + = note: the compiler expectedly panicked. this is a feature. + = note: we would appreciate a joke overview: https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675 + = note: rustc $VERSION running on $TARGET + = note: compiler flags: ... -Z ui-testing ... -Z track-diagnostics -note: the compiler expectedly panicked. this is a feature. +thread 'rustc' panicked at compiler/rustc_hir_typeck/src/lib.rs:LL:CC: +Box +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: we would appreciate a joke overview: https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675 +note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md note: rustc $VERSION running on $TARGET note: compiler flags: ... -Z ui-testing ... -Z track-diagnostics +query stack during panic: +#0 [typeck] type-checking `main` +#1 [analysis] running analysis passes on this crate +end of query stack error: aborting due to 3 previous errors Some errors have detailed explanations: E0268, E0425.