Skip to content

Commit 19659db

Browse files
committed
Forbid object lifetime changing pointer casts
1 parent d423c81 commit 19659db

File tree

6 files changed

+68
-11
lines changed

6 files changed

+68
-11
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,7 +1505,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
15051505
//
15061506
// Note that other checks (such as denying `dyn Send` -> `dyn
15071507
// Debug`) are in `rustc_hir_typeck`.
1508-
if let ty::Dynamic(src_tty, _src_lt, ty::Dyn) = *src_tail.kind()
1508+
if let ty::Dynamic(src_tty, src_lt, ty::Dyn) = *src_tail.kind()
15091509
&& let ty::Dynamic(dst_tty, dst_lt, ty::Dyn) = *dst_tail.kind()
15101510
&& src_tty.principal().is_some()
15111511
&& dst_tty.principal().is_some()
@@ -1517,9 +1517,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
15171517
tcx.mk_poly_existential_predicates(
15181518
&src_tty.without_auto_traits().collect::<Vec<_>>(),
15191519
),
1520-
// FIXME: Once we disallow casting `*const dyn Trait + 'short`
1521-
// to `*const dyn Trait + 'long`, then this can just be `src_lt`.
1522-
dst_lt,
1520+
src_lt,
15231521
ty::Dyn,
15241522
);
15251523
let dst_obj = Ty::new_dynamic(

library/std/src/thread/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -578,8 +578,11 @@ impl Builder {
578578
let main = Box::new(main);
579579
// SAFETY: dynamic size and alignment of the Box remain the same. See below for why the
580580
// lifetime change is justified.
581-
let main =
582-
unsafe { Box::from_raw(Box::into_raw(main) as *mut (dyn FnOnce() + Send + 'static)) };
581+
let main = unsafe {
582+
let ptr = Box::into_raw(main) as *mut (dyn FnOnce() + Send + '_);
583+
let ptr: *mut (dyn FnOnce() + Send + 'static) = crate::mem::transmute(ptr);
584+
Box::from_raw(ptr)
585+
};
583586

584587
Ok(JoinInner {
585588
// SAFETY:

tests/ui/cast/ptr-to-ptr-different-regions.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
//@ check-pass
2-
31
// https://github.com/rust-lang/rust/issues/113257
42

53
#![deny(trivial_casts)] // The casts here are not trivial.
64

7-
struct Foo<'a> { a: &'a () }
5+
struct Foo<'a> {
6+
a: &'a (),
7+
}
88

99
fn extend_lifetime_very_very_safely<'a>(v: *const Foo<'a>) -> *const Foo<'static> {
1010
// This should pass because raw pointer casts can do anything they want.
@@ -15,6 +15,7 @@ trait Trait {}
1515

1616
fn assert_static<'a>(ptr: *mut (dyn Trait + 'a)) -> *mut (dyn Trait + 'static) {
1717
ptr as _
18+
//~^ ERROR: lifetime may not live long enough
1819
}
1920

2021
fn main() {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/ptr-to-ptr-different-regions.rs:17:5
3+
|
4+
LL | fn assert_static<'a>(ptr: *mut (dyn Trait + 'a)) -> *mut (dyn Trait + 'static) {
5+
| -- lifetime `'a` defined here
6+
LL | ptr as _
7+
| ^^^^^^^^ returning this value requires that `'a` must outlive `'static`
8+
|
9+
= note: requirement occurs because of a mutable pointer to `dyn Trait`
10+
= note: mutable pointers are invariant over their type parameter
11+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
12+
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `ptr`
13+
|
14+
LL | fn assert_static<'a>(ptr: *mut (dyn Trait + 'a)) -> *mut (dyn Trait + 'a) {
15+
| ~~
16+
help: alternatively, add an explicit `'static` bound to this reference
17+
|
18+
LL | fn assert_static<'a>(ptr: *mut (dyn Trait + 'static)) -> *mut (dyn Trait + 'static) {
19+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
20+
21+
error: aborting due to 1 previous error
22+

tests/ui/cast/ptr-to-trait-obj-ok.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
//@ check-pass
2-
31
trait Trait<'a> {}
42

53
fn remove_auto<'a>(x: *mut (dyn Trait<'a> + Send)) -> *mut dyn Trait<'a> {
@@ -8,6 +6,7 @@ fn remove_auto<'a>(x: *mut (dyn Trait<'a> + Send)) -> *mut dyn Trait<'a> {
86

97
fn cast_inherent_lt<'a, 'b>(x: *mut (dyn Trait<'static> + 'a)) -> *mut (dyn Trait<'static> + 'b) {
108
x as _
9+
//~^ ERROR: lifetime may not live long enough
1110
}
1211

1312
fn cast_away_higher_ranked<'a>(x: *mut dyn for<'b> Trait<'b>) -> *mut dyn Trait<'a> {
@@ -33,6 +32,7 @@ fn cast_inherent_lt_wrap<'a, 'b>(
3332
x: *mut (dyn Trait<'static> + 'a),
3433
) -> *mut Wrapper<dyn Trait<'static> + 'b> {
3534
x as _
35+
//~^ ERROR: lifetime may not live long enough
3636
}
3737

3838
fn cast_away_higher_ranked_wrap<'a>(x: *mut dyn for<'b> Trait<'b>) -> *mut Wrapper<dyn Trait<'a>> {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/ptr-to-trait-obj-ok.rs:8:5
3+
|
4+
LL | fn cast_inherent_lt<'a, 'b>(x: *mut (dyn Trait<'static> + 'a)) -> *mut (dyn Trait<'static> + 'b) {
5+
| -- -- lifetime `'b` defined here
6+
| |
7+
| lifetime `'a` defined here
8+
LL | x as _
9+
| ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
10+
|
11+
= help: consider adding the following bound: `'a: 'b`
12+
= note: requirement occurs because of a mutable pointer to `dyn Trait<'_>`
13+
= note: mutable pointers are invariant over their type parameter
14+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
15+
16+
error: lifetime may not live long enough
17+
--> $DIR/ptr-to-trait-obj-ok.rs:34:5
18+
|
19+
LL | fn cast_inherent_lt_wrap<'a, 'b>(
20+
| -- -- lifetime `'b` defined here
21+
| |
22+
| lifetime `'a` defined here
23+
...
24+
LL | x as _
25+
| ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
26+
|
27+
= help: consider adding the following bound: `'a: 'b`
28+
= note: requirement occurs because of a mutable pointer to `Wrapper<dyn Trait<'_>>`
29+
= note: mutable pointers are invariant over their type parameter
30+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
31+
32+
error: aborting due to 2 previous errors
33+

0 commit comments

Comments
 (0)