Skip to content

Commit e19a229

Browse files
authored
Rollup merge of rust-lang#60756 - matthewjasper:extra-impl-trait-tests, r=nikomatsakis
Add better tests for hidden lifetimes in impl trait cc rust-lang#60670
2 parents d85e256 + 53e0474 commit e19a229

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed
+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Test to show what happens if we were not careful and allowed invariant
2+
// lifetimes to escape though an impl trait.
3+
//
4+
// Specifically we swap a long lived and short lived reference, giving us a
5+
// dangling pointer.
6+
7+
use std::cell::RefCell;
8+
use std::rc::Rc;
9+
10+
trait Swap: Sized {
11+
fn swap(self, other: Self);
12+
}
13+
14+
impl<T> Swap for &mut T {
15+
fn swap(self, other: Self) {
16+
std::mem::swap(self, other);
17+
}
18+
}
19+
20+
impl<T> Swap for Rc<RefCell<T>> {
21+
fn swap(self, other: Self) {
22+
<RefCell<T>>::swap(&self, &other);
23+
}
24+
}
25+
26+
// Here we are hiding `'b` making the caller believe that `&'a mut &'s T` and
27+
// `&'a mut &'l T` are the same type.
28+
fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
29+
//~^ ERROR hidden type
30+
x
31+
}
32+
33+
fn dangle_ref() -> &'static [i32; 3] {
34+
let mut res = &[4, 5, 6];
35+
let x = [1, 2, 3];
36+
hide_ref(&mut res).swap(hide_ref(&mut &x));
37+
res
38+
}
39+
40+
// Here we are hiding `'b` making the caller believe that `Rc<RefCell<&'s T>>`
41+
// and `Rc<RefCell<&'l T>>` are the same type.
42+
//
43+
// This is different to the previous example because the concrete return type
44+
// only has a single lifetime.
45+
fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
46+
//~^ ERROR hidden type
47+
x
48+
}
49+
50+
fn dangle_rc_refcell() -> &'static [i32; 3] {
51+
let long = Rc::new(RefCell::new(&[4, 5, 6]));
52+
let x = [1, 2, 3];
53+
let short = Rc::new(RefCell::new(&x));
54+
hide_rc_refcell(long.clone()).swap(hide_rc_refcell(short));
55+
let res: &'static [i32; 3] = *long.borrow();
56+
res
57+
}
58+
59+
fn main() {
60+
// both will print nonsense values.
61+
println!("{:?}", dangle_ref());
62+
println!("{:?}", dangle_rc_refcell())
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
2+
--> $DIR/hidden-lifetimes.rs:28:54
3+
|
4+
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
5+
| ^^^^^^^^^^^^^^
6+
|
7+
note: hidden type `&'a mut &'b T` captures the lifetime 'b as defined on the function body at 28:17
8+
--> $DIR/hidden-lifetimes.rs:28:17
9+
|
10+
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
11+
| ^^
12+
13+
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
14+
--> $DIR/hidden-lifetimes.rs:45:70
15+
|
16+
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
17+
| ^^^^^^^^^^^^^^
18+
|
19+
note: hidden type `std::rc::Rc<std::cell::RefCell<&'b T>>` captures the lifetime 'b as defined on the function body at 45:24
20+
--> $DIR/hidden-lifetimes.rs:45:24
21+
|
22+
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
23+
| ^^
24+
25+
error: aborting due to 2 previous errors
26+
27+
For more information about this error, try `rustc --explain E0700`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Test that multiple liftimes are allowed in impl trait types.
2+
// compile-pass
3+
4+
trait X<'x>: Sized {}
5+
6+
impl<U> X<'_> for U {}
7+
8+
fn multiple_lifeteimes<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl X<'b> + 'a {
9+
x
10+
}
11+
12+
fn main() {}

0 commit comments

Comments
 (0)