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

Raw pointer cast triggers "lifetime may not live long enough" #113257

Closed
ChayimFriedman2 opened this issue Jul 2, 2023 · 4 comments · Fixed by #113262
Closed

Raw pointer cast triggers "lifetime may not live long enough" #113257

ChayimFriedman2 opened this issue Jul 2, 2023 · 4 comments · Fixed by #113262
Assignees
Labels
A-coercions Area: implicit and explicit `expr as Type` coercions A-raw-pointers Area: raw pointers, MaybeUninit, NonNull C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@ChayimFriedman2
Copy link
Contributor

I tried this code:

struct Foo<'a>(&'a ());

fn foo(v: *const Foo<'_>) -> *const Foo<'static> {
    v as *const Foo<'static>
}

Playground.

I expected to see this happen: it compiles, since raw pointer casts should be allowed even for completely different types.

Instead, this happened: it fails with:

error: lifetime may not live long enough
 --> src/lib.rs:4:5
  |
3 | fn foo(v: *const Foo<'_>) -> *const Foo<'static> {
  |        - has type `*const Foo<'1>`
4 |     v as *const Foo<'static>
  |     ^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`

It looks like for some reason the compiler creates a lifetime obligation here.

Strangely, it works with cast():

fn foo(v: *const Foo<'_>) -> *const Foo<'static> {
    v.cast::<Foo<'static>>()
}

Playground.

@ChayimFriedman2 ChayimFriedman2 added the C-bug Category: This is a bug. label Jul 2, 2023
@Noratrieb Noratrieb added A-raw-pointers Area: raw pointers, MaybeUninit, NonNull T-types Relevant to the types team, which will review and decide on the PR/issue. labels Jul 2, 2023
@Noratrieb
Copy link
Member

I've looked into this. The issue is that typeck considers this cast to be a "coercion cast", because typeck thinks that you could replace the function body with just v since the types are the same (it also triggers the trivial_casts lint (allow-by-default)). HIR typeck isn't aware of lifetimes. So then THIR building and MIR building build MIR that doesn't contain a PtrToPtr cast but instead just assigns one to the other. The borrow checker is rightfully not pleased.

The bug here is that the THIR does not contain an explicit cast anymore. I'm not sure how to best fix this, as the current logic for "is this a no-op cast (called coercion cast in the code)" is just "try to coerce the types in the same way that happens on coercion sites and if it works it has to be useless". Which is wrong in the presence of lifetimes.

It seems like the current strategy works this way because it reuses some code in THIR building.

Thinking about it a little more, this is very special to pointer casts, because only pointer casts are allowed to change the type like this. Maybe THIR building should just special case pointer casts to always be emitted?

@Noratrieb Noratrieb added A-coercions Area: implicit and explicit `expr as Type` coercions T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed T-types Relevant to the types team, which will review and decide on the PR/issue. labels Jul 2, 2023
@Noratrieb Noratrieb self-assigned this Jul 2, 2023
@RalfJung
Copy link
Member

Unfortunately due to this bug there is a transmute in the standard library that should be turned into a raw pointer cast, but we cannot.

@Noratrieb
Copy link
Member

I think that's a different case, these are boxes and not raw pointers, and box->box casts are not allowed to do arbitrary changes (and are in fact coercion casts, so the as doesn't actually do anything). The error there is correct and this needs a transmute.

@RalfJung
Copy link
Member

@Nilstrieb I'd like to replace the transmutes by raw pointer casts, which IMO is much preferable, similar to #114799. But this bug is in the way of that.

@bors bors closed this as completed in 6f65201 Oct 26, 2023
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Oct 27, 2023
replace transmute by raw pointer cast

Now that rust-lang#113257 is fixed we can finally do this. :)
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Oct 27, 2023
Rollup merge of rust-lang#117266 - RalfJung:cast-not-transmute, r=thomcc

replace transmute by raw pointer cast

Now that rust-lang#113257 is fixed we can finally do this. :)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-coercions Area: implicit and explicit `expr as Type` coercions A-raw-pointers Area: raw pointers, MaybeUninit, NonNull C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants