Skip to content
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

Have tidy ensure that we document all unsafe blocks in libcore #63793

Merged
merged 5 commits into from
Nov 8, 2019
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: 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 @@ -182,6 +182,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