about summary refs log tree commit diff
path: root/src/libcore
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 /src/libcore
parentfebdc3b201bcce1546c88e3be1b956d3f90d3059 (diff)
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`.
Diffstat (limited to 'src/libcore')
-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
6 files changed, 72 insertions, 32 deletions
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)
     }