From 00a527744c188108fb4f2d6d4bc6b794090ed89a Mon Sep 17 00:00:00 2001 From: Filipe Rodrigues Date: Wed, 21 Oct 2020 00:35:33 +0100 Subject: [PATCH] Now informing the compiler of certain invariants in `AsciiStrArr::len`. Removed certain impossible debug asserts. --- dcb/src/ascii_str_arr.rs | 8 ++++---- dcb/src/lib.rs | 4 +++- dcb/src/util/null_ascii_string.rs | 3 +-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/dcb/src/ascii_str_arr.rs b/dcb/src/ascii_str_arr.rs index 5fec6e9..b564981 100644 --- a/dcb/src/ascii_str_arr.rs +++ b/dcb/src/ascii_str_arr.rs @@ -24,8 +24,7 @@ pub struct AsciiStrArr { chars: [MaybeUninit; N], /// Size - // Invariant `self.len <= N` - // Note: On all methods except `Self::len()`, one should call `self.len()` instead of using `self.len`. + // Invariant: `self.len <= N` len: usize, } @@ -49,6 +48,9 @@ impl AsciiStrArr { /// Returns the length of this string #[must_use] pub const fn len(&self) -> usize { + // Guarantee to the compiler len's invariant + // SAFETY: We guarantee this through a field invariant. + unsafe { std::intrinsics::assume(self.len <= N) }; self.len } @@ -87,7 +89,6 @@ impl AsciiStrArr { // Then get a reference to them // SAFETY: The first `self.len` elements are initialized let chars = unsafe { MaybeUninit::slice_assume_init_ref(chars) }; - debug_assert!(chars.len() == self.len()); <&AsciiStr>::from(chars) } @@ -103,7 +104,6 @@ impl AsciiStrArr { // Then get a mutable reference to them // SAFETY: The first `self.len` elements are initialized let chars = unsafe { MaybeUninit::slice_assume_init_mut(chars) }; - debug_assert!(chars.len() == len); <&mut AsciiStr>::from(chars) } diff --git a/dcb/src/lib.rs b/dcb/src/lib.rs index ae2c007..96f8782 100644 --- a/dcb/src/lib.rs +++ b/dcb/src/lib.rs @@ -45,7 +45,9 @@ maybe_uninit_uninit_array, maybe_uninit_slice, array_map, - const_mut_refs + const_mut_refs, + core_intrinsics, + const_assume )] // Lints #![warn(clippy::restriction, clippy::pedantic, clippy::nursery)] diff --git a/dcb/src/util/null_ascii_string.rs b/dcb/src/util/null_ascii_string.rs index ba8659e..c52cfcc 100644 --- a/dcb/src/util/null_ascii_string.rs +++ b/dcb/src/util/null_ascii_string.rs @@ -42,10 +42,9 @@ macro impl_null_ascii_string($($N:expr),* $(,)?) { #[allow(unused_comparisons)] // With N = 0 this function does nothing fn write_string(&mut self, input: &AsciiStrArr<$N>) { // Copy everything over and set the last byte to 0 - // SAFETY: We guarantee `len <= N`. // Note: No need to override the remaining bytes + // SAFETY: We guarantee `len <= N`. let len = input.len(); - debug_assert!(len <= $N); unsafe { std::intrinsics::copy_nonoverlapping::(input.as_bytes().as_ptr(), self.as_mut_ptr(), len) }; *unsafe { self.get_unchecked_mut(len) } = 0; }