// 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:-Zverbose #![allow(warnings)] #![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| { // 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) //~^ ERROR the parameter type `T` may not live long enough }) } #[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| { // See `correct_region` require(&x, &y) //~^ ERROR the parameter type `T` may not live long enough }) } #[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() {}