diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 002f6e36cd8b3..f115e344237a4 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -39,7 +39,7 @@ use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::source_map::Spanned; -use rustc_span::{DUMMY_SP, Span, sym}; +use rustc_span::{Span, sym}; use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; use tracing::{debug, instrument, trace}; @@ -52,7 +52,6 @@ use crate::polonius::legacy::{PoloniusFacts, PoloniusLocationTable}; use crate::polonius::{PoloniusContext, PoloniusLivenessContext}; use crate::region_infer::TypeTest; use crate::region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices}; -use crate::renumber::RegionCtxt; use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst}; use crate::type_check::free_region_relations::{CreateResult, UniversalRegionRelations}; use crate::universal_regions::{DefiningTy, UniversalRegions}; @@ -2120,8 +2119,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // // Note that other checks (such as denying `dyn Send` -> `dyn // Debug`) are in `rustc_hir_typeck`. - if let ty::Dynamic(src_tty, ..) = src_tail.kind() - && let ty::Dynamic(dst_tty, ..) = dst_tail.kind() + if let ty::Dynamic(src_tty, src_region_bound, ..) = src_tail.kind() + && let ty::Dynamic(dst_tty, dst_region_bound, ..) = + dst_tail.kind() && src_tty.principal().is_some() && dst_tty.principal().is_some() { @@ -2131,25 +2131,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { tcx.mk_poly_existential_predicates( &src_tty.without_auto_traits().collect::>(), ), - tcx.lifetimes.re_static, + *src_region_bound, ty::Dyn, )); let dst_obj = tcx.mk_ty_from_kind(ty::Dynamic( tcx.mk_poly_existential_predicates( &dst_tty.without_auto_traits().collect::>(), ), - tcx.lifetimes.re_static, + *dst_region_bound, ty::Dyn, )); - // Replace trait object lifetimes with fresh vars, to allow - // casts like - // `*mut dyn FnOnce() + 'a` -> `*mut dyn FnOnce() + 'static` - let src_obj = - freshen_single_trait_object_lifetime(self.infcx, src_obj); - let dst_obj = - freshen_single_trait_object_lifetime(self.infcx, dst_obj); - debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj); self.sub_types( @@ -2706,16 +2698,3 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> { Ok(output) } } - -fn freshen_single_trait_object_lifetime<'tcx>( - infcx: &BorrowckInferCtxt<'tcx>, - ty: Ty<'tcx>, -) -> Ty<'tcx> { - let &ty::Dynamic(tty, _, dyn_kind @ ty::Dyn) = ty.kind() else { bug!("expected trait object") }; - - let fresh = infcx - .next_region_var(rustc_infer::infer::RegionVariableOrigin::MiscVariable(DUMMY_SP), || { - RegionCtxt::Unknown - }); - infcx.tcx.mk_ty_from_kind(ty::Dynamic(tty, fresh, dyn_kind)) -} diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 59b395336f2e3..a5445e7fee76d 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -578,8 +578,11 @@ impl Builder { let main = Box::new(main); // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the // lifetime change is justified. - let main = - unsafe { Box::from_raw(Box::into_raw(main) as *mut (dyn FnOnce() + Send + 'static)) }; + let main = unsafe { + let ptr = Box::into_raw(main) as *mut (dyn FnOnce() + Send + '_); + let ptr: *mut (dyn FnOnce() + Send + 'static) = crate::mem::transmute(ptr); + Box::from_raw(ptr) + }; Ok(JoinInner { // SAFETY: diff --git a/tests/ui/cast/ptr-to-ptr-different-regions.rs b/tests/ui/cast/ptr-to-ptr-different-regions.rs index 0d525edc1332f..144fc1f3c326f 100644 --- a/tests/ui/cast/ptr-to-ptr-different-regions.rs +++ b/tests/ui/cast/ptr-to-ptr-different-regions.rs @@ -1,10 +1,10 @@ -//@ check-pass - // https://github.com/rust-lang/rust/issues/113257 #![deny(trivial_casts)] // The casts here are not trivial. -struct Foo<'a> { a: &'a () } +struct Foo<'a> { + a: &'a (), +} fn extend_lifetime_very_very_safely<'a>(v: *const Foo<'a>) -> *const Foo<'static> { // This should pass because raw pointer casts can do anything they want. @@ -15,6 +15,7 @@ trait Trait {} fn assert_static<'a>(ptr: *mut (dyn Trait + 'a)) -> *mut (dyn Trait + 'static) { ptr as _ + //~^ ERROR: lifetime may not live long enough } fn main() { diff --git a/tests/ui/cast/ptr-to-ptr-different-regions.stderr b/tests/ui/cast/ptr-to-ptr-different-regions.stderr new file mode 100644 index 0000000000000..39e860d79de4f --- /dev/null +++ b/tests/ui/cast/ptr-to-ptr-different-regions.stderr @@ -0,0 +1,22 @@ +error: lifetime may not live long enough + --> $DIR/ptr-to-ptr-different-regions.rs:17:5 + | +LL | fn assert_static<'a>(ptr: *mut (dyn Trait + 'a)) -> *mut (dyn Trait + 'static) { + | -- lifetime `'a` defined here +LL | ptr as _ + | ^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | + = note: requirement occurs because of a mutable pointer to `dyn Trait` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `ptr` + | +LL | fn assert_static<'a>(ptr: *mut (dyn Trait + 'a)) -> *mut (dyn Trait + 'a) { + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn assert_static<'a>(ptr: *mut (dyn Trait + 'static)) -> *mut (dyn Trait + 'static) { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 1 previous error + diff --git a/tests/ui/cast/ptr-to-trait-obj-ok.rs b/tests/ui/cast/ptr-to-trait-obj-ok.rs index dbeee9d29441e..b4827cb1d4a94 100644 --- a/tests/ui/cast/ptr-to-trait-obj-ok.rs +++ b/tests/ui/cast/ptr-to-trait-obj-ok.rs @@ -1,5 +1,3 @@ -//@ check-pass - trait Trait<'a> {} 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> { fn cast_inherent_lt<'a, 'b>(x: *mut (dyn Trait<'static> + 'a)) -> *mut (dyn Trait<'static> + 'b) { x as _ + //~^ ERROR: lifetime may not live long enough } 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>( x: *mut (dyn Trait<'static> + 'a), ) -> *mut Wrapper + 'b> { x as _ + //~^ ERROR: lifetime may not live long enough } fn cast_away_higher_ranked_wrap<'a>(x: *mut dyn for<'b> Trait<'b>) -> *mut Wrapper> { diff --git a/tests/ui/cast/ptr-to-trait-obj-ok.stderr b/tests/ui/cast/ptr-to-trait-obj-ok.stderr new file mode 100644 index 0000000000000..e162be16ce49a --- /dev/null +++ b/tests/ui/cast/ptr-to-trait-obj-ok.stderr @@ -0,0 +1,33 @@ +error: lifetime may not live long enough + --> $DIR/ptr-to-trait-obj-ok.rs:8:5 + | +LL | fn cast_inherent_lt<'a, 'b>(x: *mut (dyn Trait<'static> + 'a)) -> *mut (dyn Trait<'static> + 'b) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x as _ + | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a mutable pointer to `dyn Trait<'_>` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/ptr-to-trait-obj-ok.rs:34:5 + | +LL | fn cast_inherent_lt_wrap<'a, 'b>( + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | x as _ + | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a mutable pointer to `Wrapper>` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance + +error: aborting due to 2 previous errors +