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
|
|
@ -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