about summary refs log tree commit diff
path: root/compiler/rustc_middle/src/ty
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2025-02-18 01:15:59 +0000
committerEsteban Küber <esteban@kuber.com.ar>2025-02-25 16:56:03 +0000
commitd12ecaed558426ec7998816d64b240ea685a2a8f (patch)
tree5c0c68022dd9b4da83daa6e7bd645f24ce738d0b /compiler/rustc_middle/src/ty
parentc51b9b6d5234aa8e50c3b87784113a1af1af47cb (diff)
downloadrust-d12ecaed558426ec7998816d64b240ea685a2a8f.tar.gz
rust-d12ecaed558426ec7998816d64b240ea685a2a8f.zip
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
```
Diffstat (limited to 'compiler/rustc_middle/src/ty')
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs2
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs10
-rw-r--r--compiler/rustc_middle/src/ty/error.rs10
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs4
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs4
-rw-r--r--compiler/rustc_middle/src/ty/predicate.rs18
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs18
7 files changed, 42 insertions, 24 deletions
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index b72edc1c532..7c9280fae16 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<std::path::PathBuf>) -> 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 cb218a27e62..881381a5ee6 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<std::path::PathBuf>) -> 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 8c1991ddb36..a0e67929c52 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<T>(self, p: T, length_limit: usize) -> String
     where
-        T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift<TyCtxt<'tcx>> + Copy,
-        <T as Lift<TyCtxt<'tcx>>>::Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>,
+        T: Copy + for<'a, 'b> Lift<TyCtxt<'b>, 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<PathBuf>) -> String
+    pub fn short_string<T>(self, p: T, path: &mut Option<PathBuf>) -> String
     where
-        T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift<TyCtxt<'tcx>> + Copy + Hash,
-        <T as Lift<TyCtxt<'tcx>>>::Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>,
+        T: Copy + Hash + for<'a, 'b> Lift<TyCtxt<'b>, 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 ed0b3059d75..27576a2ec4a 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<std::path::PathBuf>) -> 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 eb14ed20fba..272bb0cc915 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<std::path::PathBuf>) -> 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 553de83dfcb..de6d30a89d4 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<std::path::PathBuf>) -> 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<std::path::PathBuf>) -> 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 ed0839f47e6..942411945bf 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<U>` instead of
 /// `<T as Trait<U>>`.
-#[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<std::path::PathBuf>) -> 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<std::path::PathBuf>) -> 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))
+        })
     }
 }