From d12ecaed558426ec7998816d64b240ea685a2a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2025 01:15:59 +0000 Subject: [PATCH 1/7] Teach structured errors to display short `Ty` Make it so that every structured error annotated with `#[derive(Diagnostic)]` that has a field of type `Ty<'_>`, the printing of that value into a `String` will look at the thread-local storage `TyCtxt` in order to shorten to a length appropriate with the terminal width. When this happen, the resulting error will have a note with the file where the full type name was written to. ``` error[E0618]: expected function, found `((..., ..., ..., ...), ..., ..., ...)`` --> long.rs:7:5 | 6 | fn foo(x: D) { //~ `x` has type `(... | - `x` has type `((..., ..., ..., ...), ..., ..., ...)` 7 | x(); //~ ERROR expected function, found `(... | ^-- | | | call expression requires function | = note: the full name for the type has been written to 'long.long-type-14182675702747116984.txt' = note: consider using `--verbose` to print the full type name to the console ``` --- compiler/rustc_ast_passes/src/errors.rs | 1 - .../src/diagnostics/conflict_errors.rs | 1 - .../src/diagnostics/move_errors.rs | 9 +- .../src/diagnostics/region_name.rs | 4 +- .../rustc_borrowck/src/session_diagnostics.rs | 6 +- .../src/assert_module_sources.rs | 2 +- compiler/rustc_codegen_ssa/src/errors.rs | 4 +- .../rustc_const_eval/src/const_eval/error.rs | 8 +- compiler/rustc_const_eval/src/errors.rs | 2 +- compiler/rustc_errors/src/diagnostic.rs | 6 +- compiler/rustc_errors/src/diagnostic_impls.rs | 96 +++++++++---------- compiler/rustc_hir_typeck/messages.ftl | 6 +- compiler/rustc_hir_typeck/src/callee.rs | 45 +++++---- compiler/rustc_hir_typeck/src/cast.rs | 15 ++- compiler/rustc_hir_typeck/src/errors.rs | 19 ++-- compiler/rustc_metadata/src/locator.rs | 2 +- compiler/rustc_middle/src/error.rs | 4 +- .../rustc_middle/src/mir/interpret/error.rs | 8 +- compiler/rustc_middle/src/mir/terminator.rs | 2 +- compiler/rustc_middle/src/ty/consts/int.rs | 2 +- compiler/rustc_middle/src/ty/diagnostics.rs | 10 +- compiler/rustc_middle/src/ty/error.rs | 10 +- compiler/rustc_middle/src/ty/generic_args.rs | 4 +- compiler/rustc_middle/src/ty/layout.rs | 4 +- compiler/rustc_middle/src/ty/predicate.rs | 18 ++-- compiler/rustc_middle/src/ty/print/pretty.rs | 18 ++-- compiler/rustc_mir_build/src/errors.rs | 4 +- .../src/thir/pattern/check_match.rs | 6 +- compiler/rustc_parse/src/errors.rs | 1 - compiler/rustc_passes/src/check_attr.rs | 4 +- compiler/rustc_passes/src/errors.rs | 4 +- compiler/rustc_passes/src/layout_test.rs | 3 +- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_session/src/config.rs | 4 +- compiler/rustc_session/src/session.rs | 4 +- .../src/error_reporting/infer/mod.rs | 2 +- .../error_reporting/infer/need_type_info.rs | 2 +- .../nice_region_error/placeholder_error.rs | 2 +- compiler/rustc_trait_selection/src/errors.rs | 6 +- .../src/errors/note_and_explain.rs | 4 +- tests/ui/diagnostic-width/long-E0618.rs | 13 +++ tests/ui/diagnostic-width/long-E0618.stderr | 16 ++++ 42 files changed, 216 insertions(+), 167 deletions(-) create mode 100644 tests/ui/diagnostic-width/long-E0618.rs create mode 100644 tests/ui/diagnostic-width/long-E0618.stderr diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 9f0d2325475a..8e53e600f7ac 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -535,7 +535,6 @@ pub(crate) struct WhereClauseBeforeTypeAlias { } #[derive(Subdiagnostic)] - pub(crate) enum WhereClauseBeforeTypeAliasSugg { #[suggestion(ast_passes_remove_suggestion, applicability = "machine-applicable", code = "")] Remove { diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index f33f2ab58e05..2694a1eda78d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -287,7 +287,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { None => "value".to_owned(), }; if needs_note { - let ty = self.infcx.tcx.short_string(ty, err.long_ty_path()); if let Some(local) = place.as_local() { let span = self.body.local_decls[local].source_info.span; err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 5e83d2ffa97a..29cc749877b3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -596,10 +596,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning(err, place_ty, expr, None); } - let ty = self.infcx.tcx.short_string(place_ty, err.long_ty_path()); err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { is_partial_move: false, - ty, + ty: place_ty, place: &place_desc, span, }); @@ -629,10 +628,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning(err, place_ty, expr, Some(use_spans)); } - let ty = self.infcx.tcx.short_string(place_ty, err.long_ty_path()); err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { is_partial_move: false, - ty, + ty: place_ty, place: &place_desc, span: use_span, }); @@ -833,10 +831,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning(err, bind_to.ty, expr, None); } - let ty = self.infcx.tcx.short_string(bind_to.ty, err.long_ty_path()); err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { is_partial_move: false, - ty, + ty: bind_to.ty, place: place_desc, span: binding_span, }); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index be28f84debd9..a15f9744bf31 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -194,8 +194,8 @@ impl Display for RegionName { } impl rustc_errors::IntoDiagArg for RegionName { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { + self.to_string().into_diag_arg(path) } } diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 11b30c145c2c..4be5d0dbf428 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -459,17 +459,17 @@ pub(crate) enum OnClosureNote<'a> { } #[derive(Subdiagnostic)] -pub(crate) enum TypeNoCopy<'a> { +pub(crate) enum TypeNoCopy<'a, 'tcx> { #[label(borrowck_ty_no_impl_copy)] Label { is_partial_move: bool, - ty: String, + ty: Ty<'tcx>, place: &'a str, #[primary_span] span: Span, }, #[note(borrowck_ty_no_impl_copy)] - Note { is_partial_move: bool, ty: String, place: &'a str }, + Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str }, } #[derive(Diagnostic)] diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index da9f8d692972..32f689608f81 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -211,7 +211,7 @@ impl fmt::Display for CguReuse { } impl IntoDiagArg for CguReuse { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self.to_string())) } } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 5e25de02a77f..7e28961599f0 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -161,7 +161,7 @@ impl<'a> CopyPath<'a> { struct DebugArgPath<'a>(pub &'a Path); impl IntoDiagArg for DebugArgPath<'_> { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> rustc_errors::DiagArgValue { DiagArgValue::Str(Cow::Owned(format!("{:?}", self.0))) } } @@ -1087,7 +1087,7 @@ pub enum ExpectedPointerMutability { } impl IntoDiagArg for ExpectedPointerMutability { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { match self { ExpectedPointerMutability::Mut => DiagArgValue::Str(Cow::Borrowed("*mut")), ExpectedPointerMutability::Not => DiagArgValue::Str(Cow::Borrowed("*_")), diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index cc21a18af3a0..3e32336d8fca 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -49,10 +49,10 @@ impl MachineStopType for ConstEvalErrKind { | WriteThroughImmutablePointer => {} AssertFailure(kind) => kind.add_args(adder), Panic { msg, line, col, file } => { - adder("msg".into(), msg.into_diag_arg()); - adder("file".into(), file.into_diag_arg()); - adder("line".into(), line.into_diag_arg()); - adder("col".into(), col.into_diag_arg()); + adder("msg".into(), msg.into_diag_arg(&mut None)); + adder("file".into(), file.into_diag_arg(&mut None)); + adder("line".into(), line.into_diag_arg(&mut None)); + adder("col".into(), col.into_diag_arg(&mut None)); } } } diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index c08495c012f8..ef756e58c5e0 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -967,7 +967,7 @@ impl ReportErrorExt for ResourceExhaustionInfo { } impl rustc_errors::IntoDiagArg for InternKind { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(match self { InternKind::Static(Mutability::Not) => "static", InternKind::Static(Mutability::Mut) => "static_mut", diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 29a74ed3f4e4..97daf891b0fe 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -148,11 +148,11 @@ where /// converted rather than on `DiagArgValue`, which enables types from other `rustc_*` crates to /// implement this. pub trait IntoDiagArg { - fn into_diag_arg(self) -> DiagArgValue; + fn into_diag_arg(self, path: &mut Option) -> DiagArgValue; } impl IntoDiagArg for DiagArgValue { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { self } } @@ -395,7 +395,7 @@ impl DiagInner { } pub(crate) fn arg(&mut self, name: impl Into, arg: impl IntoDiagArg) { - self.args.insert(name.into(), arg.into_diag_arg()); + self.args.insert(name.into(), arg.into_diag_arg(&mut self.long_ty_path)); } /// Fields used for Hash, and PartialEq trait. diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index db6532f41eab..e0c8caf1317e 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -25,8 +25,8 @@ use crate::{ pub struct DiagArgFromDisplay<'a>(pub &'a dyn fmt::Display); impl IntoDiagArg for DiagArgFromDisplay<'_> { - fn into_diag_arg(self) -> DiagArgValue { - self.0.to_string().into_diag_arg() + fn into_diag_arg(self, path: &mut Option) -> DiagArgValue { + self.0.to_string().into_diag_arg(path) } } @@ -43,8 +43,8 @@ impl<'a, T: fmt::Display> From<&'a T> for DiagArgFromDisplay<'a> { } impl<'a, T: Clone + IntoDiagArg> IntoDiagArg for &'a T { - fn into_diag_arg(self) -> DiagArgValue { - self.clone().into_diag_arg() + fn into_diag_arg(self, path: &mut Option) -> DiagArgValue { + self.clone().into_diag_arg(path) } } @@ -53,8 +53,8 @@ macro_rules! into_diag_arg_using_display { ($( $ty:ty ),+ $(,)?) => { $( impl IntoDiagArg for $ty { - fn into_diag_arg(self) -> DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, path: &mut Option) -> DiagArgValue { + self.to_string().into_diag_arg(path) } } )+ @@ -65,13 +65,13 @@ macro_rules! into_diag_arg_for_number { ($( $ty:ty ),+ $(,)?) => { $( impl IntoDiagArg for $ty { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, path: &mut Option) -> DiagArgValue { // Convert to a string if it won't fit into `Number`. #[allow(irrefutable_let_patterns)] if let Ok(n) = TryInto::::try_into(self) { DiagArgValue::Number(n) } else { - self.to_string().into_diag_arg() + self.to_string().into_diag_arg(path) } } } @@ -104,26 +104,26 @@ impl IntoDiagArg for RustcVersion { } impl IntoDiagArg for rustc_type_ir::TraitRef { - fn into_diag_arg(self) -> DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, path: &mut Option) -> DiagArgValue { + self.to_string().into_diag_arg(path) } } impl IntoDiagArg for rustc_type_ir::ExistentialTraitRef { - fn into_diag_arg(self) -> DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, path: &mut Option) -> DiagArgValue { + self.to_string().into_diag_arg(path) } } impl IntoDiagArg for rustc_type_ir::UnevaluatedConst { - fn into_diag_arg(self) -> DiagArgValue { - format!("{self:?}").into_diag_arg() + fn into_diag_arg(self, path: &mut Option) -> DiagArgValue { + format!("{self:?}").into_diag_arg(path) } } impl IntoDiagArg for rustc_type_ir::FnSig { - fn into_diag_arg(self) -> DiagArgValue { - format!("{self:?}").into_diag_arg() + fn into_diag_arg(self, path: &mut Option) -> DiagArgValue { + format!("{self:?}").into_diag_arg(path) } } @@ -131,15 +131,15 @@ impl IntoDiagArg for rustc_type_ir::Binder where T: IntoDiagArg, { - fn into_diag_arg(self) -> DiagArgValue { - self.skip_binder().into_diag_arg() + fn into_diag_arg(self, path: &mut Option) -> DiagArgValue { + self.skip_binder().into_diag_arg(path) } } into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize); impl IntoDiagArg for bool { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { if self { DiagArgValue::Str(Cow::Borrowed("true")) } else { @@ -149,13 +149,13 @@ impl IntoDiagArg for bool { } impl IntoDiagArg for char { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(format!("{self:?}"))) } } impl IntoDiagArg for Vec { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::StrListSepByAnd( self.into_iter().map(|c| Cow::Owned(format!("{c:?}"))).collect(), ) @@ -163,49 +163,49 @@ impl IntoDiagArg for Vec { } impl IntoDiagArg for Symbol { - fn into_diag_arg(self) -> DiagArgValue { - self.to_ident_string().into_diag_arg() + fn into_diag_arg(self, path: &mut Option) -> DiagArgValue { + self.to_ident_string().into_diag_arg(path) } } impl<'a> IntoDiagArg for &'a str { - fn into_diag_arg(self) -> DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, path: &mut Option) -> DiagArgValue { + self.to_string().into_diag_arg(path) } } impl IntoDiagArg for String { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self)) } } impl<'a> IntoDiagArg for Cow<'a, str> { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self.into_owned())) } } impl<'a> IntoDiagArg for &'a Path { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self.display().to_string())) } } impl IntoDiagArg for PathBuf { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self.display().to_string())) } } impl IntoDiagArg for PanicStrategy { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self.desc().to_string())) } } impl IntoDiagArg for hir::ConstContext { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(match self { hir::ConstContext::ConstFn => "const_fn", hir::ConstContext::Static(_) => "static", @@ -215,49 +215,49 @@ impl IntoDiagArg for hir::ConstContext { } impl IntoDiagArg for ast::Expr { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(pprust::expr_to_string(&self))) } } impl IntoDiagArg for ast::Path { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(pprust::path_to_string(&self))) } } impl IntoDiagArg for ast::token::Token { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(pprust::token_to_string(&self)) } } impl IntoDiagArg for ast::token::TokenKind { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(pprust::token_kind_to_string(&self)) } } impl IntoDiagArg for FloatTy { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(self.name_str())) } } impl IntoDiagArg for std::ffi::CString { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned())) } } impl IntoDiagArg for rustc_data_structures::small_c_str::SmallCStr { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned())) } } impl IntoDiagArg for ast::Visibility { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { let s = pprust::vis_to_string(&self); let s = s.trim_end().to_string(); DiagArgValue::Str(Cow::Owned(s)) @@ -265,49 +265,49 @@ impl IntoDiagArg for ast::Visibility { } impl IntoDiagArg for rustc_lint_defs::Level { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(self.to_cmd_flag())) } } impl IntoDiagArg for hir::def::Res { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(self.descr())) } } impl IntoDiagArg for DiagLocation { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::from(self.to_string())) } } impl IntoDiagArg for Backtrace { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::from(self.to_string())) } } impl IntoDiagArg for Level { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::from(self.to_string())) } } impl IntoDiagArg for ClosureKind { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(self.as_str().into()) } } impl IntoDiagArg for hir::def::Namespace { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(self.descr())) } } impl IntoDiagArg for ExprPrecedence { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Number(self as i32) } } @@ -328,7 +328,7 @@ impl FromIterator for DiagSymbolList { } impl IntoDiagArg for DiagSymbolList { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::StrListSepByAnd( self.0.into_iter().map(|sym| Cow::Owned(format!("`{sym}`"))).collect(), ) diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index a994b31aeb43..291c61fb0f62 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -112,7 +112,11 @@ hir_typeck_int_to_fat = cannot cast `{$expr_ty}` to a pointer that {$known_wide hir_typeck_int_to_fat_label = creating a `{$cast_ty}` requires both an address and {$metadata} hir_typeck_int_to_fat_label_nightly = consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` -hir_typeck_invalid_callee = expected function, found {$ty} +hir_typeck_invalid_callee = expected function, found {$found} +hir_typeck_invalid_defined = `{$path}` defined here +hir_typeck_invalid_defined_kind = {$kind} `{$path}` defined here +hir_typeck_invalid_fn_defined = `{$func}` defined here returns `{$ty}` +hir_typeck_invalid_local = `{$local_name}` has type `{$ty}` hir_typeck_lossy_provenance_int2ptr = strict provenance disallows casting integer `{$expr_ty}` to pointer `{$cast_ty}` diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index d18869b6d90c..5e00161f693f 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -23,7 +23,7 @@ use tracing::{debug, instrument}; use super::method::MethodCallee; use super::method::probe::ProbeScope; use super::{Expectation, FnCtxt, TupleArgumentsFlag}; -use crate::errors; +use crate::{errors, fluent_generated}; /// Checks that it is legal to call methods of the trait corresponding /// to `trait_id` (this only cares about the trait, not the specific @@ -674,13 +674,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let callee_ty = self.resolve_vars_if_possible(callee_ty); + let mut path = None; let mut err = self.dcx().create_err(errors::InvalidCallee { span: callee_expr.span, - ty: match &unit_variant { + ty: callee_ty, + found: match &unit_variant { Some((_, kind, path)) => format!("{kind} `{path}`"), - None => format!("`{callee_ty}`"), + None => format!("`{}`", self.tcx.short_string(callee_ty, &mut path)), }, }); + *err.long_ty_path() = path; if callee_ty.references_error() { err.downgrade_to_delayed_bug(); } @@ -780,27 +783,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(span) = self.tcx.hir().res_span(def) { let callee_ty = callee_ty.to_string(); let label = match (unit_variant, inner_callee_path) { - (Some((_, kind, path)), _) => Some(format!("{kind} `{path}` defined here")), - (_, Some(hir::QPath::Resolved(_, path))) => self - .tcx - .sess - .source_map() - .span_to_snippet(path.span) - .ok() - .map(|p| format!("`{p}` defined here returns `{callee_ty}`")), + (Some((_, kind, path)), _) => { + err.arg("kind", kind); + err.arg("path", path); + Some(fluent_generated::hir_typeck_invalid_defined_kind) + } + (_, Some(hir::QPath::Resolved(_, path))) => { + self.tcx.sess.source_map().span_to_snippet(path.span).ok().map(|p| { + err.arg("func", p); + fluent_generated::hir_typeck_invalid_fn_defined + }) + } _ => { match def { // Emit a different diagnostic for local variables, as they are not // type definitions themselves, but rather variables *of* that type. - Res::Local(hir_id) => Some(format!( - "`{}` has type `{}`", - self.tcx.hir().name(hir_id), - callee_ty - )), + Res::Local(hir_id) => { + err.arg("local_name", self.tcx.hir().name(hir_id)); + Some(fluent_generated::hir_typeck_invalid_local) + } Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => { - Some(format!("`{}` defined here", self.tcx.def_path_str(def_id),)) + err.arg("path", self.tcx.def_path_str(def_id)); + Some(fluent_generated::hir_typeck_invalid_defined) + } + _ => { + err.arg("path", callee_ty); + Some(fluent_generated::hir_typeck_invalid_defined) } - _ => Some(format!("`{callee_ty}` defined here")), } } }; diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index f5f6ada12c3c..462983be88d8 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -548,17 +548,19 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.emit(); } CastError::SizedUnsizedCast => { + let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty); + let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); fcx.dcx().emit_err(errors::CastThinPointerToWidePointer { span: self.span, - expr_ty: self.expr_ty, - cast_ty: fcx.ty_to_string(self.cast_ty), + expr_ty, + cast_ty, teach: fcx.tcx.sess.teach(E0607), }); } CastError::IntToWideCast(known_metadata) => { let expr_if_nightly = fcx.tcx.sess.is_nightly_build().then_some(self.expr_span); let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty); - let expr_ty = fcx.ty_to_string(self.expr_ty); + let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); let metadata = known_metadata.unwrap_or("type-specific metadata"); let known_wide = known_metadata.is_some(); let span = self.cast_span; @@ -1164,10 +1166,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { if let Some((deref_ty, _)) = derefed { // Give a note about what the expr derefs to. if deref_ty != self.expr_ty.peel_refs() { - err.subdiagnostic(errors::DerefImplsIsEmpty { - span: self.expr_span, - deref_ty: fcx.ty_to_string(deref_ty), - }); + err.subdiagnostic(errors::DerefImplsIsEmpty { span: self.expr_span, deref_ty }); } // Create a multipart suggestion: add `!` and `.is_empty()` in @@ -1175,7 +1174,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.subdiagnostic(errors::UseIsEmpty { lo: self.expr_span.shrink_to_lo(), hi: self.span.with_lo(self.expr_span.hi()), - expr_ty: fcx.ty_to_string(self.expr_ty), + expr_ty: self.expr_ty, }); } } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 1bf8aa4f78d4..4347c5a92770 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -91,7 +91,7 @@ pub(crate) enum ReturnLikeStatementKind { } impl IntoDiagArg for ReturnLikeStatementKind { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { let kind = match self { Self::Return => "return", Self::Become => "become", @@ -456,10 +456,11 @@ impl HelpUseLatestEdition { #[derive(Diagnostic)] #[diag(hir_typeck_invalid_callee, code = E0618)] -pub(crate) struct InvalidCallee { +pub(crate) struct InvalidCallee<'tcx> { #[primary_span] pub span: Span, - pub ty: String, + pub ty: Ty<'tcx>, + pub found: String, } #[derive(Diagnostic)] @@ -469,7 +470,7 @@ pub(crate) struct IntToWide<'tcx> { #[label(hir_typeck_int_to_fat_label)] pub span: Span, pub metadata: &'tcx str, - pub expr_ty: String, + pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, #[label(hir_typeck_int_to_fat_label_nightly)] pub expr_if_nightly: Option, @@ -581,12 +582,12 @@ pub(crate) struct UnionPatDotDot { applicability = "maybe-incorrect", style = "verbose" )] -pub(crate) struct UseIsEmpty { +pub(crate) struct UseIsEmpty<'tcx> { #[suggestion_part(code = "!")] pub lo: Span, #[suggestion_part(code = ".is_empty()")] pub hi: Span, - pub expr_ty: String, + pub expr_ty: Ty<'tcx>, } #[derive(Diagnostic)] @@ -745,10 +746,10 @@ pub(crate) struct CtorIsPrivate { #[derive(Subdiagnostic)] #[note(hir_typeck_deref_is_empty)] -pub(crate) struct DerefImplsIsEmpty { +pub(crate) struct DerefImplsIsEmpty<'tcx> { #[primary_span] pub span: Span, - pub deref_ty: String, + pub deref_ty: Ty<'tcx>, } #[derive(Subdiagnostic)] @@ -826,7 +827,7 @@ pub(crate) struct CastThinPointerToWidePointer<'tcx> { #[primary_span] pub span: Span, pub expr_ty: Ty<'tcx>, - pub cast_ty: String, + pub cast_ty: Ty<'tcx>, #[note(hir_typeck_teach_help)] pub(crate) teach: bool, } diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 3f3e58384cbf..d5dd5059aacc 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -290,7 +290,7 @@ impl fmt::Display for CrateFlavor { } impl IntoDiagArg for CrateFlavor { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> rustc_errors::DiagArgValue { match self { CrateFlavor::Rlib => DiagArgValue::Str(Cow::Borrowed("rlib")), CrateFlavor::Rmeta => DiagArgValue::Str(Cow::Borrowed("rmeta")), diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index be8a3403ba95..bd315577efb5 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -47,10 +47,10 @@ pub struct UnsupportedUnion { // FIXME(autodiff): I should get used somewhere #[derive(Diagnostic)] #[diag(middle_autodiff_unsafe_inner_const_ref)] -pub struct AutodiffUnsafeInnerConstRef { +pub struct AutodiffUnsafeInnerConstRef<'tcx> { #[primary_span] pub span: Span, - pub ty: String, + pub ty: Ty<'tcx>, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 743812e3a20a..890756a17cae 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -248,7 +248,7 @@ pub enum InvalidMetaKind { } impl IntoDiagArg for InvalidMetaKind { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(match self { InvalidMetaKind::SliceTooBig => "slice_too_big", InvalidMetaKind::TooBig => "too_big", @@ -282,7 +282,7 @@ pub struct Misalignment { macro_rules! impl_into_diag_arg_through_debug { ($($ty:ty),*$(,)?) => {$( impl IntoDiagArg for $ty { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(format!("{self:?}"))) } } @@ -401,7 +401,7 @@ pub enum PointerKind { } impl IntoDiagArg for PointerKind { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str( match self { Self::Ref(_) => "ref", @@ -666,7 +666,7 @@ macro_rules! err_ub_custom { msg: || $msg, add_args: Box::new(move |mut set_arg| { $($( - set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name)); + set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name, &mut None)); )*)? }) } diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index b887370fd699..bc77f22af67b 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -357,7 +357,7 @@ impl AssertKind { macro_rules! add { ($name: expr, $value: expr) => { - adder($name.into(), $value.into_diag_arg()); + adder($name.into(), $value.into_diag_arg(&mut None)); }; } diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index b72edc1c5325..7c9280fae16d 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -118,7 +118,7 @@ impl std::fmt::Debug for ConstInt { impl IntoDiagArg for ConstInt { // FIXME this simply uses the Debug impl, but we could probably do better by converting both // to an inherent method that returns `Cow`. - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(format!("{self:?}").into()) } } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index cb218a27e623..881381a5ee61 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -19,8 +19,16 @@ use crate::ty::{ TypeSuperVisitable, TypeVisitable, TypeVisitor, }; +impl IntoDiagArg for Ty<'_> { + fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { + ty::tls::with(|tcx| { + let ty = tcx.short_string(self, path); + rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(ty)) + }) + } +} + into_diag_arg_using_display! { - Ty<'_>, ty::Region<'_>, } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 8c1991ddb36e..a0e67929c528 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -213,10 +213,9 @@ impl<'tcx> Ty<'tcx> { } impl<'tcx> TyCtxt<'tcx> { - pub fn string_with_limit<'a, T>(self, p: T, length_limit: usize) -> String + pub fn string_with_limit(self, p: T, length_limit: usize) -> String where - T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift> + Copy, - >>::Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>, + T: Copy + for<'a, 'b> Lift, Lifted: Print<'b, FmtPrinter<'a, 'b>>>, { let mut type_limit = 50; let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| { @@ -253,10 +252,9 @@ impl<'tcx> TyCtxt<'tcx> { /// `tcx.short_string(ty, diag.long_ty_path())`. The diagnostic itself is the one that keeps /// the existence of a "long type" anywhere in the diagnostic, so the note telling the user /// where we wrote the file to is only printed once. - pub fn short_string<'a, T>(self, p: T, path: &mut Option) -> String + pub fn short_string(self, p: T, path: &mut Option) -> String where - T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift> + Copy + Hash, - >>::Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>, + T: Copy + Hash + for<'a, 'b> Lift, Lifted: Print<'b, FmtPrinter<'a, 'b>>>, { let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| { self.lift(p).expect("could not lift for printing").print(cx) diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index ed0b3059d752..27576a2ec4a2 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -159,8 +159,8 @@ unsafe impl<'tcx> Sync for GenericArg<'tcx> where } impl<'tcx> IntoDiagArg for GenericArg<'tcx> { - fn into_diag_arg(self) -> DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { + self.to_string().into_diag_arg(&mut None) } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index eb14ed20fbac..272bb0cc915f 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -315,8 +315,8 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { } impl<'tcx> IntoDiagArg for LayoutError<'tcx> { - fn into_diag_arg(self) -> DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { + self.to_string().into_diag_arg(&mut None) } } diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 553de83dfcb4..de6d30a89d47 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -158,15 +158,21 @@ impl<'tcx> Predicate<'tcx> { } } -impl rustc_errors::IntoDiagArg for Predicate<'_> { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { - rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(self.to_string())) +impl<'tcx> rustc_errors::IntoDiagArg for Predicate<'tcx> { + fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { + ty::tls::with(|tcx| { + let pred = tcx.short_string(self, path); + rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(pred)) + }) } } -impl rustc_errors::IntoDiagArg for Clause<'_> { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { - rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(self.to_string())) +impl<'tcx> rustc_errors::IntoDiagArg for Clause<'tcx> { + fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { + ty::tls::with(|tcx| { + let clause = tcx.short_string(self, path); + rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(clause)) + }) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ed0839f47e69..942411945bfe 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2898,12 +2898,15 @@ where /// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only /// the trait path. That is, it will print `Trait` instead of /// `>`. -#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)] pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>); impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintOnlyTraitPath<'tcx> { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { + ty::tls::with(|tcx| { + let trait_ref = tcx.short_string(self, path); + rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(trait_ref)) + }) } } @@ -2915,12 +2918,15 @@ impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { /// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only /// the trait path, and additionally tries to "sugar" `Fn(...)` trait bounds. -#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)] pub struct TraitRefPrintSugared<'tcx>(ty::TraitRef<'tcx>); impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintSugared<'tcx> { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { + ty::tls::with(|tcx| { + let trait_ref = tcx.short_string(self, path); + rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(trait_ref)) + }) } } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index f1753be845d4..17b22f25dbb0 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -828,7 +828,7 @@ pub(crate) struct IrrefutableLetPatternsWhileLet { #[derive(Diagnostic)] #[diag(mir_build_borrow_of_moved_value)] -pub(crate) struct BorrowOfMovedValue { +pub(crate) struct BorrowOfMovedValue<'tcx> { #[primary_span] #[label] #[label(mir_build_occurs_because_label)] @@ -836,7 +836,7 @@ pub(crate) struct BorrowOfMovedValue { #[label(mir_build_value_borrowed_label)] pub(crate) conflicts_ref: Vec, pub(crate) name: Ident, - pub(crate) ty: String, + pub(crate) ty: Ty<'tcx>, #[suggestion(code = "ref ", applicability = "machine-applicable")] pub(crate) suggest_borrowing: Option, } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index d60ae6484afb..954d0cf97abe 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -786,17 +786,13 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: } }); if !conflicts_ref.is_empty() { - let mut path = None; - let ty = cx.tcx.short_string(ty, &mut path); - let mut err = sess.dcx().create_err(BorrowOfMovedValue { + sess.dcx().emit_err(BorrowOfMovedValue { binding_span: pat.span, conflicts_ref, name: Ident::new(name, pat.span), ty, suggest_borrowing: Some(pat.span.shrink_to_lo()), }); - *err.long_ty_path() = path; - err.emit(); } return; } diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index dc03d6f9521d..173c68b3a722 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -772,7 +772,6 @@ pub(crate) struct LabeledLoopInBreak { } #[derive(Subdiagnostic)] - pub(crate) enum WrapInParentheses { #[multipart_suggestion( parse_sugg_wrap_expression_in_parentheses, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9be868122872..5ada289cc209 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -80,13 +80,13 @@ pub(crate) enum ProcMacroKind { } impl IntoDiagArg for ProcMacroKind { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> rustc_errors::DiagArgValue { match self { ProcMacroKind::Attribute => "attribute proc macro", ProcMacroKind::Derive => "derive proc macro", ProcMacroKind::FunctionLike => "function-like proc macro", } - .into_diag_arg() + .into_diag_arg(&mut None) } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 5f686f38babd..51b5861ee0ae 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1005,10 +1005,10 @@ pub(crate) struct LayoutHomogeneousAggregate { #[derive(Diagnostic)] #[diag(passes_layout_of)] -pub(crate) struct LayoutOf { +pub(crate) struct LayoutOf<'tcx> { #[primary_span] pub span: Span, - pub normalized_ty: String, + pub normalized_ty: Ty<'tcx>, pub ty_layout: String, } diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index 1133cf93304d..d4512c9417eb 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -112,8 +112,7 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { } sym::debug => { - let normalized_ty = - format!("{}", tcx.normalize_erasing_regions(typing_env, ty)); + let normalized_ty = tcx.normalize_erasing_regions(typing_env, ty); // FIXME: using the `Debug` impl here isn't ideal. let ty_layout = format!("{:#?}", *ty_layout); tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout }); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index ad9c3465f0cc..32ef781631be 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -94,7 +94,7 @@ impl PatternSource { } impl IntoDiagArg for PatternSource { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(self.descr())) } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 8f0b17b5e887..ba7ccd6a02da 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2807,8 +2807,8 @@ impl fmt::Display for CrateType { } impl IntoDiagArg for CrateType { - fn into_diag_arg(self) -> DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { + self.to_string().into_diag_arg(&mut None) } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 8e5ff1d3bc48..ecdf76d22fb2 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -109,8 +109,8 @@ impl Mul for Limit { } impl rustc_errors::IntoDiagArg for Limit { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, _: &mut Option) -> rustc_errors::DiagArgValue { + self.to_string().into_diag_arg(&mut None) } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index a618bae269fa..847bd06bb017 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -2418,7 +2418,7 @@ impl<'tcx> ObligationCause<'tcx> { pub struct ObligationCauseAsDiagArg<'tcx>(pub ObligationCause<'tcx>); impl IntoDiagArg for ObligationCauseAsDiagArg<'_> { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> rustc_errors::DiagArgValue { let kind = match self.0.code() { ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => "method_compat", ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => "type_compat", diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index bed9734f389c..a6d8eb6add7d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -137,7 +137,7 @@ impl InferenceDiagnosticsParentData { } impl IntoDiagArg for UnderspecifiedArgKind { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> rustc_errors::DiagArgValue { let kind = match self { Self::Type { .. } => "type", Self::Const { is_parameter: true } => "const_with_param", diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index aaaefd81d19b..5056161e117e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -31,7 +31,7 @@ impl<'tcx, T> IntoDiagArg for Highlighted<'tcx, T> where T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>, { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> rustc_errors::DiagArgValue { rustc_errors::DiagArgValue::Str(self.to_string().into()) } } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 23aa38006604..fe859eb53cd7 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -784,10 +784,10 @@ pub enum TyOrSig<'tcx> { } impl IntoDiagArg for TyOrSig<'_> { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { match self { - TyOrSig::Ty(ty) => ty.into_diag_arg(), - TyOrSig::ClosureSig(sig) => sig.into_diag_arg(), + TyOrSig::Ty(ty) => ty.into_diag_arg(path), + TyOrSig::ClosureSig(sig) => sig.into_diag_arg(path), } } } diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs index 4601ddf678a0..46622246a178 100644 --- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs @@ -105,7 +105,7 @@ pub enum SuffixKind { } impl IntoDiagArg for PrefixKind { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> rustc_errors::DiagArgValue { let kind = match self { Self::Empty => "empty", Self::RefValidFor => "ref_valid_for", @@ -127,7 +127,7 @@ impl IntoDiagArg for PrefixKind { } impl IntoDiagArg for SuffixKind { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> rustc_errors::DiagArgValue { let kind = match self { Self::Empty => "empty", Self::Continues => "continues", diff --git a/tests/ui/diagnostic-width/long-E0618.rs b/tests/ui/diagnostic-width/long-E0618.rs new file mode 100644 index 000000000000..f8626ab9455e --- /dev/null +++ b/tests/ui/diagnostic-width/long-E0618.rs @@ -0,0 +1,13 @@ +//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes +// The regex below normalizes the long type file name to make it suitable for compare-modes. +//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'" +type A = (i32, i32, i32, i32); +type B = (A, A, A, A); +type C = (B, B, B, B); +type D = (C, C, C, C); + +fn foo(x: D) { //~ `x` has type `(... + x(); //~ ERROR expected function, found `(... +} + +fn main() {} diff --git a/tests/ui/diagnostic-width/long-E0618.stderr b/tests/ui/diagnostic-width/long-E0618.stderr new file mode 100644 index 000000000000..f0838cbddcc6 --- /dev/null +++ b/tests/ui/diagnostic-width/long-E0618.stderr @@ -0,0 +1,16 @@ +error[E0618]: expected function, found `(..., ..., ..., ...)` + --> $DIR/long-E0618.rs:10:5 + | +LL | fn foo(x: D) { + | - `x` has type `(..., ..., ..., ...)` +LL | x(); + | ^-- + | | + | call expression requires function + | + = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + = note: consider using `--verbose` to print the full type name to the console + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0618`. From 693ed264cee6844006dc9e30295ba176a3e819b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2025 01:16:16 +0000 Subject: [PATCH 2/7] Add tests --- tests/ui/diagnostic-width/long-E0529.rs | 14 ++++++++++++++ tests/ui/diagnostic-width/long-E0529.stderr | 9 +++++++++ tests/ui/diagnostic-width/long-E0609.rs | 13 +++++++++++++ tests/ui/diagnostic-width/long-E0609.stderr | 9 +++++++++ tests/ui/diagnostic-width/long-E0614.rs | 13 +++++++++++++ tests/ui/diagnostic-width/long-E0614.stderr | 9 +++++++++ 6 files changed, 67 insertions(+) create mode 100644 tests/ui/diagnostic-width/long-E0529.rs create mode 100644 tests/ui/diagnostic-width/long-E0529.stderr create mode 100644 tests/ui/diagnostic-width/long-E0609.rs create mode 100644 tests/ui/diagnostic-width/long-E0609.stderr create mode 100644 tests/ui/diagnostic-width/long-E0614.rs create mode 100644 tests/ui/diagnostic-width/long-E0614.stderr diff --git a/tests/ui/diagnostic-width/long-E0529.rs b/tests/ui/diagnostic-width/long-E0529.rs new file mode 100644 index 000000000000..2ebc21f51ef3 --- /dev/null +++ b/tests/ui/diagnostic-width/long-E0529.rs @@ -0,0 +1,14 @@ +//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes +// The regex below normalizes the long type file name to make it suitable for compare-modes. +//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'" +type A = (i32, i32, i32, i32); +type B = (A, A, A, A); +type C = (B, B, B, B); +type D = (C, C, C, C); + +fn foo(x: D) { + let [] = x; //~ ERROR expected an array or slice, found `( + //~^ pattern cannot match with input type `( +} + +fn main() {} diff --git a/tests/ui/diagnostic-width/long-E0529.stderr b/tests/ui/diagnostic-width/long-E0529.stderr new file mode 100644 index 000000000000..8dcd4fa6b382 --- /dev/null +++ b/tests/ui/diagnostic-width/long-E0529.stderr @@ -0,0 +1,9 @@ +error[E0529]: expected an array or slice, found `((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))` + --> $DIR/long-E0529.rs:10:9 + | +LL | let [] = x; + | ^^ pattern cannot match with input type `((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0529`. diff --git a/tests/ui/diagnostic-width/long-E0609.rs b/tests/ui/diagnostic-width/long-E0609.rs new file mode 100644 index 000000000000..ae57e4f76d2f --- /dev/null +++ b/tests/ui/diagnostic-width/long-E0609.rs @@ -0,0 +1,13 @@ +//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes +// The regex below normalizes the long type file name to make it suitable for compare-modes. +//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'" +type A = (i32, i32, i32, i32); +type B = (A, A, A, A); +type C = (B, B, B, B); +type D = (C, C, C, C); + +fn foo(x: D) { + x.field; //~ ERROR no field `field` on type `( +} + +fn main() {} diff --git a/tests/ui/diagnostic-width/long-E0609.stderr b/tests/ui/diagnostic-width/long-E0609.stderr new file mode 100644 index 000000000000..708cd4ef93a8 --- /dev/null +++ b/tests/ui/diagnostic-width/long-E0609.stderr @@ -0,0 +1,9 @@ +error[E0609]: no field `field` on type `((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))` + --> $DIR/long-E0609.rs:10:7 + | +LL | x.field; + | ^^^^^ unknown field + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/diagnostic-width/long-E0614.rs b/tests/ui/diagnostic-width/long-E0614.rs new file mode 100644 index 000000000000..35129c909da4 --- /dev/null +++ b/tests/ui/diagnostic-width/long-E0614.rs @@ -0,0 +1,13 @@ +//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes +// The regex below normalizes the long type file name to make it suitable for compare-modes. +//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'" +type A = (i32, i32, i32, i32); +type B = (A, A, A, A); +type C = (B, B, B, B); +type D = (C, C, C, C); + +fn foo(x: D) { + *x; //~ ERROR type `( +} + +fn main() {} diff --git a/tests/ui/diagnostic-width/long-E0614.stderr b/tests/ui/diagnostic-width/long-E0614.stderr new file mode 100644 index 000000000000..6bbfbad57f23 --- /dev/null +++ b/tests/ui/diagnostic-width/long-E0614.stderr @@ -0,0 +1,9 @@ +error[E0614]: type `((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))` cannot be dereferenced + --> $DIR/long-E0614.rs:10:5 + | +LL | *x; + | ^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0614`. From ae3a825faa5dbcba6a223d0d225fd5535bf5f014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2025 01:39:08 +0000 Subject: [PATCH 3/7] Make E0529 a structured error --- compiler/rustc_hir_typeck/messages.ftl | 6 ++++ compiler/rustc_hir_typeck/src/errors.rs | 38 +++++++++++++++++++++ compiler/rustc_hir_typeck/src/pat.rs | 34 +++++++----------- tests/ui/diagnostic-width/long-E0529.rs | 4 +-- tests/ui/diagnostic-width/long-E0529.stderr | 7 ++-- 5 files changed, 64 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 291c61fb0f62..9c1f1bb91be5 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -10,6 +10,7 @@ hir_typeck_address_of_temporary_taken = cannot take address of a temporary hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where .note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new +hir_typeck_as_deref_suggestion = consider using `as_deref` here hir_typeck_base_expression_double_dot = base expression required after `..` hir_typeck_base_expression_double_dot_add_expr = add a base expression here hir_typeck_base_expression_double_dot_enable_default_field_values = @@ -72,6 +73,9 @@ hir_typeck_dependency_on_unit_never_type_fallback = this function depends on nev hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty` +hir_typeck_expected_array_or_slice = expected an array or slice, found `{$ty}` +hir_typeck_expected_array_or_slice_label = pattern cannot match with input type `{$ty}` + hir_typeck_expected_default_return_type = expected `()` because of default return type hir_typeck_expected_return_type = expected `{$expected}` because of return type @@ -187,6 +191,8 @@ hir_typeck_self_ctor_from_outer_item = can't reference `Self` constructor from o .label = the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference .suggestion = replace `Self` with the actual type +hir_typeck_slicing_suggestion = consider slicing here + hir_typeck_struct_expr_non_exhaustive = cannot create non-exhaustive {$what} using struct expression diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 4347c5a92770..335ac1c57a71 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -454,6 +454,44 @@ impl HelpUseLatestEdition { } } +#[derive(Diagnostic)] +#[diag(hir_typeck_expected_array_or_slice, code = E0529)] +pub(crate) struct ExpectedArrayOrSlice<'tcx> { + #[primary_span] + #[label(hir_typeck_expected_array_or_slice_label)] + pub(crate) span: Span, + pub(crate) ty: Ty<'tcx>, + pub(crate) slice_pat_semantics: bool, + #[subdiagnostic] + pub(crate) as_deref: Option, + #[subdiagnostic] + pub(crate) slicing: Option, +} + +#[derive(Subdiagnostic)] +#[suggestion( + hir_typeck_as_deref_suggestion, + code = ".as_deref()", + style = "verbose", + applicability = "maybe-incorrect" +)] +pub(crate) struct AsDerefSuggestion { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion( + hir_typeck_slicing_suggestion, + code = "[..]", + style = "verbose", + applicability = "maybe-incorrect" +)] +pub(crate) struct SlicingSuggestion { + #[primary_span] + pub(crate) span: Span, +} + #[derive(Diagnostic)] #[diag(hir_typeck_invalid_callee, code = E0618)] pub(crate) struct InvalidCallee<'tcx> { diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index bd0848b99166..19ae3e3899c9 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2771,16 +2771,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> ErrorGuaranteed { let PatInfo { top_info: ti, current_depth, .. } = pat_info; - let mut err = struct_span_code_err!( - self.dcx(), - span, - E0529, - "expected an array or slice, found `{expected_ty}`" - ); + let mut slice_pat_semantics = false; + let mut as_deref = None; + let mut slicing = None; if let ty::Ref(_, ty, _) = expected_ty.kind() && let ty::Array(..) | ty::Slice(..) = ty.kind() { - err.help("the semantics of slice patterns changed recently; see issue #62254"); + slice_pat_semantics = true; } else if self .autoderef(span, expected_ty) .silence_errors() @@ -2797,28 +2794,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) => { // Slicing won't work here, but `.as_deref()` might (issue #91328). - err.span_suggestion_verbose( - span.shrink_to_hi(), - "consider using `as_deref` here", - ".as_deref()", - Applicability::MaybeIncorrect, - ); + as_deref = Some(errors::AsDerefSuggestion { span: span.shrink_to_hi() }); } _ => (), } let is_top_level = current_depth <= 1; if is_slice_or_array_or_vector && is_top_level { - err.span_suggestion_verbose( - span.shrink_to_hi(), - "consider slicing here", - "[..]", - Applicability::MachineApplicable, - ); + slicing = Some(errors::SlicingSuggestion { span: span.shrink_to_hi() }); } } - err.span_label(span, format!("pattern cannot match with input type `{expected_ty}`")); - err.emit() + self.dcx().emit_err(errors::ExpectedArrayOrSlice { + span, + ty: expected_ty, + slice_pat_semantics, + as_deref, + slicing, + }) } fn is_slice_or_array_or_vector(&self, ty: Ty<'tcx>) -> (bool, Ty<'tcx>) { diff --git a/tests/ui/diagnostic-width/long-E0529.rs b/tests/ui/diagnostic-width/long-E0529.rs index 2ebc21f51ef3..3ebc4f5f8c82 100644 --- a/tests/ui/diagnostic-width/long-E0529.rs +++ b/tests/ui/diagnostic-width/long-E0529.rs @@ -7,8 +7,8 @@ type C = (B, B, B, B); type D = (C, C, C, C); fn foo(x: D) { - let [] = x; //~ ERROR expected an array or slice, found `( - //~^ pattern cannot match with input type `( + let [] = x; //~ ERROR expected an array or slice, found `(... + //~^ pattern cannot match with input type `(... } fn main() {} diff --git a/tests/ui/diagnostic-width/long-E0529.stderr b/tests/ui/diagnostic-width/long-E0529.stderr index 8dcd4fa6b382..da03e5fab2ca 100644 --- a/tests/ui/diagnostic-width/long-E0529.stderr +++ b/tests/ui/diagnostic-width/long-E0529.stderr @@ -1,8 +1,11 @@ -error[E0529]: expected an array or slice, found `((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))` +error[E0529]: expected an array or slice, found `(..., ..., ..., ...)` --> $DIR/long-E0529.rs:10:9 | LL | let [] = x; - | ^^ pattern cannot match with input type `((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))` + | ^^ pattern cannot match with input type `(..., ..., ..., ...)` + | + = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + = note: consider using `--verbose` to print the full type name to the console error: aborting due to 1 previous error From 7302dc660b997c882b3a250fb6a23f60259fbdf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2025 01:50:10 +0000 Subject: [PATCH 4/7] Make E0614 a structured error ``` error[E0614]: type `(..., ..., ..., ...)` cannot be dereferenced --> $DIR/long-E0614.rs:10:5 | LL | *x; | ^^ can't be dereferenced | = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' = note: consider using `--verbose` to print the full type name to the console ``` --- compiler/rustc_hir_typeck/messages.ftl | 3 +++ compiler/rustc_hir_typeck/src/errors.rs | 9 +++++++++ compiler/rustc_hir_typeck/src/expr.rs | 15 +++++---------- tests/ui/deref-non-pointer.stderr | 2 +- tests/ui/diagnostic-width/long-E0614.rs | 2 +- tests/ui/diagnostic-width/long-E0614.stderr | 7 +++++-- tests/ui/error-codes/E0614.stderr | 2 +- tests/ui/issues/issue-17373.stderr | 2 +- tests/ui/issues/issue-9814.stderr | 2 +- tests/ui/parser/expr-as-stmt.stderr | 2 +- .../nested-binding-modes-ref.stderr | 4 ++-- tests/ui/reachable/expr_unary.stderr | 2 +- .../ui/type/type-check/missing_trait_impl.stderr | 2 +- 13 files changed, 32 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 9c1f1bb91be5..1a75a2ec3152 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -28,6 +28,9 @@ hir_typeck_cannot_cast_to_bool = cannot cast `{$expr_ty}` as `bool` .help = compare with zero instead .label = unsupported cast +hir_typeck_cant_dereference = type `{$ty}` cannot be dereferenced +hir_typeck_cant_dereference_label = can't be dereferenced + hir_typeck_cast_enum_drop = cannot cast enum `{$expr_ty}` into integer `{$cast_ty}` because it implements `Drop` hir_typeck_cast_thin_pointer_to_wide_pointer = cannot cast thin pointer `{$expr_ty}` to wide pointer `{$cast_ty}` diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 335ac1c57a71..968bcee45cf4 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -454,6 +454,15 @@ impl HelpUseLatestEdition { } } +#[derive(Diagnostic)] +#[diag(hir_typeck_cant_dereference, code = E0614)] +pub(crate) struct CantDereference<'tcx> { + #[primary_span] + #[label(hir_typeck_cant_dereference_label)] + pub(crate) span: Span, + pub(crate) ty: Ty<'tcx>, +} + #[derive(Diagnostic)] #[diag(hir_typeck_expected_array_or_slice, code = E0529)] pub(crate) struct ExpectedArrayOrSlice<'tcx> { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 4815627a0ce0..a857a91834e6 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -45,9 +45,9 @@ use crate::coercion::{CoerceMany, DynamicCoerceMany}; use crate::errors::{ AddressOfTemporaryTaken, BaseExpressionDoubleDot, BaseExpressionDoubleDotAddExpr, BaseExpressionDoubleDotEnableDefaultFieldValues, BaseExpressionDoubleDotRemove, - FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition, - ReturnLikeStatementKind, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive, - TypeMismatchFruTypo, YieldExprOutsideOfCoroutine, + CantDereference, FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, + HelpUseLatestEdition, ReturnLikeStatementKind, ReturnStmtOutsideOfFnBody, + StructExprNonExhaustive, TypeMismatchFruTypo, YieldExprOutsideOfCoroutine, }; use crate::{ BreakableCtxt, CoroutineTypes, Diverges, FnCtxt, Needs, cast, fatally_break_rust, @@ -607,13 +607,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(ty) = self.lookup_derefing(expr, oprnd, oprnd_t) { oprnd_t = ty; } else { - let mut err = type_error_struct!( - self.dcx(), - expr.span, - oprnd_t, - E0614, - "type `{oprnd_t}` cannot be dereferenced", - ); + let mut err = + self.dcx().create_err(CantDereference { span: expr.span, ty: oprnd_t }); let sp = tcx.sess.source_map().start_point(expr.span).with_parent(None); if let Some(sp) = tcx.sess.psess.ambiguous_block_expr_parse.borrow().get(&sp) diff --git a/tests/ui/deref-non-pointer.stderr b/tests/ui/deref-non-pointer.stderr index 2e5e574fb6c7..3ee354819e5d 100644 --- a/tests/ui/deref-non-pointer.stderr +++ b/tests/ui/deref-non-pointer.stderr @@ -2,7 +2,7 @@ error[E0614]: type `{integer}` cannot be dereferenced --> $DIR/deref-non-pointer.rs:2:9 | LL | match *1 { - | ^^ + | ^^ can't be dereferenced error: aborting due to 1 previous error diff --git a/tests/ui/diagnostic-width/long-E0614.rs b/tests/ui/diagnostic-width/long-E0614.rs index 35129c909da4..0b78444a00d2 100644 --- a/tests/ui/diagnostic-width/long-E0614.rs +++ b/tests/ui/diagnostic-width/long-E0614.rs @@ -7,7 +7,7 @@ type C = (B, B, B, B); type D = (C, C, C, C); fn foo(x: D) { - *x; //~ ERROR type `( + *x; //~ ERROR type `(... } fn main() {} diff --git a/tests/ui/diagnostic-width/long-E0614.stderr b/tests/ui/diagnostic-width/long-E0614.stderr index 6bbfbad57f23..1c16ff617faa 100644 --- a/tests/ui/diagnostic-width/long-E0614.stderr +++ b/tests/ui/diagnostic-width/long-E0614.stderr @@ -1,8 +1,11 @@ -error[E0614]: type `((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))` cannot be dereferenced +error[E0614]: type `(..., ..., ..., ...)` cannot be dereferenced --> $DIR/long-E0614.rs:10:5 | LL | *x; - | ^^ + | ^^ can't be dereferenced + | + = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + = note: consider using `--verbose` to print the full type name to the console error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0614.stderr b/tests/ui/error-codes/E0614.stderr index ae7c2ce9a132..0bba0753980d 100644 --- a/tests/ui/error-codes/E0614.stderr +++ b/tests/ui/error-codes/E0614.stderr @@ -2,7 +2,7 @@ error[E0614]: type `u32` cannot be dereferenced --> $DIR/E0614.rs:3:5 | LL | *y; - | ^^ + | ^^ can't be dereferenced error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-17373.stderr b/tests/ui/issues/issue-17373.stderr index 9438f5c6345d..0e16d08c87d3 100644 --- a/tests/ui/issues/issue-17373.stderr +++ b/tests/ui/issues/issue-17373.stderr @@ -2,7 +2,7 @@ error[E0614]: type `!` cannot be dereferenced --> $DIR/issue-17373.rs:2:5 | LL | *return - | ^^^^^^^ + | ^^^^^^^ can't be dereferenced error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-9814.stderr b/tests/ui/issues/issue-9814.stderr index d647edaf37e2..fa23fb7c1762 100644 --- a/tests/ui/issues/issue-9814.stderr +++ b/tests/ui/issues/issue-9814.stderr @@ -2,7 +2,7 @@ error[E0614]: type `Foo` cannot be dereferenced --> $DIR/issue-9814.rs:7:13 | LL | let _ = *Foo::Bar(2); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ can't be dereferenced error: aborting due to 1 previous error diff --git a/tests/ui/parser/expr-as-stmt.stderr b/tests/ui/parser/expr-as-stmt.stderr index 76a83aa0161b..577c3455a718 100644 --- a/tests/ui/parser/expr-as-stmt.stderr +++ b/tests/ui/parser/expr-as-stmt.stderr @@ -133,7 +133,7 @@ error[E0614]: type `{integer}` cannot be dereferenced --> $DIR/expr-as-stmt.rs:25:11 | LL | { 3 } * 3 - | ^^^ + | ^^^ can't be dereferenced | help: parentheses are required to parse this as an expression | diff --git a/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr b/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr index b378fe356ce1..46477f16090b 100644 --- a/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr +++ b/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr @@ -2,13 +2,13 @@ error[E0614]: type `{integer}` cannot be dereferenced --> $DIR/nested-binding-modes-ref.rs:4:5 | LL | *is_val; - | ^^^^^^^ + | ^^^^^^^ can't be dereferenced error[E0614]: type `{integer}` cannot be dereferenced --> $DIR/nested-binding-modes-ref.rs:9:5 | LL | *is_val; - | ^^^^^^^ + | ^^^^^^^ can't be dereferenced error: aborting due to 2 previous errors diff --git a/tests/ui/reachable/expr_unary.stderr b/tests/ui/reachable/expr_unary.stderr index 0a763087c6f1..7deca1b86021 100644 --- a/tests/ui/reachable/expr_unary.stderr +++ b/tests/ui/reachable/expr_unary.stderr @@ -2,7 +2,7 @@ error[E0614]: type `!` cannot be dereferenced --> $DIR/expr_unary.rs:8:16 | LL | let x: ! = * { return; }; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ can't be dereferenced error: unreachable expression --> $DIR/expr_unary.rs:8:16 diff --git a/tests/ui/type/type-check/missing_trait_impl.stderr b/tests/ui/type/type-check/missing_trait_impl.stderr index 033b42e6736d..28ffae2d5e55 100644 --- a/tests/ui/type/type-check/missing_trait_impl.stderr +++ b/tests/ui/type/type-check/missing_trait_impl.stderr @@ -50,7 +50,7 @@ error[E0614]: type `T` cannot be dereferenced --> $DIR/missing_trait_impl.rs:15:13 | LL | let y = *x; - | ^^ + | ^^ can't be dereferenced error: aborting due to 5 previous errors From 26f74ef586d2d8849e93e9a1a6c6e803a0d21065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2025 03:54:04 +0000 Subject: [PATCH 5/7] Make E0609 a structured error --- compiler/rustc_hir_typeck/messages.ftl | 6 ++++ compiler/rustc_hir_typeck/src/errors.rs | 23 +++++++++++++ compiler/rustc_hir_typeck/src/expr.rs | 36 ++++++++++----------- tests/ui/diagnostic-width/long-E0609.rs | 2 +- tests/ui/diagnostic-width/long-E0609.stderr | 5 ++- 5 files changed, 51 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 1a75a2ec3152..ed80bc3e7be7 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -153,6 +153,12 @@ hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for { *[other] {" "}in the current scope } +hir_typeck_no_field_on_type = no field `{$field}` on type `{$ty}` + +hir_typeck_no_field_on_variant = no field named `{$field}` on enum variant `{$container}::{$ident}` +hir_typeck_no_field_on_variant_enum = this enum variant... +hir_typeck_no_field_on_variant_field = ...does not have this field + hir_typeck_note_caller_chooses_ty_for_ty_param = the caller chooses a type for `{$ty_param_name}` which can be different from `{$found_ty}` hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 968bcee45cf4..20688a5b949d 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -454,6 +454,29 @@ impl HelpUseLatestEdition { } } +#[derive(Diagnostic)] +#[diag(hir_typeck_no_field_on_type, code = E0609)] +pub(crate) struct NoFieldOnType<'tcx> { + #[primary_span] + pub(crate) span: Span, + pub(crate) ty: Ty<'tcx>, + pub(crate) field: Ident, +} + +#[derive(Diagnostic)] +#[diag(hir_typeck_no_field_on_variant, code = E0609)] +pub(crate) struct NoFieldOnVariant<'tcx> { + #[primary_span] + pub(crate) span: Span, + pub(crate) container: Ty<'tcx>, + pub(crate) ident: Ident, + pub(crate) field: Ident, + #[label(hir_typeck_no_field_on_variant_enum)] + pub(crate) enum_span: Span, + #[label(hir_typeck_no_field_on_variant_field)] + pub(crate) field_span: Span, +} + #[derive(Diagnostic)] #[diag(hir_typeck_cant_dereference, code = E0614)] pub(crate) struct CantDereference<'tcx> { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a857a91834e6..43dfec0f408b 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -46,8 +46,9 @@ use crate::errors::{ AddressOfTemporaryTaken, BaseExpressionDoubleDot, BaseExpressionDoubleDotAddExpr, BaseExpressionDoubleDotEnableDefaultFieldValues, BaseExpressionDoubleDotRemove, CantDereference, FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, - HelpUseLatestEdition, ReturnLikeStatementKind, ReturnStmtOutsideOfFnBody, - StructExprNonExhaustive, TypeMismatchFruTypo, YieldExprOutsideOfCoroutine, + HelpUseLatestEdition, NoFieldOnType, NoFieldOnVariant, ReturnLikeStatementKind, + ReturnStmtOutsideOfFnBody, StructExprNonExhaustive, TypeMismatchFruTypo, + YieldExprOutsideOfCoroutine, }; use crate::{ BreakableCtxt, CoroutineTypes, Diverges, FnCtxt, Needs, cast, fatally_break_rust, @@ -3282,13 +3283,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let span = field.span; debug!("no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})", span, field, expr_t); - let mut err = type_error_struct!( - self.dcx(), - span, - expr_t, - E0609, - "no field `{field}` on type `{expr_t}`", - ); + let mut err = self.dcx().create_err(NoFieldOnType { span, ty: expr_t, field }); + if expr_t.references_error() { + err.downgrade_to_delayed_bug(); + } // try to add a suggestion in case the field is a nested field of a field of the Adt let mod_id = self.tcx.parent_module(id).to_def_id(); @@ -3862,16 +3860,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter_enumerated() .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == subident) else { - type_error_struct!( - self.dcx(), - ident.span, - container, - E0609, - "no field named `{subfield}` on enum variant `{container}::{ident}`", - ) - .with_span_label(field.span, "this enum variant...") - .with_span_label(subident.span, "...does not have this field") - .emit(); + self.dcx() + .create_err(NoFieldOnVariant { + span: ident.span, + container, + ident, + field: subfield, + enum_span: field.span, + field_span: subident.span, + }) + .emit_unless(container.references_error()); break; }; diff --git a/tests/ui/diagnostic-width/long-E0609.rs b/tests/ui/diagnostic-width/long-E0609.rs index ae57e4f76d2f..39442bdeae03 100644 --- a/tests/ui/diagnostic-width/long-E0609.rs +++ b/tests/ui/diagnostic-width/long-E0609.rs @@ -7,7 +7,7 @@ type C = (B, B, B, B); type D = (C, C, C, C); fn foo(x: D) { - x.field; //~ ERROR no field `field` on type `( + x.field; //~ ERROR no field `field` on type `(... } fn main() {} diff --git a/tests/ui/diagnostic-width/long-E0609.stderr b/tests/ui/diagnostic-width/long-E0609.stderr index 708cd4ef93a8..6815caa6b6ba 100644 --- a/tests/ui/diagnostic-width/long-E0609.stderr +++ b/tests/ui/diagnostic-width/long-E0609.stderr @@ -1,8 +1,11 @@ -error[E0609]: no field `field` on type `((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))` +error[E0609]: no field `field` on type `(..., ..., ..., ...)` --> $DIR/long-E0609.rs:10:7 | LL | x.field; | ^^^^^ unknown field + | + = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + = note: consider using `--verbose` to print the full type name to the console error: aborting due to 1 previous error From a4e89deb52eac24d857823f46a3f38b02178731a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2025 20:45:27 +0000 Subject: [PATCH 6/7] add doc comment detail --- compiler/rustc_errors/src/diagnostic.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 97daf891b0fe..7fffeaddb866 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -148,6 +148,12 @@ where /// converted rather than on `DiagArgValue`, which enables types from other `rustc_*` crates to /// implement this. pub trait IntoDiagArg { + /// Convert `Self` into a `DiagArgValue` suitable for rendering in a diagnostic. + /// + /// It takes a `path` where "long values" could be written to, if the `DiagArgValue` is too big + /// for displaying on the terminal. This path comes from the `Diag` itself. When rendering + /// values that come from `TyCtxt`, like `Ty<'_>`, they can use `TyCtxt::short_string`. If a + /// value has no shortening logic that could be used, the argument can be safely ignored. fn into_diag_arg(self, path: &mut Option) -> DiagArgValue; } From c550bee64148a8f702f5fd18d4da75b93832c4df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 25 Feb 2025 17:27:22 +0000 Subject: [PATCH 7/7] Fix rebase --- compiler/rustc_errors/src/diagnostic_impls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index e0c8caf1317e..cb2e1769fa1c 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -98,7 +98,7 @@ into_diag_arg_using_display!( ); impl IntoDiagArg for RustcVersion { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(self.to_string())) } }