Skip to content

Can't cast a pointer of a trait object newtype to a pointer of that trait object. #128625

New issue

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

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

Already on GitHub? # to your account

Closed
theemathas opened this issue Aug 4, 2024 · 2 comments · Fixed by #136127
Closed
Labels
A-raw-pointers Area: raw pointers, MaybeUninit, NonNull A-trait-objects Area: trait objects, vtable layout C-discussion Category: Discussion or questions that doesn't represent real issues. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@theemathas
Copy link
Contributor

theemathas commented Aug 4, 2024

I tried this code:

trait Trait {}

struct Wrap(dyn Trait);

fn cast(x: *mut Wrap) {
    x as *mut dyn Trait;
}

I expected the code to compile. Instead, I got the following error, where it appears that the compiler is trying to do an unsize coercion and failing:

   Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `Wrap: Trait` is not satisfied
 --> src/lib.rs:6:5
  |
6 |     x as *mut dyn Trait;
  |     ^ the trait `Trait` is not implemented for `Wrap`
  |
help: this trait has no implementations, consider adding one
 --> src/lib.rs:1:1
  |
1 | trait Trait {}
  | ^^^^^^^^^^^
  = note: required for the cast from `*mut Wrap` to `*mut dyn Trait`

error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
 --> src/lib.rs:6:5
  |
6 |     x as *mut dyn Trait;
  |     ^ doesn't have a size known at compile-time
  |
  = help: within `Wrap`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`, which is required by `Wrap: Sized`
note: required because it appears within the type `Wrap`
 --> src/lib.rs:3:8
  |
3 | struct Wrap(dyn Trait);
  |        ^^^^
  = note: required for the cast from `*mut Wrap` to `*mut dyn Trait`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` (lib) due to 2 previous errors

Of note, the following code compiles fine:

trait Trait {}

struct Wrap(dyn Trait);

fn cast(x: *mut Wrap) {
    x as *mut (dyn Trait,);
}

Probably related to #128621

Meta

This issue reproduces on the playground on stable (1.80.0), and nightly (2024-08-02 fd8d6fb).

@theemathas theemathas added the C-bug Category: This is a bug. label Aug 4, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Aug 4, 2024
@saethlin saethlin added C-discussion Category: Discussion or questions that doesn't represent real issues. and removed C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Aug 4, 2024
@theemathas
Copy link
Contributor Author

Another variant that compiles fine:

trait Trait {}

struct Wrap1(dyn Trait);
struct Wrap2(dyn Trait);

fn cast(x: *mut Wrap1) -> *mut Wrap2 {
    x as *mut Wrap2
}

@saethlin saethlin added the T-types Relevant to the types team, which will review and decide on the PR/issue. label Aug 4, 2024
@fmease fmease added A-raw-pointers Area: raw pointers, MaybeUninit, NonNull A-trait-objects Area: trait objects, vtable layout labels Dec 21, 2024
@theemathas
Copy link
Contributor Author

Oddly, doing the cast a roundabout way using a generic makes the code compile:

trait Trait {}

struct Wrap<T: ?Sized>(T);

fn cast_specific(x: *mut Wrap<dyn Trait>) -> *mut dyn Trait {
    cast_generic::<dyn Trait>(x) // compiles fine
    // x as *mut dyn Trait // doesn't work
}

fn cast_generic<T: ?Sized>(x: *mut Wrap<T>) -> *mut T {
    x as *mut T
}

jieyouxu added a commit to jieyouxu/rust that referenced this issue Mar 9, 2025
…r=compiler-errors

Allow `*const W<dyn A> -> *const dyn A` ptr cast

Followup of rust-lang#120248 (comment).

This PR allows casting pointers from something wrapping a trait object, to the trait object, i.e. `*const W<dyn A> -> *const dyn A` where `W` is `struct W<T: ?Sized>(T);`.

r? compiler-errors

Fixes rust-lang#128625
@bors bors closed this as completed in 84c2050 Mar 9, 2025
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Mar 9, 2025
Rollup merge of rust-lang#136127 - WaffleLapkin:dyn_ptr_unwrap_cast, r=compiler-errors

Allow `*const W<dyn A> -> *const dyn A` ptr cast

Followup of rust-lang#120248 (comment).

This PR allows casting pointers from something wrapping a trait object, to the trait object, i.e. `*const W<dyn A> -> *const dyn A` where `W` is `struct W<T: ?Sized>(T);`.

r? compiler-errors

Fixes rust-lang#128625
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-raw-pointers Area: raw pointers, MaybeUninit, NonNull A-trait-objects Area: trait objects, vtable layout C-discussion Category: Discussion or questions that doesn't represent real issues. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants