Skip to content

Commit d5ebeac

Browse files
committed
Forbid object lifetime changing pointer casts
1 parent 1ff2135 commit d5ebeac

File tree

6 files changed

+72
-34
lines changed

6 files changed

+72
-34
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

+6-27
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use rustc_mir_dataflow::move_paths::MoveData;
3939
use rustc_mir_dataflow::points::DenseLocationMap;
4040
use rustc_span::def_id::CRATE_DEF_ID;
4141
use rustc_span::source_map::Spanned;
42-
use rustc_span::{DUMMY_SP, Span, sym};
42+
use rustc_span::{Span, sym};
4343
use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
4444
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
4545
use tracing::{debug, instrument, trace};
@@ -52,7 +52,6 @@ use crate::polonius::legacy::{PoloniusFacts, PoloniusLocationTable};
5252
use crate::polonius::{PoloniusContext, PoloniusLivenessContext};
5353
use crate::region_infer::TypeTest;
5454
use crate::region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices};
55-
use crate::renumber::RegionCtxt;
5655
use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst};
5756
use crate::type_check::free_region_relations::{CreateResult, UniversalRegionRelations};
5857
use crate::universal_regions::{DefiningTy, UniversalRegions};
@@ -2120,8 +2119,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21202119
//
21212120
// Note that other checks (such as denying `dyn Send` -> `dyn
21222121
// Debug`) are in `rustc_hir_typeck`.
2123-
if let ty::Dynamic(src_tty, ..) = src_tail.kind()
2124-
&& let ty::Dynamic(dst_tty, ..) = dst_tail.kind()
2122+
if let ty::Dynamic(src_tty, src_region_bound, ..) = src_tail.kind()
2123+
&& let ty::Dynamic(dst_tty, dst_region_bound, ..) =
2124+
dst_tail.kind()
21252125
&& src_tty.principal().is_some()
21262126
&& dst_tty.principal().is_some()
21272127
{
@@ -2131,25 +2131,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21312131
tcx.mk_poly_existential_predicates(
21322132
&src_tty.without_auto_traits().collect::<Vec<_>>(),
21332133
),
2134-
tcx.lifetimes.re_static,
2134+
*src_region_bound,
21352135
ty::Dyn,
21362136
));
21372137
let dst_obj = tcx.mk_ty_from_kind(ty::Dynamic(
21382138
tcx.mk_poly_existential_predicates(
21392139
&dst_tty.without_auto_traits().collect::<Vec<_>>(),
21402140
),
2141-
tcx.lifetimes.re_static,
2141+
*dst_region_bound,
21422142
ty::Dyn,
21432143
));
21442144

2145-
// Replace trait object lifetimes with fresh vars, to allow
2146-
// casts like
2147-
// `*mut dyn FnOnce() + 'a` -> `*mut dyn FnOnce() + 'static`
2148-
let src_obj =
2149-
freshen_single_trait_object_lifetime(self.infcx, src_obj);
2150-
let dst_obj =
2151-
freshen_single_trait_object_lifetime(self.infcx, dst_obj);
2152-
21532145
debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
21542146

21552147
self.sub_types(
@@ -2706,16 +2698,3 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
27062698
Ok(output)
27072699
}
27082700
}
2709-
2710-
fn freshen_single_trait_object_lifetime<'tcx>(
2711-
infcx: &BorrowckInferCtxt<'tcx>,
2712-
ty: Ty<'tcx>,
2713-
) -> Ty<'tcx> {
2714-
let &ty::Dynamic(tty, _, dyn_kind @ ty::Dyn) = ty.kind() else { bug!("expected trait object") };
2715-
2716-
let fresh = infcx
2717-
.next_region_var(rustc_infer::infer::RegionVariableOrigin::MiscVariable(DUMMY_SP), || {
2718-
RegionCtxt::Unknown
2719-
});
2720-
infcx.tcx.mk_ty_from_kind(ty::Dynamic(tty, fresh, dyn_kind))
2721-
}

library/std/src/thread/mod.rs

+5-2
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

+4-3
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() {
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

+2-2
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>> {
+33
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)