Have tidy ensure that we document all unsafe
blocks in libcore
This commit is contained in:
parent
e8b190ac4a
commit
02f9167f94
41 changed files with 137 additions and 5 deletions
|
@ -1,5 +1,7 @@
|
|||
//! Memory allocation APIs
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
#![stable(feature = "alloc_module", since = "1.28.0")]
|
||||
|
||||
use crate::cmp;
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -424,7 +426,11 @@ impl TypeId {
|
|||
#[rustc_const_unstable(feature="const_type_id")]
|
||||
pub const fn of<T: ?Sized + 'static>() -> TypeId {
|
||||
TypeId {
|
||||
#[cfg(boostrap_stdarch_ignore_this)]
|
||||
// SAFETY: going away soon
|
||||
t: unsafe { intrinsics::type_id::<T>() },
|
||||
#[cfg(not(boostrap_stdarch_ignore_this))]
|
||||
t: intrinsics::type_id::<T>(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(()))
|
||||
|
@ -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(()))
|
||||
|
|
|
@ -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()]) })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>()
|
||||
};
|
||||
|
@ -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>()
|
||||
};
|
||||
|
|
|
@ -182,6 +182,8 @@
|
|||
//! ```
|
||||
//!
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::cmp::Ordering;
|
||||
|
|
|
@ -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) })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -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) }))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
//! Integer and floating-point number formatting
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
|
||||
use crate::fmt;
|
||||
use crate::ops::{Div, Rem, Sub};
|
||||
|
|
|
@ -79,6 +79,8 @@
|
|||
//! }
|
||||
//! ```
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::fmt;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -517,9 +517,15 @@ impl<I> Iterator for StepBy<I> where I: Iterator {
|
|||
// overflow handling
|
||||
loop {
|
||||
let mul = n.checked_mul(step);
|
||||
#[cfg(boostrap_stdarch_ignore_this)]
|
||||
// SAFETY: going away soon
|
||||
if unsafe { intrinsics::likely(mul.is_some()) } {
|
||||
return self.iter.nth(mul.unwrap() - 1);
|
||||
}
|
||||
#[cfg(not(boostrap_stdarch_ignore_this))]
|
||||
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;
|
||||
let nth_n = div_n * n;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
use crate::cmp;
|
||||
|
||||
use super::super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) }
|
||||
}
|
||||
|
||||
|
@ -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(boostrap_stdarch_ignore_this)]
|
||||
// SAFETY: going away soon
|
||||
unsafe { intrinsics::size_of_val(val) }
|
||||
#[cfg(not(boostrap_stdarch_ignore_this))]
|
||||
intrinsics::size_of_val(val)
|
||||
}
|
||||
|
||||
/// Returns the [ABI]-required minimum alignment of a type.
|
||||
|
@ -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(boostrap_stdarch_ignore_this)]
|
||||
// SAFETY: going away soon
|
||||
unsafe { intrinsics::min_align_of_val(val) }
|
||||
#[cfg(not(boostrap_stdarch_ignore_this))]
|
||||
intrinsics::min_align_of_val(val)
|
||||
}
|
||||
|
||||
/// Returns the [ABI]-required minimum alignment of a type.
|
||||
|
@ -351,7 +361,7 @@ pub const fn align_of<T>() -> usize {
|
|||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
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.
|
||||
|
@ -508,6 +518,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);
|
||||
}
|
||||
|
@ -822,7 +834,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(boostrap_stdarch_ignore_this)]
|
||||
// SAFETY: going away soon
|
||||
unsafe {
|
||||
Discriminant(intrinsics::discriminant_value(v), PhantomData)
|
||||
}
|
||||
#[cfg(not(boostrap_stdarch_ignore_this))]
|
||||
Discriminant(intrinsics::discriminant_value(v), PhantomData)
|
||||
}
|
||||
|
|
|
@ -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") }
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -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) }
|
||||
}
|
||||
|
||||
|
@ -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) }
|
||||
}
|
||||
|
|
|
@ -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) }
|
||||
}
|
||||
|
||||
|
@ -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) }
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", s
|
|||
#[inline]
|
||||
pub fn new(n: $Int) -> Option<Self> {
|
||||
if n != 0 {
|
||||
// SAFETY: we just checked that there's no `0`
|
||||
Some(unsafe { $Ty(n) })
|
||||
} else {
|
||||
None
|
||||
|
@ -703,6 +704,7 @@ $EndFeature, "
|
|||
if rhs == 0 || (self == Self::min_value() && rhs == -1) {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: div by zero and by INT_MIN have been checked above
|
||||
Some(unsafe { intrinsics::unchecked_div(self, rhs) })
|
||||
}
|
||||
}
|
||||
|
@ -759,6 +761,7 @@ $EndFeature, "
|
|||
if rhs == 0 || (self == Self::min_value() && rhs == -1) {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: div by zero and by INT_MIN have been checked above
|
||||
Some(unsafe { intrinsics::unchecked_rem(self, rhs) })
|
||||
}
|
||||
}
|
||||
|
@ -1329,6 +1332,8 @@ $EndFeature, "
|
|||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_shl(self, rhs: u32) -> Self {
|
||||
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
|
||||
// out of bounds
|
||||
unsafe {
|
||||
intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
|
||||
}
|
||||
|
@ -1358,6 +1363,8 @@ $EndFeature, "
|
|||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_shr(self, rhs: u32) -> Self {
|
||||
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
|
||||
// out of bounds
|
||||
unsafe {
|
||||
intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
|
||||
}
|
||||
|
@ -2113,6 +2120,8 @@ assert_eq!(
|
|||
#[rustc_const_unstable(feature = "const_int_conversion")]
|
||||
#[inline]
|
||||
pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
|
||||
// SAFETY: integers are plain old datatypes so we can always transmute them to
|
||||
// arrays of bytes
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
@ -2221,6 +2230,7 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
|
|||
#[rustc_const_unstable(feature = "const_int_conversion")]
|
||||
#[inline]
|
||||
pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
|
||||
// SAFETY: integers are plain old datatypes so we can always transmute to them
|
||||
unsafe { mem::transmute(bytes) }
|
||||
}
|
||||
}
|
||||
|
@ -2748,6 +2758,8 @@ assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, "
|
|||
pub fn checked_div(self, rhs: Self) -> Option<Self> {
|
||||
match rhs {
|
||||
0 => None,
|
||||
// SAFETY: div by zero has been checked above and unsigned types have no other
|
||||
// failure modes for division
|
||||
rhs => Some(unsafe { intrinsics::unchecked_div(self, rhs) }),
|
||||
}
|
||||
}
|
||||
|
@ -2799,6 +2811,8 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, "
|
|||
if rhs == 0 {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: div by zero has been checked above and unsigned types have no other
|
||||
// failure modes for division
|
||||
Some(unsafe { intrinsics::unchecked_rem(self, rhs) })
|
||||
}
|
||||
}
|
||||
|
@ -3248,6 +3262,8 @@ assert_eq!(1", stringify!($SelfT), ".wrapping_shl(128), 1);", $EndFeature, "
|
|||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_shl(self, rhs: u32) -> Self {
|
||||
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
|
||||
// out of bounds
|
||||
unsafe {
|
||||
intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
|
||||
}
|
||||
|
@ -3279,6 +3295,8 @@ assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);", $EndFeature, "
|
|||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_shr(self, rhs: u32) -> Self {
|
||||
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
|
||||
// out of bounds
|
||||
unsafe {
|
||||
intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
|
||||
}
|
||||
|
@ -3775,11 +3793,11 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, "
|
|||
fn one_less_than_next_power_of_two(self) -> Self {
|
||||
if self <= 1 { return 0; }
|
||||
|
||||
// Because `p > 0`, it cannot consist entirely of leading zeros.
|
||||
let p = self - 1;
|
||||
// SAFETY: Because `p > 0`, it cannot consist entirely of leading zeros.
|
||||
// That means the shift is always in-bounds, and some processors
|
||||
// (such as intel pre-haswell) have more efficient ctlz
|
||||
// intrinsics when the argument is non-zero.
|
||||
let p = self - 1;
|
||||
let z = unsafe { intrinsics::ctlz_nonzero(p) };
|
||||
<$SelfT>::max_value() >> z
|
||||
}
|
||||
|
@ -3925,6 +3943,8 @@ assert_eq!(
|
|||
#[rustc_const_unstable(feature = "const_int_conversion")]
|
||||
#[inline]
|
||||
pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
|
||||
// SAFETY: integers are plain old datatypes so we can always transmute them to
|
||||
// arrays of bytes
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
@ -4033,6 +4053,7 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
|
|||
#[rustc_const_unstable(feature = "const_int_conversion")]
|
||||
#[inline]
|
||||
pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
|
||||
// SAFETY: integers are plain old datatypes so we can always transmute to them
|
||||
unsafe { mem::transmute(bytes) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,6 +133,8 @@
|
|||
//! [`Box<T>`]: ../../std/boxed/struct.Box.html
|
||||
//! [`i32`]: ../../std/primitive.i32.html
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::iter::{FromIterator, FusedIterator, TrustedLen};
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
//! one function. Currently, the actual symbol is declared in the standard
|
||||
//! library, but the location of this may change over time.
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
#![allow(dead_code, missing_docs)]
|
||||
#![unstable(feature = "core_panic",
|
||||
reason = "internal details of the implementation of the `panic!` \
|
||||
|
|
|
@ -552,6 +552,7 @@ impl<P: Deref> Pin<P> {
|
|||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
#[inline(always)]
|
||||
pub fn as_ref(&self) -> Pin<&P::Target> {
|
||||
// SAFETY: see documentation on this function
|
||||
unsafe { Pin::new_unchecked(&*self.pointer) }
|
||||
}
|
||||
|
||||
|
@ -610,6 +611,7 @@ impl<P: DerefMut> Pin<P> {
|
|||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
#[inline(always)]
|
||||
pub fn as_mut(&mut self) -> Pin<&mut P::Target> {
|
||||
// SAFETY: see documentation on this function
|
||||
unsafe { Pin::new_unchecked(&mut *self.pointer) }
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,8 @@
|
|||
//! [`write_volatile`]: ./fn.write_volatile.html
|
||||
//! [`NonNull::dangling`]: ./struct.NonNull.html#method.dangling
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::intrinsics;
|
||||
|
|
|
@ -7,6 +7,8 @@ use crate::mem;
|
|||
use crate::ptr::Unique;
|
||||
use crate::cmp::Ordering;
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
/// `*mut T` but non-zero and covariant.
|
||||
///
|
||||
/// This is often the correct thing to use when building data structures using
|
||||
|
|
|
@ -5,6 +5,8 @@ use crate::marker::{PhantomData, Unsize};
|
|||
use crate::mem;
|
||||
use crate::ptr::NonNull;
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
|
||||
/// of this wrapper owns the referent. Useful for building abstractions like
|
||||
/// `Box<T>`, `Vec<T>`, `String`, and `HashMap<K, V>`.
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// Original implementation taken from rust-memchr.
|
||||
// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
use crate::cmp;
|
||||
use crate::mem;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// ignore-tidy-filelength
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
//! Slice management and manipulation.
|
||||
//!
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
//! Unstable sorting is compatible with libcore because it doesn't allocate memory, unlike our
|
||||
//! stable sorting implementation.
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
use crate::cmp;
|
||||
use crate::mem::{self, MaybeUninit};
|
||||
use crate::ptr;
|
||||
|
|
|
@ -3,6 +3,8 @@ use crate::str as core_str;
|
|||
use crate::fmt::{self, Write};
|
||||
use crate::mem;
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
/// Lossy UTF-8 string.
|
||||
#[unstable(feature = "str_internals", issue = "0")]
|
||||
pub struct Utf8Lossy {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// ignore-tidy-filelength
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
//! String manipulation.
|
||||
//!
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
//! For more details, see the traits [`Pattern`], [`Searcher`],
|
||||
//! [`ReverseSearcher`], and [`DoubleEndedSearcher`].
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
#![unstable(feature = "pattern",
|
||||
reason = "API not fully fleshed out and ready to be stabilized",
|
||||
issue = "27721")]
|
||||
|
|
|
@ -112,6 +112,8 @@
|
|||
//! println!("live threads: {}", old_thread_count + 1);
|
||||
//! ```
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(dead_code))]
|
||||
#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(unused_imports))]
|
||||
|
|
|
@ -85,6 +85,8 @@ fn ldexp_f64(a: f64, b: i32) -> f64 {
|
|||
extern {
|
||||
fn ldexp(x: f64, n: i32) -> f64;
|
||||
}
|
||||
// SAFETY: assuming a correct `ldexp` has been supplied, the given arguments cannot possibly
|
||||
// cause undefined behavior
|
||||
unsafe { ldexp(a, b) }
|
||||
}
|
||||
|
||||
|
|
|
@ -920,7 +920,7 @@ impl fmt::Debug for Duration {
|
|||
if end == 0 {
|
||||
write!(f, "{}", integer_part)
|
||||
} else {
|
||||
// We are only writing ASCII digits into the buffer and it was
|
||||
// SAFETY: We are only writing ASCII digits into the buffer and it was
|
||||
// initialized with '0's, so it contains valid UTF8.
|
||||
let s = unsafe {
|
||||
crate::str::from_utf8_unchecked(&buf[..end])
|
||||
|
|
|
@ -67,11 +67,13 @@ fn equate_intrinsic_type<'tcx>(
|
|||
pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
|
||||
match intrinsic {
|
||||
"size_of" | "min_align_of" | "needs_drop" | "caller_location" |
|
||||
"size_of_val" | "min_align_of_val" |
|
||||
"add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" |
|
||||
"wrapping_add" | "wrapping_sub" | "wrapping_mul" |
|
||||
"saturating_add" | "saturating_sub" |
|
||||
"rotate_left" | "rotate_right" |
|
||||
"ctpop" | "ctlz" | "cttz" | "bswap" | "bitreverse" |
|
||||
"discriminant_value" | "type_id" | "likely" | "unlikely" |
|
||||
"minnumf32" | "minnumf64" | "maxnumf32" | "maxnumf64" | "type_name"
|
||||
=> hir::Unsafety::Normal,
|
||||
_ => hir::Unsafety::Unsafe,
|
||||
|
|
|
@ -160,6 +160,8 @@ pub fn check(path: &Path, bad: &mut bool) {
|
|||
let can_contain = contents.contains("// ignore-tidy-") ||
|
||||
contents.contains("# ignore-tidy-");
|
||||
let mut skip_cr = contains_ignore_directive(can_contain, &contents, "cr");
|
||||
let mut skip_undocumented_unsafe =
|
||||
contains_ignore_directive(can_contain, &contents, "undocumented-unsafe");
|
||||
let mut skip_tab = contains_ignore_directive(can_contain, &contents, "tab");
|
||||
let mut skip_line_length = contains_ignore_directive(can_contain, &contents, "linelength");
|
||||
let mut skip_file_length = contains_ignore_directive(can_contain, &contents, "filelength");
|
||||
|
@ -171,6 +173,7 @@ pub fn check(path: &Path, bad: &mut bool) {
|
|||
let mut leading_new_lines = false;
|
||||
let mut trailing_new_lines = 0;
|
||||
let mut lines = 0;
|
||||
let mut last_safety_comment = false;
|
||||
for (i, line) in contents.split('\n').enumerate() {
|
||||
let mut err = |msg: &str| {
|
||||
tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg);
|
||||
|
@ -200,6 +203,20 @@ pub fn check(path: &Path, bad: &mut bool) {
|
|||
err("XXX is deprecated; use FIXME")
|
||||
}
|
||||
}
|
||||
let is_test = || file.components().any(|c| c.as_os_str() == "tests");
|
||||
// for now we just check libcore
|
||||
if line.contains("unsafe {") && !line.trim().starts_with("//") && !last_safety_comment {
|
||||
if file.components().any(|c| c.as_os_str() == "libcore") && !is_test() {
|
||||
suppressible_tidy_err!(err, skip_undocumented_unsafe, "undocumented unsafe");
|
||||
}
|
||||
}
|
||||
if line.contains("// SAFETY: ") || line.contains("// Safety: ") {
|
||||
last_safety_comment = true;
|
||||
} else if line.trim().starts_with("//") || line.trim().is_empty() {
|
||||
// keep previous value
|
||||
} else {
|
||||
last_safety_comment = false;
|
||||
}
|
||||
if (line.starts_with("// Copyright") ||
|
||||
line.starts_with("# Copyright") ||
|
||||
line.starts_with("Copyright"))
|
||||
|
|
Loading…
Add table
Reference in a new issue