forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of rust-lang#60756 - matthewjasper:extra-impl-trait-test…
…s, r=nikomatsakis Add better tests for hidden lifetimes in impl trait cc rust-lang#60670
- Loading branch information
Showing
3 changed files
with
102 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Test to show what happens if we were not careful and allowed invariant | ||
// lifetimes to escape though an impl trait. | ||
// | ||
// Specifically we swap a long lived and short lived reference, giving us a | ||
// dangling pointer. | ||
|
||
use std::cell::RefCell; | ||
use std::rc::Rc; | ||
|
||
trait Swap: Sized { | ||
fn swap(self, other: Self); | ||
} | ||
|
||
impl<T> Swap for &mut T { | ||
fn swap(self, other: Self) { | ||
std::mem::swap(self, other); | ||
} | ||
} | ||
|
||
impl<T> Swap for Rc<RefCell<T>> { | ||
fn swap(self, other: Self) { | ||
<RefCell<T>>::swap(&self, &other); | ||
} | ||
} | ||
|
||
// Here we are hiding `'b` making the caller believe that `&'a mut &'s T` and | ||
// `&'a mut &'l T` are the same type. | ||
fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { | ||
//~^ ERROR hidden type | ||
x | ||
} | ||
|
||
fn dangle_ref() -> &'static [i32; 3] { | ||
let mut res = &[4, 5, 6]; | ||
let x = [1, 2, 3]; | ||
hide_ref(&mut res).swap(hide_ref(&mut &x)); | ||
res | ||
} | ||
|
||
// Here we are hiding `'b` making the caller believe that `Rc<RefCell<&'s T>>` | ||
// and `Rc<RefCell<&'l T>>` are the same type. | ||
// | ||
// This is different to the previous example because the concrete return type | ||
// only has a single lifetime. | ||
fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a { | ||
//~^ ERROR hidden type | ||
x | ||
} | ||
|
||
fn dangle_rc_refcell() -> &'static [i32; 3] { | ||
let long = Rc::new(RefCell::new(&[4, 5, 6])); | ||
let x = [1, 2, 3]; | ||
let short = Rc::new(RefCell::new(&x)); | ||
hide_rc_refcell(long.clone()).swap(hide_rc_refcell(short)); | ||
let res: &'static [i32; 3] = *long.borrow(); | ||
res | ||
} | ||
|
||
fn main() { | ||
// both will print nonsense values. | ||
println!("{:?}", dangle_ref()); | ||
println!("{:?}", dangle_rc_refcell()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds | ||
--> $DIR/hidden-lifetimes.rs:28:54 | ||
| | ||
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { | ||
| ^^^^^^^^^^^^^^ | ||
| | ||
note: hidden type `&'a mut &'b T` captures the lifetime 'b as defined on the function body at 28:17 | ||
--> $DIR/hidden-lifetimes.rs:28:17 | ||
| | ||
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { | ||
| ^^ | ||
|
||
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds | ||
--> $DIR/hidden-lifetimes.rs:45:70 | ||
| | ||
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a { | ||
| ^^^^^^^^^^^^^^ | ||
| | ||
note: hidden type `std::rc::Rc<std::cell::RefCell<&'b T>>` captures the lifetime 'b as defined on the function body at 45:24 | ||
--> $DIR/hidden-lifetimes.rs:45:24 | ||
| | ||
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a { | ||
| ^^ | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0700`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// Test that multiple liftimes are allowed in impl trait types. | ||
// compile-pass | ||
|
||
trait X<'x>: Sized {} | ||
|
||
impl<U> X<'_> for U {} | ||
|
||
fn multiple_lifeteimes<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl X<'b> + 'a { | ||
x | ||
} | ||
|
||
fn main() {} |