about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/ty/context.rs16
-rw-r--r--src/librustc/ty/sty.rs35
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs7
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_errors.rs16
-rw-r--r--src/librustc_mir/borrow_check/universal_regions.rs23
5 files changed, 83 insertions, 14 deletions
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index e59738d8886..fd2f58d24f8 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -209,7 +209,7 @@ fn validate_hir_id_for_typeck_tables(
             ty::tls::with(|tcx| {
                 bug!(
                     "node {} with HirId::owner {:?} cannot be placed in \
-                        TypeckTables with local_id_root {:?}",
+                     TypeckTables with local_id_root {:?}",
                     tcx.hir().node_to_string(hir_id),
                     DefId::local(hir_id.owner),
                     local_id_root
@@ -1512,6 +1512,20 @@ impl<'tcx> TyCtxt<'tcx> {
                 .subst(*self, self.mk_substs([self.lifetimes.re_static.into()].iter())),
         )
     }
+
+    /// Returns a displayable description and article for the given `def_id` (e.g. `("a", "closure")`).
+    pub fn article_and_description(
+        &self,
+        def_id: crate::hir::def_id::DefId,
+    ) -> (&'static str, &'static str) {
+        self.def_kind(def_id).map_or_else(
+            || {
+                // TODO: is it a problem to try to use the ty here?
+                self.type_of(def_id).kind.article_and_description()
+            },
+            |def_kind| (def_kind.article(), def_kind.descr(def_id)),
+        )
+    }
 }
 
 impl<'tcx> GlobalCtxt<'tcx> {
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index c3698f402a9..a54bf4d7eff 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -254,6 +254,41 @@ pub enum TyKind<'tcx> {
     Error,
 }
 
+impl<'tcx> TyKind<'tcx> {
+    pub fn article_and_description(&self) -> (&'static str, &'static str) {
+        match *self {
+            Bool => ("a", "boolean value"),
+            Char => ("a", "character"),
+            Int(..) => ("a", "signed interger"),
+            Uint(..) => ("an", "unsigned integer"),
+            Float(..) => ("a", "floating point number"),
+            Adt(..) => ("an", "abstract data type"),
+            Foreign(..) => ("a", "foreign type"),
+            Str => ("a", "string slice"),
+            Array(..) => ("an", "array"),
+            Slice(..) => ("a", "slice"),
+            RawPtr(..) => ("a", "raw pointer"),
+            Ref(..) => ("a", "reference"),
+            FnDef(..) => ("a", "function"),
+            FnPtr(..) => ("a", "function pointer"),
+            Dynamic(..) => ("a", "trait object"),
+            Closure(..) => ("a", "closure"),
+            Generator(..) => ("a", "generator"),
+            GeneratorWitness(..) => ("a", "generator witness"),
+            Never => ("a", "never"),
+            Tuple(..) => ("a", "tuple"),
+            Projection(..) => ("a", "projection"),
+            UnnormalizedProjection(..) => ("an", "unnormalized projection"),
+            Opaque(..) => ("an", "opaque type"),
+            Param(..) => ("a", "type parameter"),
+            Bound(..) => ("a", "bound type variable"),
+            Placeholder(..) => ("a", "universally quantified higher-ranked type"),
+            Infer(..) => ("an", "inference variable"),
+            Error => ("a", "type error"),
+        }
+    }
+}
+
 // `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
 static_assert_size!(TyKind<'_>, 24);
diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index 0ed7dd03f3a..41a99d1125b 100644
--- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -1257,7 +1257,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
             _ => bug!(
                 "report_escaping_closure_capture called with unexpected constraint \
-                       category: `{:?}`",
+                 category: `{:?}`",
                 category
             ),
         };
@@ -1279,8 +1279,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             let tables = tcx.typeck_tables_of(self.mir_def_id);
             let mir_hir_id = tcx.hir().def_index_to_hir_id(self.mir_def_id.index);
             match tables.node_type(mir_hir_id).kind {
-                ty::Closure(..) => "closure",
-                ty::Generator(..) => "generator",
+                ref kind @ ty::Closure(..) | ref kind @ ty::Generator(..) => {
+                    kind.article_and_description().1
+                }
                 _ => bug!("Closure body doesn't have a closure or generator type"),
             }
         } else {
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index a3e0e51c5b6..0f0fd64844a 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -427,18 +427,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             errci.outlived_fr,
         );
 
-        let escapes_from = match self.regioncx.universal_regions().defining_ty {
-            DefiningTy::Closure(..) => "closure",
-            DefiningTy::Generator(..) => "generator",
-            DefiningTy::FnDef(..) => "function",
-            DefiningTy::Const(..) => "const",
-        };
+        let (_, escapes_from) =
+            self.infcx.tcx.article_and_description(self.universal_regions.defining_ty.def_id());
 
         // Revert to the normal error in these cases.
         // Assignments aren't "escapes" in function items.
         if (fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none())
-            || (*category == ConstraintCategory::Assignment && escapes_from == "function")
-            || escapes_from == "const"
+            || (*category == ConstraintCategory::Assignment
+                && self.universal_regions.defining_ty.is_fn_def())
+            || self.universal_regions.defining_ty.is_closure()
         {
             return self.report_general_error(&ErrorConstraintInfo {
                 fr_is_local: true,
@@ -504,8 +501,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let mut diag =
             self.infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough");
 
-        let mir_def_name =
-            if self.infcx.tcx.is_closure(self.mir_def_id) { "closure" } else { "function" };
+        let (_, mir_def_name) = self.infcx.tcx.article_and_description(self.mir_def_id);
 
         let fr_name = self.give_region_a_name(*fr).unwrap();
         fr_name.highlight_region_name(&mut diag);
diff --git a/src/librustc_mir/borrow_check/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs
index 0913de63e8e..777eea22eb6 100644
--- a/src/librustc_mir/borrow_check/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/universal_regions.rs
@@ -131,6 +131,29 @@ impl<'tcx> DefiningTy<'tcx> {
             DefiningTy::FnDef(..) | DefiningTy::Const(..) => 0,
         }
     }
+
+    pub fn is_closure(&self) -> bool {
+        match *self {
+            DefiningTy::Closure(..) => true,
+            _ => false,
+        }
+    }
+
+    pub fn is_fn_def(&self) -> bool {
+        match *self {
+            DefiningTy::FnDef(..) => true,
+            _ => false,
+        }
+    }
+
+    pub fn def_id(&self) -> DefId {
+        match *self {
+            DefiningTy::Closure(def_id, ..) => def_id,
+            DefiningTy::Generator(def_id, ..) => def_id,
+            DefiningTy::FnDef(def_id, ..) => def_id,
+            DefiningTy::Const(def_id, ..) => def_id,
+        }
+    }
 }
 
 #[derive(Debug)]