rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.57k stars 12.74k forks source link

Wide raw pointer casts let me assert marker trait bounds but not lifetime bounds #114798

Closed RalfJung closed 1 year ago

RalfJung commented 1 year ago

The following code compiles just fine:

trait Trait {}

fn assert_send(ptr: *mut dyn Trait) -> *mut (dyn Trait + Send) {
    ptr as _
}

This basically unsafely asserts that our underlying type is actually Send.

However, strangely, the following code is rejected:

fn assert_static<'a>(ptr: *mut (dyn Trait + 'a)) -> *mut (dyn Trait + 'static) {
    ptr as _
}

This does basically the same as the above, it unsafely assertions that our underlying type satisfies the 'static bound. So I would expect both of these to be accepted. But somehow the borrow checker is getting in the way and says something about variance:

error: lifetime may not live long enough
 --> src/lib.rs:8:5
  |
7 | fn assert_static<'a>(ptr: *mut (dyn Trait + 'a)) -> *mut (dyn Trait + 'static) {
  |                  -- lifetime `'a` defined here
8 |     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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `ptr`
  |
7 | fn assert_static<'a>(ptr: *mut (dyn Trait + 'a)) -> *mut (dyn Trait + 'a) {
  |                                                                       ~~
help: alternatively, add an explicit `'static` bound to this reference
  |
7 | fn assert_static<'a>(ptr: *mut (dyn Trait + 'static)) -> *mut (dyn Trait + 'static) {
  |                           ~~~~~~~~~~~~~~~~~~~~~~~~~~

To work around this, one has to use a transmute, and that's always a bad sign. This even happens in the standard library.

Cc @rust-lang/types

lcnr commented 1 year ago

I expect the following to happen here:

I think this should be fixable :thinking:

lukas-code commented 1 year ago

related: https://github.com/rust-lang/rust/issues/113257

RalfJung commented 1 year ago

Oh interesting, so this fails even when the pointers are not wide -- yes that definitely looks like a bug to me.

Closing as a duplicate of https://github.com/rust-lang/rust/issues/113257.