Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
RalfJung opened this issue Aug 14, 2023 · 3 comments
Closed

Comments

@RalfJung
Copy link
Member

RalfJung commented Aug 14, 2023

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

@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Aug 14, 2023
@lcnr
Copy link
Contributor

lcnr commented Aug 14, 2023

I expect the following to happen here:

  • the cast works in HIR typeck
  • during MIR building, we throw out identity casts. This looks at the types returned by HIR typeck which have erased regions
  • this means the MIR used by borrowck doesn't have cast

I think this should be fixable 🤔

@lukas-code
Copy link
Member

related: #113257

@RalfJung
Copy link
Member Author

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 #113257.

@Noratrieb Noratrieb removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Aug 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants