Skip to content

Commit

Permalink
Rollup merge of rust-lang#63793 - oli-obk:🧹, r=dtolnay
Browse files Browse the repository at this point in the history
Have tidy ensure that we document all `unsafe` blocks in libcore

cc @rust-lang/libs

I documented a few and added ignore flags on the other files. We can incrementally document the files, but won't regress any files this way.
  • Loading branch information
Centril authored Nov 7, 2019
2 parents 50f8aad + e28287b commit c36badf
Show file tree
Hide file tree
Showing 46 changed files with 180 additions and 42 deletions.
2 changes: 2 additions & 0 deletions src/libcore/alloc.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Memory allocation APIs

// ignore-tidy-undocumented-unsafe

#![stable(feature = "alloc_module", since = "1.28.0")]

use crate::cmp;
Expand Down
6 changes: 6 additions & 0 deletions src/libcore/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ impl dyn Any {
#[inline]
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
if self.is::<T>() {
// SAFETY: just checked whether we are pointing to the correct type
unsafe {
Some(&*(self as *const dyn Any as *const T))
}
Expand Down Expand Up @@ -217,6 +218,7 @@ impl dyn Any {
#[inline]
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
if self.is::<T>() {
// SAFETY: just checked whether we are pointing to the correct type
unsafe {
Some(&mut *(self as *mut dyn Any as *mut T))
}
Expand Down Expand Up @@ -424,7 +426,11 @@ impl TypeId {
#[rustc_const_unstable(feature="const_type_id")]
pub const fn of<T: ?Sized + 'static>() -> TypeId {
TypeId {
#[cfg(bootstrap)]
// SAFETY: going away soon
t: unsafe { intrinsics::type_id::<T>() },
#[cfg(not(bootstrap))]
t: intrinsics::type_id::<T>(),
}
}
}
Expand Down
13 changes: 8 additions & 5 deletions src/libcore/array/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ where
/// iterator (either via `IntoIterator` for arrays or via another way).
#[unstable(feature = "array_value_iter", issue = "65798")]
pub fn new(array: [T; N]) -> Self {
// The transmute here is actually safe. The docs of `MaybeUninit`
// SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
// promise:
//
// > `MaybeUninit<T>` is guaranteed to have the same size and alignment
Expand Down Expand Up @@ -84,10 +84,10 @@ where
/// Returns an immutable slice of all elements that have not been yielded
/// yet.
fn as_slice(&self) -> &[T] {
// This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
let slice = &self.data[self.alive.clone()];
// SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
// the size and alignment of `T`. Furthermore, we know that all
// elements within `alive` are properly initialized.
let slice = &self.data[self.alive.clone()];
unsafe {
mem::transmute::<&[MaybeUninit<T>], &[T]>(slice)
}
Expand Down Expand Up @@ -117,7 +117,8 @@ where
let idx = self.alive.start;
self.alive.start += 1;

// Read the element from the array. This is safe: `idx` is an index
// Read the element from the array.
// SAFETY: This is safe: `idx` is an index
// into the "alive" region of the array. Reading this element means
// that `data[idx]` is regarded as dead now (i.e. do not touch). As
// `idx` was the start of the alive-zone, the alive zone is now
Expand Down Expand Up @@ -163,7 +164,8 @@ where
// + 1]`.
self.alive.end -= 1;

// Read the element from the array. This is safe: `alive.end` is an
// Read the element from the array.
// SAFETY: This is safe: `alive.end` is an
// index into the "alive" region of the array. Compare the previous
// comment that states that the alive region is
// `data[alive.start..alive.end + 1]`. Reading this element means that
Expand Down Expand Up @@ -226,6 +228,7 @@ where
[T; N]: LengthAtMost32,
{
fn clone(&self) -> Self {
// SAFETY: each point of unsafety is documented inside the unsafe block
unsafe {
// This creates a new uninitialized array. Note that the `assume_init`
// refers to the array, not the individual elements. And it is Ok if
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ where
fn try_from(slice: &[T]) -> Result<&[T; N], TryFromSliceError> {
if slice.len() == N {
let ptr = slice.as_ptr() as *const [T; N];
// SAFETY: ok because we just checked that the length fits
unsafe { Ok(&*ptr) }
} else {
Err(TryFromSliceError(()))
Expand All @@ -173,6 +174,7 @@ where
fn try_from(slice: &mut [T]) -> Result<&mut [T; N], TryFromSliceError> {
if slice.len() == N {
let ptr = slice.as_mut_ptr() as *mut [T; N];
// SAFETY: ok because we just checked that the length fits
unsafe { Ok(&mut *ptr) }
} else {
Err(TryFromSliceError(()))
Expand Down
1 change: 1 addition & 0 deletions src/libcore/ascii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ impl FusedIterator for EscapeDefault {}
#[stable(feature = "ascii_escape_display", since = "1.39.0")]
impl fmt::Display for EscapeDefault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// SAFETY: ok because `escape_default` created only valid utf-8 data
f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) })
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/benches/ascii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ benches! {
}

fn case07_fake_simd_u32(bytes: &mut [u8]) {
// SAFETY: transmuting a sequence of `u8` to `u32` is always fine
let (before, aligned, after) = unsafe {
bytes.align_to_mut::<u32>()
};
Expand All @@ -142,6 +143,7 @@ benches! {
}

fn case08_fake_simd_u64(bytes: &mut [u8]) {
// SAFETY: transmuting a sequence of `u8` to `u64` is always fine
let (before, aligned, after) = unsafe {
bytes.align_to_mut::<u64>()
};
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@
//! ```
//!

// ignore-tidy-undocumented-unsafe

#![stable(feature = "rust1", since = "1.0.0")]

use crate::cmp::Ordering;
Expand Down
1 change: 1 addition & 0 deletions src/libcore/char/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ impl TryFrom<u32> for char {
if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
Err(CharTryFromError(()))
} else {
// SAFETY: checked that it's a legal unicode value
Ok(unsafe { from_u32_unchecked(i) })
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/libcore/char/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
};

if u < 0xD800 || 0xDFFF < u {
// not a surrogate
// SAFETY: not a surrogate
Some(Ok(unsafe { from_u32_unchecked(u as u32) }))
} else if u >= 0xDC00 {
// a trailing surrogate
Expand All @@ -107,6 +107,7 @@ impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {

// all ok, so lets decode it.
let c = (((u - 0xD800) as u32) << 10 | (u2 - 0xDC00) as u32) + 0x1_0000;
// SAFETY: we checked that it's a legal unicode value
Some(Ok(unsafe { from_u32_unchecked(c) }))
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/char/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ impl char {
#[inline]
pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
let code = self as u32;
// SAFETY: each arm checks the size of the slice and only uses `get_unchecked` unsafe ops
unsafe {
let len = if code < MAX_ONE_B && !dst.is_empty() {
*dst.get_unchecked_mut(0) = code as u8;
Expand Down Expand Up @@ -507,6 +508,7 @@ impl char {
#[inline]
pub fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] {
let mut code = self as u32;
// SAFETY: each arm checks whether there are enough bits to write into
unsafe {
if (code & 0xFFFF) == code && !dst.is_empty() {
// The BMP falls through (assuming non-surrogate, as it should)
Expand Down
1 change: 1 addition & 0 deletions src/libcore/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ impl<'f> Clone for VaListImpl<'f> {
#[inline]
fn clone(&self) -> Self {
let mut dest = crate::mem::MaybeUninit::uninit();
// SAFETY: we write to the `MaybeUninit`, thus it is initialized and `assume_init` is legal
unsafe {
va_copy(dest.as_mut_ptr(), self);
dest.assume_init()
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/fmt/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use crate::fmt::{Formatter, Result, LowerExp, UpperExp, Display, Debug};
use crate::mem::MaybeUninit;
use crate::num::flt2dec;

// ignore-tidy-undocumented-unsafe

// Don't inline this so callers don't use the stack space this function
// requires unless they have to.
#[inline(never)]
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/fmt/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Utilities for formatting and printing strings.

// ignore-tidy-undocumented-unsafe

#![stable(feature = "rust1", since = "1.0.0")]

use crate::cell::{UnsafeCell, Cell, RefCell, Ref, RefMut};
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/fmt/num.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Integer and floating-point number formatting

// ignore-tidy-undocumented-unsafe


use crate::fmt;
use crate::ops::{Div, Rem, Sub};
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/hash/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@
//! }
//! ```

// ignore-tidy-undocumented-unsafe

#![stable(feature = "rust1", since = "1.0.0")]

use crate::fmt;
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/hash/sip.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! An implementation of SipHash.

// ignore-tidy-undocumented-unsafe

#![allow(deprecated)] // the types in this module are deprecated

use crate::marker::PhantomData;
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

//! Hints to compiler that affects how code should be emitted or optimized.

// ignore-tidy-undocumented-unsafe

use crate::intrinsics;

/// Informs the compiler that this point in the code is not reachable, enabling
Expand Down
14 changes: 12 additions & 2 deletions src/libcore/iter/adapters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,8 +517,18 @@ impl<I> Iterator for StepBy<I> where I: Iterator {
// overflow handling
loop {
let mul = n.checked_mul(step);
if unsafe { intrinsics::likely(mul.is_some()) } {
return self.iter.nth(mul.unwrap() - 1);
#[cfg(bootstrap)]
{
// SAFETY: going away soon
if unsafe { intrinsics::likely(mul.is_some()) } {
return self.iter.nth(mul.unwrap() - 1);
}
}
#[cfg(not(bootstrap))]
{
if intrinsics::likely(mul.is_some()) {
return self.iter.nth(mul.unwrap() - 1);
}
}
let div_n = usize::MAX / n;
let div_step = usize::MAX / step;
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/iter/adapters/zip.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore-tidy-undocumented-unsafe

use crate::cmp;

use super::super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen};
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/mem/maybe_uninit.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::intrinsics;
use crate::mem::ManuallyDrop;

// ignore-tidy-undocumented-unsafe

/// A wrapper type to construct uninitialized instances of `T`.
///
/// # Initialization invariant
Expand Down
19 changes: 18 additions & 1 deletion src/libcore/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ pub fn forget<T>(t: T) {
#[inline]
#[unstable(feature = "forget_unsized", issue = "0")]
pub fn forget_unsized<T: ?Sized>(t: T) {
// SAFETY: the forget intrinsic could be safe, but there's no point in making it safe since
// we'll be implementing this function soon via `ManuallyDrop`
unsafe { intrinsics::forget(t) }
}

Expand Down Expand Up @@ -266,7 +268,11 @@ pub const fn size_of<T>() -> usize {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
#[cfg(bootstrap)]
// SAFETY: going away soon
unsafe { intrinsics::size_of_val(val) }
#[cfg(not(bootstrap))]
intrinsics::size_of_val(val)
}

/// Returns the [ABI]-required minimum alignment of a type.
Expand Down Expand Up @@ -310,7 +316,11 @@ pub fn min_align_of<T>() -> usize {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(reason = "use `align_of_val` instead", since = "1.2.0")]
pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
#[cfg(bootstrap)]
// SAFETY: going away soon
unsafe { intrinsics::min_align_of_val(val) }
#[cfg(not(bootstrap))]
intrinsics::min_align_of_val(val)
}

/// Returns the [ABI]-required minimum alignment of a type.
Expand Down Expand Up @@ -350,8 +360,9 @@ pub const fn align_of<T>() -> usize {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
unsafe { intrinsics::min_align_of_val(val) }
min_align_of_val(val)
}

/// Returns `true` if dropping values of type `T` matters.
Expand Down Expand Up @@ -508,6 +519,8 @@ pub unsafe fn uninitialized<T>() -> T {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn swap<T>(x: &mut T, y: &mut T) {
// SAFETY: the raw pointers have been created from safe mutable references satisfying all the
// constraints on `ptr::swap_nonoverlapping_one`
unsafe {
ptr::swap_nonoverlapping_one(x, y);
}
Expand Down Expand Up @@ -822,7 +835,11 @@ impl<T> fmt::Debug for Discriminant<T> {
/// ```
#[stable(feature = "discriminant_value", since = "1.21.0")]
pub fn discriminant<T>(v: &T) -> Discriminant<T> {
#[cfg(bootstrap)]
// SAFETY: going away soon
unsafe {
Discriminant(intrinsics::discriminant_value(v), PhantomData)
}
#[cfg(not(bootstrap))]
Discriminant(intrinsics::discriminant_value(v), PhantomData)
}
4 changes: 4 additions & 0 deletions src/libcore/num/dec2flt/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ mod fpu_precision {
pub struct FPUControlWord(u16);

fn set_cw(cw: u16) {
// SAFETY: the `fldcw` instruction has been audited to be able to work correctly with
// any `u16`
unsafe { asm!("fldcw $0" :: "m" (cw) :: "volatile") }
}

Expand All @@ -74,6 +76,8 @@ mod fpu_precision {

// Get the original value of the control word to restore it later, when the
// `FPUControlWord` structure is dropped
// SAFETY: the `fnstcw` instruction has been audited to be able to work correctly with
// any `u16`
unsafe { asm!("fnstcw $0" : "=*m" (&cw) ::: "volatile") }

// Set the control word to the desired precision. This is achieved by masking away the old
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ impl f32 {
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn to_bits(self) -> u32 {
// SAFETY: `u32` is a plain old datatype so we can always transmute to it
unsafe { mem::transmute(self) }
}

Expand Down Expand Up @@ -456,6 +457,7 @@ impl f32 {
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn from_bits(v: u32) -> Self {
// SAFETY: `u32` is a plain old datatype so we can always transmute from it
// It turns out the safety issues with sNaN were overblown! Hooray!
unsafe { mem::transmute(v) }
}
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/num/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ impl f64 {
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn to_bits(self) -> u64 {
// SAFETY: `u64` is a plain old datatype so we can always transmute to it
unsafe { mem::transmute(self) }
}

Expand Down Expand Up @@ -469,6 +470,7 @@ impl f64 {
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn from_bits(v: u64) -> Self {
// SAFETY: `u64` is a plain old datatype so we can always transmute from it
// It turns out the safety issues with sNaN were overblown! Hooray!
unsafe { mem::transmute(v) }
}
Expand Down
Loading

0 comments on commit c36badf

Please sign in to comment.