Skip to content

Commit 3d69bec

Browse files
committed
Auto merge of #27252 - tbu-:pr_less_transmutes, r=alexcrichton
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`. This builds upon #27233.
2 parents 96a1f40 + 33af24c commit 3d69bec

File tree

30 files changed

+133
-108
lines changed

30 files changed

+133
-108
lines changed

src/liballoc/arc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ impl<T> Arc<T> {
193193
weak: atomic::AtomicUsize::new(1),
194194
data: data,
195195
};
196-
Arc { _ptr: unsafe { NonZero::new(mem::transmute(x)) } }
196+
Arc { _ptr: unsafe { NonZero::new(Box::into_raw(x)) } }
197197
}
198198
}
199199

src/libarena/lib.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ unsafe fn destroy_chunk(chunk: &Chunk) {
152152
let fill = chunk.fill.get();
153153

154154
while idx < fill {
155-
let tydesc_data: *const usize = mem::transmute(buf.offset(idx as isize));
155+
let tydesc_data = buf.offset(idx as isize) as *const usize;
156156
let (tydesc, is_done) = un_bitpack_tydesc_ptr(*tydesc_data);
157157
let (size, align) = ((*tydesc).size, (*tydesc).align);
158158

@@ -305,7 +305,7 @@ impl<'longer_than_self> Arena<'longer_than_self> {
305305
let ptr = ptr as *mut T;
306306
// Write in our tydesc along with a bit indicating that it
307307
// has *not* been initialized yet.
308-
*ty_ptr = mem::transmute(tydesc);
308+
*ty_ptr = bitpack_tydesc_ptr(tydesc, false);
309309
// Actually initialize it
310310
ptr::write(&mut(*ptr), op());
311311
// Now that we are done, update the tydesc to indicate that
@@ -443,8 +443,7 @@ impl<T> TypedArenaChunk<T> {
443443
fn start(&self) -> *const u8 {
444444
let this: *const TypedArenaChunk<T> = self;
445445
unsafe {
446-
mem::transmute(round_up(this.offset(1) as usize,
447-
mem::align_of::<T>()))
446+
round_up(this.offset(1) as usize, mem::align_of::<T>()) as *const u8
448447
}
449448
}
450449

@@ -488,7 +487,7 @@ impl<T> TypedArena<T> {
488487
}
489488

490489
let ptr: &mut T = unsafe {
491-
let ptr: &mut T = mem::transmute(self.ptr.clone());
490+
let ptr: &mut T = &mut *(self.ptr.get() as *mut T);
492491
ptr::write(ptr, object);
493492
self.ptr.set(self.ptr.get().offset(1));
494493
ptr

src/libcollections/btree/node.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use core::iter::Zip;
2525
use core::marker::PhantomData;
2626
use core::ops::{Deref, DerefMut, Index, IndexMut};
2727
use core::ptr::Unique;
28-
use core::{slice, mem, ptr, cmp, raw};
28+
use core::{slice, mem, ptr, cmp};
2929
use alloc::heap::{self, EMPTY};
3030

3131
use borrow::Borrow;
@@ -357,7 +357,10 @@ impl<K, V> Node<K, V> {
357357

358358
#[inline]
359359
pub fn as_slices_mut<'a>(&'a mut self) -> (&'a mut [K], &'a mut [V]) {
360-
unsafe { mem::transmute(self.as_slices()) }
360+
unsafe {(
361+
slice::from_raw_parts_mut(*self.keys, self.len()),
362+
slice::from_raw_parts_mut(*self.vals, self.len()),
363+
)}
361364
}
362365

363366
#[inline]
@@ -372,10 +375,7 @@ impl<K, V> Node<K, V> {
372375
None => heap::EMPTY as *const Node<K,V>,
373376
Some(ref p) => **p as *const Node<K,V>,
374377
};
375-
mem::transmute(raw::Slice {
376-
data: data,
377-
len: self.len() + 1
378-
})
378+
slice::from_raw_parts(data, self.len() + 1)
379379
}
380380
};
381381
NodeSlice {
@@ -390,6 +390,7 @@ impl<K, V> Node<K, V> {
390390

391391
#[inline]
392392
pub fn as_slices_internal_mut<'b>(&'b mut self) -> MutNodeSlice<'b, K, V> {
393+
// FIXME(#27620): Bad: This relies on structure layout!
393394
unsafe { mem::transmute(self.as_slices_internal()) }
394395
}
395396

src/libcollections/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
#![feature(oom)]
4848
#![feature(pattern)]
4949
#![feature(ptr_as_ref)]
50-
#![feature(raw)]
5150
#![feature(slice_patterns)]
5251
#![feature(staged_api)]
5352
#![feature(step_by)]

src/libcollections/str.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -504,8 +504,7 @@ impl str {
504504
/// # Unsafety
505505
///
506506
/// Caller must check both UTF-8 sequence boundaries and the boundaries
507-
/// of the entire slice as
508-
/// well.
507+
/// of the entire slice as well.
509508
///
510509
/// # Examples
511510
///

src/libcollections/string.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@ impl ops::Index<ops::RangeFull> for String {
977977

978978
#[inline]
979979
fn index(&self, _index: ops::RangeFull) -> &str {
980-
unsafe { mem::transmute(&*self.vec) }
980+
unsafe { str::from_utf8_unchecked(&self.vec) }
981981
}
982982
}
983983

@@ -1016,15 +1016,15 @@ impl ops::Deref for String {
10161016

10171017
#[inline]
10181018
fn deref(&self) -> &str {
1019-
unsafe { mem::transmute(&self.vec[..]) }
1019+
unsafe { str::from_utf8_unchecked(&self.vec) }
10201020
}
10211021
}
10221022

10231023
#[stable(feature = "derefmut_for_string", since = "1.2.0")]
10241024
impl ops::DerefMut for String {
10251025
#[inline]
10261026
fn deref_mut(&mut self) -> &mut str {
1027-
unsafe { mem::transmute(&mut self.vec[..]) }
1027+
unsafe { mem::transmute(&mut *self.vec) }
10281028
}
10291029
}
10301030

src/libcollections/vec.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1714,7 +1714,7 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
17141714
} else {
17151715
self.end = self.end.offset(-1);
17161716

1717-
Some(ptr::read(mem::transmute(self.end)))
1717+
Some(ptr::read(self.end))
17181718
}
17191719
}
17201720
}

src/libcore/any.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ impl Any {
146146
let to: TraitObject = transmute(self);
147147

148148
// Extract the data pointer
149-
Some(transmute(to.data))
149+
Some(&*(to.data as *const T))
150150
}
151151
} else {
152152
None
@@ -164,7 +164,7 @@ impl Any {
164164
let to: TraitObject = transmute(self);
165165

166166
// Extract the data pointer
167-
Some(transmute(to.data))
167+
Some(&mut *(to.data as *const T as *mut T))
168168
}
169169
} else {
170170
None

src/libcore/cmp.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
use self::Ordering::*;
2121

22+
use mem;
2223
use marker::Sized;
2324
use option::Option::{self, Some, None};
2425

@@ -114,6 +115,10 @@ pub enum Ordering {
114115
}
115116

116117
impl Ordering {
118+
unsafe fn from_i8_unchecked(v: i8) -> Ordering {
119+
mem::transmute(v)
120+
}
121+
117122
/// Reverse the `Ordering`.
118123
///
119124
/// * `Less` becomes `Greater`.
@@ -155,7 +160,7 @@ impl Ordering {
155160
//
156161
// NB. it is safe because of the explicit discriminants
157162
// given above.
158-
::mem::transmute::<_, Ordering>(-(self as i8))
163+
Ordering::from_i8_unchecked(-(self as i8))
159164
}
160165
}
161166
}

src/libcore/fmt/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub trait Write {
9090
fn write_char(&mut self, c: char) -> Result {
9191
let mut utf_8 = [0u8; 4];
9292
let bytes_written = c.encode_utf8(&mut utf_8).unwrap_or(0);
93-
self.write_str(unsafe { mem::transmute(&utf_8[..bytes_written]) })
93+
self.write_str(unsafe { str::from_utf8_unchecked(&utf_8[..bytes_written]) })
9494
}
9595

9696
/// Glue for usage of the `write!` macro with implementers of this trait.
@@ -1320,7 +1320,7 @@ impl Display for char {
13201320
} else {
13211321
let mut utf8 = [0; 4];
13221322
let amt = self.encode_utf8(&mut utf8).unwrap_or(0);
1323-
let s: &str = unsafe { mem::transmute(&utf8[..amt]) };
1323+
let s: &str = unsafe { str::from_utf8_unchecked(&utf8[..amt]) };
13241324
f.pad(s)
13251325
}
13261326
}

src/libcore/ptr.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
1717
#![stable(feature = "rust1", since = "1.0.0")]
1818

19-
use mem;
2019
use clone::Clone;
2120
use intrinsics;
2221
use ops::Deref;
2322
use fmt;
2423
use option::Option::{self, Some, None};
2524
use marker::{PhantomData, Send, Sized, Sync};
25+
use mem;
2626
use nonzero::NonZero;
2727

2828
use cmp::{PartialEq, Eq, Ord, PartialOrd};
@@ -100,7 +100,7 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
100100
#[inline]
101101
#[stable(feature = "rust1", since = "1.0.0")]
102102
pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
103-
mem::swap(mem::transmute(dest), &mut src); // cannot overlap
103+
mem::swap(&mut *dest, &mut src); // cannot overlap
104104
src
105105
}
106106

@@ -327,15 +327,14 @@ impl<T: ?Sized> Clone for *mut T {
327327

328328
// Equality for extern "C" fn pointers
329329
mod externfnpointers {
330-
use mem;
331330
use cmp::PartialEq;
332331

333332
#[stable(feature = "rust1", since = "1.0.0")]
334333
impl<_R> PartialEq for extern "C" fn() -> _R {
335334
#[inline]
336335
fn eq(&self, other: &extern "C" fn() -> _R) -> bool {
337-
let self_: *const () = unsafe { mem::transmute(*self) };
338-
let other_: *const () = unsafe { mem::transmute(*other) };
336+
let self_ = *self as usize;
337+
let other_ = *other as usize;
339338
self_ == other_
340339
}
341340
}
@@ -345,9 +344,9 @@ mod externfnpointers {
345344
impl<_R,$($p),*> PartialEq for extern "C" fn($($p),*) -> _R {
346345
#[inline]
347346
fn eq(&self, other: &extern "C" fn($($p),*) -> _R) -> bool {
348-
let self_: *const () = unsafe { mem::transmute(*self) };
347+
let self_ = *self as usize;
349348

350-
let other_: *const () = unsafe { mem::transmute(*other) };
349+
let other_ = *other as usize;
351350
self_ == other_
352351
}
353352
}

src/libcore/slice.rs

+40-12
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
// * The `raw` and `bytes` submodules.
3434
// * Boilerplate trait implementations.
3535

36-
use mem::transmute;
3736
use clone::Clone;
3837
use cmp::{Ordering, PartialEq, PartialOrd, Eq, Ord};
3938
use cmp::Ordering::{Less, Equal, Greater};
@@ -148,7 +147,7 @@ macro_rules! slice_ref {
148147
// Use a non-null pointer value
149148
&mut *(1 as *mut _)
150149
} else {
151-
transmute(ptr)
150+
mem::transmute(ptr)
152151
}
153152
}};
154153
}
@@ -261,7 +260,7 @@ impl<T> SliceExt for [T] {
261260

262261
#[inline]
263262
unsafe fn get_unchecked(&self, index: usize) -> &T {
264-
transmute(self.repr().data.offset(index as isize))
263+
&*(self.repr().data.offset(index as isize))
265264
}
266265

267266
#[inline]
@@ -430,7 +429,7 @@ impl<T> SliceExt for [T] {
430429

431430
#[inline]
432431
unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
433-
transmute((self.repr().data as *mut T).offset(index as isize))
432+
&mut *(self.repr().data as *mut T).offset(index as isize)
434433
}
435434

436435
#[inline]
@@ -547,8 +546,7 @@ impl<T> ops::Index<usize> for [T] {
547546

548547
fn index(&self, index: usize) -> &T {
549548
assert!(index < self.len());
550-
551-
unsafe { mem::transmute(self.repr().data.offset(index as isize)) }
549+
unsafe { self.get_unchecked(index) }
552550
}
553551
}
554552

@@ -557,8 +555,7 @@ impl<T> ops::IndexMut<usize> for [T] {
557555
#[inline]
558556
fn index_mut(&mut self, index: usize) -> &mut T {
559557
assert!(index < self.len());
560-
561-
unsafe { mem::transmute(self.repr().data.offset(index as isize)) }
558+
unsafe { self.get_unchecked_mut(index) }
562559
}
563560
}
564561

@@ -1427,7 +1424,7 @@ pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
14271424
#[inline]
14281425
#[stable(feature = "rust1", since = "1.0.0")]
14291426
pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: usize) -> &'a [T] {
1430-
transmute(RawSlice { data: p, len: len })
1427+
mem::transmute(RawSlice { data: p, len: len })
14311428
}
14321429

14331430
/// Performs the same functionality as `from_raw_parts`, except that a mutable
@@ -1439,7 +1436,38 @@ pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: usize) -> &'a [T] {
14391436
#[inline]
14401437
#[stable(feature = "rust1", since = "1.0.0")]
14411438
pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] {
1442-
transmute(RawSlice { data: p, len: len })
1439+
mem::transmute(RawSlice { data: p, len: len })
1440+
}
1441+
1442+
#[inline]
1443+
fn check_types<T,U>() {
1444+
assert!(mem::size_of::<T>() == mem::size_of::<U>());
1445+
assert!(mem::align_of::<T>() % mem::align_of::<U>() == 0)
1446+
}
1447+
1448+
/// Reinterprets a slice of one type as a slice of another type.
1449+
///
1450+
/// Both types have to have the same size and the type that is converted to
1451+
/// must have equal or less restrictive alignment.
1452+
///
1453+
/// # Panics
1454+
///
1455+
/// This functions panics if the above preconditions about the types are not
1456+
/// met.
1457+
#[inline]
1458+
unsafe fn transmute<T,U>(slice: &[T]) -> &[U] {
1459+
check_types::<T,U>();
1460+
from_raw_parts(slice.as_ptr() as *const U, slice.len())
1461+
}
1462+
1463+
/// Reinterprets a mutable slice of one type as a mutable slice of another
1464+
/// type.
1465+
///
1466+
/// Equivalent of `slice::transmute` for mutable slices.
1467+
#[inline]
1468+
unsafe fn transmute_mut<T,U>(slice: &mut [T]) -> &mut [U] {
1469+
check_types::<T,U>();
1470+
from_raw_parts_mut(slice.as_mut_ptr() as *mut U, slice.len())
14431471
}
14441472

14451473
//
@@ -1580,9 +1608,9 @@ macro_rules! impl_int_slice {
15801608
#[inline]
15811609
fn as_signed(&self) -> &[$s] { unsafe { transmute(self) } }
15821610
#[inline]
1583-
fn as_unsigned_mut(&mut self) -> &mut [$u] { unsafe { transmute(self) } }
1611+
fn as_unsigned_mut(&mut self) -> &mut [$u] { unsafe { transmute_mut(self) } }
15841612
#[inline]
1585-
fn as_signed_mut(&mut self) -> &mut [$s] { unsafe { transmute(self) } }
1613+
fn as_signed_mut(&mut self) -> &mut [$s] { unsafe { transmute_mut(self) } }
15861614
}
15871615
}
15881616
}

0 commit comments

Comments
 (0)