diff options
Diffstat (limited to 'compiler')
73 files changed, 708 insertions, 1341 deletions
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 42ada39f515..ce5a737ef63 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -725,8 +725,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 fd2b0866867..fdb5d66bf62 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::<Vec<_>>(); 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 e07eb2e490b..f9ddffcc155 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<str>` 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 2af46f175d7..568f8247b28 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -395,10 +395,10 @@ 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.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 1b1ed0b411c..e9283b19894 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -119,12 +119,12 @@ impl<G: EmissionGuarantee> 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/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index c607533a08e..45be85934b4 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_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 8db97d577ca..422e8edff5f 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -107,7 +107,7 @@ impl<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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 5a8db7bbf2d..d2c6b6e0c7b 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 => Level::Error, + 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(); @@ -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 2b628d2aa69..c1086bebb8d 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -244,30 +244,30 @@ impl<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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 110ff87e27e..171cc89d6ad 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<G: EmissionGuarantee>( 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_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index b249ffb84b3..0b73691204d 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<BasicBlock>, - place_cache: FxHashSet<PlaceRef<'tcx>>, value_cache: FxHashSet<u128>, // 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_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 2041ffefe77..fd925b62702 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/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 48e48f59a99..5c0e210f147 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<Lrc<SourceMap>>, fluent_bundle: Option<Lrc<FluentBundle>>, 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<FluentBundle>> { 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()); @@ -86,9 +86,7 @@ fn source_string(file: Lrc<SourceFile>, 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, @@ -99,7 +97,7 @@ fn annotation_type_for_level(level: Level) -> AnnotationType { } } -impl AnnotateSnippetEmitterWriter { +impl AnnotateSnippetEmitter { pub fn new( source_map: Option<Lrc<SourceMap>>, fluent_bundle: Option<Lrc<FluentBundle>>, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 49431fb7b3f..701c1c02ab0 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<M: Into<DiagnosticMessage>>(level: Level, message: M) -> Self { @@ -241,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 @@ -308,25 +309,27 @@ 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. + /// 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<SubdiagnosticMessage>) -> &mut Self { self.span.push_span_label(span, self.subdiagnostic_message_to_diagnostic_message(label)); @@ -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<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self { + pub fn span<S: Into<MultiSpan>>(&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<DiagnosticMessage>) -> &mut Self { + pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &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<Cow<'static, str>>, arg: impl IntoDiagnosticArg, diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index ae54d343dad..e018c14a4a5 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 } } @@ -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 } @@ -356,35 +356,16 @@ 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. - /// - /// 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<SubdiagnosticMessage>) -> &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<SubdiagnosticMessage> + ) -> &mut Self); + forward!(pub fn span_labels( &mut self, spans: impl IntoIterator<Item = Span>, label: &str, ) -> &mut Self); - forward!(pub fn note_expected_found( &mut self, expected_label: &dyn fmt::Display, @@ -392,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, @@ -402,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<SubdiagnosticMessage>) -> &mut Self); forward!(pub fn note_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self); forward!(pub fn span_note( @@ -428,10 +407,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { sp: impl Into<MultiSpan>, msg: impl Into<SubdiagnosticMessage>, ) -> &mut Self); - forward!(pub fn set_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<SubdiagnosticMessage>, @@ -498,16 +475,14 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { suggestion: impl ToString, applicability: Applicability, ) -> &mut Self); - - forward!(pub fn set_primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self); - forward!(pub fn set_span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self); + forward!(pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self); + forward!(pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &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<Cow<'static, str>>, arg: impl IntoDiagnosticArg, ) -> &mut Self); - forward!(pub fn subdiagnostic( &mut self, subdiagnostic: impl crate::AddToDiagnostic diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 29cb304e8b5..de27c6e910b 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -254,29 +254,29 @@ impl<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 546159c9d13..987832e6937 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<dyn WriteColor + Send>, 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) } } @@ -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<Diagnostic>) {} - /// 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, @@ -501,7 +503,7 @@ pub trait Emitter: Translate { } } -impl Translate for EmitterWriter { +impl Translate for HumanEmitter { fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> { self.fluent_bundle.as_ref() } @@ -511,7 +513,7 @@ impl Translate for EmitterWriter { } } -impl Emitter for EmitterWriter { +impl Emitter for HumanEmitter { fn source_map(&self) -> Option<&Lrc<SourceMap>> { self.sm.as_ref() } @@ -622,7 +624,7 @@ impl ColorConfig { /// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short` #[derive(Setters)] -pub struct EmitterWriter { +pub struct HumanEmitter { #[setters(skip)] dst: IntoDynSyncSend<Destination>, sm: Option<Lrc<SourceMap>>, @@ -647,14 +649,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 +675,7 @@ impl EmitterWriter { pub fn new( dst: Box<dyn WriteColor + Send>, 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 6707e17e90f..25bec9f766b 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}; @@ -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, @@ -574,7 +571,7 @@ impl DiagCtxt { sm: Option<Lrc<SourceMap>>, 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 { @@ -673,7 +670,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 +694,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; @@ -732,7 +729,7 @@ impl DiagCtxt { msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, ()> { let mut result = self.struct_warn(msg); - result.set_span(span); + result.span(span); result } @@ -789,7 +786,7 @@ impl DiagCtxt { msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_> { let mut result = self.struct_err(msg); - result.set_span(span); + result.span(span); result } @@ -812,7 +809,7 @@ impl DiagCtxt { #[rustc_lint_diagnostics] #[track_caller] pub fn struct_err(&self, msg: impl Into<DiagnosticMessage>) -> 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`. @@ -850,7 +847,7 @@ impl DiagCtxt { msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, FatalAbort> { let mut result = self.struct_fatal(msg); - result.set_span(span); + result.span(span); result } @@ -878,16 +875,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<DiagnosticMessage>, - ) -> 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<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { @@ -917,7 +904,7 @@ impl DiagCtxt { msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, BugAbort> { let mut result = self.struct_bug(msg); - result.set_span(span); + result.span(span); result } @@ -1004,11 +991,10 @@ 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); - diagnostic.set_span(sp); + diagnostic.span(sp); self.emit_diagnostic(diagnostic).unwrap() } @@ -1016,11 +1002,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<DiagnosticMessage>) { 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)); } @@ -1039,7 +1021,7 @@ impl DiagCtxt { msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, ()> { let mut db = DiagnosticBuilder::new(self, Note, msg); - db.set_span(span); + db.span(span); db } @@ -1222,7 +1204,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] @@ -1377,7 +1359,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; @@ -1408,7 +1390,7 @@ impl DiagCtxtInner { &mut self, diagnostic: &mut Diagnostic, ) -> Option<ErrorGuaranteed> { - 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; } @@ -1430,10 +1412,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() { @@ -1509,7 +1489,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(); @@ -1705,11 +1685,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. /// @@ -1768,7 +1744,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(_) => { @@ -1789,7 +1765,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/expand.rs b/compiler/rustc_expand/src/expand.rs index 676f9f17976..5a616e0ffbf 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 5eb6aed7253..66695e020f1 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<SmallVec<[tokenstream::TokenTree; 2]>> impl ToInternal<rustc_errors::Level> 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, @@ -497,7 +497,7 @@ impl server::FreeFunctions for Rustc<'_, '_> { fn emit_diagnostic(&mut self, diagnostic: Diagnostic<Self::Span>) { 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_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs index 0b859841828..3c14ad5e7b8 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<SourceMap>, Arc<Mutex<Vec<u8>>>) { 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_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index f17f19bb77c..d22c4fe201d 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/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 7d840ba7e81..3f0ad6584b6 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/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index f3b93c91ae9..6675f517cfa 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -1,7 +1,9 @@ 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; use super::AstConv; @@ -32,32 +34,146 @@ 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 sugg = self.add_generic_param_suggestion(generics, self_ty.span, &impl_trait_name); + if sugg.is_empty() { + 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 add_generic_param_suggestion( + &self, + generics: &hir::Generics<'_>, + self_ty_span: Span, + impl_trait_name: &str, + ) -> Vec<(Span, String)> { + // 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}>")) + }; + 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) = 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())]; + 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 + { + 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", + ); + 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![ + (ty.span.shrink_to_lo(), "Box<dyn ".to_string()), + (ty.span.shrink_to_hi(), ">".to_string()), + ], + Applicability::MachineApplicable, + ); + } else { + // We'll emit the object safety error already, with a structured suggestion. + diag.downgrade_to_delayed_bug(); + } + return true; + } + for ty in sig.decl.inputs { + 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`")); + // 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. + 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 +214,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 +234,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/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index a614d4abf25..8a3df79cb25 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_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 75e7a5524a7..9124d502110 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/check.rs b/compiler/rustc_hir_typeck/src/check.rs index a852c3d2be3..c887368b2a2 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -73,7 +73,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. @@ -81,14 +82,14 @@ 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_or_coroutine(fn_def_id.into()) { None } else { - ty_span + ty.map(|ty| ty.hir_id) }, ), ); diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index ff03cf16a27..4f929068887 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/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index e169b45d725..52dc1e85916 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<Span>, + 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_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8a179c5a440..560537b468b 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 a0768fc7115..aee99063e03 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 68bf36a1615..8e45cc6d80e 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_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index d89c205da3f..4aabe5c2922 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<hir::HirId>, 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_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 75410db1e36..f3f59b05682 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); @@ -806,7 +805,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_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index eccea35c702..841d282a099 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 5950bc76ade..49821437b76 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 ca6408bdf3d..614c3ecbcae 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}; @@ -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 { @@ -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<F>(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with<F>(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 `<T as Bound>::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<F>(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with<F>(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,8 +419,8 @@ 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); + 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) { // Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited. @@ -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<F>(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with<F>(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<F>(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with<F>(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<F>(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with<F>(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<F>(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with<F>(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 } => { @@ -830,7 +812,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() @@ -953,12 +935,9 @@ pub struct NonBindingLetSub { } impl AddToDiagnostic for NonBindingLetSub { - fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with<F>(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,8 +1126,8 @@ pub struct NonFmtPanicUnused { // Used because of two suggestions based on one Option<Span> impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("count", self.count); + 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 { diag.span_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<F>(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with<F>(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, ()>) { - diag.set_arg("predicate", self.predicate); - diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id)); + 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, ()>) { - diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id)); + 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<F>(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with<F>(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,9 +1606,9 @@ pub struct ImproperCTypes<'a> { // Used because of the complexity of Option<DiagnosticMessage>, DiagnosticMessage, and Option<Span> 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); + 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); if let Some(help) = self.help { diag.help(help); @@ -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,10 +1749,10 @@ 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)); + 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)); // check for #[must_use = "..."] if let Some(note) = self.note { diag.note(note.to_string()); @@ -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 } } diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 9fcd70ba0b5..f0bbc03d747 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 f3e98d68b60..fb908fe2db1 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 663abecb67c..c029b931e7d 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 2700f02e33a..4684306e235 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<Applicability>, /// 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 e13068cb6f9..27c26d31781 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -500,10 +500,10 @@ pub(crate) struct MultipleCandidates { impl<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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 ae432a04065..d45ec8e4646 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -314,14 +314,14 @@ 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 { - 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_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index e6536074f35..1b4e9c28635 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<ConstValue<'tcx>, ErrorHandled>; /// This is needed in `thir::pattern::lower_inline_const`. pub type EvalToValTreeResult<'tcx> = Result<Option<ValTree<'tcx>>, 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 2db56008553..0da3524e055 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; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 0a1a72b442a..c863c68123d 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 0b487eae36d..a1e5d73a0fd 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 cb9fc0d37f2..00000000000 --- 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 = "</span>\n<span class=\"line\">"; -const HEADER: &str = r#"<!DOCTYPE html> -<html lang="en"> -<head> -<meta charset="utf-8">"#; -const START_BODY: &str = r#"</head> -<body>"#; -const FOOTER: &str = r#"</body> -</html>"#; - -const STYLE_SECTION: &str = r#"<style> - .line { - counter-increment: line; - } - .line:before { - content: counter(line) ": "; - font-family: Menlo, Monaco, monospace; - font-style: italic; - width: 3.8em; - display: inline-block; - text-align: right; - filter: opacity(50%); - -webkit-user-select: none; - } - .code { - color: #dddddd; - background-color: #222222; - font-family: Menlo, Monaco, monospace; - line-height: 1.4em; - border-bottom: 2px solid #222222; - white-space: pre; - display: inline-block; - } - .odd { - background-color: #55bbff; - color: #223311; - } - .even { - background-color: #ee7756; - color: #551133; - } - .code { - --index: calc(var(--layer) - 1); - padding-top: calc(var(--index) * 0.15em); - filter: - hue-rotate(calc(var(--index) * 25deg)) - saturate(calc(100% - (var(--index) * 2%))) - brightness(calc(100% - (var(--index) * 1.5%))); - } - .annotation { - color: #4444ff; - font-family: monospace; - font-style: italic; - display: none; - -webkit-user-select: none; - } - body:active .annotation { - /* requires holding mouse down anywhere on the page */ - display: inline-block; - } - span:hover .annotation { - /* requires hover over a span ONLY on its first line */ - display: inline-block; - } -</style>"#; - -/// 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<SpanViewable>, - 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>{title}</title>")?; - writeln!(w, "{STYLE_SECTION}")?; - writeln!(w, "{START_BODY}")?; - write!( - w, - r#"<div class="code" style="counter-reset: line {}"><span class="line">{}"#, - 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#"</span></div>"#)?; - 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<SpanViewable> { - 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<SpanViewable> { - 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<SpanViewable> { - 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<W>(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<W>( - 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, "<span>")?; - } - for (i, line) in html_snippet.lines().enumerate() { - if i > 0 { - write!(w, "{NEW_LINE_SPAN}")?; - } - write!( - w, - r#"<span class="code{maybe_alt_class}" style="--layer: {layer}"{maybe_title_attr}>{line}</span>"# - )?; - } - // 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, "</span>")?; - } - Ok(()) -} - -fn make_html_snippet( - tcx: TyCtxt<'_>, - span: Span, - some_viewable: Option<&SpanViewable>, -) -> Option<String> { - 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#"<span class="annotation">{}{}</span>"#, 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#"<span class="annotation">{}{}</span>"#, - 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<Statement<'tcx>>, - terminator: &Option<Terminator<'tcx>>, -) -> 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_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 09b0a0dfbf3..af601a0d702 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<Span>), + SizedArgumentType(Option<hir::HirId>), /// Return type must be `Sized`. SizedReturnType, /// Yield type must be `Sized`. diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 8677cba6a7c..61ad99acf38 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/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 15502adfb5a..cd80f423466 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/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 17916e16daf..bde442049b1 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<P> { 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_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs index 3940d0ddbf3..c0c0a3f5ee6 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::*; @@ -11,7 +12,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 +24,19 @@ 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, + places: Default::default(), + }; + for (bb, data) in traversal::reachable(body) { + lint.visit_basic_block_data(bb, data); } - .visit_body(body); } struct Lint<'a, 'tcx> { @@ -43,9 +45,9 @@ struct Lint<'a, 'tcx> { body: &'a Body<'tcx>, is_fn_like: bool, always_live_locals: &'a BitSet<Local>, - reachable_blocks: BitSet<BasicBlock>, maybe_storage_live: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>, maybe_storage_dead: ResultsCursor<'a, 'tcx, MaybeStorageDead<'a>>, + places: FxHashSet<PlaceRef<'tcx>>, } impl<'a, 'tcx> Lint<'a, 'tcx> { @@ -67,7 +69,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")); @@ -76,18 +78,28 @@ 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) { + 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, - format!("StorageLive({local:?}) which already has storage here"), + "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) { + self.fail( + location, + format!("StorageLive({local:?}) which already has storage here"), + ); + } + } _ => {} } @@ -95,9 +107,9 @@ 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.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) { @@ -111,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/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 82074f1960d..f4c572aec12 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<MirPhase>, 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/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 592e71251b8..2ca14673a58 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -51,7 +51,7 @@ impl<G: EmissionGuarantee> 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 936c5de2ae8..0de252707bd 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 083d1984e00..4819ed6021d 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}; @@ -252,7 +250,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); @@ -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( diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index f06aeed8628..579c3cffcfb 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 fb8ad05f25d..c8629069968 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 77bca2f138a..aed5e11133b 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 3932d32a6e1..b201d36455e 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 edce99db705..e4bbc9eeaf7 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 856256a0641..9bd9dd41cf6 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -868,8 +868,8 @@ impl<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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 cb712fe640c..1a4f3edd810 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 9bd58dfe82b..6c38ed62270 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/config.rs b/compiler/rustc_session/src/config.rs index 89508c77639..12d8293ecd2 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` @@ -1162,7 +1147,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, @@ -2051,23 +2035,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 +2640,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( diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 0f86773b73f..758c3122404 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_session/src/options.rs b/compiler/rustc_session/src/options.rs index 0b0b67ef890..842bf1d60f6 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<MirSpanview>, 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<MirSpanview> = (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"), @@ -1841,8 +1812,6 @@ options! { remark_dir: Option<PathBuf> = (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<bool> = (Some(true), parse_opt_bool, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index c80990402a9..ce166ae352f 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -17,8 +17,8 @@ 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::emitter::{DynEmitter, EmitterWriter, HumanReadableErrorType}; +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; use rustc_errors::{ @@ -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, @@ -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) @@ -1504,7 +1504,7 @@ fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> { let emitter: Box<DynEmitter> = 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/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs index 06a2b3ca9c4..0fa59d2ddfb 100644 --- a/compiler/rustc_symbol_mangling/src/errors.rs +++ b/compiler/rustc_symbol_mangling/src/errors.rs @@ -19,7 +19,7 @@ impl<G: EmissionGuarantee> 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 bea6fbd6ac5..5eff52afbca 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -66,12 +66,9 @@ impl<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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<G: EmissionGuarantee> 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 f63314081d6..58700850a60 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}; @@ -2008,7 +2007,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 +2712,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 +2800,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 { @@ -3200,35 +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 { - 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 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, - ); + 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, + ); + } + _ => {} } - err.span_suggestion_verbose( - span.shrink_to_lo(), - "function arguments must have a statically known size, borrowed types \ - always have a known size", - "&", - Applicability::MachineApplicable, - ); } else { err.note("all function arguments must have a statically known size"); } 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 d2598b0defe..efc75ee538e 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) => { @@ -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) )); |
