]> git.lizzy.rs Git - rust.git/blob - src/librustc_error_codes/error_codes/E0139.md
Auto merge of #66396 - smmalis37:pythontest, r=alexcrichton
[rust.git] / src / librustc_error_codes / error_codes / E0139.md
1 #### Note: this error code is no longer emitted by the compiler.
2
3 There are various restrictions on transmuting between types in Rust; for example
4 types being transmuted must have the same size. To apply all these restrictions,
5 the compiler must know the exact types that may be transmuted. When type
6 parameters are involved, this cannot always be done.
7
8 So, for example, the following is not allowed:
9
10 ```
11 use std::mem::transmute;
12
13 struct Foo<T>(Vec<T>);
14
15 fn foo<T>(x: Vec<T>) {
16     // we are transmuting between Vec<T> and Foo<F> here
17     let y: Foo<T> = unsafe { transmute(x) };
18     // do something with y
19 }
20 ```
21
22 In this specific case there's a good chance that the transmute is harmless (but
23 this is not guaranteed by Rust). However, when alignment and enum optimizations
24 come into the picture, it's quite likely that the sizes may or may not match
25 with different type parameter substitutions. It's not possible to check this for
26 _all_ possible types, so `transmute()` simply only accepts types without any
27 unsubstituted type parameters.
28
29 If you need this, there's a good chance you're doing something wrong. Keep in
30 mind that Rust doesn't guarantee much about the layout of different structs
31 (even two structs with identical declarations may have different layouts). If
32 there is a solution that avoids the transmute entirely, try it instead.
33
34 If it's possible, hand-monomorphize the code by writing the function for each
35 possible type substitution. It's possible to use traits to do this cleanly,
36 for example:
37
38 ```
39 use std::mem::transmute;
40
41 struct Foo<T>(Vec<T>);
42
43 trait MyTransmutableType: Sized {
44     fn transmute(_: Vec<Self>) -> Foo<Self>;
45 }
46
47 impl MyTransmutableType for u8 {
48     fn transmute(x: Vec<u8>) -> Foo<u8> {
49         unsafe { transmute(x) }
50     }
51 }
52
53 impl MyTransmutableType for String {
54     fn transmute(x: Vec<String>) -> Foo<String> {
55         unsafe { transmute(x) }
56     }
57 }
58
59 // ... more impls for the types you intend to transmute
60
61 fn foo<T: MyTransmutableType>(x: Vec<T>) {
62     let y: Foo<T> = <T as MyTransmutableType>::transmute(x);
63     // do something with y
64 }
65 ```
66
67 Each impl will be checked for a size match in the transmute as usual, and since
68 there are no unbound type parameters involved, this should compile unless there
69 is a size mismatch in one of the impls.
70
71 It is also possible to manually transmute:
72
73 ```
74 # use std::ptr;
75 # let v = Some("value");
76 # type SomeType = &'static [u8];
77 unsafe {
78     ptr::read(&v as *const _ as *const SomeType) // `v` transmuted to `SomeType`
79 }
80 # ;
81 ```
82
83 Note that this does not move `v` (unlike `transmute`), and may need a
84 call to `mem::forget(v)` in case you want to avoid destructors being called.