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>2023-01-02 18:00:33 -0800
committerEsteban Küber <esteban@kuber.com.ar>2023-01-30 20:12:19 +0000
commit62ba3e70a1f01d801d068b84a097e38bd82a8c6e (patch)
treee7834f2924d6a0aa0ef7eddb6bb9b2db50b2be1d /compiler/rustc_middle/src/ty
parent006ca9b14da1e0145844598b3d6a554c042c702a (diff)
downloadrust-62ba3e70a1f01d801d068b84a097e38bd82a8c6e.tar.gz
rust-62ba3e70a1f01d801d068b84a097e38bd82a8c6e.zip
Modify primary span label for E0308
The previous output was unintuitive to users.
Diffstat (limited to 'compiler/rustc_middle/src/ty')
-rw-r--r--compiler/rustc_middle/src/ty/error.rs191
1 files changed, 67 insertions, 124 deletions
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index d83fc95ac4e..bb87b0eea37 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -8,9 +8,7 @@ use rustc_span::symbol::Symbol;
 use rustc_target::spec::abi;
 use std::borrow::Cow;
 use std::collections::hash_map::DefaultHasher;
-use std::fmt;
-use std::hash::Hash;
-use std::hash::Hasher;
+use std::hash::{Hash, Hasher};
 use std::path::PathBuf;
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable, Lift)]
@@ -87,20 +85,16 @@ impl TypeError<'_> {
 /// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
 /// afterwards to present additional details, particularly when it comes to lifetime-related
 /// errors.
-impl<'tcx> fmt::Display for TypeError<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl<'tcx> TypeError<'tcx> {
+    pub fn to_string(self, tcx: TyCtxt<'tcx>) -> String {
         use self::TypeError::*;
-        fn report_maybe_different(
-            f: &mut fmt::Formatter<'_>,
-            expected: &str,
-            found: &str,
-        ) -> fmt::Result {
+        fn report_maybe_different(expected: &str, found: &str) -> String {
             // A naive approach to making sure that we're not reporting silly errors such as:
             // (expected closure, found closure).
             if expected == found {
-                write!(f, "expected {}, found a different {}", expected, found)
+                format!("expected {}, found a different {}", expected, found)
             } else {
-                write!(f, "expected {}, found {}", expected, found)
+                format!("expected {}, found {}", expected, found)
             }
         }
 
@@ -109,64 +103,59 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
             _ => String::new(),
         };
 
-        match *self {
-            CyclicTy(_) => write!(f, "cyclic type of infinite size"),
-            CyclicConst(_) => write!(f, "encountered a self-referencing constant"),
-            Mismatch => write!(f, "types differ"),
+        match self {
+            CyclicTy(_) => format!("cyclic type of infinite size"),
+            CyclicConst(_) => format!("encountered a self-referencing constant"),
+            Mismatch => format!("types differ"),
             ConstnessMismatch(values) => {
-                write!(f, "expected {} bound, found {} bound", values.expected, values.found)
+                format!("expected {} bound, found {} bound", values.expected, values.found)
             }
             PolarityMismatch(values) => {
-                write!(f, "expected {} polarity, found {} polarity", values.expected, values.found)
+                format!("expected {} polarity, found {} polarity", values.expected, values.found)
             }
             UnsafetyMismatch(values) => {
-                write!(f, "expected {} fn, found {} fn", values.expected, values.found)
+                format!("expected {} fn, found {} fn", values.expected, values.found)
             }
             AbiMismatch(values) => {
-                write!(f, "expected {} fn, found {} fn", values.expected, values.found)
+                format!("expected {} fn, found {} fn", values.expected, values.found)
             }
-            ArgumentMutability(_) | Mutability => write!(f, "types differ in mutability"),
-            TupleSize(values) => write!(
-                f,
+            ArgumentMutability(_) | Mutability => format!("types differ in mutability"),
+            TupleSize(values) => format!(
                 "expected a tuple with {} element{}, found one with {} element{}",
                 values.expected,
                 pluralize!(values.expected),
                 values.found,
                 pluralize!(values.found)
             ),
-            FixedArraySize(values) => write!(
-                f,
+            FixedArraySize(values) => format!(
                 "expected an array with a fixed size of {} element{}, found one with {} element{}",
                 values.expected,
                 pluralize!(values.expected),
                 values.found,
                 pluralize!(values.found)
             ),
-            ArgCount => write!(f, "incorrect number of function parameters"),
-            FieldMisMatch(adt, field) => write!(f, "field type mismatch: {}.{}", adt, field),
-            RegionsDoesNotOutlive(..) => write!(f, "lifetime mismatch"),
+            ArgCount => format!("incorrect number of function parameters"),
+            FieldMisMatch(adt, field) => format!("field type mismatch: {}.{}", adt, field),
+            RegionsDoesNotOutlive(..) => format!("lifetime mismatch"),
             // Actually naming the region here is a bit confusing because context is lacking
             RegionsInsufficientlyPolymorphic(..) => {
-                write!(f, "one type is more general than the other")
+                format!("one type is more general than the other")
             }
-            RegionsOverlyPolymorphic(br, _) => write!(
-                f,
+            RegionsOverlyPolymorphic(br, _) => format!(
                 "expected concrete lifetime, found bound lifetime parameter{}",
                 br_string(br)
             ),
-            RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"),
-            ArgumentSorts(values, _) | Sorts(values) => ty::tls::with(|tcx| {
-                let (mut expected, mut found) = with_forced_trimmed_paths!((
-                    values.expected.sort_string(tcx),
-                    values.found.sort_string(tcx),
-                ));
+            RegionsPlaceholderMismatch => format!("one type is more general than the other"),
+            ArgumentSorts(values, _) | Sorts(values) => {
+                let mut expected = values.expected.sort_string(tcx);
+                let mut found = values.found.sort_string(tcx);
                 if expected == found {
                     expected = values.expected.sort_string(tcx);
                     found = values.found.sort_string(tcx);
                 }
-                report_maybe_different(f, &expected, &found)
-            }),
-            Traits(values) => ty::tls::with(|tcx| {
+                report_maybe_different(&expected, &found)
+            }
+            Traits(values) => {
                 let (mut expected, mut found) = with_forced_trimmed_paths!((
                     tcx.def_path_str(values.expected),
                     tcx.def_path_str(values.found),
@@ -175,12 +164,8 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
                     expected = tcx.def_path_str(values.expected);
                     found = tcx.def_path_str(values.found);
                 }
-                report_maybe_different(
-                    f,
-                    &format!("trait `{expected}`"),
-                    &format!("trait `{found}`"),
-                )
-            }),
+                report_maybe_different(&format!("trait `{expected}`"), &format!("trait `{found}`"))
+            }
             IntMismatch(ref values) => {
                 let expected = match values.expected {
                     ty::IntVarValue::IntType(ty) => ty.name_str(),
@@ -190,41 +175,34 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
                     ty::IntVarValue::IntType(ty) => ty.name_str(),
                     ty::IntVarValue::UintType(ty) => ty.name_str(),
                 };
-                write!(f, "expected `{}`, found `{}`", expected, found)
+                format!("expected `{}`, found `{}`", expected, found)
             }
             FloatMismatch(ref values) => {
-                write!(
-                    f,
+                format!(
                     "expected `{}`, found `{}`",
                     values.expected.name_str(),
                     values.found.name_str()
                 )
             }
-            VariadicMismatch(ref values) => write!(
-                f,
+            VariadicMismatch(ref values) => format!(
                 "expected {} fn, found {} function",
                 if values.expected { "variadic" } else { "non-variadic" },
                 if values.found { "variadic" } else { "non-variadic" }
             ),
-            ProjectionMismatched(ref values) => ty::tls::with(|tcx| {
-                write!(
-                    f,
-                    "expected {}, found {}",
-                    tcx.def_path_str(values.expected),
-                    tcx.def_path_str(values.found)
-                )
-            }),
+            ProjectionMismatched(ref values) => format!(
+                "expected {}, found {}",
+                tcx.def_path_str(values.expected),
+                tcx.def_path_str(values.found)
+            ),
             ExistentialMismatch(ref values) => report_maybe_different(
-                f,
                 &format!("trait `{}`", values.expected),
                 &format!("trait `{}`", values.found),
             ),
             ConstMismatch(ref values) => {
-                write!(f, "expected `{}`, found `{}`", values.expected, values.found)
+                format!("expected `{}`, found `{}`", values.expected, values.found)
             }
-            IntrinsicCast => write!(f, "cannot coerce intrinsics to function pointers"),
-            TargetFeatureCast(_) => write!(
-                f,
+            IntrinsicCast => format!("cannot coerce intrinsics to function pointers"),
+            TargetFeatureCast(_) => format!(
                 "cannot coerce functions with `#[target_feature]` to safe function pointers"
             ),
         }
@@ -259,60 +237,9 @@ impl<'tcx> TypeError<'tcx> {
 }
 
 impl<'tcx> Ty<'tcx> {
-    pub fn sort_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
+    pub fn sort_string(self, tcx: TyCtxt<'tcx>) -> String {
         match *self.kind() {
-            ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => {
-                format!("`{}`", self).into()
-            }
-            ty::Tuple(ref tys) if tys.is_empty() => format!("`{}`", self).into(),
-
-            ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did())).into(),
             ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
-            ty::Array(t, n) => {
-                if t.is_simple_ty() {
-                    return format!("array `{}`", self).into();
-                }
-
-                let n = tcx.lift(n).unwrap();
-                if let ty::ConstKind::Value(v) = n.kind() {
-                    if let Some(n) = v.try_to_machine_usize(tcx) {
-                        return format!("array of {} element{}", n, pluralize!(n)).into();
-                    }
-                }
-                "array".into()
-            }
-            ty::Slice(ty) if ty.is_simple_ty() => format!("slice `{}`", self).into(),
-            ty::Slice(_) => "slice".into(),
-            ty::RawPtr(tymut) => {
-                let tymut_string = match tymut.mutbl {
-                    hir::Mutability::Mut => tymut.to_string(),
-                    hir::Mutability::Not => format!("const {}", tymut.ty),
-                };
-
-                if tymut_string != "_" && (tymut.ty.is_simple_text() || tymut_string.len() < "const raw pointer".len()) {
-                    format!("`*{}`", tymut_string).into()
-                } else {
-                    // Unknown type name, it's long or has type arguments
-                    "raw pointer".into()
-                }
-            },
-            ty::Ref(_, ty, mutbl) => {
-                let tymut = ty::TypeAndMut { ty, mutbl };
-                let tymut_string = tymut.to_string();
-
-                if tymut_string != "_"
-                    && (ty.is_simple_text() || tymut_string.len() < "mutable reference".len())
-                {
-                    format!("`&{}`", tymut_string).into()
-                } else {
-                    // Unknown type name, it's long or has type arguments
-                    match mutbl {
-                        hir::Mutability::Mut => "mutable reference",
-                        _ => "reference",
-                    }
-                    .into()
-                }
-            }
             ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
                 DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
                 DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
@@ -320,14 +247,13 @@ impl<'tcx> Ty<'tcx> {
             },
             ty::FnPtr(_) => "fn pointer".into(),
             ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => {
-                format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
+                format!("`dyn {}`", tcx.def_path_str(principal.def_id()))
             }
             ty::Dynamic(..) => "trait object".into(),
             ty::Closure(..) => "closure".into(),
             ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
             ty::GeneratorWitness(..) |
             ty::GeneratorWitnessMIR(..) => "generator witness".into(),
-            ty::Tuple(..) => "tuple".into(),
             ty::Infer(ty::TyVar(_)) => "inferred type".into(),
             ty::Infer(ty::IntVar(_)) => "integer".into(),
             ty::Infer(ty::FloatVar(_)) => "floating-point number".into(),
@@ -337,9 +263,14 @@ impl<'tcx> Ty<'tcx> {
             ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
             ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
             ty::Alias(ty::Projection, _) => "associated type".into(),
-            ty::Param(p) => format!("type parameter `{}`", p).into(),
+            ty::Param(p) => format!("type parameter `{p}`").into(),
             ty::Alias(ty::Opaque, ..) => "opaque type".into(),
             ty::Error(_) => "type error".into(),
+            _ => {
+                let width = tcx.sess.diagnostic_width();
+                let length_limit = std::cmp::max(width / 4, 15);
+                format!("`{}`", tcx.ty_string_with_limit(self, length_limit))
+            }
         }
     }
 
@@ -386,16 +317,14 @@ impl<'tcx> Ty<'tcx> {
 }
 
 impl<'tcx> TyCtxt<'tcx> {
-    pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
-        let width = self.sess.diagnostic_width();
-        let length_limit = width.saturating_sub(30);
+    pub fn ty_string_with_limit(self, ty: Ty<'tcx>, length_limit: usize) -> String {
         let mut type_limit = 50;
         let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
             .pretty_print_type(ty)
             .expect("could not write to `String`")
             .into_buffer();
-        if regular.len() <= width {
-            return (regular, None);
+        if regular.len() <= length_limit {
+            return regular;
         }
         let mut short;
         loop {
@@ -415,6 +344,20 @@ impl<'tcx> TyCtxt<'tcx> {
             }
             type_limit -= 1;
         }
+        short
+    }
+
+    pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
+        let width = self.sess.diagnostic_width();
+        let length_limit = width.saturating_sub(30);
+        let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
+            .pretty_print_type(ty)
+            .expect("could not write to `String`")
+            .into_buffer();
+        if regular.len() <= width {
+            return (regular, None);
+        }
+        let short = self.ty_string_with_limit(ty, length_limit);
         if regular == short {
             return (regular, None);
         }