@@ -821,6 +821,70 @@ This error indicates that the compiler found multiple functions with the
821
821
point into a Rust program.
822
822
"## ,
823
823
824
+ // FIXME link this to the relevant turpl chapters for instilling fear of the
825
+ // transmute gods in the user
826
+ E0139 : r##"
827
+ There are various restrictions on transmuting between types in Rust; for example
828
+ types being transmuted must have the same size. To apply all these restrictions,
829
+ the compiler must know the exact types that may be transmuted. When type
830
+ parameters are involved, this cannot always be done.
831
+
832
+ So, for example, the following is not allowed:
833
+
834
+ ```
835
+ struct Foo<T>(Vec<T>)
836
+
837
+ fn foo<T>(x: Vec<T>) {
838
+ // we are transmuting between Vec<T> and Foo<T> here
839
+ let y: Foo<T> = unsafe { transmute(x) };
840
+ // do something with y
841
+ }
842
+ ```
843
+
844
+ In this specific case there's a good chance that the transmute is harmless (but
845
+ this is not guaranteed by Rust). However, when alignment and enum optimizations
846
+ come into the picture, it's quite likely that the sizes may or may not match
847
+ with different type parameter substitutions. It's not possible to check this for
848
+ _all_ possible types, so `transmute()` simply only accepts types without any
849
+ unsubstituted type parameters.
850
+
851
+ If you need this, there's a good chance you're doing something wrong. Keep in
852
+ mind that Rust doesn't guarantee much about the layout of different structs
853
+ (even two structs with identical declarations may have different layouts). If
854
+ there is a solution that avoids the transmute entirely, try it instead.
855
+
856
+ If it's possible, hand-monomorphize the code by writing the function for each
857
+ possible type substitution. It's possible to use traits to do this cleanly,
858
+ for example:
859
+
860
+ ```
861
+ trait MyTransmutableType {
862
+ fn transmute(Vec<Self>) -> Foo<Self>
863
+ }
864
+
865
+ impl MyTransmutableType for u8 {
866
+ fn transmute(x: Foo<u8>) -> Vec<u8> {
867
+ transmute(x)
868
+ }
869
+ }
870
+ impl MyTransmutableType for String {
871
+ fn transmute(x: Foo<String>) -> Vec<String> {
872
+ transmute(x)
873
+ }
874
+ }
875
+ // ... more impls for the types you intend to transmute
876
+
877
+ fn foo<T: MyTransmutableType>(x: Vec<T>) {
878
+ let y: Foo<T> = <T as MyTransmutableType>::transmute(x);
879
+ // do something with y
880
+ }
881
+ ```
882
+
883
+ Each impl will be checked for a size match in the transmute as usual, and since
884
+ there are no unbound type parameters involved, this should compile unless there
885
+ is a size mismatch in one of the impls.
886
+ "## ,
887
+
824
888
E0152 : r##"
825
889
Lang items are already implemented in the standard library. Unless you are
826
890
writing a free-standing application (e.g. a kernel), you do not need to provide
@@ -1608,7 +1672,6 @@ register_diagnostics! {
1608
1672
// E0006 // merged with E0005
1609
1673
// E0134,
1610
1674
// E0135,
1611
- E0139 ,
1612
1675
E0264 , // unknown external lang item
1613
1676
E0269 , // not all control paths return a value
1614
1677
E0270 , // computation may converge in a function marked as diverging
0 commit comments