]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/ty/error.rs
Rollup merge of #66503 - thomasetter:panic-error-msg, r=joshtriplett
[rust.git] / src / librustc / ty / error.rs
index c61d559af53f5867db3b641a4c2b515aa4ed9255..be6d21564a0f1bd939feba5ac2ba062bab561532 100644 (file)
@@ -1,23 +1,24 @@
+use crate::hir;
 use crate::hir::def_id::DefId;
 use crate::ty::{self, BoundRegion, Region, Ty, TyCtxt};
-use std::borrow::Cow;
-use std::fmt;
+
+use errors::{Applicability, DiagnosticBuilder};
 use rustc_target::spec::abi;
 use syntax::ast;
 use syntax::errors::pluralize;
-use errors::{Applicability, DiagnosticBuilder};
 use syntax_pos::Span;
 
-use crate::hir;
+use std::borrow::Cow;
+use std::fmt;
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable)]
 pub struct ExpectedFound<T> {
     pub expected: T,
     pub found: T,
 }
 
 // Data structures used in type unification
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, TypeFoldable)]
 pub enum TypeError<'tcx> {
     Mismatch,
     UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
@@ -64,8 +65,11 @@ pub enum UnconstrainedNumeric {
 impl<'tcx> fmt::Display for TypeError<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         use self::TypeError::*;
-        fn report_maybe_different(f: &mut fmt::Formatter<'_>,
-                                  expected: &str, found: &str) -> fmt::Result {
+        fn report_maybe_different(
+            f: &mut fmt::Formatter<'_>,
+            expected: &str,
+            found: &str,
+        ) -> fmt::Result {
             // A naive approach to making sure that we're not reporting silly errors such as:
             // (expected closure, found closure).
             if expected == found {
@@ -183,46 +187,77 @@ fn report_maybe_different(f: &mut fmt::Formatter<'_>,
     }
 }
 
+impl<'tcx> TypeError<'tcx> {
+    pub fn must_include_note(&self) -> bool {
+        use self::TypeError::*;
+        match self {
+            CyclicTy(_) |
+            UnsafetyMismatch(_) |
+            Mismatch |
+            AbiMismatch(_) |
+            FixedArraySize(_) |
+            Sorts(_) |
+            IntMismatch(_) |
+            FloatMismatch(_) |
+            VariadicMismatch(_) => false,
+
+            Mutability |
+            TupleSize(_) |
+            ArgCount |
+            RegionsDoesNotOutlive(..) |
+            RegionsInsufficientlyPolymorphic(..) |
+            RegionsOverlyPolymorphic(..) |
+            RegionsPlaceholderMismatch |
+            Traits(_) |
+            ProjectionMismatched(_) |
+            ProjectionBoundsLength(_) |
+            ExistentialMismatch(_) |
+            ConstMismatch(_) |
+            IntrinsicCast |
+            ObjectUnsafeCoercion(_) => true,
+        }
+    }
+}
+
 impl<'tcx> ty::TyS<'tcx> {
     pub fn sort_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
         match self.kind {
             ty::Bool | ty::Char | ty::Int(_) |
-            ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => self.to_string().into(),
-            ty::Tuple(ref tys) if tys.is_empty() => self.to_string().into(),
+            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(_, n) => {
+            ty::Array(t, n) => {
                 let n = tcx.lift(&n).unwrap();
                 match n.try_eval_usize(tcx, ty::ParamEnv::empty()) {
-                    Some(n) => {
-                        format!("array of {} element{}", n, pluralize!(n)).into()
-                    }
+                    _ if t.is_simple_ty() => format!("array `{}`", self).into(),
+                    Some(n) => format!("array of {} element{} ", n, pluralize!(n)).into(),
                     None => "array".into(),
                 }
             }
+            ty::Slice(ty) if ty.is_simple_ty() => format!("slice `{}`", self).into(),
             ty::Slice(_) => "slice".into(),
             ty::RawPtr(_) => "*-ptr".into(),
-            ty::Ref(region, ty, mutbl) => {
+            ty::Ref(_, ty, mutbl) => {
                 let tymut = ty::TypeAndMut { ty, mutbl };
                 let tymut_string = tymut.to_string();
-                if tymut_string == "_" ||         //unknown type name,
-                   tymut_string.len() > 10 ||     //name longer than saying "reference",
-                   region.to_string() != "'_"     //... or a complex type
-                {
-                    format!("{}reference", match mutbl {
-                        hir::Mutability::Mutable => "mutable ",
-                        _ => ""
-                    }).into()
-                } else {
-                    format!("&{}", tymut_string).into()
+                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::Mutable => "mutable reference",
+                        _ => "reference",
+                    }.into()
                 }
             }
             ty::FnDef(..) => "fn item".into(),
             ty::FnPtr(_) => "fn pointer".into(),
             ty::Dynamic(ref inner, ..) => {
                 if let Some(principal) = inner.principal() {
-                    format!("trait {}", tcx.def_path_str(principal.def_id())).into()
+                    format!("trait `{}`", tcx.def_path_str(principal.def_id())).into()
                 } else {
                     "trait".into()
                 }
@@ -246,6 +281,36 @@ pub fn sort_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
             ty::Error => "type error".into(),
         }
     }
+
+    pub fn prefix_string(&self) -> Cow<'static, str> {
+        match self.kind {
+            ty::Infer(_) | ty::Error | ty::Bool | ty::Char | ty::Int(_) |
+            ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => "type".into(),
+            ty::Tuple(ref tys) if tys.is_empty() => "unit type".into(),
+            ty::Adt(def, _) => def.descr().into(),
+            ty::Foreign(_) => "extern type".into(),
+            ty::Array(..) => "array".into(),
+            ty::Slice(_) => "slice".into(),
+            ty::RawPtr(_) => "raw pointer".into(),
+            ty::Ref(.., mutbl) => match mutbl {
+                hir::Mutability::Mutable => "mutable reference",
+                _ => "reference"
+            }.into(),
+            ty::FnDef(..) => "fn item".into(),
+            ty::FnPtr(_) => "fn pointer".into(),
+            ty::Dynamic(..) => "trait object".into(),
+            ty::Closure(..) => "closure".into(),
+            ty::Generator(..) => "generator".into(),
+            ty::GeneratorWitness(..) => "generator witness".into(),
+            ty::Tuple(..) => "tuple".into(),
+            ty::Placeholder(..) => "higher-ranked type".into(),
+            ty::Bound(..) => "bound type variable".into(),
+            ty::Projection(_) => "associated type".into(),
+            ty::UnnormalizedProjection(_) => "associated type".into(),
+            ty::Param(_) => "type parameter".into(),
+            ty::Opaque(..) => "opaque type".into(),
+        }
+    }
 }
 
 impl<'tcx> TyCtxt<'tcx> {