about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2017-12-04 13:04:38 -0500
committerNiko Matsakis <niko@alum.mit.edu>2017-12-15 10:27:51 -0500
commit85e1d4749e5ba14ff89073f5812974ec8fdbffd4 (patch)
tree5442f2b3f0f5dc1e885c09bfdb50bdfcc95cf2c2 /src
parent5804637a81a8e5216fbbf2e3e7c0a7bdca9c99de (diff)
downloadrust-85e1d4749e5ba14ff89073f5812974ec8fdbffd4.tar.gz
rust-85e1d4749e5ba14ff89073f5812974ec8fdbffd4.zip
propagate type tests from closure to closure creators
Currently, we only propagate type tests that exclude all regions from
the type.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/mod.rs157
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs1
-rw-r--r--src/librustc_mir/borrow_check/nll/universal_regions.rs43
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs66
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr58
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs96
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr191
7 files changed, 581 insertions, 31 deletions
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 4a1eca38bc7..244abb40798 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -12,15 +12,18 @@ use super::universal_regions::UniversalRegions;
 use rustc::hir::def_id::DefId;
 use rustc::infer::InferCtxt;
 use rustc::infer::NLLRegionVariableOrigin;
+use rustc::infer::RegionObligation;
 use rustc::infer::RegionVariableOrigin;
 use rustc::infer::SubregionOrigin;
 use rustc::infer::region_constraints::{GenericKind, VarOrigins};
 use rustc::mir::{ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
                  Location, Mir};
-use rustc::ty::{self, RegionVid};
+use rustc::traits::ObligationCause;
+use rustc::ty::{self, RegionVid, TypeFoldable};
 use rustc_data_structures::indexed_vec::IndexVec;
 use std::fmt;
 use std::rc::Rc;
+use syntax::ast;
 use syntax_pos::Span;
 
 mod annotation;
@@ -361,7 +364,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             None
         };
 
-        self.check_type_tests(infcx, mir);
+        self.check_type_tests(infcx, mir, outlives_requirements.as_mut());
 
         self.check_universal_regions(infcx, outlives_requirements.as_mut());
 
@@ -439,21 +442,27 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// therefore add `end('a)` into the region for `'b` -- but we
     /// 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>) {
+    fn check_type_tests<'gcx>(
+        &self,
+        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
+        mir: &Mir<'tcx>,
+        mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
+    ) {
         let tcx = infcx.tcx;
 
         for type_test in &self.type_tests {
             debug!("check_type_test: {:?}", type_test);
 
-            if self.eval_region_test(
-                mir,
-                type_test.point,
-                type_test.lower_bound,
-                &type_test.test,
-            ) {
+            if self.eval_region_test(mir, type_test.point, type_test.lower_bound, &type_test.test) {
                 continue;
             }
 
+            if let Some(propagated_outlives_requirements) = &mut propagated_outlives_requirements {
+                if self.try_promote_type_test(infcx, type_test, propagated_outlives_requirements) {
+                    continue;
+                }
+            }
+
             // Oh the humanity. Obviously we will do better than this error eventually.
             tcx.sess.span_err(
                 type_test.span,
@@ -462,6 +471,103 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
     }
 
+    fn try_promote_type_test<'gcx>(
+        &self,
+        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
+        type_test: &TypeTest<'tcx>,
+        propagated_outlives_requirements: &mut Vec<ClosureOutlivesRequirement<'gcx>>,
+    ) -> bool {
+        let tcx = infcx.tcx;
+        let gcx = tcx.global_tcx();
+
+        let TypeTest {
+            generic_kind,
+            lower_bound,
+            point: _,
+            span,
+            test: _,
+        } = type_test;
+
+        // TODO. For now, just fail to promote anything with a
+        // region. This is obviously too strict: we will for example
+        // fail to promote `<T as Foo<'static>>::Bar` to our
+        // caller. But it is always sound not to promote, that just
+        // means more errors, and ignoring regions is a convenient
+        // starting point. This is because we would want to promote to
+        // a type that references the region-vids of the closure, for
+        // which we have no global representation just now.
+        let generic_ty = generic_kind.to_ty(tcx);
+        if generic_ty.has_free_regions() {
+            return false;
+        }
+        let generic_ty = gcx.lift(&generic_ty).unwrap();
+
+        // Find some bounding subject-region R+ that is a super-region
+        // of the existing subject-region R. This should be a non-local, universal
+        // region, which ensures it can be encoded in a `ClosureOutlivesRequirement`.
+        let lower_bound_plus = self.promoted_type_test_bound(*lower_bound);
+        assert!(self.universal_regions.is_universal_region(lower_bound_plus));
+        assert!(!self.universal_regions
+            .is_local_free_region(lower_bound_plus));
+
+        propagated_outlives_requirements.push(ClosureOutlivesRequirement {
+            subject: ClosureOutlivesSubject::Ty(generic_ty),
+            outlived_free_region: lower_bound_plus,
+            blame_span: *span,
+        });
+        true
+    }
+
+    /// Here, `lower_bound` (henceforth, `'r`) represents the bound from
+    /// some type-test `T: 'r`. We are a closure and have found that
+    /// `T: 'r` is not locally satisfiable, so we want to propagate
+    /// this constraint to our creator. It is sound for us to do so
+    /// with some `'r+` known to our creator, where `'r+: 'r`.
+    ///
+    /// The tricky bit here: this region `'r` may contain (a) any
+    /// number of points in the CFG and (b) any number of `end('x)`
+    /// elements of universally quantified regions. To communicate with
+    /// our creator, however, we have to pick exactly one universally
+    /// quantified region -- in other words, exactly one `end('x)`
+    /// element -- that they understand and which will be `'r+`.
+    ///
+    /// We do this as follows:
+    ///
+    /// - Ignore the CFG points in `'r`. All universally quantified regions
+    ///   include the CFG anyhow.
+    /// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
+    ///   a result `'y`.
+    /// - Finally, we take the non-local upper bound of `'y`.
+    fn promoted_type_test_bound(&self, lower_bound: RegionVid) -> RegionVid {
+        let inferred_values = self.inferred_values.as_ref().unwrap();
+
+        debug!(
+            "promoted_type_test_bound(lower_bound={:?}={})",
+            lower_bound,
+            inferred_values.region_value_str(lower_bound)
+        );
+
+        // Find the smallest universal region that contains all other
+        // universal regions within `region`.
+        let mut lub = self.universal_regions.fr_fn_body;
+        for ur in inferred_values.universal_regions_outlived_by(lower_bound) {
+            lub = self.universal_regions.postdom_upper_bound(lub, ur);
+        }
+
+        debug!("promoted_type_test_bound: lub={:?}", lub);
+
+        // Grow further to get smallest universal region known to
+        // creator.
+        let non_local_lub = self.universal_regions.non_local_upper_bound(lub);
+
+        debug!(
+            "promoted_type_test_bound: non_local_lub={:?}",
+            non_local_lub
+        );
+
+        non_local_lub
+    }
+
     /// Test if `test` is true when applied to `lower_bound` at
     /// `point`, and returns true or false.
     fn eval_region_test(
@@ -487,13 +593,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 .iter()
                 .any(|&r| self.eval_outlives(mir, r, lower_bound, point)),
 
-            RegionTest::Any(tests) => tests.iter().any(|test| {
-                self.eval_region_test(mir, point, lower_bound, test)
-            }),
+            RegionTest::Any(tests) => tests
+                .iter()
+                .any(|test| self.eval_region_test(mir, point, lower_bound, test)),
 
-            RegionTest::All(tests) => tests.iter().all(|test| {
-                self.eval_region_test(mir, point, lower_bound, test)
-            }),
+            RegionTest::All(tests) => tests
+                .iter()
+                .all(|test| self.eval_region_test(mir, point, lower_bound, test)),
         }
     }
 
@@ -772,17 +878,18 @@ impl fmt::Debug for Constraint {
     }
 }
 
-pub trait ClosureRegionRequirementsExt {
+pub trait ClosureRegionRequirementsExt<'gcx> {
     fn apply_requirements<'tcx>(
         &self,
-        infcx: &InferCtxt<'_, '_, 'tcx>,
+        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
+        body_id: ast::NodeId,
         location: Location,
         closure_def_id: DefId,
         closure_substs: ty::ClosureSubsts<'tcx>,
     );
 }
 
-impl<'gcx> ClosureRegionRequirementsExt for ClosureRegionRequirements<'gcx> {
+impl<'gcx> ClosureRegionRequirementsExt<'gcx> for ClosureRegionRequirements<'gcx> {
     /// Given an instance T of the closure type, this method
     /// instantiates the "extra" requirements that we computed for the
     /// closure into the inference context. This has the effect of
@@ -797,7 +904,8 @@ impl<'gcx> ClosureRegionRequirementsExt for ClosureRegionRequirements<'gcx> {
     /// requirements.
     fn apply_requirements<'tcx>(
         &self,
-        infcx: &InferCtxt<'_, '_, 'tcx>,
+        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
+        body_id: ast::NodeId,
         location: Location,
         closure_def_id: DefId,
         closure_substs: ty::ClosureSubsts<'tcx>,
@@ -843,8 +951,15 @@ impl<'gcx> ClosureRegionRequirementsExt for ClosureRegionRequirements<'gcx> {
                     infcx.sub_regions(origin, outlived_region, region);
                 }
 
-                ClosureOutlivesSubject::Ty(_ty) => {
-                    bug!("TODO not yet implemented -- closure outlives subject of a type");
+                ClosureOutlivesSubject::Ty(ty) => {
+                    infcx.register_region_obligation(
+                        body_id,
+                        RegionObligation {
+                            sup_type: ty,
+                            sub_region: outlived_region,
+                            cause: ObligationCause::misc(outlives_requirement.blame_span, body_id),
+                        },
+                    );
                 }
             }
         }
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 f7493f653e0..5c3cdbe2207 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -1409,6 +1409,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 if let Some(closure_region_requirements) = tcx.mir_borrowck(*def_id) {
                     closure_region_requirements.apply_requirements(
                         self.infcx,
+                        self.body_id,
                         location,
                         *def_id,
                         *substs,
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index ce931a68a0c..d3e75626e63 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -267,6 +267,20 @@ impl<'tcx> UniversalRegions<'tcx> {
         self.num_universals
     }
 
+    /// Given two universal regions, returns the postdominating
+    /// upper-bound (effectively the least upper bound).
+    ///
+    /// (See `TransitiveRelation::postdom_upper_bound` for details on
+    /// the postdominating upper bound in general.)
+    pub fn postdom_upper_bound(&self, fr1: RegionVid, fr2: RegionVid) -> RegionVid {
+        assert!(self.is_universal_region(fr1));
+        assert!(self.is_universal_region(fr2));
+        *self.relations
+            .inverse_outlives
+            .postdom_upper_bound(&fr1, &fr2)
+            .unwrap_or(&self.fr_static)
+    }
+
     /// Finds an "upper bound" for `fr` that is not local. In other
     /// words, returns the smallest (*) known region `fr1` that (a)
     /// outlives `fr` and (b) is not local. This cannot fail, because
@@ -431,7 +445,10 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
         // - `'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);
+            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);
@@ -442,15 +459,21 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
         // we should not have created any more variables
         assert_eq!(self.infcx.num_region_vars(), num_universals);
 
-        debug!("build: global regions = {}..{}",
-               FIRST_GLOBAL_INDEX,
-               first_extern_index);
-        debug!("build: extern regions = {}..{}",
-               first_extern_index,
-               first_local_index);
-        debug!("build: local regions  = {}..{}",
-               first_local_index,
-               num_universals);
+        debug!(
+            "build: global regions = {}..{}",
+            FIRST_GLOBAL_INDEX,
+            first_extern_index
+        );
+        debug!(
+            "build: extern regions = {}..{}",
+            first_extern_index,
+            first_local_index
+        );
+        debug!(
+            "build: local regions  = {}..{}",
+            first_local_index,
+            num_universals
+        );
 
         UniversalRegions {
             indices,
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs
new file mode 100644
index 00000000000..6b23c82c771
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs
@@ -0,0 +1,66 @@
+// 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 -Zverbose
+
+#![allow(warnings)]
+#![feature(dyn_trait)]
+#![feature(rustc_attrs)]
+
+use std::fmt::Debug;
+
+fn with_signature<'a, T, F>(x: Box<T>, op: F) -> Box<dyn Debug + 'a>
+    where F: FnOnce(Box<T>) -> Box<dyn Debug + 'a>
+{
+    op(x)
+}
+
+#[rustc_regions]
+fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a>
+where
+    T: Debug,
+{
+    // Here, the closure winds up being required to prove that `T:
+    // 'a`.  In principle, it could know that, except that it is
+    // type-checked in a fully generic way, and hence it winds up with
+    // a propagated requirement that `T: '_#2`, where `'_#2` appears
+    // in the return type. The caller makes the mapping from `'_#2` to
+    // `'a` (and subsequently reports an error).
+
+    with_signature(x, |y| y)
+    //~^ WARNING not reporting region error due to -Znll
+    //~| ERROR failed type test
+}
+
+fn correct_region<'a, T>(x: Box<T>) -> Box<Debug + 'a>
+where
+    T: 'a + Debug,
+{
+    x
+}
+
+fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
+where
+    T: 'b + Debug,
+{
+    x
+    //~^ WARNING not reporting region error due to -Znll
+    //~| ERROR failed type test
+}
+
+fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
+where
+    T: 'b + Debug,
+    'b: 'a,
+{
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
new file mode 100644
index 00000000000..721896a93ff
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
@@ -0,0 +1,58 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:37:27
+   |
+37 |     with_signature(x, |y| y)
+   |                           ^
+
+warning: not reporting region error due to -Znll
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:53:5
+   |
+53 |     x
+   |     ^
+
+note: External requirements
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:37:23
+   |
+37 |     with_signature(x, |y| y)
+   |                       ^^^^^
+   |
+   = note: defining type: DefId(0/1:14 ~ ty_param_closure_outlives_from_return_type[317d]::no_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<std::fmt::Debug + '_#2r>
+           ]
+   = note: number of external vids: 3
+   = note: where T: '_#2r
+
+error: failed type test: TypeTest { generic_kind: T/#1, lower_bound: '_#4r, point: bb0[5], span: $DIR/ty-param-closure-outlives-from-return-type.rs:37:23: 37:28, test: IsOutlivedByAnyRegionIn(['_#2r]) }
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:37:23
+   |
+37 |     with_signature(x, |y| y)
+   |                       ^^^^^
+
+note: No external requirements
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:1
+   |
+26 | / fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a>
+27 | | where
+28 | |     T: Debug,
+29 | | {
+...  |
+39 | |     //~| ERROR failed type test
+40 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:5 ~ ty_param_closure_outlives_from_return_type[317d]::no_region[0]) with substs [
+               '_#1r,
+               T
+           ]
+
+error: failed type test: TypeTest { generic_kind: T/#2, lower_bound: '_#4r, point: bb0[3], span: $DIR/ty-param-closure-outlives-from-return-type.rs:53:5: 53:6, test: IsOutlivedByAnyRegionIn(['_#2r, '_#3r]) }
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:53:5
+   |
+53 |     x
+   |     ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
new file mode 100644
index 00000000000..54f7b4fa50d
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
@@ -0,0 +1,96 @@
+// 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.
+
+// Test that we can propagate `T: 'a` obligations to our caller.  See
+// `correct_region` for an explanation of how this test is setup; it's
+// somewhat intricate.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![allow(warnings)]
+#![feature(dyn_trait)]
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+fn with_signature<'a, T, F>(a: Cell<&'a ()>, b: T, op: F)
+where
+    F: FnOnce(Cell<&'a ()>, T),
+{
+    op(a, b)
+}
+
+fn require<'a, T>(_a: &Cell<&'a ()>, _b: &T)
+where
+    T: 'a,
+{
+}
+
+#[rustc_regions]
+fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
+    with_signature(a, b, |x, y| {
+        //~^ ERROR failed type test
+        //
+        // See `correct_region`, which explains the point of this
+        // test.  The only difference is that, in the case of this
+        // function, there is no where clause *anywhere*, and hence we
+        // get an error (but reported by the closure creator).
+        require(&x, &y)
+        //~^ WARNING not reporting region error due to -Znll
+    })
+}
+
+#[rustc_regions]
+fn correct_region<'a, T>(a: Cell<&'a ()>, b: T)
+where
+    T: 'a,
+{
+    with_signature(a, b, |x, y| {
+        // Key point of this test:
+        //
+        // The *closure* is being type-checked with all of its free
+        // regions "universalized". In particular, it does not know
+        // that `x` has the type `Cell<&'a ()>`, but rather treats it
+        // as if the type of `x` is `Cell<&'A ()>`, where `'A` is some
+        // fresh, independent region distinct from the `'a` which
+        // appears in the environment. The call to `require` here
+        // forces us then to prove that `T: 'A`, but the closure
+        // cannot do it on its own. It has to surface this requirement
+        // to its creator (which knows that `'a == 'A`).
+        require(&x, &y)
+    })
+}
+
+#[rustc_regions]
+fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
+where
+    T: 'b,
+{
+    with_signature(a, b, |x, y| {
+        //~^ ERROR failed type test
+        // See `correct_region`
+        require(&x, &y)
+        //~^ WARNING not reporting region error due to -Znll
+    })
+}
+
+#[rustc_regions]
+fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
+where
+    T: 'b,
+    'b: 'a,
+{
+    with_signature(a, b, |x, y| {
+        // See `correct_region`
+        require(&x, &y)
+    })
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
new file mode 100644
index 00000000000..748333badce
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
@@ -0,0 +1,191 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:45:9
+   |
+45 |         require(&x, &y)
+   |         ^^^^^^^
+
+warning: not reporting region error due to -Znll
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:79:9
+   |
+79 |         require(&x, &y)
+   |         ^^^^^^^
+
+note: External requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:26
+   |
+38 |       with_signature(a, b, |x, y| {
+   |  __________________________^
+39 | |         //~^ ERROR failed type test
+40 | |         //
+41 | |         // See `correct_region`, which explains the point of this
+...  |
+46 | |         //~^ WARNING not reporting region error due to -Znll
+47 | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:16 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]::{{closure}}[0]) with closure substs [
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#1r ()>, T))
+           ]
+   = note: number of external vids: 2
+   = note: where T: '_#1r
+
+note: External requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:55:26
+   |
+55 |       with_signature(a, b, |x, y| {
+   |  __________________________^
+56 | |         // Key point of this test:
+57 | |         //
+58 | |         // The *closure* is being type-checked with all of its free
+...  |
+67 | |         require(&x, &y)
+68 | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:19 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+           ]
+   = note: number of external vids: 3
+   = note: where T: '_#2r
+
+note: External requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26
+   |
+76 |       with_signature(a, b, |x, y| {
+   |  __________________________^
+77 | |         //~^ ERROR failed type test
+78 | |         // See `correct_region`
+79 | |         require(&x, &y)
+80 | |         //~^ WARNING not reporting region error due to -Znll
+81 | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:23 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+           ]
+   = note: number of external vids: 3
+   = note: where T: '_#2r
+
+note: External requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:90:26
+   |
+90 |       with_signature(a, b, |x, y| {
+   |  __________________________^
+91 | |         // See `correct_region`
+92 | |         require(&x, &y)
+93 | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:27 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [
+               '_#1r,
+               '_#2r,
+               T,
+               i32,
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+           ]
+   = note: number of external vids: 4
+   = note: where T: '_#3r
+
+error: failed type test: TypeTest { generic_kind: T/#0, lower_bound: '_#3r, point: bb0[5], span: $DIR/ty-param-closure-outlives-from-where-clause.rs:38:26: 47:6, test: IsOutlivedByAnyRegionIn(['_#2r]) }
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:26
+   |
+38 |       with_signature(a, b, |x, y| {
+   |  __________________________^
+39 | |         //~^ ERROR failed type test
+40 | |         //
+41 | |         // See `correct_region`, which explains the point of this
+...  |
+46 | |         //~^ WARNING not reporting region error due to -Znll
+47 | |     })
+   | |_____^
+
+note: No external requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:1
+   |
+37 | / fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
+38 | |     with_signature(a, b, |x, y| {
+39 | |         //~^ ERROR failed type test
+40 | |         //
+...  |
+47 | |     })
+48 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]) with substs [
+               T
+           ]
+
+note: No external requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:51:1
+   |
+51 | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T)
+52 | | where
+53 | |     T: 'a,
+54 | | {
+...  |
+68 | |     })
+69 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:7 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]) with substs [
+               '_#1r,
+               T
+           ]
+
+error: failed type test: TypeTest { generic_kind: T/#1, lower_bound: '_#5r, point: bb0[5], span: $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26: 81:6, test: IsOutlivedByAnyRegionIn(['_#1r, '_#3r]) }
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26
+   |
+76 |       with_signature(a, b, |x, y| {
+   |  __________________________^
+77 | |         //~^ ERROR failed type test
+78 | |         // See `correct_region`
+79 | |         require(&x, &y)
+80 | |         //~^ WARNING not reporting region error due to -Znll
+81 | |     })
+   | |_____^
+
+note: No external requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:72:1
+   |
+72 | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
+73 | | where
+74 | |     T: 'b,
+75 | | {
+...  |
+81 | |     })
+82 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]) with substs [
+               '_#1r,
+               T
+           ]
+
+note: No external requirements
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:85:1
+   |
+85 | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
+86 | | where
+87 | |     T: 'b,
+88 | |     'b: 'a,
+...  |
+93 | |     })
+94 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:9 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]) with substs [
+               '_#1r,
+               '_#2r,
+               T
+           ]
+
+error: aborting due to 2 previous errors
+