about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTobias Bucher <tobiasbucher5991@gmail.com>2015-07-24 03:04:55 +0200
committerTobias Bucher <tobiasbucher5991@gmail.com>2015-08-09 22:05:22 +0200
commit22ec5f4af7b5a85ad375d672ed727571b49f3cad (patch)
treeeea29f1286398aaaa9d55f23163ddcc49b033eeb
parentfebdc3b201bcce1546c88e3be1b956d3f90d3059 (diff)
downloadrust-22ec5f4af7b5a85ad375d672ed727571b49f3cad.tar.gz
rust-22ec5f4af7b5a85ad375d672ed727571b49f3cad.zip
Replace many uses of `mem::transmute` with more specific functions
The replacements are functions that usually use a single `mem::transmute` in
their body and restrict input and output via more concrete types than `T` and
`U`. Worth noting are the `transmute` functions for slices and the `from_utf8*`
family for mutable slices. Additionally, `mem::transmute` was often used for
casting raw pointers, when you can already cast raw pointers just fine with
`as`.
-rw-r--r--src/liballoc/arc.rs2
-rw-r--r--src/libarena/lib.rs9
-rw-r--r--src/libcollections/btree/node.rs13
-rw-r--r--src/libcollections/lib.rs1
-rw-r--r--src/libcollections/slice.rs1
-rw-r--r--src/libcollections/str.rs16
-rw-r--r--src/libcollections/string.rs6
-rw-r--r--src/libcollections/vec.rs2
-rw-r--r--src/libcore/any.rs4
-rw-r--r--src/libcore/cmp.rs7
-rw-r--r--src/libcore/fmt/mod.rs4
-rw-r--r--src/libcore/ptr.rs13
-rw-r--r--src/libcore/slice.rs54
-rw-r--r--src/libcore/str/mod.rs22
-rw-r--r--src/libcoretest/hash/mod.rs13
-rw-r--r--src/libcoretest/ptr.rs3
-rw-r--r--src/liblog/lib.rs2
-rw-r--r--src/librand/distributions/exponential.rs6
-rw-r--r--src/librustc_trans/back/write.rs7
-rw-r--r--src/librustc_trans/lib.rs1
-rw-r--r--src/librustc_trans/trans/type_.rs38
-rw-r--r--src/librustc_unicode/lib.rs1
-rw-r--r--src/librustc_unicode/normalize.rs16
-rw-r--r--src/librustc_unicode/u_str.rs5
-rw-r--r--src/libstd/ascii.rs5
-rw-r--r--src/libstd/error.rs4
-rw-r--r--src/libstd/ffi/c_str.rs2
-rw-r--r--src/libstd/ffi/os_str.rs10
-rw-r--r--src/libstd/lib.rs2
-rw-r--r--src/libstd/path.rs8
-rw-r--r--src/libstd/rand/reader.rs4
-rw-r--r--src/libstd/sync/mpsc/select.rs5
-rw-r--r--src/libstd/sys/unix/backtrace.rs3
-rw-r--r--src/libsyntax/lib.rs1
34 files changed, 187 insertions, 103 deletions
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index 1e592397014..56c7324090e 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -193,7 +193,7 @@ impl<T> Arc<T> {
             weak: atomic::AtomicUsize::new(1),
             data: data,
         };
-        Arc { _ptr: unsafe { NonZero::new(mem::transmute(x)) } }
+        Arc { _ptr: unsafe { NonZero::new(Box::into_raw(x)) } }
     }
 }
 
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index 4d064b16ad0..54df3b35bdb 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -152,7 +152,7 @@ unsafe fn destroy_chunk(chunk: &Chunk) {
     let fill = chunk.fill.get();
 
     while idx < fill {
-        let tydesc_data: *const usize = mem::transmute(buf.offset(idx as isize));
+        let tydesc_data = buf.offset(idx as isize) as *const usize;
         let (tydesc, is_done) = un_bitpack_tydesc_ptr(*tydesc_data);
         let (size, align) = ((*tydesc).size, (*tydesc).align);
 
@@ -305,7 +305,7 @@ impl<'longer_than_self> Arena<'longer_than_self> {
             let ptr = ptr as *mut T;
             // Write in our tydesc along with a bit indicating that it
             // has *not* been initialized yet.
-            *ty_ptr = mem::transmute(tydesc);
+            *ty_ptr = bitpack_tydesc_ptr(tydesc, false);
             // Actually initialize it
             ptr::write(&mut(*ptr), op());
             // Now that we are done, update the tydesc to indicate that
@@ -443,8 +443,7 @@ impl<T> TypedArenaChunk<T> {
     fn start(&self) -> *const u8 {
         let this: *const TypedArenaChunk<T> = self;
         unsafe {
-            mem::transmute(round_up(this.offset(1) as usize,
-                                    mem::align_of::<T>()))
+            round_up(this.offset(1) as usize, mem::align_of::<T>()) as *const u8
         }
     }
 
@@ -488,7 +487,7 @@ impl<T> TypedArena<T> {
         }
 
         let ptr: &mut T = unsafe {
-            let ptr: &mut T = mem::transmute(self.ptr.clone());
+            let ptr: &mut T = &mut *(self.ptr.get() as *mut T);
             ptr::write(ptr, object);
             self.ptr.set(self.ptr.get().offset(1));
             ptr
diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs
index 9f2e1db42c9..d36fe669fa3 100644
--- a/src/libcollections/btree/node.rs
+++ b/src/libcollections/btree/node.rs
@@ -25,7 +25,7 @@ use core::iter::Zip;
 use core::marker::PhantomData;
 use core::ops::{Deref, DerefMut, Index, IndexMut};
 use core::ptr::Unique;
-use core::{slice, mem, ptr, cmp, raw};
+use core::{slice, mem, ptr, cmp};
 use alloc::heap::{self, EMPTY};
 
 use borrow::Borrow;
@@ -357,7 +357,10 @@ impl<K, V> Node<K, V> {
 
     #[inline]
     pub fn as_slices_mut<'a>(&'a mut self) -> (&'a mut [K], &'a mut [V]) {
-        unsafe { mem::transmute(self.as_slices()) }
+        unsafe {(
+            slice::from_raw_parts_mut(*self.keys, self.len()),
+            slice::from_raw_parts_mut(*self.vals, self.len()),
+        )}
     }
 
     #[inline]
@@ -372,10 +375,7 @@ impl<K, V> Node<K, V> {
                     None => heap::EMPTY as *const Node<K,V>,
                     Some(ref p) => **p as *const Node<K,V>,
                 };
-                mem::transmute(raw::Slice {
-                    data: data,
-                    len: self.len() + 1
-                })
+                slice::from_raw_parts(data, self.len() + 1)
             }
         };
         NodeSlice {
@@ -390,6 +390,7 @@ impl<K, V> Node<K, V> {
 
     #[inline]
     pub fn as_slices_internal_mut<'b>(&'b mut self) -> MutNodeSlice<'b, K, V> {
+        // TODO: Bad: This relies on structure layout!
         unsafe { mem::transmute(self.as_slices_internal()) }
     }
 
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index 5fb28d67974..3be5f32d6c2 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -47,7 +47,6 @@
 #![feature(oom)]
 #![feature(pattern)]
 #![feature(ptr_as_ref)]
-#![feature(raw)]
 #![feature(slice_patterns)]
 #![feature(staged_api)]
 #![feature(step_by)]
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index 5ccf3973c28..b681f7a6341 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -109,6 +109,7 @@ pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split};
 pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
 pub use core::slice::{bytes, mut_ref_slice, ref_slice};
 pub use core::slice::{from_raw_parts, from_raw_parts_mut};
+pub use core::slice::{transmute, transmute_mut};
 
 ////////////////////////////////////////////////////////////////////////////////
 // Basic slice extension methods
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index 670d99bae40..d359d7548f3 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -479,6 +479,19 @@ impl str {
         core_str::StrExt::as_bytes(self)
     }
 
+    /// Converts `self` to a mutable byte slice.
+    ///
+    /// # Unsafety
+    ///
+    /// The `str` type guarantees that its contents are UTF-8 bytes, which can
+    /// be violated using this function, leading to memory-unsafeties in other
+    /// string functions.
+    #[unstable(feature = "str_as_bytes_mut")]
+    #[inline(always)]
+    pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
+        core_str::StrExt::as_bytes_mut(self)
+    }
+
     /// Returns a raw pointer to the `&str`'s buffer.
     ///
     /// The caller must ensure that the string outlives this pointer, and
@@ -504,8 +517,7 @@ impl str {
     /// # Unsafety
     ///
     /// Caller must check both UTF-8 sequence boundaries and the boundaries
-    /// of the entire slice as
-    /// well.
+    /// of the entire slice as well.
     ///
     /// # Examples
     ///
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index b323ab03ec6..2bd5b315c4c 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -977,7 +977,7 @@ impl ops::Index<ops::RangeFull> for String {
 
     #[inline]
     fn index(&self, _index: ops::RangeFull) -> &str {
-        unsafe { mem::transmute(&*self.vec) }
+        unsafe { str::from_utf8_unchecked(&self.vec) }
     }
 }
 
@@ -1016,7 +1016,7 @@ impl ops::Deref for String {
 
     #[inline]
     fn deref(&self) -> &str {
-        unsafe { mem::transmute(&self.vec[..]) }
+        unsafe { str::from_utf8_unchecked(&self.vec) }
     }
 }
 
@@ -1024,7 +1024,7 @@ impl ops::Deref for String {
 impl ops::DerefMut for String {
     #[inline]
     fn deref_mut(&mut self) -> &mut str {
-        unsafe { mem::transmute(&mut self.vec[..]) }
+        unsafe { mem::transmute(&mut *self.vec) }
     }
 }
 
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 9a29f6f9b82..83786648ea0 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -1714,7 +1714,7 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
                 } else {
                     self.end = self.end.offset(-1);
 
-                    Some(ptr::read(mem::transmute(self.end)))
+                    Some(ptr::read(self.end))
                 }
             }
         }
diff --git a/src/libcore/any.rs b/src/libcore/any.rs
index e7b39c11f4c..ed912d59ce6 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -146,7 +146,7 @@ impl Any {
                 let to: TraitObject = transmute(self);
 
                 // Extract the data pointer
-                Some(transmute(to.data))
+                Some(&*(to.data as *const T))
             }
         } else {
             None
@@ -164,7 +164,7 @@ impl Any {
                 let to: TraitObject = transmute(self);
 
                 // Extract the data pointer
-                Some(transmute(to.data))
+                Some(&mut *(to.data as *const T as *mut T))
             }
         } else {
             None
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 9d151abea78..da4bb41fd9c 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -19,6 +19,7 @@
 
 use self::Ordering::*;
 
+use mem;
 use marker::Sized;
 use option::Option::{self, Some, None};
 
@@ -114,6 +115,10 @@ pub enum Ordering {
 }
 
 impl Ordering {
+    unsafe fn from_i8_unchecked(v: i8) -> Ordering {
+        mem::transmute(v)
+    }
+
     /// Reverse the `Ordering`.
     ///
     /// * `Less` becomes `Greater`.
@@ -155,7 +160,7 @@ impl Ordering {
             //
             // NB. it is safe because of the explicit discriminants
             // given above.
-            ::mem::transmute::<_, Ordering>(-(self as i8))
+            Ordering::from_i8_unchecked(-(self as i8))
         }
     }
 }
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 668e2ecf1c6..ea2a9d1cfaf 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -90,7 +90,7 @@ pub trait Write {
     fn write_char(&mut self, c: char) -> Result {
         let mut utf_8 = [0u8; 4];
         let bytes_written = c.encode_utf8(&mut utf_8).unwrap_or(0);
-        self.write_str(unsafe { mem::transmute(&utf_8[..bytes_written]) })
+        self.write_str(unsafe { str::from_utf8_unchecked(&utf_8[..bytes_written]) })
     }
 
     /// Glue for usage of the `write!` macro with implementers of this trait.
@@ -1320,7 +1320,7 @@ impl Display for char {
         } else {
             let mut utf8 = [0; 4];
             let amt = self.encode_utf8(&mut utf8).unwrap_or(0);
-            let s: &str = unsafe { mem::transmute(&utf8[..amt]) };
+            let s: &str = unsafe { str::from_utf8_unchecked(&utf8[..amt]) };
             f.pad(s)
         }
     }
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 116c1dfaa3e..64727242b9c 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -16,13 +16,13 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use mem;
 use clone::Clone;
 use intrinsics;
 use ops::Deref;
 use fmt;
 use option::Option::{self, Some, None};
 use marker::{PhantomData, Send, Sized, Sync};
+use mem;
 use nonzero::NonZero;
 
 use cmp::{PartialEq, Eq, Ord, PartialOrd};
@@ -100,7 +100,7 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
-    mem::swap(mem::transmute(dest), &mut src); // cannot overlap
+    mem::swap(&mut *dest, &mut src); // cannot overlap
     src
 }
 
@@ -327,15 +327,14 @@ impl<T: ?Sized> Clone for *mut T {
 
 // Equality for extern "C" fn pointers
 mod externfnpointers {
-    use mem;
     use cmp::PartialEq;
 
     #[stable(feature = "rust1", since = "1.0.0")]
     impl<_R> PartialEq for extern "C" fn() -> _R {
         #[inline]
         fn eq(&self, other: &extern "C" fn() -> _R) -> bool {
-            let self_: *const () = unsafe { mem::transmute(*self) };
-            let other_: *const () = unsafe { mem::transmute(*other) };
+            let self_ = *self as usize;
+            let other_ = *other as usize;
             self_ == other_
         }
     }
@@ -345,9 +344,9 @@ mod externfnpointers {
             impl<_R,$($p),*> PartialEq for extern "C" fn($($p),*) -> _R {
                 #[inline]
                 fn eq(&self, other: &extern "C" fn($($p),*) -> _R) -> bool {
-                    let self_: *const () = unsafe { mem::transmute(*self) };
+                    let self_ = *self as usize;
 
-                    let other_: *const () = unsafe { mem::transmute(*other) };
+                    let other_ = *other as usize;
                     self_ == other_
                 }
             }
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index f765cdc54d8..9120da78d25 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -33,7 +33,6 @@
 // * The `raw` and `bytes` submodules.
 // * Boilerplate trait implementations.
 
-use mem::transmute;
 use clone::Clone;
 use cmp::{Ordering, PartialEq, PartialOrd, Eq, Ord};
 use cmp::Ordering::{Less, Equal, Greater};
@@ -148,7 +147,7 @@ macro_rules! slice_ref {
             // Use a non-null pointer value
             &mut *(1 as *mut _)
         } else {
-            transmute(ptr)
+            mem::transmute(ptr)
         }
     }};
 }
@@ -261,7 +260,7 @@ impl<T> SliceExt for [T] {
 
     #[inline]
     unsafe fn get_unchecked(&self, index: usize) -> &T {
-        transmute(self.repr().data.offset(index as isize))
+        &*(self.repr().data.offset(index as isize))
     }
 
     #[inline]
@@ -430,7 +429,7 @@ impl<T> SliceExt for [T] {
 
     #[inline]
     unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
-        transmute((self.repr().data as *mut T).offset(index as isize))
+        &mut *(self.repr().data as *mut T).offset(index as isize)
     }
 
     #[inline]
@@ -547,8 +546,7 @@ impl<T> ops::Index<usize> for [T] {
 
     fn index(&self, index: usize) -> &T {
         assert!(index < self.len());
-
-        unsafe { mem::transmute(self.repr().data.offset(index as isize)) }
+        unsafe { self.get_unchecked(index) }
     }
 }
 
@@ -557,8 +555,7 @@ impl<T> ops::IndexMut<usize> for [T] {
     #[inline]
     fn index_mut(&mut self, index: usize) -> &mut T {
         assert!(index < self.len());
-
-        unsafe { mem::transmute(self.repr().data.offset(index as isize)) }
+        unsafe { self.get_unchecked_mut(index) }
     }
 }
 
@@ -1427,7 +1424,7 @@ pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: usize) -> &'a [T] {
-    transmute(RawSlice { data: p, len: len })
+    mem::transmute(RawSlice { data: p, len: len })
 }
 
 /// Performs the same functionality as `from_raw_parts`, except that a mutable
@@ -1439,7 +1436,40 @@ pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: usize) -> &'a [T] {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] {
-    transmute(RawSlice { data: p, len: len })
+    mem::transmute(RawSlice { data: p, len: len })
+}
+
+#[inline]
+fn check_types<T,U>() {
+    assert!(mem::size_of::<T>() == mem::size_of::<U>());
+    assert!(mem::align_of::<T>() % mem::align_of::<U>() == 0)
+}
+
+/// Reinterprets a slice of one type as a slice of another type.
+///
+/// Both types have to have the same size and the type that is converted to
+/// must have equal or less restrictive alignment.
+///
+/// # Panics
+///
+/// This functions panics if the above preconditions about the types are not
+/// met.
+#[inline]
+#[unstable(feature = "slice_transmute", reason = "recent API addition")]
+pub unsafe fn transmute<T,U>(slice: &[T]) -> &[U] {
+    check_types::<T,U>();
+    from_raw_parts(slice.as_ptr() as *const U, slice.len())
+}
+
+/// Reinterprets a mutable slice of one type as a mutable slice of another
+/// type.
+///
+/// Equivalent of `slice::transmute` for mutable slices.
+#[inline]
+#[unstable(feature = "slice_transmute", reason = "recent API addition")]
+pub unsafe fn transmute_mut<T,U>(slice: &mut [T]) -> &mut [U] {
+    check_types::<T,U>();
+    from_raw_parts_mut(slice.as_mut_ptr() as *mut U, slice.len())
 }
 
 //
@@ -1580,9 +1610,9 @@ macro_rules! impl_int_slice {
             #[inline]
             fn as_signed(&self) -> &[$s] { unsafe { transmute(self) } }
             #[inline]
-            fn as_unsigned_mut(&mut self) -> &mut [$u] { unsafe { transmute(self) } }
+            fn as_unsigned_mut(&mut self) -> &mut [$u] { unsafe { transmute_mut(self) } }
             #[inline]
-            fn as_signed_mut(&mut self) -> &mut [$s] { unsafe { transmute(self) } }
+            fn as_signed_mut(&mut self) -> &mut [$s] { unsafe { transmute_mut(self) } }
         }
     }
 }
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 4f0b881c5cd..202fc90b40d 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -17,7 +17,7 @@
 use self::pattern::Pattern;
 use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
 
-use char::CharExt;
+use char::{self, CharExt};
 use clone::Clone;
 use cmp::Eq;
 use convert::AsRef;
@@ -123,13 +123,13 @@ impl Utf8Error {
 /// Converts a slice of bytes to a string slice without performing any
 /// allocations.
 ///
-/// Once the slice has been validated as utf-8, it is transmuted in-place and
+/// Once the slice has been validated as UTF-8, it is transmuted in-place and
 /// returned as a '&str' instead of a '&[u8]'
 ///
 /// # Failure
 ///
-/// Returns `Err` if the slice is not utf-8 with a description as to why the
-/// provided slice is not utf-8.
+/// Returns `Err` if the slice is not UTF-8 with a description as to why the
+/// provided slice is not UTF-8.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
     try!(run_utf8_validation_iterator(&mut v.iter()));
@@ -262,7 +262,7 @@ impl<'a> Iterator for Chars<'a> {
         next_code_point(&mut self.iter).map(|ch| {
             // str invariant says `ch` is a valid Unicode Scalar Value
             unsafe {
-                mem::transmute(ch)
+                char::from_u32_unchecked(ch)
             }
         })
     }
@@ -284,7 +284,7 @@ impl<'a> DoubleEndedIterator for Chars<'a> {
         next_code_point_reverse(&mut self.iter).map(|ch| {
             // str invariant says `ch` is a valid Unicode Scalar Value
             unsafe {
-                mem::transmute(ch)
+                char::from_u32_unchecked(ch)
             }
         })
     }
@@ -1264,6 +1264,7 @@ pub trait StrExt {
     fn char_at(&self, i: usize) -> char;
     fn char_at_reverse(&self, i: usize) -> char;
     fn as_bytes<'a>(&'a self) -> &'a [u8];
+    unsafe fn as_bytes_mut<'a>(&'a mut self) -> &'a mut [u8];
     fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>;
     fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
         where P::Searcher: ReverseSearcher<'a>;
@@ -1507,7 +1508,7 @@ impl StrExt for str {
     #[inline]
     fn char_range_at(&self, i: usize) -> CharRange {
         let (c, n) = char_range_at_raw(self.as_bytes(), i);
-        CharRange { ch: unsafe { mem::transmute(c) }, next: n }
+        CharRange { ch: unsafe { char::from_u32_unchecked(c) }, next: n }
     }
 
     #[inline]
@@ -1535,7 +1536,7 @@ impl StrExt for str {
             if w > 2 { val = utf8_acc_cont_byte(val, s.as_bytes()[i + 2]); }
             if w > 3 { val = utf8_acc_cont_byte(val, s.as_bytes()[i + 3]); }
 
-            return CharRange {ch: unsafe { mem::transmute(val) }, next: i};
+            return CharRange {ch: unsafe { char::from_u32_unchecked(val) }, next: i};
         }
 
         return multibyte_char_range_at_reverse(self, prev);
@@ -1556,6 +1557,11 @@ impl StrExt for str {
         unsafe { mem::transmute(self) }
     }
 
+    #[inline]
+    unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
+        mem::transmute(self)
+    }
+
     fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
         pat.into_searcher(self).next_match().map(|(i, _)| i)
     }
diff --git a/src/libcoretest/hash/mod.rs b/src/libcoretest/hash/mod.rs
index 697c3ee254b..595bce68201 100644
--- a/src/libcoretest/hash/mod.rs
+++ b/src/libcoretest/hash/mod.rs
@@ -10,7 +10,6 @@
 
 mod sip;
 
-use std::mem;
 use std::hash::{Hash, Hasher};
 use std::default::Default;
 
@@ -72,15 +71,11 @@ fn test_writer_hasher() {
 
     // FIXME (#18248) Add tests for hashing Rc<str> and Rc<[T]>
 
-    unsafe {
-        let ptr: *const i32 = mem::transmute(5_usize);
-        assert_eq!(hash(&ptr), 5);
-    }
+    let ptr = 5_usize as *const i32;
+    assert_eq!(hash(&ptr), 5);
 
-    unsafe {
-        let ptr: *mut i32 = mem::transmute(5_usize);
-        assert_eq!(hash(&ptr), 5);
-    }
+    let ptr = 5_usize as *mut i32;
+    assert_eq!(hash(&ptr), 5);
 }
 
 struct Custom { hash: u64 }
diff --git a/src/libcoretest/ptr.rs b/src/libcoretest/ptr.rs
index 865b049aae5..343db93d4a9 100644
--- a/src/libcoretest/ptr.rs
+++ b/src/libcoretest/ptr.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use core::ptr::*;
-use core::mem;
 
 #[test]
 fn test() {
@@ -20,7 +19,7 @@ fn test() {
         };
         let mut p = Pair {fst: 10, snd: 20};
         let pptr: *mut Pair = &mut p;
-        let iptr: *mut isize = mem::transmute(pptr);
+        let iptr: *mut isize = pptr as *mut isize;
         assert_eq!(*iptr, 10);
         *iptr = 30;
         assert_eq!(*iptr, 30);
diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs
index 7bafd9382f0..bec4f24a565 100644
--- a/src/liblog/lib.rs
+++ b/src/liblog/lib.rs
@@ -294,7 +294,7 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
             1 => panic!("cannot log after main thread has exited"),
             n => {
                 let filter = mem::transmute::<_, &String>(n);
-                if !args.to_string().contains(&filter[..]) {
+                if !args.to_string().contains(filter) {
                     return
                 }
             }
diff --git a/src/librand/distributions/exponential.rs b/src/librand/distributions/exponential.rs
index f46d35a33db..c3a02ec5aab 100644
--- a/src/librand/distributions/exponential.rs
+++ b/src/librand/distributions/exponential.rs
@@ -17,9 +17,9 @@ use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample};
 
 /// A wrapper around an `f64` to generate Exp(1) random numbers.
 ///
-/// See `Exp` for the general exponential distribution.Note that this
- // has to be unwrapped before use as an `f64` (using either
-/// `*` or `mem::transmute` is safe).
+/// See `Exp` for the general exponential distribution. Note that this has to
+/// be unwrapped before use as an `f64` (using either `*` or `mem::transmute`
+/// is safe).
 ///
 /// Implemented via the ZIGNOR variant[1] of the Ziggurat method. The
 /// exact description in the paper was adjusted to use tables for the
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index b901e31a53a..d1fb0c2e8d7 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -25,7 +25,6 @@ use syntax::diagnostic::{Emitter, Handler, Level};
 
 use std::ffi::{CStr, CString};
 use std::fs;
-use std::mem;
 use std::path::Path;
 use std::ptr;
 use std::str;
@@ -375,8 +374,7 @@ unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext<'a>,
 unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef,
                                         user: *const c_void,
                                         cookie: c_uint) {
-    let HandlerFreeVars { cgcx, .. }
-        = *mem::transmute::<_, *const HandlerFreeVars>(user);
+    let HandlerFreeVars { cgcx, .. } = *(user as *const HandlerFreeVars);
 
     let msg = llvm::build_string(|s| llvm::LLVMWriteSMDiagnosticToString(diag, s))
         .expect("non-UTF8 SMDiagnostic");
@@ -385,8 +383,7 @@ unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef,
 }
 
 unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
-    let HandlerFreeVars { llcx, cgcx }
-        = *mem::transmute::<_, *const HandlerFreeVars>(user);
+    let HandlerFreeVars { llcx, cgcx } = *(user as *const HandlerFreeVars);
 
     match llvm::diagnostic::Diagnostic::unpack(info) {
         llvm::diagnostic::InlineAsm(inline) => {
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index af894b218ef..24f4713cad2 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -25,6 +25,7 @@
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/")]
 
+#![cfg_attr(not(stage0), feature(slice_transmute))]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(const_fn)]
diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs
index 699115a0709..530b1a8ebc0 100644
--- a/src/librustc_trans/trans/type_.rs
+++ b/src/librustc_trans/trans/type_.rs
@@ -20,8 +20,11 @@ use util::nodemap::FnvHashMap;
 use syntax::ast;
 
 use std::ffi::CString;
+#[cfg(stage0)]
 use std::mem;
 use std::ptr;
+#[cfg(not(stage0))]
+use std::slice;
 use std::cell::RefCell;
 
 use libc::c_uint;
@@ -148,18 +151,35 @@ impl Type {
         }
     }
 
+    #[cfg(stage0)]
     pub fn func(args: &[Type], ret: &Type) -> Type {
         let vec : &[TypeRef] = unsafe { mem::transmute(args) };
         ty!(llvm::LLVMFunctionType(ret.to_ref(), vec.as_ptr(),
                                    args.len() as c_uint, False))
     }
 
+    #[cfg(not(stage0))]
+    pub fn func(args: &[Type], ret: &Type) -> Type {
+        let vec: &[TypeRef] = unsafe { slice::transmute(args) };
+        ty!(llvm::LLVMFunctionType(ret.to_ref(), vec.as_ptr(),
+                                   args.len() as c_uint, False))
+    }
+
+    #[cfg(stage0)]
     pub fn variadic_func(args: &[Type], ret: &Type) -> Type {
         let vec : &[TypeRef] = unsafe { mem::transmute(args) };
         ty!(llvm::LLVMFunctionType(ret.to_ref(), vec.as_ptr(),
                                    args.len() as c_uint, True))
     }
 
+    #[cfg(not(stage0))]
+    pub fn variadic_func(args: &[Type], ret: &Type) -> Type {
+        let vec: &[TypeRef] = unsafe { slice::transmute(args) };
+        ty!(llvm::LLVMFunctionType(ret.to_ref(), vec.as_ptr(),
+                                   args.len() as c_uint, True))
+    }
+
+    #[cfg(stage0)]
     pub fn struct_(ccx: &CrateContext, els: &[Type], packed: bool) -> Type {
         let els : &[TypeRef] = unsafe { mem::transmute(els) };
         ty!(llvm::LLVMStructTypeInContext(ccx.llcx(), els.as_ptr(),
@@ -167,6 +187,14 @@ impl Type {
                                           packed as Bool))
     }
 
+    #[cfg(not(stage0))]
+    pub fn struct_(ccx: &CrateContext, els: &[Type], packed: bool) -> Type {
+        let els : &[TypeRef] = unsafe { slice::transmute(els) };
+        ty!(llvm::LLVMStructTypeInContext(ccx.llcx(), els.as_ptr(),
+                                          els.len() as c_uint,
+                                          packed as Bool))
+    }
+
     pub fn named_struct(ccx: &CrateContext, name: &str) -> Type {
         let name = CString::new(name).unwrap();
         ty!(llvm::LLVMStructCreateNamed(ccx.llcx(), name.as_ptr()))
@@ -208,6 +236,7 @@ impl Type {
         }
     }
 
+    #[cfg(stage0)]
     pub fn set_struct_body(&mut self, els: &[Type], packed: bool) {
         unsafe {
             let vec : &[TypeRef] = mem::transmute(els);
@@ -216,6 +245,15 @@ impl Type {
         }
     }
 
+    #[cfg(not(stage0))]
+    pub fn set_struct_body(&mut self, els: &[Type], packed: bool) {
+        unsafe {
+            let vec: &[TypeRef] = slice::transmute(els);
+            llvm::LLVMStructSetBody(self.to_ref(), vec.as_ptr(),
+                                    els.len() as c_uint, packed as Bool)
+        }
+    }
+
     pub fn ptr_to(&self) -> Type {
         ty!(llvm::LLVMPointerType(self.to_ref(), 0))
     }
diff --git a/src/librustc_unicode/lib.rs b/src/librustc_unicode/lib.rs
index 3a69430d078..6cd8b72cb5c 100644
--- a/src/librustc_unicode/lib.rs
+++ b/src/librustc_unicode/lib.rs
@@ -33,6 +33,7 @@
        test(no_crate_inject))]
 #![no_std]
 
+#![feature(char_from_unchecked)]
 #![feature(core_char_ext)]
 #![feature(core_slice_ext)]
 #![feature(core_str_ext)]
diff --git a/src/librustc_unicode/normalize.rs b/src/librustc_unicode/normalize.rs
index 0c2ad36c637..d5219ab28fe 100644
--- a/src/librustc_unicode/normalize.rs
+++ b/src/librustc_unicode/normalize.rs
@@ -126,20 +126,18 @@ const S_COUNT: u32 = (L_COUNT * N_COUNT);
 // Decompose a precomposed Hangul syllable
 #[inline(always)]
 fn decompose_hangul<F>(s: char, f: &mut F) where F: FnMut(char) {
-    use core::mem::transmute;
-
+    use core::char::from_u32_unchecked;
     let si = s as u32 - S_BASE;
-
     let li = si / N_COUNT;
     unsafe {
-        (*f)(transmute(L_BASE + li));
+        (*f)(from_u32_unchecked(L_BASE + li));
 
         let vi = (si % N_COUNT) / T_COUNT;
-        (*f)(transmute(V_BASE + vi));
+        (*f)(from_u32_unchecked(V_BASE + vi));
 
         let ti = si % T_COUNT;
         if ti > 0 {
-            (*f)(transmute(T_BASE + ti));
+            (*f)(from_u32_unchecked(T_BASE + ti));
         }
     }
 }
@@ -147,18 +145,18 @@ fn decompose_hangul<F>(s: char, f: &mut F) where F: FnMut(char) {
 // Compose a pair of Hangul Jamo
 #[inline(always)]
 fn compose_hangul(a: char, b: char) -> Option<char> {
-    use core::mem::transmute;
+    use core::char::from_u32_unchecked;
     let l = a as u32;
     let v = b as u32;
     // Compose an LPart and a VPart
     if L_BASE <= l && l < (L_BASE + L_COUNT) && V_BASE <= v && v < (V_BASE + V_COUNT) {
         let r = S_BASE + (l - L_BASE) * N_COUNT + (v - V_BASE) * T_COUNT;
-        return unsafe { Some(transmute(r)) };
+        return unsafe { Some(from_u32_unchecked(r)) };
     }
     // Compose an LVPart and a TPart
     if S_BASE <= l && l <= (S_BASE+S_COUNT-T_COUNT) && T_BASE <= v && v < (T_BASE+T_COUNT) {
         let r = l + (v - T_BASE);
-        return unsafe { Some(transmute(r)) };
+        return unsafe { Some(from_u32_unchecked(r)) };
     }
     None
 }
diff --git a/src/librustc_unicode/u_str.rs b/src/librustc_unicode/u_str.rs
index 95214fe2db3..37443cfa70c 100644
--- a/src/librustc_unicode/u_str.rs
+++ b/src/librustc_unicode/u_str.rs
@@ -20,7 +20,6 @@ use core::prelude::v1::*;
 use core::char;
 use core::cmp;
 use core::iter::Filter;
-use core::mem;
 use core::slice;
 use core::str::Split;
 
@@ -454,7 +453,7 @@ impl<'a> Iterator for Utf16Items<'a> {
 
         if u < 0xD800 || 0xDFFF < u {
             // not a surrogate
-            Some(Utf16Item::ScalarValue(unsafe {mem::transmute(u as u32)}))
+            Some(Utf16Item::ScalarValue(unsafe { char::from_u32_unchecked(u as u32) }))
         } else if u >= 0xDC00 {
             // a trailing surrogate
             Some(Utf16Item::LoneSurrogate(u))
@@ -476,7 +475,7 @@ impl<'a> Iterator for Utf16Items<'a> {
 
             // all ok, so lets decode it.
             let c = (((u - 0xD800) as u32) << 10 | (u2 - 0xDC00) as u32) + 0x1_0000;
-            Some(Utf16Item::ScalarValue(unsafe {mem::transmute(c)}))
+            Some(Utf16Item::ScalarValue(unsafe { char::from_u32_unchecked(c) }))
         }
     }
 
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index cd9dadd1be9..f003948be7b 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -15,7 +15,6 @@
 use prelude::v1::*;
 
 use ops::Range;
-use mem;
 
 /// Extension methods for ASCII-subset only operations on owned strings
 #[unstable(feature = "owned_ascii_ext",
@@ -186,12 +185,12 @@ impl AsciiExt for str {
     }
 
     fn make_ascii_uppercase(&mut self) {
-        let me: &mut [u8] = unsafe { mem::transmute(self) };
+        let me: &mut [u8] = unsafe { self.as_bytes_mut() };
         me.make_ascii_uppercase()
     }
 
     fn make_ascii_lowercase(&mut self) {
-        let me: &mut [u8] = unsafe { mem::transmute(self) };
+        let me: &mut [u8] = unsafe { self.as_bytes_mut() };
         me.make_ascii_lowercase()
     }
 }
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 4d08f08bb6e..f0f481d3721 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -192,7 +192,7 @@ impl Error + 'static {
                 let to: TraitObject = transmute(self);
 
                 // Extract the data pointer
-                Some(transmute(to.data))
+                Some(&*(to.data as *const T))
             }
         } else {
             None
@@ -210,7 +210,7 @@ impl Error + 'static {
                 let to: TraitObject = transmute(self);
 
                 // Extract the data pointer
-                Some(transmute(to.data))
+                Some(&mut *(to.data as *const T as *mut T))
             }
         } else {
             None
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 6eb0719d9f6..adbda6ae242 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -395,7 +395,7 @@ impl CStr {
     /// > length calculation whenever this method is called.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn to_bytes_with_nul(&self) -> &[u8] {
-        unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) }
+        unsafe { slice::transmute(&self.inner) }
     }
 
     /// Yields a `&str` slice if the `CStr` contains valid UTF-8.
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index 47b8230e430..83d76481d49 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -134,7 +134,7 @@ impl ops::Index<ops::RangeFull> for OsString {
 
     #[inline]
     fn index(&self, _index: ops::RangeFull) -> &OsStr {
-        unsafe { mem::transmute(self.inner.as_slice()) }
+        OsStr::from_inner(self.inner.as_slice())
     }
 }
 
@@ -226,6 +226,10 @@ impl OsStr {
         s.as_ref()
     }
 
+    fn from_inner(inner: &Slice) -> &OsStr {
+        unsafe { mem::transmute(inner) }
+    }
+
     /// Yields a `&str` slice if the `OsStr` is valid unicode.
     ///
     /// This conversion may entail doing a check for UTF-8 validity.
@@ -387,14 +391,14 @@ impl AsRef<OsStr> for OsString {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<OsStr> for str {
     fn as_ref(&self) -> &OsStr {
-        unsafe { mem::transmute(Slice::from_str(self)) }
+        OsStr::from_inner(Slice::from_str(self))
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<OsStr> for String {
     fn as_ref(&self) -> &OsStr {
-        unsafe { mem::transmute(Slice::from_str(self)) }
+        (&**self).as_ref()
     }
 }
 
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 7baa7558e52..65f195be4e8 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -234,7 +234,9 @@
 #![feature(reflect_marker)]
 #![feature(slice_bytes)]
 #![feature(slice_patterns)]
+#![feature(slice_transmute)]
 #![feature(staged_api)]
+#![feature(str_as_bytes_mut)]
 #![feature(str_char)]
 #![feature(str_internals)]
 #![feature(unboxed_closures)]
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 4a4db61c3b9..c3a887cbcb8 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -942,7 +942,7 @@ pub struct PathBuf {
 
 impl PathBuf {
     fn as_mut_vec(&mut self) -> &mut Vec<u8> {
-        unsafe { mem::transmute(self) }
+        unsafe { &mut *(self as *mut PathBuf as *mut Vec<u8>) }
     }
 
     /// Allocates an empty `PathBuf`.
@@ -1126,7 +1126,7 @@ impl ops::Deref for PathBuf {
     type Target = Path;
 
     fn deref(&self) -> &Path {
-        unsafe { mem::transmute(&self.inner[..]) }
+        Path::new(&self.inner)
     }
 }
 
@@ -1227,11 +1227,11 @@ impl Path {
     // The following (private!) function allows construction of a path from a u8
     // slice, which is only safe when it is known to follow the OsStr encoding.
     unsafe fn from_u8_slice(s: &[u8]) -> &Path {
-        mem::transmute(s)
+        Path::new(u8_slice_as_os_str(s))
     }
     // The following (private!) function reveals the byte encoding used for OsStr.
     fn as_u8_slice(&self) -> &[u8] {
-        unsafe { mem::transmute(self) }
+        os_str_as_u8_slice(&self.inner)
     }
 
     /// Directly wrap a string slice as a `Path` slice.
diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs
index 665f423c3f1..8ac2722f65a 100644
--- a/src/libstd/rand/reader.rs
+++ b/src/libstd/rand/reader.rs
@@ -73,8 +73,8 @@ mod tests {
     fn test_reader_rng_u64() {
         // transmute from the target to avoid endianness concerns.
         let v = &[0, 0, 0, 0, 0, 0, 0, 1,
-                  0  , 0, 0, 0, 0, 0, 0, 2,
-                  0,   0, 0, 0, 0, 0, 0, 3][..];
+                  0, 0, 0, 0, 0, 0, 0, 2,
+                  0, 0, 0, 0, 0, 0, 0, 3][..];
         let mut rng = ReaderRng::new(v);
 
         assert_eq!(rng.next_u64(), 1u64.to_be());
diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs
index 1d31ac165f6..c46e61cf414 100644
--- a/src/libstd/sync/mpsc/select.rs
+++ b/src/libstd/sync/mpsc/select.rs
@@ -62,7 +62,6 @@ use core::prelude::v1::*;
 
 use core::cell::{Cell, UnsafeCell};
 use core::marker;
-use core::mem;
 use core::ptr;
 use core::usize;
 
@@ -281,7 +280,7 @@ impl<'rx, T: Send> Handle<'rx, T> {
     pub unsafe fn add(&mut self) {
         if self.added { return }
         let selector = &mut *self.selector;
-        let me: *mut Handle<'static, ()> = mem::transmute(&*self);
+        let me = self as *mut Handle<'rx, T> as *mut Handle<'static, ()>;
 
         if selector.head.is_null() {
             selector.head = me;
@@ -302,7 +301,7 @@ impl<'rx, T: Send> Handle<'rx, T> {
         if !self.added { return }
 
         let selector = &mut *self.selector;
-        let me: *mut Handle<'static, ()> = mem::transmute(&*self);
+        let me = self as *mut Handle<'rx, T> as *mut Handle<'static, ()>;
 
         if self.prev.is_null() {
             assert_eq!(selector.head, me);
diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs
index ae8bfb07aaf..4128431ee64 100644
--- a/src/libstd/sys/unix/backtrace.rs
+++ b/src/libstd/sys/unix/backtrace.rs
@@ -90,7 +90,6 @@ use io::prelude::*;
 use ffi::CStr;
 use io;
 use libc;
-use mem;
 use str;
 use sync::StaticMutex;
 
@@ -168,7 +167,7 @@ pub fn write(w: &mut Write) -> io::Result<()> {
 
     extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
                        arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code {
-        let cx: &mut Context = unsafe { mem::transmute(arg) };
+        let cx: &mut Context = unsafe { &mut *(arg as *mut Context) };
         let mut ip_before_insn = 0;
         let mut ip = unsafe {
             uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 5424c0b214a..bce8adaf70f 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -27,6 +27,7 @@
 
 #![feature(associated_consts)]
 #![feature(bitset)]
+#![feature(copy_lifetime)]
 #![feature(drain)]
 #![feature(filling_drop)]
 #![feature(libc)]