diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 6bcfa9d8bf9a7..bfdfa896cd2b9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -410,6 +410,7 @@ impl<'tcx> BorrowExplanation<'tcx> { cx.add_sized_or_copy_bound_info(err, category, &path); if let ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: _, is_implicit_coercion: true, unsize_to: Some(unsize_ty), } = category diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 05826bea66bf8..6ebc7db62699f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -541,6 +541,23 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.add_placeholder_from_predicate_note(&mut diag, &path); self.add_sized_or_copy_bound_info(&mut diag, category, &path); + for constraint in &path { + if let ConstraintCategory::Cast { is_raw_ptr_dyn_type_cast: true, .. } = + constraint.category + { + diag.span_note( + constraint.span, + format!("raw pointer casts of trait objects cannot extend lifetimes"), + ); + diag.note(format!( + "this was previously accepted by the compiler but was changed recently" + )); + diag.help(format!( + "see for more information" + )); + } + } + self.buffer_error(diag); } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index e98c60e633805..37b9d684e1a45 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1697,6 +1697,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // should be as limited as possible; the note is prone to false positives and this // constraint usually isn't best to blame. ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: _, unsize_to: Some(unsize_ty), is_implicit_coercion: true, } if to_region == self.universal_regions().fr_static diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 43005fca29848..c066cae697de0 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1113,7 +1113,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.prove_predicate( ty::ClauseKind::WellFormed(src_ty.into()), location.to_locations(), - ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None }, + ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: false, + is_implicit_coercion, + unsize_to: None, + }, ); let src_ty = self.normalize(src_ty, location); @@ -1121,7 +1125,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { src_ty, *ty, location.to_locations(), - ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None }, + ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: false, + is_implicit_coercion, + unsize_to: None, + }, ) { span_mirbug!( self, @@ -1142,7 +1150,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.prove_predicate( ty::ClauseKind::WellFormed(src_ty.into()), location.to_locations(), - ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None }, + ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: false, + is_implicit_coercion, + unsize_to: None, + }, ); // The type that we see in the fcx is like @@ -1155,7 +1167,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { src_ty, *ty, location.to_locations(), - ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None }, + ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: false, + is_implicit_coercion, + unsize_to: None, + }, ) { span_mirbug!( self, @@ -1184,7 +1200,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ty_fn_ptr_from, *ty, location.to_locations(), - ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None }, + ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: false, + is_implicit_coercion, + unsize_to: None, + }, ) { span_mirbug!( self, @@ -1217,7 +1237,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ty_fn_ptr_from, *ty, location.to_locations(), - ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None }, + ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: false, + is_implicit_coercion, + unsize_to: None, + }, ) { span_mirbug!( self, @@ -1246,6 +1270,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { trait_ref, location.to_locations(), ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: false, is_implicit_coercion, unsize_to: Some(unsize_to), }, @@ -1271,7 +1296,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { *ty_from, *ty_to, location.to_locations(), - ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None }, + ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: false, + is_implicit_coercion, + unsize_to: None, + }, ) { span_mirbug!( self, @@ -1334,7 +1363,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { *ty_elem, *ty_to, location.to_locations(), - ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None }, + ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: false, + is_implicit_coercion, + unsize_to: None, + }, ) { span_mirbug!( self, @@ -1491,55 +1524,90 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { trait_ref, location.to_locations(), ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: false, is_implicit_coercion: true, unsize_to: None, }, ); - } else if let ty::Dynamic(src_tty, _src_lt) = + } else if let ty::Dynamic(src_tty, src_lt) = *self.struct_tail(src.ty, location).kind() && let ty::Dynamic(dst_tty, dst_lt) = *self.struct_tail(dst.ty, location).kind() - && src_tty.principal().is_some() - && dst_tty.principal().is_some() { - // This checks (lifetime part of) vtable validity for pointer casts, - // which is irrelevant when there are aren't principal traits on - // both sides (aka only auto traits). - // - // Note that other checks (such as denying `dyn Send` -> `dyn - // Debug`) are in `rustc_hir_typeck`. - - // Remove auto traits. - // Auto trait checks are handled in `rustc_hir_typeck` as FCW. - let src_obj = Ty::new_dynamic( - tcx, - tcx.mk_poly_existential_predicates( - &src_tty.without_auto_traits().collect::>(), - ), - // FIXME: Once we disallow casting `*const dyn Trait + 'short` - // to `*const dyn Trait + 'long`, then this can just be `src_lt`. - dst_lt, - ); - let dst_obj = Ty::new_dynamic( - tcx, - tcx.mk_poly_existential_predicates( - &dst_tty.without_auto_traits().collect::>(), + match (src_tty.principal(), dst_tty.principal()) { + (Some(_), Some(_)) => { + // This checks (lifetime part of) vtable validity for pointer casts, + // which is irrelevant when there are aren't principal traits on + // both sides (aka only auto traits). + // + // Note that other checks (such as denying `dyn Send` -> `dyn + // Debug`) are in `rustc_hir_typeck`. + + // Remove auto traits. + // Auto trait checks are handled in `rustc_hir_typeck`. + let src_obj = Ty::new_dynamic( + tcx, + tcx.mk_poly_existential_predicates( + &src_tty.without_auto_traits().collect::>(), + ), + src_lt, + ); + let dst_obj = Ty::new_dynamic( + tcx, + tcx.mk_poly_existential_predicates( + &dst_tty.without_auto_traits().collect::>(), + ), + dst_lt, + ); + + debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj); + + // Trait parameters are invariant, the only part that actually has + // subtyping here is the lifetime bound of the dyn-type. + // + // For example in `dyn Trait<'a> + 'b <: dyn Trait<'c> + 'd` we would + // require that `'a == 'c` but only that `'b: 'd`. + // + // We must not allow freely casting lifetime bounds of dyn-types as it + // may allow for inaccessible VTable methods being callable: #136702 + self.sub_types( + src_obj, + dst_obj, + location.to_locations(), + ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: true, + is_implicit_coercion: false, + unsize_to: None, + }, + ) + .unwrap(); + } + (None, None) => { + // The principalless (no non-auto traits) case: + // You can only cast `dyn Send + 'long` to `dyn Send + 'short`. + self.constraints.outlives_constraints.push( + OutlivesConstraint { + sup: src_lt.as_var(), + sub: dst_lt.as_var(), + locations: location.to_locations(), + span: location.to_locations().span(self.body), + category: ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: true, + is_implicit_coercion: false, + unsize_to: None, + }, + variance_info: ty::VarianceDiagInfo::default(), + from_closure: false, + }, + ); + } + (None, Some(_)) => bug!( + "introducing a principal should have errored in HIR typeck" ), - dst_lt, - ); - - debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj); - - self.sub_types( - src_obj, - dst_obj, - location.to_locations(), - ConstraintCategory::Cast { - is_implicit_coercion: false, - unsize_to: None, - }, - ) - .unwrap(); + (Some(_), None) => { + bug!("dropping the principal should have been an unsizing cast") + } + } } } CastKind::Transmute => { diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 7629ae9817fea..70954b4cb7829 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -108,6 +108,7 @@ pub enum ConstraintCategory<'tcx> { UseAsStatic, TypeAnnotation(AnnotationSource), Cast { + is_raw_ptr_dyn_type_cast: bool, /// Whether this cast is a coercion that was automatically inserted by the compiler. is_implicit_coercion: bool, /// Whether this is an unsizing coercion and if yes, this contains the target type. diff --git a/library/std/src/thread/lifecycle.rs b/library/std/src/thread/lifecycle.rs index 119322b909b52..a48594c606a35 100644 --- a/library/std/src/thread/lifecycle.rs +++ b/library/std/src/thread/lifecycle.rs @@ -111,7 +111,12 @@ where // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the // lifetime change is justified. let rust_start = unsafe { - Box::from_raw(Box::into_raw(Box::new(rust_start)) as *mut (dyn FnOnce() + Send + 'static)) + let ptr = Box::into_raw(Box::new(rust_start)); + let ptr = crate::mem::transmute::< + *mut (dyn FnOnce() + Send + '_), + *mut (dyn FnOnce() + Send + 'static), + >(ptr); + Box::from_raw(ptr) }; let init = Box::new(ThreadInit { handle: thread.clone(), rust_start }); diff --git a/tests/ui/cast/ptr-ptr-to-ptr-ptr-different-regions.rs b/tests/ui/cast/ptr-ptr-to-ptr-ptr-different-regions.rs new file mode 100644 index 0000000000000..bb4aeadbb433e --- /dev/null +++ b/tests/ui/cast/ptr-ptr-to-ptr-ptr-different-regions.rs @@ -0,0 +1,15 @@ +//@ check-pass + +// We allow extending lifetimes of object types if they are behind two layers +// of pointer indirection (as opposed to one). This is because this is the more +// general case of casting between two sized types (`*mut T as *mut U`). + +trait Trait { + fn foo(&self) {} +} + +fn bar<'a>(a: *mut *mut (dyn Trait + 'a)) -> *mut *mut (dyn Trait + 'static) { + a as _ +} + +fn main() {} diff --git a/tests/ui/cast/ptr-to-ptr-different-regions.rs b/tests/ui/cast/ptr-to-ptr-different-regions.rs index 0d525edc1332f..f0021628be018 100644 --- a/tests/ui/cast/ptr-to-ptr-different-regions.rs +++ b/tests/ui/cast/ptr-to-ptr-different-regions.rs @@ -1,20 +1,24 @@ -//@ 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. + // This should pass because raw pointer casts can do anything they want when + // VTables are not involved v as *const Foo<'static> } trait Trait {} +// We want to forbid this as extending lifetimes on object types may allow for +// uncallable VTable methods to become accessible. 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..c5910be2396be --- /dev/null +++ b/tests/ui/cast/ptr-to-ptr-different-regions.stderr @@ -0,0 +1,31 @@ +error: lifetime may not live long enough + --> $DIR/ptr-to-ptr-different-regions.rs:20: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 +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-ptr-different-regions.rs:20:5 + | +LL | ptr as _ + | ^^^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information +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 + 'static) { +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 + 'a)) -> *mut (dyn Trait + 'static) { +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-ptr-indirect-different-regions.rs b/tests/ui/cast/ptr-to-ptr-indirect-different-regions.rs new file mode 100644 index 0000000000000..50f11c568ad2a --- /dev/null +++ b/tests/ui/cast/ptr-to-ptr-indirect-different-regions.rs @@ -0,0 +1,15 @@ +// We want to forbid extending lifetimes on object types behind ptrs +// as it may allow for uncallable VTable methods to become accessible. + +trait Trait { + fn foo(&self) {} +} + +struct MyWrap(T); + +fn bar<'a>(a: *mut MyWrap<(dyn Trait + 'a)>) -> *mut MyWrap<(dyn Trait + 'static)> { + a as _ + //~^ ERROR: lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/cast/ptr-to-ptr-indirect-different-regions.stderr b/tests/ui/cast/ptr-to-ptr-indirect-different-regions.stderr new file mode 100644 index 0000000000000..43609fa570cbb --- /dev/null +++ b/tests/ui/cast/ptr-to-ptr-indirect-different-regions.stderr @@ -0,0 +1,31 @@ +error: lifetime may not live long enough + --> $DIR/ptr-to-ptr-indirect-different-regions.rs:11:5 + | +LL | fn bar<'a>(a: *mut MyWrap<(dyn Trait + 'a)>) -> *mut MyWrap<(dyn Trait + 'static)> { + | -- lifetime `'a` defined here +LL | a as _ + | ^^^^^^ returning this value requires that `'a` must outlive `'static` + | + = note: requirement occurs because of a mutable pointer to `MyWrap` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-ptr-indirect-different-regions.rs:11:5 + | +LL | a as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `a` + | +LL - fn bar<'a>(a: *mut MyWrap<(dyn Trait + 'a)>) -> *mut MyWrap<(dyn Trait + 'static)> { +LL + fn bar<'a>(a: *mut MyWrap<(dyn Trait + 'a)>) -> *mut MyWrap<(dyn Trait + 'a)> { + | +help: alternatively, add an explicit `'static` bound to this reference + | +LL - fn bar<'a>(a: *mut MyWrap<(dyn Trait + 'a)>) -> *mut MyWrap<(dyn Trait + 'static)> { +LL + fn bar<'a>(a: *mut MyWrap<(dyn Trait + 'static)>) -> *mut MyWrap<(dyn Trait + 'static)> { + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/cast/ptr-to-ptr-principalless.rs b/tests/ui/cast/ptr-to-ptr-principalless.rs new file mode 100644 index 0000000000000..0b1032d2669d7 --- /dev/null +++ b/tests/ui/cast/ptr-to-ptr-principalless.rs @@ -0,0 +1,74 @@ +// Test cases involving principal-less traits (dyn Send without a primary trait). + +struct Wrapper(T); + +// Cast to same auto trait + +fn unprincipled<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Send + 'b) { + x as _ + //~^ ERROR: lifetime may not live long enough +} + +fn unprincipled_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Send + 'static) { + x as _ + //~^ ERROR: lifetime may not live long enough +} + +fn unprincipled_wrap<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { + x as _ + //~^ ERROR: lifetime may not live long enough +} + +fn unprincipled_wrap_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { + x as _ + //~^ ERROR: lifetime may not live long enough +} + +// Cast to different auto trait + +fn unprincipled2<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'b) { + x as _ + //~^ ERROR: lifetime may not live long enough +} + +fn unprincipled2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'static) { + x as _ + //~^ ERROR: lifetime may not live long enough +} + +fn unprincipled_wrap2<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { + x as _ + //~^ ERROR: lifetime may not live long enough +} + +fn unprincipled_wrap2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { + x as _ + //~^ ERROR: lifetime may not live long enough +} + +// Cast away principal trait +trait Trait {} + +fn unprincipled3<'a, 'b>(x: *mut (dyn Trait + Send + 'a)) -> *mut (dyn Send + 'b) { + x as _ + //~^ ERROR: lifetime may not live long enough +} + +fn unprincipled3_static<'a>(x: *mut (dyn Trait + Send + 'a)) -> *mut (dyn Send + 'static) { + x as _ + //~^ ERROR: lifetime may not live long enough +} + +fn unprincipled_wrap3<'a, 'b>(x: *mut (dyn Trait + Send + 'a)) -> *mut Wrapper { + x as _ + //~^ ERROR: casting `*mut (dyn Trait + Send + 'a)` as `*mut Wrapper<(dyn Send + 'b)>` is invalid +} + +fn unprincipled_wrap3_static<'a>( + x: *mut (dyn Trait + Send + 'a) +) -> *mut Wrapper { + x as _ + //~^ ERROR: casting `*mut (dyn Trait + Send + 'a)` as `*mut Wrapper<(dyn Send + 'static)>` is invalid +} + +fn main() {} diff --git a/tests/ui/cast/ptr-to-ptr-principalless.stderr b/tests/ui/cast/ptr-to-ptr-principalless.stderr new file mode 100644 index 0000000000000..78f949232a1ca --- /dev/null +++ b/tests/ui/cast/ptr-to-ptr-principalless.stderr @@ -0,0 +1,274 @@ +error[E0606]: casting `*mut (dyn Trait + Send + 'a)` as `*mut Wrapper<(dyn Send + 'b)>` is invalid + --> $DIR/ptr-to-ptr-principalless.rs:63:5 + | +LL | x as _ + | ^^^^^^ + | + = note: the trait objects may have different vtables + +error[E0606]: casting `*mut (dyn Trait + Send + 'a)` as `*mut Wrapper<(dyn Send + 'static)>` is invalid + --> $DIR/ptr-to-ptr-principalless.rs:70:5 + | +LL | x as _ + | ^^^^^^ + | + = note: the trait objects may have different vtables + +error: lifetime may not live long enough + --> $DIR/ptr-to-ptr-principalless.rs:8:5 + | +LL | fn unprincipled<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Send + '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 Send` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-ptr-principalless.rs:8:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information + +error: lifetime may not live long enough + --> $DIR/ptr-to-ptr-principalless.rs:13:5 + | +LL | fn unprincipled_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Send + 'static) { + | -- lifetime `'a` defined here +LL | x as _ + | ^^^^^^ returning this value requires that `'a` must outlive `'static` + | + = note: requirement occurs because of a mutable pointer to `dyn Send` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-ptr-principalless.rs:13:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` + | +LL - fn unprincipled_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Send + 'static) { +LL + fn unprincipled_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Send + 'a) { + | +help: alternatively, add an explicit `'static` bound to this reference + | +LL - fn unprincipled_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Send + 'static) { +LL + fn unprincipled_static<'a>(x: *mut (dyn Send + 'static)) -> *mut (dyn Send + 'static) { + | + +error: lifetime may not live long enough + --> $DIR/ptr-to-ptr-principalless.rs:18:5 + | +LL | fn unprincipled_wrap<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { + | -- -- 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 +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-ptr-principalless.rs:18:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information + +error: lifetime may not live long enough + --> $DIR/ptr-to-ptr-principalless.rs:23:5 + | +LL | fn unprincipled_wrap_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { + | -- lifetime `'a` defined here +LL | x as _ + | ^^^^^^ returning this value requires that `'a` must outlive `'static` + | + = 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 +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-ptr-principalless.rs:23:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` + | +LL - fn unprincipled_wrap_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { +LL + fn unprincipled_wrap_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { + | +help: alternatively, add an explicit `'static` bound to this reference + | +LL - fn unprincipled_wrap_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { +LL + fn unprincipled_wrap_static<'a>(x: *mut (dyn Send + 'static)) -> *mut Wrapper { + | + +error: lifetime may not live long enough + --> $DIR/ptr-to-ptr-principalless.rs:30:5 + | +LL | fn unprincipled2<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + '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 Sync` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-ptr-principalless.rs:30:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information + +error: lifetime may not live long enough + --> $DIR/ptr-to-ptr-principalless.rs:35:5 + | +LL | fn unprincipled2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'static) { + | -- lifetime `'a` defined here +LL | x as _ + | ^^^^^^ returning this value requires that `'a` must outlive `'static` + | + = note: requirement occurs because of a mutable pointer to `dyn Sync` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-ptr-principalless.rs:35:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` + | +LL - fn unprincipled2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'static) { +LL + fn unprincipled2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'a) { + | +help: alternatively, add an explicit `'static` bound to this reference + | +LL - fn unprincipled2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'static) { +LL + fn unprincipled2_static<'a>(x: *mut (dyn Send + 'static)) -> *mut (dyn Sync + 'static) { + | + +error: lifetime may not live long enough + --> $DIR/ptr-to-ptr-principalless.rs:40:5 + | +LL | fn unprincipled_wrap2<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { + | -- -- 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 +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-ptr-principalless.rs:40:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information + +error: lifetime may not live long enough + --> $DIR/ptr-to-ptr-principalless.rs:45:5 + | +LL | fn unprincipled_wrap2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { + | -- lifetime `'a` defined here +LL | x as _ + | ^^^^^^ returning this value requires that `'a` must outlive `'static` + | + = 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 +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-ptr-principalless.rs:45:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` + | +LL - fn unprincipled_wrap2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { +LL + fn unprincipled_wrap2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { + | +help: alternatively, add an explicit `'static` bound to this reference + | +LL - fn unprincipled_wrap2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { +LL + fn unprincipled_wrap2_static<'a>(x: *mut (dyn Send + 'static)) -> *mut Wrapper { + | + +error: lifetime may not live long enough + --> $DIR/ptr-to-ptr-principalless.rs:53:5 + | +LL | fn unprincipled3<'a, 'b>(x: *mut (dyn Trait + Send + 'a)) -> *mut (dyn Send + '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 Send` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-ptr-principalless.rs:53:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information + +error: lifetime may not live long enough + --> $DIR/ptr-to-ptr-principalless.rs:58:5 + | +LL | fn unprincipled3_static<'a>(x: *mut (dyn Trait + Send + 'a)) -> *mut (dyn Send + 'static) { + | -- lifetime `'a` defined here +LL | x as _ + | ^^^^^^ returning this value requires that `'a` must outlive `'static` + | + = note: requirement occurs because of a mutable pointer to `dyn Send` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-ptr-principalless.rs:58:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` + | +LL - fn unprincipled3_static<'a>(x: *mut (dyn Trait + Send + 'a)) -> *mut (dyn Send + 'static) { +LL + fn unprincipled3_static<'a>(x: *mut (dyn Trait + Send + 'a)) -> *mut (dyn Send + 'a) { + | +help: alternatively, add an explicit `'static` bound to this reference + | +LL - fn unprincipled3_static<'a>(x: *mut (dyn Trait + Send + 'a)) -> *mut (dyn Send + 'static) { +LL + fn unprincipled3_static<'a>(x: *mut (dyn Trait + Send + 'static)) -> *mut (dyn Send + 'static) { + | + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.current.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.current.stderr index 62f17a6568550..af7744192223f 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.current.stderr +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.current.stderr @@ -6,6 +6,14 @@ LL | fn m<'a>() { LL | let unsend: *const dyn Cat<'a> = &(); LL | let _send = unsend as *const S>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:24:17 + | +LL | let _send = unsend as *const S>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information error: aborting due to 1 previous error diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr index 62f17a6568550..af7744192223f 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr @@ -6,6 +6,14 @@ LL | fn m<'a>() { LL | let unsend: *const dyn Cat<'a> = &(); LL | let _send = unsend as *const S>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:24:17 + | +LL | let _send = unsend as *const S>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information error: aborting due to 1 previous error diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr index b7319e3356bd0..4b5927f094bc3 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr @@ -5,6 +5,14 @@ LL | fn bad_cast<'a>(x: *const dyn Static<'static>) -> *const dyn Static<'a> { | -- lifetime `'a` defined here LL | x as _ | ^^^^^^ returning this value requires that `'a` must outlive `'static` + | +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-trait-obj-different-regions-lt-ext.rs:12:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information error: aborting due to 1 previous error diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr index 88a89dc4ac1b1..f2c060e4b279b 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr @@ -12,6 +12,13 @@ LL | x as _ = 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 +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:7:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:7:5 @@ -27,6 +34,13 @@ LL | x as _ = 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 +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:7:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information help: `'b` and `'a` must be the same: replace one with the other @@ -44,6 +58,13 @@ LL | x as _ = 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 +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:12:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:16:5 @@ -59,6 +80,13 @@ LL | x as _ = 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 +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:16:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:20:5 @@ -97,6 +125,13 @@ LL | x as _ = note: requirement occurs because of a mutable pointer to `dyn Assocked` = note: mutable pointers are invariant over their type parameter = help: see for more information about variance +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:32:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:32:5 @@ -113,6 +148,13 @@ LL | x as _ = note: requirement occurs because of a mutable pointer to `dyn Assocked` = note: mutable pointers are invariant over their type parameter = help: see for more information about variance +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:32:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information help: `'b` and `'a` must be the same: replace one with the other | @@ -133,6 +175,13 @@ LL | x as _ = note: requirement occurs because of a mutable pointer to `dyn Assocked>` = note: mutable pointers are invariant over their type parameter = help: see for more information about variance +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:39:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:39:5 @@ -149,6 +198,13 @@ LL | x as _ = note: requirement occurs because of a mutable pointer to `dyn Assocked>` = note: mutable pointers are invariant over their type parameter = help: see for more information about variance +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:39:5 + | +LL | x as _ + | ^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information help: `'b` and `'a` must be the same: replace one with the other | @@ -168,6 +224,14 @@ LL | require_static(ptr as _) | | | `ptr` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: raw pointer casts of trait objects cannot extend lifetimes + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:46:20 + | +LL | require_static(ptr as _) + | ^^^^^^^^ + = note: this was previously accepted by the compiler but was changed recently + = help: see for more information error: aborting due to 11 previous errors diff --git a/tests/ui/cast/ptr-to-trait-obj-ok.rs b/tests/ui/cast/ptr-to-trait-obj-ok.rs index dbeee9d29441e..e6b3b23e2da20 100644 --- a/tests/ui/cast/ptr-to-trait-obj-ok.rs +++ b/tests/ui/cast/ptr-to-trait-obj-ok.rs @@ -1,12 +1,23 @@ //@ check-pass +// Casting pointers to object types has some special rules in order to +// ensure VTables stay valid. E.g. +// - Cannot introduce new autotraits +// - Cannot extend or shrink lifetimes in trait arguments +// - Cannot extend the lifetime of the object type +// +// This test is a mostly miscellaneous set of examples of casts that do +// uphold these rules + trait Trait<'a> {} fn remove_auto<'a>(x: *mut (dyn Trait<'a> + Send)) -> *mut dyn Trait<'a> { x as _ } -fn cast_inherent_lt<'a, 'b>(x: *mut (dyn Trait<'static> + 'a)) -> *mut (dyn Trait<'static> + 'b) { +fn cast_inherent_lt<'a: 'b, 'b>( + x: *mut (dyn Trait<'static> + 'a) +) -> *mut (dyn Trait<'static> + 'b) { x as _ } @@ -14,7 +25,11 @@ fn cast_away_higher_ranked<'a>(x: *mut dyn for<'b> Trait<'b>) -> *mut dyn Trait< x as _ } -fn unprincipled<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'b) { +fn unprincipled<'a: 'b, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'b) { + x as _ +} + +fn remove_principal<'a: 'b, 'b, 't>(x: *mut (dyn Trait<'t> + Send + 'a)) -> *mut (dyn Send + 'b) { x as _ } @@ -29,7 +44,7 @@ fn remove_auto_wrap<'a>(x: *mut (dyn Trait<'a> + Send)) -> *mut Wrapper( +fn cast_inherent_lt_wrap<'a: 'b, 'b>( x: *mut (dyn Trait<'static> + 'a), ) -> *mut Wrapper + 'b> { x as _ @@ -39,7 +54,7 @@ fn cast_away_higher_ranked_wrap<'a>(x: *mut dyn for<'b> Trait<'b>) -> *mut Wrapp x as _ } -fn unprincipled_wrap<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { +fn unprincipled_wrap<'a: 'b, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { x as _ }