From 505c1371d070ba6c9e15db7d331f2d6a2b167b68 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 24 Dec 2023 09:08:41 +1100 Subject: [PATCH 01/34] Rename some `Diagnostic` setters. `Diagnostic` has 40 methods that return `&mut Self` and could be considered setters. Four of them have a `set_` prefix. This doesn't seem necessary for a type that implements the builder pattern. This commit removes the `set_` prefixes on those four methods. --- compiler/rustc_ast_passes/src/errors.rs | 4 +- .../rustc_attr/src/session_diagnostics.rs | 8 +- compiler/rustc_builtin_macros/src/errors.rs | 6 +- compiler/rustc_builtin_macros/src/test.rs | 2 +- compiler/rustc_codegen_gcc/src/errors.rs | 4 +- compiler/rustc_codegen_llvm/src/errors.rs | 10 +-- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- compiler/rustc_codegen_ssa/src/errors.rs | 54 ++++++------ compiler/rustc_const_eval/src/errors.rs | 86 +++++++++---------- compiler/rustc_errors/src/diagnostic.rs | 13 +-- .../rustc_errors/src/diagnostic_builder.rs | 10 +-- compiler/rustc_errors/src/diagnostic_impls.rs | 32 +++---- compiler/rustc_errors/src/lib.rs | 12 +-- compiler/rustc_expand/src/expand.rs | 2 +- .../rustc_expand/src/proc_macro_server.rs | 2 +- .../src/astconv/generics.rs | 2 +- compiler/rustc_hir_analysis/src/errors.rs | 6 +- compiler/rustc_hir_typeck/src/errors.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_infer/src/errors/mod.rs | 34 +++----- .../src/errors/note_and_explain.rs | 8 +- compiler/rustc_lint/src/errors.rs | 2 +- compiler/rustc_lint/src/levels.rs | 2 +- compiler/rustc_lint/src/lints.rs | 24 +++--- compiler/rustc_lint/src/non_fmt_panic.rs | 6 +- .../src/diagnostics/diagnostic_builder.rs | 18 ++-- .../src/diagnostics/subdiagnostic.rs | 14 +-- .../rustc_macros/src/diagnostics/utils.rs | 6 +- compiler/rustc_metadata/src/errors.rs | 22 ++--- compiler/rustc_middle/src/lint.rs | 6 +- compiler/rustc_mir_build/src/errors.rs | 8 +- compiler/rustc_mir_transform/src/errors.rs | 24 +++--- compiler/rustc_monomorphize/src/errors.rs | 2 +- compiler/rustc_parse/src/errors.rs | 8 +- compiler/rustc_parse/src/lexer/mod.rs | 2 +- compiler/rustc_parse/src/lib.rs | 2 +- compiler/rustc_parse/src/parser/attr.rs | 2 +- .../rustc_parse/src/parser/diagnostics.rs | 4 +- compiler/rustc_parse/src/parser/mod.rs | 7 +- compiler/rustc_passes/src/check_attr.rs | 6 +- compiler/rustc_passes/src/errors.rs | 38 ++++---- compiler/rustc_pattern_analysis/src/lints.rs | 2 +- .../rustc_resolve/src/late/diagnostics.rs | 6 +- compiler/rustc_session/src/errors.rs | 2 +- compiler/rustc_symbol_mangling/src/errors.rs | 2 +- compiler/rustc_trait_selection/src/errors.rs | 17 ++-- .../src/traits/error_reporting/suggestions.rs | 6 +- .../error_reporting/type_err_ctxt_ext.rs | 4 +- .../passes/collect_intra_doc_links.rs | 2 +- src/tools/miri/src/diagnostics.rs | 2 +- ...diagnostic-derive-doc-comment-field.stderr | 4 +- .../session-diagnostic/diagnostic-derive.rs | 2 +- .../diagnostic-derive.stderr | 2 +- 53 files changed, 274 insertions(+), 281 deletions(-) diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 0cec4374be2ee..b177378c8e7ca 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -707,8 +707,8 @@ impl AddToDiagnostic for StableFeature { rustc_errors::SubdiagnosticMessage, ) -> rustc_errors::SubdiagnosticMessage, { - diag.set_arg("name", self.name); - diag.set_arg("since", self.since); + diag.arg("name", self.name); + diag.arg("since", self.since); diag.help(fluent::ast_passes_stable_since); } } diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index fd2b08668673c..fdb5d66bf62b5 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -55,10 +55,10 @@ 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 = DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item); - diag.set_span(self.span); + diag.span(self.span); diag.code(error_code!(E0541)); - diag.set_arg("item", self.item); - diag.set_arg("expected", expected.join(", ")); + diag.arg("item", self.item); + diag.arg("expected", expected.join(", ")); diag.span_label(self.span, fluent::attr_label); diag } @@ -215,7 +215,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral { } }, ); - diag.set_span(self.span); + diag.span(self.span); diag.code(error_code!(E0565)); if self.is_bytestr { diag.span_suggestion( diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index e07eb2e490b71..f9ddffcc155d5 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -454,7 +454,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefinedWithUserMe reason = "cannot translate user-provided messages" )] let mut diag = DiagnosticBuilder::new(dcx, level, self.msg_from_user.to_string()); - diag.set_span(self.span); + diag.span(self.span); diag } } @@ -618,7 +618,7 @@ impl AddToDiagnostic for FormatUnusedArg { rustc_errors::SubdiagnosticMessage, ) -> rustc_errors::SubdiagnosticMessage, { - diag.set_arg("named", self.named); + diag.arg("named", self.named); let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into()); diag.span_label(self.span, msg); } @@ -808,7 +808,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for AsmClobberNoReg { level, crate::fluent_generated::builtin_macros_asm_clobber_no_reg, ); - diag.set_span(self.spans.clone()); + diag.span(self.spans.clone()); // eager translation as `span_labels` takes `AsRef` let lbl1 = dcx.eagerly_translate_to_string( crate::fluent_generated::builtin_macros_asm_clobber_abi, diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 2af46f175d7d8..82fe043820ccd 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -398,7 +398,7 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>) _ => Level::Error { lint: false }, }; let mut err = DiagnosticBuilder::<()>::new(dcx, level, msg); - err.set_span(attr_sp); + err.span(attr_sp); if let Some(item) = item { err.span_label( item.span, diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 1b1ed0b411c71..e9283b1989453 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -119,12 +119,12 @@ impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl fluent::codegen_gcc_target_feature_disable_or_enable ); if let Some(span) = self.span { - diag.set_span(span); + diag.span(span); }; if let Some(missing_features) = self.missing_features { diag.subdiagnostic(missing_features); } - diag.set_arg("features", self.features.join(", ")); + diag.arg("features", self.features.join(", ")); diag } } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 8db97d577ca76..422e8edff5f64 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -107,7 +107,7 @@ impl IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_ let mut diag = DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config); - diag.set_arg("error", message); + diag.arg("error", message); diag } } @@ -130,12 +130,12 @@ impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl fluent::codegen_llvm_target_feature_disable_or_enable, ); if let Some(span) = self.span { - diag.set_span(span); + diag.span(span); }; if let Some(missing_features) = self.missing_features { diag.subdiagnostic(missing_features); } - diag.set_arg("features", self.features.join(", ")); + diag.arg("features", self.features.join(", ")); diag } } @@ -205,8 +205,8 @@ impl IntoDiagnostic<'_, G> for WithLlvmError<'_> { ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err, }; 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.primary_message(msg_with_llvm_err); + diag.arg("llvm_err", self.1); diag } } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 5a8db7bbf2d67..cb12470478500 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1860,7 +1860,7 @@ impl SharedEmitterMain { if cookie != 0 { let pos = BytePos::from_u32(cookie); let span = Span::with_root_ctxt(pos, pos); - err.set_span(span); + err.span(span); }; // Point to the generated assembly if it is available. diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 2b628d2aa69b7..c1086bebb8d48 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -244,30 +244,30 @@ impl IntoDiagnostic<'_, G> for ThorinErrorWrapper { } thorin::Error::NamelessSection(_, offset) => { diag = build(fluent::codegen_ssa_thorin_section_without_name); - diag.set_arg("offset", format!("0x{offset:08x}")); + diag.arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::RelocationWithInvalidSymbol(section, offset) => { diag = build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol); - diag.set_arg("section", section); - diag.set_arg("offset", format!("0x{offset:08x}")); + diag.arg("section", section); + diag.arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::MultipleRelocations(section, offset) => { diag = build(fluent::codegen_ssa_thorin_multiple_relocations); - diag.set_arg("section", section); - diag.set_arg("offset", format!("0x{offset:08x}")); + diag.arg("section", section); + diag.arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::UnsupportedRelocation(section, offset) => { diag = build(fluent::codegen_ssa_thorin_unsupported_relocation); - diag.set_arg("section", section); - diag.set_arg("offset", format!("0x{offset:08x}")); + diag.arg("section", section); + diag.arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::MissingDwoName(id) => { diag = build(fluent::codegen_ssa_thorin_missing_dwo_name); - diag.set_arg("id", format!("0x{id:08x}")); + diag.arg("id", format!("0x{id:08x}")); diag } thorin::Error::NoCompilationUnits => { @@ -284,7 +284,7 @@ impl IntoDiagnostic<'_, G> for ThorinErrorWrapper { } thorin::Error::MissingRequiredSection(section) => { diag = build(fluent::codegen_ssa_thorin_missing_required_section); - diag.set_arg("section", section); + diag.arg("section", section); diag } thorin::Error::ParseUnitAbbreviations(_) => { @@ -305,34 +305,34 @@ impl IntoDiagnostic<'_, G> for ThorinErrorWrapper { } thorin::Error::IncompatibleIndexVersion(section, format, actual) => { 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.arg("section", section); + diag.arg("actual", actual); + diag.arg("format", format); diag } thorin::Error::OffsetAtIndex(_, index) => { diag = build(fluent::codegen_ssa_thorin_offset_at_index); - diag.set_arg("index", index); + diag.arg("index", index); diag } thorin::Error::StrAtOffset(_, offset) => { diag = build(fluent::codegen_ssa_thorin_str_at_offset); - diag.set_arg("offset", format!("0x{offset:08x}")); + diag.arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::ParseIndex(_, section) => { diag = build(fluent::codegen_ssa_thorin_parse_index); - diag.set_arg("section", section); + diag.arg("section", section); diag } thorin::Error::UnitNotInIndex(unit) => { diag = build(fluent::codegen_ssa_thorin_unit_not_in_index); - diag.set_arg("unit", format!("0x{unit:08x}")); + diag.arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::RowNotInIndex(_, row) => { diag = build(fluent::codegen_ssa_thorin_row_not_in_index); - diag.set_arg("row", row); + diag.arg("row", row); diag } thorin::Error::SectionNotInRow => { @@ -341,7 +341,7 @@ impl IntoDiagnostic<'_, G> for ThorinErrorWrapper { } thorin::Error::EmptyUnit(unit) => { diag = build(fluent::codegen_ssa_thorin_empty_unit); - diag.set_arg("unit", format!("0x{unit:08x}")); + diag.arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::MultipleDebugInfoSection => { @@ -358,12 +358,12 @@ impl IntoDiagnostic<'_, G> for ThorinErrorWrapper { } thorin::Error::DuplicateUnit(unit) => { diag = build(fluent::codegen_ssa_thorin_duplicate_unit); - diag.set_arg("unit", format!("0x{unit:08x}")); + diag.arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::MissingReferencedUnit(unit) => { diag = build(fluent::codegen_ssa_thorin_missing_referenced_unit); - diag.set_arg("unit", format!("0x{unit:08x}")); + diag.arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::NoOutputObjectCreated => { @@ -376,27 +376,27 @@ impl IntoDiagnostic<'_, G> for ThorinErrorWrapper { } thorin::Error::Io(e) => { diag = build(fluent::codegen_ssa_thorin_io); - diag.set_arg("error", format!("{e}")); + diag.arg("error", format!("{e}")); diag } thorin::Error::ObjectRead(e) => { diag = build(fluent::codegen_ssa_thorin_object_read); - diag.set_arg("error", format!("{e}")); + diag.arg("error", format!("{e}")); diag } thorin::Error::ObjectWrite(e) => { diag = build(fluent::codegen_ssa_thorin_object_write); - diag.set_arg("error", format!("{e}")); + diag.arg("error", format!("{e}")); diag } thorin::Error::GimliRead(e) => { diag = build(fluent::codegen_ssa_thorin_gimli_read); - diag.set_arg("error", format!("{e}")); + diag.arg("error", format!("{e}")); diag } thorin::Error::GimliWrite(e) => { diag = build(fluent::codegen_ssa_thorin_gimli_write); - diag.set_arg("error", format!("{e}")); + diag.arg("error", format!("{e}")); diag } _ => unimplemented!("Untranslated thorin error"), @@ -414,8 +414,8 @@ pub struct LinkingFailed<'a> { 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)); + diag.arg("linker_path", format!("{}", self.linker_path.display())); + diag.arg("exit_status", format!("{}", self.exit_status)); let contains_undefined_ref = self.escaped_output.contains("undefined reference to"); diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 110ff87e27ef3..171cc89d6adb8 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -518,7 +518,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { Ub(_) => {} Custom(custom) => { (custom.add_args)(&mut |name, value| { - builder.set_arg(name, value); + builder.arg(name, value); }); } ValidationError(e) => e.add_args(dcx, builder), @@ -536,65 +536,65 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { | UninhabitedEnumVariantWritten(_) | UninhabitedEnumVariantRead(_) => {} BoundsCheckFailed { len, index } => { - builder.set_arg("len", len); - builder.set_arg("index", index); + builder.arg("len", len); + builder.arg("index", index); } UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => { - builder.set_arg("pointer", ptr); + builder.arg("pointer", ptr); } PointerUseAfterFree(alloc_id, msg) => { builder - .set_arg("alloc_id", alloc_id) - .set_arg("bad_pointer_message", bad_pointer_message(msg, dcx)); + .arg("alloc_id", alloc_id) + .arg("bad_pointer_message", bad_pointer_message(msg, dcx)); } PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => { builder - .set_arg("alloc_id", alloc_id) - .set_arg("alloc_size", alloc_size.bytes()) - .set_arg("ptr_offset", ptr_offset) - .set_arg("ptr_size", ptr_size.bytes()) - .set_arg("bad_pointer_message", bad_pointer_message(msg, dcx)); + .arg("alloc_id", alloc_id) + .arg("alloc_size", alloc_size.bytes()) + .arg("ptr_offset", ptr_offset) + .arg("ptr_size", ptr_size.bytes()) + .arg("bad_pointer_message", bad_pointer_message(msg, dcx)); } DanglingIntPointer(ptr, msg) => { if ptr != 0 { - builder.set_arg("pointer", format!("{ptr:#x}[noalloc]")); + builder.arg("pointer", format!("{ptr:#x}[noalloc]")); } - builder.set_arg("bad_pointer_message", bad_pointer_message(msg, dcx)); + builder.arg("bad_pointer_message", bad_pointer_message(msg, dcx)); } AlignmentCheckFailed(Misalignment { required, has }, msg) => { - builder.set_arg("required", required.bytes()); - builder.set_arg("has", has.bytes()); - builder.set_arg("msg", format!("{msg:?}")); + builder.arg("required", required.bytes()); + builder.arg("has", has.bytes()); + builder.arg("msg", format!("{msg:?}")); } WriteToReadOnly(alloc) | DerefFunctionPointer(alloc) | DerefVTablePointer(alloc) => { - builder.set_arg("allocation", alloc); + builder.arg("allocation", alloc); } InvalidBool(b) => { - builder.set_arg("value", format!("{b:02x}")); + builder.arg("value", format!("{b:02x}")); } InvalidChar(c) => { - builder.set_arg("value", format!("{c:08x}")); + builder.arg("value", format!("{c:08x}")); } InvalidTag(tag) => { - builder.set_arg("tag", format!("{tag:x}")); + builder.arg("tag", format!("{tag:x}")); } InvalidStr(err) => { - builder.set_arg("err", format!("{err}")); + builder.arg("err", format!("{err}")); } InvalidUninitBytes(Some((alloc, info))) => { - builder.set_arg("alloc", alloc); - builder.set_arg("access", info.access); - builder.set_arg("uninit", info.bad); + builder.arg("alloc", alloc); + builder.arg("access", info.access); + builder.arg("uninit", info.bad); } ScalarSizeMismatch(info) => { - builder.set_arg("target_size", info.target_size); - builder.set_arg("data_size", info.data_size); + builder.arg("target_size", info.target_size); + builder.arg("data_size", info.data_size); } AbiMismatchArgument { caller_ty, callee_ty } | AbiMismatchReturn { caller_ty, callee_ty } => { - builder.set_arg("caller_ty", caller_ty.to_string()); - builder.set_arg("callee_ty", callee_ty.to_string()); + builder.arg("caller_ty", caller_ty.to_string()); + builder.arg("callee_ty", callee_ty.to_string()); } } } @@ -695,7 +695,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { ) }; - err.set_arg("front_matter", message); + err.arg("front_matter", message); fn add_range_arg( r: WrappingRange, @@ -725,12 +725,12 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { ]; let args = args.iter().map(|(a, b)| (a, b)); let message = dcx.eagerly_translate_to_string(msg, args); - err.set_arg("in_range", message); + err.arg("in_range", message); } match self.kind { PtrToUninhabited { ty, .. } | UninhabitedVal { ty } => { - err.set_arg("ty", ty); + err.arg("ty", ty); } PointerAsInt { expected } | Uninit { expected } => { let msg = match expected { @@ -747,28 +747,28 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { ExpectedKind::Str => fluent::const_eval_validation_expected_str, }; let msg = dcx.eagerly_translate_to_string(msg, [].into_iter()); - err.set_arg("expected", msg); + err.arg("expected", msg); } InvalidEnumTag { value } | InvalidVTablePtr { value } | InvalidBool { value } | InvalidChar { value } | InvalidFnPtr { value } => { - err.set_arg("value", value); + err.arg("value", value); } NullablePtrOutOfRange { range, max_value } | PtrOutOfRange { range, max_value } => { add_range_arg(range, max_value, dcx, err) } OutOfRange { range, max_value, value } => { - err.set_arg("value", value); + err.arg("value", value); add_range_arg(range, max_value, dcx, err); } UnalignedPtr { required_bytes, found_bytes, .. } => { - err.set_arg("required_bytes", required_bytes); - err.set_arg("found_bytes", found_bytes); + err.arg("required_bytes", required_bytes); + err.arg("found_bytes", found_bytes); } DanglingPtrNoProvenance { pointer, .. } => { - err.set_arg("pointer", pointer); + err.arg("pointer", pointer); } NullPtr { .. } | PtrToStatic { .. } @@ -814,10 +814,10 @@ impl ReportErrorExt for UnsupportedOpInfo { // print. So it's not worth the effort of having diagnostics that can print the `info`. UnsizedLocal | Unsupported(_) | ReadPointerAsInt(_) => {} OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => { - builder.set_arg("ptr", ptr); + builder.arg("ptr", ptr); } ThreadLocalStatic(did) | ReadExternStatic(did) => { - builder.set_arg("did", format!("{did:?}")); + builder.arg("did", format!("{did:?}")); } } } @@ -844,7 +844,7 @@ impl<'tcx> ReportErrorExt for InterpError<'tcx> { InterpError::InvalidProgram(e) => e.add_args(dcx, builder), InterpError::ResourceExhaustion(e) => e.add_args(dcx, builder), InterpError::MachineStop(e) => e.add_args(&mut |name, value| { - builder.set_arg(name, value); + builder.arg(name, value); }), } } @@ -880,15 +880,15 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { let diag: DiagnosticBuilder<'_, ()> = e.into_diagnostic().into_diagnostic(dcx, dummy_level); for (name, val) in diag.args() { - builder.set_arg(name.clone(), val.clone()); + builder.arg(name.clone(), val.clone()); } diag.cancel(); } InvalidProgramInfo::FnAbiAdjustForForeignAbi( AdjustForForeignAbiError::Unsupported { arch, abi }, ) => { - builder.set_arg("arch", arch); - builder.set_arg("abi", abi.name()); + builder.arg("arch", arch); + builder.arg("abi", abi.name()); } } } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 49431fb7b3f18..f2d54eb427db3 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -212,6 +212,9 @@ impl StringPart { } } +// Note: most of these methods are setters that return `&mut Self`. The small +// number of simple getter functions all have `get_` prefixes to distinguish +// them from the setters. impl Diagnostic { #[track_caller] pub fn new>(level: Level, message: M) -> Self { @@ -344,7 +347,7 @@ impl Diagnostic { pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self { let before = self.span.clone(); - self.set_span(after); + self.span(after); for span_label in before.span_labels() { if let Some(label) = span_label.label { if span_label.is_primary && keep_label { @@ -876,7 +879,7 @@ impl Diagnostic { self } - pub fn set_span>(&mut self, sp: S) -> &mut Self { + pub fn span>(&mut self, sp: S) -> &mut Self { self.span = sp.into(); if let Some(span) = self.span.primary_span() { self.sort_span = span; @@ -884,7 +887,7 @@ impl Diagnostic { self } - pub fn set_is_lint(&mut self) -> &mut Self { + pub fn is_lint(&mut self) -> &mut Self { self.is_lint = true; self } @@ -903,7 +906,7 @@ impl Diagnostic { self.code.clone() } - pub fn set_primary_message(&mut self, msg: impl Into) -> &mut Self { + pub fn primary_message(&mut self, msg: impl Into) -> &mut Self { self.messages[0] = (msg.into(), Style::NoStyle); self } @@ -915,7 +918,7 @@ impl Diagnostic { self.args.iter() } - pub fn set_arg( + pub fn arg( &mut self, name: impl Into>, arg: impl IntoDiagnosticArg, diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index ae54d343dad96..d8838bbdbab1d 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -31,7 +31,7 @@ where { 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.span(self.span); diag } } @@ -428,7 +428,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { sp: impl Into, msg: impl Into, ) -> &mut Self); - forward!(pub fn set_is_lint(&mut self,) -> &mut Self); + forward!(pub fn is_lint(&mut self,) -> &mut Self); forward!(pub fn disable_suggestions(&mut self,) -> &mut Self); @@ -499,10 +499,10 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { applicability: Applicability, ) -> &mut Self); - forward!(pub fn set_primary_message(&mut self, msg: impl Into) -> &mut Self); - forward!(pub fn set_span(&mut self, sp: impl Into) -> &mut Self); + forward!(pub fn primary_message(&mut self, msg: impl Into) -> &mut Self); + forward!(pub fn span(&mut self, sp: impl Into) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); - forward!(pub fn set_arg( + forward!(pub fn arg( &mut self, name: impl Into>, arg: impl IntoDiagnosticArg, diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 29cb304e8b5b0..de27c6e910b2b 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -254,29 +254,29 @@ impl IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_> TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => { 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.arg("addr_space", addr_space); + diag.arg("cause", cause); + diag.arg("err", err); diag } TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => { 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); - diag.set_arg("err", err); + diag.arg("kind", kind); + diag.arg("bit", bit); + diag.arg("cause", cause); + diag.arg("err", err); diag } TargetDataLayoutErrors::MissingAlignment { cause } => { diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_missing_alignment); - diag.set_arg("cause", cause); + diag.arg("cause", cause); diag } TargetDataLayoutErrors::InvalidAlignment { cause, err } => { 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.arg("cause", cause); + diag.arg("err_kind", err.diag_ident()); + diag.arg("align", err.align()); diag } TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => { @@ -285,8 +285,8 @@ impl IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_> level, fluent::errors_target_inconsistent_architecture, ); - diag.set_arg("dl", dl); - diag.set_arg("target", target); + diag.arg("dl", dl); + diag.arg("target", target); diag } TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => { @@ -295,13 +295,13 @@ impl IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_> level, fluent::errors_target_inconsistent_pointer_width, ); - diag.set_arg("pointer_size", pointer_size); - diag.set_arg("target", target); + diag.arg("pointer_size", pointer_size); + diag.arg("target", target); diag } TargetDataLayoutErrors::InvalidBitsSize { err } => { diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits_size); - diag.set_arg("err", err); + diag.arg("err", err); diag } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index e9507dcfed7e4..6dc3a8cd08ece 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -732,7 +732,7 @@ impl DiagCtxt { msg: impl Into, ) -> DiagnosticBuilder<'_, ()> { let mut result = self.struct_warn(msg); - result.set_span(span); + result.span(span); result } @@ -789,7 +789,7 @@ impl DiagCtxt { msg: impl Into, ) -> DiagnosticBuilder<'_> { let mut result = self.struct_err(msg); - result.set_span(span); + result.span(span); result } @@ -850,7 +850,7 @@ impl DiagCtxt { msg: impl Into, ) -> DiagnosticBuilder<'_, FatalAbort> { let mut result = self.struct_fatal(msg); - result.set_span(span); + result.span(span); result } @@ -917,7 +917,7 @@ impl DiagCtxt { msg: impl Into, ) -> DiagnosticBuilder<'_, BugAbort> { let mut result = self.struct_bug(msg); - result.set_span(span); + result.span(span); result } @@ -1008,7 +1008,7 @@ impl DiagCtxt { self.span_bug(sp, msg); } let mut diagnostic = Diagnostic::new(DelayedBug, msg); - diagnostic.set_span(sp); + diagnostic.span(sp); self.emit_diagnostic(diagnostic).unwrap() } @@ -1039,7 +1039,7 @@ impl DiagCtxt { msg: impl Into, ) -> DiagnosticBuilder<'_, ()> { let mut db = DiagnosticBuilder::new(self, Note, msg); - db.set_span(span); + db.span(span); db } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 676f9f17976cf..5a616e0ffbff3 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -855,7 +855,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } Err(mut err) => { if err.span.is_dummy() { - err.set_span(span); + err.span(span); } annotate_err_with_kind(&mut err, kind, span); err.emit(); diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 5eb6aed72534d..2c08891b1096a 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -497,7 +497,7 @@ impl server::FreeFunctions for Rustc<'_, '_> { fn emit_diagnostic(&mut self, diagnostic: Diagnostic) { let mut diag = rustc_errors::Diagnostic::new(diagnostic.level.to_internal(), diagnostic.message); - diag.set_span(MultiSpan::from_spans(diagnostic.spans)); + diag.span(MultiSpan::from_spans(diagnostic.spans)); for child in diagnostic.children { diag.sub(child.level.to_internal(), child.message, MultiSpan::from_spans(child.spans)); } diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 7d840ba7e8153..3f0ad6584b65f 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -70,7 +70,7 @@ fn generic_arg_mismatch_err( Res::Err => { add_braces_suggestion(arg, &mut err); return err - .set_primary_message("unresolved item provided when a constant was expected") + .primary_message("unresolved item provided when a constant was expected") .emit(); } Res::Def(DefKind::TyParam, src_def_id) => { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 75e7a5524a744..9124d50211056 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -319,10 +319,10 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for MissingTypeParams { #[track_caller] 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.span(self.span); err.code(error_code!(E0393)); - err.set_arg("parameterCount", self.missing_type_params.len()); - err.set_arg( + err.arg("parameterCount", self.missing_type_params.len()); + err.arg( "parameters", self.missing_type_params .iter() diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index ff03cf16a27f3..4f92906888796 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -215,7 +215,7 @@ impl AddToDiagnostic for TypeMismatchFruTypo { where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { - diag.set_arg("expr", self.expr.as_deref().unwrap_or("NONE")); + diag.arg("expr", self.expr.as_deref().unwrap_or("NONE")); // Only explain that `a ..b` is a range if it's split up if self.expr_span.between(self.fru_span).is_empty() { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 47fdd64796e9d..bba40b1fa3d9f 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -961,7 +961,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { but its trait bounds were not satisfied" ) }); - err.set_primary_message(primary_message); + err.primary_message(primary_message); if let Some(label) = label { custom_span_label = true; err.span_label(span, label); diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index a0768fc711546..aee99063e0396 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -247,8 +247,8 @@ impl AddToDiagnostic for RegionOriginNote<'_> { } RegionOriginNote::WithName { span, msg, name, continues } => { label_or_note(span, msg); - diag.set_arg("name", name); - diag.set_arg("continues", continues); + diag.arg("name", name); + diag.arg("continues", continues); } RegionOriginNote::WithRequirement { span, @@ -256,7 +256,7 @@ impl AddToDiagnostic for RegionOriginNote<'_> { expected_found: Some((expected, found)), } => { label_or_note(span, fluent::infer_subtype); - diag.set_arg("requirement", requirement); + diag.arg("requirement", requirement); diag.note_expected_found(&"", expected, &"", found); } @@ -265,7 +265,7 @@ impl AddToDiagnostic for RegionOriginNote<'_> { // handling of region checking when type errors are present is // *terrible*. label_or_note(span, fluent::infer_subtype_2); - diag.set_arg("requirement", requirement); + diag.arg("requirement", requirement); } }; } @@ -298,8 +298,8 @@ impl AddToDiagnostic for LifetimeMismatchLabels { diag.span_label(param_span, fluent::infer_declared_different); diag.span_label(ret_span, fluent::infer_nothing); diag.span_label(span, fluent::infer_data_returned); - diag.set_arg("label_var1_exists", label_var1.is_some()); - diag.set_arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); + diag.arg("label_var1_exists", label_var1.is_some()); + diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); } LifetimeMismatchLabels::Normal { hir_equal, @@ -317,16 +317,10 @@ impl AddToDiagnostic for LifetimeMismatchLabels { diag.span_label(ty_sup, fluent::infer_types_declared_different); diag.span_label(ty_sub, fluent::infer_nothing); diag.span_label(span, fluent::infer_data_flows); - diag.set_arg("label_var1_exists", label_var1.is_some()); - diag.set_arg( - "label_var1", - label_var1.map(|x| x.to_string()).unwrap_or_default(), - ); - diag.set_arg("label_var2_exists", label_var2.is_some()); - diag.set_arg( - "label_var2", - label_var2.map(|x| x.to_string()).unwrap_or_default(), - ); + diag.arg("label_var1_exists", label_var1.is_some()); + diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); + diag.arg("label_var2_exists", label_var2.is_some()); + diag.arg("label_var2", label_var2.map(|x| x.to_string()).unwrap_or_default()); } } } @@ -417,7 +411,7 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> { suggestions, Applicability::MaybeIncorrect, ); - diag.set_arg("is_impl", is_impl); + diag.arg("is_impl", is_impl); true }; if mk_suggestion() && self.add_note { @@ -878,8 +872,8 @@ impl AddToDiagnostic for MoreTargeted { F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { diag.code(rustc_errors::error_code!(E0772)); - diag.set_primary_message(fluent::infer_more_targeted); - diag.set_arg("ident", self.ident); + diag.primary_message(fluent::infer_more_targeted); + diag.arg("ident", self.ident); } } @@ -1299,7 +1293,7 @@ impl AddToDiagnostic for SuggestTuplePatternMany { where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { - diag.set_arg("path", self.path); + diag.arg("path", self.path); let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into()); diag.multipart_suggestions( message, diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index 68bf36a1615dd..8e45cc6d80e92 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -164,10 +164,10 @@ impl AddToDiagnostic for RegionExplanation<'_> { where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { - diag.set_arg("pref_kind", self.prefix); - diag.set_arg("suff_kind", self.suffix); - diag.set_arg("desc_kind", self.desc.kind); - diag.set_arg("desc_arg", self.desc.arg); + diag.arg("pref_kind", self.prefix); + diag.arg("suff_kind", self.suffix); + diag.arg("desc_kind", self.desc.kind); + diag.arg("desc_arg", self.desc.arg); let msg = f(diag, fluent::infer_region_explanation.into()); if let Some(span) = self.desc.span { diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index eccea35c702e0..841d282a09942 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -31,7 +31,7 @@ impl AddToDiagnostic for OverruledAttributeSub { match self { OverruledAttributeSub::DefaultSource { id } => { diag.note(fluent::lint_default_source); - diag.set_arg("id", id); + diag.arg("id", id); } OverruledAttributeSub::NodeSource { span, reason } => { diag.span_label(span, fluent::lint_node_source); diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 5950bc76adeb7..49821437b7657 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -1069,7 +1069,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { Some(span.into()), fluent::lint_unknown_gated_lint, |lint| { - lint.set_arg("name", lint_id.lint.name_lower()); + lint.arg("name", lint_id.lint.name_lower()); lint.note(fluent::lint_note); rustc_session::parse::add_feature_diagnostics_for_issue( lint, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index ca6408bdf3ddb..1b81402e0031d 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -135,7 +135,7 @@ pub struct BuiltinMissingDebugImpl<'a> { // Needed for def_path_str impl<'a> DecorateLint<'a, ()> for BuiltinMissingDebugImpl<'_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("debug", self.tcx.def_path_str(self.def_id)); + diag.arg("debug", self.tcx.def_path_str(self.def_id)); } fn msg(&self) -> DiagnosticMessage { @@ -426,7 +426,7 @@ pub struct BuiltinUnpermittedTypeInit<'a> { impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("ty", self.ty); + diag.arg("ty", self.ty); diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label); if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) { // Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited. @@ -830,7 +830,7 @@ impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub { // FIXME: in other suggestions we've reversed the inner spans of doc comments. We // should do the same here to provide the same good suggestions as we do for // literals above. - diag.set_arg( + diag.arg( "escaped", spans .into_iter() @@ -1148,7 +1148,7 @@ pub struct NonFmtPanicUnused { // Used because of two suggestions based on one Option impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("count", self.count); + diag.arg("count", self.count); diag.note(fluent::lint_note); if let Some(span) = self.suggestion { diag.span_suggestion( @@ -1343,8 +1343,8 @@ pub struct DropTraitConstraintsDiag<'a> { // Needed for def_path_str impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("predicate", self.predicate); - diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id)); + diag.arg("predicate", self.predicate); + diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); } fn msg(&self) -> rustc_errors::DiagnosticMessage { @@ -1360,7 +1360,7 @@ pub struct DropGlue<'a> { // Needed for def_path_str impl<'a> DecorateLint<'a, ()> for DropGlue<'_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id)); + diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); } fn msg(&self) -> rustc_errors::DiagnosticMessage { @@ -1634,8 +1634,8 @@ pub struct ImproperCTypes<'a> { // Used because of the complexity of Option, DiagnosticMessage, and Option impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("ty", self.ty); - diag.set_arg("desc", self.desc); + diag.arg("ty", self.ty); + diag.arg("desc", self.desc); diag.span_label(self.label, fluent::lint_label); if let Some(help) = self.help { diag.help(help); @@ -1777,9 +1777,9 @@ pub enum UnusedDefSuggestion { // Needed because of def_path_str impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("pre", self.pre); - diag.set_arg("post", self.post); - diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id)); + diag.arg("pre", self.pre); + diag.arg("post", self.post); + diag.arg("def", self.cx.tcx.def_path_str(self.def_id)); // check for #[must_use = "..."] if let Some(note) = self.note { diag.note(note.to_string()); diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 9fcd70ba0b569..f0bbc03d74777 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -121,7 +121,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc #[allow(rustc::diagnostic_outside_of_impl)] cx.struct_span_lint(NON_FMT_PANICS, arg_span, fluent::lint_non_fmt_panic, |lint| { - lint.set_arg("name", symbol); + lint.arg("name", symbol); lint.note(fluent::lint_note); lint.note(fluent::lint_more_info_note); if !is_arg_inside_call(arg_span, span) { @@ -180,7 +180,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc fmt_applicability, ); } else if suggest_debug { - lint.set_arg("ty", ty); + lint.arg("ty", ty); lint.span_suggestion_verbose( arg_span.shrink_to_lo(), fluent::lint_debug_suggestion, @@ -191,7 +191,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc if suggest_panic_any { if let Some((open, close, del)) = find_delimiters(cx, span) { - lint.set_arg("already_suggested", suggest_display || suggest_debug); + lint.arg("already_suggested", suggest_display || suggest_debug); lint.multipart_suggestion( fluent::lint_panic_suggestion, if del == '(' { diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index f3e98d68b6040..fb908fe2db155 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -5,8 +5,8 @@ use crate::diagnostics::error::{ }; use crate::diagnostics::utils::{ build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error, - should_generate_set_arg, type_is_bool, type_is_unit, type_matches_path, FieldInfo, - FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind, + should_generate_arg, type_is_bool, type_is_unit, type_matches_path, FieldInfo, FieldInnerTy, + FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind, }; use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned}; @@ -125,15 +125,15 @@ impl DiagnosticDeriveVariantBuilder { } /// Generates calls to `span_label` and similar functions based on the attributes on fields or - /// calls to `set_arg` when no attributes are present. + /// calls to `arg` when no attributes are present. pub(crate) fn body(&mut self, variant: &VariantInfo<'_>) -> TokenStream { let mut body = quote! {}; - // Generate `set_arg` calls first.. - for binding in variant.bindings().iter().filter(|bi| should_generate_set_arg(bi.ast())) { + // Generate `arg` calls first.. + for binding in variant.bindings().iter().filter(|bi| should_generate_arg(bi.ast())) { body.extend(self.generate_field_code(binding)); } // ..and then subdiagnostic additions. - for binding in variant.bindings().iter().filter(|bi| !should_generate_set_arg(bi.ast())) { + for binding in variant.bindings().iter().filter(|bi| !should_generate_arg(bi.ast())) { body.extend(self.generate_field_attrs_code(binding)); } body @@ -253,7 +253,7 @@ impl DiagnosticDeriveVariantBuilder { let ident = format_ident!("{}", ident); // strip `r#` prefix, if present quote! { - diag.set_arg( + diag.arg( stringify!(#ident), #field_binding ); @@ -312,7 +312,7 @@ impl DiagnosticDeriveVariantBuilder { let name = ident.to_string(); match (&attr.meta, name.as_str()) { // Don't need to do anything - by virtue of the attribute existing, the - // `set_arg` call will not be generated. + // `arg` call will not be generated. (Meta::Path(_), "skip_arg") => return Ok(quote! {}), (Meta::Path(_), "primary_span") => { match self.kind { @@ -320,7 +320,7 @@ impl DiagnosticDeriveVariantBuilder { report_error_if_not_applied_to_span(attr, &info)?; return Ok(quote! { - diag.set_span(#binding); + diag.span(#binding); }); } DiagnosticDeriveKind::LintDiagnostic => { diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 663abecb67c6e..c029b931e7dde 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -6,8 +6,8 @@ use crate::diagnostics::error::{ use crate::diagnostics::utils::{ build_field_mapping, build_suggestion_code, is_doc_comment, new_code_ident, report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, - should_generate_set_arg, AllowMultipleAlternatives, FieldInfo, FieldInnerTy, FieldMap, - HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind, + should_generate_arg, AllowMultipleAlternatives, FieldInfo, FieldInnerTy, FieldMap, HasFieldMap, + SetOnce, SpannedOption, SubdiagnosticKind, }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; @@ -214,7 +214,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } /// Generates the code for a field with no attributes. - fn generate_field_set_arg(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { + fn generate_field_arg(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { let diag = &self.parent.diag; let field = binding_info.ast(); @@ -225,7 +225,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let ident = format_ident!("{}", ident); // strip `r#` prefix, if present quote! { - #diag.set_arg( + #diag.arg( stringify!(#ident), #field_binding ); @@ -505,7 +505,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { .variant .bindings() .iter() - .filter(|binding| !should_generate_set_arg(binding.ast())) + .filter(|binding| !should_generate_arg(binding.ast())) .map(|binding| self.generate_field_attr_code(binding, kind_stats)) .collect(); @@ -593,8 +593,8 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { .variant .bindings() .iter() - .filter(|binding| should_generate_set_arg(binding.ast())) - .map(|binding| self.generate_field_set_arg(binding)) + .filter(|binding| should_generate_arg(binding.ast())) + .map(|binding| self.generate_field_arg(binding)) .collect(); let formatting_init = &self.formatting_init; diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 2700f02e33a66..4684306e23592 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -584,7 +584,7 @@ pub(super) enum SubdiagnosticKind { suggestion_kind: SuggestionKind, applicability: SpannedOption, /// Identifier for variable used for formatted code, e.g. `___code_0`. Enables separation - /// of formatting and diagnostic emission so that `set_arg` calls can happen in-between.. + /// of formatting and diagnostic emission so that `arg` calls can happen in-between.. code_field: syn::Ident, /// Initialization logic for `code_field`'s variable, e.g. /// `let __formatted_code = /* whatever */;` @@ -863,9 +863,9 @@ impl quote::IdentFragment for SubdiagnosticKind { } } -/// Returns `true` if `field` should generate a `set_arg` call rather than any other diagnostic +/// Returns `true` if `field` should generate a `arg` call rather than any other diagnostic /// call (like `span_label`). -pub(super) fn should_generate_set_arg(field: &Field) -> bool { +pub(super) fn should_generate_arg(field: &Field) -> bool { // Perhaps this should be an exhaustive list... field.attrs.iter().all(|attr| is_doc_comment(attr)) } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index e13068cb6f9e4..27c26d3178144 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -500,10 +500,10 @@ pub(crate) struct MultipleCandidates { 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.arg("crate_name", self.crate_name); + diag.arg("flavor", self.flavor); diag.code(error_code!(E0464)); - diag.set_span(self.span); + diag.span(self.span); for (i, candidate) in self.candidates.iter().enumerate() { diag.note(format!("candidate #{}: {}", i + 1, candidate.display())); } @@ -596,10 +596,10 @@ impl IntoDiagnostic<'_, G> for InvalidMetadataFiles { #[track_caller] 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.arg("crate_name", self.crate_name); + diag.arg("add_info", self.add_info); diag.code(error_code!(E0786)); - diag.set_span(self.span); + diag.span(self.span); for crate_rejection in self.crate_rejections { diag.note(crate_rejection); } @@ -623,12 +623,12 @@ impl IntoDiagnostic<'_, G> for CannotFindCrate { #[track_caller] 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); - diag.set_arg("locator_triple", self.locator_triple.triple()); + diag.arg("crate_name", self.crate_name); + diag.arg("current_crate", self.current_crate); + diag.arg("add_info", self.add_info); + diag.arg("locator_triple", self.locator_triple.triple()); diag.code(error_code!(E0463)); - diag.set_span(self.span); + diag.span(self.span); if (self.crate_name == sym::std || self.crate_name == sym::core) && self.locator_triple != TargetTriple::from_triple(config::host_triple()) { diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index ae432a0406567..ea1439c959d50 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -318,10 +318,10 @@ pub fn struct_lint_level( }; let mut err = DiagnosticBuilder::new(sess.dcx(), err_level, ""); if let Some(span) = span { - err.set_span(span); + err.span(span); } - err.set_is_lint(); + err.is_lint(); // If this code originates in a foreign macro, aka something that this crate // did not itself author, then it's likely that there's nothing this crate @@ -348,7 +348,7 @@ pub fn struct_lint_level( // Delay evaluating and setting the primary message until after we've // suppressed the lint due to macros. - err.set_primary_message(msg); + err.primary_message(msg); // Lint diagnostics that are covered by the expect level will not be emitted outside // the compiler. It is therefore not necessary to add any information for the user. diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 8677cba6a7c3d..61ad99acf38a5 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -467,11 +467,11 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { level, fluent::mir_build_non_exhaustive_patterns_type_not_empty, ); - diag.set_span(self.span); + diag.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); + diag.arg("ty", self.ty); + diag.arg("peeled_ty", peeled_ty); if let ty::Adt(def, _) = peeled_ty.kind() { let def_span = self @@ -855,7 +855,7 @@ impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> { where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { - diag.set_arg("ty", self.ty); + diag.arg("ty", self.ty); let mut spans = MultiSpan::from(self.adt_def_span); for Variant { span } in self.variants { diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 17916e16daf46..bde442049b1d3 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -67,11 +67,11 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe { 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(self.span); diag.span_label(self.span, self.details.label()); let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter()); - diag.set_arg("details", desc); - diag.set_arg("op_in_unsafe_fn_allowed", self.op_in_unsafe_fn_allowed); + diag.arg("details", desc); + diag.arg("op_in_unsafe_fn_allowed", self.op_in_unsafe_fn_allowed); self.details.add_subdiagnostics(&mut diag); if let Some(sp) = self.enclosing { diag.span_label(sp, fluent::mir_transform_not_inherited); @@ -122,16 +122,16 @@ impl RequiresUnsafeDetail { } CallToFunctionWith { ref missing, ref build_enabled } => { diag.help(fluent::mir_transform_target_feature_call_help); - diag.set_arg( + diag.arg( "missing_target_features", DiagnosticArgValue::StrListSepByAnd( missing.iter().map(|feature| Cow::from(feature.as_str())).collect(), ), ); - diag.set_arg("missing_target_features_count", missing.len()); + diag.arg("missing_target_features_count", missing.len()); if !build_enabled.is_empty() { diag.note(fluent::mir_transform_target_feature_call_note); - diag.set_arg( + diag.arg( "build_target_features", DiagnosticArgValue::StrListSepByAnd( build_enabled @@ -140,7 +140,7 @@ impl RequiresUnsafeDetail { .collect(), ), ); - diag.set_arg("build_target_features_count", build_enabled.len()); + diag.arg("build_target_features_count", build_enabled.len()); } } } @@ -183,7 +183,7 @@ impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { let dcx = diag.dcx().expect("lint should not yet be emitted"); let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter()); - diag.set_arg("details", desc); + diag.arg("details", desc); diag.span_label(self.details.span, self.details.label()); self.details.add_subdiagnostics(diag); @@ -213,7 +213,7 @@ impl<'a, P: std::fmt::Debug> DecorateLint<'a, ()> for AssertLint

{ let assert_kind = self.panic(); let message = assert_kind.diagnostic_message(); assert_kind.add_args(&mut |name, value| { - diag.set_arg(name, value); + diag.arg(name, value); }); diag.span_label(span, message); } @@ -280,9 +280,9 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> { diag.subdiagnostic(reason); } diag.span_help(self.src_sp, fluent::_subdiag::help); - diag.set_arg("pre", self.pre); - diag.set_arg("def_path", self.tcx.def_path_str(self.def_id)); - diag.set_arg("post", self.post); + diag.arg("pre", self.pre); + diag.arg("def_path", self.tcx.def_path_str(self.def_id)); + diag.arg("post", self.post); } fn msg(&self) -> rustc_errors::DiagnosticMessage { diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 592e71251b8ba..2ca14673a58a3 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -51,7 +51,7 @@ impl IntoDiagnostic<'_, G> for UnusedGenericParamsHint { 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); + diag.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, // or a label with a dynamic value in a hard-coded string, but I haven't figured out diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index e276b34ca37af..3f6582bda0262 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1065,8 +1065,8 @@ impl<'a> IntoDiagnostic<'a> for ExpectedIdentifier { None => fluent::parse_expected_identifier_found_str, }, ); - diag.set_span(self.span); - diag.set_arg("token", self.token); + diag.span(self.span); + diag.arg("token", self.token); if let Some(sugg) = self.suggest_raw { sugg.add_to_diagnostic(&mut diag); @@ -1123,8 +1123,8 @@ impl<'a> IntoDiagnostic<'a> for ExpectedSemi { None => fluent::parse_expected_semi_found_str, }, ); - diag.set_span(self.span); - diag.set_arg("token", self.token); + diag.span(self.span); + diag.arg("token", self.token); if let Some(unexpected_token_label) = self.unexpected_token_label { diag.span_label(unexpected_token_label, fluent::parse_label_unexpected_token); diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 083d1984e0031..fdbb19103c6e9 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -252,7 +252,7 @@ impl<'a> StringReader<'a> { if starts_with_number { let span = self.mk_sp(start, self.pos); let mut diag = self.dcx().struct_err("lifetimes cannot start with a number"); - diag.set_span(span); + diag.span(span); diag.stash(span, StashKey::LifetimeIsChar); } let ident = Symbol::intern(lifetime_name); diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index f06aeed8628b8..579c3cffcfbf5 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -154,7 +154,7 @@ fn try_file_to_source_file( let msg = format!("couldn't read {}: {}", path.display(), e); let mut diag = Diagnostic::new(Level::Fatal, msg); if let Some(sp) = spanopt { - diag.set_span(sp); + diag.span(sp); } diag }) diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index fb8ad05f25df7..c8629069968aa 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -174,7 +174,7 @@ impl<'a> Parser<'a> { ) { Ok(Some(item)) => { // FIXME(#100717) - err.set_arg("item", item.kind.descr()); + err.arg("item", item.kind.descr()); err.span_label(item.span, fluent::parse_label_does_not_annotate_this); err.span_suggestion_verbose( replacement_span, diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 77bca2f138a9d..aed5e11133bc4 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -846,7 +846,7 @@ impl<'a> Parser<'a> { ) => { let n_hashes: u8 = *n_hashes; - err.set_primary_message("too many `#` when terminating raw string"); + err.primary_message("too many `#` when terminating raw string"); let str_span = self.prev_token.span; let mut span = self.token.span; let mut count = 0; @@ -857,7 +857,7 @@ impl<'a> Parser<'a> { self.bump(); count += 1; } - err.set_span(span); + err.span(span); err.span_suggestion( span, format!("remove the extra `#`{}", pluralize!(count)), diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 3932d32a6e1a4..b201d36455e64 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -925,9 +925,8 @@ impl<'a> Parser<'a> { }); } - expect_err.set_primary_message( - "closure bodies that contain statements must be surrounded by braces", - ); + expect_err + .primary_message("closure bodies that contain statements must be surrounded by braces"); let preceding_pipe_span = closure_spans.closing_pipe; let following_token_span = self.token.span; @@ -951,7 +950,7 @@ impl<'a> Parser<'a> { ); expect_err.span_note(second_note, "the closure body may be incorrectly delimited"); - expect_err.set_span(vec![preceding_pipe_span, following_token_span]); + expect_err.span(vec![preceding_pipe_span, following_token_span]); let opening_suggestion_str = " {".to_string(); let closing_suggestion_str = "}".to_string(); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index edce99db7050c..e4bbc9eeaf7d8 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2341,17 +2341,17 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match terr { TypeError::ArgumentMutability(idx) | TypeError::ArgumentSorts(_, idx) => { if let Some(ty) = hir_sig.decl.inputs.get(idx) { - diag.set_span(ty.span); + diag.span(ty.span); cause.span = ty.span; } else if idx == hir_sig.decl.inputs.len() { let span = hir_sig.decl.output.span(); - diag.set_span(span); + diag.span(span); cause.span = span; } } TypeError::ArgCount => { if let Some(ty) = hir_sig.decl.inputs.get(expected_sig.inputs().len()) { - diag.set_span(ty.span); + diag.span(ty.span); cause.span = ty.span; } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 856256a064149..9bd9dd41cf691 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -868,8 +868,8 @@ impl IntoDiagnostic<'_, G> for InvalidAttrAtCrateLevel { 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); + diag.span(self.span); + diag.arg("name", self.name); // Only emit an error with a suggestion if we can create a string out // of the attribute span if let Some(span) = self.sugg_span { @@ -881,7 +881,7 @@ impl IntoDiagnostic<'_, G> for InvalidAttrAtCrateLevel { ); } if let Some(item) = self.item { - diag.set_arg("kind", item.kind); + diag.arg("kind", item.kind); diag.span_label(item.span, fluent::passes_invalid_attr_at_crate_level_item); } diag @@ -1018,9 +1018,9 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> { #[track_caller] 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.span(self.span); diag.code(error_code!(E0571)); - diag.set_arg("kind", self.kind); + diag.arg("kind", self.kind); diag.span_label(self.span, fluent::passes_label); if let Some(head) = self.head { diag.span_label(head, fluent::passes_label2); @@ -1162,7 +1162,7 @@ impl IntoDiagnostic<'_, G> for NakedFunctionsAsmBlock { #[track_caller] 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.span(self.span); diag.code(error_code!(E0787)); for span in self.multiple_asms.iter() { diag.span_label(*span, fluent::passes_label_multiple_asm); @@ -1273,11 +1273,11 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for NoMainErr { #[track_caller] 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.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); + diag.arg("crate_name", self.crate_name); + diag.arg("filename", self.filename); + diag.arg("has_filename", self.has_filename); let note = if !self.non_main_fns.is_empty() { for &span in &self.non_main_fns { diag.span_note(span, fluent::passes_here_is_main); @@ -1294,7 +1294,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for NoMainErr { if self.file_empty { diag.note(note); } else { - diag.set_span(self.sp.shrink_to_hi()); + diag.span(self.sp.shrink_to_hi()); diag.span_label(self.sp.shrink_to_hi(), note); } @@ -1340,15 +1340,15 @@ impl IntoDiagnostic<'_, G> for DuplicateLangItem { }, ); 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); - diag.set_arg("path", self.path); - diag.set_arg("orig_crate_name", self.orig_crate_name); - diag.set_arg("orig_dependency_of", self.orig_dependency_of); - diag.set_arg("orig_path", self.orig_path); + diag.arg("lang_item_name", self.lang_item_name); + diag.arg("crate_name", self.crate_name); + diag.arg("dependency_of", self.dependency_of); + diag.arg("path", self.path); + diag.arg("orig_crate_name", self.orig_crate_name); + diag.arg("orig_dependency_of", self.orig_dependency_of); + diag.arg("orig_path", self.orig_path); if let Some(span) = self.local_span { - diag.set_span(span); + diag.span(span); } if let Some(span) = self.first_defined_span { diag.span_note(span, fluent::passes_first_defined_span); diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index cb712fe640c5e..1a4f3edd8102e 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -204,7 +204,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>( use rustc_errors::DecorateLint; let mut err = rcx.tcx.dcx().struct_span_warn(arm.pat.data().unwrap().span, ""); - err.set_primary_message(decorator.msg()); + err.primary_message(decorator.msg()); decorator.decorate_lint(&mut err); err.emit(); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 9bd58dfe82be5..6c38ed6227038 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1383,7 +1383,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { | PathSource::TupleStruct(span, _) => { // We want the main underline to cover the suggested code as well for // cleaner output. - err.set_span(*span); + err.span(*span); *span } _ => span, @@ -1615,7 +1615,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let field_spans = match source { // e.g. `if let Enum::TupleVariant(field1, field2) = _` PathSource::TupleStruct(_, pattern_spans) => { - err.set_primary_message( + err.primary_message( "cannot match against a tuple struct which contains private fields", ); @@ -1628,7 +1628,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { span: call_span, .. })) => { - err.set_primary_message( + err.primary_message( "cannot initialize a tuple struct which contains private fields", ); self.suggest_alternative_construction_methods( diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 0f86773b73fc9..758c31224045c 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -19,7 +19,7 @@ impl<'a> IntoDiagnostic<'a> for FeatureGateError { #[track_caller] fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> { let mut diag = DiagnosticBuilder::new(dcx, level, self.explain); - diag.set_span(self.span); + diag.span(self.span); diag.code(error_code!(E0658)); diag } diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs index 06a2b3ca9c4f3..0fa59d2ddfba1 100644 --- a/compiler/rustc_symbol_mangling/src/errors.rs +++ b/compiler/rustc_symbol_mangling/src/errors.rs @@ -19,7 +19,7 @@ impl IntoDiagnostic<'_, G> for TestOutput { #[allow(rustc::untranslatable_diagnostic)] let mut diag = DiagnosticBuilder::new(dcx, level, format!("{kind}({content})")); - diag.set_span(span); + diag.span(span); diag } } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index bea6fbd6ac5cd..5eff52afbca2b 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -66,12 +66,9 @@ impl IntoDiagnostic<'_, G> for NegativePositiveConflict<'_ ) -> 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", - self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string()), - ); - diag.set_span(self.impl_span); + diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string()); + diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string())); + diag.span(self.impl_span); diag.code(rustc_errors::error_code!(E0751)); match self.negative_impl_span { Ok(span) => { @@ -79,7 +76,7 @@ impl IntoDiagnostic<'_, G> for NegativePositiveConflict<'_ } Err(cname) => { diag.note(fluent::trait_selection_negative_implementation_in_crate); - diag.set_arg("negative_impl_cname", cname.to_string()); + diag.arg("negative_impl_cname", cname.to_string()); } } match self.positive_impl_span { @@ -88,7 +85,7 @@ impl IntoDiagnostic<'_, G> for NegativePositiveConflict<'_ } Err(cname) => { diag.note(fluent::trait_selection_positive_implementation_in_crate); - diag.set_arg("positive_impl_cname", cname.to_string()); + diag.arg("positive_impl_cname", cname.to_string()); } } diag @@ -115,7 +112,7 @@ impl AddToDiagnostic for AdjustSignatureBorrow { { match self { AdjustSignatureBorrow::Borrow { to_borrow } => { - diag.set_arg("len", to_borrow.len()); + diag.arg("len", to_borrow.len()); diag.multipart_suggestion_verbose( fluent::trait_selection_adjust_signature_borrow, to_borrow, @@ -123,7 +120,7 @@ impl AddToDiagnostic for AdjustSignatureBorrow { ); } AdjustSignatureBorrow::RemoveBorrow { remove_borrow } => { - diag.set_arg("len", remove_borrow.len()); + diag.arg("len", remove_borrow.len()); diag.multipart_suggestion_verbose( fluent::trait_selection_adjust_signature_remove_borrow, remove_borrow, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index f63314081d615..787d2cac0b25c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2008,7 +2008,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }; err.code(error_code!(E0746)); - err.set_primary_message("return type cannot have an unboxed trait object"); + err.primary_message("return type cannot have an unboxed trait object"); err.children.clear(); let span = obligation.cause.span; @@ -2713,7 +2713,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if name == sym::Send { ("`Send`", "sent") } else { ("`Sync`", "shared") }; err.clear_code(); - err.set_primary_message(format!( + err.primary_message(format!( "{future_or_coroutine} cannot be {trait_verb} between threads safely" )); @@ -2801,7 +2801,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .unwrap_or_else(|| format!("{future_or_coroutine} is not {trait_name}")); span.push_span_label(original_span, message); - err.set_span(span); + err.span(span); format!("is not {trait_name}") } else { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index d2598b0defe7f..0b2c946deeb2b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -3163,14 +3163,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) { match obligation_cause_code { ObligationCauseCode::RustCall => { - err.set_primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument"); + err.primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument"); } ObligationCauseCode::BindingObligation(def_id, _) | ObligationCauseCode::ItemObligation(def_id) if self.tcx.is_fn_trait(*def_id) => { err.code(rustc_errors::error_code!(E0059)); - err.set_primary_message(format!( + err.primary_message(format!( "type parameter to bare `{}` trait must be a tuple", self.tcx.def_path_str(*def_id) )); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index ee185ab98922d..506eb56fdc8ff 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1733,7 +1733,7 @@ fn report_diagnostic( }; if let Some(sp) = span { - lint.set_span(sp); + lint.span(sp); } else { // blah blah blah\nblah\nblah [blah] blah blah\nblah blah // ^ ~~~~ diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 4375fa67b807b..d9b4eb2f0ad1b 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -459,7 +459,7 @@ pub fn report_msg<'tcx>( DiagLevel::Note => Level::Note, }; let mut err = DiagnosticBuilder::<()>::new(sess.dcx(), level, title); - err.set_span(span); + err.span(span); // Show main message. if span != DUMMY_SP { diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr index bdcf54bd19042..f07b69326b0cf 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr @@ -8,7 +8,7 @@ LL | arg: NotIntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `NotIntoDiagnosticArg` | = help: normalized in stderr -note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg` +note: required by a bound in `DiagnosticBuilder::<'a, G>::arg` --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC = note: this error originates in the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -22,7 +22,7 @@ LL | arg: NotIntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `NotIntoDiagnosticArg` | = help: normalized in stderr -note: required by a bound in `Diagnostic::set_arg` +note: required by a bound in `Diagnostic::arg` --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC error: aborting due to 2 previous errors diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 63fb78ee91995..f553aa96505ec 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -741,7 +741,7 @@ struct SubdiagnosticEagerCorrect { } // Check that formatting of `correct` in suggestion doesn't move the binding for that field, making -// the `set_arg` call a compile error; and that isn't worked around by moving the `set_arg` call +// the `arg` call a compile error; and that isn't worked around by moving the `arg` call // after the `span_suggestion` call - which breaks eager translation. #[derive(Subdiagnostic)] diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index d8ba65d297e42..f376c034587fa 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -654,7 +654,7 @@ LL | other: Hello, | ^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello` | = help: normalized in stderr -note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg` +note: required by a bound in `DiagnosticBuilder::<'a, G>::arg` --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC = note: this error originates in the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info) From 5fe5d5da4e10eccdaf3d46aee5fc21701c32f206 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 2 Jan 2024 14:39:57 +1100 Subject: [PATCH 02/34] Remove lots of `rustc_errors::` qualifiers in `lints.rs`. --- compiler/rustc_lint/src/lints.rs | 99 ++++++++++++-------------------- 1 file changed, 36 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 1b81402e0031d..614c3ecbcae2b 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -5,8 +5,8 @@ use std::num::NonZeroU32; use crate::errors::RequestedLevel; use crate::fluent_generated as fluent; use rustc_errors::{ - AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage, DiagnosticStyledString, - SuggestionStyle, + AddToDiagnostic, Applicability, DecorateLint, Diagnostic, DiagnosticBuilder, DiagnosticMessage, + DiagnosticStyledString, SubdiagnosticMessage, SuggestionStyle, }; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; @@ -239,7 +239,7 @@ pub struct BuiltinUngatedAsyncFnTrackCaller<'a> { } impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.span_label(self.label, fluent::lint_label); rustc_session::parse::add_feature_diagnostics( diag, @@ -268,12 +268,9 @@ pub struct SuggestChangingAssocTypes<'a, 'b> { } impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { // Access to associates types should use `::Assoc`, which does not need a // bound. Let's see if this type does that. @@ -281,7 +278,7 @@ impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> { // We use a HIR visitor to walk the type. use rustc_hir::intravisit::{self, Visitor}; struct WalkAssocTypes<'a> { - err: &'a mut rustc_errors::Diagnostic, + err: &'a mut Diagnostic, } impl Visitor<'_> for WalkAssocTypes<'_> { fn visit_qpath( @@ -326,12 +323,9 @@ pub struct BuiltinTypeAliasGenericBoundsSuggestion { } impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { diag.multipart_suggestion( fluent::lint_suggestion, @@ -425,7 +419,7 @@ pub struct BuiltinUnpermittedTypeInit<'a> { } impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.arg("ty", self.ty); diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label); if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) { @@ -438,7 +432,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> { self.sub.add_to_diagnostic(diag); } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> DiagnosticMessage { self.msg.clone() } } @@ -449,12 +443,9 @@ pub struct BuiltinUnpermittedTypeInitSub { } impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { let mut err = self.err; loop { @@ -506,12 +497,9 @@ pub struct BuiltinClashingExternSub<'a> { } impl AddToDiagnostic for BuiltinClashingExternSub<'_> { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { let mut expected_str = DiagnosticStyledString::new(); expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); @@ -779,12 +767,9 @@ pub struct HiddenUnicodeCodepointsDiagLabels { } impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { for (c, span) in self.spans { diag.span_label(span, format!("{c:?}")); @@ -799,12 +784,9 @@ pub enum HiddenUnicodeCodepointsDiagSub { // Used because of multiple multipart_suggestion and note impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { match self { HiddenUnicodeCodepointsDiagSub::Escape { spans } => { @@ -953,12 +935,9 @@ pub struct NonBindingLetSub { } impl AddToDiagnostic for NonBindingLetSub { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { diag.span_suggestion_verbose( self.suggestion, @@ -1147,7 +1126,7 @@ pub struct NonFmtPanicUnused { // Used because of two suggestions based on one Option impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.arg("count", self.count); diag.note(fluent::lint_note); if let Some(span) = self.suggestion { @@ -1166,7 +1145,7 @@ impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused { } } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> DiagnosticMessage { fluent::lint_non_fmt_panic_unused } } @@ -1224,12 +1203,9 @@ pub enum NonSnakeCaseDiagSub { } impl AddToDiagnostic for NonSnakeCaseDiagSub { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { match self { NonSnakeCaseDiagSub::Label { span } => { @@ -1342,12 +1318,12 @@ pub struct DropTraitConstraintsDiag<'a> { // Needed for def_path_str impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.arg("predicate", self.predicate); diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> DiagnosticMessage { fluent::lint_drop_trait_constraints } } @@ -1359,11 +1335,11 @@ pub struct DropGlue<'a> { // Needed for def_path_str impl<'a> DecorateLint<'a, ()> for DropGlue<'_> { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> DiagnosticMessage { fluent::lint_drop_glue } } @@ -1423,12 +1399,9 @@ pub enum OverflowingBinHexSign { } impl AddToDiagnostic for OverflowingBinHexSign { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { match self { OverflowingBinHexSign::Positive => { @@ -1633,7 +1606,7 @@ pub struct ImproperCTypes<'a> { // Used because of the complexity of Option, DiagnosticMessage, and Option impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.arg("ty", self.ty); diag.arg("desc", self.desc); diag.span_label(self.label, fluent::lint_label); @@ -1646,7 +1619,7 @@ impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> { } } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> DiagnosticMessage { fluent::lint_improper_ctypes } } @@ -1776,7 +1749,7 @@ pub enum UnusedDefSuggestion { // Needed because of def_path_str impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.arg("pre", self.pre); diag.arg("post", self.post); diag.arg("def", self.cx.tcx.def_path_str(self.def_id)); @@ -1789,7 +1762,7 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> { } } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> DiagnosticMessage { fluent::lint_unused_def } } @@ -1859,14 +1832,14 @@ pub struct AsyncFnInTraitDiag { } impl<'a> DecorateLint<'a, ()> for AsyncFnInTraitDiag { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.note(fluent::lint_note); if let Some(sugg) = self.sugg { diag.multipart_suggestion(fluent::lint_suggestion, sugg, Applicability::MaybeIncorrect); } } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> DiagnosticMessage { fluent::lint_async_fn_in_trait } } From 096b844a2b38436d2e7a4eb4419a6be3eff7da67 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 3 Jan 2024 14:27:35 +1100 Subject: [PATCH 03/34] Remove forward for `downgrade_to_delayed_bug`. It's not used, and doesn't quite fit the general pattern. Also, `Diagnostic::downgrade_to_delayed_bug` doesn't need to return `&mut Self` for the same reason. --- compiler/rustc_errors/src/diagnostic.rs | 4 +--- compiler/rustc_errors/src/diagnostic_builder.rs | 5 ----- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index f2d54eb427db3..e0689297b21de 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -311,15 +311,13 @@ impl Diagnostic { /// In the meantime, though, callsites are required to deal with the "bug" /// locally in whichever way makes the most sense. #[track_caller] - pub fn downgrade_to_delayed_bug(&mut self) -> &mut Self { + pub fn downgrade_to_delayed_bug(&mut self) { assert!( self.is_error(), "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error", self.level ); self.level = Level::DelayedBug; - - self } /// Adds a span/label to be included in the resulting snippet. diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index d8838bbdbab1d..d3b11552aa119 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -356,11 +356,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { self.emit() } - forward!( - #[track_caller] - pub fn downgrade_to_delayed_bug(&mut self,) -> &mut Self - ); - forward!( /// Appends a labeled span to the diagnostic. /// From caefa553476c2b9bda30ab89f5882f7a35649572 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 3 Jan 2024 14:32:17 +1100 Subject: [PATCH 04/34] Fix up `forward!` decls. - Move comments onto corresponding `Diagnostic` methods. - Make formatting more consistent. --- compiler/rustc_errors/src/diagnostic.rs | 16 ++++++---- .../rustc_errors/src/diagnostic_builder.rs | 32 ++++--------------- 2 files changed, 16 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index e0689297b21de..863bfee4f183f 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -320,14 +320,18 @@ impl Diagnostic { self.level = Level::DelayedBug; } - /// Adds a span/label to be included in the resulting snippet. + /// Appends a labeled span to the diagnostic. /// - /// This is pushed onto the [`MultiSpan`] that was created when the diagnostic - /// was first built. That means it will be shown together with the original - /// span/label, *not* a span added by one of the `span_{note,warn,help,suggestions}` methods. + /// Labels are used to convey additional context for the diagnostic's primary span. They will + /// be shown together with the original diagnostic's span, *not* with spans added by + /// `span_note`, `span_help`, etc. Therefore, if the primary span is not displayable (because + /// the span is `DUMMY_SP` or the source code isn't found), labels will not be displayed + /// either. /// - /// This span is *not* considered a ["primary span"][`MultiSpan`]; only - /// the `Span` supplied when creating the diagnostic is primary. + /// Implementation-wise, the label span is pushed onto the [`MultiSpan`] that was created when + /// the diagnostic was constructed. However, the label span is *not* considered a + /// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is + /// primary. #[rustc_lint_diagnostics] pub fn span_label(&mut self, span: Span, label: impl Into) -> &mut Self { self.span.push_span_label(span, self.subdiagnostic_message_to_diagnostic_message(label)); diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index d3b11552aa119..24efc87100126 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -356,30 +356,16 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { self.emit() } - forward!( - /// Appends a labeled span to the diagnostic. - /// - /// Labels are used to convey additional context for the diagnostic's primary span. They will - /// be shown together with the original diagnostic's span, *not* with spans added by - /// `span_note`, `span_help`, etc. Therefore, if the primary span is not displayable (because - /// the span is `DUMMY_SP` or the source code isn't found), labels will not be displayed - /// either. - /// - /// Implementation-wise, the label span is pushed onto the [`MultiSpan`] that was created when - /// the diagnostic was constructed. However, the label span is *not* considered a - /// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is - /// primary. - pub fn span_label(&mut self, span: Span, label: impl Into) -> &mut Self); - - forward!( - /// Labels all the given spans with the provided label. - /// See [`Diagnostic::span_label()`] for more information. - pub fn span_labels( + forward!(pub fn span_label( + &mut self, + span: Span, + label: impl Into + ) -> &mut Self); + forward!(pub fn span_labels( &mut self, spans: impl IntoIterator, label: &str, ) -> &mut Self); - forward!(pub fn note_expected_found( &mut self, expected_label: &dyn fmt::Display, @@ -387,7 +373,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { found_label: &dyn fmt::Display, found: DiagnosticStyledString, ) -> &mut Self); - forward!(pub fn note_expected_found_extra( &mut self, expected_label: &dyn fmt::Display, @@ -397,7 +382,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { expected_extra: &dyn fmt::Display, found_extra: &dyn fmt::Display, ) -> &mut Self); - forward!(pub fn note(&mut self, msg: impl Into) -> &mut Self); forward!(pub fn note_once(&mut self, msg: impl Into) -> &mut Self); forward!(pub fn span_note( @@ -424,9 +408,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { msg: impl Into, ) -> &mut Self); forward!(pub fn is_lint(&mut self,) -> &mut Self); - forward!(pub fn disable_suggestions(&mut self,) -> &mut Self); - forward!(pub fn multipart_suggestion( &mut self, msg: impl Into, @@ -493,7 +475,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { suggestion: impl ToString, applicability: Applicability, ) -> &mut Self); - forward!(pub fn primary_message(&mut self, msg: impl Into) -> &mut Self); forward!(pub fn span(&mut self, sp: impl Into) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); @@ -502,7 +483,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { name: impl Into>, arg: impl IntoDiagnosticArg, ) -> &mut Self); - forward!(pub fn subdiagnostic( &mut self, subdiagnostic: impl crate::AddToDiagnostic From b4a62399840d61c56081e7378220d65e183a00fb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 3 Jan 2024 14:38:20 +1100 Subject: [PATCH 05/34] Fix `forward!` so it doesn't require trailing commas in some cases. --- compiler/rustc_errors/src/diagnostic_builder.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 24efc87100126..e018c14a4a5cd 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -207,11 +207,11 @@ macro_rules! forward { // Forward pattern for &mut self -> &mut Self ( $(#[$attrs:meta])* - pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)?) -> &mut Self + pub fn $n:ident(&mut self $(, $name:ident: $ty:ty)* $(,)?) -> &mut Self ) => { $(#[$attrs])* #[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")] - pub fn $n(&mut self, $($name: $ty),*) -> &mut Self { + pub fn $n(&mut self $(, $name: $ty)*) -> &mut Self { self.diagnostic.$n($($name),*); self } @@ -407,8 +407,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { sp: impl Into, msg: impl Into, ) -> &mut Self); - forward!(pub fn is_lint(&mut self,) -> &mut Self); - forward!(pub fn disable_suggestions(&mut self,) -> &mut Self); + forward!(pub fn is_lint(&mut self) -> &mut Self); + forward!(pub fn disable_suggestions(&mut self) -> &mut Self); forward!(pub fn multipart_suggestion( &mut self, msg: impl Into, From 048750077676190a0733112d8f700e76a0553f60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Dec 2023 00:37:57 +0000 Subject: [PATCH 06/34] Provide better suggestions when encountering a bare trait as a type Add the following suggestions: ``` error[E0782]: trait objects must include the `dyn` keyword --> $DIR/not-on-bare-trait-2021.rs:11:11 | LL | fn bar(x: Foo) -> Foo { | ^^^ | help: use a generic type parameter, constrained by the trait `Foo` | LL | fn bar(x: T) -> Foo { | ++++++++ ~ help: you can also use `impl Foo`, but users won't be able to specify the type paramer when calling the `fn`, having to rely exclusively on type inference | LL | fn bar(x: impl Foo) -> Foo { | ++++ help: alternatively, use a trait object to accept any type that implements `Foo`, accessing its methods at runtime using dynamic dispatch | LL | fn bar(x: &dyn Foo) -> Foo { | ++++ error[E0782]: trait objects must include the `dyn` keyword --> $DIR/not-on-bare-trait-2021.rs:11:19 | LL | fn bar(x: Foo) -> Foo { | ^^^ | help: use `impl Foo` to return an opaque type, as long as you return a single underlying type | LL | fn bar(x: Foo) -> impl Foo { | ++++ help: alternatively, you can return an owned trait object | LL | fn bar(x: Foo) -> Box { | +++++++ + ``` --- .../rustc_hir_analysis/src/astconv/lint.rs | 131 +++++++++++++++--- .../ui/traits/bound/not-on-bare-trait-2021.rs | 17 +++ .../bound/not-on-bare-trait-2021.stderr | 56 ++++++++ .../ui/traits/bound/not-on-bare-trait.stderr | 14 +- 4 files changed, 197 insertions(+), 21 deletions(-) create mode 100644 tests/ui/traits/bound/not-on-bare-trait-2021.rs create mode 100644 tests/ui/traits/bound/not-on-bare-trait-2021.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index f3b93c91ae9ab..99dbba1ecdc51 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -2,6 +2,7 @@ use rustc_ast::TraitObjectSyntax; use rustc_errors::{Diagnostic, StashKey}; use rustc_hir as hir; use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability}; +use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; use super::AstConv; @@ -32,32 +33,120 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } let of_trait_span = of_trait_ref.path.span; // make sure that we are not calling unwrap to abort during the compilation - let Ok(impl_trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { - return; - }; let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { return; }; - // check if the trait has generics, to make a correct suggestion - let param_name = generics.params.next_type_param_name(None); - let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() { - (span, format!(", {param_name}: {impl_trait_name}")) - } else { - (generics.span, format!("<{param_name}: {impl_trait_name}>")) + let Ok(impl_trait_name) = self.tcx().sess.source_map().span_to_snippet(self_ty.span) + else { + return; + }; + let Some(sugg) = self.generics_suggestion(generics, self_ty.span, &impl_trait_name) + else { + return; }; diag.multipart_suggestion( format!( - "alternatively use a blanket \ - implementation to implement `{of_trait_name}` for \ + "alternatively use a blanket implementation to implement `{of_trait_name}` for \ all types that also implement `{impl_trait_name}`" ), - vec![(self_ty.span, param_name), add_generic_sugg], + sugg, Applicability::MaybeIncorrect, ); } } + fn generics_suggestion( + &self, + generics: &hir::Generics<'_>, + self_ty_span: Span, + impl_trait_name: &str, + ) -> Option> { + // check if the trait has generics, to make a correct suggestion + let param_name = generics.params.next_type_param_name(None); + + let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() { + (span, format!(", {param_name}: {impl_trait_name}")) + } else { + (generics.span, format!("<{param_name}: {impl_trait_name}>")) + }; + Some(vec![(self_ty_span, param_name), add_generic_sugg]) + } + + /// Make sure that we are in the condition to suggest `impl Trait`. + fn maybe_lint_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) -> bool { + let tcx = self.tcx(); + let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; + let (hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(sig, _), + generics, + .. + })) = tcx.hir_node_by_def_id(parent_id) + else { + return false; + }; + let Ok(trait_name) = self.tcx().sess.source_map().span_to_snippet(self_ty.span) else { + return false; + }; + let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())]; + if let hir::FnRetTy::Return(ty) = sig.decl.output + && ty.hir_id == self_ty.hir_id + { + diag.multipart_suggestion_verbose( + format!("use `impl {trait_name}` to return an opaque type, as long as you return a single underlying type"), + impl_sugg, + Applicability::MachineApplicable, + ); + diag.multipart_suggestion_verbose( + "alternatively, you can return an owned trait object", + vec![ + (ty.span.shrink_to_lo(), "Box".to_string()), + ], + Applicability::MachineApplicable, + ); + return true; + } + for ty in sig.decl.inputs { + if ty.hir_id == self_ty.hir_id { + if let Some(sugg) = self.generics_suggestion(generics, self_ty.span, &trait_name) { + diag.multipart_suggestion_verbose( + format!("use a new generic type parameter, constrained by `{trait_name}`"), + sugg, + Applicability::MachineApplicable, + ); + diag.multipart_suggestion_verbose( + "you can also use an opaque type, but users won't be able to specify the \ + type parameter when calling the `fn`, having to rely exclusively on type \ + inference", + impl_sugg, + Applicability::MachineApplicable, + ); + } + let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind { + // There are more than one trait bound, we need surrounding parentheses. + vec![ + (self_ty.span.shrink_to_lo(), "&(dyn ".to_string()), + (self_ty.span.shrink_to_hi(), ")".to_string()), + ] + } else { + vec![(self_ty.span.shrink_to_lo(), "&dyn ".to_string())] + }; + diag.multipart_suggestion_verbose( + format!( + "alternatively, use a trait object to accept any type that implements \ + `{trait_name}`, accessing its methods at runtime using dynamic dispatch", + ), + sugg, + Applicability::MachineApplicable, + ); + return true; + } + } + false + } + pub(super) fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) { let tcx = self.tcx(); if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = @@ -98,7 +187,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let label = "add `dyn` keyword before this trait"; let mut diag = rustc_errors::struct_span_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg); - if self_ty.span.can_be_used_for_suggestions() { + if self_ty.span.can_be_used_for_suggestions() + && !self.maybe_lint_impl_trait(self_ty, &mut diag) + { diag.multipart_suggestion_verbose( label, sugg, @@ -116,11 +207,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty.span, msg, |lint| { - lint.multipart_suggestion_verbose( - "use `dyn`", - sugg, - Applicability::MachineApplicable, - ); + if self_ty.span.can_be_used_for_suggestions() + && !self.maybe_lint_impl_trait(self_ty, lint) + { + lint.multipart_suggestion_verbose( + "use `dyn`", + sugg, + Applicability::MachineApplicable, + ); + } self.maybe_lint_blanket_trait_impl(self_ty, lint); }, ); diff --git a/tests/ui/traits/bound/not-on-bare-trait-2021.rs b/tests/ui/traits/bound/not-on-bare-trait-2021.rs new file mode 100644 index 0000000000000..3d97bddb4a49f --- /dev/null +++ b/tests/ui/traits/bound/not-on-bare-trait-2021.rs @@ -0,0 +1,17 @@ +// edition:2021 +trait Foo { + fn dummy(&self) {} +} + +// This should emit the less confusing error, not the more confusing one. + +fn foo(_x: Foo + Send) { + //~^ ERROR trait objects must include the `dyn` keyword +} +fn bar(x: Foo) -> Foo { + //~^ ERROR trait objects must include the `dyn` keyword + //~| ERROR trait objects must include the `dyn` keyword + x +} + +fn main() {} diff --git a/tests/ui/traits/bound/not-on-bare-trait-2021.stderr b/tests/ui/traits/bound/not-on-bare-trait-2021.stderr new file mode 100644 index 0000000000000..6f41f872e4cf6 --- /dev/null +++ b/tests/ui/traits/bound/not-on-bare-trait-2021.stderr @@ -0,0 +1,56 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/not-on-bare-trait-2021.rs:8:12 + | +LL | fn foo(_x: Foo + Send) { + | ^^^^^^^^^^ + | +help: use a new generic type parameter, constrained by `Foo + Send` + | +LL | fn foo(_x: T) { + | +++++++++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn foo(_x: impl Foo + Send) { + | ++++ +help: alternatively, use a trait object to accept any type that implements `Foo + Send`, accessing its methods at runtime using dynamic dispatch + | +LL | fn foo(_x: &(dyn Foo + Send)) { + | +++++ + + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/not-on-bare-trait-2021.rs:11:11 + | +LL | fn bar(x: Foo) -> Foo { + | ^^^ + | +help: use a new generic type parameter, constrained by `Foo` + | +LL | fn bar(x: T) -> Foo { + | ++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn bar(x: impl Foo) -> Foo { + | ++++ +help: alternatively, use a trait object to accept any type that implements `Foo`, accessing its methods at runtime using dynamic dispatch + | +LL | fn bar(x: &dyn Foo) -> Foo { + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/not-on-bare-trait-2021.rs:11:19 + | +LL | fn bar(x: Foo) -> Foo { + | ^^^ + | +help: use `impl Foo` to return an opaque type, as long as you return a single underlying type + | +LL | fn bar(x: Foo) -> impl Foo { + | ++++ +help: alternatively, you can return an owned trait object + | +LL | fn bar(x: Foo) -> Box { + | +++++++ + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/traits/bound/not-on-bare-trait.stderr b/tests/ui/traits/bound/not-on-bare-trait.stderr index 1d97bf3d8f957..976dd6a1bc532 100644 --- a/tests/ui/traits/bound/not-on-bare-trait.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait.stderr @@ -7,10 +7,18 @@ LL | fn foo(_x: Foo + Send) { = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use `dyn` +help: use a new generic type parameter, constrained by `Foo + Send` | -LL | fn foo(_x: dyn Foo + Send) { - | +++ +LL | fn foo(_x: T) { + | +++++++++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn foo(_x: impl Foo + Send) { + | ++++ +help: alternatively, use a trait object to accept any type that implements `Foo + Send`, accessing its methods at runtime using dynamic dispatch + | +LL | fn foo(_x: &(dyn Foo + Send)) { + | +++++ + error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time --> $DIR/not-on-bare-trait.rs:7:8 From 8551cab7b75ab8f9c51b1d5a847031093b79b546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Dec 2023 01:03:05 +0000 Subject: [PATCH 07/34] Account for multiple trait bounds in bare trait object suggestion Note the parentheses in the last suggestion: ``` error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time --> $DIR/not-on-bare-trait.rs:7:8 | LL | fn foo(_x: Foo + Send) { | ^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)` = help: unsized fn params are gated as an unstable feature help: you can use `impl Trait` as the argument type | LL | fn foo(_x: impl Foo + Send) { | ++++ help: function arguments must have a statically known size, borrowed types always have a known size | LL | fn foo(_x: &(Foo + Send)) { | ++ + ``` --- .../src/traits/error_reporting/suggestions.rs | 40 ++++++++++++++++--- tests/ui/traits/bound/not-on-bare-trait.rs | 3 ++ .../ui/traits/bound/not-on-bare-trait.stderr | 21 +++++++++- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index f63314081d615..b768108e24ce2 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3202,9 +3202,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ObligationCauseCode::SizedArgumentType(ty_span) => { if let Some(span) = ty_span { - if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() + let trait_len = if let ty::PredicateKind::Clause(clause) = + predicate.kind().skip_binder() && let ty::ClauseKind::Trait(trait_pred) = clause - && let ty::Dynamic(..) = trait_pred.self_ty().kind() + && let ty::Dynamic(preds, ..) = trait_pred.self_ty().kind() { let span = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) @@ -3221,12 +3222,39 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { "impl ".to_string(), Applicability::MaybeIncorrect, ); - } - err.span_suggestion_verbose( - span.shrink_to_lo(), + preds + .iter() + .filter(|pred| { + // We only want to count `dyn Foo + Bar`, not `dyn Foo`, + // because the later doesn't need parentheses. + matches!( + pred.skip_binder(), + ty::ExistentialPredicate::Trait(_) + | ty::ExistentialPredicate::AutoTrait(_) + ) + }) + .count() + } else { + 1 + }; + let sugg = if trait_len == 1 { + vec![(span.shrink_to_lo(), "&".to_string())] + } else if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) + && snippet.starts_with('(') + { + // We don't want to suggest `&((dyn Foo + Bar))` when we have + // `(dyn Foo + Bar)`. + vec![(span.shrink_to_lo(), "&".to_string())] + } else { + vec![ + (span.shrink_to_lo(), "&(".to_string()), + (span.shrink_to_hi(), ")".to_string()), + ] + }; + err.multipart_suggestion_verbose( "function arguments must have a statically known size, borrowed types \ always have a known size", - "&", + sugg, Applicability::MachineApplicable, ); } else { diff --git a/tests/ui/traits/bound/not-on-bare-trait.rs b/tests/ui/traits/bound/not-on-bare-trait.rs index daf18c6702e46..9e717f3c045e3 100644 --- a/tests/ui/traits/bound/not-on-bare-trait.rs +++ b/tests/ui/traits/bound/not-on-bare-trait.rs @@ -9,5 +9,8 @@ fn foo(_x: Foo + Send) { //~| WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition } +fn bar(_x: (dyn Foo + Send)) { + //~^ ERROR the size for values of type +} fn main() {} diff --git a/tests/ui/traits/bound/not-on-bare-trait.stderr b/tests/ui/traits/bound/not-on-bare-trait.stderr index 976dd6a1bc532..edb6b1d934bd4 100644 --- a/tests/ui/traits/bound/not-on-bare-trait.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait.stderr @@ -34,9 +34,26 @@ LL | fn foo(_x: impl Foo + Send) { | ++++ help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn foo(_x: &Foo + Send) { +LL | fn foo(_x: &(Foo + Send)) { + | ++ + + +error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time + --> $DIR/not-on-bare-trait.rs:12:8 + | +LL | fn bar(_x: (dyn Foo + Send)) { + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)` + = help: unsized fn params are gated as an unstable feature +help: you can use `impl Trait` as the argument type + | +LL | fn bar(_x: impl (dyn Foo + Send)) { + | ++++ +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn bar(_x: &(dyn Foo + Send)) { | + -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0277`. From 79bef72fd56c2a0f3998dceb7c08355cf3fabc4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Dec 2023 19:13:24 +0000 Subject: [PATCH 08/34] Track `HirId` instead of `Span` in `ObligationCauseCode::SizedArgumentType` This gets us more accurate suggestions. --- compiler/rustc_hir_typeck/src/check.rs | 7 +- .../rustc_hir_typeck/src/gather_locals.rs | 9 +- compiler/rustc_middle/src/traits/mod.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 136 ++++++++++-------- .../clippy/tests/ui/crashes/ice-6251.stderr | 2 +- .../feature-gate-unsized_fn_params.stderr | 6 +- tests/ui/resolve/issue-5035-2.stderr | 4 - .../ui/traits/bound/not-on-bare-trait.stderr | 12 +- 8 files changed, 96 insertions(+), 82 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 0ca0f7d2daf92..bd7c0749171f6 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -114,7 +114,8 @@ pub(super) fn check_fn<'a, 'tcx>( let inputs_fn = fn_sig.inputs().iter().copied(); for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() { // Check the pattern. - let ty_span = try { inputs_hir?.get(idx)?.span }; + let ty: Option<&hir::Ty<'_>> = try { inputs_hir?.get(idx)? }; + let ty_span = ty.map(|ty| ty.span); fcx.check_pat_top(param.pat, param_ty, ty_span, None, None); // Check that argument is Sized. @@ -122,13 +123,13 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.require_type_is_sized( param_ty, param.pat.span, - // ty_span == binding_span iff this is a closure parameter with no type ascription, + // ty.span == binding_span iff this is a closure parameter with no type ascription, // or if it's an implicit `self` parameter traits::SizedArgumentType( if ty_span == Some(param.span) && tcx.is_closure(fn_def_id.into()) { None } else { - ty_span + ty.map(|ty| ty.hir_id) }, ), ); diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 0cca779b1560e..52259c6066012 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -60,7 +60,7 @@ pub(super) struct GatherLocalsVisitor<'a, 'tcx> { // parameters are special cases of patterns, but we want to handle them as // *distinct* cases. so track when we are hitting a pattern *within* an fn // parameter. - outermost_fn_param_pat: Option, + outermost_fn_param_pat: Option<(Span, hir::HirId)>, } impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { @@ -131,7 +131,8 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { } fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { - let old_outermost_fn_param_pat = self.outermost_fn_param_pat.replace(param.ty_span); + let old_outermost_fn_param_pat = + self.outermost_fn_param_pat.replace((param.ty_span, param.hir_id)); intravisit::walk_param(self, param); self.outermost_fn_param_pat = old_outermost_fn_param_pat; } @@ -141,7 +142,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { if let PatKind::Binding(_, _, ident, _) = p.kind { let var_ty = self.assign(p.span, p.hir_id, None); - if let Some(ty_span) = self.outermost_fn_param_pat { + if let Some((ty_span, hir_id)) = self.outermost_fn_param_pat { if !self.fcx.tcx.features().unsized_fn_params { self.fcx.require_type_is_sized( var_ty, @@ -154,7 +155,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { { None } else { - Some(ty_span) + Some(hir_id) }, ), ); diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 09b0a0dfbf38c..af601a0d702ed 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -289,7 +289,7 @@ pub enum ObligationCauseCode<'tcx> { /// Type of each variable must be `Sized`. VariableType(hir::HirId), /// Argument type must be `Sized`. - SizedArgumentType(Option), + SizedArgumentType(Option), /// Return type must be `Sized`. SizedReturnType, /// Yield type must be `Sized`. diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index b768108e24ce2..bc53e0e57133e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -19,11 +19,10 @@ use rustc_errors::{ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::{Map, Visitor}; use rustc_hir::is_range_literal; use rustc_hir::lang_items::LangItem; -use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Node}; -use rustc_hir::{Expr, HirId}; +use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node}; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk}; @@ -3200,63 +3199,80 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err.help("unsized locals are gated as an unstable feature"); } } - ObligationCauseCode::SizedArgumentType(ty_span) => { - if let Some(span) = ty_span { - let trait_len = if let ty::PredicateKind::Clause(clause) = - predicate.kind().skip_binder() - && let ty::ClauseKind::Trait(trait_pred) = clause - && let ty::Dynamic(preds, ..) = trait_pred.self_ty().kind() - { - let span = if let Ok(snippet) = - self.tcx.sess.source_map().span_to_snippet(span) - && snippet.starts_with("dyn ") - { - let pos = snippet.len() - snippet[3..].trim_start().len(); - span.with_hi(span.lo() + BytePos(pos as u32)) - } else { - span.shrink_to_lo() - }; - err.span_suggestion_verbose( - span, - "you can use `impl Trait` as the argument type", - "impl ".to_string(), - Applicability::MaybeIncorrect, - ); - preds - .iter() - .filter(|pred| { - // We only want to count `dyn Foo + Bar`, not `dyn Foo`, - // because the later doesn't need parentheses. - matches!( - pred.skip_binder(), - ty::ExistentialPredicate::Trait(_) - | ty::ExistentialPredicate::AutoTrait(_) - ) - }) - .count() - } else { - 1 - }; - let sugg = if trait_len == 1 { - vec![(span.shrink_to_lo(), "&".to_string())] - } else if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) - && snippet.starts_with('(') - { - // We don't want to suggest `&((dyn Foo + Bar))` when we have - // `(dyn Foo + Bar)`. - vec![(span.shrink_to_lo(), "&".to_string())] - } else { - vec![ - (span.shrink_to_lo(), "&(".to_string()), - (span.shrink_to_hi(), ")".to_string()), - ] - }; - err.multipart_suggestion_verbose( - "function arguments must have a statically known size, borrowed types \ - always have a known size", - sugg, - Applicability::MachineApplicable, - ); + ObligationCauseCode::SizedArgumentType(hir_id) => { + let mut ty = None; + let borrowed_msg = "function arguments must have a statically known size, borrowed \ + types always have a known size"; + if let Some(hir_id) = hir_id + && let Some(hir::Node::Param(param)) = self.tcx.hir().find(hir_id) + && let Some(item) = self.tcx.hir().find_parent(hir_id) + && let Some(decl) = item.fn_decl() + && let Some(t) = decl.inputs.iter().find(|t| param.ty_span.contains(t.span)) + { + // We use `contains` because the type might be surrounded by parentheses, + // which makes `ty_span` and `t.span` disagree with each other, but one + // fully contains the other: `foo: (dyn Foo + Bar)` + // ^-------------^ + // || + // |t.span + // param._ty_span + ty = Some(t); + } else if let Some(hir_id) = hir_id + && let Some(hir::Node::Ty(t)) = self.tcx.hir().find(hir_id) + { + ty = Some(t); + } + if let Some(ty) = ty { + match ty.kind { + hir::TyKind::TraitObject(traits, _, _) => { + let (span, kw) = match traits { + [first, ..] if first.span.lo() == ty.span.lo() => { + // Missing `dyn` in front of trait object. + (ty.span.shrink_to_lo(), "dyn ") + } + [first, ..] => (ty.span.until(first.span), ""), + [] => span_bug!(ty.span, "trait object with no traits: {ty:?}"), + }; + let needs_parens = traits.len() != 1; + err.span_suggestion_verbose( + span, + "you can use `impl Trait` as the argument type", + "impl ".to_string(), + Applicability::MaybeIncorrect, + ); + let sugg = if !needs_parens { + vec![(span.shrink_to_lo(), format!("&{kw}"))] + } else { + vec![ + (span.shrink_to_lo(), format!("&({kw}")), + (ty.span.shrink_to_hi(), ")".to_string()), + ] + }; + err.multipart_suggestion_verbose( + borrowed_msg, + sugg, + Applicability::MachineApplicable, + ); + } + hir::TyKind::Slice(_ty) => { + err.span_suggestion_verbose( + ty.span.shrink_to_lo(), + "function arguments must have a statically known size, borrowed \ + slices always have a known size", + "&", + Applicability::MachineApplicable, + ); + } + hir::TyKind::Path(_) => { + err.span_suggestion_verbose( + ty.span.shrink_to_lo(), + borrowed_msg, + "&", + Applicability::MachineApplicable, + ); + } + _ => {} + } } else { err.note("all function arguments must have a statically known size"); } diff --git a/src/tools/clippy/tests/ui/crashes/ice-6251.stderr b/src/tools/clippy/tests/ui/crashes/ice-6251.stderr index 11081dc8087e2..0196c9923dbe6 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6251.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6251.stderr @@ -6,7 +6,7 @@ LL | fn bug() -> impl Iterator { | = help: the trait `std::marker::Sized` is not implemented for `[u8]` = help: unsized fn params are gated as an unstable feature -help: function arguments must have a statically known size, borrowed types always have a known size +help: function arguments must have a statically known size, borrowed slices always have a known size | LL | fn bug() -> impl Iterator { | + diff --git a/tests/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/tests/ui/feature-gates/feature-gate-unsized_fn_params.stderr index 92c71392672e1..b11c30eaad4b7 100644 --- a/tests/ui/feature-gates/feature-gate-unsized_fn_params.stderr +++ b/tests/ui/feature-gates/feature-gate-unsized_fn_params.stderr @@ -29,8 +29,8 @@ LL | fn bar(x: impl Foo) { | ++++ help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn bar(x: &Foo) { - | + +LL | fn bar(x: &dyn Foo) { + | ++++ error[E0277]: the size for values of type `[()]` cannot be known at compilation time --> $DIR/feature-gate-unsized_fn_params.rs:25:8 @@ -40,7 +40,7 @@ LL | fn qux(_: [()]) {} | = help: the trait `Sized` is not implemented for `[()]` = help: unsized fn params are gated as an unstable feature -help: function arguments must have a statically known size, borrowed types always have a known size +help: function arguments must have a statically known size, borrowed slices always have a known size | LL | fn qux(_: &[()]) {} | + diff --git a/tests/ui/resolve/issue-5035-2.stderr b/tests/ui/resolve/issue-5035-2.stderr index 8eeb398f077ea..30721c0a206e7 100644 --- a/tests/ui/resolve/issue-5035-2.stderr +++ b/tests/ui/resolve/issue-5035-2.stderr @@ -6,10 +6,6 @@ LL | fn foo(_x: K) {} | = help: the trait `Sized` is not implemented for `(dyn I + 'static)` = help: unsized fn params are gated as an unstable feature -help: you can use `impl Trait` as the argument type - | -LL | fn foo(_x: impl K) {} - | ++++ help: function arguments must have a statically known size, borrowed types always have a known size | LL | fn foo(_x: &K) {} diff --git a/tests/ui/traits/bound/not-on-bare-trait.stderr b/tests/ui/traits/bound/not-on-bare-trait.stderr index edb6b1d934bd4..8d0e40be788c1 100644 --- a/tests/ui/traits/bound/not-on-bare-trait.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait.stderr @@ -34,8 +34,8 @@ LL | fn foo(_x: impl Foo + Send) { | ++++ help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn foo(_x: &(Foo + Send)) { - | ++ + +LL | fn foo(_x: &(dyn Foo + Send)) { + | +++++ + error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time --> $DIR/not-on-bare-trait.rs:12:8 @@ -47,12 +47,12 @@ LL | fn bar(_x: (dyn Foo + Send)) { = help: unsized fn params are gated as an unstable feature help: you can use `impl Trait` as the argument type | -LL | fn bar(_x: impl (dyn Foo + Send)) { - | ++++ +LL | fn bar(_x: (impl Foo + Send)) { + | ~~~~ help: function arguments must have a statically known size, borrowed types always have a known size | -LL | fn bar(_x: &(dyn Foo + Send)) { - | + +LL | fn bar(_x: (&(dyn Foo + Send))) { + | ++ + error: aborting due to 2 previous errors; 1 warning emitted From 771966ba294be37e0613d97109f203393521e217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 3 Jan 2024 19:25:31 +0000 Subject: [PATCH 09/34] review comments --- .../rustc_hir_analysis/src/astconv/lint.rs | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index 99dbba1ecdc51..2be172e8113ae 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -41,8 +41,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { else { return; }; - let Some(sugg) = self.generics_suggestion(generics, self_ty.span, &impl_trait_name) - else { + let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &impl_trait_name); + if sugg.is_empty() { return; }; diag.multipart_suggestion( @@ -56,12 +56,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - fn generics_suggestion( + fn add_generic_param_suggestion( &self, generics: &hir::Generics<'_>, self_ty_span: Span, impl_trait_name: &str, - ) -> Option> { + ) -> Vec<(Span, String)> { // check if the trait has generics, to make a correct suggestion let param_name = generics.params.next_type_param_name(None); @@ -70,7 +70,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } else { (generics.span, format!("<{param_name}: {impl_trait_name}>")) }; - Some(vec![(self_ty_span, param_name), add_generic_sugg]) + vec![(self_ty_span, param_name), add_generic_sugg] } /// Make sure that we are in the condition to suggest `impl Trait`. @@ -86,7 +86,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { else { return false; }; - let Ok(trait_name) = self.tcx().sess.source_map().span_to_snippet(self_ty.span) else { + let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return false; }; let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())]; @@ -98,19 +98,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { impl_sugg, Applicability::MachineApplicable, ); - diag.multipart_suggestion_verbose( - "alternatively, you can return an owned trait object", - vec![ - (ty.span.shrink_to_lo(), "Box".to_string()), - ], - Applicability::MachineApplicable, - ); + if tcx.check_is_object_safe(def_id) { + diag.multipart_suggestion_verbose( + "alternatively, you can return an owned trait object", + vec![ + (ty.span.shrink_to_lo(), "Box".to_string()), + ], + Applicability::MachineApplicable, + ); + } return true; } for ty in sig.decl.inputs { if ty.hir_id == self_ty.hir_id { - if let Some(sugg) = self.generics_suggestion(generics, self_ty.span, &trait_name) { + let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &trait_name); + if !sugg.is_empty() { diag.multipart_suggestion_verbose( format!("use a new generic type parameter, constrained by `{trait_name}`"), sugg, @@ -124,6 +127,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Applicability::MachineApplicable, ); } + if !tcx.check_is_object_safe(def_id) { + diag.note(format!("it is not object safe, so it can't be `dyn`")); + } let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind { // There are more than one trait bound, we need surrounding parentheses. vec![ From 1e922239256348270dd58fc72a24ad0972ddafe4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 4 Jan 2024 07:55:59 +1100 Subject: [PATCH 10/34] Remove unused `DiagnosticBuilder::struct_almost_fatal`. `create_almost_fatal` and `emit_almost_fatal` are always used instead. --- compiler/rustc_errors/src/lib.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 6dc3a8cd08ece..a4b31748e85bd 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -878,16 +878,6 @@ impl DiagCtxt { DiagnosticBuilder::new(self, Fatal, msg) } - /// Construct a builder at the `Fatal` level with the `msg`, that doesn't abort. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_almost_fatal( - &self, - msg: impl Into, - ) -> DiagnosticBuilder<'_, FatalError> { - DiagnosticBuilder::new(self, Fatal, msg) - } - /// Construct a builder at the `Help` level with the `msg`. #[rustc_lint_diagnostics] pub fn struct_help(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { From 78ef94618b037e18d01644638eaf41ecfa5def04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 3 Jan 2024 21:00:04 +0000 Subject: [PATCH 11/34] Account for object unsafe traits Fix #119525. --- .../rustc_hir_analysis/src/astconv/lint.rs | 66 ++++++++++++------- .../bare-trait-dont-suggest-dyn.fixed | 11 ++++ .../bare-trait-dont-suggest-dyn.rs | 11 ++++ .../bare-trait-dont-suggest-dyn.stderr | 35 ++++++++++ 4 files changed, 98 insertions(+), 25 deletions(-) create mode 100644 tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed create mode 100644 tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs create mode 100644 tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index 2be172e8113ae..d26f3d5ee917f 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -1,6 +1,7 @@ use rustc_ast::TraitObjectSyntax; use rustc_errors::{Diagnostic, StashKey}; use rustc_hir as hir; +use rustc_hir::def::{DefKind, Res}; use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; @@ -90,15 +91,29 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return false; }; let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())]; + let is_object_safe = match self_ty.kind { + hir::TyKind::TraitObject(objects, ..) => { + objects.iter().all(|o| match o.trait_ref.path.res { + Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id), + _ => false, + }) + } + _ => false, + }; if let hir::FnRetTy::Return(ty) = sig.decl.output && ty.hir_id == self_ty.hir_id { - diag.multipart_suggestion_verbose( - format!("use `impl {trait_name}` to return an opaque type, as long as you return a single underlying type"), - impl_sugg, - Applicability::MachineApplicable, + let pre = if !is_object_safe { + format!("`{trait_name}` is not object safe, ") + } else { + String::new() + }; + let msg = format!( + "{pre}use `impl {trait_name}` to return an opaque type, as long as you return a \ + single underlying type", ); - if tcx.check_is_object_safe(def_id) { + diag.multipart_suggestion_verbose(msg, impl_sugg, Applicability::MachineApplicable); + if is_object_safe { diag.multipart_suggestion_verbose( "alternatively, you can return an owned trait object", vec![ @@ -111,25 +126,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return true; } for ty in sig.decl.inputs { - if ty.hir_id == self_ty.hir_id { - let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &trait_name); - if !sugg.is_empty() { - diag.multipart_suggestion_verbose( - format!("use a new generic type parameter, constrained by `{trait_name}`"), - sugg, - Applicability::MachineApplicable, - ); - diag.multipart_suggestion_verbose( - "you can also use an opaque type, but users won't be able to specify the \ - type parameter when calling the `fn`, having to rely exclusively on type \ - inference", - impl_sugg, - Applicability::MachineApplicable, - ); - } - if !tcx.check_is_object_safe(def_id) { - diag.note(format!("it is not object safe, so it can't be `dyn`")); - } + if ty.hir_id != self_ty.hir_id { + continue; + } + let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &trait_name); + if !sugg.is_empty() { + diag.multipart_suggestion_verbose( + format!("use a new generic type parameter, constrained by `{trait_name}`"), + sugg, + Applicability::MachineApplicable, + ); + diag.multipart_suggestion_verbose( + "you can also use an opaque type, but users won't be able to specify the type \ + parameter when calling the `fn`, having to rely exclusively on type inference", + impl_sugg, + Applicability::MachineApplicable, + ); + } + if !is_object_safe { + diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`")); + } else { let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind { // There are more than one trait bound, we need surrounding parentheses. vec![ @@ -147,8 +163,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { sugg, Applicability::MachineApplicable, ); - return true; } + return true; } false } diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed new file mode 100644 index 0000000000000..9720a781eb8d9 --- /dev/null +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed @@ -0,0 +1,11 @@ +// run-rustfix +#![deny(bare_trait_objects)] +fn ord_prefer_dot(s: String) -> impl Ord { + //~^ ERROR trait objects without an explicit `dyn` are deprecated + //~| ERROR the trait `Ord` cannot be made into an object + //~| WARNING this is accepted in the current edition (Rust 2015) + (s.starts_with("."), s) +} +fn main() { + let _ = ord_prefer_dot(String::new()); +} diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs new file mode 100644 index 0000000000000..31d6e336ccfe7 --- /dev/null +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs @@ -0,0 +1,11 @@ +// run-rustfix +#![deny(bare_trait_objects)] +fn ord_prefer_dot(s: String) -> Ord { + //~^ ERROR trait objects without an explicit `dyn` are deprecated + //~| ERROR the trait `Ord` cannot be made into an object + //~| WARNING this is accepted in the current edition (Rust 2015) + (s.starts_with("."), s) +} +fn main() { + let _ = ord_prefer_dot(String::new()); +} diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr new file mode 100644 index 0000000000000..468a570a0f92e --- /dev/null +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr @@ -0,0 +1,35 @@ +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/bare-trait-dont-suggest-dyn.rs:3:33 + | +LL | fn ord_prefer_dot(s: String) -> Ord { + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/bare-trait-dont-suggest-dyn.rs:2:9 + | +LL | #![deny(bare_trait_objects)] + | ^^^^^^^^^^^^^^^^^^ +help: `Ord` is not object safe, use `impl Ord` to return an opaque type, as long as you return a single underlying type + | +LL | fn ord_prefer_dot(s: String) -> impl Ord { + | ++++ + +error[E0038]: the trait `Ord` cannot be made into an object + --> $DIR/bare-trait-dont-suggest-dyn.rs:3:33 + | +LL | fn ord_prefer_dot(s: String) -> Ord { + | ^^^ `Ord` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: the trait cannot be made into an object because it uses `Self` as a type parameter + ::: $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: the trait cannot be made into an object because it uses `Self` as a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. From 9560c58c2ae77569e9855136537834669f5bbc3b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 4 Jan 2024 11:43:19 +1100 Subject: [PATCH 12/34] Avoid some `rustc_errors::` qualifiers. These are misleading, because the mixture of `Level` and `rustc_errors::Level` makes it look like there are two different types involved. --- compiler/rustc_codegen_ssa/src/back/write.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index cb12470478500..a465c83326491 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1848,9 +1848,9 @@ impl SharedEmitterMain { } Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => { let err_level = match level { - Level::Error { lint: false } => rustc_errors::Level::Error { lint: false }, - Level::Warning(_) => rustc_errors::Level::Warning(None), - Level::Note => rustc_errors::Level::Note, + Level::Error { lint: false } => Level::Error { lint: false }, + Level::Warning(_) => Level::Warning(None), + Level::Note => Level::Note, _ => bug!("Invalid inline asm diagnostic level"), }; let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string(); From 4d35981703ad64ae8b5957386550539ed1ed1435 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 4 Jan 2024 11:44:03 +1100 Subject: [PATCH 13/34] Remove unused `struct_error` function. --- compiler/rustc_middle/src/mir/interpret/error.rs | 10 +--------- compiler/rustc_middle/src/mir/interpret/mod.rs | 11 +++++------ 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index e6536074f35fc..1b4e9c286351a 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -2,14 +2,10 @@ use super::{AllocId, AllocRange, Pointer, Scalar}; use crate::error; use crate::mir::{ConstAlloc, ConstValue}; -use crate::query::TyCtxtAt; use crate::ty::{layout, tls, Ty, TyCtxt, ValTree}; use rustc_data_structures::sync::Lock; -use rustc_errors::{ - struct_span_err, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, - IntoDiagnosticArg, -}; +use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_macros::HashStable; use rustc_session::CtfeBacktrace; use rustc_span::{def_id::DefId, Span, DUMMY_SP}; @@ -90,10 +86,6 @@ pub type EvalToConstValueResult<'tcx> = Result, ErrorHandled>; /// This is needed in `thir::pattern::lower_inline_const`. pub type EvalToValTreeResult<'tcx> = Result>, ErrorHandled>; -pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'tcx> { - struct_span_err!(tcx.dcx(), tcx.span, E0080, "{}", msg) -} - #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(InterpErrorInfo<'_>, 8); diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 2db5600855343..0da3524e05564 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -142,12 +142,11 @@ use crate::ty::GenericArgKind; use crate::ty::{self, Instance, Ty, TyCtxt}; pub use self::error::{ - struct_error, BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, - EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, ExpectedKind, - InterpError, InterpErrorInfo, InterpResult, InvalidMetaKind, InvalidProgramInfo, - MachineStopType, Misalignment, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo, - ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo, - ValidationErrorKind, + BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, + EvalToConstValueResult, EvalToValTreeResult, ExpectedKind, InterpError, InterpErrorInfo, + InterpResult, InvalidMetaKind, InvalidProgramInfo, MachineStopType, Misalignment, PointerKind, + ReportedErrorInfo, ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo, + UnsupportedOpInfo, ValidationErrorInfo, ValidationErrorKind, }; pub use self::value::Scalar; From 8e6bca63f943a061264aec986446fac67c59c262 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 4 Jan 2024 11:44:16 +1100 Subject: [PATCH 14/34] Inline and remove `StringReader::struct_fatal_span_char`. It has a single call site. --- compiler/rustc_parse/src/lexer/mod.rs | 33 +++++++++------------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index fdbb19103c6e9..4819ed6021d0d 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -7,9 +7,7 @@ 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, DiagCtxt, Diagnostic, DiagnosticBuilder, FatalAbort, StashKey, -}; +use rustc_errors::{error_code, Applicability, DiagCtxt, Diagnostic, StashKey}; use rustc_lexer::unescape::{self, EscapeError, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; use rustc_lexer::{Cursor, LiteralKind}; @@ -344,18 +342,6 @@ impl<'a> StringReader<'a> { token::Ident(sym, false) } - fn struct_fatal_span_char( - &self, - from_pos: BytePos, - to_pos: BytePos, - m: &str, - c: char, - ) -> DiagnosticBuilder<'a, FatalAbort> { - self.sess - .dcx - .struct_span_fatal(self.mk_sp(from_pos, to_pos), format!("{}: {}", m, escaped_char(c))) - } - /// Detect usages of Unicode codepoints changing the direction of the text on screen and loudly /// complain about it. fn lint_unicode_text_flow(&self, start: BytePos) { @@ -568,13 +554,16 @@ impl<'a> StringReader<'a> { } fn report_non_started_raw_string(&self, start: BytePos, bad_char: char) -> ! { - self.struct_fatal_span_char( - start, - self.pos, - "found invalid character; only `#` is allowed in raw string delimitation", - bad_char, - ) - .emit() + self.sess + .dcx + .struct_span_fatal( + self.mk_sp(start, self.pos), + format!( + "found invalid character; only `#` is allowed in raw string delimitation: {}", + escaped_char(bad_char) + ), + ) + .emit() } fn report_unterminated_raw_string( From 698dfc322fd42fa4dff71474aba7cdf691a459a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 3 Jan 2024 23:40:49 +0000 Subject: [PATCH 15/34] Silence redundant warning when E0038 will be emitted --- .../rustc_hir_analysis/src/astconv/errors.rs | 2 +- .../rustc_hir_analysis/src/astconv/lint.rs | 5 ++++ .../src/astconv/object_safety.rs | 1 + .../src/traits/error_reporting/mod.rs | 22 ++++++++++++++++- .../error_reporting/type_err_ctxt_ext.rs | 4 ++-- tests/rustdoc-ui/issues/issue-105742.stderr | 4 ++++ .../bare-trait-dont-suggest-dyn.fixed | 4 +--- .../bare-trait-dont-suggest-dyn.rs | 4 +--- .../bare-trait-dont-suggest-dyn.stderr | 24 ++++--------------- ...ect-safety-supertrait-mentions-Self.stderr | 4 ++++ tests/ui/traits/issue-28576.stderr | 4 ++++ 11 files changed, 49 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index f17f19bb77c70..d22c4fe201df0 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -605,7 +605,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let violations = object_safety_violations_for_assoc_item(tcx, trait_def_id, *assoc_item); if !violations.is_empty() { - report_object_safety_error(tcx, *span, trait_def_id, &violations).emit(); + report_object_safety_error(tcx, *span, None, trait_def_id, &violations).emit(); object_safety_violations = true; } } diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index d26f3d5ee917f..6675f517cfa15 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -122,6 +122,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ], Applicability::MachineApplicable, ); + } else { + // We'll emit the object safety error already, with a structured suggestion. + diag.downgrade_to_delayed_bug(); } return true; } @@ -145,6 +148,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } if !is_object_safe { diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`")); + // We'll emit the object safety error already, with a structured suggestion. + diag.downgrade_to_delayed_bug(); } else { let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind { // There are more than one trait bound, we need surrounding parentheses. diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index a614d4abf25f7..8a3df79cb2534 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -140,6 +140,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let reported = report_object_safety_error( tcx, span, + Some(hir_id), item.trait_ref().def_id(), &object_safety_violations, ) diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index d89c205da3f52..4aabe5c292237 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -2,9 +2,10 @@ use super::ObjectSafetyViolation; use crate::infer::InferCtxt; use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{struct_span_err, DiagnosticBuilder, MultiSpan}; +use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::intravisit::Map; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Span; @@ -42,6 +43,7 @@ impl<'tcx> InferCtxt<'tcx> { pub fn report_object_safety_error<'tcx>( tcx: TyCtxt<'tcx>, span: Span, + hir_id: Option, trait_def_id: DefId, violations: &[ObjectSafetyViolation], ) -> DiagnosticBuilder<'tcx> { @@ -59,6 +61,24 @@ pub fn report_object_safety_error<'tcx>( ); err.span_label(span, format!("`{trait_str}` cannot be made into an object")); + if let Some(hir_id) = hir_id + && let Some(hir::Node::Ty(ty)) = tcx.hir().find(hir_id) + && let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind + { + let mut hir_id = hir_id; + while let hir::Node::Ty(ty) = tcx.hir().get_parent(hir_id) { + hir_id = ty.hir_id; + } + if tcx.hir().get_parent(hir_id).fn_sig().is_some() { + // Do not suggest `impl Trait` when dealing with things like super-traits. + err.span_suggestion_verbose( + ty.span.until(trait_ref.span), + "consider using an opaque type instead", + "impl ", + Applicability::MaybeIncorrect, + ); + } + } let mut reported_violations = FxIndexSet::default(); let mut multi_span = vec![]; let mut messages = vec![]; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index d2598b0defe7f..81e02a0b17ed7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -816,7 +816,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::PredicateKind::ObjectSafe(trait_def_id) => { let violations = self.tcx.object_safety_violations(trait_def_id); - report_object_safety_error(self.tcx, span, trait_def_id, violations) + report_object_safety_error(self.tcx, span, None, trait_def_id, violations) } ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => { @@ -924,7 +924,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { TraitNotObjectSafe(did) => { let violations = self.tcx.object_safety_violations(did); - report_object_safety_error(self.tcx, span, did, violations) + report_object_safety_error(self.tcx, span, None, did, violations) } SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => { diff --git a/tests/rustdoc-ui/issues/issue-105742.stderr b/tests/rustdoc-ui/issues/issue-105742.stderr index ad1020a1f0817..d5a9031075f8d 100644 --- a/tests/rustdoc-ui/issues/issue-105742.stderr +++ b/tests/rustdoc-ui/issues/issue-105742.stderr @@ -323,6 +323,10 @@ LL | || Output = ::Item> as SVec>::Item, LL | | LL | | > { | |__^ ...because it uses `Self` as a type parameter +help: consider using an opaque type instead + | +LL | pub fn next<'a, T>(s: &'a mut impl SVec) { + | ~~~~ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:15:21 diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed index 9720a781eb8d9..e95b982966d0b 100644 --- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed @@ -1,9 +1,7 @@ // run-rustfix #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> impl Ord { - //~^ ERROR trait objects without an explicit `dyn` are deprecated - //~| ERROR the trait `Ord` cannot be made into an object - //~| WARNING this is accepted in the current edition (Rust 2015) + //~^ ERROR the trait `Ord` cannot be made into an object (s.starts_with("."), s) } fn main() { diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs index 31d6e336ccfe7..fdf7e0a77aa34 100644 --- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs @@ -1,9 +1,7 @@ // run-rustfix #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> Ord { - //~^ ERROR trait objects without an explicit `dyn` are deprecated - //~| ERROR the trait `Ord` cannot be made into an object - //~| WARNING this is accepted in the current edition (Rust 2015) + //~^ ERROR the trait `Ord` cannot be made into an object (s.starts_with("."), s) } fn main() { diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr index 468a570a0f92e..2c499d240ab0b 100644 --- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr @@ -1,21 +1,3 @@ -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/bare-trait-dont-suggest-dyn.rs:3:33 - | -LL | fn ord_prefer_dot(s: String) -> Ord { - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see -note: the lint level is defined here - --> $DIR/bare-trait-dont-suggest-dyn.rs:2:9 - | -LL | #![deny(bare_trait_objects)] - | ^^^^^^^^^^^^^^^^^^ -help: `Ord` is not object safe, use `impl Ord` to return an opaque type, as long as you return a single underlying type - | -LL | fn ord_prefer_dot(s: String) -> impl Ord { - | ++++ - error[E0038]: the trait `Ord` cannot be made into an object --> $DIR/bare-trait-dont-suggest-dyn.rs:3:33 | @@ -29,7 +11,11 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all ::: $SRC_DIR/core/src/cmp.rs:LL:COL | = note: the trait cannot be made into an object because it uses `Self` as a type parameter +help: consider using an opaque type instead + | +LL | fn ord_prefer_dot(s: String) -> impl Ord { + | ++++ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr index 08df069275a60..fc476691d0147 100644 --- a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr +++ b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr @@ -11,6 +11,10 @@ LL | trait Baz : Bar { | --- ^^^^^^^^^ ...because it uses `Self` as a type parameter | | | this trait cannot be made into an object... +help: consider using an opaque type instead + | +LL | fn make_baz(t: &T) -> &impl Baz { + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr index 9fe508646423e..3b45a510341fe 100644 --- a/tests/ui/traits/issue-28576.stderr +++ b/tests/ui/traits/issue-28576.stderr @@ -14,6 +14,10 @@ LL | pub trait Bar: Foo { | | | ...because it uses `Self` as a type parameter | | ...because it uses `Self` as a type parameter | this trait cannot be made into an object... +help: consider using an opaque type instead + | +LL | impl Bar + | ~~~~ error: aborting due to 1 previous error From af3205421ff989c143e09b6e96413eadaa1dbc4d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 4 Jan 2024 13:43:27 +1100 Subject: [PATCH 16/34] Remove `-Zdump-mir-spanview` --- compiler/rustc_interface/src/tests.rs | 5 +- compiler/rustc_middle/src/mir/mod.rs | 1 - compiler/rustc_middle/src/mir/pretty.rs | 11 - compiler/rustc_middle/src/mir/spanview.rs | 642 ------------------ compiler/rustc_session/src/config.rs | 15 - compiler/rustc_session/src/options.rs | 29 - .../spanview_block.main.built.after.html | 67 -- tests/mir-opt/spanview_block.rs | 6 - .../spanview_statement.main.built.after.html | 67 -- tests/mir-opt/spanview_statement.rs | 6 - .../spanview_terminator.main.built.after.html | 66 -- tests/mir-opt/spanview_terminator.rs | 6 - 12 files changed, 2 insertions(+), 919 deletions(-) delete mode 100644 compiler/rustc_middle/src/mir/spanview.rs delete mode 100644 tests/mir-opt/spanview_block.main.built.after.html delete mode 100644 tests/mir-opt/spanview_block.rs delete mode 100644 tests/mir-opt/spanview_statement.main.built.after.html delete mode 100644 tests/mir-opt/spanview_statement.rs delete mode 100644 tests/mir-opt/spanview_terminator.main.built.after.html delete mode 100644 tests/mir-opt/spanview_terminator.rs diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index c4a1f3a0e510b..06dde1402a9b7 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -6,8 +6,8 @@ use rustc_session::config::{ build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, - LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, MirSpanview, NextSolverConfig, - OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, + LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, + Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use rustc_session::lint::Level; @@ -666,7 +666,6 @@ fn test_unstable_options_tracking_hash() { untracked!(dump_mir_dir, String::from("abc")); untracked!(dump_mir_exclude_pass_number, true); untracked!(dump_mir_graphviz, true); - untracked!(dump_mir_spanview, Some(MirSpanview::Statement)); untracked!(dump_mono_stats, SwitchWithOptPath::Enabled(Some("mono-items-dir/".into()))); untracked!(dump_mono_stats_format, DumpMonoStatsFormat::Json); untracked!(dylib_lto, true); diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 5c425fef27ebc..903da8374cd3b 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -55,7 +55,6 @@ pub mod mono; pub mod patch; pub mod pretty; mod query; -pub mod spanview; mod statement; mod syntax; pub mod tcx; diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 0b487eae36dbd..a1e5d73a0fdb1 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -5,7 +5,6 @@ use std::io::{self, Write as _}; use std::path::{Path, PathBuf}; use super::graphviz::write_mir_fn_graphviz; -use super::spanview::write_mir_fn_spanview; use rustc_ast::InlineAsmTemplatePiece; use rustc_middle::mir::interpret::{ alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer, @@ -141,16 +140,6 @@ fn dump_matched_mir_node<'tcx, F>( write_mir_fn_graphviz(tcx, body, false, &mut file)?; }; } - - if let Some(spanview) = tcx.sess.opts.unstable_opts.dump_mir_spanview { - let _: io::Result<()> = try { - let file_basename = dump_file_basename(tcx, pass_num, pass_name, disambiguator, body); - let mut file = create_dump_file_with_basename(tcx, &file_basename, "html")?; - if body.source.def_id().is_local() { - write_mir_fn_spanview(tcx, body, spanview, &file_basename, &mut file)?; - } - }; - } } /// Returns the file basename portion (without extension) of a filename path diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs deleted file mode 100644 index cb9fc0d37f2e0..0000000000000 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ /dev/null @@ -1,642 +0,0 @@ -use rustc_middle::hir; -use rustc_middle::mir::*; -use rustc_session::config::MirSpanview; -use rustc_span::{BytePos, Pos}; - -use std::cmp; -use std::io::{self, Write}; - -pub const TOOLTIP_INDENT: &str = " "; - -const CARET: char = '\u{2038}'; // Unicode `CARET` -const ANNOTATION_LEFT_BRACKET: char = '\u{298a}'; // Unicode `Z NOTATION RIGHT BINDING BRACKET` -const ANNOTATION_RIGHT_BRACKET: char = '\u{2989}'; // Unicode `Z NOTATION LEFT BINDING BRACKET` -const NEW_LINE_SPAN: &str = "\n"; -const HEADER: &str = r#" - - -"#; -const START_BODY: &str = r#" -"#; -const FOOTER: &str = r#" -"#; - -const STYLE_SECTION: &str = r#""#; - -/// Metadata to highlight the span of a MIR BasicBlock, Statement, or Terminator. -#[derive(Clone, Debug)] -pub struct SpanViewable { - pub bb: BasicBlock, - pub span: Span, - pub id: String, - pub tooltip: String, -} - -/// Write a spanview HTML+CSS file to analyze MIR element spans. -pub fn write_mir_fn_spanview<'tcx, W>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, - spanview: MirSpanview, - title: &str, - w: &mut W, -) -> io::Result<()> -where - W: Write, -{ - let def_id = body.source.def_id(); - let hir_body = hir_body(tcx, def_id); - if hir_body.is_none() { - return Ok(()); - } - let body_span = hir_body.unwrap().value.span; - let mut span_viewables = Vec::new(); - for (bb, data) in body.basic_blocks.iter_enumerated() { - match spanview { - MirSpanview::Statement => { - for (i, statement) in data.statements.iter().enumerate() { - if let Some(span_viewable) = - statement_span_viewable(tcx, body_span, bb, i, statement) - { - span_viewables.push(span_viewable); - } - } - if let Some(span_viewable) = terminator_span_viewable(tcx, body_span, bb, data) { - span_viewables.push(span_viewable); - } - } - MirSpanview::Terminator => { - if let Some(span_viewable) = terminator_span_viewable(tcx, body_span, bb, data) { - span_viewables.push(span_viewable); - } - } - MirSpanview::Block => { - if let Some(span_viewable) = block_span_viewable(tcx, body_span, bb, data) { - span_viewables.push(span_viewable); - } - } - } - } - write_document(tcx, fn_span(tcx, def_id), span_viewables, title, w)?; - Ok(()) -} - -/// Generate a spanview HTML+CSS document for the given local function `def_id`, and a pre-generated -/// list `SpanViewable`s. -pub fn write_document<'tcx, W>( - tcx: TyCtxt<'tcx>, - spanview_span: Span, - mut span_viewables: Vec, - title: &str, - w: &mut W, -) -> io::Result<()> -where - W: Write, -{ - let mut from_pos = spanview_span.lo(); - let end_pos = spanview_span.hi(); - let source_map = tcx.sess.source_map(); - let start = source_map.lookup_char_pos(from_pos); - let indent_to_initial_start_col = " ".repeat(start.col.to_usize()); - debug!( - "spanview_span={:?}; source is:\n{}{}", - spanview_span, - indent_to_initial_start_col, - source_map.span_to_snippet(spanview_span).expect("function should have printable source") - ); - writeln!(w, "{HEADER}")?; - writeln!(w, "{title}")?; - writeln!(w, "{STYLE_SECTION}")?; - writeln!(w, "{START_BODY}")?; - write!( - w, - r#"

{}"#, - start.line - 1, - indent_to_initial_start_col, - )?; - span_viewables.sort_unstable_by(|a, b| { - let a = a.span; - let b = b.span; - if a.lo() == b.lo() { - // Sort hi() in reverse order so shorter spans are attempted after longer spans. - // This should give shorter spans a higher "layer", so they are not covered by - // the longer spans. - b.hi().partial_cmp(&a.hi()) - } else { - a.lo().partial_cmp(&b.lo()) - } - .unwrap() - }); - let mut ordered_viewables = &span_viewables[..]; - const LOWEST_VIEWABLE_LAYER: usize = 1; - let mut alt = false; - while ordered_viewables.len() > 0 { - debug!( - "calling write_next_viewable with from_pos={}, end_pos={}, and viewables len={}", - from_pos.to_usize(), - end_pos.to_usize(), - ordered_viewables.len() - ); - let curr_id = &ordered_viewables[0].id; - let (next_from_pos, next_ordered_viewables) = write_next_viewable_with_overlaps( - tcx, - from_pos, - end_pos, - ordered_viewables, - alt, - LOWEST_VIEWABLE_LAYER, - w, - )?; - debug!( - "DONE calling write_next_viewable, with new from_pos={}, \ - and remaining viewables len={}", - next_from_pos.to_usize(), - next_ordered_viewables.len() - ); - assert!( - from_pos != next_from_pos || ordered_viewables.len() != next_ordered_viewables.len(), - "write_next_viewable_with_overlaps() must make a state change" - ); - from_pos = next_from_pos; - if next_ordered_viewables.len() != ordered_viewables.len() { - ordered_viewables = next_ordered_viewables; - if let Some(next_ordered_viewable) = ordered_viewables.first() { - if &next_ordered_viewable.id != curr_id { - alt = !alt; - } - } - } - } - if from_pos < end_pos { - write_coverage_gap(tcx, from_pos, end_pos, w)?; - } - writeln!(w, r#"
"#)?; - writeln!(w, "{FOOTER}")?; - Ok(()) -} - -/// Format a string showing the start line and column, and end line and column within a file. -pub fn source_range_no_file(tcx: TyCtxt<'_>, span: Span) -> String { - let source_map = tcx.sess.source_map(); - let start = source_map.lookup_char_pos(span.lo()); - let end = source_map.lookup_char_pos(span.hi()); - format!("{}:{}-{}:{}", start.line, start.col.to_usize() + 1, end.line, end.col.to_usize() + 1) -} - -fn statement_span_viewable<'tcx>( - tcx: TyCtxt<'tcx>, - body_span: Span, - bb: BasicBlock, - i: usize, - statement: &Statement<'tcx>, -) -> Option { - let span = statement.source_info.span; - if !body_span.contains(span) { - return None; - } - let id = format!("{}[{}]", bb.index(), i); - let tooltip = tooltip(tcx, &id, span, vec![statement.clone()], &None); - Some(SpanViewable { bb, span, id, tooltip }) -} - -fn terminator_span_viewable<'tcx>( - tcx: TyCtxt<'tcx>, - body_span: Span, - bb: BasicBlock, - data: &BasicBlockData<'tcx>, -) -> Option { - let term = data.terminator(); - let span = term.source_info.span; - if !body_span.contains(span) { - return None; - } - let id = format!("{}:{}", bb.index(), term.kind.name()); - let tooltip = tooltip(tcx, &id, span, vec![], &data.terminator); - Some(SpanViewable { bb, span, id, tooltip }) -} - -fn block_span_viewable<'tcx>( - tcx: TyCtxt<'tcx>, - body_span: Span, - bb: BasicBlock, - data: &BasicBlockData<'tcx>, -) -> Option { - let span = compute_block_span(data, body_span); - if !body_span.contains(span) { - return None; - } - let id = format!("{}", bb.index()); - let tooltip = tooltip(tcx, &id, span, data.statements.clone(), &data.terminator); - Some(SpanViewable { bb, span, id, tooltip }) -} - -fn compute_block_span(data: &BasicBlockData<'_>, body_span: Span) -> Span { - let mut span = data.terminator().source_info.span; - for statement_span in data.statements.iter().map(|statement| statement.source_info.span) { - // Only combine Spans from the root context, and within the function's body_span. - if statement_span.ctxt().is_root() && body_span.contains(statement_span) { - span = span.to(statement_span); - } - } - span -} - -/// Recursively process each ordered span. Spans that overlap will have progressively varying -/// styles, such as increased padding for each overlap. Non-overlapping adjacent spans will -/// have alternating style choices, to help distinguish between them if, visually adjacent. -/// The `layer` is incremented for each overlap, and the `alt` bool alternates between true -/// and false, for each adjacent non-overlapping span. Source code between the spans (code -/// that is not in any coverage region) has neutral styling. -fn write_next_viewable_with_overlaps<'tcx, 'b, W>( - tcx: TyCtxt<'tcx>, - mut from_pos: BytePos, - mut to_pos: BytePos, - ordered_viewables: &'b [SpanViewable], - alt: bool, - layer: usize, - w: &mut W, -) -> io::Result<(BytePos, &'b [SpanViewable])> -where - W: Write, -{ - let debug_indent = " ".repeat(layer); - let (viewable, mut remaining_viewables) = - ordered_viewables.split_first().expect("ordered_viewables should have some"); - - if from_pos < viewable.span.lo() { - debug!( - "{}advance from_pos to next SpanViewable (from from_pos={} to viewable.span.lo()={} \ - of {:?}), with to_pos={}", - debug_indent, - from_pos.to_usize(), - viewable.span.lo().to_usize(), - viewable.span, - to_pos.to_usize() - ); - let hi = cmp::min(viewable.span.lo(), to_pos); - write_coverage_gap(tcx, from_pos, hi, w)?; - from_pos = hi; - if from_pos < viewable.span.lo() { - debug!( - "{}EARLY RETURN: stopped before getting to next SpanViewable, at {}", - debug_indent, - from_pos.to_usize() - ); - return Ok((from_pos, ordered_viewables)); - } - } - - if from_pos < viewable.span.hi() { - // Set to_pos to the end of this `viewable` to ensure the recursive calls stop writing - // with room to print the tail. - to_pos = cmp::min(viewable.span.hi(), to_pos); - debug!( - "{}update to_pos (if not closer) to viewable.span.hi()={}; to_pos is now {}", - debug_indent, - viewable.span.hi().to_usize(), - to_pos.to_usize() - ); - } - - let mut subalt = false; - while remaining_viewables.len() > 0 && remaining_viewables[0].span.overlaps(viewable.span) { - let overlapping_viewable = &remaining_viewables[0]; - debug!("{}overlapping_viewable.span={:?}", debug_indent, overlapping_viewable.span); - - let span = - trim_span(viewable.span, from_pos, cmp::min(overlapping_viewable.span.lo(), to_pos)); - let mut some_html_snippet = if from_pos <= viewable.span.hi() || viewable.span.is_empty() { - // `viewable` is not yet fully rendered, so start writing the span, up to either the - // `to_pos` or the next `overlapping_viewable`, whichever comes first. - debug!( - "{}make html_snippet (may not write it if early exit) for partial span {:?} \ - of viewable.span {:?}", - debug_indent, span, viewable.span - ); - from_pos = span.hi(); - make_html_snippet(tcx, span, Some(viewable)) - } else { - None - }; - - // Defer writing the HTML snippet (until after early return checks) ONLY for empty spans. - // An empty Span with Some(html_snippet) is probably a tail marker. If there is an early - // exit, there should be another opportunity to write the tail marker. - if !span.is_empty() { - if let Some(ref html_snippet) = some_html_snippet { - debug!( - "{}write html_snippet for that partial span of viewable.span {:?}", - debug_indent, viewable.span - ); - write_span(html_snippet, &viewable.tooltip, alt, layer, w)?; - } - some_html_snippet = None; - } - - if from_pos < overlapping_viewable.span.lo() { - debug!( - "{}EARLY RETURN: from_pos={} has not yet reached the \ - overlapping_viewable.span {:?}", - debug_indent, - from_pos.to_usize(), - overlapping_viewable.span - ); - // must have reached `to_pos` before reaching the start of the - // `overlapping_viewable.span` - return Ok((from_pos, ordered_viewables)); - } - - if from_pos == to_pos - && !(from_pos == overlapping_viewable.span.lo() && overlapping_viewable.span.is_empty()) - { - debug!( - "{}EARLY RETURN: from_pos=to_pos={} and overlapping_viewable.span {:?} is not \ - empty, or not from_pos", - debug_indent, - to_pos.to_usize(), - overlapping_viewable.span - ); - // `to_pos` must have occurred before the overlapping viewable. Return - // `ordered_viewables` so we can continue rendering the `viewable`, from after the - // `to_pos`. - return Ok((from_pos, ordered_viewables)); - } - - if let Some(ref html_snippet) = some_html_snippet { - debug!( - "{}write html_snippet for that partial span of viewable.span {:?}", - debug_indent, viewable.span - ); - write_span(html_snippet, &viewable.tooltip, alt, layer, w)?; - } - - debug!( - "{}recursively calling write_next_viewable with from_pos={}, to_pos={}, \ - and viewables len={}", - debug_indent, - from_pos.to_usize(), - to_pos.to_usize(), - remaining_viewables.len() - ); - // Write the overlaps (and the overlaps' overlaps, if any) up to `to_pos`. - let curr_id = &remaining_viewables[0].id; - let (next_from_pos, next_remaining_viewables) = write_next_viewable_with_overlaps( - tcx, - from_pos, - to_pos, - remaining_viewables, - subalt, - layer + 1, - w, - )?; - debug!( - "{}DONE recursively calling write_next_viewable, with new from_pos={}, and remaining \ - viewables len={}", - debug_indent, - next_from_pos.to_usize(), - next_remaining_viewables.len() - ); - assert!( - from_pos != next_from_pos - || remaining_viewables.len() != next_remaining_viewables.len(), - "write_next_viewable_with_overlaps() must make a state change" - ); - from_pos = next_from_pos; - if next_remaining_viewables.len() != remaining_viewables.len() { - remaining_viewables = next_remaining_viewables; - if let Some(next_ordered_viewable) = remaining_viewables.first() { - if &next_ordered_viewable.id != curr_id { - subalt = !subalt; - } - } - } - } - if from_pos <= viewable.span.hi() { - let span = trim_span(viewable.span, from_pos, to_pos); - debug!( - "{}After overlaps, writing (end span?) {:?} of viewable.span {:?}", - debug_indent, span, viewable.span - ); - if let Some(ref html_snippet) = make_html_snippet(tcx, span, Some(viewable)) { - from_pos = span.hi(); - write_span(html_snippet, &viewable.tooltip, alt, layer, w)?; - } - } - debug!("{}RETURN: No more overlap", debug_indent); - Ok(( - from_pos, - if from_pos < viewable.span.hi() { ordered_viewables } else { remaining_viewables }, - )) -} - -#[inline(always)] -fn write_coverage_gap(tcx: TyCtxt<'_>, lo: BytePos, hi: BytePos, w: &mut W) -> io::Result<()> -where - W: Write, -{ - let span = Span::with_root_ctxt(lo, hi); - if let Some(ref html_snippet) = make_html_snippet(tcx, span, None) { - write_span(html_snippet, "", false, 0, w) - } else { - Ok(()) - } -} - -fn write_span( - html_snippet: &str, - tooltip: &str, - alt: bool, - layer: usize, - w: &mut W, -) -> io::Result<()> -where - W: Write, -{ - let maybe_alt_class = if layer > 0 { if alt { " odd" } else { " even" } } else { "" }; - let maybe_title_attr = if !tooltip.is_empty() { - format!(" title=\"{}\"", escape_attr(tooltip)) - } else { - "".to_owned() - }; - if layer == 1 { - write!(w, "")?; - } - for (i, line) in html_snippet.lines().enumerate() { - if i > 0 { - write!(w, "{NEW_LINE_SPAN}")?; - } - write!( - w, - r#"{line}"# - )?; - } - // Check for and translate trailing newlines, because `str::lines()` ignores them - if html_snippet.ends_with('\n') { - write!(w, "{NEW_LINE_SPAN}")?; - } - if layer == 1 { - write!(w, "")?; - } - Ok(()) -} - -fn make_html_snippet( - tcx: TyCtxt<'_>, - span: Span, - some_viewable: Option<&SpanViewable>, -) -> Option { - let source_map = tcx.sess.source_map(); - let snippet = source_map - .span_to_snippet(span) - .unwrap_or_else(|err| bug!("span_to_snippet error for span {:?}: {:?}", span, err)); - let html_snippet = if let Some(viewable) = some_viewable { - let is_head = span.lo() == viewable.span.lo(); - let is_tail = span.hi() == viewable.span.hi(); - let mut labeled_snippet = if is_head { - format!(r#"{}{}"#, viewable.id, ANNOTATION_LEFT_BRACKET) - } else { - "".to_owned() - }; - if span.is_empty() { - if is_head && is_tail { - labeled_snippet.push(CARET); - } - } else { - labeled_snippet.push_str(&escape_html(&snippet)); - }; - if is_tail { - labeled_snippet.push_str(&format!( - r#"{}{}"#, - ANNOTATION_RIGHT_BRACKET, viewable.id - )); - } - labeled_snippet - } else { - escape_html(&snippet) - }; - if html_snippet.is_empty() { None } else { Some(html_snippet) } -} - -fn tooltip<'tcx>( - tcx: TyCtxt<'tcx>, - spanview_id: &str, - span: Span, - statements: Vec>, - terminator: &Option>, -) -> String { - let source_map = tcx.sess.source_map(); - let mut text = Vec::new(); - text.push(format!("{}: {}:", spanview_id, &source_map.span_to_embeddable_string(span))); - for statement in statements { - let source_range = source_range_no_file(tcx, statement.source_info.span); - text.push(format!( - "\n{}{}: {}: {:?}", - TOOLTIP_INDENT, - source_range, - statement.kind.name(), - statement - )); - } - if let Some(term) = terminator { - let source_range = source_range_no_file(tcx, term.source_info.span); - text.push(format!( - "\n{}{}: {}: {:?}", - TOOLTIP_INDENT, - source_range, - term.kind.name(), - term.kind - )); - } - text.join("") -} - -fn trim_span(span: Span, from_pos: BytePos, to_pos: BytePos) -> Span { - trim_span_hi(trim_span_lo(span, from_pos), to_pos) -} - -fn trim_span_lo(span: Span, from_pos: BytePos) -> Span { - if from_pos <= span.lo() { span } else { span.with_lo(cmp::min(span.hi(), from_pos)) } -} - -fn trim_span_hi(span: Span, to_pos: BytePos) -> Span { - if to_pos >= span.hi() { span } else { span.with_hi(cmp::max(span.lo(), to_pos)) } -} - -fn fn_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span { - let fn_decl_span = tcx.def_span(def_id); - if let Some(body_span) = hir_body(tcx, def_id).map(|hir_body| hir_body.value.span) { - if fn_decl_span.eq_ctxt(body_span) { fn_decl_span.to(body_span) } else { body_span } - } else { - fn_decl_span - } -} - -fn hir_body(tcx: TyCtxt<'_>, def_id: DefId) -> Option<&rustc_hir::Body<'_>> { - let hir_node = tcx.hir().get_if_local(def_id).expect("expected DefId is local"); - hir::map::associated_body(hir_node).map(|(_, fn_body_id)| tcx.hir().body(fn_body_id)) -} - -fn escape_html(s: &str) -> String { - s.replace('&', "&").replace('<', "<").replace('>', ">") -} - -fn escape_attr(s: &str) -> String { - s.replace('&', "&") - .replace('\"', """) - .replace('\'', "'") - .replace('<', "<") - .replace('>', ">") -} diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 89508c77639aa..770c85cd0fcbe 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -125,21 +125,6 @@ pub enum LtoCli { Unspecified, } -/// The different settings that the `-Z dump_mir_spanview` flag can have. `Statement` generates a -/// document highlighting each span of every statement (including terminators). `Terminator` and -/// `Block` highlight a single span per `BasicBlock`: the span of the block's `Terminator`, or a -/// computed span for the block, representing the entire range, covering the block's terminator and -/// all of its statements. -#[derive(Clone, Copy, PartialEq, Hash, Debug)] -pub enum MirSpanview { - /// Default `-Z dump_mir_spanview` or `-Z dump_mir_spanview=statement` - Statement, - /// `-Z dump_mir_spanview=terminator` - Terminator, - /// `-Z dump_mir_spanview=block` - Block, -} - /// The different settings that the `-C instrument-coverage` flag can have. /// /// Coverage instrumentation now supports combining `-C instrument-coverage` diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 8274fd05bc057..d13b02f046fa4 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -391,7 +391,6 @@ mod desc { pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; - pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`"; pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`"; pub const parse_instrument_coverage: &str = "`all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off`"; @@ -866,29 +865,6 @@ mod parse { } } - pub(crate) fn parse_mir_spanview(slot: &mut Option, v: Option<&str>) -> bool { - if v.is_some() { - let mut bool_arg = None; - if parse_opt_bool(&mut bool_arg, v) { - *slot = bool_arg.unwrap().then_some(MirSpanview::Statement); - return true; - } - } - - let Some(v) = v else { - *slot = Some(MirSpanview::Statement); - return true; - }; - - *slot = Some(match v.trim_end_matches('s') { - "statement" | "stmt" => MirSpanview::Statement, - "terminator" | "term" => MirSpanview::Terminator, - "block" | "basicblock" => MirSpanview::Block, - _ => return false, - }); - true - } - pub(crate) fn parse_time_passes_format(slot: &mut TimePassesFormat, v: Option<&str>) -> bool { match v { None => true, @@ -1601,11 +1577,6 @@ options! { "exclude the pass number when dumping MIR (used in tests) (default: no)"), dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED], "in addition to `.mir` files, create graphviz `.dot` files (default: no)"), - dump_mir_spanview: Option = (None, parse_mir_spanview, [UNTRACKED], - "in addition to `.mir` files, create `.html` files to view spans for \ - all `statement`s (including terminators), only `terminator` spans, or \ - computed `block` spans (one span encompassing a block's terminator and \ - all statements)."), dump_mono_stats: SwitchWithOptPath = (SwitchWithOptPath::Disabled, parse_switch_with_opt_path, [UNTRACKED], "output statistics about monomorphization collection"), diff --git a/tests/mir-opt/spanview_block.main.built.after.html b/tests/mir-opt/spanview_block.main.built.after.html deleted file mode 100644 index 54ef00f56f3b8..0000000000000 --- a/tests/mir-opt/spanview_block.main.built.after.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - -spanview_block.main.built.after - - - -
fn main() 0⦊{}⦉0
- - diff --git a/tests/mir-opt/spanview_block.rs b/tests/mir-opt/spanview_block.rs deleted file mode 100644 index e8bc3d16348a2..0000000000000 --- a/tests/mir-opt/spanview_block.rs +++ /dev/null @@ -1,6 +0,0 @@ -// skip-filecheck -// Test spanview block output -// compile-flags: -Z dump-mir-spanview=block - -// EMIT_MIR spanview_block.main.built.after.html -fn main() {} diff --git a/tests/mir-opt/spanview_statement.main.built.after.html b/tests/mir-opt/spanview_statement.main.built.after.html deleted file mode 100644 index 5e782b05f3b79..0000000000000 --- a/tests/mir-opt/spanview_statement.main.built.after.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - -spanview_statement.main.built.after - - - -
fn main() 0[0]⦊{}⦉0[0]0:Return⦊‸⦉0:Return
- - diff --git a/tests/mir-opt/spanview_statement.rs b/tests/mir-opt/spanview_statement.rs deleted file mode 100644 index d547e6cb1e0b0..0000000000000 --- a/tests/mir-opt/spanview_statement.rs +++ /dev/null @@ -1,6 +0,0 @@ -// skip-filecheck -// Test spanview output (the default value for `-Z dump-mir-spanview` is "statement") -// compile-flags: -Z dump-mir-spanview - -// EMIT_MIR spanview_statement.main.built.after.html -fn main() {} diff --git a/tests/mir-opt/spanview_terminator.main.built.after.html b/tests/mir-opt/spanview_terminator.main.built.after.html deleted file mode 100644 index 2a651489e235f..0000000000000 --- a/tests/mir-opt/spanview_terminator.main.built.after.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - -spanview_terminator.main.built.after - - - -
fn main() {}0:Return⦊‸⦉0:Return
- - diff --git a/tests/mir-opt/spanview_terminator.rs b/tests/mir-opt/spanview_terminator.rs deleted file mode 100644 index a2c68b98ef55b..0000000000000 --- a/tests/mir-opt/spanview_terminator.rs +++ /dev/null @@ -1,6 +0,0 @@ -// skip-filecheck -// Test spanview terminator output -// compile-flags: -Z dump-mir-spanview=terminator - -// EMIT_MIR spanview_terminator.main.built.after.html -fn main() {} From 8388112970288c79ddb217949070cfb04c2798a5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 4 Jan 2024 11:44:37 +1100 Subject: [PATCH 17/34] Remove `is_lint` field from `Level::Error`. Because it's redundant w.r.t. `Diagnostic::is_lint`, which is present for every diagnostic level. `struct_lint_level_impl` was the only place that set the `Error` field to `true`, and it's also the only place that calls `Diagnostic::is_lint()` to set the `is_lint` field. --- compiler/rustc_builtin_macros/src/test.rs | 2 +- compiler/rustc_codegen_llvm/src/back/write.rs | 2 +- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- .../src/annotate_snippet_emitter_writer.rs | 4 +--- compiler/rustc_errors/src/diagnostic.rs | 8 +++---- compiler/rustc_errors/src/lib.rs | 24 ++++++++----------- .../rustc_expand/src/proc_macro_server.rs | 2 +- compiler/rustc_middle/src/lint.rs | 2 +- src/tools/miri/src/diagnostics.rs | 2 +- 9 files changed, 20 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 82fe043820ccd..568f8247b2807 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -395,7 +395,7 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>) // These were a warning before #92959 and need to continue being that to avoid breaking // stable user code (#94508). Some(ast::ItemKind::MacCall(_)) => Level::Warning(None), - _ => Level::Error { lint: false }, + _ => Level::Error, }; let mut err = DiagnosticBuilder::<()>::new(dcx, level, msg); err.span(attr_sp); diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index c607533a08ed0..45be85934b46b 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -416,7 +416,7 @@ fn report_inline_asm( cookie = 0; } let level = match level { - llvm::DiagnosticLevel::Error => Level::Error { lint: false }, + llvm::DiagnosticLevel::Error => Level::Error, llvm::DiagnosticLevel::Warning => Level::Warning(None), llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note, }; diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index a465c83326491..d2c6b6e0c7bf6 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1848,7 +1848,7 @@ impl SharedEmitterMain { } Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => { let err_level = match level { - Level::Error { lint: false } => Level::Error { lint: false }, + Level::Error => Level::Error, Level::Warning(_) => Level::Warning(None), Level::Note => Level::Note, _ => bug!("Invalid inline asm diagnostic level"), diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 48e48f59a9992..0390829b33b45 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -86,9 +86,7 @@ fn source_string(file: Lrc, line: &Line) -> String { /// Maps `Diagnostic::Level` to `snippet::AnnotationType` fn annotation_type_for_level(level: Level) -> AnnotationType { match level { - Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error { .. } => { - AnnotationType::Error - } + Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error => AnnotationType::Error, Level::Warning(_) => AnnotationType::Warning, Level::Note | Level::OnceNote => AnnotationType::Note, Level::Help | Level::OnceHelp => AnnotationType::Help, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 863bfee4f183f..701c1c02ab0ef 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -244,11 +244,9 @@ impl Diagnostic { pub fn is_error(&self) -> bool { match self.level { - Level::Bug - | Level::DelayedBug - | Level::Fatal - | Level::Error { .. } - | Level::FailureNote => true, + Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error | Level::FailureNote => { + true + } Level::Warning(_) | Level::Note diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a4b31748e85bd..1cedc6081ef31 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -673,7 +673,7 @@ impl DiagCtxt { let key = (span.with_parent(None), key); if diag.is_error() { - if matches!(diag.level, Error { lint: true }) { + if diag.level == Error && diag.is_lint { inner.lint_err_count += 1; } else { inner.err_count += 1; @@ -697,7 +697,7 @@ impl DiagCtxt { let key = (span.with_parent(None), key); let diag = inner.stashed_diagnostics.remove(&key)?; if diag.is_error() { - if matches!(diag.level, Error { lint: true }) { + if diag.level == Error && diag.is_lint { inner.lint_err_count -= 1; } else { inner.err_count -= 1; @@ -812,7 +812,7 @@ impl DiagCtxt { #[rustc_lint_diagnostics] #[track_caller] pub fn struct_err(&self, msg: impl Into) -> DiagnosticBuilder<'_> { - DiagnosticBuilder::new(self, Error { lint: false }, msg) + DiagnosticBuilder::new(self, Error, msg) } /// Construct a builder at the `Error` level with the `msg` and the `code`. @@ -1212,7 +1212,7 @@ impl DiagCtxt { #[track_caller] pub fn create_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> DiagnosticBuilder<'a> { - err.into_diagnostic(self, Error { lint: false }) + err.into_diagnostic(self, Error) } #[track_caller] @@ -1367,7 +1367,7 @@ impl DiagCtxtInner { for diag in diags { // Decrement the count tracking the stash; emitting will increment it. if diag.is_error() { - if matches!(diag.level, Error { lint: true }) { + if diag.level == Error && diag.is_lint { self.lint_err_count -= 1; } else { self.err_count -= 1; @@ -1398,7 +1398,7 @@ impl DiagCtxtInner { &mut self, diagnostic: &mut Diagnostic, ) -> Option { - if matches!(diagnostic.level, Error { .. } | Fatal) && self.treat_err_as_bug() { + if matches!(diagnostic.level, Error | Fatal) && self.treat_err_as_bug() { diagnostic.level = Bug; } @@ -1499,7 +1499,7 @@ impl DiagCtxtInner { } } if diagnostic.is_error() { - if matches!(diagnostic.level, Error { lint: true }) { + if diagnostic.level == Error && diagnostic.is_lint { self.bump_lint_err_count(); } else { self.bump_err_count(); @@ -1695,11 +1695,7 @@ pub enum Level { /// most common case. /// /// Its `EmissionGuarantee` is `ErrorGuaranteed`. - Error { - /// If this error comes from a lint, don't abort compilation even when abort_if_errors() is - /// called. - lint: bool, - }, + Error, /// A warning about the code being compiled. Does not prevent compilation from finishing. /// @@ -1758,7 +1754,7 @@ impl Level { fn color(self) -> ColorSpec { let mut spec = ColorSpec::new(); match self { - Bug | DelayedBug | Fatal | Error { .. } => { + Bug | DelayedBug | Fatal | Error => { spec.set_fg(Some(Color::Red)).set_intense(true); } Warning(_) => { @@ -1779,7 +1775,7 @@ impl Level { pub fn to_str(self) -> &'static str { match self { Bug | DelayedBug => "error: internal compiler error", - Fatal | Error { .. } => "error", + Fatal | Error => "error", Warning(_) => "warning", Note | OnceNote => "note", Help | OnceHelp => "help", diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 2c08891b1096a..66695e020f1d1 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -379,7 +379,7 @@ impl ToInternal> impl ToInternal for Level { fn to_internal(self) -> rustc_errors::Level { match self { - Level::Error => rustc_errors::Level::Error { lint: false }, + Level::Error => rustc_errors::Level::Error, Level::Warning => rustc_errors::Level::Warning(None), Level::Note => rustc_errors::Level::Note, Level::Help => rustc_errors::Level::Help, diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index ea1439c959d50..d45ec8e464690 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -314,7 +314,7 @@ pub fn struct_lint_level( } Level::ForceWarn(Some(expect_id)) => rustc_errors::Level::Warning(Some(expect_id)), Level::Warn | Level::ForceWarn(None) => rustc_errors::Level::Warning(None), - Level::Deny | Level::Forbid => rustc_errors::Level::Error { lint: true }, + Level::Deny | Level::Forbid => rustc_errors::Level::Error, }; let mut err = DiagnosticBuilder::new(sess.dcx(), err_level, ""); if let Some(span) = span { diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index d9b4eb2f0ad1b..d3d4490f30202 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -454,7 +454,7 @@ pub fn report_msg<'tcx>( let span = stacktrace.first().map_or(DUMMY_SP, |fi| fi.span); let sess = machine.tcx.sess; let level = match diag_level { - DiagLevel::Error => Level::Error { lint: false }, + DiagLevel::Error => Level::Error, DiagLevel::Warning => Level::Warning(None), DiagLevel::Note => Level::Note, }; From cf9484e61551f3d4fad60dce49c89b83732e1622 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 4 Jan 2024 17:16:07 +1100 Subject: [PATCH 18/34] Remove `-Zreport-delayed-bugs`. It's not used within the repository in any way (e.g. in tests), and doesn't seem useful. --- compiler/rustc_errors/src/lib.rs | 16 +++------------- compiler/rustc_interface/src/tests.rs | 1 - compiler/rustc_session/src/config.rs | 1 - compiler/rustc_session/src/options.rs | 2 -- 4 files changed, 3 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index e9507dcfed7e4..0cf837dec0407 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -525,9 +525,6 @@ pub struct DiagCtxtFlags { /// If true, immediately emit diagnostics that would otherwise be buffered. /// (rustc: see `-Z dont-buffer-diagnostics` and `-Z treat-err-as-bug`) pub dont_buffer_diagnostics: bool, - /// If true, immediately print bugs registered with `span_delayed_bug`. - /// (rustc: see `-Z report-delayed-bugs`) - pub report_delayed_bugs: bool, /// Show macro backtraces. /// (rustc: see `-Z macro-backtrace`) pub macro_backtrace: bool, @@ -1004,7 +1001,6 @@ impl DiagCtxt { ) -> ErrorGuaranteed { let treat_next_err_as_bug = self.inner.borrow().treat_next_err_as_bug(); if treat_next_err_as_bug { - // FIXME: don't abort here if report_delayed_bugs is off self.span_bug(sp, msg); } let mut diagnostic = Diagnostic::new(DelayedBug, msg); @@ -1016,11 +1012,7 @@ impl DiagCtxt { // where the explanation of what "good path" is (also, it should be renamed). pub fn good_path_delayed_bug(&self, msg: impl Into) { let mut inner = self.inner.borrow_mut(); - - let mut diagnostic = Diagnostic::new(DelayedBug, msg); - if inner.flags.report_delayed_bugs { - inner.emit_diagnostic_without_consuming(&mut diagnostic); - } + let diagnostic = Diagnostic::new(DelayedBug, msg); let backtrace = std::backtrace::Backtrace::capture(); inner.good_path_delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); } @@ -1430,10 +1422,8 @@ impl DiagCtxtInner { self.span_delayed_bugs .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace)); - if !self.flags.report_delayed_bugs { - #[allow(deprecated)] - return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); - } + #[allow(deprecated)] + return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); } if diagnostic.has_future_breakage() { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index c4a1f3a0e510b..1999e4fb7bcb3 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -806,7 +806,6 @@ fn test_unstable_options_tracking_hash() { tracked!(relax_elf_relocations, Some(true)); tracked!(relro_level, Some(RelroLevel::Full)); tracked!(remap_cwd_prefix, Some(PathBuf::from("abc"))); - tracked!(report_delayed_bugs, true); tracked!(sanitizer, SanitizerSet::ADDRESS); tracked!(sanitizer_cfi_canonical_jump_tables, None); tracked!(sanitizer_cfi_generalize_pointers, Some(true)); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 89508c77639aa..be5dcbc0c03dc 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1162,7 +1162,6 @@ impl UnstableOptions { can_emit_warnings, treat_err_as_bug: self.treat_err_as_bug, dont_buffer_diagnostics: self.dont_buffer_diagnostics, - report_delayed_bugs: self.report_delayed_bugs, macro_backtrace: self.macro_backtrace, deduplicate_diagnostics: self.deduplicate_diagnostics, track_diagnostics: self.track_diagnostics, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 8274fd05bc057..4d9a2a3aed2de 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1841,8 +1841,6 @@ options! { remark_dir: Option = (None, parse_opt_pathbuf, [UNTRACKED], "directory into which to write optimization remarks (if not specified, they will be \ written to standard error output)"), - report_delayed_bugs: bool = (false, parse_bool, [TRACKED], - "immediately print bugs registered with `span_delayed_bug` (default: no)"), sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED], "use a sanitizer"), sanitizer_cfi_canonical_jump_tables: Option = (Some(true), parse_opt_bool, [TRACKED], From 59c76fb21b3315e4a7bc0bca305416a1cf32833c Mon Sep 17 00:00:00 2001 From: AngelicosPhosphoros Date: Thu, 4 Jan 2024 19:14:31 +0100 Subject: [PATCH 19/34] Make `intrinsics::assume` const stable Closes https://github.com/rust-lang/rust/issues/76972 Blocks https://github.com/rust-lang/rust/pull/119452 Approved in https://github.com/rust-lang/rust/pull/119452#issuecomment-1875741678 --- library/core/src/intrinsics.rs | 2 +- library/core/src/lib.rs | 1 - library/core/tests/lib.rs | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 5107ba1a9e1be..78108b7d1d46c 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -947,7 +947,7 @@ extern "rust-intrinsic" { /// own, or if it does not enable any significant optimizations. /// /// This intrinsic does not have a stable counterpart. - #[rustc_const_unstable(feature = "const_assume", issue = "76972")] + #[rustc_const_stable(feature = "const_assume", since = "CURRENT_RUSTC_VERSION")] #[rustc_nounwind] pub fn assume(b: bool); diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 07720f235989b..9316ec93f240d 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -119,7 +119,6 @@ #![feature(const_arguments_as_str)] #![feature(const_array_from_ref)] #![feature(const_array_into_iter_constructors)] -#![feature(const_assume)] #![feature(const_bigint_helper_methods)] #![feature(const_black_box)] #![feature(const_caller_location)] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index c531117bed5ad..64c16eff4986d 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -7,7 +7,6 @@ #![feature(bigint_helper_methods)] #![feature(cell_update)] #![feature(const_align_offset)] -#![feature(const_assume)] #![feature(const_align_of_val_raw)] #![feature(const_black_box)] #![feature(const_caller_location)] From 35ad2ae71cee3685f4ef54a4bb0d535ae5e4fa05 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 4 Jan 2024 20:19:39 +0100 Subject: [PATCH 20/34] Fix invalid handling for static method calls in jump to definition feature --- src/librustdoc/html/render/span_map.rs | 52 ++++++++++++++++---------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index d1ece73374dc3..b055e355b788a 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -154,6 +154,28 @@ impl<'tcx> SpanMapVisitor<'tcx> { self.matches.insert(new_span, link_from_src); true } + + fn handle_call(&mut self, hir_id: HirId, expr_hir_id: Option, span: Span) { + let hir = self.tcx.hir(); + let body_id = hir.enclosing_body_owner(hir_id); + // FIXME: this is showing error messages for parts of the code that are not + // compiled (because of cfg)! + // + // See discussion in https://github.com/rust-lang/rust/issues/69426#issuecomment-1019412352 + let typeck_results = self + .tcx + .typeck_body(hir.maybe_body_owned_by(body_id).expect("a body which isn't a body")); + // Interestingly enough, for method calls, we need the whole expression whereas for static + // method/function calls, we need the call expression specifically. + if let Some(def_id) = typeck_results.type_dependent_def_id(expr_hir_id.unwrap_or(hir_id)) { + let link = if def_id.as_local().is_some() { + LinkFromSrc::Local(rustc_span(def_id, self.tcx)) + } else { + LinkFromSrc::External(def_id) + }; + self.matches.insert(span, link); + } + } } impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { @@ -191,27 +213,17 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { } fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'tcx>) { - if let ExprKind::MethodCall(segment, ..) = expr.kind { - let hir = self.tcx.hir(); - let body_id = hir.enclosing_body_owner(segment.hir_id); - // FIXME: this is showing error messages for parts of the code that are not - // compiled (because of cfg)! - // - // See discussion in https://github.com/rust-lang/rust/issues/69426#issuecomment-1019412352 - let typeck_results = self - .tcx - .typeck_body(hir.maybe_body_owned_by(body_id).expect("a body which isn't a body")); - if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) { - let link = if def_id.as_local().is_some() { - LinkFromSrc::Local(rustc_span(def_id, self.tcx)) - } else { - LinkFromSrc::External(def_id) - }; - self.matches.insert(segment.ident.span, link); + match expr.kind { + ExprKind::MethodCall(segment, ..) => { + self.handle_call(segment.hir_id, Some(expr.hir_id), segment.ident.span) + } + ExprKind::Call(call, ..) => self.handle_call(call.hir_id, None, call.span), + _ => { + if self.handle_macro(expr.span) { + // We don't want to go deeper into the macro. + return; + } } - } else if self.handle_macro(expr.span) { - // We don't want to go deeper into the macro. - return; } intravisit::walk_expr(self, expr); } From 5bc76873517d152fc5753c28059b247daabbf341 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 4 Jan 2024 20:20:07 +0100 Subject: [PATCH 21/34] Add regression test for jump to def static method calls --- .../rustdoc/check-source-code-urls-to-def.rs | 2 +- tests/rustdoc/jump-to-def-doc-links-calls.rs | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc/jump-to-def-doc-links-calls.rs diff --git a/tests/rustdoc/check-source-code-urls-to-def.rs b/tests/rustdoc/check-source-code-urls-to-def.rs index b803c7e9e86c7..c31c579030e0d 100644 --- a/tests/rustdoc/check-source-code-urls-to-def.rs +++ b/tests/rustdoc/check-source-code-urls-to-def.rs @@ -62,7 +62,7 @@ pub trait AnotherTrait2 {} // @has - '//pre[@class="rust"]//a[@href="#61"]' 'AnotherTrait2' pub fn foo4() { - let x: Vec = Vec::new(); + let x: Vec<&dyn AnotherTrait2> = Vec::new(); } // @has - '//pre[@class="rust"]//a[@href="../../foo/primitive.bool.html"]' 'bool' diff --git a/tests/rustdoc/jump-to-def-doc-links-calls.rs b/tests/rustdoc/jump-to-def-doc-links-calls.rs new file mode 100644 index 0000000000000..549d068528e25 --- /dev/null +++ b/tests/rustdoc/jump-to-def-doc-links-calls.rs @@ -0,0 +1,27 @@ +// compile-flags: -Zunstable-options --generate-link-to-definition + +#![crate_name = "foo"] + +// @has 'src/foo/jump-to-def-doc-links-calls.rs.html' + +// @has - '//a[@href="../../foo/struct.Bar.html"]' 'Bar' +pub struct Bar; + +impl std::default::Default for Bar { + // @has - '//a[@href="#20-22"]' 'Self::new' + fn default() -> Self { + Self::new() + } +} + +// @has - '//a[@href="#8"]' 'Bar' +impl Bar { + // @has - '//a[@href="#24-26"]' 'Self::bar' + pub fn new()-> Self { + Self::bar() + } + + pub fn bar() -> Self { + Self + } +} From 073ed0e26274a4f665f7406071bf55b5047c21ae Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Thu, 4 Jan 2024 20:31:59 +0100 Subject: [PATCH 22/34] Move `i586-unknown-netbsd` from tier 2 to tier 3 platform support table It appears it was intended to be tier 3, but was accidentally added to tier 2. --- src/doc/rustc/src/platform-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 09070168b67b9..c7e0f2dbc6f40 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -151,7 +151,6 @@ target | std | notes `i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE [^x86_32-floats-x87] `i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17) [^x86_32-floats-x87] `i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL [^x86_32-floats-x87] -[`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ | 32-bit x86, restricted to Pentium [`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android [^x86_32-floats-return-ABI] `i686-unknown-freebsd` | ✓ | 32-bit FreeBSD [^x86_32-floats-return-ABI] `i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL [^x86_32-floats-return-ABI] @@ -270,6 +269,7 @@ target | std | host | notes `hexagon-unknown-linux-musl` | ? | | `i386-apple-ios` | ✓ | | 32-bit x86 iOS [^x86_32-floats-return-ABI] [`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS [^x86_32-floats-return-ABI] +[`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ | | 32-bit x86, restricted to Pentium `i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+) [^x86_32-floats-return-ABI] `i686-pc-windows-msvc` | * | | 32-bit Windows XP support [^x86_32-floats-return-ABI] [`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | [^x86_32-floats-return-ABI] From 12b92c8a87c041416dfec8cdd61c7f14c1cd9d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 30 Dec 2023 00:00:00 +0000 Subject: [PATCH 23/34] Visit only reachable blocks in MIR lint No functional changes - all checks have been emitted conditionally on block being rechable already. --- compiler/rustc_mir_transform/src/lint.rs | 27 +++++++++++------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs index 3940d0ddbf344..e5d607e39b239 100644 --- a/compiler/rustc_mir_transform/src/lint.rs +++ b/compiler/rustc_mir_transform/src/lint.rs @@ -11,7 +11,6 @@ use rustc_mir_dataflow::{Analysis, ResultsCursor}; use std::borrow::Cow; pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) { - let reachable_blocks = traversal::reachable_as_bitset(body); let always_live_locals = &always_storage_live_locals(body); let maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals)) @@ -24,17 +23,18 @@ pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) { .iterate_to_fixpoint() .into_results_cursor(body); - Lint { + let mut lint = Lint { tcx, when, body, is_fn_like: tcx.def_kind(body.source.def_id()).is_fn_like(), always_live_locals, - reachable_blocks, maybe_storage_live, maybe_storage_dead, + }; + for (bb, data) in traversal::reachable(body) { + lint.visit_basic_block_data(bb, data); } - .visit_body(body); } struct Lint<'a, 'tcx> { @@ -43,7 +43,6 @@ struct Lint<'a, 'tcx> { body: &'a Body<'tcx>, is_fn_like: bool, always_live_locals: &'a BitSet, - reachable_blocks: BitSet, maybe_storage_live: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>, maybe_storage_dead: ResultsCursor<'a, 'tcx, MaybeStorageDead<'a>>, } @@ -67,7 +66,7 @@ impl<'a, 'tcx> Lint<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) { - if self.reachable_blocks.contains(location.block) && context.is_use() { + if context.is_use() { self.maybe_storage_dead.seek_after_primary_effect(location); if self.maybe_storage_dead.get().contains(local) { self.fail(location, format!("use of local {local:?}, which has no storage here")); @@ -78,14 +77,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match statement.kind { StatementKind::StorageLive(local) => { - if self.reachable_blocks.contains(location.block) { - self.maybe_storage_live.seek_before_primary_effect(location); - if self.maybe_storage_live.get().contains(local) { - self.fail( - location, - format!("StorageLive({local:?}) which already has storage here"), - ); - } + self.maybe_storage_live.seek_before_primary_effect(location); + if self.maybe_storage_live.get().contains(local) { + self.fail( + location, + format!("StorageLive({local:?}) which already has storage here"), + ); } } _ => {} @@ -97,7 +94,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { match terminator.kind { TerminatorKind::Return => { - if self.is_fn_like && self.reachable_blocks.contains(location.block) { + if self.is_fn_like { self.maybe_storage_live.seek_after_primary_effect(location); for local in self.maybe_storage_live.get().iter() { if !self.always_live_locals.contains(local) { From a084e063e690697a6ad46545a107228247024393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 1 Jan 2024 00:00:00 +0000 Subject: [PATCH 24/34] Fix validation and linting of injected MIR Reevaluate `body.should_skip()` after updating the MIR phase to ensure that injected MIR is processed correctly. Update a few custom MIR tests that were ill-formed for the injected phase. --- compiler/rustc_mir_transform/src/pass_manager.rs | 12 +++++++++--- .../custom_move_arg.f.CopyProp.panic-unwind.diff | 8 ++++---- tests/mir-opt/copy-prop/custom_move_arg.rs | 6 +++--- .../move_projection.f.CopyProp.panic-unwind.diff | 6 +++--- tests/mir-opt/copy-prop/move_projection.rs | 6 +++--- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 82074f1960d25..f4c572aec128a 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -109,14 +109,15 @@ fn run_passes_inner<'tcx>( phase_change: Option, validate_each: bool, ) { - let lint = tcx.sess.opts.unstable_opts.lint_mir & !body.should_skip(); - let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir & !body.should_skip(); let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; trace!(?overridden_passes); let prof_arg = tcx.sess.prof.enabled().then(|| format!("{:?}", body.source.def_id())); if !body.should_skip() { + let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir; + let lint = tcx.sess.opts.unstable_opts.lint_mir; + for pass in passes { let name = pass.name(); @@ -162,7 +163,12 @@ fn run_passes_inner<'tcx>( body.pass_count = 0; dump_mir_for_phase_change(tcx, body); - if validate || new_phase == MirPhase::Runtime(RuntimePhase::Optimized) { + + let validate = + (validate_each & tcx.sess.opts.unstable_opts.validate_mir & !body.should_skip()) + || new_phase == MirPhase::Runtime(RuntimePhase::Optimized); + let lint = tcx.sess.opts.unstable_opts.lint_mir & !body.should_skip(); + if validate { validate_body(tcx, body, format!("after phase change to {}", new_phase.name())); } if lint { diff --git a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff index eb40183c1c954..7ba8530105179 100644 --- a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff @@ -8,14 +8,14 @@ bb0: { - _2 = _1; -- _0 = opaque::(move _1) -> [return: bb1, unwind continue]; -+ _0 = opaque::(_1) -> [return: bb1, unwind continue]; +- _0 = opaque::(move _1) -> [return: bb1, unwind unreachable]; ++ _0 = opaque::(_1) -> [return: bb1, unwind unreachable]; } bb1: { - _3 = move _2; -- _0 = opaque::(_3) -> [return: bb2, unwind continue]; -+ _0 = opaque::(_1) -> [return: bb2, unwind continue]; +- _0 = opaque::(_3) -> [return: bb2, unwind unreachable]; ++ _0 = opaque::(_1) -> [return: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/copy-prop/custom_move_arg.rs b/tests/mir-opt/copy-prop/custom_move_arg.rs index 45913626a8fe5..1ee294fcfd917 100644 --- a/tests/mir-opt/copy-prop/custom_move_arg.rs +++ b/tests/mir-opt/copy-prop/custom_move_arg.rs @@ -10,15 +10,15 @@ use core::intrinsics::mir::*; struct NotCopy(bool); // EMIT_MIR custom_move_arg.f.CopyProp.diff -#[custom_mir(dialect = "analysis", phase = "post-cleanup")] +#[custom_mir(dialect = "runtime")] fn f(_1: NotCopy) { mir!({ let _2 = _1; - Call(RET = opaque(Move(_1)), ReturnTo(bb1), UnwindContinue()) + Call(RET = opaque(Move(_1)), ReturnTo(bb1), UnwindUnreachable()) } bb1 = { let _3 = Move(_2); - Call(RET = opaque(_3), ReturnTo(bb2), UnwindContinue()) + Call(RET = opaque(_3), ReturnTo(bb2), UnwindUnreachable()) } bb2 = { Return() diff --git a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff index ad3889639e0cf..b2b89968d70b0 100644 --- a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff @@ -9,13 +9,13 @@ bb0: { - _2 = _1; - _3 = move (_2.0: u8); -- _0 = opaque::(move _1) -> [return: bb1, unwind continue]; +- _0 = opaque::(move _1) -> [return: bb1, unwind unreachable]; + _3 = (_1.0: u8); -+ _0 = opaque::(_1) -> [return: bb1, unwind continue]; ++ _0 = opaque::(_1) -> [return: bb1, unwind unreachable]; } bb1: { - _0 = opaque::(move _3) -> [return: bb2, unwind continue]; + _0 = opaque::(move _3) -> [return: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/copy-prop/move_projection.rs b/tests/mir-opt/copy-prop/move_projection.rs index f02867814ac0a..f31e82c1f0302 100644 --- a/tests/mir-opt/copy-prop/move_projection.rs +++ b/tests/mir-opt/copy-prop/move_projection.rs @@ -11,17 +11,17 @@ fn opaque(_: impl Sized) -> bool { true } struct Foo(u8); -#[custom_mir(dialect = "analysis", phase = "post-cleanup")] +#[custom_mir(dialect = "runtime")] fn f(a: Foo) -> bool { mir!( { let b = a; // This is a move out of a copy, so must become a copy of `a.0`. let c = Move(b.0); - Call(RET = opaque(Move(a)), ReturnTo(bb1), UnwindContinue()) + Call(RET = opaque(Move(a)), ReturnTo(bb1), UnwindUnreachable()) } bb1 = { - Call(RET = opaque(Move(c)), ReturnTo(ret), UnwindContinue()) + Call(RET = opaque(Move(c)), ReturnTo(ret), UnwindUnreachable()) } ret = { Return() From df116ec246a795c0940993454643c62e0d849b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 4 Jan 2024 14:24:41 +0100 Subject: [PATCH 25/34] Migrate memory overlap check from validator to lint The check attempts to identify potential undefined behaviour, rather than whether MIR is well-formed. It belongs in the lint not validator. --- .../src/transform/validate.rs | 46 +---------- compiler/rustc_mir_transform/src/dest_prop.rs | 7 -- compiler/rustc_mir_transform/src/lint.rs | 43 +++++++++- ....f.DestinationPropagation.panic-abort.diff | 82 ------------------- ...f.DestinationPropagation.panic-unwind.diff | 82 ------------------- tests/mir-opt/dest-prop/unreachable.rs | 20 ----- tests/ui/mir/lint/assignment-overlap.rs | 19 +++++ tests/ui/mir/lint/call-overlap.rs | 23 ++++++ 8 files changed, 85 insertions(+), 237 deletions(-) delete mode 100644 tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-abort.diff delete mode 100644 tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff delete mode 100644 tests/mir-opt/dest-prop/unreachable.rs create mode 100644 tests/ui/mir/lint/assignment-overlap.rs create mode 100644 tests/ui/mir/lint/call-overlap.rs diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index b249ffb84b3a8..0b73691204d53 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -74,7 +74,6 @@ impl<'tcx> MirPass<'tcx> for Validator { mir_phase, unwind_edge_count: 0, reachable_blocks: traversal::reachable_as_bitset(body), - place_cache: FxHashSet::default(), value_cache: FxHashSet::default(), can_unwind, }; @@ -106,7 +105,6 @@ struct CfgChecker<'a, 'tcx> { mir_phase: MirPhase, unwind_edge_count: usize, reachable_blocks: BitSet, - place_cache: FxHashSet>, value_cache: FxHashSet, // If `false`, then the MIR must not contain `UnwindAction::Continue` or // `TerminatorKind::Resume`. @@ -294,19 +292,6 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match &statement.kind { - StatementKind::Assign(box (dest, rvalue)) => { - // FIXME(JakobDegen): Check this for all rvalues, not just this one. - if let Rvalue::Use(Operand::Copy(src) | Operand::Move(src)) = rvalue { - // The sides of an assignment must not alias. Currently this just checks whether - // the places are identical. - if dest == src { - self.fail( - location, - "encountered `Assign` statement with overlapping memory", - ); - } - } - } StatementKind::AscribeUserType(..) => { if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( @@ -341,7 +326,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { self.fail(location, format!("explicit `{kind:?}` is forbidden")); } } - StatementKind::StorageLive(_) + StatementKind::Assign(..) + | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Intrinsic(_) | StatementKind::Coverage(_) @@ -404,10 +390,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } // The call destination place and Operand::Move place used as an argument might be - // passed by a reference to the callee. Consequently they must be non-overlapping - // and cannot be packed. Currently this simply checks for duplicate places. - self.place_cache.clear(); - self.place_cache.insert(destination.as_ref()); + // passed by a reference to the callee. Consequently they cannot be packed. if is_within_packed(self.tcx, &self.body.local_decls, *destination).is_some() { // This is bad! The callee will expect the memory to be aligned. self.fail( @@ -418,10 +401,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { ), ); } - let mut has_duplicates = false; for arg in args { if let Operand::Move(place) = arg { - has_duplicates |= !self.place_cache.insert(place.as_ref()); if is_within_packed(self.tcx, &self.body.local_decls, *place).is_some() { // This is bad! The callee will expect the memory to be aligned. self.fail( @@ -434,16 +415,6 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } } } - - if has_duplicates { - self.fail( - location, - format!( - "encountered overlapping memory in `Move` arguments to `Call` terminator: {:?}", - terminator.kind, - ), - ); - } } TerminatorKind::Assert { target, unwind, .. } => { self.check_edge(location, *target, EdgeKind::Normal); @@ -1112,17 +1083,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ) } } - // FIXME(JakobDegen): Check this for all rvalues, not just this one. - if let Rvalue::Use(Operand::Copy(src) | Operand::Move(src)) = rvalue { - // The sides of an assignment must not alias. Currently this just checks whether - // the places are identical. - if dest == src { - self.fail( - location, - "encountered `Assign` statement with overlapping memory", - ); - } - } } StatementKind::AscribeUserType(..) => { if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 15502adfb5aad..cd80f423466bc 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -133,7 +133,6 @@ use std::collections::hash_map::{Entry, OccupiedEntry}; -use crate::simplify::remove_dead_blocks; use crate::MirPass; use rustc_data_structures::fx::FxHashMap; use rustc_index::bit_set::BitSet; @@ -241,12 +240,6 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { apply_merges(body, tcx, &merges, &merged_locals); } - if round_count != 0 { - // Merging can introduce overlap between moved arguments and/or call destination in an - // unreachable code, which validator considers to be ill-formed. - remove_dead_blocks(body); - } - trace!(round_count); } } diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs index e5d607e39b239..c0c0a3f5ee649 100644 --- a/compiler/rustc_mir_transform/src/lint.rs +++ b/compiler/rustc_mir_transform/src/lint.rs @@ -1,6 +1,7 @@ //! This pass statically detects code which has undefined behaviour or is likely to be erroneous. //! It can be used to locate problems in MIR building or optimizations. It assumes that all code //! can be executed, so it has false positives. +use rustc_data_structures::fx::FxHashSet; use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::*; @@ -31,6 +32,7 @@ pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) { always_live_locals, maybe_storage_live, maybe_storage_dead, + places: Default::default(), }; for (bb, data) in traversal::reachable(body) { lint.visit_basic_block_data(bb, data); @@ -45,6 +47,7 @@ struct Lint<'a, 'tcx> { always_live_locals: &'a BitSet, maybe_storage_live: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>, maybe_storage_dead: ResultsCursor<'a, 'tcx, MaybeStorageDead<'a>>, + places: FxHashSet>, } impl<'a, 'tcx> Lint<'a, 'tcx> { @@ -75,10 +78,22 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { } fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { - match statement.kind { + match &statement.kind { + StatementKind::Assign(box (dest, rvalue)) => { + if let Rvalue::Use(Operand::Copy(src) | Operand::Move(src)) = rvalue { + // The sides of an assignment must not alias. Currently this just checks whether + // the places are identical. + if dest == src { + self.fail( + location, + "encountered `Assign` statement with overlapping memory", + ); + } + } + } StatementKind::StorageLive(local) => { self.maybe_storage_live.seek_before_primary_effect(location); - if self.maybe_storage_live.get().contains(local) { + if self.maybe_storage_live.get().contains(*local) { self.fail( location, format!("StorageLive({local:?}) which already has storage here"), @@ -92,7 +107,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { } fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { - match terminator.kind { + match &terminator.kind { TerminatorKind::Return => { if self.is_fn_like { self.maybe_storage_live.seek_after_primary_effect(location); @@ -108,6 +123,28 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { } } } + TerminatorKind::Call { args, destination, .. } => { + // The call destination place and Operand::Move place used as an argument might be + // passed by a reference to the callee. Consequently they must be non-overlapping. + // Currently this simply checks for duplicate places. + self.places.clear(); + self.places.insert(destination.as_ref()); + let mut has_duplicates = false; + for arg in args { + if let Operand::Move(place) = arg { + has_duplicates |= !self.places.insert(place.as_ref()); + } + } + if has_duplicates { + self.fail( + location, + format!( + "encountered overlapping memory in `Move` arguments to `Call` terminator: {:?}", + terminator.kind, + ), + ); + } + } _ => {} } diff --git a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-abort.diff deleted file mode 100644 index 80b5681ad062c..0000000000000 --- a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-abort.diff +++ /dev/null @@ -1,82 +0,0 @@ -- // MIR for `f` before DestinationPropagation -+ // MIR for `f` after DestinationPropagation - - fn f(_1: T) -> () { - debug a => _1; - let mut _0: (); - let _2: T; - let mut _3: bool; - let _4: (); - let mut _5: T; - let mut _6: T; - let _7: (); - let mut _8: T; - let mut _9: T; - scope 1 { -- debug b => _2; -+ debug b => _1; - } - - bb0: { -- StorageLive(_2); -- _2 = _1; -+ nop; -+ nop; - StorageLive(_3); - _3 = const false; -- goto -> bb3; -+ goto -> bb1; - } - - bb1: { -- StorageLive(_4); -- StorageLive(_5); -- _5 = _1; -- StorageLive(_6); -- _6 = _1; -- _4 = g::(_1, _1) -> [return: bb2, unwind unreachable]; -- } -- -- bb2: { -- StorageDead(_6); -- StorageDead(_5); -- StorageDead(_4); -- _0 = const (); -- goto -> bb5; -- } -- -- bb3: { - StorageLive(_7); -- StorageLive(_8); -- _8 = _1; -- StorageLive(_9); -- _9 = _1; -- _7 = g::(_1, _1) -> [return: bb4, unwind unreachable]; -+ nop; -+ nop; -+ nop; -+ nop; -+ _7 = g::(_1, _1) -> [return: bb2, unwind unreachable]; - } - -- bb4: { -- StorageDead(_9); -- StorageDead(_8); -+ bb2: { -+ nop; -+ nop; - StorageDead(_7); - _0 = const (); -- goto -> bb5; -+ goto -> bb3; - } - -- bb5: { -+ bb3: { - StorageDead(_3); -- StorageDead(_2); -+ nop; - return; - } - } - diff --git a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff deleted file mode 100644 index eae7dd17b4882..0000000000000 --- a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff +++ /dev/null @@ -1,82 +0,0 @@ -- // MIR for `f` before DestinationPropagation -+ // MIR for `f` after DestinationPropagation - - fn f(_1: T) -> () { - debug a => _1; - let mut _0: (); - let _2: T; - let mut _3: bool; - let _4: (); - let mut _5: T; - let mut _6: T; - let _7: (); - let mut _8: T; - let mut _9: T; - scope 1 { -- debug b => _2; -+ debug b => _1; - } - - bb0: { -- StorageLive(_2); -- _2 = _1; -+ nop; -+ nop; - StorageLive(_3); - _3 = const false; -- goto -> bb3; -+ goto -> bb1; - } - - bb1: { -- StorageLive(_4); -- StorageLive(_5); -- _5 = _1; -- StorageLive(_6); -- _6 = _1; -- _4 = g::(_1, _1) -> [return: bb2, unwind continue]; -- } -- -- bb2: { -- StorageDead(_6); -- StorageDead(_5); -- StorageDead(_4); -- _0 = const (); -- goto -> bb5; -- } -- -- bb3: { - StorageLive(_7); -- StorageLive(_8); -- _8 = _1; -- StorageLive(_9); -- _9 = _1; -- _7 = g::(_1, _1) -> [return: bb4, unwind continue]; -+ nop; -+ nop; -+ nop; -+ nop; -+ _7 = g::(_1, _1) -> [return: bb2, unwind continue]; - } - -- bb4: { -- StorageDead(_9); -- StorageDead(_8); -+ bb2: { -+ nop; -+ nop; - StorageDead(_7); - _0 = const (); -- goto -> bb5; -+ goto -> bb3; - } - -- bb5: { -+ bb3: { - StorageDead(_3); -- StorageDead(_2); -+ nop; - return; - } - } - diff --git a/tests/mir-opt/dest-prop/unreachable.rs b/tests/mir-opt/dest-prop/unreachable.rs deleted file mode 100644 index 0bde157ff6185..0000000000000 --- a/tests/mir-opt/dest-prop/unreachable.rs +++ /dev/null @@ -1,20 +0,0 @@ -// skip-filecheck -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// Check that unreachable code is removed after the destination propagation. -// Regression test for issue #105428. -// -// compile-flags: --crate-type=lib -Zmir-opt-level=0 -// compile-flags: -Zmir-enable-passes=+GVN,+SimplifyConstCondition-after-const-prop,+DestinationPropagation - -// EMIT_MIR unreachable.f.DestinationPropagation.diff -pub fn f(a: T) { - let b = a; - if false { - g(a, b); - } else { - g(b, b); - } -} - -#[inline(never)] -pub fn g(_: T, _: T) {} diff --git a/tests/ui/mir/lint/assignment-overlap.rs b/tests/ui/mir/lint/assignment-overlap.rs new file mode 100644 index 0000000000000..0e4a11467dc8a --- /dev/null +++ b/tests/ui/mir/lint/assignment-overlap.rs @@ -0,0 +1,19 @@ +// compile-flags: --crate-type=lib -Zlint-mir -Ztreat-err-as-bug +// build-fail +// failure-status: 101 +// dont-check-compiler-stderr +// error-pattern: encountered `Assign` statement with overlapping memory +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn main() { + mir!( + let a: [u8; 1024]; + { + a = a; + Return() + } + ) +} diff --git a/tests/ui/mir/lint/call-overlap.rs b/tests/ui/mir/lint/call-overlap.rs new file mode 100644 index 0000000000000..df38e901e7328 --- /dev/null +++ b/tests/ui/mir/lint/call-overlap.rs @@ -0,0 +1,23 @@ +// compile-flags: -Zlint-mir -Ztreat-err-as-bug +// build-fail +// failure-status: 101 +// dont-check-compiler-stderr +// error-pattern: encountered overlapping memory in `Move` arguments to `Call` +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn main() { + mir!( + let a: [u8; 1024]; + { + Call(a = f(Move(a)), ReturnTo(bb1), UnwindUnreachable()) + } + bb1 = { + Return() + } + ) +} + +pub fn f(a: T) -> T { a } From cb9abcae7936181331a2e5a7d0de8506c8f98690 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 5 Jan 2024 10:02:40 +1100 Subject: [PATCH 26/34] Rename `EmitterWriter` as `HumanEmitter`. For consistency with other `Emitter` impls, such as `JsonEmitter`, `SilentEmitter`, `SharedEmitter`, etc. --- compiler/rustc_driver_impl/src/lib.rs | 2 +- compiler/rustc_errors/src/emitter.rs | 20 +++++++++---------- compiler/rustc_errors/src/lib.rs | 4 ++-- compiler/rustc_expand/src/tests.rs | 4 ++-- compiler/rustc_session/src/session.rs | 6 +++--- src/librustdoc/core.rs | 4 ++-- src/librustdoc/doctest.rs | 10 +++++----- .../src/doc/needless_doctest_main.rs | 4 ++-- src/tools/rustfmt/src/parse/session.rs | 4 ++-- 9 files changed, 29 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index ca6b0afc76a9b..ebdea997861dc 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1393,7 +1393,7 @@ fn report_ice( ) { let fallback_bundle = rustc_errors::fallback_fluent_bundle(crate::DEFAULT_LOCALE_RESOURCES.to_vec(), false); - let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr( + let emitter = Box::new(rustc_errors::emitter::HumanEmitter::stderr( rustc_errors::ColorConfig::Auto, fallback_bundle, )); diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 546159c9d13dd..3f0fd559b6047 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -61,13 +61,13 @@ impl HumanReadableErrorType { self, mut dst: Box, fallback_bundle: LazyFallbackBundle, - ) -> EmitterWriter { + ) -> HumanEmitter { let (short, color_config) = self.unzip(); let color = color_config.suggests_using_colors(); if !dst.supports_color() && color { dst = Box::new(Ansi::new(dst)); } - EmitterWriter::new(dst, fallback_bundle).short_message(short) + HumanEmitter::new(dst, fallback_bundle).short_message(short) } } @@ -501,7 +501,7 @@ pub trait Emitter: Translate { } } -impl Translate for EmitterWriter { +impl Translate for HumanEmitter { fn fluent_bundle(&self) -> Option<&Lrc> { self.fluent_bundle.as_ref() } @@ -511,7 +511,7 @@ impl Translate for EmitterWriter { } } -impl Emitter for EmitterWriter { +impl Emitter for HumanEmitter { fn source_map(&self) -> Option<&Lrc> { self.sm.as_ref() } @@ -622,7 +622,7 @@ impl ColorConfig { /// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short` #[derive(Setters)] -pub struct EmitterWriter { +pub struct HumanEmitter { #[setters(skip)] dst: IntoDynSyncSend, sm: Option>, @@ -647,14 +647,14 @@ pub struct FileWithAnnotatedLines { multiline_depth: usize, } -impl EmitterWriter { - pub fn stderr(color_config: ColorConfig, fallback_bundle: LazyFallbackBundle) -> EmitterWriter { +impl HumanEmitter { + pub fn stderr(color_config: ColorConfig, fallback_bundle: LazyFallbackBundle) -> HumanEmitter { let dst = from_stderr(color_config); Self::create(dst, fallback_bundle) } - fn create(dst: Destination, fallback_bundle: LazyFallbackBundle) -> EmitterWriter { - EmitterWriter { + fn create(dst: Destination, fallback_bundle: LazyFallbackBundle) -> HumanEmitter { + HumanEmitter { dst: IntoDynSyncSend(dst), sm: None, fluent_bundle: None, @@ -673,7 +673,7 @@ impl EmitterWriter { pub fn new( dst: Box, fallback_bundle: LazyFallbackBundle, - ) -> EmitterWriter { + ) -> HumanEmitter { Self::create(dst, fallback_bundle) } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index e9507dcfed7e4..821b40a237570 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -53,7 +53,7 @@ pub use snippet::Style; pub use termcolor::{Color, ColorSpec, WriteColor}; use crate::diagnostic_impls::{DelayedAtWithNewline, DelayedAtWithoutNewline}; -use emitter::{is_case_difference, DynEmitter, Emitter, EmitterWriter}; +use emitter::{is_case_difference, DynEmitter, Emitter, HumanEmitter}; use registry::Registry; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; @@ -574,7 +574,7 @@ impl DiagCtxt { sm: Option>, fallback_bundle: LazyFallbackBundle, ) -> Self { - let emitter = Box::new(EmitterWriter::stderr(ColorConfig::Auto, fallback_bundle).sm(sm)); + let emitter = Box::new(HumanEmitter::stderr(ColorConfig::Auto, fallback_bundle).sm(sm)); Self::with_emitter(emitter) } pub fn disable_warnings(mut self) -> Self { diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs index 0b859841828ee..3c14ad5e7b824 100644 --- a/compiler/rustc_expand/src/tests.rs +++ b/compiler/rustc_expand/src/tests.rs @@ -7,7 +7,7 @@ use rustc_span::source_map::{FilePathMapping, SourceMap}; use rustc_span::{BytePos, Span}; use rustc_data_structures::sync::Lrc; -use rustc_errors::emitter::EmitterWriter; +use rustc_errors::emitter::HumanEmitter; use rustc_errors::{DiagCtxt, MultiSpan, PResult}; use termcolor::WriteColor; @@ -30,7 +30,7 @@ fn create_test_handler() -> (DiagCtxt, Lrc, Arc>>) { vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE], false, ); - let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }), fallback_bundle) + let emitter = HumanEmitter::new(Box::new(Shared { data: output.clone() }), fallback_bundle) .sm(Some(source_map.clone())) .diagnostic_width(Some(140)); let dcx = DiagCtxt::with_emitter(Box::new(emitter)); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 9ee7625e5bfeb..b2e3bce09bd6b 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -18,7 +18,7 @@ use rustc_data_structures::sync::{ AtomicU64, DynSend, DynSync, Lock, Lrc, OneThread, Ordering::SeqCst, }; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter; -use rustc_errors::emitter::{DynEmitter, EmitterWriter, HumanReadableErrorType}; +use rustc_errors::emitter::{DynEmitter, HumanEmitter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; use rustc_errors::{ @@ -1009,7 +1009,7 @@ fn default_emitter( ); Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing)) } else { - let emitter = EmitterWriter::stderr(color_config, fallback_bundle) + let emitter = HumanEmitter::stderr(color_config, fallback_bundle) .fluent_bundle(bundle) .sm(Some(source_map)) .short_message(short) @@ -1501,7 +1501,7 @@ fn mk_emitter(output: ErrorOutputType) -> Box { let emitter: Box = match output { config::ErrorOutputType::HumanReadable(kind) => { let (short, color_config) = kind.unzip(); - Box::new(EmitterWriter::stderr(color_config, fallback_bundle).short_message(short)) + Box::new(HumanEmitter::stderr(color_config, fallback_bundle).short_message(short)) } config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::basic( pretty, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 102a9f40e9b32..4f5ef2234c33b 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -1,7 +1,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::unord::UnordSet; -use rustc_errors::emitter::{DynEmitter, EmitterWriter}; +use rustc_errors::emitter::{DynEmitter, HumanEmitter}; use rustc_errors::json::JsonEmitter; use rustc_errors::TerminalUrl; use rustc_feature::UnstableFeatures; @@ -138,7 +138,7 @@ pub(crate) fn new_dcx( ErrorOutputType::HumanReadable(kind) => { let (short, color_config) = kind.unzip(); Box::new( - EmitterWriter::stderr(color_config, fallback_bundle) + HumanEmitter::stderr(color_config, fallback_bundle) .sm(source_map.map(|sm| sm as _)) .short_message(short) .teach(unstable_opts.teach) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index c74f2ecb0184d..9a9006252684d 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -557,7 +557,7 @@ pub(crate) fn make_test( // crate already is included. let result = rustc_driver::catch_fatal_errors(|| { rustc_span::create_session_if_not_set_then(edition, |_| { - use rustc_errors::emitter::{Emitter, EmitterWriter}; + use rustc_errors::emitter::{Emitter, HumanEmitter}; use rustc_errors::DiagCtxt; use rustc_parse::parser::ForceCollect; use rustc_span::source_map::FilePathMapping; @@ -572,11 +572,11 @@ pub(crate) fn make_test( rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false, ); - supports_color = EmitterWriter::stderr(ColorConfig::Auto, fallback_bundle.clone()) + supports_color = HumanEmitter::stderr(ColorConfig::Auto, fallback_bundle.clone()) .diagnostic_width(Some(80)) .supports_color(); - let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle); + let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle); // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser let dcx = DiagCtxt::with_emitter(Box::new(emitter)).disable_warnings(); @@ -739,7 +739,7 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool { } rustc_driver::catch_fatal_errors(|| { rustc_span::create_session_if_not_set_then(edition, |_| { - use rustc_errors::emitter::EmitterWriter; + use rustc_errors::emitter::HumanEmitter; use rustc_errors::DiagCtxt; use rustc_span::source_map::FilePathMapping; @@ -752,7 +752,7 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool { false, ); - let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle); + let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle); let dcx = DiagCtxt::with_emitter(Box::new(emitter)).disable_warnings(); let sess = ParseSess::with_dcx(dcx, sm); diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs index c639813a3f9ae..a744b69ecb478 100644 --- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs +++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs @@ -5,7 +5,7 @@ use crate::doc::{NEEDLESS_DOCTEST_MAIN, TEST_ATTR_IN_DOCTEST}; use clippy_utils::diagnostics::span_lint; use rustc_ast::{CoroutineKind, Fn, FnRetTy, Item, ItemKind}; use rustc_data_structures::sync::Lrc; -use rustc_errors::emitter::EmitterWriter; +use rustc_errors::emitter::HumanEmitter; use rustc_errors::DiagCtxt; use rustc_lint::LateContext; use rustc_parse::maybe_new_parser_from_source_str; @@ -44,7 +44,7 @@ pub fn check( let fallback_bundle = rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false); - let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle); + let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle); let dcx = DiagCtxt::with_emitter(Box::new(emitter)).disable_warnings(); #[expect(clippy::arc_with_non_send_sync)] // `Lrc` is expected by with_dcx let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index 8303c03e1eb4c..2663f16b8e8d8 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -2,7 +2,7 @@ use std::path::Path; use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::{IntoDynSyncSend, Lrc}; -use rustc_errors::emitter::{DynEmitter, Emitter, EmitterWriter}; +use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter}; use rustc_errors::translation::Translate; use rustc_errors::{ColorConfig, DiagCtxt, Diagnostic, Level as DiagnosticLevel}; use rustc_session::parse::ParseSess as RawParseSess; @@ -139,7 +139,7 @@ fn default_dcx( rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false, ); - Box::new(EmitterWriter::stderr(emit_color, fallback_bundle).sm(Some(source_map.clone()))) + Box::new(HumanEmitter::stderr(emit_color, fallback_bundle).sm(Some(source_map.clone()))) }; DiagCtxt::with_emitter(Box::new(SilentOnIgnoredFilesEmitter { has_non_ignorable_parser_errors: false, From c4d63c7f760d23c2f5c509fa08a0b0afd34fd6fb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 5 Jan 2024 10:37:44 +1100 Subject: [PATCH 27/34] Rename `AnnotateSnippetEmitterWriter` as `AnnotateSnippetEmitter`. For consistency with other `Emitter` impls. --- .../rustc_errors/src/annotate_snippet_emitter_writer.rs | 8 ++++---- compiler/rustc_session/src/session.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 48e48f59a9992..3e2cb898124b1 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -20,7 +20,7 @@ use rustc_span::source_map::SourceMap; use rustc_span::SourceFile; /// Generates diagnostics using annotate-snippet -pub struct AnnotateSnippetEmitterWriter { +pub struct AnnotateSnippetEmitter { source_map: Option>, fluent_bundle: Option>, fallback_bundle: LazyFallbackBundle, @@ -33,7 +33,7 @@ pub struct AnnotateSnippetEmitterWriter { macro_backtrace: bool, } -impl Translate for AnnotateSnippetEmitterWriter { +impl Translate for AnnotateSnippetEmitter { fn fluent_bundle(&self) -> Option<&Lrc> { self.fluent_bundle.as_ref() } @@ -43,7 +43,7 @@ impl Translate for AnnotateSnippetEmitterWriter { } } -impl Emitter for AnnotateSnippetEmitterWriter { +impl Emitter for AnnotateSnippetEmitter { /// The entry point for the diagnostics generation fn emit_diagnostic(&mut self, diag: &Diagnostic) { let fluent_args = to_fluent_args(diag.args()); @@ -99,7 +99,7 @@ fn annotation_type_for_level(level: Level) -> AnnotationType { } } -impl AnnotateSnippetEmitterWriter { +impl AnnotateSnippetEmitter { pub fn new( source_map: Option>, fluent_bundle: Option>, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index b2e3bce09bd6b..e77932a13e3b4 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -17,7 +17,7 @@ use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; use rustc_data_structures::sync::{ AtomicU64, DynSend, DynSync, Lock, Lrc, OneThread, Ordering::SeqCst, }; -use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter; +use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter; use rustc_errors::emitter::{DynEmitter, HumanEmitter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; @@ -1000,7 +1000,7 @@ fn default_emitter( let (short, color_config) = kind.unzip(); if let HumanReadableErrorType::AnnotateSnippet(_) = kind { - let emitter = AnnotateSnippetEmitterWriter::new( + let emitter = AnnotateSnippetEmitter::new( Some(source_map), bundle, fallback_bundle, From 453fface11dbe314fcdf1e0558ad084600c0b1f5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 5 Jan 2024 10:49:35 +1100 Subject: [PATCH 28/34] Add some comments to `Emitter`. There are three functions only used for the JSON format. --- compiler/rustc_errors/src/emitter.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 3f0fd559b6047..987832e6937bd 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -196,13 +196,15 @@ pub trait Emitter: Translate { fn emit_diagnostic(&mut self, diag: &Diagnostic); /// Emit a notification that an artifact has been output. - /// This is currently only supported for the JSON format, - /// other formats can, and will, simply ignore it. + /// Currently only supported for the JSON format. fn emit_artifact_notification(&mut self, _path: &Path, _artifact_type: &str) {} + /// Emit a report about future breakage. + /// Currently only supported for the JSON format. fn emit_future_breakage_report(&mut self, _diags: Vec) {} - /// Emit list of unused externs + /// Emit list of unused externs. + /// Currently only supported for the JSON format. fn emit_unused_externs( &mut self, _lint_level: rustc_lint_defs::Level, From f9df1ad4f252531d0d66c97beb0d25c0deb3e07d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 28 Oct 2023 09:26:39 +1100 Subject: [PATCH 29/34] Check for profiler support via a flag, instead of an environment var --- src/bootstrap/src/core/build_steps/test.rs | 2 +- src/tools/compiletest/src/common.rs | 4 ++++ src/tools/compiletest/src/header/needs.rs | 2 +- src/tools/compiletest/src/header/tests.rs | 18 ++++++++++++++++++ src/tools/compiletest/src/lib.rs | 3 +++ 5 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 3ae3af38bf85b..f757bdb001eba 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1976,7 +1976,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the } if builder.config.profiler_enabled(target) { - cmd.env("RUSTC_PROFILER_SUPPORT", "1"); + cmd.arg("--profiler-support"); } cmd.env("RUST_TEST_TMPDIR", builder.tempdir()); diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index e85f6319936bf..4cf5a710586c1 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -387,6 +387,10 @@ pub struct Config { // Needed both to construct build_helper::git::GitConfig pub git_repository: String, pub nightly_branch: String, + + /// True if the profiler runtime is enabled for this target. + /// Used by the "needs-profiler-support" header in test files. + pub profiler_support: bool, } impl Config { diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 4a40fb55f5c16..9b22b2112a8c0 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -238,7 +238,7 @@ impl CachedNeedsConditions { sanitizer_memtag: sanitizers.contains(&Sanitizer::Memtag), sanitizer_shadow_call_stack: sanitizers.contains(&Sanitizer::ShadowCallStack), sanitizer_safestack: sanitizers.contains(&Sanitizer::Safestack), - profiler_support: std::env::var_os("RUSTC_PROFILER_SUPPORT").is_some(), + profiler_support: config.profiler_support, xray: config.target_cfg().xray, // For tests using the `needs-rust-lld` directive (e.g. for `-Clink-self-contained=+linker`), diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 295134c78dcb1..c6d63f7419fed 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -62,6 +62,7 @@ struct ConfigBuilder { llvm_version: Option, git_hash: bool, system_llvm: bool, + profiler_support: bool, } impl ConfigBuilder { @@ -100,6 +101,11 @@ impl ConfigBuilder { self } + fn profiler_support(&mut self, s: bool) -> &mut Self { + self.profiler_support = s; + self + } + fn build(&mut self) -> Config { let args = &[ "compiletest", @@ -142,6 +148,9 @@ impl ConfigBuilder { if self.system_llvm { args.push("--system-llvm".to_owned()); } + if self.profiler_support { + args.push("--profiler-support".to_owned()); + } args.push("--rustc-path".to_string()); // This is a subtle/fragile thing. On rust-lang CI, there is no global @@ -340,6 +349,15 @@ fn sanitizers() { assert!(check_ignore(&config, "// needs-sanitizer-thread")); } +#[test] +fn profiler_support() { + let config: Config = cfg().profiler_support(false).build(); + assert!(check_ignore(&config, "// needs-profiler-support")); + + let config: Config = cfg().profiler_support(true).build(); + assert!(!check_ignore(&config, "// needs-profiler-support")); +} + #[test] fn asm_support() { let asms = [ diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 5a80b9121f063..60dd15841b766 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -142,6 +142,7 @@ pub fn parse_config(args: Vec) -> Config { .optflag("", "force-rerun", "rerun tests even if the inputs are unchanged") .optflag("", "only-modified", "only run tests that result been modified") .optflag("", "nocapture", "") + .optflag("", "profiler-support", "is the profiler runtime enabled for this target") .optflag("h", "help", "show this message") .reqopt("", "channel", "current Rust channel", "CHANNEL") .optflag("", "git-hash", "run tests which rely on commit version being compiled into the binaries") @@ -315,6 +316,8 @@ pub fn parse_config(args: Vec) -> Config { git_repository: matches.opt_str("git-repository").unwrap(), nightly_branch: matches.opt_str("nightly-branch").unwrap(), + + profiler_support: matches.opt_present("profiler-support"), } } From aa4bf0bbf0078ca0f9b2cc1a9c0edea0b551af35 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 30 Nov 2023 17:45:03 +1100 Subject: [PATCH 30/34] Allow tests to ignore individual test modes Normally, each test in `tests/coverage` is automatically run in both `coverage-map` mode and `coverage-run` mode. This new family of directives allows an individual test to specify that it should not be run in a particular mode. --- src/tools/compiletest/src/header/cfg.rs | 13 +++++++++++- src/tools/compiletest/src/header/tests.rs | 26 +++++++++++++++++++++-- tests/coverage/ignore_map.coverage | 4 ++++ tests/coverage/ignore_map.rs | 3 +++ tests/coverage/ignore_run.cov-map | 8 +++++++ tests/coverage/ignore_run.rs | 3 +++ 6 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 tests/coverage/ignore_map.coverage create mode 100644 tests/coverage/ignore_map.rs create mode 100644 tests/coverage/ignore_run.cov-map create mode 100644 tests/coverage/ignore_run.rs diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index e2a04b7e55882..df8c804705029 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -1,4 +1,4 @@ -use crate::common::{CompareMode, Config, Debugger}; +use crate::common::{CompareMode, Config, Debugger, Mode}; use crate::header::IgnoreDecision; use std::collections::HashSet; @@ -208,6 +208,17 @@ pub(super) fn parse_cfg_name_directive<'a>( }, message: "when comparing with {name}", } + // Coverage tests run the same test file in multiple modes. + // If a particular test should not be run in one of the modes, ignore it + // with "ignore-mode-coverage-map" or "ignore-mode-coverage-run". + condition! { + name: format!("mode-{}", config.mode.to_str()), + allowed_names: ContainsPrefixed { + prefix: "mode-", + inner: Mode::STR_VARIANTS, + }, + message: "when the test mode is {name}", + } if prefix == "ignore" && outcome == MatchOutcome::Invalid { // Don't error out for ignore-tidy-* diretives, as those are not handled by compiletest. diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index c6d63f7419fed..8882f1582acc7 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -1,7 +1,8 @@ use std::io::Read; use std::path::Path; +use std::str::FromStr; -use crate::common::{Config, Debugger}; +use crate::common::{Config, Debugger, Mode}; use crate::header::{parse_normalization_string, EarlyProps, HeadersCache}; fn make_test_description( @@ -55,6 +56,7 @@ fn test_parse_normalization_string() { #[derive(Default)] struct ConfigBuilder { + mode: Option, channel: Option, host: Option, target: Option, @@ -66,6 +68,11 @@ struct ConfigBuilder { } impl ConfigBuilder { + fn mode(&mut self, s: &str) -> &mut Self { + self.mode = Some(s.to_owned()); + self + } + fn channel(&mut self, s: &str) -> &mut Self { self.channel = Some(s.to_owned()); self @@ -109,7 +116,8 @@ impl ConfigBuilder { fn build(&mut self) -> Config { let args = &[ "compiletest", - "--mode=ui", + "--mode", + self.mode.as_deref().unwrap_or("ui"), "--suite=ui", "--compile-lib-path=", "--run-lib-path=", @@ -548,3 +556,17 @@ fn families() { assert!(!check_ignore(&config, &format!("// ignore-{other}"))); } } + +#[test] +fn ignore_mode() { + for &mode in Mode::STR_VARIANTS { + // Indicate profiler support so that "coverage-run" tests aren't skipped. + let config: Config = cfg().mode(mode).profiler_support(true).build(); + let other = if mode == "coverage-run" { "coverage-map" } else { "coverage-run" }; + assert_ne!(mode, other); + assert_eq!(config.mode, Mode::from_str(mode).unwrap()); + assert_ne!(config.mode, Mode::from_str(other).unwrap()); + assert!(check_ignore(&config, &format!("// ignore-mode-{mode}"))); + assert!(!check_ignore(&config, &format!("// ignore-mode-{other}"))); + } +} diff --git a/tests/coverage/ignore_map.coverage b/tests/coverage/ignore_map.coverage new file mode 100644 index 0000000000000..04bcb5bec6ec2 --- /dev/null +++ b/tests/coverage/ignore_map.coverage @@ -0,0 +1,4 @@ + LL| |// ignore-mode-coverage-map + LL| | + LL| 1|fn main() {} + diff --git a/tests/coverage/ignore_map.rs b/tests/coverage/ignore_map.rs new file mode 100644 index 0000000000000..71b82e8fc9def --- /dev/null +++ b/tests/coverage/ignore_map.rs @@ -0,0 +1,3 @@ +// ignore-mode-coverage-map + +fn main() {} diff --git a/tests/coverage/ignore_run.cov-map b/tests/coverage/ignore_run.cov-map new file mode 100644 index 0000000000000..9865efae0a1ef --- /dev/null +++ b/tests/coverage/ignore_run.cov-map @@ -0,0 +1,8 @@ +Function name: ignore_run::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 00, 0d] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 13) + diff --git a/tests/coverage/ignore_run.rs b/tests/coverage/ignore_run.rs new file mode 100644 index 0000000000000..87108867a057d --- /dev/null +++ b/tests/coverage/ignore_run.rs @@ -0,0 +1,3 @@ +// ignore-mode-coverage-run + +fn main() {} From 9ab8c632ee2ede9a350104278864154d933ed1db Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 4 Jan 2024 11:08:01 +1100 Subject: [PATCH 31/34] Extract a `split_flags` helper in header directive parsing --- src/tools/compiletest/src/header.rs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index f85f9e674ab12..a9f022664cfd9 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -321,16 +321,23 @@ impl TestProps { |r| r, ); - if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) { - self.compile_flags.extend( - flags - .split("'") - .enumerate() - .flat_map(|(i, f)| { + fn split_flags(flags: &str) -> Vec { + // Individual flags can be single-quoted to preserve spaces; see + // . + flags + .split("'") + .enumerate() + .flat_map( + |(i, f)| { if i % 2 == 1 { vec![f] } else { f.split_whitespace().collect() } - }) - .map(|s| s.to_owned()), - ); + }, + ) + .map(move |s| s.to_owned()) + .collect::>() + } + + if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) { + self.compile_flags.extend(split_flags(&flags)); } if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() { panic!("`compiler-flags` directive should be spelled `compile-flags`"); From 731ba80a6b53e3397eadeda37b18bd8fb3016aad Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 16 Dec 2023 13:30:47 +1100 Subject: [PATCH 32/34] Allow coverage tests to enable `llvm-cov --use-color` --- src/tools/compiletest/src/header.rs | 9 +++++++++ src/tools/compiletest/src/runtest.rs | 2 ++ tests/coverage/color.coverage | 13 +++++++++++++ tests/coverage/color.rs | 11 +++++++++++ 4 files changed, 35 insertions(+) create mode 100644 tests/coverage/color.coverage create mode 100644 tests/coverage/color.rs diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index a9f022664cfd9..e70e01e8757e0 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -178,6 +178,9 @@ pub struct TestProps { // Whether to tell `rustc` to remap the "src base" directory to a fake // directory. pub remap_src_base: bool, + /// Extra flags to pass to `llvm-cov` when producing coverage reports. + /// Only used by the "coverage-run" test mode. + pub llvm_cov_flags: Vec, } mod directives { @@ -216,6 +219,7 @@ mod directives { pub const MIR_UNIT_TEST: &'static str = "unit-test"; pub const REMAP_SRC_BASE: &'static str = "remap-src-base"; pub const COMPARE_OUTPUT_LINES_BY_SUBSET: &'static str = "compare-output-lines-by-subset"; + pub const LLVM_COV_FLAGS: &'static str = "llvm-cov-flags"; // This isn't a real directive, just one that is probably mistyped often pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags"; } @@ -265,6 +269,7 @@ impl TestProps { stderr_per_bitwidth: false, mir_unit_test: None, remap_src_base: false, + llvm_cov_flags: vec![], } } @@ -495,6 +500,10 @@ impl TestProps { COMPARE_OUTPUT_LINES_BY_SUBSET, &mut self.compare_output_lines_by_subset, ); + + if let Some(flags) = config.parse_name_value_directive(ln, LLVM_COV_FLAGS) { + self.llvm_cov_flags.extend(split_flags(&flags)); + } }); } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 1f5f77839de41..b258b748ca876 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -575,6 +575,8 @@ impl<'test> TestCx<'test> { cmd.arg("--object"); cmd.arg(bin); } + + cmd.args(&self.props.llvm_cov_flags); }); if !proc_res.status.success() { self.fatal_proc_rec("llvm-cov show failed!", &proc_res); diff --git a/tests/coverage/color.coverage b/tests/coverage/color.coverage new file mode 100644 index 0000000000000..bc49fff9cb75d --- /dev/null +++ b/tests/coverage/color.coverage @@ -0,0 +1,13 @@ + LL| |// edition: 2021 + LL| |// ignore-mode-coverage-map + LL| |// ignore-windows + LL| |// llvm-cov-flags: --use-color + LL| | + LL| |// Verify that telling `llvm-cov` to use colored output actually works. + LL| |// Ignored on Windows because we can't tell the tool to use ANSI escapes. + LL| | + LL| 1|fn main() { + LL| 1| for _i in 0..0 {} + ^0 ^0 + LL| 1|} + diff --git a/tests/coverage/color.rs b/tests/coverage/color.rs new file mode 100644 index 0000000000000..bd727946c781b --- /dev/null +++ b/tests/coverage/color.rs @@ -0,0 +1,11 @@ +// edition: 2021 +// ignore-mode-coverage-map +// ignore-windows +// llvm-cov-flags: --use-color + +// Verify that telling `llvm-cov` to use colored output actually works. +// Ignored on Windows because we can't tell the tool to use ANSI escapes. + +fn main() { + for _i in 0..0 {} +} From f5a09a9e1d162793d16b53cd6ad266a37e11d800 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 5 Jan 2024 14:19:02 +1100 Subject: [PATCH 33/34] Unbreak `tests/ui/lint/use_suggestion_json.rs`. PR #82639 changed UI tests so `-Z unstable-options` aren't passed to UI tests by default. This completely broke `use_suggestion_json.rs`, which uses the unstable `--error-format=pretty-json` option. The expected output went from 400 lines of pretty JSON error messages to a single JSON error saying "`--error-format=pretty-json` is unstable"! This commit adds `-Z unstable-options` back and reinstates the old expected output, with some minor changes to account for shifted spans and slightly JSON output changes since then. --- tests/ui/lint/use_suggestion_json.rs | 2 +- tests/ui/lint/use_suggestion_json.stderr | 424 ++++++++++++++++++++++- 2 files changed, 423 insertions(+), 3 deletions(-) diff --git a/tests/ui/lint/use_suggestion_json.rs b/tests/ui/lint/use_suggestion_json.rs index 7d641e08bf012..6a947f1430280 100644 --- a/tests/ui/lint/use_suggestion_json.rs +++ b/tests/ui/lint/use_suggestion_json.rs @@ -1,6 +1,6 @@ // ignore-windows // ignore-sgx std::os::fortanix_sgx::usercalls::alloc::Iter changes compiler suggestions -// compile-flags: --error-format pretty-json --json=diagnostic-rendered-ansi +// compile-flags: --error-format pretty-json --json=diagnostic-rendered-ansi -Z unstable-options // The output for humans should just highlight the whole span without showing // the suggested replacement, but we also want to test that suggested diff --git a/tests/ui/lint/use_suggestion_json.stderr b/tests/ui/lint/use_suggestion_json.stderr index 7dfd269a4e247..b3c973680b7f8 100644 --- a/tests/ui/lint/use_suggestion_json.stderr +++ b/tests/ui/lint/use_suggestion_json.stderr @@ -1,3 +1,423 @@ -{"$message_type":"diagnostic","message":"`--error-format=pretty-json` is unstable","code":null,"level":"error","spans":[],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: `--error-format=pretty-json` is unstable\u001b[0m +{ + "$message_type": "diagnostic", + "message": "cannot find type `Iter` in this scope", + "code": { + "code": "E0412", + "explanation": "A used type name is not in scope. -"} +Erroneous code examples: + +```compile_fail,E0412 +impl Something {} // error: type name `Something` is not in scope + +// or: + +trait Foo { + fn bar(N); // error: type name `N` is not in scope +} + +// or: + +fn foo(x: T) {} // type name `T` is not in scope +``` + +To fix this error, please verify you didn't misspell the type name, you did +declare it or imported it into the scope. Examples: + +``` +struct Something; + +impl Something {} // ok! + +// or: + +trait Foo { + type N; + + fn bar(_: Self::N); // ok! +} + +// or: + +fn foo(x: T) {} // ok! +``` + +Another case that causes this error is when a type is imported into a parent +module. To fix this, you can follow the suggestion and use File directly or +`use super::File;` which will import the types from the parent namespace. An +example that causes this error is below: + +```compile_fail,E0412 +use std::fs::File; + +mod foo { + fn some_function(f: File) {} +} +``` + +``` +use std::fs::File; + +mod foo { + // either + use super::File; + // or + // use std::fs::File; + fn foo(f: File) {} +} +# fn main() {} // don't insert it for us; that'll break imports +``` +" + }, + "level": "error", + "spans": [ + { + "file_name": "$DIR/use_suggestion_json.rs", + "byte_start": 561, + "byte_end": 565, + "line_start": 12, + "line_end": 12, + "column_start": 12, + "column_end": 16, + "is_primary": true, + "text": [ + { + "text": " let x: Iter;", + "highlight_start": 12, + "highlight_end": 16 + } + ], + "label": "not found in this scope", + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [ + { + "message": "consider importing one of these items", + "code": null, + "level": "help", + "spans": [ + { + "file_name": "$DIR/use_suggestion_json.rs", + "byte_start": 538, + "byte_end": 538, + "line_start": 11, + "line_end": 11, + "column_start": 1, + "column_end": 1, + "is_primary": true, + "text": [ + { + "text": "fn main() {", + "highlight_start": 1, + "highlight_end": 1 + } + ], + "label": null, + "suggested_replacement": "use std::collections::binary_heap::Iter; + +", + "suggestion_applicability": "MaybeIncorrect", + "expansion": null + }, + { + "file_name": "$DIR/use_suggestion_json.rs", + "byte_start": 538, + "byte_end": 538, + "line_start": 11, + "line_end": 11, + "column_start": 1, + "column_end": 1, + "is_primary": true, + "text": [ + { + "text": "fn main() {", + "highlight_start": 1, + "highlight_end": 1 + } + ], + "label": null, + "suggested_replacement": "use std::collections::btree_map::Iter; + +", + "suggestion_applicability": "MaybeIncorrect", + "expansion": null + }, + { + "file_name": "$DIR/use_suggestion_json.rs", + "byte_start": 538, + "byte_end": 538, + "line_start": 11, + "line_end": 11, + "column_start": 1, + "column_end": 1, + "is_primary": true, + "text": [ + { + "text": "fn main() {", + "highlight_start": 1, + "highlight_end": 1 + } + ], + "label": null, + "suggested_replacement": "use std::collections::btree_set::Iter; + +", + "suggestion_applicability": "MaybeIncorrect", + "expansion": null + }, + { + "file_name": "$DIR/use_suggestion_json.rs", + "byte_start": 538, + "byte_end": 538, + "line_start": 11, + "line_end": 11, + "column_start": 1, + "column_end": 1, + "is_primary": true, + "text": [ + { + "text": "fn main() {", + "highlight_start": 1, + "highlight_end": 1 + } + ], + "label": null, + "suggested_replacement": "use std::collections::hash_map::Iter; + +", + "suggestion_applicability": "MaybeIncorrect", + "expansion": null + }, + { + "file_name": "$DIR/use_suggestion_json.rs", + "byte_start": 538, + "byte_end": 538, + "line_start": 11, + "line_end": 11, + "column_start": 1, + "column_end": 1, + "is_primary": true, + "text": [ + { + "text": "fn main() {", + "highlight_start": 1, + "highlight_end": 1 + } + ], + "label": null, + "suggested_replacement": "use std::collections::hash_set::Iter; + +", + "suggestion_applicability": "MaybeIncorrect", + "expansion": null + }, + { + "file_name": "$DIR/use_suggestion_json.rs", + "byte_start": 538, + "byte_end": 538, + "line_start": 11, + "line_end": 11, + "column_start": 1, + "column_end": 1, + "is_primary": true, + "text": [ + { + "text": "fn main() {", + "highlight_start": 1, + "highlight_end": 1 + } + ], + "label": null, + "suggested_replacement": "use std::collections::linked_list::Iter; + +", + "suggestion_applicability": "MaybeIncorrect", + "expansion": null + }, + { + "file_name": "$DIR/use_suggestion_json.rs", + "byte_start": 538, + "byte_end": 538, + "line_start": 11, + "line_end": 11, + "column_start": 1, + "column_end": 1, + "is_primary": true, + "text": [ + { + "text": "fn main() {", + "highlight_start": 1, + "highlight_end": 1 + } + ], + "label": null, + "suggested_replacement": "use std::collections::vec_deque::Iter; + +", + "suggestion_applicability": "MaybeIncorrect", + "expansion": null + }, + { + "file_name": "$DIR/use_suggestion_json.rs", + "byte_start": 538, + "byte_end": 538, + "line_start": 11, + "line_end": 11, + "column_start": 1, + "column_end": 1, + "is_primary": true, + "text": [ + { + "text": "fn main() {", + "highlight_start": 1, + "highlight_end": 1 + } + ], + "label": null, + "suggested_replacement": "use std::option::Iter; + +", + "suggestion_applicability": "MaybeIncorrect", + "expansion": null + }, + { + "file_name": "$DIR/use_suggestion_json.rs", + "byte_start": 538, + "byte_end": 538, + "line_start": 11, + "line_end": 11, + "column_start": 1, + "column_end": 1, + "is_primary": true, + "text": [ + { + "text": "fn main() {", + "highlight_start": 1, + "highlight_end": 1 + } + ], + "label": null, + "suggested_replacement": "use std::path::Iter; + +", + "suggestion_applicability": "MaybeIncorrect", + "expansion": null + }, + { + "file_name": "$DIR/use_suggestion_json.rs", + "byte_start": 538, + "byte_end": 538, + "line_start": 11, + "line_end": 11, + "column_start": 1, + "column_end": 1, + "is_primary": true, + "text": [ + { + "text": "fn main() {", + "highlight_start": 1, + "highlight_end": 1 + } + ], + "label": null, + "suggested_replacement": "use std::result::Iter; + +", + "suggestion_applicability": "MaybeIncorrect", + "expansion": null + }, + { + "file_name": "$DIR/use_suggestion_json.rs", + "byte_start": 538, + "byte_end": 538, + "line_start": 11, + "line_end": 11, + "column_start": 1, + "column_end": 1, + "is_primary": true, + "text": [ + { + "text": "fn main() {", + "highlight_start": 1, + "highlight_end": 1 + } + ], + "label": null, + "suggested_replacement": "use std::slice::Iter; + +", + "suggestion_applicability": "MaybeIncorrect", + "expansion": null + }, + { + "file_name": "$DIR/use_suggestion_json.rs", + "byte_start": 538, + "byte_end": 538, + "line_start": 11, + "line_end": 11, + "column_start": 1, + "column_end": 1, + "is_primary": true, + "text": [ + { + "text": "fn main() {", + "highlight_start": 1, + "highlight_end": 1 + } + ], + "label": null, + "suggested_replacement": "use std::sync::mpsc::Iter; + +", + "suggestion_applicability": "MaybeIncorrect", + "expansion": null + } + ], + "children": [], + "rendered": null + } + ], + "rendered": "\u001b[0m\u001b[1m\u001b[38;5;9merror[E0412]\u001b[0m\u001b[0m\u001b[1m: cannot find type `Iter` in this scope\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0m$DIR/use_suggestion_json.rs:12:12\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m +\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let x: Iter;\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mnot found in this scope\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m +\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: consider importing one of these items\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m +\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[38;5;10m+ use std::collections::binary_heap::Iter;\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m +\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[38;5;10m+ use std::collections::btree_map::Iter;\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m +\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[38;5;10m+ use std::collections::btree_set::Iter;\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m +\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[38;5;10m+ use std::collections::hash_map::Iter;\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m +\u001b[0m and 8 other candidates\u001b[0m + +" +} +{ + "$message_type": "diagnostic", + "message": "aborting due to 1 previous error", + "code": null, + "level": "error", + "spans": [], + "children": [], + "rendered": "\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: aborting due to 1 previous error\u001b[0m + +" +} +{ + "$message_type": "diagnostic", + "message": "For more information about this error, try `rustc --explain E0412`.", + "code": null, + "level": "failure-note", + "spans": [], + "children": [], + "rendered": "\u001b[0m\u001b[1mFor more information about this error, try `rustc --explain E0412`.\u001b[0m +" +} From 884322389759a9a9563e492d8bbd96b83c27c2de Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 5 Jan 2024 14:11:12 +1100 Subject: [PATCH 34/34] Change printing of "`--error-format` is unstable" errors. Currently for these two errors we go to the effort of switching to a standard JSON emitter, for no obvious reason, and unlike any other errors. This behaviour was added for `pretty-json` in #45737, and then `human-annotate-rs` copied it some time later when it was added. This commit changes things to just using the requested emitter, which is simpler and consistent with other errors. Old output: ``` $ rustc --error-format pretty-json {"$message_type":"diagnostic","message":"`--error-format=pretty-json` is unstable","code":null,"level":"error","spans":[],"children":[],"rendered":"error: `--error-format=pretty-json` is unstable\n\n"} $ rustc --error-format human-annotate-rs {"$message_type":"diagnostic","message":"`--error-format=human-annotate-rs` is unstable","code":null,"level":"error","spans":[],"children":[],"rendered":"error: `--error-format=human-annotate-rs` is unstable\n\n"} ``` New output: ``` $ rustc --error-format pretty-json { "$message_type": "diagnostic", "message": "`--error-format=pretty-json` is unstable", "code": null, "level": "error", "spans": [], "children": [], "rendered": "error: `--error-format=pretty-json` is unstable\n\n" } $ rustc --error-format human-annotate-rs error: `--error-format=human-annotate-rs` is unstable ``` --- compiler/rustc_session/src/config.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 89508c77639aa..c04c67dd39810 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2051,23 +2051,14 @@ fn check_error_format_stability( early_dcx: &mut EarlyDiagCtxt, unstable_opts: &UnstableOptions, error_format: ErrorOutputType, - json_rendered: HumanReadableErrorType, ) { if !unstable_opts.unstable_options { - if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format { - early_dcx.abort_if_error_and_set_error_format(ErrorOutputType::Json { - pretty: false, - json_rendered, - }); + if let ErrorOutputType::Json { pretty: true, .. } = error_format { early_dcx.early_fatal("`--error-format=pretty-json` is unstable"); } if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) = error_format { - early_dcx.abort_if_error_and_set_error_format(ErrorOutputType::Json { - pretty: false, - json_rendered, - }); early_dcx.early_fatal("`--error-format=human-annotate-rs` is unstable"); } } @@ -2665,7 +2656,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let mut unstable_opts = UnstableOptions::build(early_dcx, matches); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches); - check_error_format_stability(early_dcx, &unstable_opts, error_format, json_rendered); + check_error_format_stability(early_dcx, &unstable_opts, error_format); if !unstable_opts.unstable_options && json_unused_externs.is_enabled() { early_dcx.early_fatal(