From b291b7c8b133b88e06e3edfe7834a2cb2ed92213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 12 Feb 2025 01:55:46 +0000 Subject: [PATCH] Enforce short type string in more errors ``` error[E0529]: expected an array or slice, found `(..., ..., ..., ...)` --> $DIR/long-E0529.rs:10:9 | LL | let [] = x; | ^^ 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[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[E0614]: type `(..., ..., ..., ...)` cannot be dereferenced --> $DIR/long-E0614.rs:10:5 | LL | *x; | ^^ | = 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[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 ``` Use multipart suggestion for cast -> into: ``` error[E0604]: only `u8` can be cast as `char`, not `u32` --> $DIR/E0604.rs:2:5 | LL | 1u32 as char; | ^^^^^^^^^^^^ invalid cast | help: try `char::from_u32` instead | LL - 1u32 as char; LL + char::from_u32(1u32); | ``` --- .../src/diagnostics/conflict_errors.rs | 31 +++---- compiler/rustc_hir_typeck/src/callee.rs | 7 +- compiler/rustc_hir_typeck/src/cast.rs | 82 +++++++++++-------- compiler/rustc_hir_typeck/src/errors.rs | 6 +- compiler/rustc_hir_typeck/src/expr.rs | 10 ++- .../rustc_hir_typeck/src/gather_locals.rs | 4 +- compiler/rustc_hir_typeck/src/method/probe.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_hir_typeck/src/pat.rs | 15 ++-- compiler/rustc_infer/src/infer/mod.rs | 4 - compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- .../src/error_reporting/infer/mod.rs | 5 +- .../src/error_reporting/infer/region.rs | 6 +- .../src/error_reporting/traits/suggestions.rs | 35 ++++---- ...ntract-captures-via-closure-noncopy.stderr | 2 +- tests/ui/diagnostic-width/long-E0529.rs | 14 ++++ tests/ui/diagnostic-width/long-E0529.stderr | 12 +++ tests/ui/diagnostic-width/long-E0609.rs | 13 +++ tests/ui/diagnostic-width/long-E0609.stderr | 12 +++ tests/ui/diagnostic-width/long-E0614.rs | 13 +++ tests/ui/diagnostic-width/long-E0614.stderr | 12 +++ tests/ui/diagnostic-width/long-E0618.rs | 13 +++ tests/ui/diagnostic-width/long-E0618.stderr | 16 ++++ tests/ui/error-codes/E0604.stderr | 11 ++- tests/ui/error-festival.stderr | 11 ++- tests/ui/mismatched_types/cast-rfc0401.stderr | 11 ++- 26 files changed, 248 insertions(+), 103 deletions(-) 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 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_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 6269728e67f73..8f4a413b7fcfe 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -312,8 +312,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .. } = use_spans { + let ty = self.infcx.tcx.short_string(deref_target_ty, err.long_ty_path()); err.note(format!( - "{} occurs due to deref coercion to `{deref_target_ty}`", + "{} occurs due to deref coercion to `{ty}`", desired_action.as_noun(), )); @@ -1222,13 +1223,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ), }; let prefix = if !self.implements_clone(ty) { - let msg = format!("`{ty}` doesn't implement `Copy` or `Clone`"); + let t = self.infcx.tcx.short_string(ty, err.long_ty_path()); + let msg = format!("`{t}` doesn't implement `Copy` or `Clone`"); if let ty::Adt(def, _) = ty.kind() { err.span_note(self.infcx.tcx.def_span(def.did()), msg); } else { err.note(msg); } - format!("if `{ty}` implemented `Clone`, you could ") + format!("if `{t}` implemented `Clone`, you could ") } else { String::new() }; @@ -1270,10 +1272,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let mut span: MultiSpan = ty_span.into(); span.push_span_label(ty_span, "consider implementing `Clone` for this type"); span.push_span_label(expr.span, "you could clone this value"); - err.span_note( - span, - format!("if `{ty}` implemented `Clone`, you could clone the value"), - ); + let t = self.infcx.tcx.short_string(ty, err.long_ty_path()); + err.span_note(span, format!("if `{t}` implemented `Clone`, you could clone the value")); } else if let ty::Param(param) = ty.kind() && let Some(_clone_trait_def) = self.infcx.tcx.lang_items().clone_trait() && let generics = self.infcx.tcx.generics_of(self.mir_def_id()) @@ -1302,10 +1302,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { "consider constraining this type parameter with `Clone`", ); span.push_span_label(expr.span, "you could clone this value"); - err.span_help( - span, - format!("if `{ty}` implemented `Clone`, you could clone the value"), - ); + let t = self.infcx.tcx.short_string(ty, err.long_ty_path()); + err.span_help(span, format!("if `{t}` implemented `Clone`, you could clone the value")); } } @@ -1951,11 +1949,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { && let None = self.infcx.type_implements_trait_shallow(clone, inner, self.infcx.param_env) { + let rcvr_ty = self.infcx.tcx.short_string(rcvr_ty, err.long_ty_path()); + let inner_str = self.infcx.tcx.short_string(inner, err.long_ty_path()); err.span_label( span, format!( - "this call doesn't do anything, the result is still `{rcvr_ty}` \ - because `{inner}` doesn't implement `Clone`", + "this call doesn't do anything, the result is still `{rcvr_ty}` because \ + `{inner_str}` doesn't implement `Clone`", ), ); types_to_constrain.insert(inner); @@ -3067,6 +3067,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let borrow_span = borrow_spans.var_or_use(); let mut err = self.cannot_borrow_across_destructor(borrow_span); + let dropped_ty = self.infcx.tcx.short_string(dropped_ty, err.long_ty_path()); let what_was_dropped = match self.describe_place(place.as_ref()) { Some(name) => format!("`{name}`"), @@ -3245,6 +3246,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { && path.ident.name == sym::iter && let Some(ty) = expr_ty { + let ty = self.infcx.tcx.short_string(ty, err.long_ty_path()); err.span_suggestion_verbose( path.ident.span, format!( @@ -3799,7 +3801,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { Some(self.infcx.tcx.fn_arg_names(method_did)[0]), ) { - err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`")); + let ty = self.infcx.tcx.short_string(deref_target_ty, err.long_ty_path()); + err.note(format!("borrow occurs due to deref coercion to `{ty}`")); if let Some(deref_target_span) = deref_target_span { err.span_note(deref_target_span, "deref defined here"); } diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index f2d0b9117314c..2a3b32a11cb1a 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -675,13 +675,15 @@ 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 { 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(); } @@ -764,6 +766,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { DefIdOrName::DefId(def_id) => self.tcx.def_descr(def_id), DefIdOrName::Name(name) => name, }; + let output_ty = self.tcx.short_string(output_ty, err.long_ty_path()); err.span_label( callee_expr.span, format!("this {descr} returns an unsized value `{output_ty}`, so it cannot be called") @@ -779,7 +782,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(span) = self.tcx.hir().res_span(def) { - let callee_ty = callee_ty.to_string(); + let callee_ty = self.tcx.short_string(callee_ty, err.long_ty_path()); let label = match (unit_variant, inner_callee_path) { (Some((_, kind, path)), _) => Some(format!("{kind} `{path}` defined here")), (_, Some(hir::QPath::Resolved(_, path))) => self diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index d8015bcc91424..668067a71c002 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -196,15 +196,18 @@ fn make_invalid_casting_error<'a, 'tcx>( cast_ty: Ty<'tcx>, fcx: &FnCtxt<'a, 'tcx>, ) -> Diag<'a> { - type_error_struct!( + let mut path = None; + let expr = fcx.tcx.short_string(expr_ty, &mut path); + let cast = fcx.tcx.short_string(cast_ty, &mut path); + let mut err = type_error_struct!( fcx.dcx(), span, expr_ty, E0606, - "casting `{}` as `{}` is invalid", - fcx.ty_to_string(expr_ty), - fcx.ty_to_string(cast_ty) - ) + "casting `{expr}` as `{cast}` is invalid", + ); + *err.long_ty_path() = path; + err } /// If a cast from `from_ty` to `to_ty` is valid, returns a `Some` containing the kind @@ -259,6 +262,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { } fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError<'tcx>) { + let mut path = None; match e { CastError::ErrorGuaranteed(_) => { // an error has already been reported @@ -369,27 +373,26 @@ impl<'a, 'tcx> CastCheck<'tcx> { fcx.dcx().emit_err(errors::CannotCastToBool { span: self.span, expr_ty, help }); } CastError::CastToChar => { + let expr = fcx.tcx.short_string(self.expr_ty, &mut path); let mut err = type_error_struct!( fcx.dcx(), self.span, self.expr_ty, E0604, - "only `u8` can be cast as `char`, not `{}`", - self.expr_ty + "only `u8` can be cast as `char`, not `{expr}`", ); + *err.long_ty_path() = path; err.span_label(self.span, "invalid cast"); if self.expr_ty.is_numeric() { if self.expr_ty == fcx.tcx.types.u32 { - match fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) { - Ok(snippet) => err.span_suggestion( - self.span, - "try `char::from_u32` instead", - format!("char::from_u32({snippet})"), - Applicability::MachineApplicable, - ), - - Err(_) => err.span_help(self.span, "try `char::from_u32` instead"), - }; + err.multipart_suggestion_verbose( + "try `char::from_u32` instead", + vec![ + (self.span.shrink_to_lo(), "char::from_u32(".to_string()), + (self.span.with_lo(self.expr.span.hi()), ")".to_string()), + ], + Applicability::MachineApplicable, + ); } else if self.expr_ty == fcx.tcx.types.i8 { err.span_help(self.span, "try casting from `u8` instead"); } else { @@ -399,15 +402,16 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.emit(); } CastError::NonScalar => { + let expr = fcx.tcx.short_string(self.expr_ty, &mut path); + let cast = fcx.tcx.short_string(self.cast_ty, &mut path); let mut err = type_error_struct!( fcx.dcx(), self.span, self.expr_ty, E0605, - "non-primitive cast: `{}` as `{}`", - self.expr_ty, - fcx.ty_to_string(self.cast_ty) + "non-primitive cast: `{expr}` as `{cast}`", ); + *err.long_ty_path() = path; let mut sugg = None; let mut sugg_mutref = false; if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() { @@ -548,21 +552,26 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.emit(); } CastError::SizedUnsizedCast => { - fcx.dcx().emit_err(errors::CastThinPointerToWidePointer { + let expr_ty = fcx.tcx.short_string(self.expr_ty, &mut path); + let cast_ty = fcx.tcx.short_string(self.cast_ty, &mut path); + let mut err = fcx.dcx().create_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), }); + *err.long_ty_path() = path; + err.emit(); } 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.tcx.short_string(self.expr_ty, &mut path); + let cast_ty = + fcx.tcx.short_string(fcx.resolve_vars_if_possible(self.cast_ty), &mut path); let metadata = known_metadata.unwrap_or("type-specific metadata"); let known_wide = known_metadata.is_some(); let span = self.cast_span; - fcx.dcx().emit_err(errors::IntToWide { + let mut err = fcx.dcx().create_err(errors::IntToWide { span, metadata, expr_ty, @@ -570,6 +579,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { expr_if_nightly, known_wide, }); + *err.long_ty_path() = path; + err.emit(); } CastError::UnknownCastPtrKind | CastError::UnknownExprPtrKind => { let unknown_cast_to = match e { @@ -605,16 +616,18 @@ impl<'a, 'tcx> CastCheck<'tcx> { return err; } - let tstr = fcx.ty_to_string(self.cast_ty); + let mut path = None; + let tstr = fcx.tcx.short_string(self.cast_ty, &mut path); + let expr_ty = fcx.tcx.short_string(fcx.resolve_vars_if_possible(self.expr_ty), &mut path); + let mut err = type_error_struct!( fcx.dcx(), self.span, self.expr_ty, E0620, - "cast to unsized type: `{}` as `{}`", - fcx.resolve_vars_if_possible(self.expr_ty), - tstr + "cast to unsized type: `{expr_ty}` as `{tstr}`", ); + *err.long_ty_path() = path; match self.expr_ty.kind() { ty::Ref(_, _, mt) => { let mtstr = mt.prefix_str(); @@ -1164,18 +1177,17 @@ 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), - }); + let deref_ty = fcx.tcx.short_string(deref_ty, err.long_ty_path()); + err.subdiagnostic(errors::DerefImplsIsEmpty { span: self.expr_span, deref_ty }); } + let expr_ty = fcx.tcx.short_string(self.expr_ty, err.long_ty_path()); // Create a multipart suggestion: add `!` and `.is_empty()` in // place of the cast. 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, }); } } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 143736072aa55..500df216a9058 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -470,7 +470,7 @@ pub(crate) struct IntToWide<'tcx> { pub span: Span, pub metadata: &'tcx str, pub expr_ty: String, - pub cast_ty: Ty<'tcx>, + pub cast_ty: String, #[label(hir_typeck_int_to_fat_label_nightly)] pub expr_if_nightly: Option, pub known_wide: bool, @@ -822,10 +822,10 @@ pub(crate) struct ReplaceWithName { #[derive(Diagnostic)] #[diag(hir_typeck_cast_thin_pointer_to_wide_pointer, code = E0607)] -pub(crate) struct CastThinPointerToWidePointer<'tcx> { +pub(crate) struct CastThinPointerToWidePointer { #[primary_span] pub span: Span, - pub expr_ty: Ty<'tcx>, + pub expr_ty: String, pub cast_ty: String, #[note(hir_typeck_teach_help)] pub(crate) teach: bool, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 9dd965a4dcbbb..646d3c97f78f8 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -606,13 +606,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(ty) = self.lookup_derefing(expr, oprnd, oprnd_t) { oprnd_t = ty; } else { + let mut path = None; + let ty = self.tcx.short_string(oprnd_t, &mut path); let mut err = type_error_struct!( self.dcx(), expr.span, oprnd_t, E0614, - "type `{oprnd_t}` cannot be dereferenced", + "type `{ty}` cannot be dereferenced", ); + *err.long_ty_path() = path; 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) @@ -3286,13 +3289,16 @@ 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 path = None; + let ty = self.tcx.short_string(expr_t, &mut path); let mut err = type_error_struct!( self.dcx(), span, expr_t, E0609, - "no field `{field}` on type `{expr_t}`", + "no field `{field}` on type `{ty}`", ); + *err.long_ty_path() = path; // 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(); diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 48fd5f1f98249..361bac2de2b24 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -114,7 +114,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { debug!( "local variable {:?} is assigned type {}", decl.pat, - self.fcx.ty_to_string(*self.fcx.locals.borrow().get(&decl.hir_id).unwrap()) + *self.fcx.locals.borrow().get(&decl.hir_id).unwrap() ); } } @@ -174,7 +174,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { debug!( "pattern binding {} is assigned to {} with type {:?}", ident, - self.fcx.ty_to_string(*self.fcx.locals.borrow().get(&p.hir_id).unwrap()), + *self.fcx.locals.borrow().get(&p.hir_id).unwrap(), var_ty ); } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index b9d1f93bfb8e4..616ef4bb94911 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1555,7 +1555,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { pick_diag_hints: &mut PickDiagHints<'_, 'tcx>, pick_constraints: Option<&PickConstraintsForShadowed>, ) -> Option> { - debug!("pick_method(self_ty={})", self.ty_to_string(self_ty)); + debug!("pick_method(self_ty={})", self_ty); for (kind, candidates) in [("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)] diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 6c4ad65be6a63..25c852e3c6ca9 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3246,7 +3246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String { match ty.kind() { ty::Adt(def, args) => self.tcx.def_path_str_with_args(def.did(), args), - _ => self.ty_to_string(ty), + _ => self.resolve_vars_if_possible(ty).to_string(), } } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 7c2a2b3fdf7da..42786c0f0d308 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1108,16 +1108,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let Some(pointee_ty) = self.shallow_resolve(expected).builtin_deref(true) && let ty::Dynamic(..) = pointee_ty.kind() { + let mut path = None; // This is "x = dyn SomeTrait" being reduced from // "let &x = &dyn SomeTrait" or "let box x = Box", an error. - let type_str = self.ty_to_string(expected); + let type_str = self.tcx.short_string(expected, &mut path); let mut err = struct_span_code_err!( self.dcx(), span, E0033, - "type `{}` cannot be dereferenced", - type_str + "type `{type_str}` cannot be dereferenced", ); + *err.long_ty_path() = path; err.span_label(span, format!("type `{type_str}` cannot be dereferenced")); if self.tcx.sess.teach(err.code.unwrap()) { err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ); @@ -2712,12 +2713,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> ErrorGuaranteed { let PatInfo { top_info: ti, current_depth, .. } = pat_info; + let mut path = None; + let found = self.tcx.short_string(expected_ty, &mut path); + let mut err = struct_span_code_err!( self.dcx(), span, E0529, - "expected an array or slice, found `{expected_ty}`" + "expected an array or slice, found `{found}`" ); + *err.long_ty_path() = path; if let ty::Ref(_, ty, _) = expected_ty.kind() && let ty::Array(..) | ty::Slice(..) = ty.kind() { @@ -2758,7 +2763,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } - err.span_label(span, format!("pattern cannot match with input type `{expected_ty}`")); + err.span_label(span, format!("pattern cannot match with input type `{found}`")); err.emit() } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index c2513a1af1988..668ebe490ccb2 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -983,10 +983,6 @@ impl<'tcx> InferCtxt<'tcx> { } } - pub fn ty_to_string(&self, t: Ty<'tcx>) -> String { - self.resolve_vars_if_possible(t).to_string() - } - /// If `TyVar(vid)` resolves to a type, return that type. Else, return the /// universe index of `TyVar(vid)`. pub fn probe_ty_var(&self, vid: TyVid) -> Result, ty::UniverseIndex> { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index feae8ea312eaa..d91593ec606e7 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2961,7 +2961,7 @@ impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> { } } -#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)] pub struct TraitPredPrintModifiersAndPath<'tcx>(ty::TraitPredicate<'tcx>); impl<'tcx> fmt::Debug for TraitPredPrintModifiersAndPath<'tcx> { 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 091773009e98d..de516bb5b550c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -137,7 +137,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let actual_ty = self.resolve_vars_if_possible(actual_ty); debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty); - let mut err = mk_diag(self.ty_to_string(actual_ty)); + let mut path = None; + let ty = self.tcx.short_string(actual_ty, &mut path); + let mut err = mk_diag(ty); + *err.long_ty_path() = path; // Don't report an error if actual type is `Error`. if actual_ty.references_error() { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index f35a5349ecb3c..3bc77c6a36d3a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -233,19 +233,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .add_to_diag(err); } infer::ReferenceOutlivesReferent(ty, span) => { + let name = self.tcx.short_string(ty, err.long_ty_path()); RegionOriginNote::WithName { span, msg: fluent::trait_selection_reference_outlives_referent, - name: &self.ty_to_string(ty), + name: &name, continues: false, } .add_to_diag(err); } infer::RelateParamBound(span, ty, opt_span) => { + let name = self.tcx.short_string(ty, err.long_ty_path()); RegionOriginNote::WithName { span, msg: fluent::trait_selection_relate_param_bound, - name: &self.ty_to_string(ty), + name: &name, continues: opt_span.is_some(), } .add_to_diag(err); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 527d2e54e4327..cda61c47b162a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1417,6 +1417,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } + let self_ty = self.tcx.short_string(self_ty, err.long_ty_path()); + let target_ty = self.tcx.short_string(target_ty, err.long_ty_path()); err.span_suggestion( obligation.cause.span.shrink_to_lo(), format!( @@ -1719,13 +1721,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { obligation.param_env, trait_pred.map_bound(|trait_pred| (trait_pred, ty)) )) { + let ty = self.tcx.short_string(ty, err.long_ty_path()); + let pred = self + .tcx + .short_string(trait_pred.print_modifiers_and_trait_path(), err.long_ty_path()); err.span_label( expr.span, - format!( - "this expression has type `{}`, which implements `{}`", - ty, - trait_pred.print_modifiers_and_trait_path() - ), + format!("this expression has type `{ty}`, which implements `{pred}`"), ); err.span_suggestion( self.tcx.sess.source_map().end_point(stmt.span), @@ -3818,15 +3820,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .unwrap_or(Ty::new_misc_error(tcx)); let span = inner_expr.span; if Some(span) != err.span.primary_span() { - err.span_label( - span, - if ty.references_error() { - String::new() - } else { - let ty = with_forced_trimmed_paths!(self.ty_to_string(ty)); - format!("this tail expression is of type `{ty}`") - }, - ); + let label = if ty.references_error() { + String::new() + } else { + let ty = + tcx.short_string(self.resolve_vars_if_possible(ty), err.long_ty_path()); + format!("this tail expression is of type `{ty}`") + }; + err.span_label(span, label); if let ty::PredicateKind::Clause(clause) = failed_pred.kind().skip_binder() && let ty::ClauseKind::Trait(pred) = clause && [ @@ -4227,7 +4228,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(ty) = typeck_results.expr_ty_opt(expr) && print_root_expr { - let ty = with_forced_trimmed_paths!(self.ty_to_string(ty)); + let ty = tcx.short_string(self.resolve_vars_if_possible(ty), err.long_ty_path()); // Point at the root expression // vec![1, 2, 3].iter().map(mapper).sum() // ^^^^^^^^^^^^^ @@ -4272,7 +4273,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { match (entry, prev_entry) { (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => { - let ty_str = with_forced_trimmed_paths!(self.ty_to_string(ty)); + let ty_str = self.tcx.short_string(ty, err.long_ty_path()); let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc)); if !self.can_eq(param_env, ty, *prev_ty) { @@ -4296,7 +4297,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { with_forced_trimmed_paths!(format!( "`{}` is `{}` here", self.tcx.def_path_str(assoc), - self.ty_to_string(ty), + self.tcx.short_string(ty, err.long_ty_path()), )), )); } diff --git a/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr b/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr index 4a47671fee191..2e31aed0bdcfd 100644 --- a/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr +++ b/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr @@ -14,7 +14,7 @@ LL | #[core::contracts::ensures({let old = x; move |ret:&Baz| ret.baz == old.baz | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^^ | | | | | within this `{closure@$DIR/contract-captures-via-closure-noncopy.rs:12:42: 12:57}` - | | this tail expression is of type `{closure@contract-captures-via-closure-noncopy.rs:12:42}` + | | this tail expression is of type `{closure@$DIR/contract-captures-via-closure-noncopy.rs:12:42: 12:57}` | unsatisfied trait bound | = help: within `{closure@$DIR/contract-captures-via-closure-noncopy.rs:12:42: 12:57}`, the trait `std::marker::Copy` is not implemented for `Baz` diff --git a/tests/ui/diagnostic-width/long-E0529.rs b/tests/ui/diagnostic-width/long-E0529.rs new file mode 100644 index 0000000000000..3ebc4f5f8c825 --- /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 0000000000000..da03e5fab2ca2 --- /dev/null +++ b/tests/ui/diagnostic-width/long-E0529.stderr @@ -0,0 +1,12 @@ +error[E0529]: expected an array or slice, found `(..., ..., ..., ...)` + --> $DIR/long-E0529.rs:10:9 + | +LL | let [] = x; + | ^^ 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 + +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 0000000000000..39442bdeae03a --- /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 0000000000000..6815caa6b6ba1 --- /dev/null +++ b/tests/ui/diagnostic-width/long-E0609.stderr @@ -0,0 +1,12 @@ +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 + +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 0000000000000..0b78444a00d24 --- /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 0000000000000..23cda41686af5 --- /dev/null +++ b/tests/ui/diagnostic-width/long-E0614.stderr @@ -0,0 +1,12 @@ +error[E0614]: type `(..., ..., ..., ...)` cannot be dereferenced + --> $DIR/long-E0614.rs:10:5 + | +LL | *x; + | ^^ + | + = 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 E0614`. diff --git a/tests/ui/diagnostic-width/long-E0618.rs b/tests/ui/diagnostic-width/long-E0618.rs new file mode 100644 index 0000000000000..f8626ab9455e2 --- /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 0000000000000..f0838cbddcc64 --- /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`. diff --git a/tests/ui/error-codes/E0604.stderr b/tests/ui/error-codes/E0604.stderr index e91f74d6b3fd6..b949ed973cdc2 100644 --- a/tests/ui/error-codes/E0604.stderr +++ b/tests/ui/error-codes/E0604.stderr @@ -2,10 +2,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32` --> $DIR/E0604.rs:2:5 | LL | 1u32 as char; - | ^^^^^^^^^^^^ - | | - | invalid cast - | help: try `char::from_u32` instead: `char::from_u32(1u32)` + | ^^^^^^^^^^^^ invalid cast + | +help: try `char::from_u32` instead + | +LL - 1u32 as char; +LL + char::from_u32(1u32); + | error: aborting due to 1 previous error diff --git a/tests/ui/error-festival.stderr b/tests/ui/error-festival.stderr index 9db9536379141..4236c71e4b6ec 100644 --- a/tests/ui/error-festival.stderr +++ b/tests/ui/error-festival.stderr @@ -58,10 +58,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32` --> $DIR/error-festival.rs:25:5 | LL | 0u32 as char; - | ^^^^^^^^^^^^ - | | - | invalid cast - | help: try `char::from_u32` instead: `char::from_u32(0u32)` + | ^^^^^^^^^^^^ invalid cast + | +help: try `char::from_u32` instead + | +LL - 0u32 as char; +LL + char::from_u32(0u32); + | error[E0605]: non-primitive cast: `u8` as `Vec` --> $DIR/error-festival.rs:29:5 diff --git a/tests/ui/mismatched_types/cast-rfc0401.stderr b/tests/ui/mismatched_types/cast-rfc0401.stderr index a427639594415..eb95d659840d7 100644 --- a/tests/ui/mismatched_types/cast-rfc0401.stderr +++ b/tests/ui/mismatched_types/cast-rfc0401.stderr @@ -104,10 +104,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32` --> $DIR/cast-rfc0401.rs:41:13 | LL | let _ = 0x61u32 as char; - | ^^^^^^^^^^^^^^^ - | | - | invalid cast - | help: try `char::from_u32` instead: `char::from_u32(0x61u32)` + | ^^^^^^^^^^^^^^^ invalid cast + | +help: try `char::from_u32` instead + | +LL - let _ = 0x61u32 as char; +LL + let _ = char::from_u32(0x61u32); + | error[E0606]: casting `bool` as `f32` is invalid --> $DIR/cast-rfc0401.rs:43:13