about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-11-07 14:27:20 +0100
committerGitHub <noreply@github.com>2019-11-07 14:27:20 +0100
commit379b19c17f6fb9eda810222671ba9046e375e7ec (patch)
treea443a94d9e2c5101779487b24bd345f025fb3867 /src/libcore
parent50f8aadd746ebc929a752e5ffb133936ee75c52f (diff)
parente28287b32c40c44fb120c9a3a7eae6f82a7031fa (diff)
downloadrust-379b19c17f6fb9eda810222671ba9046e375e7ec.tar.gz
rust-379b19c17f6fb9eda810222671ba9046e375e7ec.zip
Rollup merge of #63793 - oli-obk:🧹, r=dtolnay
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.
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/alloc.rs2
-rw-r--r--src/libcore/any.rs6
-rw-r--r--src/libcore/array/iter.rs13
-rw-r--r--src/libcore/array/mod.rs2
-rw-r--r--src/libcore/ascii.rs1
-rw-r--r--src/libcore/benches/ascii.rs2
-rw-r--r--src/libcore/cell.rs2
-rw-r--r--src/libcore/char/convert.rs1
-rw-r--r--src/libcore/char/decode.rs3
-rw-r--r--src/libcore/char/methods.rs2
-rw-r--r--src/libcore/ffi.rs1
-rw-r--r--src/libcore/fmt/float.rs2
-rw-r--r--src/libcore/fmt/mod.rs2
-rw-r--r--src/libcore/fmt/num.rs2
-rw-r--r--src/libcore/hash/mod.rs2
-rw-r--r--src/libcore/hash/sip.rs2
-rw-r--r--src/libcore/hint.rs2
-rw-r--r--src/libcore/iter/adapters/mod.rs14
-rw-r--r--src/libcore/iter/adapters/zip.rs2
-rw-r--r--src/libcore/mem/maybe_uninit.rs2
-rw-r--r--src/libcore/mem/mod.rs19
-rw-r--r--src/libcore/num/dec2flt/algorithm.rs4
-rw-r--r--src/libcore/num/f32.rs2
-rw-r--r--src/libcore/num/f64.rs2
-rw-r--r--src/libcore/num/mod.rs25
-rw-r--r--src/libcore/option.rs2
-rw-r--r--src/libcore/panicking.rs2
-rw-r--r--src/libcore/pin.rs2
-rw-r--r--src/libcore/ptr/mod.rs2
-rw-r--r--src/libcore/ptr/non_null.rs2
-rw-r--r--src/libcore/ptr/unique.rs2
-rw-r--r--src/libcore/slice/memchr.rs2
-rw-r--r--src/libcore/slice/mod.rs1
-rw-r--r--src/libcore/slice/sort.rs2
-rw-r--r--src/libcore/str/lossy.rs2
-rw-r--r--src/libcore/str/mod.rs1
-rw-r--r--src/libcore/str/pattern.rs2
-rw-r--r--src/libcore/sync/atomic.rs2
-rw-r--r--src/libcore/tests/num/flt2dec/mod.rs2
-rw-r--r--src/libcore/time.rs2
40 files changed, 133 insertions, 12 deletions
diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs
index 5d0333d5226..1b06baeb711 100644
--- a/src/libcore/alloc.rs
+++ b/src/libcore/alloc.rs
@@ -1,5 +1,7 @@
 //! Memory allocation APIs
 
+// ignore-tidy-undocumented-unsafe
+
 #![stable(feature = "alloc_module", since = "1.28.0")]
 
 use crate::cmp;
diff --git a/src/libcore/any.rs b/src/libcore/any.rs
index e2704e807d1..39a5dd7263c 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -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(bootstrap)]
+            // SAFETY: going away soon
             t: unsafe { intrinsics::type_id::<T>() },
+            #[cfg(not(bootstrap))]
+            t: intrinsics::type_id::<T>(),
         }
     }
 }
diff --git a/src/libcore/array/iter.rs b/src/libcore/array/iter.rs
index 11803238407..307e9b90ee2 100644
--- a/src/libcore/array/iter.rs
+++ b/src/libcore/array/iter.rs
@@ -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
@@ -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)
         }
@@ -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
@@ -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
@@ -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
diff --git a/src/libcore/array/mod.rs b/src/libcore/array/mod.rs
index e1ec8b795d0..74a7d062d3f 100644
--- a/src/libcore/array/mod.rs
+++ b/src/libcore/array/mod.rs
@@ -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(()))
diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs
index 4087333e2cf..9b588525bd6 100644
--- a/src/libcore/ascii.rs
+++ b/src/libcore/ascii.rs
@@ -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()]) })
     }
 }
diff --git a/src/libcore/benches/ascii.rs b/src/libcore/benches/ascii.rs
index a337c467131..e921dd1ba06 100644
--- a/src/libcore/benches/ascii.rs
+++ b/src/libcore/benches/ascii.rs
@@ -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>()
         };
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 817c04d0af9..87d8e7aff05 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -187,6 +187,8 @@
 //! ```
 //!
 
+// ignore-tidy-undocumented-unsafe
+
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::cmp::Ordering;
diff --git a/src/libcore/char/convert.rs b/src/libcore/char/convert.rs
index c456e14db12..28f52074495 100644
--- a/src/libcore/char/convert.rs
+++ b/src/libcore/char/convert.rs
@@ -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) })
         }
     }
diff --git a/src/libcore/char/decode.rs b/src/libcore/char/decode.rs
index b71c9c2c40b..ae09251c776 100644
--- a/src/libcore/char/decode.rs
+++ b/src/libcore/char/decode.rs
@@ -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) }))
         }
     }
diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs
index 971d89e0044..c048bab287d 100644
--- a/src/libcore/char/methods.rs
+++ b/src/libcore/char/methods.rs
@@ -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)
diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs
index 569c667ac0a..499dd0facd3 100644
--- a/src/libcore/ffi.rs
+++ b/src/libcore/ffi.rs
@@ -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()
diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs
index a2fff913ac7..b52b56b1bdb 100644
--- a/src/libcore/fmt/float.rs
+++ b/src/libcore/fmt/float.rs
@@ -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)]
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 0e83a282b18..5a039144f66 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -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};
diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs
index 3b5c9fbff25..3c7aefc090f 100644
--- a/src/libcore/fmt/num.rs
+++ b/src/libcore/fmt/num.rs
@@ -1,5 +1,7 @@
 //! Integer and floating-point number formatting
 
+// ignore-tidy-undocumented-unsafe
+
 
 use crate::fmt;
 use crate::ops::{Div, Rem, Sub};
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index 020e085abf8..0082363692d 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -79,6 +79,8 @@
 //! }
 //! ```
 
+// ignore-tidy-undocumented-unsafe
+
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::fmt;
diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs
index 19aeafd882e..194d9e6e2f8 100644
--- a/src/libcore/hash/sip.rs
+++ b/src/libcore/hash/sip.rs
@@ -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;
diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs
index 368a2f16b28..f68a3e5a76f 100644
--- a/src/libcore/hint.rs
+++ b/src/libcore/hint.rs
@@ -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
diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs
index 3b8edc2ad61..39d571006e6 100644
--- a/src/libcore/iter/adapters/mod.rs
+++ b/src/libcore/iter/adapters/mod.rs
@@ -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;
diff --git a/src/libcore/iter/adapters/zip.rs b/src/libcore/iter/adapters/zip.rs
index 430ceacdd9f..14d9d5499b8 100644
--- a/src/libcore/iter/adapters/zip.rs
+++ b/src/libcore/iter/adapters/zip.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-undocumented-unsafe
+
 use crate::cmp;
 
 use super::super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen};
diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs
index 03093139bc2..4b3dc1c83c4 100644
--- a/src/libcore/mem/maybe_uninit.rs
+++ b/src/libcore/mem/maybe_uninit.rs
@@ -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
diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs
index c7da56aad30..26909be9496 100644
--- a/src/libcore/mem/mod.rs
+++ b/src/libcore/mem/mod.rs
@@ -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(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.
@@ -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.
@@ -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.
@@ -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);
     }
@@ -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)
 }
diff --git a/src/libcore/num/dec2flt/algorithm.rs b/src/libcore/num/dec2flt/algorithm.rs
index ed89852dc48..64146302626 100644
--- a/src/libcore/num/dec2flt/algorithm.rs
+++ b/src/libcore/num/dec2flt/algorithm.rs
@@ -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
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 5730088c4d9..7662bba6b5e 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -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) }
     }
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 2bdeda340dc..4a2a35dfb09 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -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) }
     }
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index b4ade704144..4b9e82c7cfe 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -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) }
             }
         }
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index f0ac5e749f6..958f31c0fd2 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -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};
diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs
index 685b749776b..b88dc336097 100644
--- a/src/libcore/panicking.rs
+++ b/src/libcore/panicking.rs
@@ -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!` \
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index be057ed6d59..1219fd09a9d 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -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) }
     }
 
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs
index 1a13ac465f4..5a75730cf2b 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -65,6 +65,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;
diff --git a/src/libcore/ptr/non_null.rs b/src/libcore/ptr/non_null.rs
index 7dcd57f1f98..7599991f0f1 100644
--- a/src/libcore/ptr/non_null.rs
+++ b/src/libcore/ptr/non_null.rs
@@ -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
diff --git a/src/libcore/ptr/unique.rs b/src/libcore/ptr/unique.rs
index 3521dd79979..11a3aed1ab4 100644
--- a/src/libcore/ptr/unique.rs
+++ b/src/libcore/ptr/unique.rs
@@ -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>`.
diff --git a/src/libcore/slice/memchr.rs b/src/libcore/slice/memchr.rs
index 45ab016c496..2a2169dd348 100644
--- a/src/libcore/slice/memchr.rs
+++ b/src/libcore/slice/memchr.rs
@@ -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;
 
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 7655b2f8065..c8fe9f98613 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -1,4 +1,5 @@
 // ignore-tidy-filelength
+// ignore-tidy-undocumented-unsafe
 
 //! Slice management and manipulation.
 //!
diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs
index 2f2170f7ff1..a719a51b616 100644
--- a/src/libcore/slice/sort.rs
+++ b/src/libcore/slice/sort.rs
@@ -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;
diff --git a/src/libcore/str/lossy.rs b/src/libcore/str/lossy.rs
index e8f747f1a67..762de0489a9 100644
--- a/src/libcore/str/lossy.rs
+++ b/src/libcore/str/lossy.rs
@@ -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 {
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 1968919f554..25b7eec5b33 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1,4 +1,5 @@
 // ignore-tidy-filelength
+// ignore-tidy-undocumented-unsafe
 
 //! String manipulation.
 //!
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs
index ad9d956fda1..a494274118a 100644
--- a/src/libcore/str/pattern.rs
+++ b/src/libcore/str/pattern.rs
@@ -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")]
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 73d5abf1aed..d311cb16b64 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -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))]
diff --git a/src/libcore/tests/num/flt2dec/mod.rs b/src/libcore/tests/num/flt2dec/mod.rs
index c41d35efced..a35897e9bc1 100644
--- a/src/libcore/tests/num/flt2dec/mod.rs
+++ b/src/libcore/tests/num/flt2dec/mod.rs
@@ -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) }
 }
 
diff --git a/src/libcore/time.rs b/src/libcore/time.rs
index 5a0e4388e03..57fc1a7b760 100644
--- a/src/libcore/time.rs
+++ b/src/libcore/time.rs
@@ -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])