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

mem::transmute on types of different size (but the type size is known) #47966

Closed
Avarel opened this issue Feb 2, 2018 · 9 comments
Closed

mem::transmute on types of different size (but the type size is known) #47966

Avarel opened this issue Feb 2, 2018 · 9 comments
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Avarel
Copy link

Avarel commented Feb 2, 2018

Problem

When I try to compile this method, the compiler reports that mem::transmute is being called on types of different sizes. (Which doesn't make sense because T size should be known in this context).

pub fn partition2<T: Sized>(source: [T; 52]) -> [[T; 13]; 4] {
    use std::mem;
    unsafe { mem::transmute(source) }
}

Compiler Error

error[E0512]: transmute called with types of different sizes
 --> src/main.rs:9:14
  |
9 |     unsafe { mem::transmute(source) }
  |              ^^^^^^^^^^^^^^
  |
  = note: source type: [T; 52] (size can vary because of T)
  = note: target type: [[T; 13]; 4] (size can vary because of T)

Working Example

Replacing T with a struct and it compiles fine (also works with String):

pub struct Card {
    value: u8,
    suit: Suit
}

pub enum Suit {
    Spades,
    Clubs,
    Diamonds,
    Hearts,
}

pub fn partition(source: [Card; 52]) -> [[Card; 13]; 4] {
    use std::mem;
    unsafe { mem::transmute(source) }
}

Meta

rustc 1.24.0-nightly (23032d0af 2017-11-30)
binary: rustc
commit-hash: 23032d0afa2b0e0c60a9b2ae62709f846d90007c
commit-date: 2017-11-30
host: x86_64-apple-darwin
release: 1.24.0-nightly
LLVM version: 4.0
@kennytm kennytm added C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 2, 2018
@kennytm
Copy link
Member

kennytm commented Feb 2, 2018

I doubt if we can easily fix this without pushing this E0512 error to post-monomorphization. Allowing this means the compiler has to be able to solve equations to prove that size_of::<T>() * 52 == (size_of::<T>() * 13) * 4.

@vitalyd
Copy link

vitalyd commented Feb 2, 2018

size_of::<T>() doesn’t really matter though right? Whatever it is post-monomorphization, it’s the same on both sides.

@hanna-kruppe
Copy link
Contributor

The check for equal size is pre-monomorphization (intentionally). So the compiler would have to reason about the size of the type parameter T abstractly to some degree.

@leonardo-m
Copy link

I think having a compiler able to solve first degree equations like that is going to be useful once we have const generics.

@scottmcm
Copy link
Member

scottmcm commented Feb 4, 2018

I believe the correct answer here is "just use pointer casting". I don't think there's a good argument for adding complexity here when the method's use is discouraged anyway.

I'm confident, however, that eventually we'll have const bounds enough to allow things like where const size_of::<T>() == size_of::<U>(), but that's a long way off -- the current RFC doesn't even know that N+1 == N+1, having intentionally left all such equation solving for a future RFC: https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#equality-of-two-abstract-const-expressions

@steveklabnik
Copy link
Member

Triage: two years later, I think we should close this. Maybe it can be done someday, as @scottmcm points out, but it's unclear when that, if ever, will happen.

@That3Percent
Copy link

It would be useful to have a working example of the "just use pointer casting" technique in the interim while waiting for something to be implemented.

I'm arriving at this thread after writing a function which attempts to transmute a [MaybeUninit<T>; const_size]. transmute is the recommended method when initializing that type, and it's unclear how to accomplish this when generics are involved.

@That3Percent
Copy link

There is a crate which allows for this call to be made - transmute

@scottmcm
Copy link
Member

An an update to anyone following this, there's a group working on safe transmutes that may end up being the solution for this desire: rust-lang/lang-team#21

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

8 participants