Skip to content

Replace many uses of mem::transmute with more specific functions #27252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 10, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/liballoc/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)) } }
}
}

Expand Down
9 changes: 4 additions & 5 deletions src/libarena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
}

Expand Down Expand Up @@ -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
Expand Down
13 changes: 7 additions & 6 deletions src/libcollections/btree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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]
Expand All @@ -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 {
Expand All @@ -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> {
// FIXME(#27620): Bad: This relies on structure layout!
unsafe { mem::transmute(self.as_slices_internal()) }
}

Expand Down
1 change: 0 additions & 1 deletion src/libcollections/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
#![feature(oom)]
#![feature(pattern)]
#![feature(ptr_as_ref)]
#![feature(raw)]
#![feature(slice_patterns)]
#![feature(staged_api)]
#![feature(step_by)]
Expand Down
3 changes: 1 addition & 2 deletions src/libcollections/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,8 +504,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
///
Expand Down
6 changes: 3 additions & 3 deletions src/libcollections/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
}
}

Expand Down Expand Up @@ -1016,15 +1016,15 @@ impl ops::Deref for String {

#[inline]
fn deref(&self) -> &str {
unsafe { mem::transmute(&self.vec[..]) }
unsafe { str::from_utf8_unchecked(&self.vec) }
}
}

#[stable(feature = "derefmut_for_string", since = "1.2.0")]
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) }
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
7 changes: 6 additions & 1 deletion src/libcore/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

use self::Ordering::*;

use mem;
use marker::Sized;
use option::Option::{self, Some, None};

Expand Down Expand Up @@ -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`.
Expand Down Expand Up @@ -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))
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
}
}
Expand Down
13 changes: 6 additions & 7 deletions src/libcore/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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_
}
}
Expand All @@ -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_
}
}
Expand Down
52 changes: 40 additions & 12 deletions src/libcore/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -148,7 +147,7 @@ macro_rules! slice_ref {
// Use a non-null pointer value
&mut *(1 as *mut _)
} else {
transmute(ptr)
mem::transmute(ptr)
}
}};
}
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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) }
}
}

Expand All @@ -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) }
}
}

Expand Down Expand Up @@ -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
Expand All @@ -1439,7 +1436,38 @@ 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]
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]
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())
}

//
Expand Down Expand Up @@ -1580,9 +1608,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) } }
}
}
}
Expand Down
Loading