| // Issue #29793, small regression tests: do not let borrows of |
| // parameters to ever be returned (expanded with exploration of |
| // variations). |
| |
| // CLOSURES |
| |
| fn escaping_borrow_of_closure_params_1() { |
| let g = |x: usize, y:usize| { |
| let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) |
| //~^ ERROR E0373 |
| //~| ERROR E0373 |
| return f; |
| }; |
| |
| // We delberately do not call `g`; this small version of the test, |
| // after adding such a call, was (properly) rejected even when the |
| // system still suffered from issue #29793. |
| |
| // g(10, 20)(true); |
| } |
| |
| fn escaping_borrow_of_closure_params_2() { |
| let g = |x: usize, y:usize| { |
| let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) |
| //~^ ERROR E0373 |
| //~| ERROR E0373 |
| f |
| }; |
| |
| // (we don't call `g`; see above) |
| } |
| |
| fn move_of_closure_params() { |
| let g = |x: usize, y:usize| { |
| let f = move |t: bool| if t { x } else { y }; |
| f; |
| }; |
| // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`) |
| (g(1,2)); |
| } |
| |
| fn ok_borrow_of_fn_params(a: usize, b:usize) { |
| let g = |x: usize, y:usize| { |
| let f = |t: bool| if t { a } else { b }; |
| return f; |
| }; |
| // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`) |
| (g(1,2))(true); |
| } |
| |
| // TOP-LEVEL FN'S |
| |
| fn escaping_borrow_of_fn_params_1() { |
| fn g<'a>(x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> { |
| let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) |
| //~^ ERROR E0373 |
| //~| ERROR E0373 |
| return Box::new(f); |
| }; |
| |
| // (we don't call `g`; see above) |
| } |
| |
| fn escaping_borrow_of_fn_params_2() { |
| fn g<'a>(x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> { |
| let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) |
| //~^ ERROR E0373 |
| //~| ERROR E0373 |
| Box::new(f) |
| }; |
| |
| // (we don't call `g`; see above) |
| } |
| |
| fn move_of_fn_params() { |
| fn g<'a>(x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> { |
| let f = move |t: bool| if t { x } else { y }; |
| return Box::new(f); |
| }; |
| // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`) |
| (g(1,2))(true); |
| } |
| |
| // INHERENT METHODS |
| |
| fn escaping_borrow_of_method_params_1() { |
| struct S; |
| impl S { |
| fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> { |
| let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) |
| //~^ ERROR E0373 |
| //~| ERROR E0373 |
| return Box::new(f); |
| } |
| } |
| |
| // (we don't call `g`; see above) |
| } |
| |
| fn escaping_borrow_of_method_params_2() { |
| struct S; |
| impl S { |
| fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> { |
| let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) |
| //~^ ERROR E0373 |
| //~| ERROR E0373 |
| Box::new(f) |
| } |
| } |
| // (we don't call `g`; see above) |
| } |
| |
| fn move_of_method_params() { |
| struct S; |
| impl S { |
| fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> { |
| let f = move |t: bool| if t { x } else { y }; |
| return Box::new(f); |
| } |
| } |
| // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`) |
| (S.g(1,2))(true); |
| } |
| |
| // TRAIT IMPL METHODS |
| |
| fn escaping_borrow_of_trait_impl_params_1() { |
| trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a>; } |
| struct S; |
| impl T for S { |
| fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> { |
| let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) |
| //~^ ERROR E0373 |
| //~| ERROR E0373 |
| return Box::new(f); |
| } |
| } |
| |
| // (we don't call `g`; see above) |
| } |
| |
| fn escaping_borrow_of_trait_impl_params_2() { |
| trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a>; } |
| struct S; |
| impl T for S { |
| fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> { |
| let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) |
| //~^ ERROR E0373 |
| //~| ERROR E0373 |
| Box::new(f) |
| } |
| } |
| // (we don't call `g`; see above) |
| } |
| |
| fn move_of_trait_impl_params() { |
| trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a>; } |
| struct S; |
| impl T for S { |
| fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> { |
| let f = move |t: bool| if t { x } else { y }; |
| return Box::new(f); |
| } |
| } |
| // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`) |
| (S.g(1,2))(true); |
| } |
| |
| // TRAIT DEFAULT METHODS |
| |
| fn escaping_borrow_of_trait_default_params_1() { |
| struct S; |
| trait T { |
| fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> { |
| let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) |
| //~^ ERROR E0373 |
| //~| ERROR E0373 |
| return Box::new(f); |
| } |
| } |
| impl T for S {} |
| // (we don't call `g`; see above) |
| } |
| |
| fn escaping_borrow_of_trait_default_params_2() { |
| struct S; |
| trait T { |
| fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> { |
| let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) |
| //~^ ERROR E0373 |
| //~| ERROR E0373 |
| Box::new(f) |
| } |
| } |
| impl T for S {} |
| // (we don't call `g`; see above) |
| } |
| |
| fn move_of_trait_default_params() { |
| struct S; |
| trait T { |
| fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> { |
| let f = move |t: bool| if t { x } else { y }; |
| return Box::new(f); |
| } |
| } |
| impl T for S {} |
| // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`) |
| (S.g(1,2))(true); |
| } |
| |
| fn main() { } |