Skip to content

Commit 674fb83

Browse files
committed
---
yaml --- r: 228732 b: refs/heads/try c: 74768e9 h: refs/heads/master v: v3
1 parent 04ba490 commit 674fb83

File tree

2 files changed

+65
-2
lines changed

2 files changed

+65
-2
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: aca2057ed5fb7af3f8905b2bc01f72fa001c35c8
33
refs/heads/snap-stage3: 1af31d4974e33027a68126fa5a5a3c2c6491824f
4-
refs/heads/try: 3080df36e27ed74399f9fe22e4796e209abd2b69
4+
refs/heads/try: 74768e9a6ccac85f813e4125c76f9cb52a2ac618
55
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
66
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
77
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try/src/librustc/diagnostics.rs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,70 @@ This error indicates that the compiler found multiple functions with the
821821
point into a Rust program.
822822
"##,
823823

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+
824888
E0152: r##"
825889
Lang items are already implemented in the standard library. Unless you are
826890
writing a free-standing application (e.g. a kernel), you do not need to provide
@@ -1608,7 +1672,6 @@ register_diagnostics! {
16081672
// E0006 // merged with E0005
16091673
// E0134,
16101674
// E0135,
1611-
E0139,
16121675
E0264, // unknown external lang item
16131676
E0269, // not all control paths return a value
16141677
E0270, // computation may converge in a function marked as diverging

0 commit comments

Comments
 (0)