about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs32
-rw-r--r--src/test/ui/nll/user-annotations/promoted-annotation.rs12
-rw-r--r--src/test/ui/nll/user-annotations/promoted-annotation.stderr17
3 files changed, 46 insertions, 15 deletions
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 4929c69d873..9fa3bf55247 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -39,7 +39,8 @@ use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::{Subst, SubstsRef, UnpackedKind, UserSubsts};
 use rustc::ty::{
     self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind, UserType,
-    CanonicalUserTypeAnnotation, UserTypeAnnotationIndex,
+    CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
+    UserTypeAnnotationIndex,
 };
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
@@ -283,7 +284,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 location.to_locations(),
                 ConstraintCategory::Boring,
             ) {
-                let annotation = &self.mir.user_type_annotations[annotation_index];
+                let annotation = &self.cx.user_type_annotations[annotation_index];
                 span_mirbug!(
                     self,
                     constant,
@@ -550,8 +551,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
         // checker on the promoted MIR, then transfer the constraints back to
         // the main MIR, changing the locations to the provided location.
 
-        let main_mir = mem::replace(&mut self.mir, promoted_mir);
-        self.cx.mir = promoted_mir;
+        let parent_mir = mem::replace(&mut self.mir, promoted_mir);
 
         let all_facts = &mut None;
         let mut constraints = Default::default();
@@ -573,8 +573,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
             self.cx.typeck_mir(promoted_mir);
         }
 
-        self.mir = main_mir;
-        self.cx.mir = main_mir;
+        self.mir = parent_mir;
         // Merge the outlives constraints back in, at the given location.
         if let Some(ref mut base_bcx) = self.cx.borrowck_context {
             mem::swap(base_bcx.all_facts, all_facts);
@@ -818,7 +817,9 @@ struct TypeChecker<'a, 'gcx: 'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     param_env: ty::ParamEnv<'gcx>,
     last_span: Span,
-    mir: &'a Mir<'tcx>,
+    /// User type annotations are shared between the main MIR and the MIR of
+    /// all of the promoted items.
+    user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
     mir_def_id: DefId,
     region_bound_pairs: &'a RegionBoundPairs<'tcx>,
     implicit_region_bound: Option<ty::Region<'tcx>>,
@@ -973,8 +974,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         let mut checker = Self {
             infcx,
             last_span: DUMMY_SP,
-            mir,
             mir_def_id,
+            user_type_annotations: &mir.user_type_annotations,
             param_env,
             region_bound_pairs,
             implicit_region_bound,
@@ -990,9 +991,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     fn check_user_type_annotations(&mut self) {
         debug!(
             "check_user_type_annotations: user_type_annotations={:?}",
-             self.mir.user_type_annotations
+             self.user_type_annotations
         );
-        for user_annotation in &self.mir.user_type_annotations {
+        for user_annotation in self.user_type_annotations {
             let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
             let (annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
                 span, user_ty
@@ -1175,7 +1176,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             a, v, user_ty, locations,
         );
 
-        let annotated_type = self.mir.user_type_annotations[user_ty.base].inferred_ty;
+        let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
         let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
 
         let tcx = self.infcx.tcx;
@@ -1361,7 +1362,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                         location.to_locations(),
                         ConstraintCategory::Boring,
                     ) {
-                        let annotation = &mir.user_type_annotations[annotation_index];
+                        let annotation = &self.user_type_annotations[annotation_index];
                         span_mirbug!(
                             self,
                             stmt,
@@ -1420,7 +1421,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     Locations::All(stmt.source_info.span),
                     ConstraintCategory::TypeAnnotation,
                 ) {
-                    let annotation = &mir.user_type_annotations[projection.base];
+                    let annotation = &self.user_type_annotations[projection.base];
                     span_mirbug!(
                         self,
                         stmt,
@@ -2078,7 +2079,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             }
 
             Rvalue::Ref(region, _borrow_kind, borrowed_place) => {
-                self.add_reborrow_constraint(location, region, borrowed_place);
+                self.add_reborrow_constraint(mir, location, region, borrowed_place);
             }
 
             // FIXME: These other cases have to be implemented in future PRs
@@ -2177,6 +2178,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     /// - `borrowed_place`: the place `P` being borrowed
     fn add_reborrow_constraint(
         &mut self,
+        mir: &Mir<'tcx>,
         location: Location,
         borrow_region: ty::Region<'tcx>,
         borrowed_place: &Place<'tcx>,
@@ -2226,7 +2228,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             match *elem {
                 ProjectionElem::Deref => {
                     let tcx = self.infcx.tcx;
-                    let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
+                    let base_ty = base.ty(mir, tcx).to_ty(tcx);
 
                     debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
                     match base_ty.sty {
diff --git a/src/test/ui/nll/user-annotations/promoted-annotation.rs b/src/test/ui/nll/user-annotations/promoted-annotation.rs
new file mode 100644
index 00000000000..fa2d2fb8118
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/promoted-annotation.rs
@@ -0,0 +1,12 @@
+// Test that type annotations are checked in promoted constants correctly.
+
+#![feature(nll)]
+
+fn foo<'a>() {
+    let x = 0;
+    let f = &drop::<&'a i32>;
+    f(&x);
+    //~^ ERROR `x` does not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/user-annotations/promoted-annotation.stderr b/src/test/ui/nll/user-annotations/promoted-annotation.stderr
new file mode 100644
index 00000000000..144af1e0ec1
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/promoted-annotation.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/promoted-annotation.rs:8:7
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let x = 0;
+LL |     let f = &drop::<&'a i32>;
+   |             ---------------- assignment requires that `x` is borrowed for `'a`
+LL |     f(&x);
+   |       ^^ borrowed value does not live long enough
+LL |     //~^ ERROR `x` does not live long enough
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.