| #### Note: this error code is no longer emitted by the compiler. |
| |
| There are various restrictions on transmuting between types in Rust; for example |
| types being transmuted must have the same size. To apply all these restrictions, |
| the compiler must know the exact types that may be transmuted. When type |
| parameters are involved, this cannot always be done. |
| |
| So, for example, the following is not allowed: |
| |
| ``` |
| use std::mem::transmute; |
| |
| struct Foo<T>(Vec<T>); |
| |
| fn foo<T>(x: Vec<T>) { |
| // we are transmuting between Vec<T> and Foo<F> here |
| let y: Foo<T> = unsafe { transmute(x) }; |
| // do something with y |
| } |
| ``` |
| |
| In this specific case there's a good chance that the transmute is harmless (but |
| this is not guaranteed by Rust). However, when alignment and enum optimizations |
| come into the picture, it's quite likely that the sizes may or may not match |
| with different type parameter instantiations. It's not possible to check this |
| for _all_ possible types, so `transmute()` simply only accepts types without any |
| uninstantiated type parameters. |
| |
| If you need this, there's a good chance you're doing something wrong. Keep in |
| mind that Rust doesn't guarantee much about the layout of different structs |
| (even two structs with identical declarations may have different layouts). If |
| there is a solution that avoids the transmute entirely, try it instead. |
| |
| If it's possible, hand-monomorphize the code by writing the function for each |
| possible type instantiation. It's possible to use traits to do this cleanly, |
| for example: |
| |
| ``` |
| use std::mem::transmute; |
| |
| struct Foo<T>(Vec<T>); |
| |
| trait MyTransmutableType: Sized { |
| fn transmute(_: Vec<Self>) -> Foo<Self>; |
| } |
| |
| impl MyTransmutableType for u8 { |
| fn transmute(x: Vec<u8>) -> Foo<u8> { |
| unsafe { transmute(x) } |
| } |
| } |
| |
| impl MyTransmutableType for String { |
| fn transmute(x: Vec<String>) -> Foo<String> { |
| unsafe { transmute(x) } |
| } |
| } |
| |
| // ... more impls for the types you intend to transmute |
| |
| fn foo<T: MyTransmutableType>(x: Vec<T>) { |
| let y: Foo<T> = <T as MyTransmutableType>::transmute(x); |
| // do something with y |
| } |
| ``` |
| |
| Each impl will be checked for a size match in the transmute as usual, and since |
| there are no unbound type parameters involved, this should compile unless there |
| is a size mismatch in one of the impls. |
| |
| It is also possible to manually transmute: |
| |
| ``` |
| # use std::ptr; |
| # let v = Some("value"); |
| # type SomeType = &'static [u8]; |
| unsafe { |
| ptr::read(&v as *const _ as *const SomeType) // `v` transmuted to `SomeType` |
| } |
| # ; |
| ``` |
| |
| Note that this does not move `v` (unlike `transmute`), and may need a |
| call to `mem::forget(v)` in case you want to avoid destructors being called. |