Have tidy ensure that we document all unsafe blocks in libcore

This commit is contained in:
Oliver Scherer 2019-08-21 19:56:46 +02:00
parent e8b190ac4a
commit 02f9167f94
41 changed files with 137 additions and 5 deletions

View file

@ -1,5 +1,7 @@
//! Memory allocation APIs
// ignore-tidy-undocumented-unsafe
#![stable(feature = "alloc_module", since = "1.28.0")]
use crate::cmp;

View file

@ -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>(),
}
}
}

View file

@ -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(()))

View file

@ -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()]) })
}
}

View file

@ -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>()
};

View file

@ -182,6 +182,8 @@
//! ```
//!
// ignore-tidy-undocumented-unsafe
#![stable(feature = "rust1", since = "1.0.0")]
use crate::cmp::Ordering;

View file

@ -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) })
}
}

View file

@ -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) }))
}
}

View file

@ -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)

View file

@ -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()

View file

@ -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)]

View file

@ -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};

View file

@ -1,5 +1,7 @@
//! Integer and floating-point number formatting
// ignore-tidy-undocumented-unsafe
use crate::fmt;
use crate::ops::{Div, Rem, Sub};

View file

@ -79,6 +79,8 @@
//! }
//! ```
// ignore-tidy-undocumented-unsafe
#![stable(feature = "rust1", since = "1.0.0")]
use crate::fmt;

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -1,3 +1,5 @@
// ignore-tidy-undocumented-unsafe
use crate::cmp;
use super::super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen};

View file

@ -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

View file

@ -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)
}

View file

@ -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

View file

@ -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) }
}

View file

@ -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) }
}

View file

@ -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) }
}
}

View file

@ -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};

View file

@ -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!` \

View file

@ -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) }
}

View file

@ -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;

View file

@ -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

View file

@ -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>`.

View file

@ -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;

View file

@ -1,4 +1,5 @@
// ignore-tidy-filelength
// ignore-tidy-undocumented-unsafe
//! Slice management and manipulation.
//!

View file

@ -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;

View file

@ -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 {

View file

@ -1,4 +1,5 @@
// ignore-tidy-filelength
// ignore-tidy-undocumented-unsafe
//! String manipulation.
//!

View file

@ -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")]

View file

@ -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))]

View file

@ -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) }
}

View file

@ -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])

View file

@ -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,

View file

@ -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"))