propagate type tests from closure to closure creators
Currently, we only propagate type tests that exclude all regions from the type.
This commit is contained in:
parent
5804637a81
commit
85e1d4749e
7 changed files with 581 additions and 31 deletions
|
|
@ -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),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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() {}
|
||||
|
|
@ -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
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue