Skip to content

Commit 6c65e34

Browse files
committed
Less as * in library/core
`cast`/`cast_const`/`cast_mut` have been stable and const-stable for a while, so let's use them instead of `as`, for clarity about what the cast is doing and to emphasize `as` casts doing anything else. After all, if it had existed back then, using `.cast::<T>()` instead of `as *mut T` would have helped catch the soundness bug back in <https://blog.rust-lang.org/2017/02/09/Rust-1.15.1.html#whats-in-1151-stable>. I'm working on a lint to enforce this, which is how I found all these cases :) Old zulip conversation about moving things off `as` where feasible: <https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Adding.20methods.20as.20more.20specific.20versions.20of.20.60as.60/near/238374585>.
1 parent f177b7c commit 6c65e34

File tree

17 files changed

+55
-54
lines changed

17 files changed

+55
-54
lines changed

library/core/src/array/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
253253

254254
fn try_from(slice: &[T]) -> Result<&[T; N], TryFromSliceError> {
255255
if slice.len() == N {
256-
let ptr = slice.as_ptr() as *const [T; N];
256+
let ptr = slice.as_ptr().cast::<[T; N]>();
257257
// SAFETY: ok because we just checked that the length fits
258258
unsafe { Ok(&*ptr) }
259259
} else {
@@ -280,7 +280,7 @@ impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
280280

281281
fn try_from(slice: &mut [T]) -> Result<&mut [T; N], TryFromSliceError> {
282282
if slice.len() == N {
283-
let ptr = slice.as_mut_ptr() as *mut [T; N];
283+
let ptr = slice.as_mut_ptr().cast::<[T; N]>();
284284
// SAFETY: ok because we just checked that the length fits
285285
unsafe { Ok(&mut *ptr) }
286286
} else {

library/core/src/cell.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ impl<T, const N: usize> Cell<[T; N]> {
624624
#[unstable(feature = "as_array_of_cells", issue = "88248")]
625625
pub fn as_array_of_cells(&self) -> &[Cell<T>; N] {
626626
// SAFETY: `Cell<T>` has the same memory layout as `T`.
627-
unsafe { &*(self as *const Cell<[T; N]> as *const [Cell<T>; N]) }
627+
unsafe { &*ptr::from_ref(self).cast::<[Cell<T>; N]>() }
628628
}
629629
}
630630

library/core/src/hash/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,7 @@ mod impls {
835835
#[inline]
836836
fn hash_slice<H: ~const Hasher>(data: &[$ty], state: &mut H) {
837837
let newlen = mem::size_of_val(data);
838-
let ptr = data.as_ptr() as *const u8;
838+
let ptr = data.as_ptr().cast::<u8>();
839839
// SAFETY: `ptr` is valid and aligned, as this macro is only used
840840
// for numeric primitives which have no padding. The new slice only
841841
// spans across `data` and is never mutated, and its total size is the

library/core/src/iter/adapters/copied.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ where
223223
unsafe {
224224
ptr::copy_nonoverlapping(
225225
self.as_ref().as_ptr(),
226-
raw_array.as_mut_ptr() as *mut T,
226+
raw_array.as_mut_ptr().cast::<T>(),
227227
len,
228228
);
229229
let _ = self.advance_by(len);
@@ -234,7 +234,7 @@ where
234234
// SAFETY: `len` is larger than the array size. Copy a fixed amount here to fully initialize
235235
// the array.
236236
unsafe {
237-
ptr::copy_nonoverlapping(self.as_ref().as_ptr(), raw_array.as_mut_ptr() as *mut T, N);
237+
ptr::copy_nonoverlapping(self.as_ref().as_ptr(), raw_array.as_mut_ptr().cast::<T>(), N);
238238
let _ = self.advance_by(N);
239239
Ok(MaybeUninit::array_assume_init(raw_array))
240240
}

library/core/src/mem/maybe_uninit.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,8 @@ impl<T> MaybeUninit<T> {
527527
#[inline(always)]
528528
pub const fn as_ptr(&self) -> *const T {
529529
// `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer.
530-
self as *const _ as *const T
530+
// FIXME: consider `ptr::from_ref` once that's const-stable
531+
ptr::addr_of!(*self).cast::<T>()
531532
}
532533

533534
/// Gets a mutable pointer to the contained value. Reading from this pointer or turning it
@@ -566,7 +567,7 @@ impl<T> MaybeUninit<T> {
566567
#[inline(always)]
567568
pub const fn as_mut_ptr(&mut self) -> *mut T {
568569
// `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer.
569-
self as *mut _ as *mut T
570+
ptr::from_mut(self).cast::<T>()
570571
}
571572

572573
/// Extracts the value from the `MaybeUninit<T>` container. This is a great way
@@ -947,7 +948,7 @@ impl<T> MaybeUninit<T> {
947948
// And thus the conversion is safe
948949
let ret = unsafe {
949950
intrinsics::assert_inhabited::<[T; N]>();
950-
(&array as *const _ as *const [T; N]).read()
951+
ptr::from_ref(&array).cast::<[T; N]>().read()
951952
};
952953

953954
// FIXME: required to avoid `~const Destruct` bound
@@ -1002,15 +1003,15 @@ impl<T> MaybeUninit<T> {
10021003
#[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
10031004
#[inline(always)]
10041005
pub const fn slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T {
1005-
this.as_ptr() as *const T
1006+
this.as_ptr().cast::<T>()
10061007
}
10071008

10081009
/// Gets a mutable pointer to the first element of the array.
10091010
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
10101011
#[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
10111012
#[inline(always)]
10121013
pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
1013-
this.as_mut_ptr() as *mut T
1014+
this.as_mut_ptr().cast::<T>()
10141015
}
10151016

10161017
/// Copies the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`.
@@ -1182,7 +1183,7 @@ impl<T> MaybeUninit<T> {
11821183
pub fn as_bytes(&self) -> &[MaybeUninit<u8>] {
11831184
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
11841185
unsafe {
1185-
slice::from_raw_parts(self.as_ptr() as *const MaybeUninit<u8>, mem::size_of::<T>())
1186+
slice::from_raw_parts(self.as_ptr().cast::<MaybeUninit<u8>>(), mem::size_of::<T>())
11861187
}
11871188
}
11881189

@@ -1214,7 +1215,7 @@ impl<T> MaybeUninit<T> {
12141215
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
12151216
unsafe {
12161217
slice::from_raw_parts_mut(
1217-
self.as_mut_ptr() as *mut MaybeUninit<u8>,
1218+
self.as_mut_ptr().cast::<MaybeUninit<u8>>(),
12181219
mem::size_of::<T>(),
12191220
)
12201221
}
@@ -1244,7 +1245,7 @@ impl<T> MaybeUninit<T> {
12441245
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
12451246
unsafe {
12461247
slice::from_raw_parts(
1247-
this.as_ptr() as *const MaybeUninit<u8>,
1248+
this.as_ptr().cast::<MaybeUninit<u8>>(),
12481249
this.len() * mem::size_of::<T>(),
12491250
)
12501251
}
@@ -1277,7 +1278,7 @@ impl<T> MaybeUninit<T> {
12771278
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
12781279
unsafe {
12791280
slice::from_raw_parts_mut(
1280-
this.as_mut_ptr() as *mut MaybeUninit<u8>,
1281+
this.as_mut_ptr().cast::<MaybeUninit<u8>>(),
12811282
this.len() * mem::size_of::<T>(),
12821283
)
12831284
}

library/core/src/mem/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1054,12 +1054,12 @@ pub const unsafe fn transmute_copy<Src, Dst>(src: &Src) -> Dst {
10541054
if align_of::<Dst>() > align_of::<Src>() {
10551055
// SAFETY: `src` is a reference which is guaranteed to be valid for reads.
10561056
// The caller must guarantee that the actual transmutation is safe.
1057-
unsafe { ptr::read_unaligned(src as *const Src as *const Dst) }
1057+
unsafe { ptr::from_ref(src).cast::<Dst>().read_unaligned() }
10581058
} else {
10591059
// SAFETY: `src` is a reference which is guaranteed to be valid for reads.
10601060
// We just checked that `src as *const Dst` was properly aligned.
10611061
// The caller must guarantee that the actual transmutation is safe.
1062-
unsafe { ptr::read(src as *const Src as *const Dst) }
1062+
unsafe { ptr::from_ref(src).cast::<Dst>().read() }
10631063
}
10641064
}
10651065

library/core/src/ptr/const_ptr.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl<T: ?Sized> *const T {
4848
}
4949

5050
// SAFETY: The two versions are equivalent at runtime.
51-
unsafe { const_eval_select((self as *const u8,), const_impl, runtime_impl) }
51+
unsafe { const_eval_select((self.cast::<u8>(),), const_impl, runtime_impl) }
5252
}
5353

5454
/// Casts to a pointer of another type.
@@ -95,7 +95,7 @@ impl<T: ?Sized> *const T {
9595
where
9696
U: ?Sized,
9797
{
98-
from_raw_parts::<U>(self as *const (), metadata(meta))
98+
from_raw_parts::<U>(self.cast::<()>(), metadata(meta))
9999
}
100100

101101
/// Changes constness without changing the type.
@@ -400,7 +400,7 @@ impl<T: ?Sized> *const T {
400400
{
401401
// SAFETY: the caller must guarantee that `self` meets all the
402402
// requirements for a reference.
403-
if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
403+
if self.is_null() { None } else { Some(unsafe { &*self.cast::<MaybeUninit<T>>() }) }
404404
}
405405

406406
/// Calculates the offset from a pointer.
@@ -822,7 +822,7 @@ impl<T: ?Sized> *const T {
822822
where
823823
T: Sized,
824824
{
825-
match intrinsics::ptr_guaranteed_cmp(self as _, other as _) {
825+
match intrinsics::ptr_guaranteed_cmp(self, other) {
826826
2 => None,
827827
other => Some(other == 1),
828828
}

library/core/src/ptr/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1278,7 +1278,7 @@ pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
12781278
// Also, since we just wrote a valid value into `tmp`, it is guaranteed
12791279
// to be properly initialized.
12801280
unsafe {
1281-
copy_nonoverlapping(src as *const u8, tmp.as_mut_ptr() as *mut u8, mem::size_of::<T>());
1281+
copy_nonoverlapping(src.cast::<u8>(), tmp.as_mut_ptr().cast::<u8>(), mem::size_of::<T>());
12821282
tmp.assume_init()
12831283
}
12841284
}
@@ -1473,7 +1473,7 @@ pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
14731473
// `dst` cannot overlap `src` because the caller has mutable access
14741474
// to `dst` while `src` is owned by this function.
14751475
unsafe {
1476-
copy_nonoverlapping(&src as *const T as *const u8, dst as *mut u8, mem::size_of::<T>());
1476+
copy_nonoverlapping(addr_of!(src).cast::<u8>(), dst.cast::<u8>(), mem::size_of::<T>());
14771477
// We are calling the intrinsic directly to avoid function calls in the generated code.
14781478
intrinsics::forget(src);
14791479
}

library/core/src/ptr/mut_ptr.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ impl<T: ?Sized> *mut T {
412412
{
413413
// SAFETY: the caller must guarantee that `self` meets all the
414414
// requirements for a reference.
415-
if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
415+
unsafe { self.cast_const().as_uninit_ref() }
416416
}
417417

418418
/// Calculates the offset from a pointer.
@@ -476,7 +476,7 @@ impl<T: ?Sized> *mut T {
476476
// SAFETY: the caller must uphold the safety contract for `offset`.
477477
// The obtained pointer is valid for writes since the caller must
478478
// guarantee that it points to the same allocated object as `self`.
479-
unsafe { intrinsics::offset(self, count) as *mut T }
479+
unsafe { intrinsics::offset(self, count).cast_mut() }
480480
}
481481

482482
/// Calculates the offset from a pointer in bytes.
@@ -555,7 +555,7 @@ impl<T: ?Sized> *mut T {
555555
T: Sized,
556556
{
557557
// SAFETY: the `arith_offset` intrinsic has no prerequisites to be called.
558-
unsafe { intrinsics::arith_offset(self, count) as *mut T }
558+
unsafe { intrinsics::arith_offset(self, count).cast_mut() }
559559
}
560560

561561
/// Calculates the offset from a pointer in bytes using wrapping arithmetic.
@@ -717,7 +717,7 @@ impl<T: ?Sized> *mut T {
717717
{
718718
// SAFETY: the caller must guarantee that `self` meets all the
719719
// requirements for a reference.
720-
if self.is_null() { None } else { Some(unsafe { &mut *(self as *mut MaybeUninit<T>) }) }
720+
if self.is_null() { None } else { Some(unsafe { &mut *self.cast::<MaybeUninit<T>>() }) }
721721
}
722722

723723
/// Returns whether two pointers are guaranteed to be equal.
@@ -744,7 +744,7 @@ impl<T: ?Sized> *mut T {
744744
where
745745
T: Sized,
746746
{
747-
(self as *const T).guaranteed_eq(other as _)
747+
self.cast_const().guaranteed_eq(other.cast_const())
748748
}
749749

750750
/// Returns whether two pointers are guaranteed to be inequal.
@@ -771,7 +771,7 @@ impl<T: ?Sized> *mut T {
771771
where
772772
T: Sized,
773773
{
774-
(self as *const T).guaranteed_ne(other as _)
774+
self.cast_const().guaranteed_ne(other.cast_const())
775775
}
776776

777777
/// Calculates the distance between two pointers. The returned value is in
@@ -864,7 +864,7 @@ impl<T: ?Sized> *mut T {
864864
T: Sized,
865865
{
866866
// SAFETY: the caller must uphold the safety contract for `offset_from`.
867-
unsafe { (self as *const T).offset_from(origin) }
867+
unsafe { self.cast_const().offset_from(origin) }
868868
}
869869

870870
/// Calculates the distance between two pointers. The returned value is in
@@ -955,7 +955,7 @@ impl<T: ?Sized> *mut T {
955955
T: Sized,
956956
{
957957
// SAFETY: the caller must uphold the safety contract for `sub_ptr`.
958-
unsafe { (self as *const T).sub_ptr(origin) }
958+
unsafe { self.cast_const().sub_ptr(origin) }
959959
}
960960

961961
/// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).

library/core/src/slice/ascii.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ fn is_ascii(s: &[u8]) -> bool {
271271

272272
let start = s.as_ptr();
273273
// SAFETY: We verify `len < USIZE_SIZE` above.
274-
let first_word = unsafe { (start as *const usize).read_unaligned() };
274+
let first_word = unsafe { start.cast::<usize>().read_unaligned() };
275275

276276
if contains_nonascii(first_word) {
277277
return false;
@@ -283,7 +283,7 @@ fn is_ascii(s: &[u8]) -> bool {
283283

284284
// SAFETY: word_ptr is the (properly aligned) usize ptr we use to read the
285285
// middle chunk of the slice.
286-
let mut word_ptr = unsafe { start.add(offset_to_aligned) as *const usize };
286+
let mut word_ptr = unsafe { start.add(offset_to_aligned).cast::<usize>() };
287287

288288
// `byte_pos` is the byte index of `word_ptr`, used for loop end checks.
289289
let mut byte_pos = offset_to_aligned;
@@ -322,7 +322,7 @@ fn is_ascii(s: &[u8]) -> bool {
322322
debug_assert!(byte_pos <= len && len - byte_pos <= USIZE_SIZE);
323323

324324
// SAFETY: This relies on `len >= USIZE_SIZE`, which we check at the start.
325-
let last_word = unsafe { (start.add(len - USIZE_SIZE) as *const usize).read_unaligned() };
325+
let last_word = unsafe { start.add(len - USIZE_SIZE).cast::<usize>().read_unaligned() };
326326

327327
!contains_nonascii(last_word)
328328
}

library/core/src/slice/cmp.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ where
8888
// The two slices have been checked to have the same size above.
8989
unsafe {
9090
let size = mem::size_of_val(self);
91-
memcmp(self.as_ptr() as *const u8, other.as_ptr() as *const u8, size) == 0
91+
memcmp(self.as_ptr().cast::<u8>(), other.as_ptr().cast::<u8>(), size) == 0
9292
}
9393
}
9494
}
@@ -231,7 +231,7 @@ impl SliceContains for i8 {
231231
// as `*const u8` is safe. The `x.as_ptr()` comes from a reference and is thus guaranteed
232232
// to be valid for reads for the length of the slice `x.len()`, which cannot be larger
233233
// than `isize::MAX`. The returned slice is never mutated.
234-
let bytes: &[u8] = unsafe { from_raw_parts(x.as_ptr() as *const u8, x.len()) };
234+
let bytes: &[u8] = unsafe { from_raw_parts(x.as_ptr().cast::<u8>(), x.len()) };
235235
memchr::memchr(byte, bytes).is_some()
236236
}
237237
}

library/core/src/slice/iter.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ impl<'a, T> Iter<'a, T> {
9090
let end =
9191
if T::IS_ZST { ptr.wrapping_byte_add(slice.len()) } else { ptr.add(slice.len()) };
9292

93-
Self { ptr: NonNull::new_unchecked(ptr as *mut T), end, _marker: PhantomData }
93+
Self { ptr: NonNull::new_unchecked(ptr.cast_mut()), end, _marker: PhantomData }
9494
}
9595
}
9696

library/core/src/slice/mod.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1800,7 +1800,7 @@ impl<T> [T] {
18001800
pub fn split_array_ref<const N: usize>(&self) -> (&[T; N], &[T]) {
18011801
let (a, b) = self.split_at(N);
18021802
// SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at)
1803-
unsafe { (&*(a.as_ptr() as *const [T; N]), b) }
1803+
unsafe { (&*a.as_ptr().cast::<[T; N]>(), b) }
18041804
}
18051805

18061806
/// Divides one mutable slice into an array and a remainder slice at an index.
@@ -1833,7 +1833,7 @@ impl<T> [T] {
18331833
pub fn split_array_mut<const N: usize>(&mut self) -> (&mut [T; N], &mut [T]) {
18341834
let (a, b) = self.split_at_mut(N);
18351835
// SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at_mut)
1836-
unsafe { (&mut *(a.as_mut_ptr() as *mut [T; N]), b) }
1836+
unsafe { (&mut *a.as_mut_ptr().cast::<[T; N]>(), b) }
18371837
}
18381838

18391839
/// Divides one slice into an array and a remainder slice at an index from
@@ -1879,7 +1879,7 @@ impl<T> [T] {
18791879
assert!(N <= self.len());
18801880
let (a, b) = self.split_at(self.len() - N);
18811881
// SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at)
1882-
unsafe { (a, &*(b.as_ptr() as *const [T; N])) }
1882+
unsafe { (a, &*b.as_ptr().cast::<[T; N]>()) }
18831883
}
18841884

18851885
/// Divides one mutable slice into an array and a remainder slice at an
@@ -1913,7 +1913,7 @@ impl<T> [T] {
19131913
assert!(N <= self.len());
19141914
let (a, b) = self.split_at_mut(self.len() - N);
19151915
// SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at_mut)
1916-
unsafe { (a, &mut *(b.as_mut_ptr() as *mut [T; N])) }
1916+
unsafe { (a, &mut *b.as_mut_ptr().cast::<[T; N]>()) }
19171917
}
19181918

19191919
/// Returns an iterator over subslices separated by elements that match
@@ -3582,7 +3582,7 @@ impl<T> [T] {
35823582
unsafe {
35833583
(
35843584
left,
3585-
from_raw_parts(rest.as_ptr() as *const U, us_len),
3585+
from_raw_parts(rest.as_ptr().cast::<U>(), us_len),
35863586
from_raw_parts(rest.as_ptr().add(rest.len() - ts_len), ts_len),
35873587
)
35883588
}
@@ -3652,7 +3652,7 @@ impl<T> [T] {
36523652
unsafe {
36533653
(
36543654
left,
3655-
from_raw_parts_mut(mut_ptr as *mut U, us_len),
3655+
from_raw_parts_mut(mut_ptr.cast::<U>(), us_len),
36563656
from_raw_parts_mut(mut_ptr.add(rest_len - ts_len), ts_len),
36573657
)
36583658
}

library/core/src/slice/rotate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize)
162162
// Algorithm 2
163163
// The `[T; 0]` here is to ensure this is appropriately aligned for T
164164
let mut rawarray = MaybeUninit::<(BufType, [T; 0])>::uninit();
165-
let buf = rawarray.as_mut_ptr() as *mut T;
165+
let buf = rawarray.as_mut_ptr().cast::<T>();
166166
// SAFETY: `mid-left <= mid-left+right < mid+right`
167167
let dim = unsafe { mid.sub(left).add(right) };
168168
if left <= right {

0 commit comments

Comments
 (0)