about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2017-12-04 05:40:43 -0500
committerNiko Matsakis <niko@alum.mit.edu>2017-12-15 10:27:50 -0500
commitc7cfa2367b0ad4aed16dff7ad3d8d3e9eea6540a (patch)
tree6a9f663c0e4649eb5e47614389ac6b43e05c58ad
parent154cd9419763f35c0f38b1cb044f43eeece1ebf0 (diff)
downloadrust-c7cfa2367b0ad4aed16dff7ad3d8d3e9eea6540a.tar.gz
rust-c7cfa2367b0ad4aed16dff7ad3d8d3e9eea6540a.zip
thread through an implicit region body of the fn body
-rw-r--r--src/librustc_mir/borrow_check/nll/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/mod.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs28
-rw-r--r--src/librustc_mir/borrow_check/nll/universal_regions.rs15
-rw-r--r--src/test/mir-opt/nll/named-lifetimes-basic.rs10
-rw-r--r--src/test/mir-opt/nll/reborrow-basic.rs8
-rw-r--r--src/test/mir-opt/nll/region-liveness-basic.rs8
-rw-r--r--src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs4
-rw-r--r--src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs4
-rw-r--r--src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs12
-rw-r--r--src/test/mir-opt/nll/region-subtyping-basic.rs12
-rw-r--r--src/test/ui/nll/capture-ref-in-struct.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/escape-argument.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr2
-rw-r--r--src/test/ui/nll/ty-outlives/projection-fn.stderr4
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn-body.rs41
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr14
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn.stderr4
20 files changed, 135 insertions, 45 deletions
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index 3329448e2b7..9e7c94cd7ff 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -78,11 +78,13 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     // Run the MIR type-checker.
     let mir_node_id = infcx.tcx.hir.as_local_node_id(def_id).unwrap();
     let liveness = &LivenessResults::compute(mir);
+    let fr_fn_body = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
     let constraint_sets = &type_check::type_check(
         infcx,
         mir_node_id,
         param_env,
         mir,
+        fr_fn_body,
         &liveness,
         flow_inits,
         move_data,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index efa0734b016..4759185d226 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -439,6 +439,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// have no evidence that `'b` outlives `'a`, so we want to report
     /// an error.
     fn check_type_tests(&self, infcx: &InferCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) {
+        let tcx = infcx.tcx;
+
         for type_test in &self.type_tests {
             debug!("check_type_test: {:?}", type_test);
 
@@ -452,7 +454,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             }
 
             // Oh the humanity. Obviously we will do better than this error eventually.
-            infcx.tcx.sess.span_err(
+            tcx.sess.span_err(
                 type_test.span,
                 &format!("failed type test: {:?}", type_test),
             );
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 8f18105600a..f7493f653e0 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -51,13 +51,19 @@ pub(crate) fn type_check<'gcx, 'tcx>(
     body_id: ast::NodeId,
     param_env: ty::ParamEnv<'gcx>,
     mir: &Mir<'tcx>,
+    implicit_region_bound: ty::Region<'tcx>,
     liveness: &LivenessResults,
     flow_inits: &mut FlowAtLocation<MaybeInitializedLvals<'_, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
 ) -> MirTypeckRegionConstraints<'tcx> {
-    type_check_internal(infcx, body_id, param_env, mir, &mut |cx| {
-        liveness::generate(cx, mir, liveness, flow_inits, move_data)
-    })
+    type_check_internal(
+        infcx,
+        body_id,
+        param_env,
+        mir,
+        Some(implicit_region_bound),
+        &mut |cx| liveness::generate(cx, mir, liveness, flow_inits, move_data),
+    )
 }
 
 fn type_check_internal<'gcx, 'tcx>(
@@ -65,9 +71,10 @@ fn type_check_internal<'gcx, 'tcx>(
     body_id: ast::NodeId,
     param_env: ty::ParamEnv<'gcx>,
     mir: &Mir<'tcx>,
+    implicit_region_bound: Option<ty::Region<'tcx>>,
     extra: &mut FnMut(&mut TypeChecker<'_, 'gcx, 'tcx>),
 ) -> MirTypeckRegionConstraints<'tcx> {
-    let mut checker = TypeChecker::new(infcx, body_id, param_env);
+    let mut checker = TypeChecker::new(infcx, body_id, param_env, implicit_region_bound);
     let errors_reported = {
         let mut verifier = TypeVerifier::new(&mut checker, mir);
         verifier.visit_mir(mir);
@@ -535,6 +542,7 @@ struct TypeChecker<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     param_env: ty::ParamEnv<'gcx>,
     last_span: Span,
     body_id: ast::NodeId,
+    implicit_region_bound: Option<ty::Region<'tcx>>,
     reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
     constraints: MirTypeckRegionConstraints<'tcx>,
 }
@@ -588,12 +596,14 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
         body_id: ast::NodeId,
         param_env: ty::ParamEnv<'gcx>,
+        implicit_region_bound: Option<ty::Region<'tcx>>,
     ) -> Self {
         TypeChecker {
             infcx,
             last_span: DUMMY_SP,
             body_id,
             param_env,
+            implicit_region_bound,
             reported_errors: FxHashSet(),
             constraints: MirTypeckRegionConstraints::default(),
         }
@@ -618,8 +628,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             span_mirbug!(self, "", "errors selecting obligation: {:?}", e);
         }
 
-        self.infcx
-            .process_registered_region_obligations(&[], None, self.param_env, self.body_id);
+        self.infcx.process_registered_region_obligations(
+            &[],
+            self.implicit_region_bound,
+            self.param_env,
+            self.body_id,
+        );
 
         let data = self.infcx.take_and_reset_region_constraints();
         if !data.is_empty() {
@@ -1501,7 +1515,7 @@ impl MirPass for TypeckMir {
         }
         let param_env = tcx.param_env(def_id);
         tcx.infer_ctxt().enter(|infcx| {
-            let _ = type_check_internal(&infcx, id, param_env, mir, &mut |_| ());
+            let _ = type_check_internal(&infcx, id, param_env, mir, None, &mut |_| ());
 
             // For verification purposes, we just ignore the resulting
             // region constraint sets. Not our problem. =)
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index 5336bd271f5..ce931a68a0c 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -45,6 +45,11 @@ pub struct UniversalRegions<'tcx> {
     /// The vid assigned to `'static`
     pub fr_static: RegionVid,
 
+    /// A special region vid created to represent the current MIR fn
+    /// body.  It will outlive the entire CFG but it will not outlive
+    /// any other universal regions.
+    pub fr_fn_body: RegionVid,
+
     /// We create region variables such that they are ordered by their
     /// `RegionClassification`. The first block are globals, then
     /// externals, then locals. So things from:
@@ -408,6 +413,7 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
         let first_local_index = self.infcx.num_region_vars();
         let inputs_and_output = self.infcx
             .replace_bound_regions_with_nll_infer_vars(FR, &bound_inputs_and_output);
+        let fr_fn_body = self.infcx.next_nll_region_var(FR).to_region_vid();
         let num_universals = self.infcx.num_region_vars();
 
         // Insert the facts we know from the predicates. Why? Why not.
@@ -419,12 +425,16 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
             self.add_implied_bounds(&indices, ty);
         }
 
-        // Finally, outlives is reflexive, and static outlives every
-        // other free region.
+        // Finally:
+        // - outlives is reflexive, so `'r: 'r` for every region `'r`
+        // - `'static: 'r` for every region `'r`
+        // - `'r: 'fn_body` for every (other) universally quantified
+        //   region `'r`, all of which are provided by our caller
         for fr in (FIRST_GLOBAL_INDEX..num_universals).map(RegionVid::new) {
             debug!("build: relating free region {:?} to itself and to 'static", fr);
             self.relations.relate_universal_regions(fr, fr);
             self.relations.relate_universal_regions(fr_static, fr);
+            self.relations.relate_universal_regions(fr, fr_fn_body);
         }
 
         let (output_ty, input_tys) = inputs_and_output.split_last().unwrap();
@@ -445,6 +455,7 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
         UniversalRegions {
             indices,
             fr_static,
+            fr_fn_body,
             first_extern_index,
             first_local_index,
             num_universals,
diff --git a/src/test/mir-opt/nll/named-lifetimes-basic.rs b/src/test/mir-opt/nll/named-lifetimes-basic.rs
index f3a57c08840..71304f71b61 100644
--- a/src/test/mir-opt/nll/named-lifetimes-basic.rs
+++ b/src/test/mir-opt/nll/named-lifetimes-basic.rs
@@ -27,16 +27,18 @@ fn main() {
 // END RUST SOURCE
 // START rustc.use_x.nll.0.mir
 // | Free Region Mapping
-// | '_#0r    | Global   | ['_#2r, '_#1r, '_#0r, '_#3r]
-// | '_#1r    | External | ['_#1r]
-// | '_#2r    | External | ['_#2r, '_#1r]
-// | '_#3r    | Local    | ['_#3r]
+// | '_#0r    | Global   | ['_#2r, '_#1r, '_#0r, '_#4r, '_#3r]
+// | '_#1r    | External | ['_#1r, '_#4r]
+// | '_#2r    | External | ['_#2r, '_#1r, '_#4r]
+// | '_#3r    | Local    | ['_#4r, '_#3r]
+// | '_#4r    | Local    | ['_#4r]
 // |
 // | Inferred Region Values
 // | '_#0r    | {'_#0r, bb0[0], bb0[1]}
 // | '_#1r    | {'_#1r, bb0[0], bb0[1]}
 // | '_#2r    | {'_#2r, bb0[0], bb0[1]}
 // | '_#3r    | {'_#3r, bb0[0], bb0[1]}
+// | '_#4r    | {'_#4r, bb0[0], bb0[1]}
 // |
 // ...
 // fn use_x(_1: &'_#1r mut i32, _2: &'_#2r u32, _3: &'_#1r u32, _4: &'_#3r u32) -> bool {
diff --git a/src/test/mir-opt/nll/reborrow-basic.rs b/src/test/mir-opt/nll/reborrow-basic.rs
index d203472f20c..9e6d6aaee15 100644
--- a/src/test/mir-opt/nll/reborrow-basic.rs
+++ b/src/test/mir-opt/nll/reborrow-basic.rs
@@ -28,11 +28,11 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#6r    | {bb0[6], bb0[7], bb0[8], bb0[9], bb0[10], bb0[11], bb0[12], bb0[13], bb0[14]}
+// | '_#7r    | {bb0[6], bb0[7], bb0[8], bb0[9], bb0[10], bb0[11], bb0[12], bb0[13], bb0[14]}
 // ...
-// | '_#8r    | {bb0[11], bb0[12], bb0[13], bb0[14]}
+// | '_#9r    | {bb0[11], bb0[12], bb0[13], bb0[14]}
 // ...
-// let _2: &'_#6r mut i32;
+// let _2: &'_#7r mut i32;
 // ...
-// let _4: &'_#8r mut i32;
+// let _4: &'_#9r mut i32;
 // END rustc.main.nll.0.mir
diff --git a/src/test/mir-opt/nll/region-liveness-basic.rs b/src/test/mir-opt/nll/region-liveness-basic.rs
index c04cedbc04b..ab99d79d7f3 100644
--- a/src/test/mir-opt/nll/region-liveness-basic.rs
+++ b/src/test/mir-opt/nll/region-liveness-basic.rs
@@ -31,15 +31,15 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#1r    | {bb2[0], bb2[1], bb3[0], bb3[1]}
-// | '_#2r    | {bb2[1], bb3[0], bb3[1]}
+// | '_#2r    | {bb2[0], bb2[1], bb3[0], bb3[1]}
+// | '_#3r    | {bb2[1], bb3[0], bb3[1]}
 // ...
-//             let _2: &'_#2r usize;
+//             let _2: &'_#3r usize;
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
 //    bb2: {
 //            | Live variables on entry to bb2[0]: [_1, _3]
-//        _2 = &'_#1r _1[_3];
+//        _2 = &'_#2r _1[_3];
 //            | Live variables on entry to bb2[1]: [_2]
 //        switchInt(const true) -> [0u8: bb4, otherwise: bb3];
 //    }
diff --git a/src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs b/src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs
index e2ad49a4436..515772a9427 100644
--- a/src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs
+++ b/src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs
@@ -44,5 +44,7 @@ unsafe impl<#[may_dangle] T> Drop for Wrap<T> {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#5r    | {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1]}
+// | '_#6r    | {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1]}
+// ...
+// let _2: Wrap<&'_#6r usize>;
 // END rustc.main.nll.0.mir
diff --git a/src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs b/src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs
index e0272a51d03..a257910b0b8 100644
--- a/src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs
+++ b/src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs
@@ -46,5 +46,7 @@ impl<T> Drop for Wrap<T> {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#5r    | {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1], bb3[2], bb4[0], bb5[0], bb5[1], bb5[2], bb6[0], bb7[0], bb7[1], bb8[0]}
+// | '_#6r    | {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1], bb3[2], bb4[0], bb5[0], bb5[1], bb5[2], bb6[0], bb7[0], bb7[1], bb8[0]}
+// ...
+// let _2: Wrap<&'_#6r usize>;
 // END rustc.main.nll.0.mir
diff --git a/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs b/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs
index 8aa0eb1a3a9..3041c2cb061 100644
--- a/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs
+++ b/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs
@@ -36,14 +36,14 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#1r    | {bb2[0], bb2[1], bb3[0], bb3[1]}
+// | '_#2r    | {bb2[0], bb2[1], bb3[0], bb3[1]}
 // ...
-// | '_#3r    | {bb8[1], bb8[2], bb8[3], bb8[4]}
-// | '_#4r    | {bb2[1], bb3[0], bb3[1], bb8[2], bb8[3], bb8[4]}
+// | '_#4r    | {bb8[1], bb8[2], bb8[3], bb8[4]}
+// | '_#5r    | {bb2[1], bb3[0], bb3[1], bb8[2], bb8[3], bb8[4]}
 // ...
-// let mut _2: &'_#4r usize;
+// let mut _2: &'_#5r usize;
 // ...
-// _2 = &'_#1r _1[_3];
+// _2 = &'_#2r _1[_3];
 // ...
-// _2 = &'_#3r (*_10);
+// _2 = &'_#4r (*_10);
 // END rustc.main.nll.0.mir
diff --git a/src/test/mir-opt/nll/region-subtyping-basic.rs b/src/test/mir-opt/nll/region-subtyping-basic.rs
index 2bc165bd3c4..5a3f831331c 100644
--- a/src/test/mir-opt/nll/region-subtyping-basic.rs
+++ b/src/test/mir-opt/nll/region-subtyping-basic.rs
@@ -32,16 +32,16 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#1r    | {bb2[0], bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]}
-// | '_#2r    | {bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]}
-// | '_#3r    | {bb2[5], bb2[6], bb3[0], bb3[1]}
+// | '_#2r    | {bb2[0], bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]}
+// | '_#3r    | {bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]}
+// | '_#4r    | {bb2[5], bb2[6], bb3[0], bb3[1]}
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
-// let _2: &'_#2r usize;
+// let _2: &'_#3r usize;
 // ...
-// let _6: &'_#3r usize;
+// let _6: &'_#4r usize;
 // ...
-// _2 = &'_#1r _1[_3];
+// _2 = &'_#2r _1[_3];
 // ...
 // _7 = _2;
 // ...
diff --git a/src/test/ui/nll/capture-ref-in-struct.stderr b/src/test/ui/nll/capture-ref-in-struct.stderr
index 6b57f91987b..9f62b2a41c5 100644
--- a/src/test/ui/nll/capture-ref-in-struct.stderr
+++ b/src/test/ui/nll/capture-ref-in-struct.stderr
@@ -7,7 +7,7 @@ error[E0597]: `y` does not live long enough
 37 |     }
    |      - borrowed value only lives until here
    |
-   = note: borrowed value must be valid for lifetime '_#4r...
+   = note: borrowed value must be valid for lifetime '_#5r...
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr
index 567ed299ac1..2b0e3661376 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr
@@ -32,7 +32,7 @@ error[E0597]: `y` does not live long enough
 39 |     }
    |      - borrowed value only lives until here
    |
-   = note: borrowed value must be valid for lifetime '_#5r...
+   = note: borrowed value must be valid for lifetime '_#6r...
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
index 6c70afa0c9c..ddda72c5686 100644
--- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
@@ -59,7 +59,7 @@ error[E0597]: `y` does not live long enough
 36 |       }
    |        - borrowed value only lives until here
    |
-   = note: borrowed value must be valid for lifetime '_#3r...
+   = note: borrowed value must be valid for lifetime '_#4r...
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
index 0b982dd812b..a0814cfc15f 100644
--- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
@@ -36,7 +36,7 @@ error[E0597]: `y` does not live long enough
 36 |     }
    |      - borrowed value only lives until here
    |
-   = note: borrowed value must be valid for lifetime '_#3r...
+   = note: borrowed value must be valid for lifetime '_#4r...
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
index 3e54e62d011..c5107322f6f 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -79,7 +79,7 @@ error[E0597]: `a` does not live long enough
 49 | }
    | - borrowed value only lives until here
    |
-   = note: borrowed value must be valid for lifetime '_#1r...
+   = note: borrowed value must be valid for lifetime '_#2r...
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/ty-outlives/projection-fn.stderr b/src/test/ui/nll/ty-outlives/projection-fn.stderr
index a478348edc1..77eabef6545 100644
--- a/src/test/ui/nll/ty-outlives/projection-fn.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-fn.stderr
@@ -10,13 +10,13 @@ warning: not reporting region error due to -Znll
 40 |     Box::new(x.next())
    |     ^^^^^^^^^^^^^^^^^^
 
-error: failed type test: TypeTest { generic_kind: ProjectionTy { substs: Slice([T]), item_def_id: DefId(2/0:1695 ~ core[2633]::iter[0]::iterator[0]::Iterator[0]::Item[0]) }, lower_bound: '_#3r, point: bb5[0], span: $DIR/projection-fn.rs:24:5: 24:23, test: IsOutlivedByAnyRegionIn([]) }
+error: failed type test: TypeTest { generic_kind: ProjectionTy { substs: Slice([T]), item_def_id: DefId(2/0:1695 ~ core[2633]::iter[0]::iterator[0]::Iterator[0]::Item[0]) }, lower_bound: '_#4r, point: bb5[0], span: $DIR/projection-fn.rs:24:5: 24:23, test: IsOutlivedByAnyRegionIn(['_#2r]) }
   --> $DIR/projection-fn.rs:24:5
    |
 24 |     Box::new(x.next())
    |     ^^^^^^^^^^^^^^^^^^
 
-error: failed type test: TypeTest { generic_kind: ProjectionTy { substs: Slice([T]), item_def_id: DefId(2/0:1695 ~ core[2633]::iter[0]::iterator[0]::Iterator[0]::Item[0]) }, lower_bound: '_#4r, point: bb5[0], span: $DIR/projection-fn.rs:40:5: 40:23, test: IsOutlivedByAnyRegionIn(['_#2r]) }
+error: failed type test: TypeTest { generic_kind: ProjectionTy { substs: Slice([T]), item_def_id: DefId(2/0:1695 ~ core[2633]::iter[0]::iterator[0]::Iterator[0]::Item[0]) }, lower_bound: '_#5r, point: bb5[0], span: $DIR/projection-fn.rs:40:5: 40:23, test: IsOutlivedByAnyRegionIn(['_#2r, '_#3r]) }
   --> $DIR/projection-fn.rs:40:5
    |
 40 |     Box::new(x.next())
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs b/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs
new file mode 100644
index 00000000000..42e62b23896
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs
@@ -0,0 +1,41 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-Znll -Zborrowck=mir
+
+// Test that we assume that universal types like `T` outlive the
+// function body.
+
+#![allow(warnings)]
+#![feature(dyn_trait)]
+
+use std::cell::Cell;
+
+// No errors here, because `'a` is local to the body.
+fn region_within_body<T>(t: T) {
+    let some_int = 22;
+    let cell = Cell::new(&some_int);
+    outlives(cell, t)
+}
+
+// Error here, because T: 'a is not satisfied.
+fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) {
+    outlives(cell, t)
+    //~^ WARNING not reporting region error due to -Znll
+    //~| ERROR failed type test
+}
+
+fn outlives<'a, T>(x: Cell<&'a usize>, y: T)
+where
+    T: 'a,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr
new file mode 100644
index 00000000000..3cc335bb29d
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr
@@ -0,0 +1,14 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ty-param-fn-body.rs:30:5
+   |
+30 |     outlives(cell, t)
+   |     ^^^^^^^^
+
+error: failed type test: TypeTest { generic_kind: T/#0, lower_bound: '_#4r, point: bb0[4], span: $DIR/ty-param-fn-body.rs:30:5: 30:22, test: IsOutlivedByAnyRegionIn(['_#2r]) }
+  --> $DIR/ty-param-fn-body.rs:30:5
+   |
+30 |     outlives(cell, t)
+   |     ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr
index 5b29ff88621..426bece3e9d 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr
@@ -10,13 +10,13 @@ warning: not reporting region error due to -Znll
 38 |     x
    |     ^
 
-error: failed type test: TypeTest { generic_kind: T/#1, lower_bound: '_#2r, point: bb0[3], span: $DIR/ty-param-fn.rs:22:5: 22:6, test: IsOutlivedByAnyRegionIn([]) }
+error: failed type test: TypeTest { generic_kind: T/#1, lower_bound: '_#3r, point: bb0[3], span: $DIR/ty-param-fn.rs:22:5: 22:6, test: IsOutlivedByAnyRegionIn(['_#2r]) }
   --> $DIR/ty-param-fn.rs:22:5
    |
 22 |     x
    |     ^
 
-error: failed type test: TypeTest { generic_kind: T/#2, lower_bound: '_#3r, point: bb0[3], span: $DIR/ty-param-fn.rs:38:5: 38:6, test: IsOutlivedByAnyRegionIn(['_#2r]) }
+error: failed type test: TypeTest { generic_kind: T/#2, lower_bound: '_#4r, point: bb0[3], span: $DIR/ty-param-fn.rs:38:5: 38:6, test: IsOutlivedByAnyRegionIn(['_#2r, '_#3r]) }
   --> $DIR/ty-param-fn.rs:38:5
    |
 38 |     x