From 85e1d4749e5ba14ff89073f5812974ec8fdbffd4 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 4 Dec 2017 13:04:38 -0500 Subject: [PATCH] propagate type tests from closure to closure creators Currently, we only propagate type tests that exclude all regions from the type. --- .../borrow_check/nll/region_infer/mod.rs | 157 ++++++++++++-- .../borrow_check/nll/type_check/mod.rs | 1 + .../borrow_check/nll/universal_regions.rs | 43 +++- ...param-closure-outlives-from-return-type.rs | 66 ++++++ ...m-closure-outlives-from-return-type.stderr | 58 ++++++ ...aram-closure-outlives-from-where-clause.rs | 96 +++++++++ ...-closure-outlives-from-where-clause.stderr | 191 ++++++++++++++++++ 7 files changed, 581 insertions(+), 31 deletions(-) create mode 100644 src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs create mode 100644 src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr create mode 100644 src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs create mode 100644 src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr 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 4a1eca38bc7c..244abb407982 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>>, + ) { 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>, + ) -> 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 `>::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 f7493f653e08..5c3cdbe2207b 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 ce931a68a0c3..d3e75626e63c 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 000000000000..6b23c82c7713 --- /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 or the MIT license +// , 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, op: F) -> Box + where F: FnOnce(Box) -> Box +{ + op(x) +} + +#[rustc_regions] +fn no_region<'a, T>(x: Box) -> Box +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) -> Box +where + T: 'a + Debug, +{ + x +} + +fn wrong_region<'a, 'b, T>(x: Box) -> Box +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) -> Box +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 000000000000..721896a93ffc --- /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,)) -> std::boxed::Box + ] + = 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) -> Box +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 000000000000..54f7b4fa50df --- /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 or the MIT license +// , 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 000000000000..748333badce8 --- /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 +