diff options
| author | Tobias Bucher <tobiasbucher5991@gmail.com> | 2015-07-24 03:04:55 +0200 |
|---|---|---|
| committer | Tobias Bucher <tobiasbucher5991@gmail.com> | 2015-08-09 22:05:22 +0200 |
| commit | 22ec5f4af7b5a85ad375d672ed727571b49f3cad (patch) | |
| tree | eea29f1286398aaaa9d55f23163ddcc49b033eeb /src/libcore | |
| parent | febdc3b201bcce1546c88e3be1b956d3f90d3059 (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.rs | 4 | ||||
| -rw-r--r-- | src/libcore/cmp.rs | 7 | ||||
| -rw-r--r-- | src/libcore/fmt/mod.rs | 4 | ||||
| -rw-r--r-- | src/libcore/ptr.rs | 13 | ||||
| -rw-r--r-- | src/libcore/slice.rs | 54 | ||||
| -rw-r--r-- | src/libcore/str/mod.rs | 22 |
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) } |
