diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 6a2db8f9e..fa1571ff9 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -60,6 +60,12 @@ jobs: # ./generate_ink_example.sh # cd .. # endGroup + # Generate markdown with progress on links for instructions + startGroup "Generate markdown with progress on links for instructions" + cd CoqOfRust/revm/revm_interpreter/instructions/links + python count_admitted.py > progress_on_links.md + cd ../../../../.. + endGroup startGroup "Save space" cargo clean endGroup @@ -69,7 +75,7 @@ jobs: time cargo build touch src/lib.rs time cargo coq-of-rust - rsync -rcv src/ ../../../../CoqOfRust/alloc/ --include='*/' --include='*.v' --exclude='*' + rsync -rcv src/ ../../../../CoqOfRust/alloc/ --include='*/' --include='*.v' --include='*.rs' --exclude='*' cd ../../../.. endGroup startGroup "Translate the core library" @@ -79,7 +85,7 @@ jobs: touch src/lib.rs export RUST_MIN_STACK=800000000 time cargo coq-of-rust - rsync -rcv src/ ../../../../CoqOfRust/core/ --include='*/' --include='*.v' --exclude='*' + rsync -rcv src/ ../../../../CoqOfRust/core/ --include='*/' --include='*.v' --include='*.rs' --exclude='*' cd ../../../.. endGroup startGroup "Save space" @@ -100,42 +106,42 @@ jobs: cargo coq-of-rust touch src/lib.rs cargo coq-of-rust --with-json - rsync -rcv src/ ../../../../CoqOfRust/revm/revm_bytecode/ --include='*/' --include='*.v' --include='*.json' --exclude='*' + rsync -rcv src/ ../../../../CoqOfRust/revm/revm_bytecode/ --include='*/' --include='*.v' --include='*.rs' --include='*.json' --exclude='*' cd .. # context/interface cd context/interface cargo coq-of-rust touch src/lib.rs cargo coq-of-rust --with-json - rsync -rcv src/ ../../../../../CoqOfRust/revm/revm_context_interface/ --include='*/' --include='*.v' --include='*.json' --exclude='*' + rsync -rcv src/ ../../../../../CoqOfRust/revm/revm_context_interface/ --include='*/' --include='*.v' --include='*.rs' --include='*.json' --exclude='*' cd ../.. # interpreter cd interpreter cargo coq-of-rust touch src/lib.rs cargo coq-of-rust --with-json - rsync -rcv src/ ../../../../CoqOfRust/revm/revm_interpreter/ --include='*/' --include='*.v' --include='*.json' --exclude='*' + rsync -rcv src/ ../../../../CoqOfRust/revm/revm_interpreter/ --include='*/' --include='*.v' --include='*.rs' --include='*.json' --exclude='*' cd .. # precompile cd precompile cargo coq-of-rust touch src/lib.rs cargo coq-of-rust --with-json - rsync -rcv src/ ../../../../CoqOfRust/revm/revm_precompile/ --include='*/' --include='*.v' --include='*.json' --exclude='*' + rsync -rcv src/ ../../../../CoqOfRust/revm/revm_precompile/ --include='*/' --include='*.v' --include='*.rs' --include='*.json' --exclude='*' cd .. # primitives cd primitives cargo coq-of-rust touch src/lib.rs cargo coq-of-rust --with-json - rsync -rcv src/ ../../../../CoqOfRust/revm/revm_primitives/ --include='*/' --include='*.v' --include='*.json' --exclude='*' + rsync -rcv src/ ../../../../CoqOfRust/revm/revm_primitives/ --include='*/' --include='*.v' --include='*.rs' --include='*.json' --exclude='*' cd .. # specification cd specification cargo coq-of-rust touch src/lib.rs cargo coq-of-rust --with-json - rsync -rcv src/ ../../../../CoqOfRust/revm/revm_specification/ --include='*/' --include='*.v' --include='*.json' --exclude='*' + rsync -rcv src/ ../../../../CoqOfRust/revm/revm_specification/ --include='*/' --include='*.v' --include='*.rs' --include='*.json' --exclude='*' cd .. cd ../../.. endGroup @@ -145,7 +151,7 @@ jobs: cargo coq-of-rust touch src/lib.rs cargo coq-of-rust - rsync -rcv src/ ../../CoqOfRust/ruint/ --include='*/' --include='*.v' --exclude='*' + rsync -rcv src/ ../../CoqOfRust/ruint/ --include='*/' --include='*.v' --include='*.rs' --exclude='*' cd ../.. endGroup startGroup "Translate Move Sui" @@ -157,35 +163,35 @@ jobs: cargo coq-of-rust touch src/lib.rs cargo coq-of-rust - rsync -rcv src/ ../../../../CoqOfRust/move_sui/translations/move_abstract_stack/ --include='*/' --include='*.v' --exclude='*' + rsync -rcv src/ ../../../../CoqOfRust/move_sui/translations/move_abstract_stack/ --include='*/' --include='*.v' --include='*.rs' --exclude='*' cd .. # move-binary-format cd move-binary-format cargo coq-of-rust touch src/lib.rs cargo coq-of-rust - rsync -rcv src/ ../../../../CoqOfRust/move_sui/translations/move_binary_format/ --include='*/' --include='*.v' --exclude='*' + rsync -rcv src/ ../../../../CoqOfRust/move_sui/translations/move_binary_format/ --include='*/' --include='*.v' --include='*.rs' --exclude='*' cd .. # move-bytecode-verifier cd move-bytecode-verifier cargo coq-of-rust touch src/lib.rs cargo coq-of-rust - rsync -rcv src/ ../../../../CoqOfRust/move_sui/translations/move_bytecode_verifier/ --include='*/' --include='*.v' --exclude='*' + rsync -rcv src/ ../../../../CoqOfRust/move_sui/translations/move_bytecode_verifier/ --include='*/' --include='*.v' --include='*.rs' --exclude='*' cd .. # move-bytecode-verifier-meter cd move-bytecode-verifier-meter cargo coq-of-rust touch src/lib.rs cargo coq-of-rust - rsync -rcv src/ ../../../../CoqOfRust/move_sui/translations/move_bytecode_verifier_meter/ --include='*/' --include='*.v' --exclude='*' + rsync -rcv src/ ../../../../CoqOfRust/move_sui/translations/move_bytecode_verifier_meter/ --include='*/' --include='*.v' --include='*.rs' --exclude='*' cd .. # move-core-types cd move-core-types cargo coq-of-rust touch src/lib.rs cargo coq-of-rust - rsync -rcv src/ ../../../../CoqOfRust/move_sui/translations/move_core_types/ --include='*/' --include='*.v' --exclude='*' + rsync -rcv src/ ../../../../CoqOfRust/move_sui/translations/move_core_types/ --include='*/' --include='*.v' --include='*.rs' --exclude='*' cd .. cd ../../.. endGroup diff --git a/CoqOfRust/alloc/alloc.rs b/CoqOfRust/alloc/alloc.rs new file mode 100644 index 000000000..04b7315e6 --- /dev/null +++ b/CoqOfRust/alloc/alloc.rs @@ -0,0 +1,447 @@ +//! Memory allocation APIs + +#![stable(feature = "alloc_module", since = "1.28.0")] + +#[stable(feature = "alloc_module", since = "1.28.0")] +#[doc(inline)] +pub use core::alloc::*; +#[cfg(not(test))] +use core::hint; +#[cfg(not(test))] +use core::ptr::{self, NonNull}; + +#[cfg(test)] +mod tests; + +extern "Rust" { + // These are the magic symbols to call the global allocator. rustc generates + // them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute + // (the code expanding that attribute macro generates those functions), or to call + // the default implementations in std (`__rdl_alloc` etc. in `library/std/src/alloc.rs`) + // otherwise. + // The rustc fork of LLVM 14 and earlier also special-cases these function names to be able to optimize them + // like `malloc`, `realloc`, and `free`, respectively. + #[rustc_allocator] + #[rustc_nounwind] + fn __rust_alloc(size: usize, align: usize) -> *mut u8; + #[rustc_deallocator] + #[rustc_nounwind] + fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); + #[rustc_reallocator] + #[rustc_nounwind] + fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8; + #[rustc_allocator_zeroed] + #[rustc_nounwind] + fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8; + + static __rust_no_alloc_shim_is_unstable: u8; +} + +/// The global memory allocator. +/// +/// This type implements the [`Allocator`] trait by forwarding calls +/// to the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s default. +/// +/// Note: while this type is unstable, the functionality it provides can be +/// accessed through the [free functions in `alloc`](self#functions). +#[unstable(feature = "allocator_api", issue = "32838")] +#[derive(Copy, Clone, Default, Debug)] +#[cfg(not(test))] +// the compiler needs to know when a Box uses the global allocator vs a custom one +#[lang = "global_alloc_ty"] +pub struct Global; + +#[cfg(test)] +pub use std::alloc::Global; + +/// Allocates memory with the global allocator. +/// +/// This function forwards calls to the [`GlobalAlloc::alloc`] method +/// of the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s default. +/// +/// This function is expected to be deprecated in favor of the `allocate` method +/// of the [`Global`] type when it and the [`Allocator`] trait become stable. +/// +/// # Safety +/// +/// See [`GlobalAlloc::alloc`]. +/// +/// # Examples +/// +/// ``` +/// use std::alloc::{alloc, dealloc, handle_alloc_error, Layout}; +/// +/// unsafe { +/// let layout = Layout::new::(); +/// let ptr = alloc(layout); +/// if ptr.is_null() { +/// handle_alloc_error(layout); +/// } +/// +/// *(ptr as *mut u16) = 42; +/// assert_eq!(*(ptr as *mut u16), 42); +/// +/// dealloc(ptr, layout); +/// } +/// ``` +#[stable(feature = "global_alloc", since = "1.28.0")] +#[must_use = "losing the pointer will leak memory"] +#[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub unsafe fn alloc(layout: Layout) -> *mut u8 { + unsafe { + // Make sure we don't accidentally allow omitting the allocator shim in + // stable code until it is actually stabilized. + core::ptr::read_volatile(&__rust_no_alloc_shim_is_unstable); + + __rust_alloc(layout.size(), layout.align()) + } +} + +/// Deallocates memory with the global allocator. +/// +/// This function forwards calls to the [`GlobalAlloc::dealloc`] method +/// of the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s default. +/// +/// This function is expected to be deprecated in favor of the `deallocate` method +/// of the [`Global`] type when it and the [`Allocator`] trait become stable. +/// +/// # Safety +/// +/// See [`GlobalAlloc::dealloc`]. +#[stable(feature = "global_alloc", since = "1.28.0")] +#[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { + unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } +} + +/// Reallocates memory with the global allocator. +/// +/// This function forwards calls to the [`GlobalAlloc::realloc`] method +/// of the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s default. +/// +/// This function is expected to be deprecated in favor of the `grow` and `shrink` methods +/// of the [`Global`] type when it and the [`Allocator`] trait become stable. +/// +/// # Safety +/// +/// See [`GlobalAlloc::realloc`]. +#[stable(feature = "global_alloc", since = "1.28.0")] +#[must_use = "losing the pointer will leak memory"] +#[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) } +} + +/// Allocates zero-initialized memory with the global allocator. +/// +/// This function forwards calls to the [`GlobalAlloc::alloc_zeroed`] method +/// of the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s default. +/// +/// This function is expected to be deprecated in favor of the `allocate_zeroed` method +/// of the [`Global`] type when it and the [`Allocator`] trait become stable. +/// +/// # Safety +/// +/// See [`GlobalAlloc::alloc_zeroed`]. +/// +/// # Examples +/// +/// ``` +/// use std::alloc::{alloc_zeroed, dealloc, handle_alloc_error, Layout}; +/// +/// unsafe { +/// let layout = Layout::new::(); +/// let ptr = alloc_zeroed(layout); +/// if ptr.is_null() { +/// handle_alloc_error(layout); +/// } +/// +/// assert_eq!(*(ptr as *mut u16), 0); +/// +/// dealloc(ptr, layout); +/// } +/// ``` +#[stable(feature = "global_alloc", since = "1.28.0")] +#[must_use = "losing the pointer will leak memory"] +#[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { + unsafe { + // Make sure we don't accidentally allow omitting the allocator shim in + // stable code until it is actually stabilized. + core::ptr::read_volatile(&__rust_no_alloc_shim_is_unstable); + + __rust_alloc_zeroed(layout.size(), layout.align()) + } +} + +#[cfg(not(test))] +impl Global { + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result, AllocError> { + match layout.size() { + 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), + // SAFETY: `layout` is non-zero in size, + size => unsafe { + let raw_ptr = if zeroed { alloc_zeroed(layout) } else { alloc(layout) }; + let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?; + Ok(NonNull::slice_from_raw_parts(ptr, size)) + }, + } + } + + // SAFETY: Same as `Allocator::grow` + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + unsafe fn grow_impl( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + zeroed: bool, + ) -> Result, AllocError> { + debug_assert!( + new_layout.size() >= old_layout.size(), + "`new_layout.size()` must be greater than or equal to `old_layout.size()`" + ); + + match old_layout.size() { + 0 => self.alloc_impl(new_layout, zeroed), + + // SAFETY: `new_size` is non-zero as `old_size` is greater than or equal to `new_size` + // as required by safety conditions. Other conditions must be upheld by the caller + old_size if old_layout.align() == new_layout.align() => unsafe { + let new_size = new_layout.size(); + + // `realloc` probably checks for `new_size >= old_layout.size()` or something similar. + hint::assert_unchecked(new_size >= old_layout.size()); + + let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size); + let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?; + if zeroed { + raw_ptr.add(old_size).write_bytes(0, new_size - old_size); + } + Ok(NonNull::slice_from_raw_parts(ptr, new_size)) + }, + + // SAFETY: because `new_layout.size()` must be greater than or equal to `old_size`, + // both the old and new memory allocation are valid for reads and writes for `old_size` + // bytes. Also, because the old allocation wasn't yet deallocated, it cannot overlap + // `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract + // for `dealloc` must be upheld by the caller. + old_size => unsafe { + let new_ptr = self.alloc_impl(new_layout, zeroed)?; + ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_size); + self.deallocate(ptr, old_layout); + Ok(new_ptr) + }, + } + } +} + +#[unstable(feature = "allocator_api", issue = "32838")] +#[cfg(not(test))] +unsafe impl Allocator for Global { + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + fn allocate(&self, layout: Layout) -> Result, AllocError> { + self.alloc_impl(layout, false) + } + + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + fn allocate_zeroed(&self, layout: Layout) -> Result, AllocError> { + self.alloc_impl(layout, true) + } + + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + if layout.size() != 0 { + // SAFETY: `layout` is non-zero in size, + // other conditions must be upheld by the caller + unsafe { dealloc(ptr.as_ptr(), layout) } + } + } + + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + unsafe fn grow( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // SAFETY: all conditions must be upheld by the caller + unsafe { self.grow_impl(ptr, old_layout, new_layout, false) } + } + + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + unsafe fn grow_zeroed( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // SAFETY: all conditions must be upheld by the caller + unsafe { self.grow_impl(ptr, old_layout, new_layout, true) } + } + + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + unsafe fn shrink( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + debug_assert!( + new_layout.size() <= old_layout.size(), + "`new_layout.size()` must be smaller than or equal to `old_layout.size()`" + ); + + match new_layout.size() { + // SAFETY: conditions must be upheld by the caller + 0 => unsafe { + self.deallocate(ptr, old_layout); + Ok(NonNull::slice_from_raw_parts(new_layout.dangling(), 0)) + }, + + // SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller + new_size if old_layout.align() == new_layout.align() => unsafe { + // `realloc` probably checks for `new_size <= old_layout.size()` or something similar. + hint::assert_unchecked(new_size <= old_layout.size()); + + let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size); + let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?; + Ok(NonNull::slice_from_raw_parts(ptr, new_size)) + }, + + // SAFETY: because `new_size` must be smaller than or equal to `old_layout.size()`, + // both the old and new memory allocation are valid for reads and writes for `new_size` + // bytes. Also, because the old allocation wasn't yet deallocated, it cannot overlap + // `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract + // for `dealloc` must be upheld by the caller. + new_size => unsafe { + let new_ptr = self.allocate(new_layout)?; + ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), new_size); + self.deallocate(ptr, old_layout); + Ok(new_ptr) + }, + } + } +} + +/// The allocator for unique pointers. +#[cfg(all(not(no_global_oom_handling), not(test)))] +#[lang = "exchange_malloc"] +#[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { + let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; + match Global.allocate(layout) { + Ok(ptr) => ptr.as_mut_ptr(), + Err(_) => handle_alloc_error(layout), + } +} + +// # Allocation error handler + +#[cfg(not(no_global_oom_handling))] +extern "Rust" { + // This is the magic symbol to call the global alloc error handler. rustc generates + // it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the + // default implementations below (`__rdl_oom`) otherwise. + fn __rust_alloc_error_handler(size: usize, align: usize) -> !; +} + +/// Signals a memory allocation error. +/// +/// Callers of memory allocation APIs wishing to cease execution +/// in response to an allocation error are encouraged to call this function, +/// rather than directly invoking [`panic!`] or similar. +/// +/// This function is guaranteed to diverge (not return normally with a value), but depending on +/// global configuration, it may either panic (resulting in unwinding or aborting as per +/// configuration for all panics), or abort the process (with no unwinding). +/// +/// The default behavior is: +/// +/// * If the binary links against `std` (typically the case), then +/// print a message to standard error and abort the process. +/// This behavior can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`]. +/// Future versions of Rust may panic by default instead. +/// +/// * If the binary does not link against `std` (all of its crates are marked +/// [`#![no_std]`][no_std]), then call [`panic!`] with a message. +/// [The panic handler] applies as to any panic. +/// +/// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html +/// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html +/// [The panic handler]: https://doc.rust-lang.org/reference/runtime.html#the-panic_handler-attribute +/// [no_std]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute +#[stable(feature = "global_alloc", since = "1.28.0")] +#[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")] +#[cfg(all(not(no_global_oom_handling), not(test)))] +#[cold] +#[optimize(size)] +pub const fn handle_alloc_error(layout: Layout) -> ! { + const fn ct_error(_: Layout) -> ! { + panic!("allocation failed"); + } + + #[inline] + fn rt_error(layout: Layout) -> ! { + unsafe { + __rust_alloc_error_handler(layout.size(), layout.align()); + } + } + + #[cfg(not(feature = "panic_immediate_abort"))] + { + core::intrinsics::const_eval_select((layout,), ct_error, rt_error) + } + + #[cfg(feature = "panic_immediate_abort")] + ct_error(layout) +} + +// For alloc test `std::alloc::handle_alloc_error` can be used directly. +#[cfg(all(not(no_global_oom_handling), test))] +pub use std::alloc::handle_alloc_error; + +#[cfg(all(not(no_global_oom_handling), not(test)))] +#[doc(hidden)] +#[allow(unused_attributes)] +#[unstable(feature = "alloc_internals", issue = "none")] +pub mod __alloc_error_handler { + // called via generated `__rust_alloc_error_handler` if there is no + // `#[alloc_error_handler]`. + #[rustc_std_internal_symbol] + pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! { + extern "Rust" { + // This symbol is emitted by rustc next to __rust_alloc_error_handler. + // Its value depends on the -Zoom={panic,abort} compiler option. + static __rust_alloc_error_handler_should_panic: u8; + } + + if unsafe { __rust_alloc_error_handler_should_panic != 0 } { + panic!("memory allocation of {size} bytes failed") + } else { + core::panicking::panic_nounwind_fmt( + format_args!("memory allocation of {size} bytes failed"), + /* force_no_backtrace */ false, + ) + } + } +} diff --git a/CoqOfRust/alloc/alloc/tests.rs b/CoqOfRust/alloc/alloc/tests.rs new file mode 100644 index 000000000..5d6077f05 --- /dev/null +++ b/CoqOfRust/alloc/alloc/tests.rs @@ -0,0 +1,30 @@ +use super::*; + +extern crate test; +use test::Bencher; + +use crate::boxed::Box; + +#[test] +fn allocate_zeroed() { + unsafe { + let layout = Layout::from_size_align(1024, 1).unwrap(); + let ptr = + Global.allocate_zeroed(layout.clone()).unwrap_or_else(|_| handle_alloc_error(layout)); + + let mut i = ptr.as_non_null_ptr().as_ptr(); + let end = i.add(layout.size()); + while i < end { + assert_eq!(*i, 0); + i = i.add(1); + } + Global.deallocate(ptr.as_non_null_ptr(), layout); + } +} + +#[bench] +fn alloc_owned_small(b: &mut Bencher) { + b.iter(|| { + let _: Box<_> = Box::new(10); + }) +} diff --git a/CoqOfRust/alloc/borrow.rs b/CoqOfRust/alloc/borrow.rs new file mode 100644 index 000000000..dbfd2e74a --- /dev/null +++ b/CoqOfRust/alloc/borrow.rs @@ -0,0 +1,494 @@ +//! A module for working with borrowed data. + +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::borrow::{Borrow, BorrowMut}; +use core::cmp::Ordering; +use core::hash::{Hash, Hasher}; +#[cfg(not(no_global_oom_handling))] +use core::ops::{Add, AddAssign}; +use core::ops::{Deref, DerefPure}; + +use Cow::*; + +use crate::fmt; +#[cfg(not(no_global_oom_handling))] +use crate::string::String; + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Borrow for Cow<'a, B> +where + B: ToOwned, +{ + fn borrow(&self) -> &B { + &**self + } +} + +/// A generalization of `Clone` to borrowed data. +/// +/// Some types make it possible to go from borrowed to owned, usually by +/// implementing the `Clone` trait. But `Clone` works only for going from `&T` +/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data +/// from any borrow of a given type. +#[cfg_attr(not(test), rustc_diagnostic_item = "ToOwned")] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait ToOwned { + /// The resulting type after obtaining ownership. + #[stable(feature = "rust1", since = "1.0.0")] + type Owned: Borrow; + + /// Creates owned data from borrowed data, usually by cloning. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s: &str = "a"; + /// let ss: String = s.to_owned(); + /// + /// let v: &[i32] = &[1, 2]; + /// let vv: Vec = v.to_owned(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "cloning is often expensive and is not expected to have side effects"] + #[cfg_attr(not(test), rustc_diagnostic_item = "to_owned_method")] + fn to_owned(&self) -> Self::Owned; + + /// Uses borrowed data to replace owned data, usually by cloning. + /// + /// This is borrow-generalized version of [`Clone::clone_from`]. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s: String = String::new(); + /// "hello".clone_into(&mut s); + /// + /// let mut v: Vec = Vec::new(); + /// [1, 2][..].clone_into(&mut v); + /// ``` + #[stable(feature = "toowned_clone_into", since = "1.63.0")] + fn clone_into(&self, target: &mut Self::Owned) { + *target = self.to_owned(); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for T +where + T: Clone, +{ + type Owned = T; + fn to_owned(&self) -> T { + self.clone() + } + + fn clone_into(&self, target: &mut T) { + target.clone_from(self); + } +} + +/// A clone-on-write smart pointer. +/// +/// The type `Cow` is a smart pointer providing clone-on-write functionality: it +/// can enclose and provide immutable access to borrowed data, and clone the +/// data lazily when mutation or ownership is required. The type is designed to +/// work with general borrowed data via the `Borrow` trait. +/// +/// `Cow` implements `Deref`, which means that you can call +/// non-mutating methods directly on the data it encloses. If mutation +/// is desired, `to_mut` will obtain a mutable reference to an owned +/// value, cloning if necessary. +/// +/// If you need reference-counting pointers, note that +/// [`Rc::make_mut`][crate::rc::Rc::make_mut] and +/// [`Arc::make_mut`][crate::sync::Arc::make_mut] can provide clone-on-write +/// functionality as well. +/// +/// # Examples +/// +/// ``` +/// use std::borrow::Cow; +/// +/// fn abs_all(input: &mut Cow<'_, [i32]>) { +/// for i in 0..input.len() { +/// let v = input[i]; +/// if v < 0 { +/// // Clones into a vector if not already owned. +/// input.to_mut()[i] = -v; +/// } +/// } +/// } +/// +/// // No clone occurs because `input` doesn't need to be mutated. +/// let slice = [0, 1, 2]; +/// let mut input = Cow::from(&slice[..]); +/// abs_all(&mut input); +/// +/// // Clone occurs because `input` needs to be mutated. +/// let slice = [-1, 0, 1]; +/// let mut input = Cow::from(&slice[..]); +/// abs_all(&mut input); +/// +/// // No clone occurs because `input` is already owned. +/// let mut input = Cow::from(vec![-1, 0, 1]); +/// abs_all(&mut input); +/// ``` +/// +/// Another example showing how to keep `Cow` in a struct: +/// +/// ``` +/// use std::borrow::Cow; +/// +/// struct Items<'a, X> where [X]: ToOwned> { +/// values: Cow<'a, [X]>, +/// } +/// +/// impl<'a, X: Clone + 'a> Items<'a, X> where [X]: ToOwned> { +/// fn new(v: Cow<'a, [X]>) -> Self { +/// Items { values: v } +/// } +/// } +/// +/// // Creates a container from borrowed values of a slice +/// let readonly = [1, 2]; +/// let borrowed = Items::new((&readonly[..]).into()); +/// match borrowed { +/// Items { values: Cow::Borrowed(b) } => println!("borrowed {b:?}"), +/// _ => panic!("expect borrowed value"), +/// } +/// +/// let mut clone_on_write = borrowed; +/// // Mutates the data from slice into owned vec and pushes a new value on top +/// clone_on_write.values.to_mut().push(3); +/// println!("clone_on_write = {:?}", clone_on_write.values); +/// +/// // The data was mutated. Let's check it out. +/// match clone_on_write { +/// Items { values: Cow::Owned(_) } => println!("clone_on_write contains owned data"), +/// _ => panic!("expect owned data"), +/// } +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Cow")] +pub enum Cow<'a, B: ?Sized + 'a> +where + B: ToOwned, +{ + /// Borrowed data. + #[stable(feature = "rust1", since = "1.0.0")] + Borrowed(#[stable(feature = "rust1", since = "1.0.0")] &'a B), + + /// Owned data. + #[stable(feature = "rust1", since = "1.0.0")] + Owned(#[stable(feature = "rust1", since = "1.0.0")] ::Owned), +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Cow<'_, B> { + fn clone(&self) -> Self { + match *self { + Borrowed(b) => Borrowed(b), + Owned(ref o) => { + let b: &B = o.borrow(); + Owned(b.to_owned()) + } + } + } + + fn clone_from(&mut self, source: &Self) { + match (self, source) { + (&mut Owned(ref mut dest), &Owned(ref o)) => o.borrow().clone_into(dest), + (t, s) => *t = s.clone(), + } + } +} + +impl Cow<'_, B> { + /// Returns true if the data is borrowed, i.e. if `to_mut` would require additional work. + /// + /// # Examples + /// + /// ``` + /// #![feature(cow_is_borrowed)] + /// use std::borrow::Cow; + /// + /// let cow = Cow::Borrowed("moo"); + /// assert!(cow.is_borrowed()); + /// + /// let bull: Cow<'_, str> = Cow::Owned("...moo?".to_string()); + /// assert!(!bull.is_borrowed()); + /// ``` + #[unstable(feature = "cow_is_borrowed", issue = "65143")] + pub const fn is_borrowed(&self) -> bool { + match *self { + Borrowed(_) => true, + Owned(_) => false, + } + } + + /// Returns true if the data is owned, i.e. if `to_mut` would be a no-op. + /// + /// # Examples + /// + /// ``` + /// #![feature(cow_is_borrowed)] + /// use std::borrow::Cow; + /// + /// let cow: Cow<'_, str> = Cow::Owned("moo".to_string()); + /// assert!(cow.is_owned()); + /// + /// let bull = Cow::Borrowed("...moo?"); + /// assert!(!bull.is_owned()); + /// ``` + #[unstable(feature = "cow_is_borrowed", issue = "65143")] + pub const fn is_owned(&self) -> bool { + !self.is_borrowed() + } + + /// Acquires a mutable reference to the owned form of the data. + /// + /// Clones the data if it is not already owned. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::Cow; + /// + /// let mut cow = Cow::Borrowed("foo"); + /// cow.to_mut().make_ascii_uppercase(); + /// + /// assert_eq!( + /// cow, + /// Cow::Owned(String::from("FOO")) as Cow<'_, str> + /// ); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn to_mut(&mut self) -> &mut ::Owned { + match *self { + Borrowed(borrowed) => { + *self = Owned(borrowed.to_owned()); + match *self { + Borrowed(..) => unreachable!(), + Owned(ref mut owned) => owned, + } + } + Owned(ref mut owned) => owned, + } + } + + /// Extracts the owned data. + /// + /// Clones the data if it is not already owned. + /// + /// # Examples + /// + /// Calling `into_owned` on a `Cow::Borrowed` returns a clone of the borrowed data: + /// + /// ``` + /// use std::borrow::Cow; + /// + /// let s = "Hello world!"; + /// let cow = Cow::Borrowed(s); + /// + /// assert_eq!( + /// cow.into_owned(), + /// String::from(s) + /// ); + /// ``` + /// + /// Calling `into_owned` on a `Cow::Owned` returns the owned data. The data is moved out of the + /// `Cow` without being cloned. + /// + /// ``` + /// use std::borrow::Cow; + /// + /// let s = "Hello world!"; + /// let cow: Cow<'_, str> = Cow::Owned(String::from(s)); + /// + /// assert_eq!( + /// cow.into_owned(), + /// String::from(s) + /// ); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_owned(self) -> ::Owned { + match self { + Borrowed(borrowed) => borrowed.to_owned(), + Owned(owned) => owned, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for Cow<'_, B> +where + B::Owned: Borrow, +{ + type Target = B; + + fn deref(&self) -> &B { + match *self { + Borrowed(borrowed) => borrowed, + Owned(ref owned) => owned.borrow(), + } + } +} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for Cow<'_, B> where B::Owned: Borrow {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Cow<'_, B> where B: Eq + ToOwned {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Cow<'_, B> +where + B: Ord + ToOwned, +{ + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq> for Cow<'a, B> +where + B: PartialEq + ToOwned, + C: ToOwned, +{ + #[inline] + fn eq(&self, other: &Cow<'b, C>) -> bool { + PartialEq::eq(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> +where + B: PartialOrd + ToOwned, +{ + #[inline] + fn partial_cmp(&self, other: &Cow<'a, B>) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Cow<'_, B> +where + B: fmt::Debug + ToOwned, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Borrowed(ref b) => fmt::Debug::fmt(b, f), + Owned(ref o) => fmt::Debug::fmt(o, f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Cow<'_, B> +where + B: fmt::Display + ToOwned, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Borrowed(ref b) => fmt::Display::fmt(b, f), + Owned(ref o) => fmt::Display::fmt(o, f), + } + } +} + +#[stable(feature = "default", since = "1.11.0")] +impl Default for Cow<'_, B> +where + B: ToOwned, +{ + /// Creates an owned Cow<'a, B> with the default value for the contained owned value. + fn default() -> Self { + Owned(::Owned::default()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Cow<'_, B> +where + B: Hash + ToOwned, +{ + #[inline] + fn hash(&self, state: &mut H) { + Hash::hash(&**self, state) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for Cow<'_, T> { + fn as_ref(&self) -> &T { + self + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_add", since = "1.14.0")] +impl<'a> Add<&'a str> for Cow<'a, str> { + type Output = Cow<'a, str>; + + #[inline] + fn add(mut self, rhs: &'a str) -> Self::Output { + self += rhs; + self + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_add", since = "1.14.0")] +impl<'a> Add> for Cow<'a, str> { + type Output = Cow<'a, str>; + + #[inline] + fn add(mut self, rhs: Cow<'a, str>) -> Self::Output { + self += rhs; + self + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_add", since = "1.14.0")] +impl<'a> AddAssign<&'a str> for Cow<'a, str> { + fn add_assign(&mut self, rhs: &'a str) { + if self.is_empty() { + *self = Cow::Borrowed(rhs) + } else if !rhs.is_empty() { + if let Cow::Borrowed(lhs) = *self { + let mut s = String::with_capacity(lhs.len() + rhs.len()); + s.push_str(lhs); + *self = Cow::Owned(s); + } + self.to_mut().push_str(rhs); + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_add", since = "1.14.0")] +impl<'a> AddAssign> for Cow<'a, str> { + fn add_assign(&mut self, rhs: Cow<'a, str>) { + if self.is_empty() { + *self = rhs + } else if !rhs.is_empty() { + if let Cow::Borrowed(lhs) = *self { + let mut s = String::with_capacity(lhs.len() + rhs.len()); + s.push_str(lhs); + *self = Cow::Owned(s); + } + self.to_mut().push_str(&rhs); + } + } +} diff --git a/CoqOfRust/alloc/boxed.rs b/CoqOfRust/alloc/boxed.rs new file mode 100644 index 000000000..e0f94428c --- /dev/null +++ b/CoqOfRust/alloc/boxed.rs @@ -0,0 +1,2136 @@ +//! The `Box` type for heap allocation. +//! +//! [`Box`], casually referred to as a 'box', provides the simplest form of +//! heap allocation in Rust. Boxes provide ownership for this allocation, and +//! drop their contents when they go out of scope. Boxes also ensure that they +//! never allocate more than `isize::MAX` bytes. +//! +//! # Examples +//! +//! Move a value from the stack to the heap by creating a [`Box`]: +//! +//! ``` +//! let val: u8 = 5; +//! let boxed: Box = Box::new(val); +//! ``` +//! +//! Move a value from a [`Box`] back to the stack by [dereferencing]: +//! +//! ``` +//! let boxed: Box = Box::new(5); +//! let val: u8 = *boxed; +//! ``` +//! +//! Creating a recursive data structure: +//! +//! ``` +//! ##[allow(dead_code)] +//! #[derive(Debug)] +//! enum List { +//! Cons(T, Box>), +//! Nil, +//! } +//! +//! let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil)))); +//! println!("{list:?}"); +//! ``` +//! +//! This will print `Cons(1, Cons(2, Nil))`. +//! +//! Recursive structures must be boxed, because if the definition of `Cons` +//! looked like this: +//! +//! ```compile_fail,E0072 +//! # enum List { +//! Cons(T, List), +//! # } +//! ``` +//! +//! It wouldn't work. This is because the size of a `List` depends on how many +//! elements are in the list, and so we don't know how much memory to allocate +//! for a `Cons`. By introducing a [`Box`], which has a defined size, we know how +//! big `Cons` needs to be. +//! +//! # Memory layout +//! +//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for its allocation. It is +//! valid to convert both ways between a [`Box`] and a raw pointer allocated with the [`Global`] +//! allocator, given that the [`Layout`] used with the allocator is correct for the type and the raw +//! pointer points to a valid value of the right type. More precisely, a `value: *mut T` that has +//! been allocated with the [`Global`] allocator with `Layout::for_value(&*value)` may be converted +//! into a box using [`Box::::from_raw(value)`]. Conversely, the memory backing a `value: *mut T` +//! obtained from [`Box::::into_raw`] may be deallocated using the [`Global`] allocator with +//! [`Layout::for_value(&*value)`]. +//! +//! For zero-sized values, the `Box` pointer has to be non-null and sufficiently aligned. The +//! recommended way to build a Box to a ZST if `Box::new` cannot be used is to use +//! [`ptr::NonNull::dangling`]. +//! +//! On top of these basic layout requirements, a `Box` must point to a valid value of `T`. +//! +//! So long as `T: Sized`, a `Box` is guaranteed to be represented +//! as a single pointer and is also ABI-compatible with C pointers +//! (i.e. the C type `T*`). This means that if you have extern "C" +//! Rust functions that will be called from C, you can define those +//! Rust functions using `Box` types, and use `T*` as corresponding +//! type on the C side. As an example, consider this C header which +//! declares functions that create and destroy some kind of `Foo` +//! value: +//! +//! ```c +//! /* C header */ +//! +//! /* Returns ownership to the caller */ +//! struct Foo* foo_new(void); +//! +//! /* Takes ownership from the caller; no-op when invoked with null */ +//! void foo_delete(struct Foo*); +//! ``` +//! +//! These two functions might be implemented in Rust as follows. Here, the +//! `struct Foo*` type from C is translated to `Box`, which captures +//! the ownership constraints. Note also that the nullable argument to +//! `foo_delete` is represented in Rust as `Option>`, since `Box` +//! cannot be null. +//! +//! ``` +//! #[repr(C)] +//! pub struct Foo; +//! +//! #[no_mangle] +//! pub extern "C" fn foo_new() -> Box { +//! Box::new(Foo) +//! } +//! +//! #[no_mangle] +//! pub extern "C" fn foo_delete(_: Option>) {} +//! ``` +//! +//! Even though `Box` has the same representation and C ABI as a C pointer, +//! this does not mean that you can convert an arbitrary `T*` into a `Box` +//! and expect things to work. `Box` values will always be fully aligned, +//! non-null pointers. Moreover, the destructor for `Box` will attempt to +//! free the value with the global allocator. In general, the best practice +//! is to only use `Box` for pointers that originated from the global +//! allocator. +//! +//! **Important.** At least at present, you should avoid using +//! `Box` types for functions that are defined in C but invoked +//! from Rust. In those cases, you should directly mirror the C types +//! as closely as possible. Using types like `Box` where the C +//! definition is just using `T*` can lead to undefined behavior, as +//! described in [rust-lang/unsafe-code-guidelines#198][ucg#198]. +//! +//! # Considerations for unsafe code +//! +//! **Warning: This section is not normative and is subject to change, possibly +//! being relaxed in the future! It is a simplified summary of the rules +//! currently implemented in the compiler.** +//! +//! The aliasing rules for `Box` are the same as for `&mut T`. `Box` +//! asserts uniqueness over its content. Using raw pointers derived from a box +//! after that box has been mutated through, moved or borrowed as `&mut T` +//! is not allowed. For more guidance on working with box from unsafe code, see +//! [rust-lang/unsafe-code-guidelines#326][ucg#326]. +//! +//! # Editions +//! +//! A special case exists for the implementation of `IntoIterator` for arrays on the Rust 2021 +//! edition, as documented [here][array]. Unfortunately, it was later found that a similar +//! workaround should be added for boxed slices, and this was applied in the 2024 edition. +//! +//! Specifically, `IntoIterator` is implemented for `Box<[T]>` on all editions, but specific calls +//! to `into_iter()` for boxed slices will defer to the slice implementation on editions before +//! 2024: +//! +//! ```rust,edition2021 +//! // Rust 2015, 2018, and 2021: +//! +//! # #![allow(boxed_slice_into_iter)] // override our `deny(warnings)` +//! let boxed_slice: Box<[i32]> = vec![0; 3].into_boxed_slice(); +//! +//! // This creates a slice iterator, producing references to each value. +//! for item in boxed_slice.into_iter().enumerate() { +//! let (i, x): (usize, &i32) = item; +//! println!("boxed_slice[{i}] = {x}"); +//! } +//! +//! // The `boxed_slice_into_iter` lint suggests this change for future compatibility: +//! for item in boxed_slice.iter().enumerate() { +//! let (i, x): (usize, &i32) = item; +//! println!("boxed_slice[{i}] = {x}"); +//! } +//! +//! // You can explicitly iterate a boxed slice by value using `IntoIterator::into_iter` +//! for item in IntoIterator::into_iter(boxed_slice).enumerate() { +//! let (i, x): (usize, i32) = item; +//! println!("boxed_slice[{i}] = {x}"); +//! } +//! ``` +//! +//! Similar to the array implementation, this may be modified in the future to remove this override, +//! and it's best to avoid relying on this edition-dependent behavior if you wish to preserve +//! compatibility with future versions of the compiler. +//! +//! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198 +//! [ucg#326]: https://github.com/rust-lang/unsafe-code-guidelines/issues/326 +//! [dereferencing]: core::ops::Deref +//! [`Box::::from_raw(value)`]: Box::from_raw +//! [`Global`]: crate::alloc::Global +//! [`Layout`]: crate::alloc::Layout +//! [`Layout::for_value(&*value)`]: crate::alloc::Layout::for_value +//! [valid]: ptr#safety + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::borrow::{Borrow, BorrowMut}; +#[cfg(not(no_global_oom_handling))] +use core::clone::CloneToUninit; +use core::cmp::Ordering; +use core::error::{self, Error}; +use core::fmt; +use core::future::Future; +use core::hash::{Hash, Hasher}; +use core::marker::{PointerLike, Tuple, Unsize}; +use core::mem::{self, SizedTypeProperties}; +use core::ops::{ + AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, + DerefPure, DispatchFromDyn, LegacyReceiver, +}; +use core::pin::{Pin, PinCoerceUnsized}; +use core::ptr::{self, NonNull, Unique}; +use core::task::{Context, Poll}; + +#[cfg(not(no_global_oom_handling))] +use crate::alloc::handle_alloc_error; +use crate::alloc::{AllocError, Allocator, Global, Layout}; +use crate::raw_vec::RawVec; +#[cfg(not(no_global_oom_handling))] +use crate::str::from_boxed_utf8_unchecked; + +/// Conversion related impls for `Box<_>` (`From`, `downcast`, etc) +mod convert; +/// Iterator related impls for `Box<_>`. +mod iter; +/// [`ThinBox`] implementation. +mod thin; + +#[unstable(feature = "thin_box", issue = "92791")] +pub use thin::ThinBox; + +/// A pointer type that uniquely owns a heap allocation of type `T`. +/// +/// See the [module-level documentation](../../std/boxed/index.html) for more. +#[lang = "owned_box"] +#[fundamental] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_insignificant_dtor] +#[doc(search_unbox)] +// The declaration of the `Box` struct must be kept in sync with the +// compiler or ICEs will happen. +pub struct Box< + T: ?Sized, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +>(Unique, A); + +impl Box { + /// Allocates memory on the heap and then places `x` into it. + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// let five = Box::new(5); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline(always)] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + #[rustc_diagnostic_item = "box_new"] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn new(x: T) -> Self { + #[rustc_box] + Box::new(x) + } + + /// Constructs a new box with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// let mut five = Box::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "new_uninit", since = "1.82.0")] + #[must_use] + #[inline] + pub fn new_uninit() -> Box> { + Self::new_uninit_in(Global) + } + + /// Constructs a new `Box` with uninitialized contents, with the memory + /// being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_zeroed_alloc)] + /// + /// let zero = Box::::new_zeroed(); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[inline] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] + #[must_use] + pub fn new_zeroed() -> Box> { + Self::new_zeroed_in(Global) + } + + /// Constructs a new `Pin>`. If `T` does not implement [`Unpin`], then + /// `x` will be pinned in memory and unable to be moved. + /// + /// Constructing and pinning of the `Box` can also be done in two steps: `Box::pin(x)` + /// does the same as [Box::into_pin]\([Box::new]\(x)). Consider using + /// [`into_pin`](Box::into_pin) if you already have a `Box`, or if you want to + /// construct a (pinned) `Box` in a different way than with [`Box::new`]. + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "pin", since = "1.33.0")] + #[must_use] + #[inline(always)] + pub fn pin(x: T) -> Pin> { + Box::new(x).into() + } + + /// Allocates memory on the heap then places `x` into it, + /// returning an error if the allocation fails + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// let five = Box::try_new(5)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new(x: T) -> Result { + Self::try_new_in(x, Global) + } + + /// Constructs a new box with uninitialized contents on the heap, + /// returning an error if the allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// let mut five = Box::::try_new_uninit()?; + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn try_new_uninit() -> Result>, AllocError> { + Box::try_new_uninit_in(Global) + } + + /// Constructs a new `Box` with uninitialized contents, with the memory + /// being filled with `0` bytes on the heap + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// let zero = Box::::try_new_zeroed()?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn try_new_zeroed() -> Result>, AllocError> { + Box::try_new_zeroed_in(Global) + } +} + +impl Box { + /// Allocates memory in the given allocator then places `x` into it. + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let five = Box::new_in(5, System); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] + #[inline] + pub fn new_in(x: T, alloc: A) -> Self + where + A: Allocator, + { + let mut boxed = Self::new_uninit_in(alloc); + unsafe { + boxed.as_mut_ptr().write(x); + boxed.assume_init() + } + } + + /// Allocates memory in the given allocator then places `x` into it, + /// returning an error if the allocation fails + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let five = Box::try_new_in(5, System)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new_in(x: T, alloc: A) -> Result + where + A: Allocator, + { + let mut boxed = Self::try_new_uninit_in(alloc)?; + unsafe { + boxed.as_mut_ptr().write(x); + Ok(boxed.assume_init()) + } + } + + /// Constructs a new box with uninitialized contents in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let mut five = Box::::new_uninit_in(System); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[cfg(not(no_global_oom_handling))] + #[must_use] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_in(alloc: A) -> Box, A> + where + A: Allocator, + { + let layout = Layout::new::>(); + // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. + // That would make code size bigger. + match Box::try_new_uninit_in(alloc) { + Ok(m) => m, + Err(_) => handle_alloc_error(layout), + } + } + + /// Constructs a new box with uninitialized contents in the provided allocator, + /// returning an error if the allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let mut five = Box::::try_new_uninit_in(System)?; + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> + where + A: Allocator, + { + let ptr = if T::IS_ZST { + NonNull::dangling() + } else { + let layout = Layout::new::>(); + alloc.allocate(layout)?.cast() + }; + unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } + } + + /// Constructs a new `Box` with uninitialized contents, with the memory + /// being filled with `0` bytes in the provided allocator. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let zero = Box::::new_zeroed_in(System); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + #[cfg(not(no_global_oom_handling))] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] + pub fn new_zeroed_in(alloc: A) -> Box, A> + where + A: Allocator, + { + let layout = Layout::new::>(); + // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. + // That would make code size bigger. + match Box::try_new_zeroed_in(alloc) { + Ok(m) => m, + Err(_) => handle_alloc_error(layout), + } + } + + /// Constructs a new `Box` with uninitialized contents, with the memory + /// being filled with `0` bytes in the provided allocator, + /// returning an error if the allocation fails, + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let zero = Box::::try_new_zeroed_in(System)?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> + where + A: Allocator, + { + let ptr = if T::IS_ZST { + NonNull::dangling() + } else { + let layout = Layout::new::>(); + alloc.allocate_zeroed(layout)?.cast() + }; + unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } + } + + /// Constructs a new `Pin>`. If `T` does not implement [`Unpin`], then + /// `x` will be pinned in memory and unable to be moved. + /// + /// Constructing and pinning of the `Box` can also be done in two steps: `Box::pin_in(x, alloc)` + /// does the same as [Box::into_pin]\([Box::new_in]\(x, alloc)). Consider using + /// [`into_pin`](Box::into_pin) if you already have a `Box`, or if you want to + /// construct a (pinned) `Box` in a different way than with [`Box::new_in`]. + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] + #[inline(always)] + pub fn pin_in(x: T, alloc: A) -> Pin + where + A: 'static + Allocator, + { + Self::into_pin(Self::new_in(x, alloc)) + } + + /// Converts a `Box` into a `Box<[T]>` + /// + /// This conversion does not allocate on the heap and happens in place. + #[unstable(feature = "box_into_boxed_slice", issue = "71582")] + pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> { + let (raw, alloc) = Box::into_raw_with_allocator(boxed); + unsafe { Box::from_raw_in(raw as *mut [T; 1], alloc) } + } + + /// Consumes the `Box`, returning the wrapped value. + /// + /// # Examples + /// + /// ``` + /// #![feature(box_into_inner)] + /// + /// let c = Box::new(5); + /// + /// assert_eq!(Box::into_inner(c), 5); + /// ``` + #[unstable(feature = "box_into_inner", issue = "80437")] + #[inline] + pub fn into_inner(boxed: Self) -> T { + *boxed + } +} + +impl Box<[T]> { + /// Constructs a new boxed slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// let mut values = Box::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "new_uninit", since = "1.82.0")] + #[must_use] + pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { + unsafe { RawVec::with_capacity(len).into_box(len) } + } + + /// Constructs a new boxed slice with uninitialized contents, with the memory + /// being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_zeroed_alloc)] + /// + /// let values = Box::<[u32]>::new_zeroed_slice(3); + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] + #[must_use] + pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit]> { + unsafe { RawVec::with_capacity_zeroed(len).into_box(len) } + } + + /// Constructs a new boxed slice with uninitialized contents. Returns an error if + /// the allocation fails. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// let mut values = Box::<[u32]>::try_new_uninit_slice(3)?; + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new_uninit_slice(len: usize) -> Result]>, AllocError> { + let ptr = if T::IS_ZST || len == 0 { + NonNull::dangling() + } else { + let layout = match Layout::array::>(len) { + Ok(l) => l, + Err(_) => return Err(AllocError), + }; + Global.allocate(layout)?.cast() + }; + unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) } + } + + /// Constructs a new boxed slice with uninitialized contents, with the memory + /// being filled with `0` bytes. Returns an error if the allocation fails. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// let values = Box::<[u32]>::try_new_zeroed_slice(3)?; + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new_zeroed_slice(len: usize) -> Result]>, AllocError> { + let ptr = if T::IS_ZST || len == 0 { + NonNull::dangling() + } else { + let layout = match Layout::array::>(len) { + Ok(l) => l, + Err(_) => return Err(AllocError), + }; + Global.allocate_zeroed(layout)?.cast() + }; + unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) } + } +} + +impl Box<[T], A> { + /// Constructs a new boxed slice with uninitialized contents in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let mut values = Box::<[u32], _>::new_uninit_slice_in(3, System); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] + pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { + unsafe { RawVec::with_capacity_in(len, alloc).into_box(len) } + } + + /// Constructs a new boxed slice with uninitialized contents in the provided allocator, + /// with the memory being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let values = Box::<[u32], _>::new_zeroed_slice_in(3, System); + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] + pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { + unsafe { RawVec::with_capacity_zeroed_in(len, alloc).into_box(len) } + } + + /// Constructs a new boxed slice with uninitialized contents in the provided allocator. Returns an error if + /// the allocation fails. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let mut values = Box::<[u32], _>::try_new_uninit_slice_in(3, System)?; + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new_uninit_slice_in( + len: usize, + alloc: A, + ) -> Result], A>, AllocError> { + let ptr = if T::IS_ZST || len == 0 { + NonNull::dangling() + } else { + let layout = match Layout::array::>(len) { + Ok(l) => l, + Err(_) => return Err(AllocError), + }; + alloc.allocate(layout)?.cast() + }; + unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, alloc).into_box(len)) } + } + + /// Constructs a new boxed slice with uninitialized contents in the provided allocator, with the memory + /// being filled with `0` bytes. Returns an error if the allocation fails. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let values = Box::<[u32], _>::try_new_zeroed_slice_in(3, System)?; + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new_zeroed_slice_in( + len: usize, + alloc: A, + ) -> Result], A>, AllocError> { + let ptr = if T::IS_ZST || len == 0 { + NonNull::dangling() + } else { + let layout = match Layout::array::>(len) { + Ok(l) => l, + Err(_) => return Err(AllocError), + }; + alloc.allocate_zeroed(layout)?.cast() + }; + unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, alloc).into_box(len)) } + } +} + +impl Box, A> { + /// Converts to `Box`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + /// + /// # Examples + /// + /// ``` + /// let mut five = Box::::new_uninit(); + /// + /// let five: Box = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[stable(feature = "new_uninit", since = "1.82.0")] + #[inline] + pub unsafe fn assume_init(self) -> Box { + let (raw, alloc) = Box::into_raw_with_allocator(self); + unsafe { Box::from_raw_in(raw as *mut T, alloc) } + } + + /// Writes the value and converts to `Box`. + /// + /// This method converts the box similarly to [`Box::assume_init`] but + /// writes `value` into it before conversion thus guaranteeing safety. + /// In some scenarios use of this method may improve performance because + /// the compiler may be able to optimize copying from stack. + /// + /// # Examples + /// + /// ``` + /// #![feature(box_uninit_write)] + /// + /// let big_box = Box::<[usize; 1024]>::new_uninit(); + /// + /// let mut array = [0; 1024]; + /// for (i, place) in array.iter_mut().enumerate() { + /// *place = i; + /// } + /// + /// // The optimizer may be able to elide this copy, so previous code writes + /// // to heap directly. + /// let big_box = Box::write(big_box, array); + /// + /// for (i, x) in big_box.iter().enumerate() { + /// assert_eq!(*x, i); + /// } + /// ``` + #[unstable(feature = "box_uninit_write", issue = "129397")] + #[inline] + pub fn write(mut boxed: Self, value: T) -> Box { + unsafe { + (*boxed).write(value); + boxed.assume_init() + } + } +} + +impl Box<[mem::MaybeUninit], A> { + /// Converts to `Box<[T], A>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the values + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + /// + /// # Examples + /// + /// ``` + /// let mut values = Box::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[stable(feature = "new_uninit", since = "1.82.0")] + #[inline] + pub unsafe fn assume_init(self) -> Box<[T], A> { + let (raw, alloc) = Box::into_raw_with_allocator(self); + unsafe { Box::from_raw_in(raw as *mut [T], alloc) } + } +} + +impl Box { + /// Constructs a box from a raw pointer. + /// + /// After calling this function, the raw pointer is owned by the + /// resulting `Box`. Specifically, the `Box` destructor will call + /// the destructor of `T` and free the allocated memory. For this + /// to be safe, the memory must have been allocated in accordance + /// with the [memory layout] used by `Box` . + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, a double-free may occur if the + /// function is called twice on the same raw pointer. + /// + /// The safety conditions are described in the [memory layout] section. + /// + /// # Examples + /// + /// Recreate a `Box` which was previously converted to a raw pointer + /// using [`Box::into_raw`]: + /// ``` + /// let x = Box::new(5); + /// let ptr = Box::into_raw(x); + /// let x = unsafe { Box::from_raw(ptr) }; + /// ``` + /// Manually create a `Box` from scratch by using the global allocator: + /// ``` + /// use std::alloc::{alloc, Layout}; + /// + /// unsafe { + /// let ptr = alloc(Layout::new::()) as *mut i32; + /// // In general .write is required to avoid attempting to destruct + /// // the (uninitialized) previous contents of `ptr`, though for this + /// // simple example `*ptr = 5` would have worked as well. + /// ptr.write(5); + /// let x = Box::from_raw(ptr); + /// } + /// ``` + /// + /// [memory layout]: self#memory-layout + /// [`Layout`]: crate::Layout + #[stable(feature = "box_raw", since = "1.4.0")] + #[inline] + #[must_use = "call `drop(Box::from_raw(ptr))` if you intend to drop the `Box`"] + pub unsafe fn from_raw(raw: *mut T) -> Self { + unsafe { Self::from_raw_in(raw, Global) } + } + + /// Constructs a box from a `NonNull` pointer. + /// + /// After calling this function, the `NonNull` pointer is owned by + /// the resulting `Box`. Specifically, the `Box` destructor will call + /// the destructor of `T` and free the allocated memory. For this + /// to be safe, the memory must have been allocated in accordance + /// with the [memory layout] used by `Box` . + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, a double-free may occur if the + /// function is called twice on the same `NonNull` pointer. + /// + /// The safety conditions are described in the [memory layout] section. + /// + /// # Examples + /// + /// Recreate a `Box` which was previously converted to a `NonNull` + /// pointer using [`Box::into_non_null`]: + /// ``` + /// #![feature(box_vec_non_null)] + /// + /// let x = Box::new(5); + /// let non_null = Box::into_non_null(x); + /// let x = unsafe { Box::from_non_null(non_null) }; + /// ``` + /// Manually create a `Box` from scratch by using the global allocator: + /// ``` + /// #![feature(box_vec_non_null)] + /// + /// use std::alloc::{alloc, Layout}; + /// use std::ptr::NonNull; + /// + /// unsafe { + /// let non_null = NonNull::new(alloc(Layout::new::()).cast::()) + /// .expect("allocation failed"); + /// // In general .write is required to avoid attempting to destruct + /// // the (uninitialized) previous contents of `non_null`. + /// non_null.write(5); + /// let x = Box::from_non_null(non_null); + /// } + /// ``` + /// + /// [memory layout]: self#memory-layout + /// [`Layout`]: crate::Layout + #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + #[inline] + #[must_use = "call `drop(Box::from_non_null(ptr))` if you intend to drop the `Box`"] + pub unsafe fn from_non_null(ptr: NonNull) -> Self { + unsafe { Self::from_raw(ptr.as_ptr()) } + } +} + +impl Box { + /// Constructs a box from a raw pointer in the given allocator. + /// + /// After calling this function, the raw pointer is owned by the + /// resulting `Box`. Specifically, the `Box` destructor will call + /// the destructor of `T` and free the allocated memory. For this + /// to be safe, the memory must have been allocated in accordance + /// with the [memory layout] used by `Box` . + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, a double-free may occur if the + /// function is called twice on the same raw pointer. + /// + /// + /// # Examples + /// + /// Recreate a `Box` which was previously converted to a raw pointer + /// using [`Box::into_raw_with_allocator`]: + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let x = Box::new_in(5, System); + /// let (ptr, alloc) = Box::into_raw_with_allocator(x); + /// let x = unsafe { Box::from_raw_in(ptr, alloc) }; + /// ``` + /// Manually create a `Box` from scratch by using the system allocator: + /// ``` + /// #![feature(allocator_api, slice_ptr_get)] + /// + /// use std::alloc::{Allocator, Layout, System}; + /// + /// unsafe { + /// let ptr = System.allocate(Layout::new::())?.as_mut_ptr() as *mut i32; + /// // In general .write is required to avoid attempting to destruct + /// // the (uninitialized) previous contents of `ptr`, though for this + /// // simple example `*ptr = 5` would have worked as well. + /// ptr.write(5); + /// let x = Box::from_raw_in(ptr, System); + /// } + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [memory layout]: self#memory-layout + /// [`Layout`]: crate::Layout + #[unstable(feature = "allocator_api", issue = "32838")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] + #[inline] + pub const unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { + Box(unsafe { Unique::new_unchecked(raw) }, alloc) + } + + /// Constructs a box from a `NonNull` pointer in the given allocator. + /// + /// After calling this function, the `NonNull` pointer is owned by + /// the resulting `Box`. Specifically, the `Box` destructor will call + /// the destructor of `T` and free the allocated memory. For this + /// to be safe, the memory must have been allocated in accordance + /// with the [memory layout] used by `Box` . + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, a double-free may occur if the + /// function is called twice on the same raw pointer. + /// + /// + /// # Examples + /// + /// Recreate a `Box` which was previously converted to a `NonNull` pointer + /// using [`Box::into_non_null_with_allocator`]: + /// ``` + /// #![feature(allocator_api, box_vec_non_null)] + /// + /// use std::alloc::System; + /// + /// let x = Box::new_in(5, System); + /// let (non_null, alloc) = Box::into_non_null_with_allocator(x); + /// let x = unsafe { Box::from_non_null_in(non_null, alloc) }; + /// ``` + /// Manually create a `Box` from scratch by using the system allocator: + /// ``` + /// #![feature(allocator_api, box_vec_non_null, slice_ptr_get)] + /// + /// use std::alloc::{Allocator, Layout, System}; + /// + /// unsafe { + /// let non_null = System.allocate(Layout::new::())?.cast::(); + /// // In general .write is required to avoid attempting to destruct + /// // the (uninitialized) previous contents of `non_null`. + /// non_null.write(5); + /// let x = Box::from_non_null_in(non_null, System); + /// } + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [memory layout]: self#memory-layout + /// [`Layout`]: crate::Layout + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] + #[inline] + pub const unsafe fn from_non_null_in(raw: NonNull, alloc: A) -> Self { + // SAFETY: guaranteed by the caller. + unsafe { Box::from_raw_in(raw.as_ptr(), alloc) } + } + + /// Consumes the `Box`, returning a wrapped raw pointer. + /// + /// The pointer will be properly aligned and non-null. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Box`. In particular, the + /// caller should properly destroy `T` and release the memory, taking + /// into account the [memory layout] used by `Box`. The easiest way to + /// do this is to convert the raw pointer back into a `Box` with the + /// [`Box::from_raw`] function, allowing the `Box` destructor to perform + /// the cleanup. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// Converting the raw pointer back into a `Box` with [`Box::from_raw`] + /// for automatic cleanup: + /// ``` + /// let x = Box::new(String::from("Hello")); + /// let ptr = Box::into_raw(x); + /// let x = unsafe { Box::from_raw(ptr) }; + /// ``` + /// Manual cleanup by explicitly running the destructor and deallocating + /// the memory: + /// ``` + /// use std::alloc::{dealloc, Layout}; + /// use std::ptr; + /// + /// let x = Box::new(String::from("Hello")); + /// let ptr = Box::into_raw(x); + /// unsafe { + /// ptr::drop_in_place(ptr); + /// dealloc(ptr as *mut u8, Layout::new::()); + /// } + /// ``` + /// Note: This is equivalent to the following: + /// ``` + /// let x = Box::new(String::from("Hello")); + /// let ptr = Box::into_raw(x); + /// unsafe { + /// drop(Box::from_raw(ptr)); + /// } + /// ``` + /// + /// [memory layout]: self#memory-layout + #[must_use = "losing the pointer will leak memory"] + #[stable(feature = "box_raw", since = "1.4.0")] + #[inline] + pub fn into_raw(b: Self) -> *mut T { + // Make sure Miri realizes that we transition from a noalias pointer to a raw pointer here. + unsafe { &raw mut *&mut *Self::into_raw_with_allocator(b).0 } + } + + /// Consumes the `Box`, returning a wrapped `NonNull` pointer. + /// + /// The pointer will be properly aligned. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Box`. In particular, the + /// caller should properly destroy `T` and release the memory, taking + /// into account the [memory layout] used by `Box`. The easiest way to + /// do this is to convert the `NonNull` pointer back into a `Box` with the + /// [`Box::from_non_null`] function, allowing the `Box` destructor to + /// perform the cleanup. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::into_non_null(b)` instead of `b.into_non_null()`. + /// This is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// Converting the `NonNull` pointer back into a `Box` with [`Box::from_non_null`] + /// for automatic cleanup: + /// ``` + /// #![feature(box_vec_non_null)] + /// + /// let x = Box::new(String::from("Hello")); + /// let non_null = Box::into_non_null(x); + /// let x = unsafe { Box::from_non_null(non_null) }; + /// ``` + /// Manual cleanup by explicitly running the destructor and deallocating + /// the memory: + /// ``` + /// #![feature(box_vec_non_null)] + /// + /// use std::alloc::{dealloc, Layout}; + /// + /// let x = Box::new(String::from("Hello")); + /// let non_null = Box::into_non_null(x); + /// unsafe { + /// non_null.drop_in_place(); + /// dealloc(non_null.as_ptr().cast::(), Layout::new::()); + /// } + /// ``` + /// Note: This is equivalent to the following: + /// ``` + /// #![feature(box_vec_non_null)] + /// + /// let x = Box::new(String::from("Hello")); + /// let non_null = Box::into_non_null(x); + /// unsafe { + /// drop(Box::from_non_null(non_null)); + /// } + /// ``` + /// + /// [memory layout]: self#memory-layout + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + #[inline] + pub fn into_non_null(b: Self) -> NonNull { + // SAFETY: `Box` is guaranteed to be non-null. + unsafe { NonNull::new_unchecked(Self::into_raw(b)) } + } + + /// Consumes the `Box`, returning a wrapped raw pointer and the allocator. + /// + /// The pointer will be properly aligned and non-null. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Box`. In particular, the + /// caller should properly destroy `T` and release the memory, taking + /// into account the [memory layout] used by `Box`. The easiest way to + /// do this is to convert the raw pointer back into a `Box` with the + /// [`Box::from_raw_in`] function, allowing the `Box` destructor to perform + /// the cleanup. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::into_raw_with_allocator(b)` instead of `b.into_raw_with_allocator()`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// Converting the raw pointer back into a `Box` with [`Box::from_raw_in`] + /// for automatic cleanup: + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let x = Box::new_in(String::from("Hello"), System); + /// let (ptr, alloc) = Box::into_raw_with_allocator(x); + /// let x = unsafe { Box::from_raw_in(ptr, alloc) }; + /// ``` + /// Manual cleanup by explicitly running the destructor and deallocating + /// the memory: + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::{Allocator, Layout, System}; + /// use std::ptr::{self, NonNull}; + /// + /// let x = Box::new_in(String::from("Hello"), System); + /// let (ptr, alloc) = Box::into_raw_with_allocator(x); + /// unsafe { + /// ptr::drop_in_place(ptr); + /// let non_null = NonNull::new_unchecked(ptr); + /// alloc.deallocate(non_null.cast(), Layout::new::()); + /// } + /// ``` + /// + /// [memory layout]: self#memory-layout + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) { + let mut b = mem::ManuallyDrop::new(b); + // We carefully get the raw pointer out in a way that Miri's aliasing model understands what + // is happening: using the primitive "deref" of `Box`. In case `A` is *not* `Global`, we + // want *no* aliasing requirements here! + // In case `A` *is* `Global`, this does not quite have the right behavior; `into_raw` + // works around that. + let ptr = &raw mut **b; + let alloc = unsafe { ptr::read(&b.1) }; + (ptr, alloc) + } + + /// Consumes the `Box`, returning a wrapped `NonNull` pointer and the allocator. + /// + /// The pointer will be properly aligned. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Box`. In particular, the + /// caller should properly destroy `T` and release the memory, taking + /// into account the [memory layout] used by `Box`. The easiest way to + /// do this is to convert the `NonNull` pointer back into a `Box` with the + /// [`Box::from_non_null_in`] function, allowing the `Box` destructor to + /// perform the cleanup. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::into_non_null_with_allocator(b)` instead of + /// `b.into_non_null_with_allocator()`. This is so that there is no + /// conflict with a method on the inner type. + /// + /// # Examples + /// Converting the `NonNull` pointer back into a `Box` with + /// [`Box::from_non_null_in`] for automatic cleanup: + /// ``` + /// #![feature(allocator_api, box_vec_non_null)] + /// + /// use std::alloc::System; + /// + /// let x = Box::new_in(String::from("Hello"), System); + /// let (non_null, alloc) = Box::into_non_null_with_allocator(x); + /// let x = unsafe { Box::from_non_null_in(non_null, alloc) }; + /// ``` + /// Manual cleanup by explicitly running the destructor and deallocating + /// the memory: + /// ``` + /// #![feature(allocator_api, box_vec_non_null)] + /// + /// use std::alloc::{Allocator, Layout, System}; + /// + /// let x = Box::new_in(String::from("Hello"), System); + /// let (non_null, alloc) = Box::into_non_null_with_allocator(x); + /// unsafe { + /// non_null.drop_in_place(); + /// alloc.deallocate(non_null.cast::(), Layout::new::()); + /// } + /// ``` + /// + /// [memory layout]: self#memory-layout + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + #[inline] + pub fn into_non_null_with_allocator(b: Self) -> (NonNull, A) { + let (ptr, alloc) = Box::into_raw_with_allocator(b); + // SAFETY: `Box` is guaranteed to be non-null. + unsafe { (NonNull::new_unchecked(ptr), alloc) } + } + + #[unstable( + feature = "ptr_internals", + issue = "none", + reason = "use `Box::leak(b).into()` or `Unique::from(Box::leak(b))` instead" + )] + #[inline] + #[doc(hidden)] + pub fn into_unique(b: Self) -> (Unique, A) { + let (ptr, alloc) = Box::into_raw_with_allocator(b); + unsafe { (Unique::from(&mut *ptr), alloc) } + } + + /// Returns a raw mutable pointer to the `Box`'s contents. + /// + /// The caller must ensure that the `Box` outlives the pointer this + /// function returns, or else it will end up dangling. + /// + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying memory, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`]. + /// Note that calling other methods that materialize references to the memory + /// may still invalidate this pointer. + /// See the example below for how this guarantee can be used. + /// + /// # Examples + /// + /// Due to the aliasing guarantee, the following code is legal: + /// + /// ```rust + /// #![feature(box_as_ptr)] + /// + /// unsafe { + /// let mut b = Box::new(0); + /// let ptr1 = Box::as_mut_ptr(&mut b); + /// ptr1.write(1); + /// let ptr2 = Box::as_mut_ptr(&mut b); + /// ptr2.write(2); + /// // Notably, the write to `ptr2` did *not* invalidate `ptr1`: + /// ptr1.write(3); + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Self::as_mut_ptr + /// [`as_ptr`]: Self::as_ptr + #[unstable(feature = "box_as_ptr", issue = "129090")] + #[rustc_never_returns_null_ptr] + #[rustc_as_ptr] + #[inline] + pub fn as_mut_ptr(b: &mut Self) -> *mut T { + // This is a primitive deref, not going through `DerefMut`, and therefore not materializing + // any references. + &raw mut **b + } + + /// Returns a raw pointer to the `Box`'s contents. + /// + /// The caller must ensure that the `Box` outlives the pointer this + /// function returns, or else it will end up dangling. + /// + /// The caller must also ensure that the memory the pointer (non-transitively) points to + /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer + /// derived from it. If you need to mutate the contents of the `Box`, use [`as_mut_ptr`]. + /// + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying memory, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`]. + /// Note that calling other methods that materialize mutable references to the memory, + /// as well as writing to this memory, may still invalidate this pointer. + /// See the example below for how this guarantee can be used. + /// + /// # Examples + /// + /// Due to the aliasing guarantee, the following code is legal: + /// + /// ```rust + /// #![feature(box_as_ptr)] + /// + /// unsafe { + /// let mut v = Box::new(0); + /// let ptr1 = Box::as_ptr(&v); + /// let ptr2 = Box::as_mut_ptr(&mut v); + /// let _val = ptr2.read(); + /// // No write to this memory has happened yet, so `ptr1` is still valid. + /// let _val = ptr1.read(); + /// // However, once we do a write... + /// ptr2.write(1); + /// // ... `ptr1` is no longer valid. + /// // This would be UB: let _val = ptr1.read(); + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Self::as_mut_ptr + /// [`as_ptr`]: Self::as_ptr + #[unstable(feature = "box_as_ptr", issue = "129090")] + #[rustc_never_returns_null_ptr] + #[rustc_as_ptr] + #[inline] + pub fn as_ptr(b: &Self) -> *const T { + // This is a primitive deref, not going through `DerefMut`, and therefore not materializing + // any references. + &raw const **b + } + + /// Returns a reference to the underlying allocator. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::allocator(&b)` instead of `b.allocator()`. This + /// is so that there is no conflict with a method on the inner type. + #[unstable(feature = "allocator_api", issue = "32838")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] + #[inline] + pub const fn allocator(b: &Self) -> &A { + &b.1 + } + + /// Consumes and leaks the `Box`, returning a mutable reference, + /// `&'a mut T`. + /// + /// Note that the type `T` must outlive the chosen lifetime `'a`. If the type + /// has only static references, or none at all, then this may be chosen to be + /// `'static`. + /// + /// This function is mainly useful for data that lives for the remainder of + /// the program's life. Dropping the returned reference will cause a memory + /// leak. If this is not acceptable, the reference should first be wrapped + /// with the [`Box::from_raw`] function producing a `Box`. This `Box` can + /// then be dropped which will properly destroy `T` and release the + /// allocated memory. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::leak(b)` instead of `b.leak()`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// + /// Simple usage: + /// + /// ``` + /// let x = Box::new(41); + /// let static_ref: &'static mut usize = Box::leak(x); + /// *static_ref += 1; + /// assert_eq!(*static_ref, 42); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # drop(unsafe { Box::from_raw(static_ref) }); + /// ``` + /// + /// Unsized data: + /// + /// ``` + /// let x = vec![1, 2, 3].into_boxed_slice(); + /// let static_ref = Box::leak(x); + /// static_ref[0] = 4; + /// assert_eq!(*static_ref, [4, 2, 3]); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # drop(unsafe { Box::from_raw(static_ref) }); + /// ``` + #[stable(feature = "box_leak", since = "1.26.0")] + #[inline] + pub fn leak<'a>(b: Self) -> &'a mut T + where + A: 'a, + { + unsafe { &mut *Box::into_raw(b) } + } + + /// Converts a `Box` into a `Pin>`. If `T` does not implement [`Unpin`], then + /// `*boxed` will be pinned in memory and unable to be moved. + /// + /// This conversion does not allocate on the heap and happens in place. + /// + /// This is also available via [`From`]. + /// + /// Constructing and pinning a `Box` with Box::into_pin([Box::new]\(x)) + /// can also be written more concisely using [Box::pin]\(x). + /// This `into_pin` method is useful if you already have a `Box`, or you are + /// constructing a (pinned) `Box` in a different way than with [`Box::new`]. + /// + /// # Notes + /// + /// It's not recommended that crates add an impl like `From> for Pin`, + /// as it'll introduce an ambiguity when calling `Pin::from`. + /// A demonstration of such a poor impl is shown below. + /// + /// ```compile_fail + /// # use std::pin::Pin; + /// struct Foo; // A type defined in this crate. + /// impl From> for Pin { + /// fn from(_: Box<()>) -> Pin { + /// Pin::new(Foo) + /// } + /// } + /// + /// let foo = Box::new(()); + /// let bar = Pin::from(foo); + /// ``` + #[stable(feature = "box_into_pin", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] + pub const fn into_pin(boxed: Self) -> Pin + where + A: 'static, + { + // It's not possible to move or replace the insides of a `Pin>` + // when `T: !Unpin`, so it's safe to pin it directly without any + // additional requirements. + unsafe { Pin::new_unchecked(boxed) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box { + #[inline] + fn drop(&mut self) { + // the T in the Box is dropped by the compiler before the destructor is run + + let ptr = self.0; + + unsafe { + let layout = Layout::for_value_raw(ptr.as_ptr()); + if layout.size() != 0 { + self.1.deallocate(From::from(ptr.cast()), layout); + } + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Box { + /// Creates a `Box`, with the `Default` value for T. + #[inline] + fn default() -> Self { + Box::write(Box::new_uninit(), T::default()) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Box<[T]> { + #[inline] + fn default() -> Self { + let ptr: Unique<[T]> = Unique::<[T; 0]>::dangling(); + Box(ptr, Global) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "default_box_extra", since = "1.17.0")] +impl Default for Box { + #[inline] + fn default() -> Self { + // SAFETY: This is the same as `Unique::cast` but with an unsized `U = str`. + let ptr: Unique = unsafe { + let bytes: Unique<[u8]> = Unique::<[u8; 0]>::dangling(); + Unique::new_unchecked(bytes.as_ptr() as *mut str) + }; + Box(ptr, Global) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Box { + /// Returns a new box with a `clone()` of this box's contents. + /// + /// # Examples + /// + /// ``` + /// let x = Box::new(5); + /// let y = x.clone(); + /// + /// // The value is the same + /// assert_eq!(x, y); + /// + /// // But they are unique objects + /// assert_ne!(&*x as *const i32, &*y as *const i32); + /// ``` + #[inline] + fn clone(&self) -> Self { + // Pre-allocate memory to allow writing the cloned value directly. + let mut boxed = Self::new_uninit_in(self.1.clone()); + unsafe { + (**self).clone_to_uninit(boxed.as_mut_ptr().cast()); + boxed.assume_init() + } + } + + /// Copies `source`'s contents into `self` without creating a new allocation. + /// + /// # Examples + /// + /// ``` + /// let x = Box::new(5); + /// let mut y = Box::new(10); + /// let yp: *const i32 = &*y; + /// + /// y.clone_from(&x); + /// + /// // The value is the same + /// assert_eq!(x, y); + /// + /// // And no allocation occurred + /// assert_eq!(yp, &*y); + /// ``` + #[inline] + fn clone_from(&mut self, source: &Self) { + (**self).clone_from(&(**source)); + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_slice_clone", since = "1.3.0")] +impl Clone for Box<[T], A> { + fn clone(&self) -> Self { + let alloc = Box::allocator(self).clone(); + self.to_vec_in(alloc).into_boxed_slice() + } + + /// Copies `source`'s contents into `self` without creating a new allocation, + /// so long as the two are of the same length. + /// + /// # Examples + /// + /// ``` + /// let x = Box::new([5, 6, 7]); + /// let mut y = Box::new([8, 9, 10]); + /// let yp: *const [i32] = &*y; + /// + /// y.clone_from(&x); + /// + /// // The value is the same + /// assert_eq!(x, y); + /// + /// // And no allocation occurred + /// assert_eq!(yp, &*y); + /// ``` + fn clone_from(&mut self, source: &Self) { + if self.len() == source.len() { + self.clone_from_slice(&source); + } else { + *self = source.clone(); + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_slice_clone", since = "1.3.0")] +impl Clone for Box { + fn clone(&self) -> Self { + // this makes a copy of the data + let buf: Box<[u8]> = self.as_bytes().into(); + unsafe { from_boxed_utf8_unchecked(buf) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for Box { + #[inline] + fn eq(&self, other: &Self) -> bool { + PartialEq::eq(&**self, &**other) + } + #[inline] + fn ne(&self, other: &Self) -> bool { + PartialEq::ne(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Box { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } + #[inline] + fn lt(&self, other: &Self) -> bool { + PartialOrd::lt(&**self, &**other) + } + #[inline] + fn le(&self, other: &Self) -> bool { + PartialOrd::le(&**self, &**other) + } + #[inline] + fn ge(&self, other: &Self) -> bool { + PartialOrd::ge(&**self, &**other) + } + #[inline] + fn gt(&self, other: &Self) -> bool { + PartialOrd::gt(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Box { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Box {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Box { + fn hash(&self, state: &mut H) { + (**self).hash(state); + } +} + +#[stable(feature = "indirect_hasher_impl", since = "1.22.0")] +impl Hasher for Box { + fn finish(&self) -> u64 { + (**self).finish() + } + fn write(&mut self, bytes: &[u8]) { + (**self).write(bytes) + } + fn write_u8(&mut self, i: u8) { + (**self).write_u8(i) + } + fn write_u16(&mut self, i: u16) { + (**self).write_u16(i) + } + fn write_u32(&mut self, i: u32) { + (**self).write_u32(i) + } + fn write_u64(&mut self, i: u64) { + (**self).write_u64(i) + } + fn write_u128(&mut self, i: u128) { + (**self).write_u128(i) + } + fn write_usize(&mut self, i: usize) { + (**self).write_usize(i) + } + fn write_i8(&mut self, i: i8) { + (**self).write_i8(i) + } + fn write_i16(&mut self, i: i16) { + (**self).write_i16(i) + } + fn write_i32(&mut self, i: i32) { + (**self).write_i32(i) + } + fn write_i64(&mut self, i: i64) { + (**self).write_i64(i) + } + fn write_i128(&mut self, i: i128) { + (**self).write_i128(i) + } + fn write_isize(&mut self, i: isize) { + (**self).write_isize(i) + } + fn write_length_prefix(&mut self, len: usize) { + (**self).write_length_prefix(len) + } + fn write_str(&mut self, s: &str) { + (**self).write_str(s) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Box { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Box { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Pointer for Box { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // It's not possible to extract the inner Uniq directly from the Box, + // instead we cast it to a *const which aliases the Unique + let ptr: *const T = &**self; + fmt::Pointer::fmt(&ptr, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for Box { + type Target = T; + + fn deref(&self) -> &T { + &**self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DerefMut for Box { + fn deref_mut(&mut self) -> &mut T { + &mut **self + } +} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for Box {} + +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +impl LegacyReceiver for Box {} + +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl + ?Sized, A: Allocator> FnOnce for Box { + type Output = >::Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output { + >::call_once(*self, args) + } +} + +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl + ?Sized, A: Allocator> FnMut for Box { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { + >::call_mut(self, args) + } +} + +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl + ?Sized, A: Allocator> Fn for Box { + extern "rust-call" fn call(&self, args: Args) -> Self::Output { + >::call(self, args) + } +} + +#[unstable(feature = "async_fn_traits", issue = "none")] +impl + ?Sized, A: Allocator> AsyncFnOnce for Box { + type Output = F::Output; + type CallOnceFuture = F::CallOnceFuture; + + extern "rust-call" fn async_call_once(self, args: Args) -> Self::CallOnceFuture { + F::async_call_once(*self, args) + } +} + +#[unstable(feature = "async_fn_traits", issue = "none")] +impl + ?Sized, A: Allocator> AsyncFnMut for Box { + type CallRefFuture<'a> + = F::CallRefFuture<'a> + where + Self: 'a; + + extern "rust-call" fn async_call_mut(&mut self, args: Args) -> Self::CallRefFuture<'_> { + F::async_call_mut(self, args) + } +} + +#[unstable(feature = "async_fn_traits", issue = "none")] +impl + ?Sized, A: Allocator> AsyncFn for Box { + extern "rust-call" fn async_call(&self, args: Args) -> Self::CallRefFuture<'_> { + F::async_call(self, args) + } +} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U: ?Sized, A: Allocator> CoerceUnsized> for Box {} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Box {} + +// It is quite crucial that we only allow the `Global` allocator here. +// Handling arbitrary custom allocators (which can affect the `Box` layout heavily!) +// would need a lot of codegen and interpreter adjustments. +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for Box {} + +#[stable(feature = "box_borrow", since = "1.1.0")] +impl Borrow for Box { + fn borrow(&self) -> &T { + &**self + } +} + +#[stable(feature = "box_borrow", since = "1.1.0")] +impl BorrowMut for Box { + fn borrow_mut(&mut self) -> &mut T { + &mut **self + } +} + +#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] +impl AsRef for Box { + fn as_ref(&self) -> &T { + &**self + } +} + +#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] +impl AsMut for Box { + fn as_mut(&mut self) -> &mut T { + &mut **self + } +} + +/* Nota bene + * + * We could have chosen not to add this impl, and instead have written a + * function of Pin> to Pin. Such a function would not be sound, + * because Box implements Unpin even when T does not, as a result of + * this impl. + * + * We chose this API instead of the alternative for a few reasons: + * - Logically, it is helpful to understand pinning in regard to the + * memory region being pointed to. For this reason none of the + * standard library pointer types support projecting through a pin + * (Box is the only pointer type in std for which this would be + * safe.) + * - It is in practice very useful to have Box be unconditionally + * Unpin because of trait objects, for which the structural auto + * trait functionality does not apply (e.g., Box would + * otherwise not be Unpin). + * + * Another type with the same semantics as Box but only a conditional + * implementation of `Unpin` (where `T: Unpin`) would be valid/safe, and + * could have a method to project a Pin from it. + */ +#[stable(feature = "pin", since = "1.33.0")] +impl Unpin for Box {} + +#[unstable(feature = "coroutine_trait", issue = "43122")] +impl + Unpin, R, A: Allocator> Coroutine for Box { + type Yield = G::Yield; + type Return = G::Return; + + fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState { + G::resume(Pin::new(&mut *self), arg) + } +} + +#[unstable(feature = "coroutine_trait", issue = "43122")] +impl, R, A: Allocator> Coroutine for Pin> +where + A: 'static, +{ + type Yield = G::Yield; + type Return = G::Return; + + fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState { + G::resume((*self).as_mut(), arg) + } +} + +#[stable(feature = "futures_api", since = "1.36.0")] +impl Future for Box { + type Output = F::Output; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + F::poll(Pin::new(&mut *self), cx) + } +} + +#[stable(feature = "box_error", since = "1.8.0")] +impl Error for Box { + #[allow(deprecated, deprecated_in_future)] + fn description(&self) -> &str { + Error::description(&**self) + } + + #[allow(deprecated)] + fn cause(&self) -> Option<&dyn Error> { + Error::cause(&**self) + } + + fn source(&self) -> Option<&(dyn Error + 'static)> { + Error::source(&**self) + } + + fn provide<'b>(&'b self, request: &mut error::Request<'b>) { + Error::provide(&**self, request); + } +} + +#[unstable(feature = "pointer_like_trait", issue = "none")] +impl PointerLike for Box {} diff --git a/CoqOfRust/alloc/boxed/convert.rs b/CoqOfRust/alloc/boxed/convert.rs new file mode 100644 index 000000000..255cefb1e --- /dev/null +++ b/CoqOfRust/alloc/boxed/convert.rs @@ -0,0 +1,792 @@ +use core::any::Any; +use core::error::Error; +use core::mem; +use core::pin::Pin; +#[cfg(not(no_global_oom_handling))] +use core::{fmt, ptr}; + +use crate::alloc::Allocator; +#[cfg(not(no_global_oom_handling))] +use crate::borrow::Cow; +use crate::boxed::Box; +#[cfg(not(no_global_oom_handling))] +use crate::raw_vec::RawVec; +#[cfg(not(no_global_oom_handling))] +use crate::str::from_boxed_utf8_unchecked; +#[cfg(not(no_global_oom_handling))] +use crate::string::String; +#[cfg(not(no_global_oom_handling))] +use crate::vec::Vec; + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "from_for_ptrs", since = "1.6.0")] +impl From for Box { + /// Converts a `T` into a `Box` + /// + /// The conversion allocates on the heap and moves `t` + /// from the stack into it. + /// + /// # Examples + /// + /// ```rust + /// let x = 5; + /// let boxed = Box::new(5); + /// + /// assert_eq!(Box::from(x), boxed); + /// ``` + fn from(t: T) -> Self { + Box::new(t) + } +} + +#[stable(feature = "pin", since = "1.33.0")] +impl From> for Pin> +where + A: 'static, +{ + /// Converts a `Box` into a `Pin>`. If `T` does not implement [`Unpin`], then + /// `*boxed` will be pinned in memory and unable to be moved. + /// + /// This conversion does not allocate on the heap and happens in place. + /// + /// This is also available via [`Box::into_pin`]. + /// + /// Constructing and pinning a `Box` with >>::from([Box::new]\(x)) + /// can also be written more concisely using [Box::pin]\(x). + /// This `From` implementation is useful if you already have a `Box`, or you are + /// constructing a (pinned) `Box` in a different way than with [`Box::new`]. + fn from(boxed: Box) -> Self { + Box::into_pin(boxed) + } +} + +/// Specialization trait used for `From<&[T]>`. +#[cfg(not(no_global_oom_handling))] +trait BoxFromSlice { + fn from_slice(slice: &[T]) -> Self; +} + +#[cfg(not(no_global_oom_handling))] +impl BoxFromSlice for Box<[T]> { + #[inline] + default fn from_slice(slice: &[T]) -> Self { + slice.to_vec().into_boxed_slice() + } +} + +#[cfg(not(no_global_oom_handling))] +impl BoxFromSlice for Box<[T]> { + #[inline] + fn from_slice(slice: &[T]) -> Self { + let len = slice.len(); + let buf = RawVec::with_capacity(len); + unsafe { + ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len); + buf.into_box(slice.len()).assume_init() + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_slice", since = "1.17.0")] +impl From<&[T]> for Box<[T]> { + /// Converts a `&[T]` into a `Box<[T]>` + /// + /// This conversion allocates on the heap + /// and performs a copy of `slice` and its contents. + /// + /// # Examples + /// ```rust + /// // create a &[u8] which will be used to create a Box<[u8]> + /// let slice: &[u8] = &[104, 101, 108, 108, 111]; + /// let boxed_slice: Box<[u8]> = Box::from(slice); + /// + /// println!("{boxed_slice:?}"); + /// ``` + #[inline] + fn from(slice: &[T]) -> Box<[T]> { + >::from_slice(slice) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_mut_slice", since = "1.84.0")] +impl From<&mut [T]> for Box<[T]> { + /// Converts a `&mut [T]` into a `Box<[T]>` + /// + /// This conversion allocates on the heap + /// and performs a copy of `slice` and its contents. + /// + /// # Examples + /// ```rust + /// // create a &mut [u8] which will be used to create a Box<[u8]> + /// let mut array = [104, 101, 108, 108, 111]; + /// let slice: &mut [u8] = &mut array; + /// let boxed_slice: Box<[u8]> = Box::from(slice); + /// + /// println!("{boxed_slice:?}"); + /// ``` + #[inline] + fn from(slice: &mut [T]) -> Box<[T]> { + Self::from(&*slice) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_cow", since = "1.45.0")] +impl From> for Box<[T]> { + /// Converts a `Cow<'_, [T]>` into a `Box<[T]>` + /// + /// When `cow` is the `Cow::Borrowed` variant, this + /// conversion allocates on the heap and copies the + /// underlying slice. Otherwise, it will try to reuse the owned + /// `Vec`'s allocation. + #[inline] + fn from(cow: Cow<'_, [T]>) -> Box<[T]> { + match cow { + Cow::Borrowed(slice) => Box::from(slice), + Cow::Owned(slice) => Box::from(slice), + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_slice", since = "1.17.0")] +impl From<&str> for Box { + /// Converts a `&str` into a `Box` + /// + /// This conversion allocates on the heap + /// and performs a copy of `s`. + /// + /// # Examples + /// + /// ```rust + /// let boxed: Box = Box::from("hello"); + /// println!("{boxed}"); + /// ``` + #[inline] + fn from(s: &str) -> Box { + unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_mut_slice", since = "1.84.0")] +impl From<&mut str> for Box { + /// Converts a `&mut str` into a `Box` + /// + /// This conversion allocates on the heap + /// and performs a copy of `s`. + /// + /// # Examples + /// + /// ```rust + /// let mut original = String::from("hello"); + /// let original: &mut str = &mut original; + /// let boxed: Box = Box::from(original); + /// println!("{boxed}"); + /// ``` + #[inline] + fn from(s: &mut str) -> Box { + Self::from(&*s) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_cow", since = "1.45.0")] +impl From> for Box { + /// Converts a `Cow<'_, str>` into a `Box` + /// + /// When `cow` is the `Cow::Borrowed` variant, this + /// conversion allocates on the heap and copies the + /// underlying `str`. Otherwise, it will try to reuse the owned + /// `String`'s allocation. + /// + /// # Examples + /// + /// ```rust + /// use std::borrow::Cow; + /// + /// let unboxed = Cow::Borrowed("hello"); + /// let boxed: Box = Box::from(unboxed); + /// println!("{boxed}"); + /// ``` + /// + /// ```rust + /// # use std::borrow::Cow; + /// let unboxed = Cow::Owned("hello".to_string()); + /// let boxed: Box = Box::from(unboxed); + /// println!("{boxed}"); + /// ``` + #[inline] + fn from(cow: Cow<'_, str>) -> Box { + match cow { + Cow::Borrowed(s) => Box::from(s), + Cow::Owned(s) => Box::from(s), + } + } +} + +#[stable(feature = "boxed_str_conv", since = "1.19.0")] +impl From> for Box<[u8], A> { + /// Converts a `Box` into a `Box<[u8]>` + /// + /// This conversion does not allocate on the heap and happens in place. + /// + /// # Examples + /// ```rust + /// // create a Box which will be used to create a Box<[u8]> + /// let boxed: Box = Box::from("hello"); + /// let boxed_str: Box<[u8]> = Box::from(boxed); + /// + /// // create a &[u8] which will be used to create a Box<[u8]> + /// let slice: &[u8] = &[104, 101, 108, 108, 111]; + /// let boxed_slice = Box::from(slice); + /// + /// assert_eq!(boxed_slice, boxed_str); + /// ``` + #[inline] + fn from(s: Box) -> Self { + let (raw, alloc) = Box::into_raw_with_allocator(s); + unsafe { Box::from_raw_in(raw as *mut [u8], alloc) } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_array", since = "1.45.0")] +impl From<[T; N]> for Box<[T]> { + /// Converts a `[T; N]` into a `Box<[T]>` + /// + /// This conversion moves the array to newly heap-allocated memory. + /// + /// # Examples + /// + /// ```rust + /// let boxed: Box<[u8]> = Box::from([4, 2]); + /// println!("{boxed:?}"); + /// ``` + fn from(array: [T; N]) -> Box<[T]> { + Box::new(array) + } +} + +/// Casts a boxed slice to a boxed array. +/// +/// # Safety +/// +/// `boxed_slice.len()` must be exactly `N`. +unsafe fn boxed_slice_as_array_unchecked( + boxed_slice: Box<[T], A>, +) -> Box<[T; N], A> { + debug_assert_eq!(boxed_slice.len(), N); + + let (ptr, alloc) = Box::into_raw_with_allocator(boxed_slice); + // SAFETY: Pointer and allocator came from an existing box, + // and our safety condition requires that the length is exactly `N` + unsafe { Box::from_raw_in(ptr as *mut [T; N], alloc) } +} + +#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] +impl TryFrom> for Box<[T; N]> { + type Error = Box<[T]>; + + /// Attempts to convert a `Box<[T]>` into a `Box<[T; N]>`. + /// + /// The conversion occurs in-place and does not require a + /// new memory allocation. + /// + /// # Errors + /// + /// Returns the old `Box<[T]>` in the `Err` variant if + /// `boxed_slice.len()` does not equal `N`. + fn try_from(boxed_slice: Box<[T]>) -> Result { + if boxed_slice.len() == N { + Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) }) + } else { + Err(boxed_slice) + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_array_try_from_vec", since = "1.66.0")] +impl TryFrom> for Box<[T; N]> { + type Error = Vec; + + /// Attempts to convert a `Vec` into a `Box<[T; N]>`. + /// + /// Like [`Vec::into_boxed_slice`], this is in-place if `vec.capacity() == N`, + /// but will require a reallocation otherwise. + /// + /// # Errors + /// + /// Returns the original `Vec` in the `Err` variant if + /// `boxed_slice.len()` does not equal `N`. + /// + /// # Examples + /// + /// This can be used with [`vec!`] to create an array on the heap: + /// + /// ``` + /// let state: Box<[f32; 100]> = vec![1.0; 100].try_into().unwrap(); + /// assert_eq!(state.len(), 100); + /// ``` + fn try_from(vec: Vec) -> Result { + if vec.len() == N { + let boxed_slice = vec.into_boxed_slice(); + Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) }) + } else { + Err(vec) + } + } +} + +impl Box { + /// Attempts to downcast the box to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn print_if_string(value: Box) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn downcast(self) -> Result, Self> { + if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } + } + + /// Downcasts the box to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + /// + /// [`downcast`]: Self::downcast + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "90850")] + pub unsafe fn downcast_unchecked(self) -> Box { + debug_assert!(self.is::()); + unsafe { + let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self); + Box::from_raw_in(raw as *mut T, alloc) + } + } +} + +impl Box { + /// Attempts to downcast the box to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn print_if_string(value: Box) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn downcast(self) -> Result, Self> { + if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } + } + + /// Downcasts the box to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + /// + /// [`downcast`]: Self::downcast + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "90850")] + pub unsafe fn downcast_unchecked(self) -> Box { + debug_assert!(self.is::()); + unsafe { + let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self); + Box::from_raw_in(raw as *mut T, alloc) + } + } +} + +impl Box { + /// Attempts to downcast the box to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn print_if_string(value: Box) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); + /// ``` + #[inline] + #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")] + pub fn downcast(self) -> Result, Self> { + if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } + } + + /// Downcasts the box to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + /// + /// [`downcast`]: Self::downcast + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "90850")] + pub unsafe fn downcast_unchecked(self) -> Box { + debug_assert!(self.is::()); + unsafe { + let (raw, alloc): (*mut (dyn Any + Send + Sync), _) = + Box::into_raw_with_allocator(self); + Box::from_raw_in(raw as *mut T, alloc) + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, E: Error + 'a> From for Box { + /// Converts a type of [`Error`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// use std::mem; + /// + /// #[derive(Debug)] + /// struct AnError; + /// + /// impl fmt::Display for AnError { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "An error") + /// } + /// } + /// + /// impl Error for AnError {} + /// + /// let an_error = AnError; + /// assert!(0 == mem::size_of_val(&an_error)); + /// let a_boxed_error = Box::::from(an_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, E: Error + Send + Sync + 'a> From for Box { + /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of + /// dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// use std::mem; + /// + /// #[derive(Debug)] + /// struct AnError; + /// + /// impl fmt::Display for AnError { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "An error") + /// } + /// } + /// + /// impl Error for AnError {} + /// + /// unsafe impl Send for AnError {} + /// + /// unsafe impl Sync for AnError {} + /// + /// let an_error = AnError; + /// assert!(0 == mem::size_of_val(&an_error)); + /// let a_boxed_error = Box::::from(an_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> From for Box { + /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_string_error = "a string error".to_string(); + /// let a_boxed_error = Box::::from(a_string_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + #[inline] + fn from(err: String) -> Box { + struct StringError(String); + + impl Error for StringError { + #[allow(deprecated)] + fn description(&self) -> &str { + &self.0 + } + } + + impl fmt::Display for StringError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } + } + + // Purposefully skip printing "StringError(..)" + impl fmt::Debug for StringError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } + } + + Box::new(StringError(err)) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "string_box_error", since = "1.6.0")] +impl<'a> From for Box { + /// Converts a [`String`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_string_error = "a string error".to_string(); + /// let a_boxed_error = Box::::from(a_string_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(str_err: String) -> Box { + let err1: Box = From::from(str_err); + let err2: Box = err1; + err2 + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> From<&str> for Box { + /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// [`str`]: prim@str + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_str_error = "a str error"; + /// let a_boxed_error = Box::::from(a_str_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + #[inline] + fn from(err: &str) -> Box { + From::from(String::from(err)) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "string_box_error", since = "1.6.0")] +impl<'a> From<&str> for Box { + /// Converts a [`str`] into a box of dyn [`Error`]. + /// + /// [`str`]: prim@str + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_str_error = "a str error"; + /// let a_boxed_error = Box::::from(a_str_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: &str) -> Box { + From::from(String::from(err)) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_box_error", since = "1.22.0")] +impl<'a, 'b> From> for Box { + /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// use std::borrow::Cow; + /// + /// let a_cow_str_error = Cow::from("a str error"); + /// let a_boxed_error = Box::::from(a_cow_str_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: Cow<'b, str>) -> Box { + From::from(String::from(err)) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_box_error", since = "1.22.0")] +impl<'a, 'b> From> for Box { + /// Converts a [`Cow`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// use std::borrow::Cow; + /// + /// let a_cow_str_error = Cow::from("a str error"); + /// let a_boxed_error = Box::::from(a_cow_str_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: Cow<'b, str>) -> Box { + From::from(String::from(err)) + } +} + +impl dyn Error { + /// Attempts to downcast the box to a concrete type. + #[inline] + #[stable(feature = "error_downcast", since = "1.3.0")] + #[rustc_allow_incoherent_impl] + pub fn downcast(self: Box) -> Result, Box> { + if self.is::() { + unsafe { + let raw: *mut dyn Error = Box::into_raw(self); + Ok(Box::from_raw(raw as *mut T)) + } + } else { + Err(self) + } + } +} + +impl dyn Error + Send { + /// Attempts to downcast the box to a concrete type. + #[inline] + #[stable(feature = "error_downcast", since = "1.3.0")] + #[rustc_allow_incoherent_impl] + pub fn downcast(self: Box) -> Result, Box> { + let err: Box = self; + ::downcast(err).map_err(|s| unsafe { + // Reapply the `Send` marker. + mem::transmute::, Box>(s) + }) + } +} + +impl dyn Error + Send + Sync { + /// Attempts to downcast the box to a concrete type. + #[inline] + #[stable(feature = "error_downcast", since = "1.3.0")] + #[rustc_allow_incoherent_impl] + pub fn downcast(self: Box) -> Result, Box> { + let err: Box = self; + ::downcast(err).map_err(|s| unsafe { + // Reapply the `Send + Sync` markers. + mem::transmute::, Box>(s) + }) + } +} diff --git a/CoqOfRust/alloc/boxed/iter.rs b/CoqOfRust/alloc/boxed/iter.rs new file mode 100644 index 000000000..90582aa49 --- /dev/null +++ b/CoqOfRust/alloc/boxed/iter.rs @@ -0,0 +1,194 @@ +use core::async_iter::AsyncIterator; +use core::iter::FusedIterator; +use core::pin::Pin; +use core::slice; +use core::task::{Context, Poll}; + +use crate::alloc::Allocator; +#[cfg(not(no_global_oom_handling))] +use crate::borrow::Cow; +use crate::boxed::Box; +#[cfg(not(no_global_oom_handling))] +use crate::string::String; +use crate::vec; +#[cfg(not(no_global_oom_handling))] +use crate::vec::Vec; + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Box { + type Item = I::Item; + fn next(&mut self) -> Option { + (**self).next() + } + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } + fn nth(&mut self, n: usize) -> Option { + (**self).nth(n) + } + fn last(self) -> Option { + BoxIter::last(self) + } +} + +trait BoxIter { + type Item; + fn last(self) -> Option; +} + +impl BoxIter for Box { + type Item = I::Item; + default fn last(self) -> Option { + #[inline] + fn some(_: Option, x: T) -> Option { + Some(x) + } + + self.fold(None, some) + } +} + +/// Specialization for sized `I`s that uses `I`s implementation of `last()` +/// instead of the default. +#[stable(feature = "rust1", since = "1.0.0")] +impl BoxIter for Box { + fn last(self) -> Option { + (*self).last() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Box { + fn next_back(&mut self) -> Option { + (**self).next_back() + } + fn nth_back(&mut self, n: usize) -> Option { + (**self).nth_back(n) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Box { + fn len(&self) -> usize { + (**self).len() + } + fn is_empty(&self) -> bool { + (**self).is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Box {} + +#[unstable(feature = "async_iterator", issue = "79024")] +impl AsyncIterator for Box { + type Item = S::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut **self).poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } +} + +/// This implementation is required to make sure that the `Box<[I]>: IntoIterator` +/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket. +#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] +impl !Iterator for Box<[I], A> {} + +/// This implementation is required to make sure that the `&Box<[I]>: IntoIterator` +/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket. +#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] +impl<'a, I, A: Allocator> !Iterator for &'a Box<[I], A> {} + +/// This implementation is required to make sure that the `&mut Box<[I]>: IntoIterator` +/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket. +#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] +impl<'a, I, A: Allocator> !Iterator for &'a mut Box<[I], A> {} + +// Note: the `#[rustc_skip_during_method_dispatch(boxed_slice)]` on `trait IntoIterator` +// hides this implementation from explicit `.into_iter()` calls on editions < 2024, +// so those calls will still resolve to the slice implementation, by reference. +#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] +impl IntoIterator for Box<[I], A> { + type IntoIter = vec::IntoIter; + type Item = I; + fn into_iter(self) -> vec::IntoIter { + self.into_vec().into_iter() + } +} + +#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] +impl<'a, I, A: Allocator> IntoIterator for &'a Box<[I], A> { + type IntoIter = slice::Iter<'a, I>; + type Item = &'a I; + fn into_iter(self) -> slice::Iter<'a, I> { + self.iter() + } +} + +#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] +impl<'a, I, A: Allocator> IntoIterator for &'a mut Box<[I], A> { + type IntoIter = slice::IterMut<'a, I>; + type Item = &'a mut I; + fn into_iter(self) -> slice::IterMut<'a, I> { + self.iter_mut() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_slice_from_iter", since = "1.32.0")] +impl FromIterator for Box<[I]> { + fn from_iter>(iter: T) -> Self { + iter.into_iter().collect::>().into_boxed_slice() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] +impl FromIterator for Box { + fn from_iter>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] +impl<'a> FromIterator<&'a char> for Box { + fn from_iter>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] +impl<'a> FromIterator<&'a str> for Box { + fn from_iter>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] +impl FromIterator for Box { + fn from_iter>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] +impl FromIterator> for Box { + fn from_iter>>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] +impl<'a> FromIterator> for Box { + fn from_iter>>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} diff --git a/CoqOfRust/alloc/boxed/thin.rs b/CoqOfRust/alloc/boxed/thin.rs new file mode 100644 index 000000000..78e5aec09 --- /dev/null +++ b/CoqOfRust/alloc/boxed/thin.rs @@ -0,0 +1,437 @@ +//! Based on +//! +//! by matthieu-m + +use core::error::Error; +use core::fmt::{self, Debug, Display, Formatter}; +#[cfg(not(no_global_oom_handling))] +use core::intrinsics::const_allocate; +use core::marker::PhantomData; +#[cfg(not(no_global_oom_handling))] +use core::marker::Unsize; +use core::mem; +#[cfg(not(no_global_oom_handling))] +use core::mem::SizedTypeProperties; +use core::ops::{Deref, DerefMut}; +use core::ptr::{self, NonNull, Pointee}; + +use crate::alloc::{self, Layout, LayoutError}; + +/// ThinBox. +/// +/// A thin pointer for heap allocation, regardless of T. +/// +/// # Examples +/// +/// ``` +/// #![feature(thin_box)] +/// use std::boxed::ThinBox; +/// +/// let five = ThinBox::new(5); +/// let thin_slice = ThinBox::<[i32]>::new_unsize([1, 2, 3, 4]); +/// +/// use std::mem::{size_of, size_of_val}; +/// let size_of_ptr = size_of::<*const ()>(); +/// assert_eq!(size_of_ptr, size_of_val(&five)); +/// assert_eq!(size_of_ptr, size_of_val(&thin_slice)); +/// ``` +#[unstable(feature = "thin_box", issue = "92791")] +pub struct ThinBox { + // This is essentially `WithHeader<::Metadata>`, + // but that would be invariant in `T`, and we want covariance. + ptr: WithOpaqueHeader, + _marker: PhantomData, +} + +/// `ThinBox` is `Send` if `T` is `Send` because the data is owned. +#[unstable(feature = "thin_box", issue = "92791")] +unsafe impl Send for ThinBox {} + +/// `ThinBox` is `Sync` if `T` is `Sync` because the data is owned. +#[unstable(feature = "thin_box", issue = "92791")] +unsafe impl Sync for ThinBox {} + +#[unstable(feature = "thin_box", issue = "92791")] +impl ThinBox { + /// Moves a type to the heap with its [`Metadata`] stored in the heap allocation instead of on + /// the stack. + /// + /// # Examples + /// + /// ``` + /// #![feature(thin_box)] + /// use std::boxed::ThinBox; + /// + /// let five = ThinBox::new(5); + /// ``` + /// + /// [`Metadata`]: core::ptr::Pointee::Metadata + #[cfg(not(no_global_oom_handling))] + pub fn new(value: T) -> Self { + let meta = ptr::metadata(&value); + let ptr = WithOpaqueHeader::new(meta, value); + ThinBox { ptr, _marker: PhantomData } + } + + /// Moves a type to the heap with its [`Metadata`] stored in the heap allocation instead of on + /// the stack. Returns an error if allocation fails, instead of aborting. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// #![feature(thin_box)] + /// use std::boxed::ThinBox; + /// + /// let five = ThinBox::try_new(5)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [`Metadata`]: core::ptr::Pointee::Metadata + pub fn try_new(value: T) -> Result { + let meta = ptr::metadata(&value); + WithOpaqueHeader::try_new(meta, value).map(|ptr| ThinBox { ptr, _marker: PhantomData }) + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl ThinBox { + /// Moves a type to the heap with its [`Metadata`] stored in the heap allocation instead of on + /// the stack. + /// + /// # Examples + /// + /// ``` + /// #![feature(thin_box)] + /// use std::boxed::ThinBox; + /// + /// let thin_slice = ThinBox::<[i32]>::new_unsize([1, 2, 3, 4]); + /// ``` + /// + /// [`Metadata`]: core::ptr::Pointee::Metadata + #[cfg(not(no_global_oom_handling))] + pub fn new_unsize(value: T) -> Self + where + T: Unsize, + { + if mem::size_of::() == 0 { + let ptr = WithOpaqueHeader::new_unsize_zst::(value); + ThinBox { ptr, _marker: PhantomData } + } else { + let meta = ptr::metadata(&value as &Dyn); + let ptr = WithOpaqueHeader::new(meta, value); + ThinBox { ptr, _marker: PhantomData } + } + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl Debug for ThinBox { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Debug::fmt(self.deref(), f) + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl Display for ThinBox { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Display::fmt(self.deref(), f) + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl Deref for ThinBox { + type Target = T; + + fn deref(&self) -> &T { + let value = self.data(); + let metadata = self.meta(); + let pointer = ptr::from_raw_parts(value as *const (), metadata); + unsafe { &*pointer } + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl DerefMut for ThinBox { + fn deref_mut(&mut self) -> &mut T { + let value = self.data(); + let metadata = self.meta(); + let pointer = ptr::from_raw_parts_mut::(value as *mut (), metadata); + unsafe { &mut *pointer } + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl Drop for ThinBox { + fn drop(&mut self) { + unsafe { + let value = self.deref_mut(); + let value = value as *mut T; + self.with_header().drop::(value); + } + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl ThinBox { + fn meta(&self) -> ::Metadata { + // Safety: + // - NonNull and valid. + unsafe { *self.with_header().header() } + } + + fn data(&self) -> *mut u8 { + self.with_header().value() + } + + fn with_header(&self) -> &WithHeader<::Metadata> { + // SAFETY: both types are transparent to `NonNull` + unsafe { &*((&raw const self.ptr) as *const WithHeader<_>) } + } +} + +/// A pointer to type-erased data, guaranteed to either be: +/// 1. `NonNull::dangling()`, in the case where both the pointee (`T`) and +/// metadata (`H`) are ZSTs. +/// 2. A pointer to a valid `T` that has a header `H` directly before the +/// pointed-to location. +#[repr(transparent)] +struct WithHeader(NonNull, PhantomData); + +/// An opaque representation of `WithHeader` to avoid the +/// projection invariance of `::Metadata`. +#[repr(transparent)] +struct WithOpaqueHeader(NonNull); + +impl WithOpaqueHeader { + #[cfg(not(no_global_oom_handling))] + fn new(header: H, value: T) -> Self { + let ptr = WithHeader::new(header, value); + Self(ptr.0) + } + + #[cfg(not(no_global_oom_handling))] + fn new_unsize_zst(value: T) -> Self + where + Dyn: ?Sized, + T: Unsize, + { + let ptr = WithHeader::<::Metadata>::new_unsize_zst::(value); + Self(ptr.0) + } + + fn try_new(header: H, value: T) -> Result { + WithHeader::try_new(header, value).map(|ptr| Self(ptr.0)) + } +} + +impl WithHeader { + #[cfg(not(no_global_oom_handling))] + fn new(header: H, value: T) -> WithHeader { + let value_layout = Layout::new::(); + let Ok((layout, value_offset)) = Self::alloc_layout(value_layout) else { + // We pass an empty layout here because we do not know which layout caused the + // arithmetic overflow in `Layout::extend` and `handle_alloc_error` takes `Layout` as + // its argument rather than `Result`, also this function has been + // stable since 1.28 ._. + // + // On the other hand, look at this gorgeous turbofish! + alloc::handle_alloc_error(Layout::new::<()>()); + }; + + unsafe { + // Note: It's UB to pass a layout with a zero size to `alloc::alloc`, so + // we use `layout.dangling()` for this case, which should have a valid + // alignment for both `T` and `H`. + let ptr = if layout.size() == 0 { + // Some paranoia checking, mostly so that the ThinBox tests are + // more able to catch issues. + debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST); + layout.dangling() + } else { + let ptr = alloc::alloc(layout); + if ptr.is_null() { + alloc::handle_alloc_error(layout); + } + // Safety: + // - The size is at least `aligned_header_size`. + let ptr = ptr.add(value_offset) as *mut _; + + NonNull::new_unchecked(ptr) + }; + + let result = WithHeader(ptr, PhantomData); + ptr::write(result.header(), header); + ptr::write(result.value().cast(), value); + + result + } + } + + /// Non-panicking version of `new`. + /// Any error is returned as `Err(core::alloc::AllocError)`. + fn try_new(header: H, value: T) -> Result, core::alloc::AllocError> { + let value_layout = Layout::new::(); + let Ok((layout, value_offset)) = Self::alloc_layout(value_layout) else { + return Err(core::alloc::AllocError); + }; + + unsafe { + // Note: It's UB to pass a layout with a zero size to `alloc::alloc`, so + // we use `layout.dangling()` for this case, which should have a valid + // alignment for both `T` and `H`. + let ptr = if layout.size() == 0 { + // Some paranoia checking, mostly so that the ThinBox tests are + // more able to catch issues. + debug_assert!( + value_offset == 0 && mem::size_of::() == 0 && mem::size_of::() == 0 + ); + layout.dangling() + } else { + let ptr = alloc::alloc(layout); + if ptr.is_null() { + return Err(core::alloc::AllocError); + } + + // Safety: + // - The size is at least `aligned_header_size`. + let ptr = ptr.add(value_offset) as *mut _; + + NonNull::new_unchecked(ptr) + }; + + let result = WithHeader(ptr, PhantomData); + ptr::write(result.header(), header); + ptr::write(result.value().cast(), value); + + Ok(result) + } + } + + // `Dyn` is `?Sized` type like `[u32]`, and `T` is ZST type like `[u32; 0]`. + #[cfg(not(no_global_oom_handling))] + fn new_unsize_zst(value: T) -> WithHeader + where + Dyn: Pointee + ?Sized, + T: Unsize, + { + assert!(mem::size_of::() == 0); + + const fn max(a: usize, b: usize) -> usize { + if a > b { a } else { b } + } + + // Compute a pointer to the right metadata. This will point to the beginning + // of the header, past the padding, so the assigned type makes sense. + // It also ensures that the address at the end of the header is sufficiently + // aligned for T. + let alloc: &::Metadata = const { + // FIXME: just call `WithHeader::alloc_layout` with size reset to 0. + // Currently that's blocked on `Layout::extend` not being `const fn`. + + let alloc_align = + max(mem::align_of::(), mem::align_of::<::Metadata>()); + + let alloc_size = + max(mem::align_of::(), mem::size_of::<::Metadata>()); + + unsafe { + // SAFETY: align is power of two because it is the maximum of two alignments. + let alloc: *mut u8 = const_allocate(alloc_size, alloc_align); + + let metadata_offset = + alloc_size.checked_sub(mem::size_of::<::Metadata>()).unwrap(); + // SAFETY: adding offset within the allocation. + let metadata_ptr: *mut ::Metadata = + alloc.add(metadata_offset).cast(); + // SAFETY: `*metadata_ptr` is within the allocation. + metadata_ptr.write(ptr::metadata::(ptr::dangling::() as *const Dyn)); + + // SAFETY: we have just written the metadata. + &*(metadata_ptr) + } + }; + + // SAFETY: `alloc` points to `::Metadata`, so addition stays in-bounds. + let value_ptr = + unsafe { (alloc as *const ::Metadata).add(1) }.cast::().cast_mut(); + debug_assert!(value_ptr.is_aligned()); + mem::forget(value); + WithHeader(NonNull::new(value_ptr.cast()).unwrap(), PhantomData) + } + + // Safety: + // - Assumes that either `value` can be dereferenced, or is the + // `NonNull::dangling()` we use when both `T` and `H` are ZSTs. + unsafe fn drop(&self, value: *mut T) { + struct DropGuard { + ptr: NonNull, + value_layout: Layout, + _marker: PhantomData, + } + + impl Drop for DropGuard { + fn drop(&mut self) { + // All ZST are allocated statically. + if self.value_layout.size() == 0 { + return; + } + + unsafe { + // SAFETY: Layout must have been computable if we're in drop + let (layout, value_offset) = + WithHeader::::alloc_layout(self.value_layout).unwrap_unchecked(); + + // Since we only allocate for non-ZSTs, the layout size cannot be zero. + debug_assert!(layout.size() != 0); + alloc::dealloc(self.ptr.as_ptr().sub(value_offset), layout); + } + } + } + + unsafe { + // `_guard` will deallocate the memory when dropped, even if `drop_in_place` unwinds. + let _guard = DropGuard { + ptr: self.0, + value_layout: Layout::for_value_raw(value), + _marker: PhantomData::, + }; + + // We only drop the value because the Pointee trait requires that the metadata is copy + // aka trivially droppable. + ptr::drop_in_place::(value); + } + } + + fn header(&self) -> *mut H { + // Safety: + // - At least `size_of::()` bytes are allocated ahead of the pointer. + // - We know that H will be aligned because the middle pointer is aligned to the greater + // of the alignment of the header and the data and the header size includes the padding + // needed to align the header. Subtracting the header size from the aligned data pointer + // will always result in an aligned header pointer, it just may not point to the + // beginning of the allocation. + let hp = unsafe { self.0.as_ptr().sub(Self::header_size()) as *mut H }; + debug_assert!(hp.is_aligned()); + hp + } + + fn value(&self) -> *mut u8 { + self.0.as_ptr() + } + + const fn header_size() -> usize { + mem::size_of::() + } + + fn alloc_layout(value_layout: Layout) -> Result<(Layout, usize), LayoutError> { + Layout::new::().extend(value_layout) + } +} + +#[unstable(feature = "thin_box", issue = "92791")] +impl Error for ThinBox { + fn source(&self) -> Option<&(dyn Error + 'static)> { + self.deref().source() + } +} diff --git a/CoqOfRust/alloc/collections/binary_heap/mod.rs b/CoqOfRust/alloc/collections/binary_heap/mod.rs new file mode 100644 index 000000000..5d3997e14 --- /dev/null +++ b/CoqOfRust/alloc/collections/binary_heap/mod.rs @@ -0,0 +1,1902 @@ +//! A priority queue implemented with a binary heap. +//! +//! Insertion and popping the largest element have *O*(log(*n*)) time complexity. +//! Checking the largest element is *O*(1). Converting a vector to a binary heap +//! can be done in-place, and has *O*(*n*) complexity. A binary heap can also be +//! converted to a sorted vector in-place, allowing it to be used for an *O*(*n* * log(*n*)) +//! in-place heapsort. +//! +//! # Examples +//! +//! This is a larger example that implements [Dijkstra's algorithm][dijkstra] +//! to solve the [shortest path problem][sssp] on a [directed graph][dir_graph]. +//! It shows how to use [`BinaryHeap`] with custom types. +//! +//! [dijkstra]: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm +//! [sssp]: https://en.wikipedia.org/wiki/Shortest_path_problem +//! [dir_graph]: https://en.wikipedia.org/wiki/Directed_graph +//! +//! ``` +//! use std::cmp::Ordering; +//! use std::collections::BinaryHeap; +//! +//! #[derive(Copy, Clone, Eq, PartialEq)] +//! struct State { +//! cost: usize, +//! position: usize, +//! } +//! +//! // The priority queue depends on `Ord`. +//! // Explicitly implement the trait so the queue becomes a min-heap +//! // instead of a max-heap. +//! impl Ord for State { +//! fn cmp(&self, other: &Self) -> Ordering { +//! // Notice that we flip the ordering on costs. +//! // In case of a tie we compare positions - this step is necessary +//! // to make implementations of `PartialEq` and `Ord` consistent. +//! other.cost.cmp(&self.cost) +//! .then_with(|| self.position.cmp(&other.position)) +//! } +//! } +//! +//! // `PartialOrd` needs to be implemented as well. +//! impl PartialOrd for State { +//! fn partial_cmp(&self, other: &Self) -> Option { +//! Some(self.cmp(other)) +//! } +//! } +//! +//! // Each node is represented as a `usize`, for a shorter implementation. +//! struct Edge { +//! node: usize, +//! cost: usize, +//! } +//! +//! // Dijkstra's shortest path algorithm. +//! +//! // Start at `start` and use `dist` to track the current shortest distance +//! // to each node. This implementation isn't memory-efficient as it may leave duplicate +//! // nodes in the queue. It also uses `usize::MAX` as a sentinel value, +//! // for a simpler implementation. +//! fn shortest_path(adj_list: &Vec>, start: usize, goal: usize) -> Option { +//! // dist[node] = current shortest distance from `start` to `node` +//! let mut dist: Vec<_> = (0..adj_list.len()).map(|_| usize::MAX).collect(); +//! +//! let mut heap = BinaryHeap::new(); +//! +//! // We're at `start`, with a zero cost +//! dist[start] = 0; +//! heap.push(State { cost: 0, position: start }); +//! +//! // Examine the frontier with lower cost nodes first (min-heap) +//! while let Some(State { cost, position }) = heap.pop() { +//! // Alternatively we could have continued to find all shortest paths +//! if position == goal { return Some(cost); } +//! +//! // Important as we may have already found a better way +//! if cost > dist[position] { continue; } +//! +//! // For each node we can reach, see if we can find a way with +//! // a lower cost going through this node +//! for edge in &adj_list[position] { +//! let next = State { cost: cost + edge.cost, position: edge.node }; +//! +//! // If so, add it to the frontier and continue +//! if next.cost < dist[next.position] { +//! heap.push(next); +//! // Relaxation, we have now found a better way +//! dist[next.position] = next.cost; +//! } +//! } +//! } +//! +//! // Goal not reachable +//! None +//! } +//! +//! fn main() { +//! // This is the directed graph we're going to use. +//! // The node numbers correspond to the different states, +//! // and the edge weights symbolize the cost of moving +//! // from one node to another. +//! // Note that the edges are one-way. +//! // +//! // 7 +//! // +-----------------+ +//! // | | +//! // v 1 2 | 2 +//! // 0 -----> 1 -----> 3 ---> 4 +//! // | ^ ^ ^ +//! // | | 1 | | +//! // | | | 3 | 1 +//! // +------> 2 -------+ | +//! // 10 | | +//! // +---------------+ +//! // +//! // The graph is represented as an adjacency list where each index, +//! // corresponding to a node value, has a list of outgoing edges. +//! // Chosen for its efficiency. +//! let graph = vec![ +//! // Node 0 +//! vec![Edge { node: 2, cost: 10 }, +//! Edge { node: 1, cost: 1 }], +//! // Node 1 +//! vec![Edge { node: 3, cost: 2 }], +//! // Node 2 +//! vec![Edge { node: 1, cost: 1 }, +//! Edge { node: 3, cost: 3 }, +//! Edge { node: 4, cost: 1 }], +//! // Node 3 +//! vec![Edge { node: 0, cost: 7 }, +//! Edge { node: 4, cost: 2 }], +//! // Node 4 +//! vec![]]; +//! +//! assert_eq!(shortest_path(&graph, 0, 1), Some(1)); +//! assert_eq!(shortest_path(&graph, 0, 3), Some(3)); +//! assert_eq!(shortest_path(&graph, 3, 0), Some(7)); +//! assert_eq!(shortest_path(&graph, 0, 4), Some(5)); +//! assert_eq!(shortest_path(&graph, 4, 0), None); +//! } +//! ``` + +#![allow(missing_docs)] +#![stable(feature = "rust1", since = "1.0.0")] + +use core::alloc::Allocator; +use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedFused, TrustedLen}; +use core::mem::{self, ManuallyDrop, swap}; +use core::num::NonZero; +use core::ops::{Deref, DerefMut}; +use core::{fmt, ptr}; + +use crate::alloc::Global; +use crate::collections::TryReserveError; +use crate::slice; +use crate::vec::{self, AsVecIntoIter, Vec}; + +#[cfg(test)] +mod tests; + +/// A priority queue implemented with a binary heap. +/// +/// This will be a max-heap. +/// +/// It is a logic error for an item to be modified in such a way that the +/// item's ordering relative to any other item, as determined by the [`Ord`] +/// trait, changes while it is in the heap. This is normally only possible +/// through interior mutability, global state, I/O, or unsafe code. The +/// behavior resulting from such a logic error is not specified, but will +/// be encapsulated to the `BinaryHeap` that observed the logic error and not +/// result in undefined behavior. This could include panics, incorrect results, +/// aborts, memory leaks, and non-termination. +/// +/// As long as no elements change their relative order while being in the heap +/// as described above, the API of `BinaryHeap` guarantees that the heap +/// invariant remains intact i.e. its methods all behave as documented. For +/// example if a method is documented as iterating in sorted order, that's +/// guaranteed to work as long as elements in the heap have not changed order, +/// even in the presence of closures getting unwinded out of, iterators getting +/// leaked, and similar foolishness. +/// +/// # Examples +/// +/// ``` +/// use std::collections::BinaryHeap; +/// +/// // Type inference lets us omit an explicit type signature (which +/// // would be `BinaryHeap` in this example). +/// let mut heap = BinaryHeap::new(); +/// +/// // We can use peek to look at the next item in the heap. In this case, +/// // there's no items in there yet so we get None. +/// assert_eq!(heap.peek(), None); +/// +/// // Let's add some scores... +/// heap.push(1); +/// heap.push(5); +/// heap.push(2); +/// +/// // Now peek shows the most important item in the heap. +/// assert_eq!(heap.peek(), Some(&5)); +/// +/// // We can check the length of a heap. +/// assert_eq!(heap.len(), 3); +/// +/// // We can iterate over the items in the heap, although they are returned in +/// // a random order. +/// for x in &heap { +/// println!("{x}"); +/// } +/// +/// // If we instead pop these scores, they should come back in order. +/// assert_eq!(heap.pop(), Some(5)); +/// assert_eq!(heap.pop(), Some(2)); +/// assert_eq!(heap.pop(), Some(1)); +/// assert_eq!(heap.pop(), None); +/// +/// // We can clear the heap of any remaining items. +/// heap.clear(); +/// +/// // The heap should now be empty. +/// assert!(heap.is_empty()) +/// ``` +/// +/// A `BinaryHeap` with a known list of items can be initialized from an array: +/// +/// ``` +/// use std::collections::BinaryHeap; +/// +/// let heap = BinaryHeap::from([1, 5, 2]); +/// ``` +/// +/// ## Min-heap +/// +/// Either [`core::cmp::Reverse`] or a custom [`Ord`] implementation can be used to +/// make `BinaryHeap` a min-heap. This makes `heap.pop()` return the smallest +/// value instead of the greatest one. +/// +/// ``` +/// use std::collections::BinaryHeap; +/// use std::cmp::Reverse; +/// +/// let mut heap = BinaryHeap::new(); +/// +/// // Wrap values in `Reverse` +/// heap.push(Reverse(1)); +/// heap.push(Reverse(5)); +/// heap.push(Reverse(2)); +/// +/// // If we pop these scores now, they should come back in the reverse order. +/// assert_eq!(heap.pop(), Some(Reverse(1))); +/// assert_eq!(heap.pop(), Some(Reverse(2))); +/// assert_eq!(heap.pop(), Some(Reverse(5))); +/// assert_eq!(heap.pop(), None); +/// ``` +/// +/// # Time complexity +/// +/// | [push] | [pop] | [peek]/[peek\_mut] | +/// |---------|---------------|--------------------| +/// | *O*(1)~ | *O*(log(*n*)) | *O*(1) | +/// +/// The value for `push` is an expected cost; the method documentation gives a +/// more detailed analysis. +/// +/// [`core::cmp::Reverse`]: core::cmp::Reverse +/// [`Cell`]: core::cell::Cell +/// [`RefCell`]: core::cell::RefCell +/// [push]: BinaryHeap::push +/// [pop]: BinaryHeap::pop +/// [peek]: BinaryHeap::peek +/// [peek\_mut]: BinaryHeap::peek_mut +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "BinaryHeap")] +pub struct BinaryHeap< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + data: Vec, +} + +/// Structure wrapping a mutable reference to the greatest item on a +/// `BinaryHeap`. +/// +/// This `struct` is created by the [`peek_mut`] method on [`BinaryHeap`]. See +/// its documentation for more. +/// +/// [`peek_mut`]: BinaryHeap::peek_mut +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] +pub struct PeekMut< + 'a, + T: 'a + Ord, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + heap: &'a mut BinaryHeap, + // If a set_len + sift_down are required, this is Some. If a &mut T has not + // yet been exposed to peek_mut()'s caller, it's None. + original_len: Option>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for PeekMut<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("PeekMut").field(&self.heap.data[0]).finish() + } +} + +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] +impl Drop for PeekMut<'_, T, A> { + fn drop(&mut self) { + if let Some(original_len) = self.original_len { + // SAFETY: That's how many elements were in the Vec at the time of + // the PeekMut::deref_mut call, and therefore also at the time of + // the BinaryHeap::peek_mut call. Since the PeekMut did not end up + // getting leaked, we are now undoing the leak amplification that + // the DerefMut prepared for. + unsafe { self.heap.data.set_len(original_len.get()) }; + + // SAFETY: PeekMut is only instantiated for non-empty heaps. + unsafe { self.heap.sift_down(0) }; + } + } +} + +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] +impl Deref for PeekMut<'_, T, A> { + type Target = T; + fn deref(&self) -> &T { + debug_assert!(!self.heap.is_empty()); + // SAFE: PeekMut is only instantiated for non-empty heaps + unsafe { self.heap.data.get_unchecked(0) } + } +} + +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] +impl DerefMut for PeekMut<'_, T, A> { + fn deref_mut(&mut self) -> &mut T { + debug_assert!(!self.heap.is_empty()); + + let len = self.heap.len(); + if len > 1 { + // Here we preemptively leak all the rest of the underlying vector + // after the currently max element. If the caller mutates the &mut T + // we're about to give them, and then leaks the PeekMut, all these + // elements will remain leaked. If they don't leak the PeekMut, then + // either Drop or PeekMut::pop will un-leak the vector elements. + // + // This is technique is described throughout several other places in + // the standard library as "leak amplification". + unsafe { + // SAFETY: len > 1 so len != 0. + self.original_len = Some(NonZero::new_unchecked(len)); + // SAFETY: len > 1 so all this does for now is leak elements, + // which is safe. + self.heap.data.set_len(1); + } + } + + // SAFE: PeekMut is only instantiated for non-empty heaps + unsafe { self.heap.data.get_unchecked_mut(0) } + } +} + +impl<'a, T: Ord, A: Allocator> PeekMut<'a, T, A> { + /// Removes the peeked value from the heap and returns it. + #[stable(feature = "binary_heap_peek_mut_pop", since = "1.18.0")] + pub fn pop(mut this: PeekMut<'a, T, A>) -> T { + if let Some(original_len) = this.original_len.take() { + // SAFETY: This is how many elements were in the Vec at the time of + // the BinaryHeap::peek_mut call. + unsafe { this.heap.data.set_len(original_len.get()) }; + + // Unlike in Drop, here we don't also need to do a sift_down even if + // the caller could've mutated the element. It is removed from the + // heap on the next line and pop() is not sensitive to its value. + } + + // SAFETY: Have a `PeekMut` element proves that the associated binary heap being non-empty, + // so the `pop` operation will not fail. + unsafe { this.heap.pop().unwrap_unchecked() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for BinaryHeap { + fn clone(&self) -> Self { + BinaryHeap { data: self.data.clone() } + } + + /// Overwrites the contents of `self` with a clone of the contents of `source`. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids reallocation if possible. + /// + /// See [`Vec::clone_from()`] for more details. + fn clone_from(&mut self, source: &Self) { + self.data.clone_from(&source.data); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for BinaryHeap { + /// Creates an empty `BinaryHeap`. + #[inline] + fn default() -> BinaryHeap { + BinaryHeap::new() + } +} + +#[stable(feature = "binaryheap_debug", since = "1.4.0")] +impl fmt::Debug for BinaryHeap { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.iter()).finish() + } +} + +struct RebuildOnDrop< + 'a, + T: Ord, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + heap: &'a mut BinaryHeap, + rebuild_from: usize, +} + +impl Drop for RebuildOnDrop<'_, T, A> { + fn drop(&mut self) { + self.heap.rebuild_tail(self.rebuild_from); + } +} + +impl BinaryHeap { + /// Creates an empty `BinaryHeap` as a max-heap. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new(); + /// heap.push(4); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_binary_heap_constructor", since = "1.80.0")] + #[must_use] + pub const fn new() -> BinaryHeap { + BinaryHeap { data: vec![] } + } + + /// Creates an empty `BinaryHeap` with at least the specified capacity. + /// + /// The binary heap will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is zero, the binary heap will not allocate. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::with_capacity(10); + /// heap.push(4); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn with_capacity(capacity: usize) -> BinaryHeap { + BinaryHeap { data: Vec::with_capacity(capacity) } + } +} + +impl BinaryHeap { + /// Creates an empty `BinaryHeap` as a max-heap, using `A` as allocator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new_in(System); + /// heap.push(4); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] + pub const fn new_in(alloc: A) -> BinaryHeap { + BinaryHeap { data: Vec::new_in(alloc) } + } + + /// Creates an empty `BinaryHeap` with at least the specified capacity, using `A` as allocator. + /// + /// The binary heap will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is zero, the binary heap will not allocate. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::with_capacity_in(10, System); + /// heap.push(4); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] + pub fn with_capacity_in(capacity: usize, alloc: A) -> BinaryHeap { + BinaryHeap { data: Vec::with_capacity_in(capacity, alloc) } + } + + /// Returns a mutable reference to the greatest item in the binary heap, or + /// `None` if it is empty. + /// + /// Note: If the `PeekMut` value is leaked, some heap elements might get + /// leaked along with it, but the remaining elements will remain a valid + /// heap. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new(); + /// assert!(heap.peek_mut().is_none()); + /// + /// heap.push(1); + /// heap.push(5); + /// heap.push(2); + /// { + /// let mut val = heap.peek_mut().unwrap(); + /// *val = 0; + /// } + /// assert_eq!(heap.peek(), Some(&2)); + /// ``` + /// + /// # Time complexity + /// + /// If the item is modified then the worst case time complexity is *O*(log(*n*)), + /// otherwise it's *O*(1). + #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] + pub fn peek_mut(&mut self) -> Option> { + if self.is_empty() { None } else { Some(PeekMut { heap: self, original_len: None }) } + } + + /// Removes the greatest item from the binary heap and returns it, or `None` if it + /// is empty. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::from([1, 3]); + /// + /// assert_eq!(heap.pop(), Some(3)); + /// assert_eq!(heap.pop(), Some(1)); + /// assert_eq!(heap.pop(), None); + /// ``` + /// + /// # Time complexity + /// + /// The worst case cost of `pop` on a heap containing *n* elements is *O*(log(*n*)). + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop(&mut self) -> Option { + self.data.pop().map(|mut item| { + if !self.is_empty() { + swap(&mut item, &mut self.data[0]); + // SAFETY: !self.is_empty() means that self.len() > 0 + unsafe { self.sift_down_to_bottom(0) }; + } + item + }) + } + + /// Pushes an item onto the binary heap. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new(); + /// heap.push(3); + /// heap.push(5); + /// heap.push(1); + /// + /// assert_eq!(heap.len(), 3); + /// assert_eq!(heap.peek(), Some(&5)); + /// ``` + /// + /// # Time complexity + /// + /// The expected cost of `push`, averaged over every possible ordering of + /// the elements being pushed, and over a sufficiently large number of + /// pushes, is *O*(1). This is the most meaningful cost metric when pushing + /// elements that are *not* already in any sorted pattern. + /// + /// The time complexity degrades if elements are pushed in predominantly + /// ascending order. In the worst case, elements are pushed in ascending + /// sorted order and the amortized cost per push is *O*(log(*n*)) against a heap + /// containing *n* elements. + /// + /// The worst case cost of a *single* call to `push` is *O*(*n*). The worst case + /// occurs when capacity is exhausted and needs a resize. The resize cost + /// has been amortized in the previous figures. + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("append", "put")] + pub fn push(&mut self, item: T) { + let old_len = self.len(); + self.data.push(item); + // SAFETY: Since we pushed a new item it means that + // old_len = self.len() - 1 < self.len() + unsafe { self.sift_up(0, old_len) }; + } + + /// Consumes the `BinaryHeap` and returns a vector in sorted + /// (ascending) order. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let mut heap = BinaryHeap::from([1, 2, 4, 5, 7]); + /// heap.push(6); + /// heap.push(3); + /// + /// let vec = heap.into_sorted_vec(); + /// assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] + pub fn into_sorted_vec(mut self) -> Vec { + let mut end = self.len(); + while end > 1 { + end -= 1; + // SAFETY: `end` goes from `self.len() - 1` to 1 (both included), + // so it's always a valid index to access. + // It is safe to access index 0 (i.e. `ptr`), because + // 1 <= end < self.len(), which means self.len() >= 2. + unsafe { + let ptr = self.data.as_mut_ptr(); + ptr::swap(ptr, ptr.add(end)); + } + // SAFETY: `end` goes from `self.len() - 1` to 1 (both included) so: + // 0 < 1 <= end <= self.len() - 1 < self.len() + // Which means 0 < end and end < self.len(). + unsafe { self.sift_down_range(0, end) }; + } + self.into_vec() + } + + // The implementations of sift_up and sift_down use unsafe blocks in + // order to move an element out of the vector (leaving behind a + // hole), shift along the others and move the removed element back into the + // vector at the final location of the hole. + // The `Hole` type is used to represent this, and make sure + // the hole is filled back at the end of its scope, even on panic. + // Using a hole reduces the constant factor compared to using swaps, + // which involves twice as many moves. + + /// # Safety + /// + /// The caller must guarantee that `pos < self.len()`. + unsafe fn sift_up(&mut self, start: usize, pos: usize) -> usize { + // Take out the value at `pos` and create a hole. + // SAFETY: The caller guarantees that pos < self.len() + let mut hole = unsafe { Hole::new(&mut self.data, pos) }; + + while hole.pos() > start { + let parent = (hole.pos() - 1) / 2; + + // SAFETY: hole.pos() > start >= 0, which means hole.pos() > 0 + // and so hole.pos() - 1 can't underflow. + // This guarantees that parent < hole.pos() so + // it's a valid index and also != hole.pos(). + if hole.element() <= unsafe { hole.get(parent) } { + break; + } + + // SAFETY: Same as above + unsafe { hole.move_to(parent) }; + } + + hole.pos() + } + + /// Take an element at `pos` and move it down the heap, + /// while its children are larger. + /// + /// # Safety + /// + /// The caller must guarantee that `pos < end <= self.len()`. + unsafe fn sift_down_range(&mut self, pos: usize, end: usize) { + // SAFETY: The caller guarantees that pos < end <= self.len(). + let mut hole = unsafe { Hole::new(&mut self.data, pos) }; + let mut child = 2 * hole.pos() + 1; + + // Loop invariant: child == 2 * hole.pos() + 1. + while child <= end.saturating_sub(2) { + // compare with the greater of the two children + // SAFETY: child < end - 1 < self.len() and + // child + 1 < end <= self.len(), so they're valid indexes. + // child == 2 * hole.pos() + 1 != hole.pos() and + // child + 1 == 2 * hole.pos() + 2 != hole.pos(). + // FIXME: 2 * hole.pos() + 1 or 2 * hole.pos() + 2 could overflow + // if T is a ZST + child += unsafe { hole.get(child) <= hole.get(child + 1) } as usize; + + // if we are already in order, stop. + // SAFETY: child is now either the old child or the old child+1 + // We already proven that both are < self.len() and != hole.pos() + if hole.element() >= unsafe { hole.get(child) } { + return; + } + + // SAFETY: same as above. + unsafe { hole.move_to(child) }; + child = 2 * hole.pos() + 1; + } + + // SAFETY: && short circuit, which means that in the + // second condition it's already true that child == end - 1 < self.len(). + if child == end - 1 && hole.element() < unsafe { hole.get(child) } { + // SAFETY: child is already proven to be a valid index and + // child == 2 * hole.pos() + 1 != hole.pos(). + unsafe { hole.move_to(child) }; + } + } + + /// # Safety + /// + /// The caller must guarantee that `pos < self.len()`. + unsafe fn sift_down(&mut self, pos: usize) { + let len = self.len(); + // SAFETY: pos < len is guaranteed by the caller and + // obviously len = self.len() <= self.len(). + unsafe { self.sift_down_range(pos, len) }; + } + + /// Take an element at `pos` and move it all the way down the heap, + /// then sift it up to its position. + /// + /// Note: This is faster when the element is known to be large / should + /// be closer to the bottom. + /// + /// # Safety + /// + /// The caller must guarantee that `pos < self.len()`. + unsafe fn sift_down_to_bottom(&mut self, mut pos: usize) { + let end = self.len(); + let start = pos; + + // SAFETY: The caller guarantees that pos < self.len(). + let mut hole = unsafe { Hole::new(&mut self.data, pos) }; + let mut child = 2 * hole.pos() + 1; + + // Loop invariant: child == 2 * hole.pos() + 1. + while child <= end.saturating_sub(2) { + // SAFETY: child < end - 1 < self.len() and + // child + 1 < end <= self.len(), so they're valid indexes. + // child == 2 * hole.pos() + 1 != hole.pos() and + // child + 1 == 2 * hole.pos() + 2 != hole.pos(). + // FIXME: 2 * hole.pos() + 1 or 2 * hole.pos() + 2 could overflow + // if T is a ZST + child += unsafe { hole.get(child) <= hole.get(child + 1) } as usize; + + // SAFETY: Same as above + unsafe { hole.move_to(child) }; + child = 2 * hole.pos() + 1; + } + + if child == end - 1 { + // SAFETY: child == end - 1 < self.len(), so it's a valid index + // and child == 2 * hole.pos() + 1 != hole.pos(). + unsafe { hole.move_to(child) }; + } + pos = hole.pos(); + drop(hole); + + // SAFETY: pos is the position in the hole and was already proven + // to be a valid index. + unsafe { self.sift_up(start, pos) }; + } + + /// Rebuild assuming data[0..start] is still a proper heap. + fn rebuild_tail(&mut self, start: usize) { + if start == self.len() { + return; + } + + let tail_len = self.len() - start; + + #[inline(always)] + fn log2_fast(x: usize) -> usize { + (usize::BITS - x.leading_zeros() - 1) as usize + } + + // `rebuild` takes O(self.len()) operations + // and about 2 * self.len() comparisons in the worst case + // while repeating `sift_up` takes O(tail_len * log(start)) operations + // and about 1 * tail_len * log_2(start) comparisons in the worst case, + // assuming start >= tail_len. For larger heaps, the crossover point + // no longer follows this reasoning and was determined empirically. + let better_to_rebuild = if start < tail_len { + true + } else if self.len() <= 2048 { + 2 * self.len() < tail_len * log2_fast(start) + } else { + 2 * self.len() < tail_len * 11 + }; + + if better_to_rebuild { + self.rebuild(); + } else { + for i in start..self.len() { + // SAFETY: The index `i` is always less than self.len(). + unsafe { self.sift_up(0, i) }; + } + } + } + + fn rebuild(&mut self) { + let mut n = self.len() / 2; + while n > 0 { + n -= 1; + // SAFETY: n starts from self.len() / 2 and goes down to 0. + // The only case when !(n < self.len()) is if + // self.len() == 0, but it's ruled out by the loop condition. + unsafe { self.sift_down(n) }; + } + } + + /// Moves all the elements of `other` into `self`, leaving `other` empty. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let mut a = BinaryHeap::from([-10, 1, 2, 3, 3]); + /// let mut b = BinaryHeap::from([-20, 5, 43]); + /// + /// a.append(&mut b); + /// + /// assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); + /// assert!(b.is_empty()); + /// ``` + #[stable(feature = "binary_heap_append", since = "1.11.0")] + pub fn append(&mut self, other: &mut Self) { + if self.len() < other.len() { + swap(self, other); + } + + let start = self.data.len(); + + self.data.append(&mut other.data); + + self.rebuild_tail(start); + } + + /// Clears the binary heap, returning an iterator over the removed elements + /// in heap order. If the iterator is dropped before being fully consumed, + /// it drops the remaining elements in heap order. + /// + /// The returned iterator keeps a mutable borrow on the heap to optimize + /// its implementation. + /// + /// Note: + /// * `.drain_sorted()` is *O*(*n* \* log(*n*)); much slower than `.drain()`. + /// You should use the latter for most cases. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(binary_heap_drain_sorted)] + /// use std::collections::BinaryHeap; + /// + /// let mut heap = BinaryHeap::from([1, 2, 3, 4, 5]); + /// assert_eq!(heap.len(), 5); + /// + /// drop(heap.drain_sorted()); // removes all elements in heap order + /// assert_eq!(heap.len(), 0); + /// ``` + #[inline] + #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] + pub fn drain_sorted(&mut self) -> DrainSorted<'_, T, A> { + DrainSorted { inner: self } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` for which `f(&e)` returns + /// `false`. The elements are visited in unsorted (and unspecified) order. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let mut heap = BinaryHeap::from([-10, -5, 1, 2, 4, 13]); + /// + /// heap.retain(|x| x % 2 == 0); // only keep even numbers + /// + /// assert_eq!(heap.into_sorted_vec(), [-10, 2, 4]) + /// ``` + #[stable(feature = "binary_heap_retain", since = "1.70.0")] + pub fn retain(&mut self, mut f: F) + where + F: FnMut(&T) -> bool, + { + // rebuild_start will be updated to the first touched element below, and the rebuild will + // only be done for the tail. + let mut guard = RebuildOnDrop { rebuild_from: self.len(), heap: self }; + let mut i = 0; + + guard.heap.data.retain(|e| { + let keep = f(e); + if !keep && i < guard.rebuild_from { + guard.rebuild_from = i; + } + i += 1; + keep + }); + } +} + +impl BinaryHeap { + /// Returns an iterator visiting all values in the underlying vector, in + /// arbitrary order. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let heap = BinaryHeap::from([1, 2, 3, 4]); + /// + /// // Print 1, 2, 3, 4 in arbitrary order + /// for x in heap.iter() { + /// println!("{x}"); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "binaryheap_iter")] + pub fn iter(&self) -> Iter<'_, T> { + Iter { iter: self.data.iter() } + } + + /// Returns an iterator which retrieves elements in heap order. + /// + /// This method consumes the original heap. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(binary_heap_into_iter_sorted)] + /// use std::collections::BinaryHeap; + /// let heap = BinaryHeap::from([1, 2, 3, 4, 5]); + /// + /// assert_eq!(heap.into_iter_sorted().take(2).collect::>(), [5, 4]); + /// ``` + #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] + pub fn into_iter_sorted(self) -> IntoIterSorted { + IntoIterSorted { inner: self } + } + + /// Returns the greatest item in the binary heap, or `None` if it is empty. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new(); + /// assert_eq!(heap.peek(), None); + /// + /// heap.push(1); + /// heap.push(5); + /// heap.push(2); + /// assert_eq!(heap.peek(), Some(&5)); + /// + /// ``` + /// + /// # Time complexity + /// + /// Cost is *O*(1) in the worst case. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn peek(&self) -> Option<&T> { + self.data.get(0) + } + + /// Returns the number of elements the binary heap can hold without reallocating. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::with_capacity(100); + /// assert!(heap.capacity() >= 100); + /// heap.push(4); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn capacity(&self) -> usize { + self.data.capacity() + } + + /// Reserves the minimum capacity for at least `additional` elements more than + /// the current length. Unlike [`reserve`], this will not + /// deliberately over-allocate to speculatively avoid frequent allocations. + /// After calling `reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional`. Does nothing if the capacity is already + /// sufficient. + /// + /// [`reserve`]: BinaryHeap::reserve + /// + /// # Panics + /// + /// Panics if the new capacity overflows [`usize`]. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new(); + /// heap.reserve_exact(100); + /// assert!(heap.capacity() >= 100); + /// heap.push(4); + /// ``` + /// + /// [`reserve`]: BinaryHeap::reserve + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve_exact(&mut self, additional: usize) { + self.data.reserve_exact(additional); + } + + /// Reserves capacity for at least `additional` elements more than the + /// current length. The allocator may reserve more space to speculatively + /// avoid frequent allocations. After calling `reserve`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if capacity is already sufficient. + /// + /// # Panics + /// + /// Panics if the new capacity overflows [`usize`]. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new(); + /// heap.reserve(100); + /// assert!(heap.capacity() >= 100); + /// heap.push(4); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve(&mut self, additional: usize) { + self.data.reserve(additional); + } + + /// Tries to reserve the minimum capacity for at least `additional` elements + /// more than the current length. Unlike [`try_reserve`], this will not + /// deliberately over-allocate to speculatively avoid frequent allocations. + /// After calling `try_reserve_exact`, capacity will be greater than or + /// equal to `self.len() + additional` if it returns `Ok(())`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer [`try_reserve`] if future insertions are expected. + /// + /// [`try_reserve`]: BinaryHeap::try_reserve + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BinaryHeap; + /// use std::collections::TryReserveError; + /// + /// fn find_max_slow(data: &[u32]) -> Result, TryReserveError> { + /// let mut heap = BinaryHeap::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// heap.try_reserve_exact(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// heap.extend(data.iter()); + /// + /// Ok(heap.pop()) + /// } + /// # find_max_slow(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[stable(feature = "try_reserve_2", since = "1.63.0")] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.data.try_reserve_exact(additional) + } + + /// Tries to reserve capacity for at least `additional` elements more than the + /// current length. The allocator may reserve more space to speculatively + /// avoid frequent allocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional` if it returns + /// `Ok(())`. Does nothing if capacity is already sufficient. This method + /// preserves the contents even if an error occurs. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BinaryHeap; + /// use std::collections::TryReserveError; + /// + /// fn find_max_slow(data: &[u32]) -> Result, TryReserveError> { + /// let mut heap = BinaryHeap::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// heap.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// heap.extend(data.iter()); + /// + /// Ok(heap.pop()) + /// } + /// # find_max_slow(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[stable(feature = "try_reserve_2", since = "1.63.0")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.data.try_reserve(additional) + } + + /// Discards as much additional capacity as possible. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap: BinaryHeap = BinaryHeap::with_capacity(100); + /// + /// assert!(heap.capacity() >= 100); + /// heap.shrink_to_fit(); + /// assert!(heap.capacity() == 0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn shrink_to_fit(&mut self) { + self.data.shrink_to_fit(); + } + + /// Discards capacity with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// If the current capacity is less than the lower limit, this is a no-op. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap: BinaryHeap = BinaryHeap::with_capacity(100); + /// + /// assert!(heap.capacity() >= 100); + /// heap.shrink_to(10); + /// assert!(heap.capacity() >= 10); + /// ``` + #[inline] + #[stable(feature = "shrink_to", since = "1.56.0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.data.shrink_to(min_capacity) + } + + /// Returns a slice of all values in the underlying vector, in arbitrary + /// order. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// use std::io::{self, Write}; + /// + /// let heap = BinaryHeap::from([1, 2, 3, 4, 5, 6, 7]); + /// + /// io::sink().write(heap.as_slice()).unwrap(); + /// ``` + #[must_use] + #[stable(feature = "binary_heap_as_slice", since = "1.80.0")] + pub fn as_slice(&self) -> &[T] { + self.data.as_slice() + } + + /// Consumes the `BinaryHeap` and returns the underlying vector + /// in arbitrary order. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let heap = BinaryHeap::from([1, 2, 3, 4, 5, 6, 7]); + /// let vec = heap.into_vec(); + /// + /// // Will print in some order + /// for x in vec { + /// println!("{x}"); + /// } + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] + pub fn into_vec(self) -> Vec { + self.into() + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + self.data.allocator() + } + + /// Returns the length of the binary heap. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let heap = BinaryHeap::from([1, 3]); + /// + /// assert_eq!(heap.len(), 2); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("length", "size")] + pub fn len(&self) -> usize { + self.data.len() + } + + /// Checks if the binary heap is empty. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new(); + /// + /// assert!(heap.is_empty()); + /// + /// heap.push(3); + /// heap.push(5); + /// heap.push(1); + /// + /// assert!(!heap.is_empty()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Clears the binary heap, returning an iterator over the removed elements + /// in arbitrary order. If the iterator is dropped before being fully + /// consumed, it drops the remaining elements in arbitrary order. + /// + /// The returned iterator keeps a mutable borrow on the heap to optimize + /// its implementation. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::from([1, 3]); + /// + /// assert!(!heap.is_empty()); + /// + /// for x in heap.drain() { + /// println!("{x}"); + /// } + /// + /// assert!(heap.is_empty()); + /// ``` + #[inline] + #[stable(feature = "drain", since = "1.6.0")] + pub fn drain(&mut self) -> Drain<'_, T, A> { + Drain { iter: self.data.drain(..) } + } + + /// Drops all items from the binary heap. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::from([1, 3]); + /// + /// assert!(!heap.is_empty()); + /// + /// heap.clear(); + /// + /// assert!(heap.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + self.drain(); + } +} + +/// Hole represents a hole in a slice i.e., an index without valid value +/// (because it was moved from or duplicated). +/// In drop, `Hole` will restore the slice by filling the hole +/// position with the value that was originally removed. +struct Hole<'a, T: 'a> { + data: &'a mut [T], + elt: ManuallyDrop, + pos: usize, +} + +impl<'a, T> Hole<'a, T> { + /// Creates a new `Hole` at index `pos`. + /// + /// Unsafe because pos must be within the data slice. + #[inline] + unsafe fn new(data: &'a mut [T], pos: usize) -> Self { + debug_assert!(pos < data.len()); + // SAFE: pos should be inside the slice + let elt = unsafe { ptr::read(data.get_unchecked(pos)) }; + Hole { data, elt: ManuallyDrop::new(elt), pos } + } + + #[inline] + fn pos(&self) -> usize { + self.pos + } + + /// Returns a reference to the element removed. + #[inline] + fn element(&self) -> &T { + &self.elt + } + + /// Returns a reference to the element at `index`. + /// + /// Unsafe because index must be within the data slice and not equal to pos. + #[inline] + unsafe fn get(&self, index: usize) -> &T { + debug_assert!(index != self.pos); + debug_assert!(index < self.data.len()); + unsafe { self.data.get_unchecked(index) } + } + + /// Move hole to new location + /// + /// Unsafe because index must be within the data slice and not equal to pos. + #[inline] + unsafe fn move_to(&mut self, index: usize) { + debug_assert!(index != self.pos); + debug_assert!(index < self.data.len()); + unsafe { + let ptr = self.data.as_mut_ptr(); + let index_ptr: *const _ = ptr.add(index); + let hole_ptr = ptr.add(self.pos); + ptr::copy_nonoverlapping(index_ptr, hole_ptr, 1); + } + self.pos = index; + } +} + +impl Drop for Hole<'_, T> { + #[inline] + fn drop(&mut self) { + // fill the hole again + unsafe { + let pos = self.pos; + ptr::copy_nonoverlapping(&*self.elt, self.data.get_unchecked_mut(pos), 1); + } + } +} + +/// An iterator over the elements of a `BinaryHeap`. +/// +/// This `struct` is created by [`BinaryHeap::iter()`]. See its +/// documentation for more. +/// +/// [`iter`]: BinaryHeap::iter +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Iter<'a, T: 'a> { + iter: slice::Iter<'a, T>, +} + +#[stable(feature = "default_iters_sequel", since = "1.82.0")] +impl Default for Iter<'_, T> { + /// Creates an empty `binary_heap::Iter`. + /// + /// ``` + /// # use std::collections::binary_heap; + /// let iter: binary_heap::Iter<'_, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Iter { iter: Default::default() } + } +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Iter<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Iter").field(&self.iter.as_slice()).finish() + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Iter<'_, T> { + fn clone(&self) -> Self { + Iter { iter: self.iter.clone() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + + #[inline] + fn next(&mut self) -> Option<&'a T> { + self.iter.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + #[inline] + fn last(self) -> Option<&'a T> { + self.iter.last() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for Iter<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a T> { + self.iter.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Iter<'_, T> { + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Iter<'_, T> {} + +/// An owning iterator over the elements of a `BinaryHeap`. +/// +/// This `struct` is created by [`BinaryHeap::into_iter()`] +/// (provided by the [`IntoIterator`] trait). See its documentation for more. +/// +/// [`into_iter`]: BinaryHeap::into_iter +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] +pub struct IntoIter< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + iter: vec::IntoIter, +} + +impl IntoIter { + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(&self) -> &A { + self.iter.allocator() + } +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoIter").field(&self.iter.as_slice()).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for IntoIter {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for IntoIter { + /// Creates an empty `binary_heap::IntoIter`. + /// + /// ``` + /// # use std::collections::binary_heap; + /// let iter: binary_heap::IntoIter = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + IntoIter { iter: Default::default() } + } +} + +// In addition to the SAFETY invariants of the following three unsafe traits +// also refer to the vec::in_place_collect module documentation to get an overview +#[unstable(issue = "none", feature = "inplace_iteration")] +#[doc(hidden)] +unsafe impl SourceIter for IntoIter { + type Source = IntoIter; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut Self::Source { + self + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +#[doc(hidden)] +unsafe impl InPlaceIterable for IntoIter { + const EXPAND_BY: Option> = NonZero::new(1); + const MERGE_BY: Option> = NonZero::new(1); +} + +unsafe impl AsVecIntoIter for IntoIter { + type Item = I; + + fn as_into_iter(&mut self) -> &mut vec::IntoIter { + &mut self.iter + } +} + +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] +#[derive(Clone, Debug)] +pub struct IntoIterSorted< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + inner: BinaryHeap, +} + +impl IntoIterSorted { + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(&self) -> &A { + self.inner.allocator() + } +} + +#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] +impl Iterator for IntoIterSorted { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.inner.pop() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let exact = self.inner.len(); + (exact, Some(exact)) + } +} + +#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] +impl ExactSizeIterator for IntoIterSorted {} + +#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] +impl FusedIterator for IntoIterSorted {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIterSorted {} + +/// A draining iterator over the elements of a `BinaryHeap`. +/// +/// This `struct` is created by [`BinaryHeap::drain()`]. See its +/// documentation for more. +/// +/// [`drain`]: BinaryHeap::drain +#[stable(feature = "drain", since = "1.6.0")] +#[derive(Debug)] +pub struct Drain< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + iter: vec::Drain<'a, T, A>, +} + +impl Drain<'_, T, A> { + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(&self) -> &A { + self.iter.allocator() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl Iterator for Drain<'_, T, A> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl DoubleEndedIterator for Drain<'_, T, A> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl ExactSizeIterator for Drain<'_, T, A> { + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Drain<'_, T, A> {} + +/// A draining iterator over the elements of a `BinaryHeap`. +/// +/// This `struct` is created by [`BinaryHeap::drain_sorted()`]. See its +/// documentation for more. +/// +/// [`drain_sorted`]: BinaryHeap::drain_sorted +#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] +#[derive(Debug)] +pub struct DrainSorted< + 'a, + T: Ord, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + inner: &'a mut BinaryHeap, +} + +impl<'a, T: Ord, A: Allocator> DrainSorted<'a, T, A> { + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(&self) -> &A { + self.inner.allocator() + } +} + +#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] +impl<'a, T: Ord, A: Allocator> Drop for DrainSorted<'a, T, A> { + /// Removes heap elements in heap order. + fn drop(&mut self) { + struct DropGuard<'r, 'a, T: Ord, A: Allocator>(&'r mut DrainSorted<'a, T, A>); + + impl<'r, 'a, T: Ord, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { + fn drop(&mut self) { + while self.0.inner.pop().is_some() {} + } + } + + while let Some(item) = self.inner.pop() { + let guard = DropGuard(self); + drop(item); + mem::forget(guard); + } + } +} + +#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] +impl Iterator for DrainSorted<'_, T, A> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.inner.pop() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let exact = self.inner.len(); + (exact, Some(exact)) + } +} + +#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] +impl ExactSizeIterator for DrainSorted<'_, T, A> {} + +#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] +impl FusedIterator for DrainSorted<'_, T, A> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for DrainSorted<'_, T, A> {} + +#[stable(feature = "binary_heap_extras_15", since = "1.5.0")] +impl From> for BinaryHeap { + /// Converts a `Vec` into a `BinaryHeap`. + /// + /// This conversion happens in-place, and has *O*(*n*) time complexity. + fn from(vec: Vec) -> BinaryHeap { + let mut heap = BinaryHeap { data: vec }; + heap.rebuild(); + heap + } +} + +#[stable(feature = "std_collections_from_array", since = "1.56.0")] +impl From<[T; N]> for BinaryHeap { + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let mut h1 = BinaryHeap::from([1, 4, 2, 3]); + /// let mut h2: BinaryHeap<_> = [1, 4, 2, 3].into(); + /// while let Some((a, b)) = h1.pop().zip(h2.pop()) { + /// assert_eq!(a, b); + /// } + /// ``` + fn from(arr: [T; N]) -> Self { + Self::from_iter(arr) + } +} + +#[stable(feature = "binary_heap_extras_15", since = "1.5.0")] +impl From> for Vec { + /// Converts a `BinaryHeap` into a `Vec`. + /// + /// This conversion requires no data movement or allocation, and has + /// constant time complexity. + fn from(heap: BinaryHeap) -> Vec { + heap.data + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for BinaryHeap { + fn from_iter>(iter: I) -> BinaryHeap { + BinaryHeap::from(iter.into_iter().collect::>()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for BinaryHeap { + type Item = T; + type IntoIter = IntoIter; + + /// Creates a consuming iterator, that is, one that moves each value out of + /// the binary heap in arbitrary order. The binary heap cannot be used + /// after calling this. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let heap = BinaryHeap::from([1, 2, 3, 4]); + /// + /// // Print 1, 2, 3, 4 in arbitrary order + /// for x in heap.into_iter() { + /// // x has type i32, not &i32 + /// println!("{x}"); + /// } + /// ``` + fn into_iter(self) -> IntoIter { + IntoIter { iter: self.data.into_iter() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, A: Allocator> IntoIterator for &'a BinaryHeap { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for BinaryHeap { + #[inline] + fn extend>(&mut self, iter: I) { + let guard = RebuildOnDrop { rebuild_from: self.len(), heap: self }; + guard.heap.data.extend(iter); + } + + #[inline] + fn extend_one(&mut self, item: T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, T: 'a + Ord + Copy, A: Allocator> Extend<&'a T> for BinaryHeap { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()); + } + + #[inline] + fn extend_one(&mut self, &item: &'a T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} diff --git a/CoqOfRust/alloc/collections/binary_heap/tests.rs b/CoqOfRust/alloc/collections/binary_heap/tests.rs new file mode 100644 index 000000000..ad0a020a1 --- /dev/null +++ b/CoqOfRust/alloc/collections/binary_heap/tests.rs @@ -0,0 +1,580 @@ +use std::panic::{AssertUnwindSafe, catch_unwind}; + +use super::*; +use crate::boxed::Box; +use crate::testing::crash_test::{CrashTestDummy, Panic}; + +#[test] +fn test_iterator() { + let data = vec![5, 9, 3]; + let iterout = [9, 5, 3]; + let heap = BinaryHeap::from(data); + let mut i = 0; + for el in &heap { + assert_eq!(*el, iterout[i]); + i += 1; + } +} + +#[test] +fn test_iter_rev_cloned_collect() { + let data = vec![5, 9, 3]; + let iterout = vec![3, 5, 9]; + let pq = BinaryHeap::from(data); + + let v: Vec<_> = pq.iter().rev().cloned().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_into_iter_collect() { + let data = vec![5, 9, 3]; + let iterout = vec![9, 5, 3]; + let pq = BinaryHeap::from(data); + + let v: Vec<_> = pq.into_iter().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_into_iter_size_hint() { + let data = vec![5, 9]; + let pq = BinaryHeap::from(data); + + let mut it = pq.into_iter(); + + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(it.next(), Some(9)); + + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next(), Some(5)); + + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_into_iter_rev_collect() { + let data = vec![5, 9, 3]; + let iterout = vec![3, 5, 9]; + let pq = BinaryHeap::from(data); + + let v: Vec<_> = pq.into_iter().rev().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_into_iter_sorted_collect() { + let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + let it = heap.into_iter_sorted(); + let sorted = it.collect::>(); + assert_eq!(sorted, vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0]); +} + +#[test] +fn test_drain_sorted_collect() { + let mut heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + let it = heap.drain_sorted(); + let sorted = it.collect::>(); + assert_eq!(sorted, vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0]); +} + +fn check_exact_size_iterator(len: usize, it: I) { + let mut it = it; + + for i in 0..it.len() { + let (lower, upper) = it.size_hint(); + assert_eq!(Some(lower), upper); + assert_eq!(lower, len - i); + assert_eq!(it.len(), len - i); + it.next(); + } + assert_eq!(it.len(), 0); + assert!(it.is_empty()); +} + +#[test] +fn test_exact_size_iterator() { + let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + check_exact_size_iterator(heap.len(), heap.iter()); + check_exact_size_iterator(heap.len(), heap.clone().into_iter()); + check_exact_size_iterator(heap.len(), heap.clone().into_iter_sorted()); + check_exact_size_iterator(heap.len(), heap.clone().drain()); + check_exact_size_iterator(heap.len(), heap.clone().drain_sorted()); +} + +fn check_trusted_len(len: usize, it: I) { + let mut it = it; + for i in 0..len { + let (lower, upper) = it.size_hint(); + if upper.is_some() { + assert_eq!(Some(lower), upper); + assert_eq!(lower, len - i); + } + it.next(); + } +} + +#[test] +fn test_trusted_len() { + let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + check_trusted_len(heap.len(), heap.clone().into_iter_sorted()); + check_trusted_len(heap.len(), heap.clone().drain_sorted()); +} + +#[test] +fn test_peek_and_pop() { + let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; + let mut sorted = data.clone(); + sorted.sort(); + let mut heap = BinaryHeap::from(data); + while !heap.is_empty() { + assert_eq!(heap.peek().unwrap(), sorted.last().unwrap()); + assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); + } +} + +#[test] +fn test_peek_mut() { + let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; + let mut heap = BinaryHeap::from(data); + assert_eq!(heap.peek(), Some(&10)); + { + let mut top = heap.peek_mut().unwrap(); + *top -= 2; + } + assert_eq!(heap.peek(), Some(&9)); +} + +#[test] +fn test_peek_mut_leek() { + let data = vec![4, 2, 7]; + let mut heap = BinaryHeap::from(data); + let mut max = heap.peek_mut().unwrap(); + *max = -1; + + // The PeekMut object's Drop impl would have been responsible for moving the + // -1 out of the max position of the BinaryHeap, but we don't run it. + mem::forget(max); + + // Absent some mitigation like leak amplification, the -1 would incorrectly + // end up in the last position of the returned Vec, with the rest of the + // heap's original contents in front of it in sorted order. + let sorted_vec = heap.into_sorted_vec(); + assert!(sorted_vec.is_sorted(), "{:?}", sorted_vec); +} + +#[test] +fn test_peek_mut_pop() { + let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; + let mut heap = BinaryHeap::from(data); + assert_eq!(heap.peek(), Some(&10)); + { + let mut top = heap.peek_mut().unwrap(); + *top -= 2; + assert_eq!(PeekMut::pop(top), 8); + } + assert_eq!(heap.peek(), Some(&9)); +} + +#[test] +fn test_push() { + let mut heap = BinaryHeap::from(vec![2, 4, 9]); + assert_eq!(heap.len(), 3); + assert!(*heap.peek().unwrap() == 9); + heap.push(11); + assert_eq!(heap.len(), 4); + assert!(*heap.peek().unwrap() == 11); + heap.push(5); + assert_eq!(heap.len(), 5); + assert!(*heap.peek().unwrap() == 11); + heap.push(27); + assert_eq!(heap.len(), 6); + assert!(*heap.peek().unwrap() == 27); + heap.push(3); + assert_eq!(heap.len(), 7); + assert!(*heap.peek().unwrap() == 27); + heap.push(103); + assert_eq!(heap.len(), 8); + assert!(*heap.peek().unwrap() == 103); +} + +#[test] +fn test_push_unique() { + let mut heap = BinaryHeap::>::from(vec![Box::new(2), Box::new(4), Box::new(9)]); + assert_eq!(heap.len(), 3); + assert!(**heap.peek().unwrap() == 9); + heap.push(Box::new(11)); + assert_eq!(heap.len(), 4); + assert!(**heap.peek().unwrap() == 11); + heap.push(Box::new(5)); + assert_eq!(heap.len(), 5); + assert!(**heap.peek().unwrap() == 11); + heap.push(Box::new(27)); + assert_eq!(heap.len(), 6); + assert!(**heap.peek().unwrap() == 27); + heap.push(Box::new(3)); + assert_eq!(heap.len(), 7); + assert!(**heap.peek().unwrap() == 27); + heap.push(Box::new(103)); + assert_eq!(heap.len(), 8); + assert!(**heap.peek().unwrap() == 103); +} + +fn check_to_vec(mut data: Vec) { + let heap = BinaryHeap::from(data.clone()); + let mut v = heap.clone().into_vec(); + v.sort(); + data.sort(); + + assert_eq!(v, data); + assert_eq!(heap.into_sorted_vec(), data); +} + +#[test] +fn test_to_vec() { + check_to_vec(vec![]); + check_to_vec(vec![5]); + check_to_vec(vec![3, 2]); + check_to_vec(vec![2, 3]); + check_to_vec(vec![5, 1, 2]); + check_to_vec(vec![1, 100, 2, 3]); + check_to_vec(vec![1, 3, 5, 7, 9, 2, 4, 6, 8, 0]); + check_to_vec(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + check_to_vec(vec![9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]); + check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + check_to_vec(vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]); + check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]); + check_to_vec(vec![5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]); +} + +#[test] +fn test_in_place_iterator_specialization() { + let src: Vec = vec![1, 2, 3]; + let src_ptr = src.as_ptr(); + let heap: BinaryHeap<_> = src.into_iter().map(std::convert::identity).collect(); + let heap_ptr = heap.iter().next().unwrap() as *const usize; + assert_eq!(src_ptr, heap_ptr); + let sink: Vec<_> = heap.into_iter().map(std::convert::identity).collect(); + let sink_ptr = sink.as_ptr(); + assert_eq!(heap_ptr, sink_ptr); +} + +#[test] +fn test_empty_pop() { + let mut heap = BinaryHeap::::new(); + assert!(heap.pop().is_none()); +} + +#[test] +fn test_empty_peek() { + let empty = BinaryHeap::::new(); + assert!(empty.peek().is_none()); +} + +#[test] +fn test_empty_peek_mut() { + let mut empty = BinaryHeap::::new(); + assert!(empty.peek_mut().is_none()); +} + +#[test] +fn test_from_iter() { + let xs = vec![9, 8, 7, 6, 5, 4, 3, 2, 1]; + + let mut q: BinaryHeap<_> = xs.iter().rev().cloned().collect(); + + for &x in &xs { + assert_eq!(q.pop().unwrap(), x); + } +} + +#[test] +fn test_drain() { + let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect(); + + assert_eq!(q.drain().take(5).count(), 5); + + assert!(q.is_empty()); +} + +#[test] +fn test_drain_sorted() { + let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect(); + + assert_eq!(q.drain_sorted().take(5).collect::>(), vec![9, 8, 7, 6, 5]); + + assert!(q.is_empty()); +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_drain_sorted_leak() { + let d0 = CrashTestDummy::new(0); + let d1 = CrashTestDummy::new(1); + let d2 = CrashTestDummy::new(2); + let d3 = CrashTestDummy::new(3); + let d4 = CrashTestDummy::new(4); + let d5 = CrashTestDummy::new(5); + let mut q = BinaryHeap::from(vec![ + d0.spawn(Panic::Never), + d1.spawn(Panic::Never), + d2.spawn(Panic::Never), + d3.spawn(Panic::InDrop), + d4.spawn(Panic::Never), + d5.spawn(Panic::Never), + ]); + + catch_unwind(AssertUnwindSafe(|| drop(q.drain_sorted()))).unwrap_err(); + + assert_eq!(d0.dropped(), 1); + assert_eq!(d1.dropped(), 1); + assert_eq!(d2.dropped(), 1); + assert_eq!(d3.dropped(), 1); + assert_eq!(d4.dropped(), 1); + assert_eq!(d5.dropped(), 1); + assert!(q.is_empty()); +} + +#[test] +fn test_drain_forget() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut q = + BinaryHeap::from(vec![a.spawn(Panic::Never), b.spawn(Panic::Never), c.spawn(Panic::Never)]); + + catch_unwind(AssertUnwindSafe(|| { + let mut it = q.drain(); + it.next(); + mem::forget(it); + })) + .unwrap(); + // Behavior after leaking is explicitly unspecified and order is arbitrary, + // so it's fine if these start failing, but probably worth knowing. + assert!(q.is_empty()); + assert_eq!(a.dropped() + b.dropped() + c.dropped(), 1); + assert_eq!(a.dropped(), 0); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 1); + drop(q); + assert_eq!(a.dropped(), 0); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 1); +} + +#[test] +fn test_drain_sorted_forget() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut q = + BinaryHeap::from(vec![a.spawn(Panic::Never), b.spawn(Panic::Never), c.spawn(Panic::Never)]); + + catch_unwind(AssertUnwindSafe(|| { + let mut it = q.drain_sorted(); + it.next(); + mem::forget(it); + })) + .unwrap(); + // Behavior after leaking is explicitly unspecified, + // so it's fine if these start failing, but probably worth knowing. + assert_eq!(q.len(), 2); + assert_eq!(a.dropped(), 0); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 1); + drop(q); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); + assert_eq!(c.dropped(), 1); +} + +#[test] +fn test_extend_ref() { + let mut a = BinaryHeap::new(); + a.push(1); + a.push(2); + + a.extend(&[3, 4, 5]); + + assert_eq!(a.len(), 5); + assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]); + + let mut a = BinaryHeap::new(); + a.push(1); + a.push(2); + let mut b = BinaryHeap::new(); + b.push(3); + b.push(4); + b.push(5); + + a.extend(&b); + + assert_eq!(a.len(), 5); + assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]); +} + +#[test] +fn test_append() { + let mut a = BinaryHeap::from(vec![-10, 1, 2, 3, 3]); + let mut b = BinaryHeap::from(vec![-20, 5, 43]); + + a.append(&mut b); + + assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); + assert!(b.is_empty()); +} + +#[test] +fn test_append_to_empty() { + let mut a = BinaryHeap::new(); + let mut b = BinaryHeap::from(vec![-20, 5, 43]); + + a.append(&mut b); + + assert_eq!(a.into_sorted_vec(), [-20, 5, 43]); + assert!(b.is_empty()); +} + +#[test] +fn test_extend_specialization() { + let mut a = BinaryHeap::from(vec![-10, 1, 2, 3, 3]); + let b = BinaryHeap::from(vec![-20, 5, 43]); + + a.extend(b); + + assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); +} + +#[allow(dead_code)] +fn assert_covariance() { + fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { + d + } +} + +#[test] +fn test_retain() { + let mut a = BinaryHeap::from(vec![100, 10, 50, 1, 2, 20, 30]); + a.retain(|&x| x != 2); + + // Check that 20 moved into 10's place. + assert_eq!(a.clone().into_vec(), [100, 20, 50, 1, 10, 30]); + + a.retain(|_| true); + + assert_eq!(a.clone().into_vec(), [100, 20, 50, 1, 10, 30]); + + a.retain(|&x| x < 50); + + assert_eq!(a.clone().into_vec(), [30, 20, 10, 1]); + + a.retain(|_| false); + + assert!(a.is_empty()); +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_retain_catch_unwind() { + let mut heap = BinaryHeap::from(vec![3, 1, 2]); + + // Removes the 3, then unwinds out of retain. + let _ = catch_unwind(AssertUnwindSafe(|| { + heap.retain(|e| { + if *e == 1 { + panic!(); + } + false + }); + })); + + // Naively this would be [1, 2] (an invalid heap) if BinaryHeap delegates to + // Vec's retain impl and then does not rebuild the heap after that unwinds. + assert_eq!(heap.into_vec(), [2, 1]); +} + +// old binaryheap failed this test +// +// Integrity means that all elements are present after a comparison panics, +// even if the order might not be correct. +// +// Destructors must be called exactly once per element. +// FIXME: re-enable emscripten once it can unwind again +#[test] +#[cfg(not(target_os = "emscripten"))] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn panic_safe() { + use std::cmp; + use std::panic::{self, AssertUnwindSafe}; + use std::sync::atomic::{AtomicUsize, Ordering}; + + use rand::seq::SliceRandom; + + static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); + + #[derive(Eq, PartialEq, Ord, Clone, Debug)] + struct PanicOrd(T, bool); + + impl Drop for PanicOrd { + fn drop(&mut self) { + // update global drop count + DROP_COUNTER.fetch_add(1, Ordering::SeqCst); + } + } + + impl PartialOrd for PanicOrd { + fn partial_cmp(&self, other: &Self) -> Option { + if self.1 || other.1 { + panic!("Panicking comparison"); + } + self.0.partial_cmp(&other.0) + } + } + let mut rng = crate::test_helpers::test_rng(); + const DATASZ: usize = 32; + // Miri is too slow + let ntest = if cfg!(miri) { 1 } else { 10 }; + + // don't use 0 in the data -- we want to catch the zeroed-out case. + let data = (1..=DATASZ).collect::>(); + + // since it's a fuzzy test, run several tries. + for _ in 0..ntest { + for i in 1..=DATASZ { + DROP_COUNTER.store(0, Ordering::SeqCst); + + let mut panic_ords: Vec<_> = + data.iter().filter(|&&x| x != i).map(|&x| PanicOrd(x, false)).collect(); + let panic_item = PanicOrd(i, true); + + // heapify the sane items + panic_ords.shuffle(&mut rng); + let mut heap = BinaryHeap::from(panic_ords); + let inner_data; + + { + // push the panicking item to the heap and catch the panic + let thread_result = { + let mut heap_ref = AssertUnwindSafe(&mut heap); + panic::catch_unwind(move || { + heap_ref.push(panic_item); + }) + }; + assert!(thread_result.is_err()); + + // Assert no elements were dropped + let drops = DROP_COUNTER.load(Ordering::SeqCst); + assert!(drops == 0, "Must not drop items. drops={}", drops); + inner_data = heap.clone().into_vec(); + drop(heap); + } + let drops = DROP_COUNTER.load(Ordering::SeqCst); + assert_eq!(drops, DATASZ); + + let mut data_sorted = inner_data.into_iter().map(|p| p.0).collect::>(); + data_sorted.sort(); + assert_eq!(data_sorted, data); + } + } +} diff --git a/CoqOfRust/alloc/collections/btree/append.rs b/CoqOfRust/alloc/collections/btree/append.rs new file mode 100644 index 000000000..d137d2721 --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/append.rs @@ -0,0 +1,108 @@ +use core::alloc::Allocator; +use core::iter::FusedIterator; + +use super::merge_iter::MergeIterInner; +use super::node::{self, Root}; + +impl Root { + /// Appends all key-value pairs from the union of two ascending iterators, + /// incrementing a `length` variable along the way. The latter makes it + /// easier for the caller to avoid a leak when a drop handler panicks. + /// + /// If both iterators produce the same key, this method drops the pair from + /// the left iterator and appends the pair from the right iterator. + /// + /// If you want the tree to end up in a strictly ascending order, like for + /// a `BTreeMap`, both iterators should produce keys in strictly ascending + /// order, each greater than all keys in the tree, including any keys + /// already in the tree upon entry. + pub fn append_from_sorted_iters( + &mut self, + left: I, + right: I, + length: &mut usize, + alloc: A, + ) where + K: Ord, + I: Iterator + FusedIterator, + { + // We prepare to merge `left` and `right` into a sorted sequence in linear time. + let iter = MergeIter(MergeIterInner::new(left, right)); + + // Meanwhile, we build a tree from the sorted sequence in linear time. + self.bulk_push(iter, length, alloc) + } + + /// Pushes all key-value pairs to the end of the tree, incrementing a + /// `length` variable along the way. The latter makes it easier for the + /// caller to avoid a leak when the iterator panicks. + pub fn bulk_push(&mut self, iter: I, length: &mut usize, alloc: A) + where + I: Iterator, + { + let mut cur_node = self.borrow_mut().last_leaf_edge().into_node(); + // Iterate through all key-value pairs, pushing them into nodes at the right level. + for (key, value) in iter { + // Try to push key-value pair into the current leaf node. + if cur_node.len() < node::CAPACITY { + cur_node.push(key, value); + } else { + // No space left, go up and push there. + let mut open_node; + let mut test_node = cur_node.forget_type(); + loop { + match test_node.ascend() { + Ok(parent) => { + let parent = parent.into_node(); + if parent.len() < node::CAPACITY { + // Found a node with space left, push here. + open_node = parent; + break; + } else { + // Go up again. + test_node = parent.forget_type(); + } + } + Err(_) => { + // We are at the top, create a new root node and push there. + open_node = self.push_internal_level(alloc.clone()); + break; + } + } + } + + // Push key-value pair and new right subtree. + let tree_height = open_node.height() - 1; + let mut right_tree = Root::new(alloc.clone()); + for _ in 0..tree_height { + right_tree.push_internal_level(alloc.clone()); + } + open_node.push(key, value, right_tree); + + // Go down to the rightmost leaf again. + cur_node = open_node.forget_type().last_leaf_edge().into_node(); + } + + // Increment length every iteration, to make sure the map drops + // the appended elements even if advancing the iterator panicks. + *length += 1; + } + self.fix_right_border_of_plentiful(); + } +} + +// An iterator for merging two sorted sequences into one +struct MergeIter>(MergeIterInner); + +impl Iterator for MergeIter +where + I: Iterator + FusedIterator, +{ + type Item = (K, V); + + /// If two keys are equal, returns the key-value pair from the right source. + fn next(&mut self) -> Option<(K, V)> { + let (a_next, b_next) = self.0.nexts(|a: &(K, V), b: &(K, V)| K::cmp(&a.0, &b.0)); + b_next.or(a_next) + } +} diff --git a/CoqOfRust/alloc/collections/btree/borrow.rs b/CoqOfRust/alloc/collections/btree/borrow.rs new file mode 100644 index 000000000..000b9bd0f --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/borrow.rs @@ -0,0 +1,69 @@ +use core::marker::PhantomData; +use core::ptr::NonNull; + +/// Models a reborrow of some unique reference, when you know that the reborrow +/// and all its descendants (i.e., all pointers and references derived from it) +/// will not be used any more at some point, after which you want to use the +/// original unique reference again. +/// +/// The borrow checker usually handles this stacking of borrows for you, but +/// some control flows that accomplish this stacking are too complicated for +/// the compiler to follow. A `DormantMutRef` allows you to check borrowing +/// yourself, while still expressing its stacked nature, and encapsulating +/// the raw pointer code needed to do this without undefined behavior. +pub struct DormantMutRef<'a, T> { + ptr: NonNull, + _marker: PhantomData<&'a mut T>, +} + +unsafe impl<'a, T> Sync for DormantMutRef<'a, T> where &'a mut T: Sync {} +unsafe impl<'a, T> Send for DormantMutRef<'a, T> where &'a mut T: Send {} + +impl<'a, T> DormantMutRef<'a, T> { + /// Capture a unique borrow, and immediately reborrow it. For the compiler, + /// the lifetime of the new reference is the same as the lifetime of the + /// original reference, but you promise to use it for a shorter period. + pub fn new(t: &'a mut T) -> (&'a mut T, Self) { + let ptr = NonNull::from(t); + // SAFETY: we hold the borrow throughout 'a via `_marker`, and we expose + // only this reference, so it is unique. + let new_ref = unsafe { &mut *ptr.as_ptr() }; + (new_ref, Self { ptr, _marker: PhantomData }) + } + + /// Revert to the unique borrow initially captured. + /// + /// # Safety + /// + /// The reborrow must have ended, i.e., the reference returned by `new` and + /// all pointers and references derived from it, must not be used anymore. + pub unsafe fn awaken(self) -> &'a mut T { + // SAFETY: our own safety conditions imply this reference is again unique. + unsafe { &mut *self.ptr.as_ptr() } + } + + /// Borrows a new mutable reference from the unique borrow initially captured. + /// + /// # Safety + /// + /// The reborrow must have ended, i.e., the reference returned by `new` and + /// all pointers and references derived from it, must not be used anymore. + pub unsafe fn reborrow(&mut self) -> &'a mut T { + // SAFETY: our own safety conditions imply this reference is again unique. + unsafe { &mut *self.ptr.as_ptr() } + } + + /// Borrows a new shared reference from the unique borrow initially captured. + /// + /// # Safety + /// + /// The reborrow must have ended, i.e., the reference returned by `new` and + /// all pointers and references derived from it, must not be used anymore. + pub unsafe fn reborrow_shared(&self) -> &'a T { + // SAFETY: our own safety conditions imply this reference is again unique. + unsafe { &*self.ptr.as_ptr() } + } +} + +#[cfg(test)] +mod tests; diff --git a/CoqOfRust/alloc/collections/btree/borrow/tests.rs b/CoqOfRust/alloc/collections/btree/borrow/tests.rs new file mode 100644 index 000000000..56a8434fc --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/borrow/tests.rs @@ -0,0 +1,19 @@ +use super::DormantMutRef; + +#[test] +fn test_borrow() { + let mut data = 1; + let mut stack = vec![]; + let mut rr = &mut data; + for factor in [2, 3, 7].iter() { + let (r, dormant_r) = DormantMutRef::new(rr); + rr = r; + assert_eq!(*rr, 1); + stack.push((factor, dormant_r)); + } + while let Some((factor, dormant_r)) = stack.pop() { + let r = unsafe { dormant_r.awaken() }; + *r *= factor; + } + assert_eq!(data, 42); +} diff --git a/CoqOfRust/alloc/collections/btree/dedup_sorted_iter.rs b/CoqOfRust/alloc/collections/btree/dedup_sorted_iter.rs new file mode 100644 index 000000000..cd6a88f32 --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/dedup_sorted_iter.rs @@ -0,0 +1,49 @@ +use core::iter::Peekable; + +/// An iterator for deduping the key of a sorted iterator. +/// When encountering the duplicated key, only the last key-value pair is yielded. +/// +/// Used by [`BTreeMap::bulk_build_from_sorted_iter`][1]. +/// +/// [1]: crate::collections::BTreeMap::bulk_build_from_sorted_iter +pub struct DedupSortedIter +where + I: Iterator, +{ + iter: Peekable, +} + +impl DedupSortedIter +where + I: Iterator, +{ + pub fn new(iter: I) -> Self { + Self { iter: iter.peekable() } + } +} + +impl Iterator for DedupSortedIter +where + K: Eq, + I: Iterator, +{ + type Item = (K, V); + + fn next(&mut self) -> Option<(K, V)> { + loop { + let next = match self.iter.next() { + Some(next) => next, + None => return None, + }; + + let peeked = match self.iter.peek() { + Some(peeked) => peeked, + None => return Some(next), + }; + + if next.0 != peeked.0 { + return Some(next); + } + } + } +} diff --git a/CoqOfRust/alloc/collections/btree/fix.rs b/CoqOfRust/alloc/collections/btree/fix.rs new file mode 100644 index 000000000..09edea355 --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/fix.rs @@ -0,0 +1,182 @@ +use core::alloc::Allocator; + +use super::map::MIN_LEN; +use super::node::ForceResult::*; +use super::node::LeftOrRight::*; +use super::node::{Handle, NodeRef, Root, marker}; + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + /// Stocks up a possibly underfull node by merging with or stealing from a + /// sibling. If successful but at the cost of shrinking the parent node, + /// returns that shrunk parent node. Returns an `Err` if the node is + /// an empty root. + fn fix_node_through_parent( + self, + alloc: A, + ) -> Result, K, V, marker::Internal>>, Self> { + let len = self.len(); + if len >= MIN_LEN { + Ok(None) + } else { + match self.choose_parent_kv() { + Ok(Left(mut left_parent_kv)) => { + if left_parent_kv.can_merge() { + let parent = left_parent_kv.merge_tracking_parent(alloc); + Ok(Some(parent)) + } else { + left_parent_kv.bulk_steal_left(MIN_LEN - len); + Ok(None) + } + } + Ok(Right(mut right_parent_kv)) => { + if right_parent_kv.can_merge() { + let parent = right_parent_kv.merge_tracking_parent(alloc); + Ok(Some(parent)) + } else { + right_parent_kv.bulk_steal_right(MIN_LEN - len); + Ok(None) + } + } + Err(root) => { + if len > 0 { + Ok(None) + } else { + Err(root) + } + } + } + } + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + /// Stocks up a possibly underfull node, and if that causes its parent node + /// to shrink, stocks up the parent, recursively. + /// Returns `true` if it fixed the tree, `false` if it couldn't because the + /// root node became empty. + /// + /// This method does not expect ancestors to already be underfull upon entry + /// and panics if it encounters an empty ancestor. + pub fn fix_node_and_affected_ancestors(mut self, alloc: A) -> bool { + loop { + match self.fix_node_through_parent(alloc.clone()) { + Ok(Some(parent)) => self = parent.forget_type(), + Ok(None) => return true, + Err(_) => return false, + } + } + } +} + +impl Root { + /// Removes empty levels on the top, but keeps an empty leaf if the entire tree is empty. + pub fn fix_top(&mut self, alloc: A) { + while self.height() > 0 && self.len() == 0 { + self.pop_internal_level(alloc.clone()); + } + } + + /// Stocks up or merge away any underfull nodes on the right border of the + /// tree. The other nodes, those that are not the root nor a rightmost edge, + /// must already have at least MIN_LEN elements. + pub fn fix_right_border(&mut self, alloc: A) { + self.fix_top(alloc.clone()); + if self.len() > 0 { + self.borrow_mut().last_kv().fix_right_border_of_right_edge(alloc.clone()); + self.fix_top(alloc); + } + } + + /// The symmetric clone of `fix_right_border`. + pub fn fix_left_border(&mut self, alloc: A) { + self.fix_top(alloc.clone()); + if self.len() > 0 { + self.borrow_mut().first_kv().fix_left_border_of_left_edge(alloc.clone()); + self.fix_top(alloc); + } + } + + /// Stocks up any underfull nodes on the right border of the tree. + /// The other nodes, those that are neither the root nor a rightmost edge, + /// must be prepared to have up to MIN_LEN elements stolen. + pub fn fix_right_border_of_plentiful(&mut self) { + let mut cur_node = self.borrow_mut(); + while let Internal(internal) = cur_node.force() { + // Check if rightmost child is underfull. + let mut last_kv = internal.last_kv().consider_for_balancing(); + debug_assert!(last_kv.left_child_len() >= MIN_LEN * 2); + let right_child_len = last_kv.right_child_len(); + if right_child_len < MIN_LEN { + // We need to steal. + last_kv.bulk_steal_left(MIN_LEN - right_child_len); + } + + // Go further down. + cur_node = last_kv.into_right_child(); + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::LeafOrInternal>, marker::KV> { + fn fix_left_border_of_left_edge(mut self, alloc: A) { + while let Internal(internal_kv) = self.force() { + self = internal_kv.fix_left_child(alloc.clone()).first_kv(); + debug_assert!(self.reborrow().into_node().len() > MIN_LEN); + } + } + + fn fix_right_border_of_right_edge(mut self, alloc: A) { + while let Internal(internal_kv) = self.force() { + self = internal_kv.fix_right_child(alloc.clone()).last_kv(); + debug_assert!(self.reborrow().into_node().len() > MIN_LEN); + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, marker::KV> { + /// Stocks up the left child, assuming the right child isn't underfull, and + /// provisions an extra element to allow merging its children in turn + /// without becoming underfull. + /// Returns the left child. + fn fix_left_child( + self, + alloc: A, + ) -> NodeRef, K, V, marker::LeafOrInternal> { + let mut internal_kv = self.consider_for_balancing(); + let left_len = internal_kv.left_child_len(); + debug_assert!(internal_kv.right_child_len() >= MIN_LEN); + if internal_kv.can_merge() { + internal_kv.merge_tracking_child(alloc) + } else { + // `MIN_LEN + 1` to avoid readjust if merge happens on the next level. + let count = (MIN_LEN + 1).saturating_sub(left_len); + if count > 0 { + internal_kv.bulk_steal_right(count); + } + internal_kv.into_left_child() + } + } + + /// Stocks up the right child, assuming the left child isn't underfull, and + /// provisions an extra element to allow merging its children in turn + /// without becoming underfull. + /// Returns wherever the right child ended up. + fn fix_right_child( + self, + alloc: A, + ) -> NodeRef, K, V, marker::LeafOrInternal> { + let mut internal_kv = self.consider_for_balancing(); + let right_len = internal_kv.right_child_len(); + debug_assert!(internal_kv.left_child_len() >= MIN_LEN); + if internal_kv.can_merge() { + internal_kv.merge_tracking_child(alloc) + } else { + // `MIN_LEN + 1` to avoid readjust if merge happens on the next level. + let count = (MIN_LEN + 1).saturating_sub(right_len); + if count > 0 { + internal_kv.bulk_steal_left(count); + } + internal_kv.into_right_child() + } + } +} diff --git a/CoqOfRust/alloc/collections/btree/map.rs b/CoqOfRust/alloc/collections/btree/map.rs new file mode 100644 index 000000000..d1ce4e215 --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/map.rs @@ -0,0 +1,3478 @@ +use core::borrow::Borrow; +use core::cmp::Ordering; +use core::error::Error; +use core::fmt::{self, Debug}; +use core::hash::{Hash, Hasher}; +use core::iter::FusedIterator; +use core::marker::PhantomData; +use core::mem::{self, ManuallyDrop}; +use core::ops::{Bound, Index, RangeBounds}; +use core::ptr; + +use super::borrow::DormantMutRef; +use super::dedup_sorted_iter::DedupSortedIter; +use super::navigate::{LazyLeafRange, LeafRange}; +use super::node::ForceResult::*; +use super::node::{self, Handle, NodeRef, Root, marker}; +use super::search::SearchBound; +use super::search::SearchResult::*; +use super::set_val::SetValZST; +use crate::alloc::{Allocator, Global}; +use crate::vec::Vec; + +mod entry; + +use Entry::*; +#[stable(feature = "rust1", since = "1.0.0")] +pub use entry::{Entry, OccupiedEntry, OccupiedError, VacantEntry}; + +/// Minimum number of elements in a node that is not a root. +/// We might temporarily have fewer elements during methods. +pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT; + +// A tree in a `BTreeMap` is a tree in the `node` module with additional invariants: +// - Keys must appear in ascending order (according to the key's type). +// - Every non-leaf node contains at least 1 element (has at least 2 children). +// - Every non-root node contains at least MIN_LEN elements. +// +// An empty map is represented either by the absence of a root node or by a +// root node that is an empty leaf. + +/// An ordered map based on a [B-Tree]. +/// +/// B-Trees represent a fundamental compromise between cache-efficiency and actually minimizing +/// the amount of work performed in a search. In theory, a binary search tree (BST) is the optimal +/// choice for a sorted map, as a perfectly balanced BST performs the theoretical minimum amount of +/// comparisons necessary to find an element (log2n). However, in practice the way this +/// is done is *very* inefficient for modern computer architectures. In particular, every element +/// is stored in its own individually heap-allocated node. This means that every single insertion +/// triggers a heap-allocation, and every single comparison should be a cache-miss. Since these +/// are both notably expensive things to do in practice, we are forced to, at the very least, +/// reconsider the BST strategy. +/// +/// A B-Tree instead makes each node contain B-1 to 2B-1 elements in a contiguous array. By doing +/// this, we reduce the number of allocations by a factor of B, and improve cache efficiency in +/// searches. However, this does mean that searches will have to do *more* comparisons on average. +/// The precise number of comparisons depends on the node search strategy used. For optimal cache +/// efficiency, one could search the nodes linearly. For optimal comparisons, one could search +/// the node using binary search. As a compromise, one could also perform a linear search +/// that initially only checks every ith element for some choice of i. +/// +/// Currently, our implementation simply performs naive linear search. This provides excellent +/// performance on *small* nodes of elements which are cheap to compare. However in the future we +/// would like to further explore choosing the optimal search strategy based on the choice of B, +/// and possibly other factors. Using linear search, searching for a random element is expected +/// to take B * log(n) comparisons, which is generally worse than a BST. In practice, +/// however, performance is excellent. +/// +/// It is a logic error for a key to be modified in such a way that the key's ordering relative to +/// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is +/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. +/// The behavior resulting from such a logic error is not specified, but will be encapsulated to the +/// `BTreeMap` that observed the logic error and not result in undefined behavior. This could +/// include panics, incorrect results, aborts, memory leaks, and non-termination. +/// +/// Iterators obtained from functions such as [`BTreeMap::iter`], [`BTreeMap::into_iter`], [`BTreeMap::values`], or +/// [`BTreeMap::keys`] produce their items in order by key, and take worst-case logarithmic and +/// amortized constant time per item returned. +/// +/// [B-Tree]: https://en.wikipedia.org/wiki/B-tree +/// [`Cell`]: core::cell::Cell +/// [`RefCell`]: core::cell::RefCell +/// +/// # Examples +/// +/// ``` +/// use std::collections::BTreeMap; +/// +/// // type inference lets us omit an explicit type signature (which +/// // would be `BTreeMap<&str, &str>` in this example). +/// let mut movie_reviews = BTreeMap::new(); +/// +/// // review some movies. +/// movie_reviews.insert("Office Space", "Deals with real issues in the workplace."); +/// movie_reviews.insert("Pulp Fiction", "Masterpiece."); +/// movie_reviews.insert("The Godfather", "Very enjoyable."); +/// movie_reviews.insert("The Blues Brothers", "Eye lyked it a lot."); +/// +/// // check for a specific one. +/// if !movie_reviews.contains_key("Les Misérables") { +/// println!("We've got {} reviews, but Les Misérables ain't one.", +/// movie_reviews.len()); +/// } +/// +/// // oops, this review has a lot of spelling mistakes, let's delete it. +/// movie_reviews.remove("The Blues Brothers"); +/// +/// // look up the values associated with some keys. +/// let to_find = ["Up!", "Office Space"]; +/// for movie in &to_find { +/// match movie_reviews.get(movie) { +/// Some(review) => println!("{movie}: {review}"), +/// None => println!("{movie} is unreviewed.") +/// } +/// } +/// +/// // Look up the value for a key (will panic if the key is not found). +/// println!("Movie review: {}", movie_reviews["Office Space"]); +/// +/// // iterate over everything. +/// for (movie, review) in &movie_reviews { +/// println!("{movie}: \"{review}\""); +/// } +/// ``` +/// +/// A `BTreeMap` with a known list of items can be initialized from an array: +/// +/// ``` +/// use std::collections::BTreeMap; +/// +/// let solar_distance = BTreeMap::from([ +/// ("Mercury", 0.4), +/// ("Venus", 0.7), +/// ("Earth", 1.0), +/// ("Mars", 1.5), +/// ]); +/// ``` +/// +/// `BTreeMap` implements an [`Entry API`], which allows for complex +/// methods of getting, setting, updating and removing keys and their values: +/// +/// [`Entry API`]: BTreeMap::entry +/// +/// ``` +/// use std::collections::BTreeMap; +/// +/// // type inference lets us omit an explicit type signature (which +/// // would be `BTreeMap<&str, u8>` in this example). +/// let mut player_stats = BTreeMap::new(); +/// +/// fn random_stat_buff() -> u8 { +/// // could actually return some random value here - let's just return +/// // some fixed value for now +/// 42 +/// } +/// +/// // insert a key only if it doesn't already exist +/// player_stats.entry("health").or_insert(100); +/// +/// // insert a key using a function that provides a new value only if it +/// // doesn't already exist +/// player_stats.entry("defence").or_insert_with(random_stat_buff); +/// +/// // update a key, guarding against the key possibly not being set +/// let stat = player_stats.entry("attack").or_insert(100); +/// *stat += random_stat_buff(); +/// +/// // modify an entry before an insert with in-place mutation +/// player_stats.entry("mana").and_modify(|mana| *mana += 200).or_insert(100); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeMap")] +#[rustc_insignificant_dtor] +pub struct BTreeMap< + K, + V, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + root: Option>, + length: usize, + /// `ManuallyDrop` to control drop order (needs to be dropped after all the nodes). + pub(super) alloc: ManuallyDrop, + // For dropck; the `Box` avoids making the `Unpin` impl more strict than before + _marker: PhantomData>, +} + +#[stable(feature = "btree_drop", since = "1.7.0")] +unsafe impl<#[may_dangle] K, #[may_dangle] V, A: Allocator + Clone> Drop for BTreeMap { + fn drop(&mut self) { + drop(unsafe { ptr::read(self) }.into_iter()) + } +} + +// FIXME: This implementation is "wrong", but changing it would be a breaking change. +// (The bounds of the automatic `UnwindSafe` implementation have been like this since Rust 1.50.) +// Maybe we can fix it nonetheless with a crater run, or if the `UnwindSafe` +// traits are deprecated, or disarmed (no longer causing hard errors) in the future. +#[stable(feature = "btree_unwindsafe", since = "1.64.0")] +impl core::panic::UnwindSafe for BTreeMap +where + A: core::panic::UnwindSafe, + K: core::panic::RefUnwindSafe, + V: core::panic::RefUnwindSafe, +{ +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for BTreeMap { + fn clone(&self) -> BTreeMap { + fn clone_subtree<'a, K: Clone, V: Clone, A: Allocator + Clone>( + node: NodeRef, K, V, marker::LeafOrInternal>, + alloc: A, + ) -> BTreeMap + where + K: 'a, + V: 'a, + { + match node.force() { + Leaf(leaf) => { + let mut out_tree = BTreeMap { + root: Some(Root::new(alloc.clone())), + length: 0, + alloc: ManuallyDrop::new(alloc), + _marker: PhantomData, + }; + + { + let root = out_tree.root.as_mut().unwrap(); // unwrap succeeds because we just wrapped + let mut out_node = match root.borrow_mut().force() { + Leaf(leaf) => leaf, + Internal(_) => unreachable!(), + }; + + let mut in_edge = leaf.first_edge(); + while let Ok(kv) = in_edge.right_kv() { + let (k, v) = kv.into_kv(); + in_edge = kv.right_edge(); + + out_node.push(k.clone(), v.clone()); + out_tree.length += 1; + } + } + + out_tree + } + Internal(internal) => { + let mut out_tree = + clone_subtree(internal.first_edge().descend(), alloc.clone()); + + { + let out_root = out_tree.root.as_mut().unwrap(); + let mut out_node = out_root.push_internal_level(alloc.clone()); + let mut in_edge = internal.first_edge(); + while let Ok(kv) = in_edge.right_kv() { + let (k, v) = kv.into_kv(); + in_edge = kv.right_edge(); + + let k = (*k).clone(); + let v = (*v).clone(); + let subtree = clone_subtree(in_edge.descend(), alloc.clone()); + + // We can't destructure subtree directly + // because BTreeMap implements Drop + let (subroot, sublength) = unsafe { + let subtree = ManuallyDrop::new(subtree); + let root = ptr::read(&subtree.root); + let length = subtree.length; + (root, length) + }; + + out_node.push( + k, + v, + subroot.unwrap_or_else(|| Root::new(alloc.clone())), + ); + out_tree.length += 1 + sublength; + } + } + + out_tree + } + } + } + + if self.is_empty() { + BTreeMap::new_in((*self.alloc).clone()) + } else { + clone_subtree(self.root.as_ref().unwrap().reborrow(), (*self.alloc).clone()) // unwrap succeeds because not empty + } + } +} + +/// Internal functionality for `BTreeSet`. +impl BTreeMap { + pub(super) fn replace(&mut self, key: K) -> Option + where + K: Ord, + { + let (map, dormant_map) = DormantMutRef::new(self); + let root_node = + map.root.get_or_insert_with(|| Root::new((*map.alloc).clone())).borrow_mut(); + match root_node.search_tree::(&key) { + Found(mut kv) => Some(mem::replace(kv.key_mut(), key)), + GoDown(handle) => { + VacantEntry { + key, + handle: Some(handle), + dormant_map, + alloc: (*map.alloc).clone(), + _marker: PhantomData, + } + .insert(SetValZST); + None + } + } + } + + pub(super) fn get_or_insert_with(&mut self, q: &Q, f: F) -> &K + where + K: Borrow + Ord, + Q: Ord, + F: FnOnce(&Q) -> K, + { + let (map, dormant_map) = DormantMutRef::new(self); + let root_node = + map.root.get_or_insert_with(|| Root::new((*map.alloc).clone())).borrow_mut(); + match root_node.search_tree(q) { + Found(handle) => handle.into_kv_mut().0, + GoDown(handle) => { + let key = f(q); + assert!(*key.borrow() == *q, "new value is not equal"); + VacantEntry { + key, + handle: Some(handle), + dormant_map, + alloc: (*map.alloc).clone(), + _marker: PhantomData, + } + .insert_entry(SetValZST) + .into_key() + } + } + } +} + +/// An iterator over the entries of a `BTreeMap`. +/// +/// This `struct` is created by the [`iter`] method on [`BTreeMap`]. See its +/// documentation for more. +/// +/// [`iter`]: BTreeMap::iter +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Iter<'a, K: 'a, V: 'a> { + range: LazyLeafRange, K, V>, + length: usize, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Iter<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl<'a, K: 'a, V: 'a> Default for Iter<'a, K, V> { + /// Creates an empty `btree_map::Iter`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::Iter<'_, u8, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Iter { range: Default::default(), length: 0 } + } +} + +/// A mutable iterator over the entries of a `BTreeMap`. +/// +/// This `struct` is created by the [`iter_mut`] method on [`BTreeMap`]. See its +/// documentation for more. +/// +/// [`iter_mut`]: BTreeMap::iter_mut +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IterMut<'a, K: 'a, V: 'a> { + range: LazyLeafRange, K, V>, + length: usize, + + // Be invariant in `K` and `V` + _marker: PhantomData<&'a mut (K, V)>, +} + +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for IterMut<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let range = Iter { range: self.range.reborrow(), length: self.length }; + f.debug_list().entries(range).finish() + } +} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl<'a, K: 'a, V: 'a> Default for IterMut<'a, K, V> { + /// Creates an empty `btree_map::IterMut`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::IterMut<'_, u8, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + IterMut { range: Default::default(), length: 0, _marker: PhantomData {} } + } +} + +/// An owning iterator over the entries of a `BTreeMap`, sorted by key. +/// +/// This `struct` is created by the [`into_iter`] method on [`BTreeMap`] +/// (provided by the [`IntoIterator`] trait). See its documentation for more. +/// +/// [`into_iter`]: IntoIterator::into_iter +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_insignificant_dtor] +pub struct IntoIter< + K, + V, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + range: LazyLeafRange, + length: usize, + /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`. + alloc: A, +} + +impl IntoIter { + /// Returns an iterator of references over the remaining items. + #[inline] + pub(super) fn iter(&self) -> Iter<'_, K, V> { + Iter { range: self.range.reborrow(), length: self.length } + } +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.iter()).finish() + } +} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for IntoIter +where + A: Allocator + Default + Clone, +{ + /// Creates an empty `btree_map::IntoIter`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::IntoIter = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + IntoIter { range: Default::default(), length: 0, alloc: Default::default() } + } +} + +/// An iterator over the keys of a `BTreeMap`. +/// +/// This `struct` is created by the [`keys`] method on [`BTreeMap`]. See its +/// documentation for more. +/// +/// [`keys`]: BTreeMap::keys +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Keys<'a, K, V> { + inner: Iter<'a, K, V>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Keys<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +/// An iterator over the values of a `BTreeMap`. +/// +/// This `struct` is created by the [`values`] method on [`BTreeMap`]. See its +/// documentation for more. +/// +/// [`values`]: BTreeMap::values +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Values<'a, K, V> { + inner: Iter<'a, K, V>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Values<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +/// A mutable iterator over the values of a `BTreeMap`. +/// +/// This `struct` is created by the [`values_mut`] method on [`BTreeMap`]. See its +/// documentation for more. +/// +/// [`values_mut`]: BTreeMap::values_mut +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "map_values_mut", since = "1.10.0")] +pub struct ValuesMut<'a, K, V> { + inner: IterMut<'a, K, V>, +} + +#[stable(feature = "map_values_mut", since = "1.10.0")] +impl fmt::Debug for ValuesMut<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.inner.iter().map(|(_, val)| val)).finish() + } +} + +/// An owning iterator over the keys of a `BTreeMap`. +/// +/// This `struct` is created by the [`into_keys`] method on [`BTreeMap`]. +/// See its documentation for more. +/// +/// [`into_keys`]: BTreeMap::into_keys +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "map_into_keys_values", since = "1.54.0")] +pub struct IntoKeys { + inner: IntoIter, +} + +#[stable(feature = "map_into_keys_values", since = "1.54.0")] +impl fmt::Debug for IntoKeys { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.inner.iter().map(|(key, _)| key)).finish() + } +} + +/// An owning iterator over the values of a `BTreeMap`. +/// +/// This `struct` is created by the [`into_values`] method on [`BTreeMap`]. +/// See its documentation for more. +/// +/// [`into_values`]: BTreeMap::into_values +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "map_into_keys_values", since = "1.54.0")] +pub struct IntoValues< + K, + V, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + inner: IntoIter, +} + +#[stable(feature = "map_into_keys_values", since = "1.54.0")] +impl fmt::Debug for IntoValues { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.inner.iter().map(|(_, val)| val)).finish() + } +} + +/// An iterator over a sub-range of entries in a `BTreeMap`. +/// +/// This `struct` is created by the [`range`] method on [`BTreeMap`]. See its +/// documentation for more. +/// +/// [`range`]: BTreeMap::range +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "btree_range", since = "1.17.0")] +pub struct Range<'a, K: 'a, V: 'a> { + inner: LeafRange, K, V>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Range<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +/// A mutable iterator over a sub-range of entries in a `BTreeMap`. +/// +/// This `struct` is created by the [`range_mut`] method on [`BTreeMap`]. See its +/// documentation for more. +/// +/// [`range_mut`]: BTreeMap::range_mut +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "btree_range", since = "1.17.0")] +pub struct RangeMut<'a, K: 'a, V: 'a> { + inner: LeafRange, K, V>, + + // Be invariant in `K` and `V` + _marker: PhantomData<&'a mut (K, V)>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for RangeMut<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let range = Range { inner: self.inner.reborrow() }; + f.debug_list().entries(range).finish() + } +} + +impl BTreeMap { + /// Makes a new, empty `BTreeMap`. + /// + /// Does not allocate anything on its own. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// + /// // entries can now be inserted into the empty map + /// map.insert(1, "a"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_btree_new", since = "1.66.0")] + #[inline] + #[must_use] + pub const fn new() -> BTreeMap { + BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(Global), _marker: PhantomData } + } +} + +impl BTreeMap { + /// Clears the map, removing all elements. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(1, "a"); + /// a.clear(); + /// assert!(a.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + // avoid moving the allocator + drop(BTreeMap { + root: mem::replace(&mut self.root, None), + length: mem::replace(&mut self.length, 0), + alloc: self.alloc.clone(), + _marker: PhantomData, + }); + } + + /// Makes a new empty BTreeMap with a reasonable choice for B. + /// + /// # Examples + /// + /// ``` + /// # #![feature(allocator_api)] + /// # #![feature(btreemap_alloc)] + /// use std::collections::BTreeMap; + /// use std::alloc::Global; + /// + /// let mut map = BTreeMap::new_in(Global); + /// + /// // entries can now be inserted into the empty map + /// map.insert(1, "a"); + /// ``` + #[unstable(feature = "btreemap_alloc", issue = "32838")] + pub const fn new_in(alloc: A) -> BTreeMap { + BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(alloc), _marker: PhantomData } + } +} + +impl BTreeMap { + /// Returns a reference to the value corresponding to the key. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.get(&1), Some(&"a")); + /// assert_eq!(map.get(&2), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get(&self, key: &Q) -> Option<&V> + where + K: Borrow + Ord, + Q: Ord, + { + let root_node = self.root.as_ref()?.reborrow(); + match root_node.search_tree(key) { + Found(handle) => Some(handle.into_kv().1), + GoDown(_) => None, + } + } + + /// Returns the key-value pair corresponding to the supplied key. This is + /// potentially useful: + /// - for key types where non-identical keys can be considered equal; + /// - for getting the `&K` stored key value from a borrowed `&Q` lookup key; or + /// - for getting a reference to a key with the same lifetime as the collection. + /// + /// The supplied key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// use std::collections::BTreeMap; + /// + /// #[derive(Clone, Copy, Debug)] + /// struct S { + /// id: u32, + /// # #[allow(unused)] // prevents a "field `name` is never read" error + /// name: &'static str, // ignored by equality and ordering operations + /// } + /// + /// impl PartialEq for S { + /// fn eq(&self, other: &S) -> bool { + /// self.id == other.id + /// } + /// } + /// + /// impl Eq for S {} + /// + /// impl PartialOrd for S { + /// fn partial_cmp(&self, other: &S) -> Option { + /// self.id.partial_cmp(&other.id) + /// } + /// } + /// + /// impl Ord for S { + /// fn cmp(&self, other: &S) -> Ordering { + /// self.id.cmp(&other.id) + /// } + /// } + /// + /// let j_a = S { id: 1, name: "Jessica" }; + /// let j_b = S { id: 1, name: "Jess" }; + /// let p = S { id: 2, name: "Paul" }; + /// assert_eq!(j_a, j_b); + /// + /// let mut map = BTreeMap::new(); + /// map.insert(j_a, "Paris"); + /// assert_eq!(map.get_key_value(&j_a), Some((&j_a, &"Paris"))); + /// assert_eq!(map.get_key_value(&j_b), Some((&j_a, &"Paris"))); // the notable case + /// assert_eq!(map.get_key_value(&p), None); + /// ``` + #[stable(feature = "map_get_key_value", since = "1.40.0")] + pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> + where + K: Borrow + Ord, + Q: Ord, + { + let root_node = self.root.as_ref()?.reborrow(); + match root_node.search_tree(k) { + Found(handle) => Some(handle.into_kv()), + GoDown(_) => None, + } + } + + /// Returns the first key-value pair in the map. + /// The key in this pair is the minimum key in the map. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// assert_eq!(map.first_key_value(), None); + /// map.insert(1, "b"); + /// map.insert(2, "a"); + /// assert_eq!(map.first_key_value(), Some((&1, &"b"))); + /// ``` + #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn first_key_value(&self) -> Option<(&K, &V)> + where + K: Ord, + { + let root_node = self.root.as_ref()?.reborrow(); + root_node.first_leaf_edge().right_kv().ok().map(Handle::into_kv) + } + + /// Returns the first entry in the map for in-place manipulation. + /// The key of this entry is the minimum key in the map. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// map.insert(2, "b"); + /// if let Some(mut entry) = map.first_entry() { + /// if *entry.key() > 0 { + /// entry.insert("first"); + /// } + /// } + /// assert_eq!(*map.get(&1).unwrap(), "first"); + /// assert_eq!(*map.get(&2).unwrap(), "b"); + /// ``` + #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn first_entry(&mut self) -> Option> + where + K: Ord, + { + let (map, dormant_map) = DormantMutRef::new(self); + let root_node = map.root.as_mut()?.borrow_mut(); + let kv = root_node.first_leaf_edge().right_kv().ok()?; + Some(OccupiedEntry { + handle: kv.forget_node_type(), + dormant_map, + alloc: (*map.alloc).clone(), + _marker: PhantomData, + }) + } + + /// Removes and returns the first element in the map. + /// The key of this element is the minimum key that was in the map. + /// + /// # Examples + /// + /// Draining elements in ascending order, while keeping a usable map each iteration. + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// map.insert(2, "b"); + /// while let Some((key, _val)) = map.pop_first() { + /// assert!(map.iter().all(|(k, _v)| *k > key)); + /// } + /// assert!(map.is_empty()); + /// ``` + #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn pop_first(&mut self) -> Option<(K, V)> + where + K: Ord, + { + self.first_entry().map(|entry| entry.remove_entry()) + } + + /// Returns the last key-value pair in the map. + /// The key in this pair is the maximum key in the map. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "b"); + /// map.insert(2, "a"); + /// assert_eq!(map.last_key_value(), Some((&2, &"a"))); + /// ``` + #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn last_key_value(&self) -> Option<(&K, &V)> + where + K: Ord, + { + let root_node = self.root.as_ref()?.reborrow(); + root_node.last_leaf_edge().left_kv().ok().map(Handle::into_kv) + } + + /// Returns the last entry in the map for in-place manipulation. + /// The key of this entry is the maximum key in the map. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// map.insert(2, "b"); + /// if let Some(mut entry) = map.last_entry() { + /// if *entry.key() > 0 { + /// entry.insert("last"); + /// } + /// } + /// assert_eq!(*map.get(&1).unwrap(), "a"); + /// assert_eq!(*map.get(&2).unwrap(), "last"); + /// ``` + #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn last_entry(&mut self) -> Option> + where + K: Ord, + { + let (map, dormant_map) = DormantMutRef::new(self); + let root_node = map.root.as_mut()?.borrow_mut(); + let kv = root_node.last_leaf_edge().left_kv().ok()?; + Some(OccupiedEntry { + handle: kv.forget_node_type(), + dormant_map, + alloc: (*map.alloc).clone(), + _marker: PhantomData, + }) + } + + /// Removes and returns the last element in the map. + /// The key of this element is the maximum key that was in the map. + /// + /// # Examples + /// + /// Draining elements in descending order, while keeping a usable map each iteration. + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// map.insert(2, "b"); + /// while let Some((key, _val)) = map.pop_last() { + /// assert!(map.iter().all(|(k, _v)| *k < key)); + /// } + /// assert!(map.is_empty()); + /// ``` + #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn pop_last(&mut self) -> Option<(K, V)> + where + K: Ord, + { + self.last_entry().map(|entry| entry.remove_entry()) + } + + /// Returns `true` if the map contains a value for the specified key. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.contains_key(&1), true); + /// assert_eq!(map.contains_key(&2), false); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "btreemap_contains_key")] + pub fn contains_key(&self, key: &Q) -> bool + where + K: Borrow + Ord, + Q: Ord, + { + self.get(key).is_some() + } + + /// Returns a mutable reference to the value corresponding to the key. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// if let Some(x) = map.get_mut(&1) { + /// *x = "b"; + /// } + /// assert_eq!(map[&1], "b"); + /// ``` + // See `get` for implementation notes, this is basically a copy-paste with mut's added + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> + where + K: Borrow + Ord, + Q: Ord, + { + let root_node = self.root.as_mut()?.borrow_mut(); + match root_node.search_tree(key) { + Found(handle) => Some(handle.into_val_mut()), + GoDown(_) => None, + } + } + + /// Inserts a key-value pair into the map. + /// + /// If the map did not have this key present, `None` is returned. + /// + /// If the map did have this key present, the value is updated, and the old + /// value is returned. The key is not updated, though; this matters for + /// types that can be `==` without being identical. See the [module-level + /// documentation] for more. + /// + /// [module-level documentation]: index.html#insert-and-complex-keys + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// assert_eq!(map.insert(37, "a"), None); + /// assert_eq!(map.is_empty(), false); + /// + /// map.insert(37, "b"); + /// assert_eq!(map.insert(37, "c"), Some("b")); + /// assert_eq!(map[&37], "c"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push", "put", "set")] + #[cfg_attr(not(test), rustc_diagnostic_item = "btreemap_insert")] + pub fn insert(&mut self, key: K, value: V) -> Option + where + K: Ord, + { + match self.entry(key) { + Occupied(mut entry) => Some(entry.insert(value)), + Vacant(entry) => { + entry.insert(value); + None + } + } + } + + /// Tries to insert a key-value pair into the map, and returns + /// a mutable reference to the value in the entry. + /// + /// If the map already had this key present, nothing is updated, and + /// an error containing the occupied entry and the value is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(map_try_insert)] + /// + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// assert_eq!(map.try_insert(37, "a").unwrap(), &"a"); + /// + /// let err = map.try_insert(37, "b").unwrap_err(); + /// assert_eq!(err.entry.key(), &37); + /// assert_eq!(err.entry.get(), &"a"); + /// assert_eq!(err.value, "b"); + /// ``` + #[unstable(feature = "map_try_insert", issue = "82766")] + pub fn try_insert(&mut self, key: K, value: V) -> Result<&mut V, OccupiedError<'_, K, V, A>> + where + K: Ord, + { + match self.entry(key) { + Occupied(entry) => Err(OccupiedError { entry, value }), + Vacant(entry) => Ok(entry.insert(value)), + } + } + + /// Removes a key from the map, returning the value at the key if the key + /// was previously in the map. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.remove(&1), Some("a")); + /// assert_eq!(map.remove(&1), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("delete", "take")] + pub fn remove(&mut self, key: &Q) -> Option + where + K: Borrow + Ord, + Q: Ord, + { + self.remove_entry(key).map(|(_, v)| v) + } + + /// Removes a key from the map, returning the stored key and value if the key + /// was previously in the map. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.remove_entry(&1), Some((1, "a"))); + /// assert_eq!(map.remove_entry(&1), None); + /// ``` + #[stable(feature = "btreemap_remove_entry", since = "1.45.0")] + pub fn remove_entry(&mut self, key: &Q) -> Option<(K, V)> + where + K: Borrow + Ord, + Q: Ord, + { + let (map, dormant_map) = DormantMutRef::new(self); + let root_node = map.root.as_mut()?.borrow_mut(); + match root_node.search_tree(key) { + Found(handle) => Some( + OccupiedEntry { + handle, + dormant_map, + alloc: (*map.alloc).clone(), + _marker: PhantomData, + } + .remove_entry(), + ), + GoDown(_) => None, + } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all pairs `(k, v)` for which `f(&k, &mut v)` returns `false`. + /// The elements are visited in ascending key order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap = (0..8).map(|x| (x, x*10)).collect(); + /// // Keep only the elements with even-numbered keys. + /// map.retain(|&k, _| k % 2 == 0); + /// assert!(map.into_iter().eq(vec![(0, 0), (2, 20), (4, 40), (6, 60)])); + /// ``` + #[inline] + #[stable(feature = "btree_retain", since = "1.53.0")] + pub fn retain(&mut self, mut f: F) + where + K: Ord, + F: FnMut(&K, &mut V) -> bool, + { + self.extract_if(|k, v| !f(k, v)).for_each(drop); + } + + /// Moves all elements from `other` into `self`, leaving `other` empty. + /// + /// If a key from `other` is already present in `self`, the respective + /// value from `self` will be overwritten with the respective value from `other`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(1, "a"); + /// a.insert(2, "b"); + /// a.insert(3, "c"); // Note: Key (3) also present in b. + /// + /// let mut b = BTreeMap::new(); + /// b.insert(3, "d"); // Note: Key (3) also present in a. + /// b.insert(4, "e"); + /// b.insert(5, "f"); + /// + /// a.append(&mut b); + /// + /// assert_eq!(a.len(), 5); + /// assert_eq!(b.len(), 0); + /// + /// assert_eq!(a[&1], "a"); + /// assert_eq!(a[&2], "b"); + /// assert_eq!(a[&3], "d"); // Note: "c" has been overwritten. + /// assert_eq!(a[&4], "e"); + /// assert_eq!(a[&5], "f"); + /// ``` + #[stable(feature = "btree_append", since = "1.11.0")] + pub fn append(&mut self, other: &mut Self) + where + K: Ord, + A: Clone, + { + // Do we have to append anything at all? + if other.is_empty() { + return; + } + + // We can just swap `self` and `other` if `self` is empty. + if self.is_empty() { + mem::swap(self, other); + return; + } + + let self_iter = mem::replace(self, Self::new_in((*self.alloc).clone())).into_iter(); + let other_iter = mem::replace(other, Self::new_in((*self.alloc).clone())).into_iter(); + let root = self.root.get_or_insert_with(|| Root::new((*self.alloc).clone())); + root.append_from_sorted_iters( + self_iter, + other_iter, + &mut self.length, + (*self.alloc).clone(), + ) + } + + /// Constructs a double-ended iterator over a sub-range of elements in the map. + /// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will + /// yield elements from min (inclusive) to max (exclusive). + /// The range may also be entered as `(Bound, Bound)`, so for example + /// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive + /// range from 4 to 10. + /// + /// # Panics + /// + /// Panics if range `start > end`. + /// Panics if range `start == end` and both bounds are `Excluded`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::ops::Bound::Included; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(3, "a"); + /// map.insert(5, "b"); + /// map.insert(8, "c"); + /// for (&key, &value) in map.range((Included(&4), Included(&8))) { + /// println!("{key}: {value}"); + /// } + /// assert_eq!(Some((&5, &"b")), map.range(4..).next()); + /// ``` + #[stable(feature = "btree_range", since = "1.17.0")] + pub fn range(&self, range: R) -> Range<'_, K, V> + where + T: Ord, + K: Borrow + Ord, + R: RangeBounds, + { + if let Some(root) = &self.root { + Range { inner: root.reborrow().range_search(range) } + } else { + Range { inner: LeafRange::none() } + } + } + + /// Constructs a mutable double-ended iterator over a sub-range of elements in the map. + /// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will + /// yield elements from min (inclusive) to max (exclusive). + /// The range may also be entered as `(Bound, Bound)`, so for example + /// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive + /// range from 4 to 10. + /// + /// # Panics + /// + /// Panics if range `start > end`. + /// Panics if range `start == end` and both bounds are `Excluded`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, i32> = + /// [("Alice", 0), ("Bob", 0), ("Carol", 0), ("Cheryl", 0)].into(); + /// for (_, balance) in map.range_mut("B".."Cheryl") { + /// *balance += 100; + /// } + /// for (name, balance) in &map { + /// println!("{name} => {balance}"); + /// } + /// ``` + #[stable(feature = "btree_range", since = "1.17.0")] + pub fn range_mut(&mut self, range: R) -> RangeMut<'_, K, V> + where + T: Ord, + K: Borrow + Ord, + R: RangeBounds, + { + if let Some(root) = &mut self.root { + RangeMut { inner: root.borrow_valmut().range_search(range), _marker: PhantomData } + } else { + RangeMut { inner: LeafRange::none(), _marker: PhantomData } + } + } + + /// Gets the given key's corresponding entry in the map for in-place manipulation. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut count: BTreeMap<&str, usize> = BTreeMap::new(); + /// + /// // count the number of occurrences of letters in the vec + /// for x in ["a", "b", "a", "c", "a", "b"] { + /// count.entry(x).and_modify(|curr| *curr += 1).or_insert(1); + /// } + /// + /// assert_eq!(count["a"], 3); + /// assert_eq!(count["b"], 2); + /// assert_eq!(count["c"], 1); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn entry(&mut self, key: K) -> Entry<'_, K, V, A> + where + K: Ord, + { + let (map, dormant_map) = DormantMutRef::new(self); + match map.root { + None => Vacant(VacantEntry { + key, + handle: None, + dormant_map, + alloc: (*map.alloc).clone(), + _marker: PhantomData, + }), + Some(ref mut root) => match root.borrow_mut().search_tree(&key) { + Found(handle) => Occupied(OccupiedEntry { + handle, + dormant_map, + alloc: (*map.alloc).clone(), + _marker: PhantomData, + }), + GoDown(handle) => Vacant(VacantEntry { + key, + handle: Some(handle), + dormant_map, + alloc: (*map.alloc).clone(), + _marker: PhantomData, + }), + }, + } + } + + /// Splits the collection into two at the given key. Returns everything after the given key, + /// including the key. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(1, "a"); + /// a.insert(2, "b"); + /// a.insert(3, "c"); + /// a.insert(17, "d"); + /// a.insert(41, "e"); + /// + /// let b = a.split_off(&3); + /// + /// assert_eq!(a.len(), 2); + /// assert_eq!(b.len(), 3); + /// + /// assert_eq!(a[&1], "a"); + /// assert_eq!(a[&2], "b"); + /// + /// assert_eq!(b[&3], "c"); + /// assert_eq!(b[&17], "d"); + /// assert_eq!(b[&41], "e"); + /// ``` + #[stable(feature = "btree_split_off", since = "1.11.0")] + pub fn split_off(&mut self, key: &Q) -> Self + where + K: Borrow + Ord, + A: Clone, + { + if self.is_empty() { + return Self::new_in((*self.alloc).clone()); + } + + let total_num = self.len(); + let left_root = self.root.as_mut().unwrap(); // unwrap succeeds because not empty + + let right_root = left_root.split_off(key, (*self.alloc).clone()); + + let (new_left_len, right_len) = Root::calc_split_length(total_num, &left_root, &right_root); + self.length = new_left_len; + + BTreeMap { + root: Some(right_root), + length: right_len, + alloc: self.alloc.clone(), + _marker: PhantomData, + } + } + + /// Creates an iterator that visits all elements (key-value pairs) in + /// ascending key order and uses a closure to determine if an element should + /// be removed. If the closure returns `true`, the element is removed from + /// the map and yielded. If the closure returns `false`, or panics, the + /// element remains in the map and will not be yielded. + /// + /// The iterator also lets you mutate the value of each element in the + /// closure, regardless of whether you choose to keep or remove it. + /// + /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating + /// or the iteration short-circuits, then the remaining elements will be retained. + /// Use [`retain`] with a negated predicate if you do not need the returned iterator. + /// + /// [`retain`]: BTreeMap::retain + /// + /// # Examples + /// + /// Splitting a map into even and odd keys, reusing the original map: + /// + /// ``` + /// #![feature(btree_extract_if)] + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap = (0..8).map(|x| (x, x)).collect(); + /// let evens: BTreeMap<_, _> = map.extract_if(|k, _v| k % 2 == 0).collect(); + /// let odds = map; + /// assert_eq!(evens.keys().copied().collect::>(), [0, 2, 4, 6]); + /// assert_eq!(odds.keys().copied().collect::>(), [1, 3, 5, 7]); + /// ``` + #[unstable(feature = "btree_extract_if", issue = "70530")] + pub fn extract_if(&mut self, pred: F) -> ExtractIf<'_, K, V, F, A> + where + K: Ord, + F: FnMut(&K, &mut V) -> bool, + { + let (inner, alloc) = self.extract_if_inner(); + ExtractIf { pred, inner, alloc } + } + + pub(super) fn extract_if_inner(&mut self) -> (ExtractIfInner<'_, K, V>, A) + where + K: Ord, + { + if let Some(root) = self.root.as_mut() { + let (root, dormant_root) = DormantMutRef::new(root); + let front = root.borrow_mut().first_leaf_edge(); + ( + ExtractIfInner { + length: &mut self.length, + dormant_root: Some(dormant_root), + cur_leaf_edge: Some(front), + }, + (*self.alloc).clone(), + ) + } else { + ( + ExtractIfInner { + length: &mut self.length, + dormant_root: None, + cur_leaf_edge: None, + }, + (*self.alloc).clone(), + ) + } + } + + /// Creates a consuming iterator visiting all the keys, in sorted order. + /// The map cannot be used after calling this. + /// The iterator element type is `K`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(2, "b"); + /// a.insert(1, "a"); + /// + /// let keys: Vec = a.into_keys().collect(); + /// assert_eq!(keys, [1, 2]); + /// ``` + #[inline] + #[stable(feature = "map_into_keys_values", since = "1.54.0")] + pub fn into_keys(self) -> IntoKeys { + IntoKeys { inner: self.into_iter() } + } + + /// Creates a consuming iterator visiting all the values, in order by key. + /// The map cannot be used after calling this. + /// The iterator element type is `V`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(1, "hello"); + /// a.insert(2, "goodbye"); + /// + /// let values: Vec<&str> = a.into_values().collect(); + /// assert_eq!(values, ["hello", "goodbye"]); + /// ``` + #[inline] + #[stable(feature = "map_into_keys_values", since = "1.54.0")] + pub fn into_values(self) -> IntoValues { + IntoValues { inner: self.into_iter() } + } + + /// Makes a `BTreeMap` from a sorted iterator. + pub(crate) fn bulk_build_from_sorted_iter(iter: I, alloc: A) -> Self + where + K: Ord, + I: IntoIterator, + { + let mut root = Root::new(alloc.clone()); + let mut length = 0; + root.bulk_push(DedupSortedIter::new(iter.into_iter()), &mut length, alloc.clone()); + BTreeMap { root: Some(root), length, alloc: ManuallyDrop::new(alloc), _marker: PhantomData } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V, A: Allocator + Clone> IntoIterator for &'a BTreeMap { + type Item = (&'a K, &'a V); + type IntoIter = Iter<'a, K, V>; + + fn into_iter(self) -> Iter<'a, K, V> { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { + type Item = (&'a K, &'a V); + + fn next(&mut self) -> Option<(&'a K, &'a V)> { + if self.length == 0 { + None + } else { + self.length -= 1; + Some(unsafe { self.range.next_unchecked() }) + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.length, Some(self.length)) + } + + fn last(mut self) -> Option<(&'a K, &'a V)> { + self.next_back() + } + + fn min(mut self) -> Option<(&'a K, &'a V)> + where + (&'a K, &'a V): Ord, + { + self.next() + } + + fn max(mut self) -> Option<(&'a K, &'a V)> + where + (&'a K, &'a V): Ord, + { + self.next_back() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Iter<'_, K, V> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K: 'a, V: 'a> DoubleEndedIterator for Iter<'a, K, V> { + fn next_back(&mut self) -> Option<(&'a K, &'a V)> { + if self.length == 0 { + None + } else { + self.length -= 1; + Some(unsafe { self.range.next_back_unchecked() }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Iter<'_, K, V> { + fn len(&self) -> usize { + self.length + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Iter<'_, K, V> { + fn clone(&self) -> Self { + Iter { range: self.range.clone(), length: self.length } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V, A: Allocator + Clone> IntoIterator for &'a mut BTreeMap { + type Item = (&'a K, &'a mut V); + type IntoIter = IterMut<'a, K, V>; + + fn into_iter(self) -> IterMut<'a, K, V> { + self.iter_mut() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V> Iterator for IterMut<'a, K, V> { + type Item = (&'a K, &'a mut V); + + fn next(&mut self) -> Option<(&'a K, &'a mut V)> { + if self.length == 0 { + None + } else { + self.length -= 1; + Some(unsafe { self.range.next_unchecked() }) + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.length, Some(self.length)) + } + + fn last(mut self) -> Option<(&'a K, &'a mut V)> { + self.next_back() + } + + fn min(mut self) -> Option<(&'a K, &'a mut V)> + where + (&'a K, &'a mut V): Ord, + { + self.next() + } + + fn max(mut self) -> Option<(&'a K, &'a mut V)> + where + (&'a K, &'a mut V): Ord, + { + self.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> { + fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { + if self.length == 0 { + None + } else { + self.length -= 1; + Some(unsafe { self.range.next_back_unchecked() }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IterMut<'_, K, V> { + fn len(&self) -> usize { + self.length + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IterMut<'_, K, V> {} + +impl<'a, K, V> IterMut<'a, K, V> { + /// Returns an iterator of references over the remaining items. + #[inline] + pub(super) fn iter(&self) -> Iter<'_, K, V> { + Iter { range: self.range.reborrow(), length: self.length } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for BTreeMap { + type Item = (K, V); + type IntoIter = IntoIter; + + /// Gets an owning iterator over the entries of the map, sorted by key. + fn into_iter(self) -> IntoIter { + let mut me = ManuallyDrop::new(self); + if let Some(root) = me.root.take() { + let full_range = root.into_dying().full_range(); + + IntoIter { + range: full_range, + length: me.length, + alloc: unsafe { ManuallyDrop::take(&mut me.alloc) }, + } + } else { + IntoIter { + range: LazyLeafRange::none(), + length: 0, + alloc: unsafe { ManuallyDrop::take(&mut me.alloc) }, + } + } + } +} + +#[stable(feature = "btree_drop", since = "1.7.0")] +impl Drop for IntoIter { + fn drop(&mut self) { + struct DropGuard<'a, K, V, A: Allocator + Clone>(&'a mut IntoIter); + + impl<'a, K, V, A: Allocator + Clone> Drop for DropGuard<'a, K, V, A> { + fn drop(&mut self) { + // Continue the same loop we perform below. This only runs when unwinding, so we + // don't have to care about panics this time (they'll abort). + while let Some(kv) = self.0.dying_next() { + // SAFETY: we consume the dying handle immediately. + unsafe { kv.drop_key_val() }; + } + } + } + + while let Some(kv) = self.dying_next() { + let guard = DropGuard(self); + // SAFETY: we don't touch the tree before consuming the dying handle. + unsafe { kv.drop_key_val() }; + mem::forget(guard); + } + } +} + +impl IntoIter { + /// Core of a `next` method returning a dying KV handle, + /// invalidated by further calls to this function and some others. + fn dying_next( + &mut self, + ) -> Option, marker::KV>> { + if self.length == 0 { + self.range.deallocating_end(self.alloc.clone()); + None + } else { + self.length -= 1; + Some(unsafe { self.range.deallocating_next_unchecked(self.alloc.clone()) }) + } + } + + /// Core of a `next_back` method returning a dying KV handle, + /// invalidated by further calls to this function and some others. + fn dying_next_back( + &mut self, + ) -> Option, marker::KV>> { + if self.length == 0 { + self.range.deallocating_end(self.alloc.clone()); + None + } else { + self.length -= 1; + Some(unsafe { self.range.deallocating_next_back_unchecked(self.alloc.clone()) }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = (K, V); + + fn next(&mut self) -> Option<(K, V)> { + // SAFETY: we consume the dying handle immediately. + self.dying_next().map(unsafe { |kv| kv.into_key_val() }) + } + + fn size_hint(&self) -> (usize, Option) { + (self.length, Some(self.length)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option<(K, V)> { + // SAFETY: we consume the dying handle immediately. + self.dying_next_back().map(unsafe { |kv| kv.into_key_val() }) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + fn len(&self) -> usize { + self.length + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V> Iterator for Keys<'a, K, V> { + type Item = &'a K; + + fn next(&mut self) -> Option<&'a K> { + self.inner.next().map(|(k, _)| k) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + fn last(mut self) -> Option<&'a K> { + self.next_back() + } + + fn min(mut self) -> Option<&'a K> + where + &'a K: Ord, + { + self.next() + } + + fn max(mut self) -> Option<&'a K> + where + &'a K: Ord, + { + self.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> { + fn next_back(&mut self) -> Option<&'a K> { + self.inner.next_back().map(|(k, _)| k) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Keys<'_, K, V> { + fn len(&self) -> usize { + self.inner.len() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Keys<'_, K, V> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Keys<'_, K, V> { + fn clone(&self) -> Self { + Keys { inner: self.inner.clone() } + } +} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for Keys<'_, K, V> { + /// Creates an empty `btree_map::Keys`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::Keys<'_, u8, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Keys { inner: Default::default() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V> Iterator for Values<'a, K, V> { + type Item = &'a V; + + fn next(&mut self) -> Option<&'a V> { + self.inner.next().map(|(_, v)| v) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + fn last(mut self) -> Option<&'a V> { + self.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> { + fn next_back(&mut self) -> Option<&'a V> { + self.inner.next_back().map(|(_, v)| v) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Values<'_, K, V> { + fn len(&self) -> usize { + self.inner.len() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Values<'_, K, V> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Values<'_, K, V> { + fn clone(&self) -> Self { + Values { inner: self.inner.clone() } + } +} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for Values<'_, K, V> { + /// Creates an empty `btree_map::Values`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::Values<'_, u8, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Values { inner: Default::default() } + } +} + +/// An iterator produced by calling `extract_if` on BTreeMap. +#[unstable(feature = "btree_extract_if", issue = "70530")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct ExtractIf< + 'a, + K, + V, + F, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> where + F: 'a + FnMut(&K, &mut V) -> bool, +{ + pred: F, + inner: ExtractIfInner<'a, K, V>, + /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`. + alloc: A, +} +/// Most of the implementation of ExtractIf are generic over the type +/// of the predicate, thus also serving for BTreeSet::ExtractIf. +pub(super) struct ExtractIfInner<'a, K, V> { + /// Reference to the length field in the borrowed map, updated live. + length: &'a mut usize, + /// Buried reference to the root field in the borrowed map. + /// Wrapped in `Option` to allow drop handler to `take` it. + dormant_root: Option>>, + /// Contains a leaf edge preceding the next element to be returned, or the last leaf edge. + /// Empty if the map has no root, if iteration went beyond the last leaf edge, + /// or if a panic occurred in the predicate. + cur_leaf_edge: Option, K, V, marker::Leaf>, marker::Edge>>, +} + +#[unstable(feature = "btree_extract_if", issue = "70530")] +impl fmt::Debug for ExtractIf<'_, K, V, F> +where + K: fmt::Debug, + V: fmt::Debug, + F: FnMut(&K, &mut V) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("ExtractIf").field(&self.inner.peek()).finish() + } +} + +#[unstable(feature = "btree_extract_if", issue = "70530")] +impl Iterator for ExtractIf<'_, K, V, F, A> +where + F: FnMut(&K, &mut V) -> bool, +{ + type Item = (K, V); + + fn next(&mut self) -> Option<(K, V)> { + self.inner.next(&mut self.pred, self.alloc.clone()) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +impl<'a, K, V> ExtractIfInner<'a, K, V> { + /// Allow Debug implementations to predict the next element. + pub(super) fn peek(&self) -> Option<(&K, &V)> { + let edge = self.cur_leaf_edge.as_ref()?; + edge.reborrow().next_kv().ok().map(Handle::into_kv) + } + + /// Implementation of a typical `ExtractIf::next` method, given the predicate. + pub(super) fn next(&mut self, pred: &mut F, alloc: A) -> Option<(K, V)> + where + F: FnMut(&K, &mut V) -> bool, + { + while let Ok(mut kv) = self.cur_leaf_edge.take()?.next_kv() { + let (k, v) = kv.kv_mut(); + if pred(k, v) { + *self.length -= 1; + let (kv, pos) = kv.remove_kv_tracking( + || { + // SAFETY: we will touch the root in a way that will not + // invalidate the position returned. + let root = unsafe { self.dormant_root.take().unwrap().awaken() }; + root.pop_internal_level(alloc.clone()); + self.dormant_root = Some(DormantMutRef::new(root).1); + }, + alloc.clone(), + ); + self.cur_leaf_edge = Some(pos); + return Some(kv); + } + self.cur_leaf_edge = Some(kv.next_leaf_edge()); + } + None + } + + /// Implementation of a typical `ExtractIf::size_hint` method. + pub(super) fn size_hint(&self) -> (usize, Option) { + // In most of the btree iterators, `self.length` is the number of elements + // yet to be visited. Here, it includes elements that were visited and that + // the predicate decided not to drain. Making this upper bound more tight + // during iteration would require an extra field. + (0, Some(*self.length)) + } +} + +#[unstable(feature = "btree_extract_if", issue = "70530")] +impl FusedIterator for ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl<'a, K, V> Iterator for Range<'a, K, V> { + type Item = (&'a K, &'a V); + + fn next(&mut self) -> Option<(&'a K, &'a V)> { + self.inner.next_checked() + } + + fn last(mut self) -> Option<(&'a K, &'a V)> { + self.next_back() + } + + fn min(mut self) -> Option<(&'a K, &'a V)> + where + (&'a K, &'a V): Ord, + { + self.next() + } + + fn max(mut self) -> Option<(&'a K, &'a V)> + where + (&'a K, &'a V): Ord, + { + self.next_back() + } +} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for Range<'_, K, V> { + /// Creates an empty `btree_map::Range`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::Range<'_, u8, u8> = Default::default(); + /// assert_eq!(iter.count(), 0); + /// ``` + fn default() -> Self { + Range { inner: Default::default() } + } +} + +#[stable(feature = "default_iters_sequel", since = "1.82.0")] +impl Default for RangeMut<'_, K, V> { + /// Creates an empty `btree_map::RangeMut`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::RangeMut<'_, u8, u8> = Default::default(); + /// assert_eq!(iter.count(), 0); + /// ``` + fn default() -> Self { + RangeMut { inner: Default::default(), _marker: PhantomData } + } +} + +#[stable(feature = "map_values_mut", since = "1.10.0")] +impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { + type Item = &'a mut V; + + fn next(&mut self) -> Option<&'a mut V> { + self.inner.next().map(|(_, v)| v) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + fn last(mut self) -> Option<&'a mut V> { + self.next_back() + } +} + +#[stable(feature = "map_values_mut", since = "1.10.0")] +impl<'a, K, V> DoubleEndedIterator for ValuesMut<'a, K, V> { + fn next_back(&mut self) -> Option<&'a mut V> { + self.inner.next_back().map(|(_, v)| v) + } +} + +#[stable(feature = "map_values_mut", since = "1.10.0")] +impl ExactSizeIterator for ValuesMut<'_, K, V> { + fn len(&self) -> usize { + self.inner.len() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for ValuesMut<'_, K, V> {} + +#[stable(feature = "default_iters_sequel", since = "1.82.0")] +impl Default for ValuesMut<'_, K, V> { + /// Creates an empty `btree_map::ValuesMut`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::ValuesMut<'_, u8, u8> = Default::default(); + /// assert_eq!(iter.count(), 0); + /// ``` + fn default() -> Self { + ValuesMut { inner: Default::default() } + } +} + +#[stable(feature = "map_into_keys_values", since = "1.54.0")] +impl Iterator for IntoKeys { + type Item = K; + + fn next(&mut self) -> Option { + self.inner.next().map(|(k, _)| k) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + fn last(mut self) -> Option { + self.next_back() + } + + fn min(mut self) -> Option + where + K: Ord, + { + self.next() + } + + fn max(mut self) -> Option + where + K: Ord, + { + self.next_back() + } +} + +#[stable(feature = "map_into_keys_values", since = "1.54.0")] +impl DoubleEndedIterator for IntoKeys { + fn next_back(&mut self) -> Option { + self.inner.next_back().map(|(k, _)| k) + } +} + +#[stable(feature = "map_into_keys_values", since = "1.54.0")] +impl ExactSizeIterator for IntoKeys { + fn len(&self) -> usize { + self.inner.len() + } +} + +#[stable(feature = "map_into_keys_values", since = "1.54.0")] +impl FusedIterator for IntoKeys {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for IntoKeys +where + A: Allocator + Default + Clone, +{ + /// Creates an empty `btree_map::IntoKeys`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::IntoKeys = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + IntoKeys { inner: Default::default() } + } +} + +#[stable(feature = "map_into_keys_values", since = "1.54.0")] +impl Iterator for IntoValues { + type Item = V; + + fn next(&mut self) -> Option { + self.inner.next().map(|(_, v)| v) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + fn last(mut self) -> Option { + self.next_back() + } +} + +#[stable(feature = "map_into_keys_values", since = "1.54.0")] +impl DoubleEndedIterator for IntoValues { + fn next_back(&mut self) -> Option { + self.inner.next_back().map(|(_, v)| v) + } +} + +#[stable(feature = "map_into_keys_values", since = "1.54.0")] +impl ExactSizeIterator for IntoValues { + fn len(&self) -> usize { + self.inner.len() + } +} + +#[stable(feature = "map_into_keys_values", since = "1.54.0")] +impl FusedIterator for IntoValues {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for IntoValues +where + A: Allocator + Default + Clone, +{ + /// Creates an empty `btree_map::IntoValues`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::IntoValues = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + IntoValues { inner: Default::default() } + } +} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl<'a, K, V> DoubleEndedIterator for Range<'a, K, V> { + fn next_back(&mut self) -> Option<(&'a K, &'a V)> { + self.inner.next_back_checked() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Range<'_, K, V> {} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl Clone for Range<'_, K, V> { + fn clone(&self) -> Self { + Range { inner: self.inner.clone() } + } +} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl<'a, K, V> Iterator for RangeMut<'a, K, V> { + type Item = (&'a K, &'a mut V); + + fn next(&mut self) -> Option<(&'a K, &'a mut V)> { + self.inner.next_checked() + } + + fn last(mut self) -> Option<(&'a K, &'a mut V)> { + self.next_back() + } + + fn min(mut self) -> Option<(&'a K, &'a mut V)> + where + (&'a K, &'a mut V): Ord, + { + self.next() + } + + fn max(mut self) -> Option<(&'a K, &'a mut V)> + where + (&'a K, &'a mut V): Ord, + { + self.next_back() + } +} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> { + fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { + self.inner.next_back_checked() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for RangeMut<'_, K, V> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator<(K, V)> for BTreeMap { + fn from_iter>(iter: T) -> BTreeMap { + let mut inputs: Vec<_> = iter.into_iter().collect(); + + if inputs.is_empty() { + return BTreeMap::new(); + } + + // use stable sort to preserve the insertion order. + inputs.sort_by(|a, b| a.0.cmp(&b.0)); + BTreeMap::bulk_build_from_sorted_iter(inputs, Global) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend<(K, V)> for BTreeMap { + #[inline] + fn extend>(&mut self, iter: T) { + iter.into_iter().for_each(move |(k, v)| { + self.insert(k, v); + }); + } + + #[inline] + fn extend_one(&mut self, (k, v): (K, V)) { + self.insert(k, v); + } +} + +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, K: Ord + Copy, V: Copy, A: Allocator + Clone> Extend<(&'a K, &'a V)> + for BTreeMap +{ + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().map(|(&key, &value)| (key, value))); + } + + #[inline] + fn extend_one(&mut self, (&k, &v): (&'a K, &'a V)) { + self.insert(k, v); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for BTreeMap { + fn hash(&self, state: &mut H) { + state.write_length_prefix(self.len()); + for elt in self { + elt.hash(state); + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for BTreeMap { + /// Creates an empty `BTreeMap`. + fn default() -> BTreeMap { + BTreeMap::new() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for BTreeMap { + fn eq(&self, other: &BTreeMap) -> bool { + self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a == b) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for BTreeMap {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for BTreeMap { + #[inline] + fn partial_cmp(&self, other: &BTreeMap) -> Option { + self.iter().partial_cmp(other.iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for BTreeMap { + #[inline] + fn cmp(&self, other: &BTreeMap) -> Ordering { + self.iter().cmp(other.iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for BTreeMap { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_map().entries(self.iter()).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Index<&Q> for BTreeMap +where + K: Borrow + Ord, + Q: Ord, +{ + type Output = V; + + /// Returns a reference to the value corresponding to the supplied key. + /// + /// # Panics + /// + /// Panics if the key is not present in the `BTreeMap`. + #[inline] + fn index(&self, key: &Q) -> &V { + self.get(key).expect("no entry found for key") + } +} + +#[stable(feature = "std_collections_from_array", since = "1.56.0")] +impl From<[(K, V); N]> for BTreeMap { + /// Converts a `[(K, V); N]` into a `BTreeMap<(K, V)>`. + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let map1 = BTreeMap::from([(1, 2), (3, 4)]); + /// let map2: BTreeMap<_, _> = [(1, 2), (3, 4)].into(); + /// assert_eq!(map1, map2); + /// ``` + fn from(mut arr: [(K, V); N]) -> Self { + if N == 0 { + return BTreeMap::new(); + } + + // use stable sort to preserve the insertion order. + arr.sort_by(|a, b| a.0.cmp(&b.0)); + BTreeMap::bulk_build_from_sorted_iter(arr, Global) + } +} + +impl BTreeMap { + /// Gets an iterator over the entries of the map, sorted by key. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(3, "c"); + /// map.insert(2, "b"); + /// map.insert(1, "a"); + /// + /// for (key, value) in map.iter() { + /// println!("{key}: {value}"); + /// } + /// + /// let (first_key, first_value) = map.iter().next().unwrap(); + /// assert_eq!((*first_key, *first_value), (1, "a")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter(&self) -> Iter<'_, K, V> { + if let Some(root) = &self.root { + let full_range = root.reborrow().full_range(); + + Iter { range: full_range, length: self.length } + } else { + Iter { range: LazyLeafRange::none(), length: 0 } + } + } + + /// Gets a mutable iterator over the entries of the map, sorted by key. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); + /// + /// // add 10 to the value if the key isn't "a" + /// for (key, value) in map.iter_mut() { + /// if key != &"a" { + /// *value += 10; + /// } + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { + if let Some(root) = &mut self.root { + let full_range = root.borrow_valmut().full_range(); + + IterMut { range: full_range, length: self.length, _marker: PhantomData } + } else { + IterMut { range: LazyLeafRange::none(), length: 0, _marker: PhantomData } + } + } + + /// Gets an iterator over the keys of the map, in sorted order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(2, "b"); + /// a.insert(1, "a"); + /// + /// let keys: Vec<_> = a.keys().cloned().collect(); + /// assert_eq!(keys, [1, 2]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn keys(&self) -> Keys<'_, K, V> { + Keys { inner: self.iter() } + } + + /// Gets an iterator over the values of the map, in order by key. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(1, "hello"); + /// a.insert(2, "goodbye"); + /// + /// let values: Vec<&str> = a.values().cloned().collect(); + /// assert_eq!(values, ["hello", "goodbye"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn values(&self) -> Values<'_, K, V> { + Values { inner: self.iter() } + } + + /// Gets a mutable iterator over the values of the map, in order by key. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(1, String::from("hello")); + /// a.insert(2, String::from("goodbye")); + /// + /// for value in a.values_mut() { + /// value.push_str("!"); + /// } + /// + /// let values: Vec = a.values().cloned().collect(); + /// assert_eq!(values, [String::from("hello!"), + /// String::from("goodbye!")]); + /// ``` + #[stable(feature = "map_values_mut", since = "1.10.0")] + pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { + ValuesMut { inner: self.iter_mut() } + } + + /// Returns the number of elements in the map. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// assert_eq!(a.len(), 0); + /// a.insert(1, "a"); + /// assert_eq!(a.len(), 1); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable( + feature = "const_btree_len", + issue = "71835", + implied_by = "const_btree_new" + )] + #[rustc_confusables("length", "size")] + pub const fn len(&self) -> usize { + self.length + } + + /// Returns `true` if the map contains no elements. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// assert!(a.is_empty()); + /// a.insert(1, "a"); + /// assert!(!a.is_empty()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable( + feature = "const_btree_len", + issue = "71835", + implied_by = "const_btree_new" + )] + pub const fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Returns a [`Cursor`] pointing at the gap before the smallest key + /// greater than the given bound. + /// + /// Passing `Bound::Included(x)` will return a cursor pointing to the + /// gap before the smallest key greater than or equal to `x`. + /// + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the + /// gap before the smallest key greater than `x`. + /// + /// Passing `Bound::Unbounded` will return a cursor pointing to the + /// gap before the smallest key in the map. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_cursors)] + /// + /// use std::collections::BTreeMap; + /// use std::ops::Bound; + /// + /// let map = BTreeMap::from([ + /// (1, "a"), + /// (2, "b"), + /// (3, "c"), + /// (4, "d"), + /// ]); + /// + /// let cursor = map.lower_bound(Bound::Included(&2)); + /// assert_eq!(cursor.peek_prev(), Some((&1, &"a"))); + /// assert_eq!(cursor.peek_next(), Some((&2, &"b"))); + /// + /// let cursor = map.lower_bound(Bound::Excluded(&2)); + /// assert_eq!(cursor.peek_prev(), Some((&2, &"b"))); + /// assert_eq!(cursor.peek_next(), Some((&3, &"c"))); + /// + /// let cursor = map.lower_bound(Bound::Unbounded); + /// assert_eq!(cursor.peek_prev(), None); + /// assert_eq!(cursor.peek_next(), Some((&1, &"a"))); + /// ``` + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn lower_bound(&self, bound: Bound<&Q>) -> Cursor<'_, K, V> + where + K: Borrow + Ord, + Q: Ord, + { + let root_node = match self.root.as_ref() { + None => return Cursor { current: None, root: None }, + Some(root) => root.reborrow(), + }; + let edge = root_node.lower_bound(SearchBound::from_range(bound)); + Cursor { current: Some(edge), root: self.root.as_ref() } + } + + /// Returns a [`CursorMut`] pointing at the gap before the smallest key + /// greater than the given bound. + /// + /// Passing `Bound::Included(x)` will return a cursor pointing to the + /// gap before the smallest key greater than or equal to `x`. + /// + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the + /// gap before the smallest key greater than `x`. + /// + /// Passing `Bound::Unbounded` will return a cursor pointing to the + /// gap before the smallest key in the map. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_cursors)] + /// + /// use std::collections::BTreeMap; + /// use std::ops::Bound; + /// + /// let mut map = BTreeMap::from([ + /// (1, "a"), + /// (2, "b"), + /// (3, "c"), + /// (4, "d"), + /// ]); + /// + /// let mut cursor = map.lower_bound_mut(Bound::Included(&2)); + /// assert_eq!(cursor.peek_prev(), Some((&1, &mut "a"))); + /// assert_eq!(cursor.peek_next(), Some((&2, &mut "b"))); + /// + /// let mut cursor = map.lower_bound_mut(Bound::Excluded(&2)); + /// assert_eq!(cursor.peek_prev(), Some((&2, &mut "b"))); + /// assert_eq!(cursor.peek_next(), Some((&3, &mut "c"))); + /// + /// let mut cursor = map.lower_bound_mut(Bound::Unbounded); + /// assert_eq!(cursor.peek_prev(), None); + /// assert_eq!(cursor.peek_next(), Some((&1, &mut "a"))); + /// ``` + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn lower_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, K, V, A> + where + K: Borrow + Ord, + Q: Ord, + { + let (root, dormant_root) = DormantMutRef::new(&mut self.root); + let root_node = match root.as_mut() { + None => { + return CursorMut { + inner: CursorMutKey { + current: None, + root: dormant_root, + length: &mut self.length, + alloc: &mut *self.alloc, + }, + }; + } + Some(root) => root.borrow_mut(), + }; + let edge = root_node.lower_bound(SearchBound::from_range(bound)); + CursorMut { + inner: CursorMutKey { + current: Some(edge), + root: dormant_root, + length: &mut self.length, + alloc: &mut *self.alloc, + }, + } + } + + /// Returns a [`Cursor`] pointing at the gap after the greatest key + /// smaller than the given bound. + /// + /// Passing `Bound::Included(x)` will return a cursor pointing to the + /// gap after the greatest key smaller than or equal to `x`. + /// + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the + /// gap after the greatest key smaller than `x`. + /// + /// Passing `Bound::Unbounded` will return a cursor pointing to the + /// gap after the greatest key in the map. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_cursors)] + /// + /// use std::collections::BTreeMap; + /// use std::ops::Bound; + /// + /// let map = BTreeMap::from([ + /// (1, "a"), + /// (2, "b"), + /// (3, "c"), + /// (4, "d"), + /// ]); + /// + /// let cursor = map.upper_bound(Bound::Included(&3)); + /// assert_eq!(cursor.peek_prev(), Some((&3, &"c"))); + /// assert_eq!(cursor.peek_next(), Some((&4, &"d"))); + /// + /// let cursor = map.upper_bound(Bound::Excluded(&3)); + /// assert_eq!(cursor.peek_prev(), Some((&2, &"b"))); + /// assert_eq!(cursor.peek_next(), Some((&3, &"c"))); + /// + /// let cursor = map.upper_bound(Bound::Unbounded); + /// assert_eq!(cursor.peek_prev(), Some((&4, &"d"))); + /// assert_eq!(cursor.peek_next(), None); + /// ``` + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn upper_bound(&self, bound: Bound<&Q>) -> Cursor<'_, K, V> + where + K: Borrow + Ord, + Q: Ord, + { + let root_node = match self.root.as_ref() { + None => return Cursor { current: None, root: None }, + Some(root) => root.reborrow(), + }; + let edge = root_node.upper_bound(SearchBound::from_range(bound)); + Cursor { current: Some(edge), root: self.root.as_ref() } + } + + /// Returns a [`CursorMut`] pointing at the gap after the greatest key + /// smaller than the given bound. + /// + /// Passing `Bound::Included(x)` will return a cursor pointing to the + /// gap after the greatest key smaller than or equal to `x`. + /// + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the + /// gap after the greatest key smaller than `x`. + /// + /// Passing `Bound::Unbounded` will return a cursor pointing to the + /// gap after the greatest key in the map. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_cursors)] + /// + /// use std::collections::BTreeMap; + /// use std::ops::Bound; + /// + /// let mut map = BTreeMap::from([ + /// (1, "a"), + /// (2, "b"), + /// (3, "c"), + /// (4, "d"), + /// ]); + /// + /// let mut cursor = map.upper_bound_mut(Bound::Included(&3)); + /// assert_eq!(cursor.peek_prev(), Some((&3, &mut "c"))); + /// assert_eq!(cursor.peek_next(), Some((&4, &mut "d"))); + /// + /// let mut cursor = map.upper_bound_mut(Bound::Excluded(&3)); + /// assert_eq!(cursor.peek_prev(), Some((&2, &mut "b"))); + /// assert_eq!(cursor.peek_next(), Some((&3, &mut "c"))); + /// + /// let mut cursor = map.upper_bound_mut(Bound::Unbounded); + /// assert_eq!(cursor.peek_prev(), Some((&4, &mut "d"))); + /// assert_eq!(cursor.peek_next(), None); + /// ``` + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn upper_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, K, V, A> + where + K: Borrow + Ord, + Q: Ord, + { + let (root, dormant_root) = DormantMutRef::new(&mut self.root); + let root_node = match root.as_mut() { + None => { + return CursorMut { + inner: CursorMutKey { + current: None, + root: dormant_root, + length: &mut self.length, + alloc: &mut *self.alloc, + }, + }; + } + Some(root) => root.borrow_mut(), + }; + let edge = root_node.upper_bound(SearchBound::from_range(bound)); + CursorMut { + inner: CursorMutKey { + current: Some(edge), + root: dormant_root, + length: &mut self.length, + alloc: &mut *self.alloc, + }, + } + } +} + +/// A cursor over a `BTreeMap`. +/// +/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth. +/// +/// Cursors always point to a gap between two elements in the map, and can +/// operate on the two immediately adjacent elements. +/// +/// A `Cursor` is created with the [`BTreeMap::lower_bound`] and [`BTreeMap::upper_bound`] methods. +#[unstable(feature = "btree_cursors", issue = "107540")] +pub struct Cursor<'a, K: 'a, V: 'a> { + // If current is None then it means the tree has not been allocated yet. + current: Option, K, V, marker::Leaf>, marker::Edge>>, + root: Option<&'a node::Root>, +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl Clone for Cursor<'_, K, V> { + fn clone(&self) -> Self { + let Cursor { current, root } = *self; + Cursor { current, root } + } +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl Debug for Cursor<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Cursor") + } +} + +/// A cursor over a `BTreeMap` with editing operations. +/// +/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can +/// safely mutate the map during iteration. This is because the lifetime of its yielded +/// references is tied to its own lifetime, instead of just the underlying map. This means +/// cursors cannot yield multiple elements at once. +/// +/// Cursors always point to a gap between two elements in the map, and can +/// operate on the two immediately adjacent elements. +/// +/// A `CursorMut` is created with the [`BTreeMap::lower_bound_mut`] and [`BTreeMap::upper_bound_mut`] +/// methods. +#[unstable(feature = "btree_cursors", issue = "107540")] +pub struct CursorMut< + 'a, + K: 'a, + V: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A = Global, +> { + inner: CursorMutKey<'a, K, V, A>, +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl Debug for CursorMut<'_, K, V, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("CursorMut") + } +} + +/// A cursor over a `BTreeMap` with editing operations, and which allows +/// mutating the key of elements. +/// +/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can +/// safely mutate the map during iteration. This is because the lifetime of its yielded +/// references is tied to its own lifetime, instead of just the underlying map. This means +/// cursors cannot yield multiple elements at once. +/// +/// Cursors always point to a gap between two elements in the map, and can +/// operate on the two immediately adjacent elements. +/// +/// A `CursorMutKey` is created from a [`CursorMut`] with the +/// [`CursorMut::with_mutable_key`] method. +/// +/// # Safety +/// +/// Since this cursor allows mutating keys, you must ensure that the `BTreeMap` +/// invariants are maintained. Specifically: +/// +/// * The key of the newly inserted element must be unique in the tree. +/// * All keys in the tree must remain in sorted order. +#[unstable(feature = "btree_cursors", issue = "107540")] +pub struct CursorMutKey< + 'a, + K: 'a, + V: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A = Global, +> { + // If current is None then it means the tree has not been allocated yet. + current: Option, K, V, marker::Leaf>, marker::Edge>>, + root: DormantMutRef<'a, Option>>, + length: &'a mut usize, + alloc: &'a mut A, +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl Debug for CursorMutKey<'_, K, V, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("CursorMutKey") + } +} + +impl<'a, K, V> Cursor<'a, K, V> { + /// Advances the cursor to the next gap, returning the key and value of the + /// element that it moved over. + /// + /// If the cursor is already at the end of the map then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn next(&mut self) -> Option<(&'a K, &'a V)> { + let current = self.current.take()?; + match current.next_kv() { + Ok(kv) => { + let result = kv.into_kv(); + self.current = Some(kv.next_leaf_edge()); + Some(result) + } + Err(root) => { + self.current = Some(root.last_leaf_edge()); + None + } + } + } + + /// Advances the cursor to the previous gap, returning the key and value of + /// the element that it moved over. + /// + /// If the cursor is already at the start of the map then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn prev(&mut self) -> Option<(&'a K, &'a V)> { + let current = self.current.take()?; + match current.next_back_kv() { + Ok(kv) => { + let result = kv.into_kv(); + self.current = Some(kv.next_back_leaf_edge()); + Some(result) + } + Err(root) => { + self.current = Some(root.first_leaf_edge()); + None + } + } + } + + /// Returns a reference to the key and value of the next element without + /// moving the cursor. + /// + /// If the cursor is at the end of the map then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_next(&self) -> Option<(&'a K, &'a V)> { + self.clone().next() + } + + /// Returns a reference to the key and value of the previous element + /// without moving the cursor. + /// + /// If the cursor is at the start of the map then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_prev(&self) -> Option<(&'a K, &'a V)> { + self.clone().prev() + } +} + +impl<'a, K, V, A> CursorMut<'a, K, V, A> { + /// Advances the cursor to the next gap, returning the key and value of the + /// element that it moved over. + /// + /// If the cursor is already at the end of the map then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn next(&mut self) -> Option<(&K, &mut V)> { + let (k, v) = self.inner.next()?; + Some((&*k, v)) + } + + /// Advances the cursor to the previous gap, returning the key and value of + /// the element that it moved over. + /// + /// If the cursor is already at the start of the map then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn prev(&mut self) -> Option<(&K, &mut V)> { + let (k, v) = self.inner.prev()?; + Some((&*k, v)) + } + + /// Returns a reference to the key and value of the next element without + /// moving the cursor. + /// + /// If the cursor is at the end of the map then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_next(&mut self) -> Option<(&K, &mut V)> { + let (k, v) = self.inner.peek_next()?; + Some((&*k, v)) + } + + /// Returns a reference to the key and value of the previous element + /// without moving the cursor. + /// + /// If the cursor is at the start of the map then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_prev(&mut self) -> Option<(&K, &mut V)> { + let (k, v) = self.inner.peek_prev()?; + Some((&*k, v)) + } + + /// Returns a read-only cursor pointing to the same location as the + /// `CursorMut`. + /// + /// The lifetime of the returned `Cursor` is bound to that of the + /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the + /// `CursorMut` is frozen for the lifetime of the `Cursor`. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn as_cursor(&self) -> Cursor<'_, K, V> { + self.inner.as_cursor() + } + + /// Converts the cursor into a [`CursorMutKey`], which allows mutating + /// the key of elements in the tree. + /// + /// # Safety + /// + /// Since this cursor allows mutating keys, you must ensure that the `BTreeMap` + /// invariants are maintained. Specifically: + /// + /// * The key of the newly inserted element must be unique in the tree. + /// * All keys in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn with_mutable_key(self) -> CursorMutKey<'a, K, V, A> { + self.inner + } +} + +impl<'a, K, V, A> CursorMutKey<'a, K, V, A> { + /// Advances the cursor to the next gap, returning the key and value of the + /// element that it moved over. + /// + /// If the cursor is already at the end of the map then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn next(&mut self) -> Option<(&mut K, &mut V)> { + let current = self.current.take()?; + match current.next_kv() { + Ok(mut kv) => { + // SAFETY: The key/value pointers remain valid even after the + // cursor is moved forward. The lifetimes then prevent any + // further access to the cursor. + let (k, v) = unsafe { kv.reborrow_mut().into_kv_mut() }; + let (k, v) = (k as *mut _, v as *mut _); + self.current = Some(kv.next_leaf_edge()); + Some(unsafe { (&mut *k, &mut *v) }) + } + Err(root) => { + self.current = Some(root.last_leaf_edge()); + None + } + } + } + + /// Advances the cursor to the previous gap, returning the key and value of + /// the element that it moved over. + /// + /// If the cursor is already at the start of the map then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn prev(&mut self) -> Option<(&mut K, &mut V)> { + let current = self.current.take()?; + match current.next_back_kv() { + Ok(mut kv) => { + // SAFETY: The key/value pointers remain valid even after the + // cursor is moved forward. The lifetimes then prevent any + // further access to the cursor. + let (k, v) = unsafe { kv.reborrow_mut().into_kv_mut() }; + let (k, v) = (k as *mut _, v as *mut _); + self.current = Some(kv.next_back_leaf_edge()); + Some(unsafe { (&mut *k, &mut *v) }) + } + Err(root) => { + self.current = Some(root.first_leaf_edge()); + None + } + } + } + + /// Returns a reference to the key and value of the next element without + /// moving the cursor. + /// + /// If the cursor is at the end of the map then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_next(&mut self) -> Option<(&mut K, &mut V)> { + let current = self.current.as_mut()?; + // SAFETY: We're not using this to mutate the tree. + let kv = unsafe { current.reborrow_mut() }.next_kv().ok()?.into_kv_mut(); + Some(kv) + } + + /// Returns a reference to the key and value of the previous element + /// without moving the cursor. + /// + /// If the cursor is at the start of the map then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_prev(&mut self) -> Option<(&mut K, &mut V)> { + let current = self.current.as_mut()?; + // SAFETY: We're not using this to mutate the tree. + let kv = unsafe { current.reborrow_mut() }.next_back_kv().ok()?.into_kv_mut(); + Some(kv) + } + + /// Returns a read-only cursor pointing to the same location as the + /// `CursorMutKey`. + /// + /// The lifetime of the returned `Cursor` is bound to that of the + /// `CursorMutKey`, which means it cannot outlive the `CursorMutKey` and that the + /// `CursorMutKey` is frozen for the lifetime of the `Cursor`. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn as_cursor(&self) -> Cursor<'_, K, V> { + Cursor { + // SAFETY: The tree is immutable while the cursor exists. + root: unsafe { self.root.reborrow_shared().as_ref() }, + current: self.current.as_ref().map(|current| current.reborrow()), + } + } +} + +// Now the tree editing operations +impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> { + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap before the + /// newly inserted element. + /// + /// # Safety + /// + /// You must ensure that the `BTreeMap` invariants are maintained. + /// Specifically: + /// + /// * The key of the newly inserted element must be unique in the tree. + /// * All keys in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn insert_after_unchecked(&mut self, key: K, value: V) { + let edge = match self.current.take() { + None => { + // Tree is empty, allocate a new root. + // SAFETY: We have no other reference to the tree. + let root = unsafe { self.root.reborrow() }; + debug_assert!(root.is_none()); + let mut node = NodeRef::new_leaf(self.alloc.clone()); + // SAFETY: We don't touch the root while the handle is alive. + let handle = unsafe { node.borrow_mut().push_with_handle(key, value) }; + *root = Some(node.forget_type()); + *self.length += 1; + self.current = Some(handle.left_edge()); + return; + } + Some(current) => current, + }; + + let handle = edge.insert_recursing(key, value, self.alloc.clone(), |ins| { + drop(ins.left); + // SAFETY: The handle to the newly inserted value is always on a + // leaf node, so adding a new root node doesn't invalidate it. + let root = unsafe { self.root.reborrow().as_mut().unwrap() }; + root.push_internal_level(self.alloc.clone()).push(ins.kv.0, ins.kv.1, ins.right) + }); + self.current = Some(handle.left_edge()); + *self.length += 1; + } + + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// # Safety + /// + /// You must ensure that the `BTreeMap` invariants are maintained. + /// Specifically: + /// + /// * The key of the newly inserted element must be unique in the tree. + /// * All keys in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn insert_before_unchecked(&mut self, key: K, value: V) { + let edge = match self.current.take() { + None => { + // SAFETY: We have no other reference to the tree. + match unsafe { self.root.reborrow() } { + root @ None => { + // Tree is empty, allocate a new root. + let mut node = NodeRef::new_leaf(self.alloc.clone()); + // SAFETY: We don't touch the root while the handle is alive. + let handle = unsafe { node.borrow_mut().push_with_handle(key, value) }; + *root = Some(node.forget_type()); + *self.length += 1; + self.current = Some(handle.right_edge()); + return; + } + Some(root) => root.borrow_mut().last_leaf_edge(), + } + } + Some(current) => current, + }; + + let handle = edge.insert_recursing(key, value, self.alloc.clone(), |ins| { + drop(ins.left); + // SAFETY: The handle to the newly inserted value is always on a + // leaf node, so adding a new root node doesn't invalidate it. + let root = unsafe { self.root.reborrow().as_mut().unwrap() }; + root.push_internal_level(self.alloc.clone()).push(ins.kv.0, ins.kv.1, ins.right) + }); + self.current = Some(handle.right_edge()); + *self.length += 1; + } + + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap before the + /// newly inserted element. + /// + /// If the inserted key is not greater than the key before the cursor + /// (if any), or if it not less than the key after the cursor (if any), + /// then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the keys of the map. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn insert_after(&mut self, key: K, value: V) -> Result<(), UnorderedKeyError> { + if let Some((prev, _)) = self.peek_prev() { + if &key <= prev { + return Err(UnorderedKeyError {}); + } + } + if let Some((next, _)) = self.peek_next() { + if &key >= next { + return Err(UnorderedKeyError {}); + } + } + unsafe { + self.insert_after_unchecked(key, value); + } + Ok(()) + } + + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// If the inserted key is not greater than the key before the cursor + /// (if any), or if it not less than the key after the cursor (if any), + /// then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the keys of the map. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn insert_before(&mut self, key: K, value: V) -> Result<(), UnorderedKeyError> { + if let Some((prev, _)) = self.peek_prev() { + if &key <= prev { + return Err(UnorderedKeyError {}); + } + } + if let Some((next, _)) = self.peek_next() { + if &key >= next { + return Err(UnorderedKeyError {}); + } + } + unsafe { + self.insert_before_unchecked(key, value); + } + Ok(()) + } + + /// Removes the next element from the `BTreeMap`. + /// + /// The element that was removed is returned. The cursor position is + /// unchanged (before the removed element). + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn remove_next(&mut self) -> Option<(K, V)> { + let current = self.current.take()?; + if current.reborrow().next_kv().is_err() { + self.current = Some(current); + return None; + } + let mut emptied_internal_root = false; + let (kv, pos) = current + .next_kv() + // This should be unwrap(), but that doesn't work because NodeRef + // doesn't implement Debug. The condition is checked above. + .ok()? + .remove_kv_tracking(|| emptied_internal_root = true, self.alloc.clone()); + self.current = Some(pos); + *self.length -= 1; + if emptied_internal_root { + // SAFETY: This is safe since current does not point within the now + // empty root node. + let root = unsafe { self.root.reborrow().as_mut().unwrap() }; + root.pop_internal_level(self.alloc.clone()); + } + Some(kv) + } + + /// Removes the preceding element from the `BTreeMap`. + /// + /// The element that was removed is returned. The cursor position is + /// unchanged (after the removed element). + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn remove_prev(&mut self) -> Option<(K, V)> { + let current = self.current.take()?; + if current.reborrow().next_back_kv().is_err() { + self.current = Some(current); + return None; + } + let mut emptied_internal_root = false; + let (kv, pos) = current + .next_back_kv() + // This should be unwrap(), but that doesn't work because NodeRef + // doesn't implement Debug. The condition is checked above. + .ok()? + .remove_kv_tracking(|| emptied_internal_root = true, self.alloc.clone()); + self.current = Some(pos); + *self.length -= 1; + if emptied_internal_root { + // SAFETY: This is safe since current does not point within the now + // empty root node. + let root = unsafe { self.root.reborrow().as_mut().unwrap() }; + root.pop_internal_level(self.alloc.clone()); + } + Some(kv) + } +} + +impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> { + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// # Safety + /// + /// You must ensure that the `BTreeMap` invariants are maintained. + /// Specifically: + /// + /// * The key of the newly inserted element must be unique in the tree. + /// * All keys in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn insert_after_unchecked(&mut self, key: K, value: V) { + unsafe { self.inner.insert_after_unchecked(key, value) } + } + + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// # Safety + /// + /// You must ensure that the `BTreeMap` invariants are maintained. + /// Specifically: + /// + /// * The key of the newly inserted element must be unique in the tree. + /// * All keys in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn insert_before_unchecked(&mut self, key: K, value: V) { + unsafe { self.inner.insert_before_unchecked(key, value) } + } + + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap before the + /// newly inserted element. + /// + /// If the inserted key is not greater than the key before the cursor + /// (if any), or if it not less than the key after the cursor (if any), + /// then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the keys of the map. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn insert_after(&mut self, key: K, value: V) -> Result<(), UnorderedKeyError> { + self.inner.insert_after(key, value) + } + + /// Inserts a new key-value pair into the map in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// If the inserted key is not greater than the key before the cursor + /// (if any), or if it not less than the key after the cursor (if any), + /// then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the keys of the map. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn insert_before(&mut self, key: K, value: V) -> Result<(), UnorderedKeyError> { + self.inner.insert_before(key, value) + } + + /// Removes the next element from the `BTreeMap`. + /// + /// The element that was removed is returned. The cursor position is + /// unchanged (before the removed element). + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn remove_next(&mut self) -> Option<(K, V)> { + self.inner.remove_next() + } + + /// Removes the preceding element from the `BTreeMap`. + /// + /// The element that was removed is returned. The cursor position is + /// unchanged (after the removed element). + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn remove_prev(&mut self) -> Option<(K, V)> { + self.inner.remove_prev() + } +} + +/// Error type returned by [`CursorMut::insert_before`] and +/// [`CursorMut::insert_after`] if the key being inserted is not properly +/// ordered with regards to adjacent keys. +#[derive(Clone, PartialEq, Eq, Debug)] +#[unstable(feature = "btree_cursors", issue = "107540")] +pub struct UnorderedKeyError {} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl fmt::Display for UnorderedKeyError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "key is not properly ordered relative to neighbors") + } +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl Error for UnorderedKeyError {} + +#[cfg(test)] +mod tests; diff --git a/CoqOfRust/alloc/collections/btree/map/entry.rs b/CoqOfRust/alloc/collections/btree/map/entry.rs new file mode 100644 index 000000000..ea8fa363c --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/map/entry.rs @@ -0,0 +1,620 @@ +use core::fmt::{self, Debug}; +use core::marker::PhantomData; +use core::mem; + +use Entry::*; + +use super::super::borrow::DormantMutRef; +use super::super::node::{Handle, NodeRef, marker}; +use super::BTreeMap; +use crate::alloc::{Allocator, Global}; + +/// A view into a single entry in a map, which may either be vacant or occupied. +/// +/// This `enum` is constructed from the [`entry`] method on [`BTreeMap`]. +/// +/// [`entry`]: BTreeMap::entry +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeEntry")] +pub enum Entry< + 'a, + K: 'a, + V: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + /// A vacant entry. + #[stable(feature = "rust1", since = "1.0.0")] + Vacant(#[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V, A>), + + /// An occupied entry. + #[stable(feature = "rust1", since = "1.0.0")] + Occupied(#[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V, A>), +} + +#[stable(feature = "debug_btree_map", since = "1.12.0")] +impl Debug for Entry<'_, K, V, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(), + Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(), + } + } +} + +/// A view into a vacant entry in a `BTreeMap`. +/// It is part of the [`Entry`] enum. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct VacantEntry< + 'a, + K, + V, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + pub(super) key: K, + /// `None` for a (empty) map without root + pub(super) handle: Option, K, V, marker::Leaf>, marker::Edge>>, + pub(super) dormant_map: DormantMutRef<'a, BTreeMap>, + + /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`. + pub(super) alloc: A, + + // Be invariant in `K` and `V` + pub(super) _marker: PhantomData<&'a mut (K, V)>, +} + +#[stable(feature = "debug_btree_map", since = "1.12.0")] +impl Debug for VacantEntry<'_, K, V, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("VacantEntry").field(self.key()).finish() + } +} + +/// A view into an occupied entry in a `BTreeMap`. +/// It is part of the [`Entry`] enum. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct OccupiedEntry< + 'a, + K, + V, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + pub(super) handle: Handle, K, V, marker::LeafOrInternal>, marker::KV>, + pub(super) dormant_map: DormantMutRef<'a, BTreeMap>, + + /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`. + pub(super) alloc: A, + + // Be invariant in `K` and `V` + pub(super) _marker: PhantomData<&'a mut (K, V)>, +} + +#[stable(feature = "debug_btree_map", since = "1.12.0")] +impl Debug for OccupiedEntry<'_, K, V, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OccupiedEntry").field("key", self.key()).field("value", self.get()).finish() + } +} + +/// The error returned by [`try_insert`](BTreeMap::try_insert) when the key already exists. +/// +/// Contains the occupied entry, and the value that was not inserted. +#[unstable(feature = "map_try_insert", issue = "82766")] +pub struct OccupiedError<'a, K: 'a, V: 'a, A: Allocator + Clone = Global> { + /// The entry in the map that was already occupied. + pub entry: OccupiedEntry<'a, K, V, A>, + /// The value which was not inserted, because the entry was already occupied. + pub value: V, +} + +#[unstable(feature = "map_try_insert", issue = "82766")] +impl Debug for OccupiedError<'_, K, V, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OccupiedError") + .field("key", self.entry.key()) + .field("old_value", self.entry.get()) + .field("new_value", &self.value) + .finish() + } +} + +#[unstable(feature = "map_try_insert", issue = "82766")] +impl<'a, K: Debug + Ord, V: Debug, A: Allocator + Clone> fmt::Display + for OccupiedError<'a, K, V, A> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "failed to insert {:?}, key {:?} already exists with value {:?}", + self.value, + self.entry.key(), + self.entry.get(), + ) + } +} + +#[unstable(feature = "map_try_insert", issue = "82766")] +impl<'a, K: core::fmt::Debug + Ord, V: core::fmt::Debug> core::error::Error + for crate::collections::btree_map::OccupiedError<'a, K, V> +{ + #[allow(deprecated)] + fn description(&self) -> &str { + "key already exists" + } +} + +impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { + /// Ensures a value is in the entry by inserting the default if empty, and returns + /// a mutable reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// + /// assert_eq!(map["poneyland"], 12); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn or_insert(self, default: V) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default), + } + } + + /// Ensures a value is in the entry by inserting the result of the default function if empty, + /// and returns a mutable reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, String> = BTreeMap::new(); + /// let s = "hoho".to_string(); + /// + /// map.entry("poneyland").or_insert_with(|| s); + /// + /// assert_eq!(map["poneyland"], "hoho".to_string()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn or_insert_with V>(self, default: F) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default()), + } + } + + /// Ensures a value is in the entry by inserting, if empty, the result of the default function. + /// + /// This method allows for generating key-derived values for insertion by providing the default + /// function a reference to the key that was moved during the `.entry(key)` method call. + /// + /// The reference to the moved key is provided so that cloning or copying the key is + /// unnecessary, unlike with `.or_insert_with(|| ... )`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// + /// map.entry("poneyland").or_insert_with_key(|key| key.chars().count()); + /// + /// assert_eq!(map["poneyland"], 9); + /// ``` + #[inline] + #[stable(feature = "or_insert_with_key", since = "1.50.0")] + pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => { + let value = default(entry.key()); + entry.insert(value) + } + } + } + + /// Returns a reference to this entry's key. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); + /// ``` + #[stable(feature = "map_entry_keys", since = "1.10.0")] + pub fn key(&self) -> &K { + match *self { + Occupied(ref entry) => entry.key(), + Vacant(ref entry) => entry.key(), + } + } + + /// Provides in-place mutable access to an occupied entry before any + /// potential inserts into the map. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// + /// map.entry("poneyland") + /// .and_modify(|e| { *e += 1 }) + /// .or_insert(42); + /// assert_eq!(map["poneyland"], 42); + /// + /// map.entry("poneyland") + /// .and_modify(|e| { *e += 1 }) + /// .or_insert(42); + /// assert_eq!(map["poneyland"], 43); + /// ``` + #[stable(feature = "entry_and_modify", since = "1.26.0")] + pub fn and_modify(self, f: F) -> Self + where + F: FnOnce(&mut V), + { + match self { + Occupied(mut entry) => { + f(entry.get_mut()); + Occupied(entry) + } + Vacant(entry) => Vacant(entry), + } + } + + /// Sets the value of the entry, and returns an `OccupiedEntry`. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_entry_insert)] + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, String> = BTreeMap::new(); + /// let entry = map.entry("poneyland").insert_entry("hoho".to_string()); + /// + /// assert_eq!(entry.key(), &"poneyland"); + /// ``` + #[inline] + #[unstable(feature = "btree_entry_insert", issue = "65225")] + pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, A> { + match self { + Occupied(mut entry) => { + entry.insert(value); + entry + } + Vacant(entry) => entry.insert_entry(value), + } + } +} + +impl<'a, K: Ord, V: Default, A: Allocator + Clone> Entry<'a, K, V, A> { + #[stable(feature = "entry_or_default", since = "1.28.0")] + /// Ensures a value is in the entry by inserting the default value if empty, + /// and returns a mutable reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, Option> = BTreeMap::new(); + /// map.entry("poneyland").or_default(); + /// + /// assert_eq!(map["poneyland"], None); + /// ``` + pub fn or_default(self) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(Default::default()), + } + } +} + +impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> { + /// Gets a reference to the key that would be used when inserting a value + /// through the VacantEntry. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); + /// ``` + #[stable(feature = "map_entry_keys", since = "1.10.0")] + pub fn key(&self) -> &K { + &self.key + } + + /// Take ownership of the key. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// + /// if let Entry::Vacant(v) = map.entry("poneyland") { + /// v.into_key(); + /// } + /// ``` + #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] + pub fn into_key(self) -> K { + self.key + } + + /// Sets the value of the entry with the `VacantEntry`'s key, + /// and returns a mutable reference to it. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, u32> = BTreeMap::new(); + /// + /// if let Entry::Vacant(o) = map.entry("poneyland") { + /// o.insert(37); + /// } + /// assert_eq!(map["poneyland"], 37); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push", "put")] + pub fn insert(self, value: V) -> &'a mut V { + self.insert_entry(value).into_mut() + } + + /// Sets the value of the entry with the `VacantEntry`'s key, + /// and returns an `OccupiedEntry`. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_entry_insert)] + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, u32> = BTreeMap::new(); + /// + /// if let Entry::Vacant(o) = map.entry("poneyland") { + /// let entry = o.insert_entry(37); + /// assert_eq!(entry.get(), &37); + /// } + /// assert_eq!(map["poneyland"], 37); + /// ``` + #[unstable(feature = "btree_entry_insert", issue = "65225")] + pub fn insert_entry(mut self, value: V) -> OccupiedEntry<'a, K, V, A> { + let handle = match self.handle { + None => { + // SAFETY: There is no tree yet so no reference to it exists. + let map = unsafe { self.dormant_map.reborrow() }; + let root = map.root.insert(NodeRef::new_leaf(self.alloc.clone()).forget_type()); + // SAFETY: We *just* created the root as a leaf, and we're + // stacking the new handle on the original borrow lifetime. + unsafe { + let mut leaf = root.borrow_mut().cast_to_leaf_unchecked(); + leaf.push_with_handle(self.key, value) + } + } + Some(handle) => handle.insert_recursing(self.key, value, self.alloc.clone(), |ins| { + drop(ins.left); + // SAFETY: Pushing a new root node doesn't invalidate + // handles to existing nodes. + let map = unsafe { self.dormant_map.reborrow() }; + let root = map.root.as_mut().unwrap(); // same as ins.left + root.push_internal_level(self.alloc.clone()).push(ins.kv.0, ins.kv.1, ins.right) + }), + }; + + // SAFETY: modifying the length doesn't invalidate handles to existing nodes. + unsafe { self.dormant_map.reborrow().length += 1 }; + + OccupiedEntry { + handle: handle.forget_node_type(), + dormant_map: self.dormant_map, + alloc: self.alloc, + _marker: PhantomData, + } + } +} + +impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { + /// Gets a reference to the key in the entry. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); + /// ``` + #[must_use] + #[stable(feature = "map_entry_keys", since = "1.10.0")] + pub fn key(&self) -> &K { + self.handle.reborrow().into_kv().0 + } + + /// Converts the entry into a reference to its key. + pub(crate) fn into_key(self) -> &'a K { + self.handle.into_kv_mut().0 + } + + /// Take ownership of the key and value from the map. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// + /// if let Entry::Occupied(o) = map.entry("poneyland") { + /// // We delete the entry from the map. + /// o.remove_entry(); + /// } + /// + /// // If now try to get the value, it will panic: + /// // println!("{}", map["poneyland"]); + /// ``` + #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] + pub fn remove_entry(self) -> (K, V) { + self.remove_kv() + } + + /// Gets a reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// + /// if let Entry::Occupied(o) = map.entry("poneyland") { + /// assert_eq!(o.get(), &12); + /// } + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get(&self) -> &V { + self.handle.reborrow().into_kv().1 + } + + /// Gets a mutable reference to the value in the entry. + /// + /// If you need a reference to the `OccupiedEntry` that may outlive the + /// destruction of the `Entry` value, see [`into_mut`]. + /// + /// [`into_mut`]: OccupiedEntry::into_mut + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// + /// assert_eq!(map["poneyland"], 12); + /// if let Entry::Occupied(mut o) = map.entry("poneyland") { + /// *o.get_mut() += 10; + /// assert_eq!(*o.get(), 22); + /// + /// // We can use the same Entry multiple times. + /// *o.get_mut() += 2; + /// } + /// assert_eq!(map["poneyland"], 24); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get_mut(&mut self) -> &mut V { + self.handle.kv_mut().1 + } + + /// Converts the entry into a mutable reference to its value. + /// + /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`]. + /// + /// [`get_mut`]: OccupiedEntry::get_mut + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// + /// assert_eq!(map["poneyland"], 12); + /// if let Entry::Occupied(o) = map.entry("poneyland") { + /// *o.into_mut() += 10; + /// } + /// assert_eq!(map["poneyland"], 22); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_mut(self) -> &'a mut V { + self.handle.into_val_mut() + } + + /// Sets the value of the entry with the `OccupiedEntry`'s key, + /// and returns the entry's old value. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// + /// if let Entry::Occupied(mut o) = map.entry("poneyland") { + /// assert_eq!(o.insert(15), 12); + /// } + /// assert_eq!(map["poneyland"], 15); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push", "put")] + pub fn insert(&mut self, value: V) -> V { + mem::replace(self.get_mut(), value) + } + + /// Takes the value of the entry out of the map, and returns it. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// + /// if let Entry::Occupied(o) = map.entry("poneyland") { + /// assert_eq!(o.remove(), 12); + /// } + /// // If we try to get "poneyland"'s value, it'll panic: + /// // println!("{}", map["poneyland"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("delete", "take")] + pub fn remove(self) -> V { + self.remove_kv().1 + } + + // Body of `remove_entry`, probably separate because the name reflects the returned pair. + pub(super) fn remove_kv(self) -> (K, V) { + let mut emptied_internal_root = false; + let (old_kv, _) = + self.handle.remove_kv_tracking(|| emptied_internal_root = true, self.alloc.clone()); + // SAFETY: we consumed the intermediate root borrow, `self.handle`. + let map = unsafe { self.dormant_map.awaken() }; + map.length -= 1; + if emptied_internal_root { + let root = map.root.as_mut().unwrap(); + root.pop_internal_level(self.alloc); + } + old_kv + } +} diff --git a/CoqOfRust/alloc/collections/btree/map/tests.rs b/CoqOfRust/alloc/collections/btree/map/tests.rs new file mode 100644 index 000000000..597513438 --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/map/tests.rs @@ -0,0 +1,2565 @@ +use core::assert_matches::assert_matches; +use std::iter; +use std::ops::Bound::{Excluded, Included, Unbounded}; +use std::panic::{AssertUnwindSafe, catch_unwind}; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering::SeqCst; + +use super::*; +use crate::boxed::Box; +use crate::fmt::Debug; +use crate::rc::Rc; +use crate::string::{String, ToString}; +use crate::testing::crash_test::{CrashTestDummy, Panic}; +use crate::testing::ord_chaos::{Cyclic3, Governed, Governor}; +use crate::testing::rng::DeterministicRng; + +// Minimum number of elements to insert, to guarantee a tree with 2 levels, +// i.e., a tree who's root is an internal node at height 1, with edges to leaf nodes. +// It's not the minimum size: removing an element from such a tree does not always reduce height. +const MIN_INSERTS_HEIGHT_1: usize = node::CAPACITY + 1; + +// Minimum number of elements to insert in ascending order, to guarantee a tree with 3 levels, +// i.e., a tree who's root is an internal node at height 2, with edges to more internal nodes. +// It's not the minimum size: removing an element from such a tree does not always reduce height. +const MIN_INSERTS_HEIGHT_2: usize = 89; + +// Gathers all references from a mutable iterator and makes sure Miri notices if +// using them is dangerous. +fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator) { + // Gather all those references. + let mut refs: Vec<&mut T> = iter.collect(); + // Use them all. Twice, to be sure we got all interleavings. + for r in refs.iter_mut() { + mem::swap(dummy, r); + } + for r in refs { + mem::swap(dummy, r); + } +} + +impl BTreeMap { + // Panics if the map (or the code navigating it) is corrupted. + fn check_invariants(&self) { + if let Some(root) = &self.root { + let root_node = root.reborrow(); + + // Check the back pointers top-down, before we attempt to rely on + // more serious navigation code. + assert!(root_node.ascend().is_err()); + root_node.assert_back_pointers(); + + // Check consistency of `length` with what navigation code encounters. + assert_eq!(self.length, root_node.calc_length()); + + // Lastly, check the invariant causing the least harm. + root_node.assert_min_len(if root_node.height() > 0 { 1 } else { 0 }); + } else { + assert_eq!(self.length, 0); + } + + // Check that `assert_strictly_ascending` will encounter all keys. + assert_eq!(self.length, self.keys().count()); + } + + // Panics if the map is corrupted or if the keys are not in strictly + // ascending order, in the current opinion of the `Ord` implementation. + // If the `Ord` implementation violates transitivity, this method does not + // guarantee that all keys are unique, just that adjacent keys are unique. + fn check(&self) + where + K: Debug + Ord, + { + self.check_invariants(); + self.assert_strictly_ascending(); + } + + // Returns the height of the root, if any. + fn height(&self) -> Option { + self.root.as_ref().map(node::Root::height) + } + + fn dump_keys(&self) -> String + where + K: Debug, + { + if let Some(root) = self.root.as_ref() { + root.reborrow().dump_keys() + } else { + String::from("not yet allocated") + } + } + + // Panics if the keys are not in strictly ascending order. + fn assert_strictly_ascending(&self) + where + K: Debug + Ord, + { + let mut keys = self.keys(); + if let Some(mut previous) = keys.next() { + for next in keys { + assert!(previous < next, "{:?} >= {:?}", previous, next); + previous = next; + } + } + } + + // Transform the tree to minimize wasted space, obtaining fewer nodes that + // are mostly filled up to their capacity. The same compact tree could have + // been obtained by inserting keys in a shrewd order. + fn compact(&mut self) + where + K: Ord, + { + let iter = mem::take(self).into_iter(); + if !iter.is_empty() { + self.root.insert(Root::new(*self.alloc)).bulk_push(iter, &mut self.length, *self.alloc); + } + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + fn assert_min_len(self, min_len: usize) { + assert!(self.len() >= min_len, "node len {} < {}", self.len(), min_len); + if let node::ForceResult::Internal(node) = self.force() { + for idx in 0..=node.len() { + let edge = unsafe { Handle::new_edge(node, idx) }; + edge.descend().assert_min_len(MIN_LEN); + } + } + } +} + +// Tests our value of MIN_INSERTS_HEIGHT_2. Failure may mean you just need to +// adapt that value to match a change in node::CAPACITY or the choices made +// during insertion, otherwise other test cases may fail or be less useful. +#[test] +fn test_levels() { + let mut map = BTreeMap::new(); + map.check(); + assert_eq!(map.height(), None); + assert_eq!(map.len(), 0); + + map.insert(0, ()); + while map.height() == Some(0) { + let last_key = *map.last_key_value().unwrap().0; + map.insert(last_key + 1, ()); + } + map.check(); + // Structure: + // - 1 element in internal root node with 2 children + // - 6 elements in left leaf child + // - 5 elements in right leaf child + assert_eq!(map.height(), Some(1)); + assert_eq!(map.len(), MIN_INSERTS_HEIGHT_1, "{}", map.dump_keys()); + + while map.height() == Some(1) { + let last_key = *map.last_key_value().unwrap().0; + map.insert(last_key + 1, ()); + } + map.check(); + // Structure: + // - 1 element in internal root node with 2 children + // - 6 elements in left internal child with 7 grandchildren + // - 42 elements in left child's 7 grandchildren with 6 elements each + // - 5 elements in right internal child with 6 grandchildren + // - 30 elements in right child's 5 first grandchildren with 6 elements each + // - 5 elements in right child's last grandchild + assert_eq!(map.height(), Some(2)); + assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2, "{}", map.dump_keys()); +} + +// Ensures the testing infrastructure usually notices order violations. +#[test] +#[should_panic] +fn test_check_ord_chaos() { + let gov = Governor::new(); + let map = BTreeMap::from([(Governed(1, &gov), ()), (Governed(2, &gov), ())]); + gov.flip(); + map.check(); +} + +// Ensures the testing infrastructure doesn't always mind order violations. +#[test] +fn test_check_invariants_ord_chaos() { + let gov = Governor::new(); + let map = BTreeMap::from([(Governed(1, &gov), ()), (Governed(2, &gov), ())]); + gov.flip(); + map.check_invariants(); +} + +#[test] +fn test_basic_large() { + let mut map = BTreeMap::new(); + // Miri is too slow + let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 } else { 10000 }; + let size = size + (size % 2); // round up to even number + assert_eq!(map.len(), 0); + + for i in 0..size { + assert_eq!(map.insert(i, 10 * i), None); + assert_eq!(map.len(), i + 1); + } + + assert_eq!(map.first_key_value(), Some((&0, &0))); + assert_eq!(map.last_key_value(), Some((&(size - 1), &(10 * (size - 1))))); + assert_eq!(map.first_entry().unwrap().key(), &0); + assert_eq!(map.last_entry().unwrap().key(), &(size - 1)); + + for i in 0..size { + assert_eq!(map.get(&i).unwrap(), &(i * 10)); + } + + for i in size..size * 2 { + assert_eq!(map.get(&i), None); + } + + for i in 0..size { + assert_eq!(map.insert(i, 100 * i), Some(10 * i)); + assert_eq!(map.len(), size); + } + + for i in 0..size { + assert_eq!(map.get(&i).unwrap(), &(i * 100)); + } + + for i in 0..size / 2 { + assert_eq!(map.remove(&(i * 2)), Some(i * 200)); + assert_eq!(map.len(), size - i - 1); + } + + for i in 0..size / 2 { + assert_eq!(map.get(&(2 * i)), None); + assert_eq!(map.get(&(2 * i + 1)).unwrap(), &(i * 200 + 100)); + } + + for i in 0..size / 2 { + assert_eq!(map.remove(&(2 * i)), None); + assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100)); + assert_eq!(map.len(), size / 2 - i - 1); + } + map.check(); +} + +#[test] +fn test_basic_small() { + let mut map = BTreeMap::new(); + // Empty, root is absent (None): + assert_eq!(map.remove(&1), None); + assert_eq!(map.len(), 0); + assert_eq!(map.get(&1), None); + assert_eq!(map.get_mut(&1), None); + assert_eq!(map.first_key_value(), None); + assert_eq!(map.last_key_value(), None); + assert_eq!(map.keys().count(), 0); + assert_eq!(map.values().count(), 0); + assert_eq!(map.range(..).next(), None); + assert_eq!(map.range(..1).next(), None); + assert_eq!(map.range(1..).next(), None); + assert_eq!(map.range(1..=1).next(), None); + assert_eq!(map.range(1..2).next(), None); + assert_eq!(map.height(), None); + assert_eq!(map.insert(1, 1), None); + assert_eq!(map.height(), Some(0)); + map.check(); + + // 1 key-value pair: + assert_eq!(map.len(), 1); + assert_eq!(map.get(&1), Some(&1)); + assert_eq!(map.get_mut(&1), Some(&mut 1)); + assert_eq!(map.first_key_value(), Some((&1, &1))); + assert_eq!(map.last_key_value(), Some((&1, &1))); + assert_eq!(map.keys().collect::>(), vec![&1]); + assert_eq!(map.values().collect::>(), vec![&1]); + assert_eq!(map.insert(1, 2), Some(1)); + assert_eq!(map.len(), 1); + assert_eq!(map.get(&1), Some(&2)); + assert_eq!(map.get_mut(&1), Some(&mut 2)); + assert_eq!(map.first_key_value(), Some((&1, &2))); + assert_eq!(map.last_key_value(), Some((&1, &2))); + assert_eq!(map.keys().collect::>(), vec![&1]); + assert_eq!(map.values().collect::>(), vec![&2]); + assert_eq!(map.insert(2, 4), None); + assert_eq!(map.height(), Some(0)); + map.check(); + + // 2 key-value pairs: + assert_eq!(map.len(), 2); + assert_eq!(map.get(&2), Some(&4)); + assert_eq!(map.get_mut(&2), Some(&mut 4)); + assert_eq!(map.first_key_value(), Some((&1, &2))); + assert_eq!(map.last_key_value(), Some((&2, &4))); + assert_eq!(map.keys().collect::>(), vec![&1, &2]); + assert_eq!(map.values().collect::>(), vec![&2, &4]); + assert_eq!(map.remove(&1), Some(2)); + assert_eq!(map.height(), Some(0)); + map.check(); + + // 1 key-value pair: + assert_eq!(map.len(), 1); + assert_eq!(map.get(&1), None); + assert_eq!(map.get_mut(&1), None); + assert_eq!(map.get(&2), Some(&4)); + assert_eq!(map.get_mut(&2), Some(&mut 4)); + assert_eq!(map.first_key_value(), Some((&2, &4))); + assert_eq!(map.last_key_value(), Some((&2, &4))); + assert_eq!(map.keys().collect::>(), vec![&2]); + assert_eq!(map.values().collect::>(), vec![&4]); + assert_eq!(map.remove(&2), Some(4)); + assert_eq!(map.height(), Some(0)); + map.check(); + + // Empty but root is owned (Some(...)): + assert_eq!(map.len(), 0); + assert_eq!(map.get(&1), None); + assert_eq!(map.get_mut(&1), None); + assert_eq!(map.first_key_value(), None); + assert_eq!(map.last_key_value(), None); + assert_eq!(map.keys().count(), 0); + assert_eq!(map.values().count(), 0); + assert_eq!(map.range(..).next(), None); + assert_eq!(map.range(..1).next(), None); + assert_eq!(map.range(1..).next(), None); + assert_eq!(map.range(1..=1).next(), None); + assert_eq!(map.range(1..2).next(), None); + assert_eq!(map.remove(&1), None); + assert_eq!(map.height(), Some(0)); + map.check(); +} + +#[test] +fn test_iter() { + // Miri is too slow + let size = if cfg!(miri) { 200 } else { 10000 }; + let mut map = BTreeMap::from_iter((0..size).map(|i| (i, i))); + + fn test(size: usize, mut iter: T) + where + T: Iterator, + { + for i in 0..size { + assert_eq!(iter.size_hint(), (size - i, Some(size - i))); + assert_eq!(iter.next().unwrap(), (i, i)); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + } + test(size, map.iter().map(|(&k, &v)| (k, v))); + test(size, map.iter_mut().map(|(&k, &mut v)| (k, v))); + test(size, map.into_iter()); +} + +#[test] +fn test_iter_rev() { + // Miri is too slow + let size = if cfg!(miri) { 200 } else { 10000 }; + let mut map = BTreeMap::from_iter((0..size).map(|i| (i, i))); + + fn test(size: usize, mut iter: T) + where + T: Iterator, + { + for i in 0..size { + assert_eq!(iter.size_hint(), (size - i, Some(size - i))); + assert_eq!(iter.next().unwrap(), (size - i - 1, size - i - 1)); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + } + test(size, map.iter().rev().map(|(&k, &v)| (k, v))); + test(size, map.iter_mut().rev().map(|(&k, &mut v)| (k, v))); + test(size, map.into_iter().rev()); +} + +// Specifically tests iter_mut's ability to mutate the value of pairs in-line. +fn do_test_iter_mut_mutation(size: usize) +where + T: Copy + Debug + Ord + TryFrom, + >::Error: Debug, +{ + let zero = T::try_from(0).unwrap(); + let mut map = BTreeMap::from_iter((0..size).map(|i| (T::try_from(i).unwrap(), zero))); + + // Forward and backward iteration sees enough pairs (also tested elsewhere) + assert_eq!(map.iter_mut().count(), size); + assert_eq!(map.iter_mut().rev().count(), size); + + // Iterate forwards, trying to mutate to unique values + for (i, (k, v)) in map.iter_mut().enumerate() { + assert_eq!(*k, T::try_from(i).unwrap()); + assert_eq!(*v, zero); + *v = T::try_from(i + 1).unwrap(); + } + + // Iterate backwards, checking that mutations succeeded and trying to mutate again + for (i, (k, v)) in map.iter_mut().rev().enumerate() { + assert_eq!(*k, T::try_from(size - i - 1).unwrap()); + assert_eq!(*v, T::try_from(size - i).unwrap()); + *v = T::try_from(2 * size - i).unwrap(); + } + + // Check that backward mutations succeeded + for (i, (k, v)) in map.iter_mut().enumerate() { + assert_eq!(*k, T::try_from(i).unwrap()); + assert_eq!(*v, T::try_from(size + i + 1).unwrap()); + } + map.check(); +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(align(32))] +struct Align32(usize); + +impl TryFrom for Align32 { + type Error = (); + + fn try_from(s: usize) -> Result { + Ok(Align32(s)) + } +} + +#[test] +fn test_iter_mut_mutation() { + // Check many alignments and trees with roots at various heights. + do_test_iter_mut_mutation::(0); + do_test_iter_mut_mutation::(1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_2); + do_test_iter_mut_mutation::(1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_2); + do_test_iter_mut_mutation::(1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_2); + do_test_iter_mut_mutation::(1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_2); + do_test_iter_mut_mutation::(1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_2); + do_test_iter_mut_mutation::(1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_2); +} + +#[test] +fn test_values_mut() { + let mut a = BTreeMap::from_iter((0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i))); + test_all_refs(&mut 13, a.values_mut()); + a.check(); +} + +#[test] +fn test_values_mut_mutation() { + let mut a = BTreeMap::new(); + a.insert(1, String::from("hello")); + a.insert(2, String::from("goodbye")); + + for value in a.values_mut() { + value.push_str("!"); + } + + let values = Vec::from_iter(a.values().cloned()); + assert_eq!(values, [String::from("hello!"), String::from("goodbye!")]); + a.check(); +} + +#[test] +fn test_iter_entering_root_twice() { + let mut map = BTreeMap::from([(0, 0), (1, 1)]); + let mut it = map.iter_mut(); + let front = it.next().unwrap(); + let back = it.next_back().unwrap(); + assert_eq!(front, (&0, &mut 0)); + assert_eq!(back, (&1, &mut 1)); + *front.1 = 24; + *back.1 = 42; + assert_eq!(front, (&0, &mut 24)); + assert_eq!(back, (&1, &mut 42)); + assert_eq!(it.next(), None); + assert_eq!(it.next_back(), None); + map.check(); +} + +#[test] +fn test_iter_descending_to_same_node_twice() { + let mut map = BTreeMap::from_iter((0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i))); + let mut it = map.iter_mut(); + // Descend into first child. + let front = it.next().unwrap(); + // Descend into first child again, after running through second child. + while it.next_back().is_some() {} + // Check immutable access. + assert_eq!(front, (&0, &mut 0)); + // Perform mutable access. + *front.1 = 42; + map.check(); +} + +#[test] +fn test_iter_mixed() { + // Miri is too slow + let size = if cfg!(miri) { 200 } else { 10000 }; + + let mut map = BTreeMap::from_iter((0..size).map(|i| (i, i))); + + fn test(size: usize, mut iter: T) + where + T: Iterator + DoubleEndedIterator, + { + for i in 0..size / 4 { + assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2))); + assert_eq!(iter.next().unwrap(), (i, i)); + assert_eq!(iter.next_back().unwrap(), (size - i - 1, size - i - 1)); + } + for i in size / 4..size * 3 / 4 { + assert_eq!(iter.size_hint(), (size * 3 / 4 - i, Some(size * 3 / 4 - i))); + assert_eq!(iter.next().unwrap(), (i, i)); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + } + test(size, map.iter().map(|(&k, &v)| (k, v))); + test(size, map.iter_mut().map(|(&k, &mut v)| (k, v))); + test(size, map.into_iter()); +} + +#[test] +fn test_iter_min_max() { + let mut a = BTreeMap::new(); + assert_eq!(a.iter().min(), None); + assert_eq!(a.iter().max(), None); + assert_eq!(a.iter_mut().min(), None); + assert_eq!(a.iter_mut().max(), None); + assert_eq!(a.range(..).min(), None); + assert_eq!(a.range(..).max(), None); + assert_eq!(a.range_mut(..).min(), None); + assert_eq!(a.range_mut(..).max(), None); + assert_eq!(a.keys().min(), None); + assert_eq!(a.keys().max(), None); + assert_eq!(a.values().min(), None); + assert_eq!(a.values().max(), None); + assert_eq!(a.values_mut().min(), None); + assert_eq!(a.values_mut().max(), None); + a.insert(1, 42); + a.insert(2, 24); + assert_eq!(a.iter().min(), Some((&1, &42))); + assert_eq!(a.iter().max(), Some((&2, &24))); + assert_eq!(a.iter_mut().min(), Some((&1, &mut 42))); + assert_eq!(a.iter_mut().max(), Some((&2, &mut 24))); + assert_eq!(a.range(..).min(), Some((&1, &42))); + assert_eq!(a.range(..).max(), Some((&2, &24))); + assert_eq!(a.range_mut(..).min(), Some((&1, &mut 42))); + assert_eq!(a.range_mut(..).max(), Some((&2, &mut 24))); + assert_eq!(a.keys().min(), Some(&1)); + assert_eq!(a.keys().max(), Some(&2)); + assert_eq!(a.values().min(), Some(&24)); + assert_eq!(a.values().max(), Some(&42)); + assert_eq!(a.values_mut().min(), Some(&mut 24)); + assert_eq!(a.values_mut().max(), Some(&mut 42)); + a.check(); +} + +fn range_keys(map: &BTreeMap, range: impl RangeBounds) -> Vec { + Vec::from_iter(map.range(range).map(|(&k, &v)| { + assert_eq!(k, v); + k + })) +} + +#[test] +fn test_range_small() { + let size = 4; + + let all = Vec::from_iter(1..=size); + let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]); + let map = BTreeMap::from_iter(all.iter().copied().map(|i| (i, i))); + + assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all); + assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all); + assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Included(0), Included(size))), all); + assert_eq!(range_keys(&map, (Included(0), Unbounded)), all); + assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Included(1), Included(size))), all); + assert_eq!(range_keys(&map, (Included(1), Unbounded)), all); + assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all); + assert_eq!(range_keys(&map, (Unbounded, Included(size))), all); + assert_eq!(range_keys(&map, ..), all); + + assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]); + assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]); + assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]); + assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first); + assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first); + assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first); + assert_eq!(range_keys(&map, (Included(0), Included(1))), first); + assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first); + assert_eq!(range_keys(&map, (Included(1), Included(1))), first); + assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first); + assert_eq!(range_keys(&map, (Unbounded, Included(1))), first); + assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last); + assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last); + assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last); + assert_eq!(range_keys(&map, (Included(size), Included(size))), last); + assert_eq!(range_keys(&map, (Included(size), Unbounded)), last); + assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]); + assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]); + + assert_eq!(range_keys(&map, ..3), vec![1, 2]); + assert_eq!(range_keys(&map, 3..), vec![3, 4]); + assert_eq!(range_keys(&map, 2..=3), vec![2, 3]); +} + +#[test] +fn test_range_height_1() { + // Tests tree with a root and 2 leaves. We test around the middle of the + // keys because one of those is the single key in the root node. + let map = BTreeMap::from_iter((0..MIN_INSERTS_HEIGHT_1 as i32).map(|i| (i, i))); + let middle = MIN_INSERTS_HEIGHT_1 as i32 / 2; + for root in middle - 2..=middle + 2 { + assert_eq!(range_keys(&map, (Excluded(root), Excluded(root + 1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(root), Included(root + 1))), vec![root + 1]); + assert_eq!(range_keys(&map, (Included(root), Excluded(root + 1))), vec![root]); + assert_eq!(range_keys(&map, (Included(root), Included(root + 1))), vec![root, root + 1]); + + assert_eq!(range_keys(&map, (Excluded(root - 1), Excluded(root))), vec![]); + assert_eq!(range_keys(&map, (Included(root - 1), Excluded(root))), vec![root - 1]); + assert_eq!(range_keys(&map, (Excluded(root - 1), Included(root))), vec![root]); + assert_eq!(range_keys(&map, (Included(root - 1), Included(root))), vec![root - 1, root]); + } +} + +#[test] +fn test_range_large() { + let size = 200; + + let all = Vec::from_iter(1..=size); + let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]); + let map = BTreeMap::from_iter(all.iter().copied().map(|i| (i, i))); + + assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all); + assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all); + assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Included(0), Included(size))), all); + assert_eq!(range_keys(&map, (Included(0), Unbounded)), all); + assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Included(1), Included(size))), all); + assert_eq!(range_keys(&map, (Included(1), Unbounded)), all); + assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all); + assert_eq!(range_keys(&map, (Unbounded, Included(size))), all); + assert_eq!(range_keys(&map, ..), all); + + assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]); + assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]); + assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]); + assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first); + assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first); + assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first); + assert_eq!(range_keys(&map, (Included(0), Included(1))), first); + assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first); + assert_eq!(range_keys(&map, (Included(1), Included(1))), first); + assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first); + assert_eq!(range_keys(&map, (Unbounded, Included(1))), first); + assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last); + assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last); + assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last); + assert_eq!(range_keys(&map, (Included(size), Included(size))), last); + assert_eq!(range_keys(&map, (Included(size), Unbounded)), last); + assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]); + assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]); + + fn check<'a, L, R>(lhs: L, rhs: R) + where + L: IntoIterator, + R: IntoIterator, + { + assert_eq!(Vec::from_iter(lhs), Vec::from_iter(rhs)); + } + + check(map.range(..=100), map.range(..101)); + check(map.range(5..=8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]); + check(map.range(-1..=2), vec![(&1, &1), (&2, &2)]); +} + +#[test] +fn test_range_inclusive_max_value() { + let max = usize::MAX; + let map = BTreeMap::from([(max, 0)]); + assert_eq!(Vec::from_iter(map.range(max..=max)), &[(&max, &0)]); +} + +#[test] +fn test_range_equal_empty_cases() { + let map = BTreeMap::from_iter((0..5).map(|i| (i, i))); + assert_eq!(map.range((Included(2), Excluded(2))).next(), None); + assert_eq!(map.range((Excluded(2), Included(2))).next(), None); +} + +#[test] +#[should_panic] +fn test_range_equal_excluded() { + let map = BTreeMap::from_iter((0..5).map(|i| (i, i))); + let _ = map.range((Excluded(2), Excluded(2))); +} + +#[test] +#[should_panic] +fn test_range_backwards_1() { + let map = BTreeMap::from_iter((0..5).map(|i| (i, i))); + let _ = map.range((Included(3), Included(2))); +} + +#[test] +#[should_panic] +fn test_range_backwards_2() { + let map = BTreeMap::from_iter((0..5).map(|i| (i, i))); + let _ = map.range((Included(3), Excluded(2))); +} + +#[test] +#[should_panic] +fn test_range_backwards_3() { + let map = BTreeMap::from_iter((0..5).map(|i| (i, i))); + let _ = map.range((Excluded(3), Included(2))); +} + +#[test] +#[should_panic] +fn test_range_backwards_4() { + let map = BTreeMap::from_iter((0..5).map(|i| (i, i))); + let _ = map.range((Excluded(3), Excluded(2))); +} + +#[test] +fn test_range_finding_ill_order_in_map() { + let mut map = BTreeMap::new(); + map.insert(Cyclic3::B, ()); + // Lacking static_assert, call `range` conditionally, to emphasise that + // we cause a different panic than `test_range_backwards_1` does. + // A more refined `should_panic` would be welcome. + if Cyclic3::C < Cyclic3::A { + let _ = map.range(Cyclic3::C..=Cyclic3::A); + } +} + +#[test] +fn test_range_finding_ill_order_in_range_ord() { + // Has proper order the first time asked, then flips around. + struct EvilTwin(i32); + + impl PartialOrd for EvilTwin { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } + } + + static COMPARES: AtomicUsize = AtomicUsize::new(0); + impl Ord for EvilTwin { + fn cmp(&self, other: &Self) -> Ordering { + let ord = self.0.cmp(&other.0); + if COMPARES.fetch_add(1, SeqCst) > 0 { ord.reverse() } else { ord } + } + } + + impl PartialEq for EvilTwin { + fn eq(&self, other: &Self) -> bool { + self.0.eq(&other.0) + } + } + + impl Eq for EvilTwin {} + + #[derive(PartialEq, Eq, PartialOrd, Ord)] + struct CompositeKey(i32, EvilTwin); + + impl Borrow for CompositeKey { + fn borrow(&self) -> &EvilTwin { + &self.1 + } + } + + let map = BTreeMap::from_iter((0..12).map(|i| (CompositeKey(i, EvilTwin(i)), ()))); + let _ = map.range(EvilTwin(5)..=EvilTwin(7)); +} + +#[test] +fn test_range_1000() { + // Miri is too slow + let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 as u32 } else { 1000 }; + let map = BTreeMap::from_iter((0..size).map(|i| (i, i))); + + fn test(map: &BTreeMap, size: u32, min: Bound<&u32>, max: Bound<&u32>) { + let mut kvs = map.range((min, max)).map(|(&k, &v)| (k, v)); + let mut pairs = (0..size).map(|i| (i, i)); + + for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { + assert_eq!(kv, pair); + } + assert_eq!(kvs.next(), None); + assert_eq!(pairs.next(), None); + } + test(&map, size, Included(&0), Excluded(&size)); + test(&map, size, Unbounded, Excluded(&size)); + test(&map, size, Included(&0), Included(&(size - 1))); + test(&map, size, Unbounded, Included(&(size - 1))); + test(&map, size, Included(&0), Unbounded); + test(&map, size, Unbounded, Unbounded); +} + +#[test] +fn test_range_borrowed_key() { + let mut map = BTreeMap::new(); + map.insert("aardvark".to_string(), 1); + map.insert("baboon".to_string(), 2); + map.insert("coyote".to_string(), 3); + map.insert("dingo".to_string(), 4); + // NOTE: would like to use simply "b".."d" here... + let mut iter = map.range::((Included("b"), Excluded("d"))); + assert_eq!(iter.next(), Some((&"baboon".to_string(), &2))); + assert_eq!(iter.next(), Some((&"coyote".to_string(), &3))); + assert_eq!(iter.next(), None); +} + +#[test] +fn test_range() { + let size = 200; + // Miri is too slow + let step = if cfg!(miri) { 66 } else { 1 }; + let map = BTreeMap::from_iter((0..size).map(|i| (i, i))); + + for i in (0..size).step_by(step) { + for j in (i..size).step_by(step) { + let mut kvs = map.range((Included(&i), Included(&j))).map(|(&k, &v)| (k, v)); + let mut pairs = (i..=j).map(|i| (i, i)); + + for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { + assert_eq!(kv, pair); + } + assert_eq!(kvs.next(), None); + assert_eq!(pairs.next(), None); + } + } +} + +#[test] +fn test_range_mut() { + let size = 200; + // Miri is too slow + let step = if cfg!(miri) { 66 } else { 1 }; + let mut map = BTreeMap::from_iter((0..size).map(|i| (i, i))); + + for i in (0..size).step_by(step) { + for j in (i..size).step_by(step) { + let mut kvs = map.range_mut((Included(&i), Included(&j))).map(|(&k, &mut v)| (k, v)); + let mut pairs = (i..=j).map(|i| (i, i)); + + for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { + assert_eq!(kv, pair); + } + assert_eq!(kvs.next(), None); + assert_eq!(pairs.next(), None); + } + } + map.check(); +} + +#[should_panic(expected = "range start is greater than range end in BTreeMap")] +#[test] +fn test_range_panic_1() { + let mut map = BTreeMap::new(); + map.insert(3, "a"); + map.insert(5, "b"); + map.insert(8, "c"); + + let _invalid_range = map.range((Included(&8), Included(&3))); +} + +#[should_panic(expected = "range start and end are equal and excluded in BTreeMap")] +#[test] +fn test_range_panic_2() { + let mut map = BTreeMap::new(); + map.insert(3, "a"); + map.insert(5, "b"); + map.insert(8, "c"); + + let _invalid_range = map.range((Excluded(&5), Excluded(&5))); +} + +#[should_panic(expected = "range start and end are equal and excluded in BTreeMap")] +#[test] +fn test_range_panic_3() { + let mut map: BTreeMap = BTreeMap::new(); + map.insert(3, ()); + map.insert(5, ()); + map.insert(8, ()); + + let _invalid_range = map.range((Excluded(&5), Excluded(&5))); +} + +#[test] +fn test_retain() { + let mut map = BTreeMap::from_iter((0..100).map(|x| (x, x * 10))); + + map.retain(|&k, _| k % 2 == 0); + assert_eq!(map.len(), 50); + assert_eq!(map[&2], 20); + assert_eq!(map[&4], 40); + assert_eq!(map[&6], 60); +} + +mod test_extract_if { + use super::*; + + #[test] + fn empty() { + let mut map: BTreeMap = BTreeMap::new(); + map.extract_if(|_, _| unreachable!("there's nothing to decide on")).for_each(drop); + assert_eq!(map.height(), None); + map.check(); + } + + // Explicitly consumes the iterator, where most test cases drop it instantly. + #[test] + fn consumed_keeping_all() { + let pairs = (0..3).map(|i| (i, i)); + let mut map = BTreeMap::from_iter(pairs); + assert!(map.extract_if(|_, _| false).eq(iter::empty())); + map.check(); + } + + // Explicitly consumes the iterator, where most test cases drop it instantly. + #[test] + fn consumed_removing_all() { + let pairs = (0..3).map(|i| (i, i)); + let mut map = BTreeMap::from_iter(pairs.clone()); + assert!(map.extract_if(|_, _| true).eq(pairs)); + assert!(map.is_empty()); + map.check(); + } + + // Explicitly consumes the iterator and modifies values through it. + #[test] + fn mutating_and_keeping() { + let pairs = (0..3).map(|i| (i, i)); + let mut map = BTreeMap::from_iter(pairs); + assert!( + map.extract_if(|_, v| { + *v += 6; + false + }) + .eq(iter::empty()) + ); + assert!(map.keys().copied().eq(0..3)); + assert!(map.values().copied().eq(6..9)); + map.check(); + } + + // Explicitly consumes the iterator and modifies values through it. + #[test] + fn mutating_and_removing() { + let pairs = (0..3).map(|i| (i, i)); + let mut map = BTreeMap::from_iter(pairs); + assert!( + map.extract_if(|_, v| { + *v += 6; + true + }) + .eq((0..3).map(|i| (i, i + 6))) + ); + assert!(map.is_empty()); + map.check(); + } + + #[test] + fn underfull_keeping_all() { + let pairs = (0..3).map(|i| (i, i)); + let mut map = BTreeMap::from_iter(pairs); + map.extract_if(|_, _| false).for_each(drop); + assert!(map.keys().copied().eq(0..3)); + map.check(); + } + + #[test] + fn underfull_removing_one() { + let pairs = (0..3).map(|i| (i, i)); + for doomed in 0..3 { + let mut map = BTreeMap::from_iter(pairs.clone()); + map.extract_if(|i, _| *i == doomed).for_each(drop); + assert_eq!(map.len(), 2); + map.check(); + } + } + + #[test] + fn underfull_keeping_one() { + let pairs = (0..3).map(|i| (i, i)); + for sacred in 0..3 { + let mut map = BTreeMap::from_iter(pairs.clone()); + map.extract_if(|i, _| *i != sacred).for_each(drop); + assert!(map.keys().copied().eq(sacred..=sacred)); + map.check(); + } + } + + #[test] + fn underfull_removing_all() { + let pairs = (0..3).map(|i| (i, i)); + let mut map = BTreeMap::from_iter(pairs); + map.extract_if(|_, _| true).for_each(drop); + assert!(map.is_empty()); + map.check(); + } + + #[test] + fn height_0_keeping_all() { + let pairs = (0..node::CAPACITY).map(|i| (i, i)); + let mut map = BTreeMap::from_iter(pairs); + map.extract_if(|_, _| false).for_each(drop); + assert!(map.keys().copied().eq(0..node::CAPACITY)); + map.check(); + } + + #[test] + fn height_0_removing_one() { + let pairs = (0..node::CAPACITY).map(|i| (i, i)); + for doomed in 0..node::CAPACITY { + let mut map = BTreeMap::from_iter(pairs.clone()); + map.extract_if(|i, _| *i == doomed).for_each(drop); + assert_eq!(map.len(), node::CAPACITY - 1); + map.check(); + } + } + + #[test] + fn height_0_keeping_one() { + let pairs = (0..node::CAPACITY).map(|i| (i, i)); + for sacred in 0..node::CAPACITY { + let mut map = BTreeMap::from_iter(pairs.clone()); + map.extract_if(|i, _| *i != sacred).for_each(drop); + assert!(map.keys().copied().eq(sacred..=sacred)); + map.check(); + } + } + + #[test] + fn height_0_removing_all() { + let pairs = (0..node::CAPACITY).map(|i| (i, i)); + let mut map = BTreeMap::from_iter(pairs); + map.extract_if(|_, _| true).for_each(drop); + assert!(map.is_empty()); + map.check(); + } + + #[test] + fn height_0_keeping_half() { + let mut map = BTreeMap::from_iter((0..16).map(|i| (i, i))); + assert_eq!(map.extract_if(|i, _| *i % 2 == 0).count(), 8); + assert_eq!(map.len(), 8); + map.check(); + } + + #[test] + fn height_1_removing_all() { + let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)); + let mut map = BTreeMap::from_iter(pairs); + map.extract_if(|_, _| true).for_each(drop); + assert!(map.is_empty()); + map.check(); + } + + #[test] + fn height_1_removing_one() { + let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)); + for doomed in 0..MIN_INSERTS_HEIGHT_1 { + let mut map = BTreeMap::from_iter(pairs.clone()); + map.extract_if(|i, _| *i == doomed).for_each(drop); + assert_eq!(map.len(), MIN_INSERTS_HEIGHT_1 - 1); + map.check(); + } + } + + #[test] + fn height_1_keeping_one() { + let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)); + for sacred in 0..MIN_INSERTS_HEIGHT_1 { + let mut map = BTreeMap::from_iter(pairs.clone()); + map.extract_if(|i, _| *i != sacred).for_each(drop); + assert!(map.keys().copied().eq(sacred..=sacred)); + map.check(); + } + } + + #[test] + fn height_2_removing_one() { + let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); + for doomed in (0..MIN_INSERTS_HEIGHT_2).step_by(12) { + let mut map = BTreeMap::from_iter(pairs.clone()); + map.extract_if(|i, _| *i == doomed).for_each(drop); + assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1); + map.check(); + } + } + + #[test] + fn height_2_keeping_one() { + let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); + for sacred in (0..MIN_INSERTS_HEIGHT_2).step_by(12) { + let mut map = BTreeMap::from_iter(pairs.clone()); + map.extract_if(|i, _| *i != sacred).for_each(drop); + assert!(map.keys().copied().eq(sacred..=sacred)); + map.check(); + } + } + + #[test] + fn height_2_removing_all() { + let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); + let mut map = BTreeMap::from_iter(pairs); + map.extract_if(|_, _| true).for_each(drop); + assert!(map.is_empty()); + map.check(); + } + + #[test] + #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] + fn drop_panic_leak() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut map = BTreeMap::new(); + map.insert(a.spawn(Panic::Never), ()); + map.insert(b.spawn(Panic::InDrop), ()); + map.insert(c.spawn(Panic::Never), ()); + + catch_unwind(move || map.extract_if(|dummy, _| dummy.query(true)).for_each(drop)) + .unwrap_err(); + + assert_eq!(a.queried(), 1); + assert_eq!(b.queried(), 1); + assert_eq!(c.queried(), 0); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); + assert_eq!(c.dropped(), 1); + } + + #[test] + #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] + fn pred_panic_leak() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut map = BTreeMap::new(); + map.insert(a.spawn(Panic::Never), ()); + map.insert(b.spawn(Panic::InQuery), ()); + map.insert(c.spawn(Panic::InQuery), ()); + + catch_unwind(AssertUnwindSafe(|| { + map.extract_if(|dummy, _| dummy.query(true)).for_each(drop) + })) + .unwrap_err(); + + assert_eq!(a.queried(), 1); + assert_eq!(b.queried(), 1); + assert_eq!(c.queried(), 0); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 0); + assert_eq!(map.len(), 2); + assert_eq!(map.first_entry().unwrap().key().id(), 1); + assert_eq!(map.last_entry().unwrap().key().id(), 2); + map.check(); + } + + // Same as above, but attempt to use the iterator again after the panic in the predicate + #[test] + #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] + fn pred_panic_reuse() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut map = BTreeMap::new(); + map.insert(a.spawn(Panic::Never), ()); + map.insert(b.spawn(Panic::InQuery), ()); + map.insert(c.spawn(Panic::InQuery), ()); + + { + let mut it = map.extract_if(|dummy, _| dummy.query(true)); + catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err(); + // Iterator behavior after a panic is explicitly unspecified, + // so this is just the current implementation: + let result = catch_unwind(AssertUnwindSafe(|| it.next())); + assert!(matches!(result, Ok(None))); + } + + assert_eq!(a.queried(), 1); + assert_eq!(b.queried(), 1); + assert_eq!(c.queried(), 0); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 0); + assert_eq!(map.len(), 2); + assert_eq!(map.first_entry().unwrap().key().id(), 1); + assert_eq!(map.last_entry().unwrap().key().id(), 2); + map.check(); + } +} + +#[test] +fn test_borrow() { + // make sure these compile -- using the Borrow trait + { + let mut map = BTreeMap::new(); + map.insert("0".to_string(), 1); + assert_eq!(map["0"], 1); + } + + { + let mut map = BTreeMap::new(); + map.insert(Box::new(0), 1); + assert_eq!(map[&0], 1); + } + + { + let mut map = BTreeMap::new(); + map.insert(Box::new([0, 1]) as Box<[i32]>, 1); + assert_eq!(map[&[0, 1][..]], 1); + } + + { + let mut map = BTreeMap::new(); + map.insert(Rc::new(0), 1); + assert_eq!(map[&0], 1); + } + + #[allow(dead_code)] + fn get(v: &BTreeMap, ()>, t: &T) { + let _ = v.get(t); + } + + #[allow(dead_code)] + fn get_mut(v: &mut BTreeMap, ()>, t: &T) { + let _ = v.get_mut(t); + } + + #[allow(dead_code)] + fn get_key_value(v: &BTreeMap, ()>, t: &T) { + let _ = v.get_key_value(t); + } + + #[allow(dead_code)] + fn contains_key(v: &BTreeMap, ()>, t: &T) { + let _ = v.contains_key(t); + } + + #[allow(dead_code)] + fn range(v: &BTreeMap, ()>, t: T) { + let _ = v.range(t..); + } + + #[allow(dead_code)] + fn range_mut(v: &mut BTreeMap, ()>, t: T) { + let _ = v.range_mut(t..); + } + + #[allow(dead_code)] + fn remove(v: &mut BTreeMap, ()>, t: &T) { + v.remove(t); + } + + #[allow(dead_code)] + fn remove_entry(v: &mut BTreeMap, ()>, t: &T) { + v.remove_entry(t); + } + + #[allow(dead_code)] + fn split_off(v: &mut BTreeMap, ()>, t: &T) { + v.split_off(t); + } +} + +#[test] +fn test_entry() { + let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; + + let mut map = BTreeMap::from(xs); + + // Existing key (insert) + match map.entry(1) { + Vacant(_) => unreachable!(), + Occupied(mut view) => { + assert_eq!(view.get(), &10); + assert_eq!(view.insert(100), 10); + } + } + assert_eq!(map.get(&1).unwrap(), &100); + assert_eq!(map.len(), 6); + + // Existing key (update) + match map.entry(2) { + Vacant(_) => unreachable!(), + Occupied(mut view) => { + let v = view.get_mut(); + *v *= 10; + } + } + assert_eq!(map.get(&2).unwrap(), &200); + assert_eq!(map.len(), 6); + map.check(); + + // Existing key (take) + match map.entry(3) { + Vacant(_) => unreachable!(), + Occupied(view) => { + assert_eq!(view.remove(), 30); + } + } + assert_eq!(map.get(&3), None); + assert_eq!(map.len(), 5); + map.check(); + + // Inexistent key (insert) + match map.entry(10) { + Occupied(_) => unreachable!(), + Vacant(view) => { + assert_eq!(*view.insert(1000), 1000); + } + } + assert_eq!(map.get(&10).unwrap(), &1000); + assert_eq!(map.len(), 6); + map.check(); +} + +#[test] +fn test_extend_ref() { + let mut a = BTreeMap::new(); + a.insert(1, "one"); + let mut b = BTreeMap::new(); + b.insert(2, "two"); + b.insert(3, "three"); + + a.extend(&b); + + assert_eq!(a.len(), 3); + assert_eq!(a[&1], "one"); + assert_eq!(a[&2], "two"); + assert_eq!(a[&3], "three"); + a.check(); +} + +#[test] +fn test_zst() { + let mut m = BTreeMap::new(); + assert_eq!(m.len(), 0); + + assert_eq!(m.insert((), ()), None); + assert_eq!(m.len(), 1); + + assert_eq!(m.insert((), ()), Some(())); + assert_eq!(m.len(), 1); + assert_eq!(m.iter().count(), 1); + + m.clear(); + assert_eq!(m.len(), 0); + + for _ in 0..100 { + m.insert((), ()); + } + + assert_eq!(m.len(), 1); + assert_eq!(m.iter().count(), 1); + m.check(); +} + +// This test's only purpose is to ensure that zero-sized keys with nonsensical orderings +// do not cause segfaults when used with zero-sized values. All other map behavior is +// undefined. +#[test] +fn test_bad_zst() { + #[derive(Clone, Copy, Debug)] + struct Bad; + + impl PartialEq for Bad { + fn eq(&self, _: &Self) -> bool { + false + } + } + + impl Eq for Bad {} + + impl PartialOrd for Bad { + fn partial_cmp(&self, _: &Self) -> Option { + Some(Ordering::Less) + } + } + + impl Ord for Bad { + fn cmp(&self, _: &Self) -> Ordering { + Ordering::Less + } + } + + let mut m = BTreeMap::new(); + + for _ in 0..100 { + m.insert(Bad, Bad); + } + m.check(); +} + +#[test] +fn test_clear() { + let mut map = BTreeMap::new(); + for &len in &[MIN_INSERTS_HEIGHT_1, MIN_INSERTS_HEIGHT_2, 0, node::CAPACITY] { + for i in 0..len { + map.insert(i, ()); + } + assert_eq!(map.len(), len); + map.clear(); + map.check(); + assert_eq!(map.height(), None); + } +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_clear_drop_panic_leak() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + + let mut map = BTreeMap::new(); + map.insert(a.spawn(Panic::Never), ()); + map.insert(b.spawn(Panic::InDrop), ()); + map.insert(c.spawn(Panic::Never), ()); + + catch_unwind(AssertUnwindSafe(|| map.clear())).unwrap_err(); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); + assert_eq!(c.dropped(), 1); + assert_eq!(map.len(), 0); + + drop(map); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); + assert_eq!(c.dropped(), 1); +} + +#[test] +fn test_clone() { + let mut map = BTreeMap::new(); + let size = MIN_INSERTS_HEIGHT_1; + assert_eq!(map.len(), 0); + + for i in 0..size { + assert_eq!(map.insert(i, 10 * i), None); + assert_eq!(map.len(), i + 1); + map.check(); + assert_eq!(map, map.clone()); + } + + for i in 0..size { + assert_eq!(map.insert(i, 100 * i), Some(10 * i)); + assert_eq!(map.len(), size); + map.check(); + assert_eq!(map, map.clone()); + } + + for i in 0..size / 2 { + assert_eq!(map.remove(&(i * 2)), Some(i * 200)); + assert_eq!(map.len(), size - i - 1); + map.check(); + assert_eq!(map, map.clone()); + } + + for i in 0..size / 2 { + assert_eq!(map.remove(&(2 * i)), None); + assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100)); + assert_eq!(map.len(), size / 2 - i - 1); + map.check(); + assert_eq!(map, map.clone()); + } + + // Test a tree with 2 semi-full levels and a tree with 3 levels. + map = BTreeMap::from_iter((1..MIN_INSERTS_HEIGHT_2).map(|i| (i, i))); + assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1); + assert_eq!(map, map.clone()); + map.insert(0, 0); + assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2); + assert_eq!(map, map.clone()); + map.check(); +} + +fn test_clone_panic_leak(size: usize) { + for i in 0..size { + let dummies = Vec::from_iter((0..size).map(|id| CrashTestDummy::new(id))); + let map = BTreeMap::from_iter(dummies.iter().map(|dummy| { + let panic = if dummy.id == i { Panic::InClone } else { Panic::Never }; + (dummy.spawn(panic), ()) + })); + + catch_unwind(|| map.clone()).unwrap_err(); + for d in &dummies { + assert_eq!(d.cloned(), if d.id <= i { 1 } else { 0 }, "id={}/{}", d.id, i); + assert_eq!(d.dropped(), if d.id < i { 1 } else { 0 }, "id={}/{}", d.id, i); + } + assert_eq!(map.len(), size); + + drop(map); + for d in &dummies { + assert_eq!(d.cloned(), if d.id <= i { 1 } else { 0 }, "id={}/{}", d.id, i); + assert_eq!(d.dropped(), if d.id < i { 2 } else { 1 }, "id={}/{}", d.id, i); + } + } +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_clone_panic_leak_height_0() { + test_clone_panic_leak(3) +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_clone_panic_leak_height_1() { + test_clone_panic_leak(MIN_INSERTS_HEIGHT_1) +} + +#[test] +fn test_clone_from() { + let mut map1 = BTreeMap::new(); + let max_size = MIN_INSERTS_HEIGHT_1; + + // Range to max_size inclusive, because i is the size of map1 being tested. + for i in 0..=max_size { + let mut map2 = BTreeMap::new(); + for j in 0..i { + let mut map1_copy = map2.clone(); + map1_copy.clone_from(&map1); // small cloned from large + assert_eq!(map1_copy, map1); + let mut map2_copy = map1.clone(); + map2_copy.clone_from(&map2); // large cloned from small + assert_eq!(map2_copy, map2); + map2.insert(100 * j + 1, 2 * j + 1); + } + map2.clone_from(&map1); // same length + map2.check(); + assert_eq!(map2, map1); + map1.insert(i, 10 * i); + map1.check(); + } +} + +#[allow(dead_code)] +fn assert_covariance() { + fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> { + v + } + fn map_val<'new>(v: BTreeMap<(), &'static str>) -> BTreeMap<(), &'new str> { + v + } + + fn iter_key<'a, 'new>(v: Iter<'a, &'static str, ()>) -> Iter<'a, &'new str, ()> { + v + } + fn iter_val<'a, 'new>(v: Iter<'a, (), &'static str>) -> Iter<'a, (), &'new str> { + v + } + + fn into_iter_key<'new>(v: IntoIter<&'static str, ()>) -> IntoIter<&'new str, ()> { + v + } + fn into_iter_val<'new>(v: IntoIter<(), &'static str>) -> IntoIter<(), &'new str> { + v + } + + fn into_keys_key<'new>(v: IntoKeys<&'static str, ()>) -> IntoKeys<&'new str, ()> { + v + } + fn into_keys_val<'new>(v: IntoKeys<(), &'static str>) -> IntoKeys<(), &'new str> { + v + } + + fn into_values_key<'new>(v: IntoValues<&'static str, ()>) -> IntoValues<&'new str, ()> { + v + } + fn into_values_val<'new>(v: IntoValues<(), &'static str>) -> IntoValues<(), &'new str> { + v + } + + fn range_key<'a, 'new>(v: Range<'a, &'static str, ()>) -> Range<'a, &'new str, ()> { + v + } + fn range_val<'a, 'new>(v: Range<'a, (), &'static str>) -> Range<'a, (), &'new str> { + v + } + + fn keys_key<'a, 'new>(v: Keys<'a, &'static str, ()>) -> Keys<'a, &'new str, ()> { + v + } + fn keys_val<'a, 'new>(v: Keys<'a, (), &'static str>) -> Keys<'a, (), &'new str> { + v + } + + fn values_key<'a, 'new>(v: Values<'a, &'static str, ()>) -> Values<'a, &'new str, ()> { + v + } + fn values_val<'a, 'new>(v: Values<'a, (), &'static str>) -> Values<'a, (), &'new str> { + v + } +} + +#[allow(dead_code)] +fn assert_sync() { + fn map(v: &BTreeMap) -> impl Sync + '_ { + v + } + + fn into_iter(v: BTreeMap) -> impl Sync { + v.into_iter() + } + + fn into_keys(v: BTreeMap) -> impl Sync { + v.into_keys() + } + + fn into_values(v: BTreeMap) -> impl Sync { + v.into_values() + } + + fn extract_if(v: &mut BTreeMap) -> impl Sync + '_ { + v.extract_if(|_, _| false) + } + + fn iter(v: &BTreeMap) -> impl Sync + '_ { + v.iter() + } + + fn iter_mut(v: &mut BTreeMap) -> impl Sync + '_ { + v.iter_mut() + } + + fn keys(v: &BTreeMap) -> impl Sync + '_ { + v.keys() + } + + fn values(v: &BTreeMap) -> impl Sync + '_ { + v.values() + } + + fn values_mut(v: &mut BTreeMap) -> impl Sync + '_ { + v.values_mut() + } + + fn range(v: &BTreeMap) -> impl Sync + '_ { + v.range(..) + } + + fn range_mut(v: &mut BTreeMap) -> impl Sync + '_ { + v.range_mut(..) + } + + fn entry(v: &mut BTreeMap) -> impl Sync + '_ { + v.entry(Default::default()) + } + + fn occupied_entry(v: &mut BTreeMap) -> impl Sync + '_ { + match v.entry(Default::default()) { + Occupied(entry) => entry, + _ => unreachable!(), + } + } + + fn vacant_entry(v: &mut BTreeMap) -> impl Sync + '_ { + match v.entry(Default::default()) { + Vacant(entry) => entry, + _ => unreachable!(), + } + } +} + +#[allow(dead_code)] +fn assert_send() { + fn map(v: BTreeMap) -> impl Send { + v + } + + fn into_iter(v: BTreeMap) -> impl Send { + v.into_iter() + } + + fn into_keys(v: BTreeMap) -> impl Send { + v.into_keys() + } + + fn into_values(v: BTreeMap) -> impl Send { + v.into_values() + } + + fn extract_if(v: &mut BTreeMap) -> impl Send + '_ { + v.extract_if(|_, _| false) + } + + fn iter(v: &BTreeMap) -> impl Send + '_ { + v.iter() + } + + fn iter_mut(v: &mut BTreeMap) -> impl Send + '_ { + v.iter_mut() + } + + fn keys(v: &BTreeMap) -> impl Send + '_ { + v.keys() + } + + fn values(v: &BTreeMap) -> impl Send + '_ { + v.values() + } + + fn values_mut(v: &mut BTreeMap) -> impl Send + '_ { + v.values_mut() + } + + fn range(v: &BTreeMap) -> impl Send + '_ { + v.range(..) + } + + fn range_mut(v: &mut BTreeMap) -> impl Send + '_ { + v.range_mut(..) + } + + fn entry(v: &mut BTreeMap) -> impl Send + '_ { + v.entry(Default::default()) + } + + fn occupied_entry(v: &mut BTreeMap) -> impl Send + '_ { + match v.entry(Default::default()) { + Occupied(entry) => entry, + _ => unreachable!(), + } + } + + fn vacant_entry(v: &mut BTreeMap) -> impl Send + '_ { + match v.entry(Default::default()) { + Vacant(entry) => entry, + _ => unreachable!(), + } + } +} + +#[test] +fn test_ord_absence() { + fn map(mut map: BTreeMap) { + let _ = map.is_empty(); + let _ = map.len(); + map.clear(); + let _ = map.iter(); + let _ = map.iter_mut(); + let _ = map.keys(); + let _ = map.values(); + let _ = map.values_mut(); + if true { + let _ = map.into_values(); + } else if true { + let _ = map.into_iter(); + } else { + let _ = map.into_keys(); + } + } + + fn map_debug(mut map: BTreeMap) { + let _ = format!("{map:?}"); + let _ = format!("{:?}", map.iter()); + let _ = format!("{:?}", map.iter_mut()); + let _ = format!("{:?}", map.keys()); + let _ = format!("{:?}", map.values()); + let _ = format!("{:?}", map.values_mut()); + if true { + let _ = format!("{:?}", map.into_iter()); + } else if true { + let _ = format!("{:?}", map.into_keys()); + } else { + let _ = format!("{:?}", map.into_values()); + } + } + + fn map_clone(mut map: BTreeMap) { + map.clone_from(&map.clone()); + } + + #[derive(Debug, Clone)] + struct NonOrd; + map(BTreeMap::::new()); + map_debug(BTreeMap::::new()); + map_clone(BTreeMap::::default()); +} + +#[test] +fn test_occupied_entry_key() { + let mut a = BTreeMap::new(); + let key = "hello there"; + let value = "value goes here"; + assert_eq!(a.height(), None); + a.insert(key, value); + assert_eq!(a.len(), 1); + assert_eq!(a[key], value); + + match a.entry(key) { + Vacant(_) => panic!(), + Occupied(e) => assert_eq!(key, *e.key()), + } + assert_eq!(a.len(), 1); + assert_eq!(a[key], value); + a.check(); +} + +#[test] +fn test_vacant_entry_key() { + let mut a = BTreeMap::new(); + let key = "hello there"; + let value = "value goes here"; + + assert_eq!(a.height(), None); + match a.entry(key) { + Occupied(_) => unreachable!(), + Vacant(e) => { + assert_eq!(key, *e.key()); + e.insert(value); + } + } + assert_eq!(a.len(), 1); + assert_eq!(a[key], value); + a.check(); +} + +#[test] +fn test_vacant_entry_no_insert() { + let mut a = BTreeMap::<&str, ()>::new(); + let key = "hello there"; + + // Non-allocated + assert_eq!(a.height(), None); + match a.entry(key) { + Occupied(_) => unreachable!(), + Vacant(e) => assert_eq!(key, *e.key()), + } + // Ensures the tree has no root. + assert_eq!(a.height(), None); + a.check(); + + // Allocated but still empty + a.insert(key, ()); + a.remove(&key); + assert_eq!(a.height(), Some(0)); + assert!(a.is_empty()); + match a.entry(key) { + Occupied(_) => unreachable!(), + Vacant(e) => assert_eq!(key, *e.key()), + } + // Ensures the allocated root is not changed. + assert_eq!(a.height(), Some(0)); + assert!(a.is_empty()); + a.check(); +} + +#[test] +fn test_first_last_entry() { + let mut a = BTreeMap::new(); + assert!(a.first_entry().is_none()); + assert!(a.last_entry().is_none()); + a.insert(1, 42); + assert_eq!(a.first_entry().unwrap().key(), &1); + assert_eq!(a.last_entry().unwrap().key(), &1); + a.insert(2, 24); + assert_eq!(a.first_entry().unwrap().key(), &1); + assert_eq!(a.last_entry().unwrap().key(), &2); + a.insert(0, 6); + assert_eq!(a.first_entry().unwrap().key(), &0); + assert_eq!(a.last_entry().unwrap().key(), &2); + let (k1, v1) = a.first_entry().unwrap().remove_entry(); + assert_eq!(k1, 0); + assert_eq!(v1, 6); + let (k2, v2) = a.last_entry().unwrap().remove_entry(); + assert_eq!(k2, 2); + assert_eq!(v2, 24); + assert_eq!(a.first_entry().unwrap().key(), &1); + assert_eq!(a.last_entry().unwrap().key(), &1); + a.check(); +} + +#[test] +fn test_pop_first_last() { + let mut map = BTreeMap::new(); + assert_eq!(map.pop_first(), None); + assert_eq!(map.pop_last(), None); + + map.insert(1, 10); + map.insert(2, 20); + map.insert(3, 30); + map.insert(4, 40); + + assert_eq!(map.len(), 4); + + let (key, val) = map.pop_first().unwrap(); + assert_eq!(key, 1); + assert_eq!(val, 10); + assert_eq!(map.len(), 3); + + let (key, val) = map.pop_first().unwrap(); + assert_eq!(key, 2); + assert_eq!(val, 20); + assert_eq!(map.len(), 2); + let (key, val) = map.pop_last().unwrap(); + assert_eq!(key, 4); + assert_eq!(val, 40); + assert_eq!(map.len(), 1); + + map.insert(5, 50); + map.insert(6, 60); + assert_eq!(map.len(), 3); + + let (key, val) = map.pop_first().unwrap(); + assert_eq!(key, 3); + assert_eq!(val, 30); + assert_eq!(map.len(), 2); + + let (key, val) = map.pop_last().unwrap(); + assert_eq!(key, 6); + assert_eq!(val, 60); + assert_eq!(map.len(), 1); + + let (key, val) = map.pop_last().unwrap(); + assert_eq!(key, 5); + assert_eq!(val, 50); + assert_eq!(map.len(), 0); + + assert_eq!(map.pop_first(), None); + assert_eq!(map.pop_last(), None); + + map.insert(7, 70); + map.insert(8, 80); + + let (key, val) = map.pop_last().unwrap(); + assert_eq!(key, 8); + assert_eq!(val, 80); + assert_eq!(map.len(), 1); + + let (key, val) = map.pop_last().unwrap(); + assert_eq!(key, 7); + assert_eq!(val, 70); + assert_eq!(map.len(), 0); + + assert_eq!(map.pop_first(), None); + assert_eq!(map.pop_last(), None); +} + +#[test] +fn test_get_key_value() { + let mut map = BTreeMap::new(); + + assert!(map.is_empty()); + assert_eq!(map.get_key_value(&1), None); + assert_eq!(map.get_key_value(&2), None); + + map.insert(1, 10); + map.insert(2, 20); + map.insert(3, 30); + + assert_eq!(map.len(), 3); + assert_eq!(map.get_key_value(&1), Some((&1, &10))); + assert_eq!(map.get_key_value(&3), Some((&3, &30))); + assert_eq!(map.get_key_value(&4), None); + + map.remove(&3); + + assert_eq!(map.len(), 2); + assert_eq!(map.get_key_value(&3), None); + assert_eq!(map.get_key_value(&2), Some((&2, &20))); +} + +#[test] +fn test_insert_into_full_height_0() { + let size = node::CAPACITY; + for pos in 0..=size { + let mut map = BTreeMap::from_iter((0..size).map(|i| (i * 2 + 1, ()))); + assert!(map.insert(pos * 2, ()).is_none()); + map.check(); + } +} + +#[test] +fn test_insert_into_full_height_1() { + let size = node::CAPACITY + 1 + node::CAPACITY; + for pos in 0..=size { + let mut map = BTreeMap::from_iter((0..size).map(|i| (i * 2 + 1, ()))); + map.compact(); + let root_node = map.root.as_ref().unwrap().reborrow(); + assert_eq!(root_node.len(), 1); + assert_eq!(root_node.first_leaf_edge().into_node().len(), node::CAPACITY); + assert_eq!(root_node.last_leaf_edge().into_node().len(), node::CAPACITY); + + assert!(map.insert(pos * 2, ()).is_none()); + map.check(); + } +} + +#[test] +fn test_try_insert() { + let mut map = BTreeMap::new(); + + assert!(map.is_empty()); + + assert_eq!(map.try_insert(1, 10).unwrap(), &10); + assert_eq!(map.try_insert(2, 20).unwrap(), &20); + + let err = map.try_insert(2, 200).unwrap_err(); + assert_eq!(err.entry.key(), &2); + assert_eq!(err.entry.get(), &20); + assert_eq!(err.value, 200); +} + +macro_rules! create_append_test { + ($name:ident, $len:expr) => { + #[test] + fn $name() { + let mut a = BTreeMap::new(); + for i in 0..8 { + a.insert(i, i); + } + + let mut b = BTreeMap::new(); + for i in 5..$len { + b.insert(i, 2 * i); + } + + a.append(&mut b); + + assert_eq!(a.len(), $len); + assert_eq!(b.len(), 0); + + for i in 0..$len { + if i < 5 { + assert_eq!(a[&i], i); + } else { + assert_eq!(a[&i], 2 * i); + } + } + + a.check(); + assert_eq!(a.remove(&($len - 1)), Some(2 * ($len - 1))); + assert_eq!(a.insert($len - 1, 20), None); + a.check(); + } + }; +} + +// These are mostly for testing the algorithm that "fixes" the right edge after insertion. +// Single node. +create_append_test!(test_append_9, 9); +// Two leafs that don't need fixing. +create_append_test!(test_append_17, 17); +// Two leafs where the second one ends up underfull and needs stealing at the end. +create_append_test!(test_append_14, 14); +// Two leafs where the second one ends up empty because the insertion finished at the root. +create_append_test!(test_append_12, 12); +// Three levels; insertion finished at the root. +create_append_test!(test_append_144, 144); +// Three levels; insertion finished at leaf while there is an empty node on the second level. +create_append_test!(test_append_145, 145); +// Tests for several randomly chosen sizes. +create_append_test!(test_append_170, 170); +create_append_test!(test_append_181, 181); +#[cfg(not(miri))] // Miri is too slow +create_append_test!(test_append_239, 239); +#[cfg(not(miri))] // Miri is too slow +create_append_test!(test_append_1700, 1700); + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_append_drop_leak() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut left = BTreeMap::new(); + let mut right = BTreeMap::new(); + left.insert(a.spawn(Panic::Never), ()); + left.insert(b.spawn(Panic::InDrop), ()); // first duplicate key, dropped during append + left.insert(c.spawn(Panic::Never), ()); + right.insert(b.spawn(Panic::Never), ()); + right.insert(c.spawn(Panic::Never), ()); + + catch_unwind(move || left.append(&mut right)).unwrap_err(); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); // should be 2 were it not for Rust issue #47949 + assert_eq!(c.dropped(), 2); +} + +#[test] +fn test_append_ord_chaos() { + let mut map1 = BTreeMap::new(); + map1.insert(Cyclic3::A, ()); + map1.insert(Cyclic3::B, ()); + let mut map2 = BTreeMap::new(); + map2.insert(Cyclic3::A, ()); + map2.insert(Cyclic3::B, ()); + map2.insert(Cyclic3::C, ()); // lands first, before A + map2.insert(Cyclic3::B, ()); // lands first, before C + map1.check(); + map2.check(); // keys are not unique but still strictly ascending + assert_eq!(map1.len(), 2); + assert_eq!(map2.len(), 4); + map1.append(&mut map2); + assert_eq!(map1.len(), 5); + assert_eq!(map2.len(), 0); + map1.check(); + map2.check(); +} + +fn rand_data(len: usize) -> Vec<(u32, u32)> { + let mut rng = DeterministicRng::new(); + Vec::from_iter((0..len).map(|_| (rng.next(), rng.next()))) +} + +#[test] +fn test_split_off_empty_right() { + let mut data = rand_data(173); + + let mut map = BTreeMap::from_iter(data.clone()); + let right = map.split_off(&(data.iter().max().unwrap().0 + 1)); + map.check(); + right.check(); + + data.sort(); + assert!(map.into_iter().eq(data)); + assert!(right.into_iter().eq(None)); +} + +#[test] +fn test_split_off_empty_left() { + let mut data = rand_data(314); + + let mut map = BTreeMap::from_iter(data.clone()); + let right = map.split_off(&data.iter().min().unwrap().0); + map.check(); + right.check(); + + data.sort(); + assert!(map.into_iter().eq(None)); + assert!(right.into_iter().eq(data)); +} + +// In a tree with 3 levels, if all but a part of the first leaf node is split off, +// make sure fix_top eliminates both top levels. +#[test] +fn test_split_off_tiny_left_height_2() { + let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); + let mut left = BTreeMap::from_iter(pairs.clone()); + let right = left.split_off(&1); + left.check(); + right.check(); + assert_eq!(left.len(), 1); + assert_eq!(right.len(), MIN_INSERTS_HEIGHT_2 - 1); + assert_eq!(*left.first_key_value().unwrap().0, 0); + assert_eq!(*right.first_key_value().unwrap().0, 1); +} + +// In a tree with 3 levels, if only part of the last leaf node is split off, +// make sure fix_top eliminates both top levels. +#[test] +fn test_split_off_tiny_right_height_2() { + let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); + let last = MIN_INSERTS_HEIGHT_2 - 1; + let mut left = BTreeMap::from_iter(pairs.clone()); + assert_eq!(*left.last_key_value().unwrap().0, last); + let right = left.split_off(&last); + left.check(); + right.check(); + assert_eq!(left.len(), MIN_INSERTS_HEIGHT_2 - 1); + assert_eq!(right.len(), 1); + assert_eq!(*left.last_key_value().unwrap().0, last - 1); + assert_eq!(*right.last_key_value().unwrap().0, last); +} + +#[test] +fn test_split_off_halfway() { + let mut rng = DeterministicRng::new(); + for &len in &[node::CAPACITY, 25, 50, 75, 100] { + let mut data = Vec::from_iter((0..len).map(|_| (rng.next(), ()))); + // Insertion in non-ascending order creates some variation in node length. + let mut map = BTreeMap::from_iter(data.iter().copied()); + data.sort(); + let small_keys = data.iter().take(len / 2).map(|kv| kv.0); + let large_keys = data.iter().skip(len / 2).map(|kv| kv.0); + let split_key = large_keys.clone().next().unwrap(); + let right = map.split_off(&split_key); + map.check(); + right.check(); + assert!(map.keys().copied().eq(small_keys)); + assert!(right.keys().copied().eq(large_keys)); + } +} + +#[test] +fn test_split_off_large_random_sorted() { + // Miri is too slow + let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) }; + // special case with maximum height. + data.sort(); + + let mut map = BTreeMap::from_iter(data.clone()); + let key = data[data.len() / 2].0; + let right = map.split_off(&key); + map.check(); + right.check(); + + assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key))); + assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key))); +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_into_iter_drop_leak_height_0() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let d = CrashTestDummy::new(3); + let e = CrashTestDummy::new(4); + let mut map = BTreeMap::new(); + map.insert("a", a.spawn(Panic::Never)); + map.insert("b", b.spawn(Panic::Never)); + map.insert("c", c.spawn(Panic::Never)); + map.insert("d", d.spawn(Panic::InDrop)); + map.insert("e", e.spawn(Panic::Never)); + + catch_unwind(move || drop(map.into_iter())).unwrap_err(); + + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); + assert_eq!(c.dropped(), 1); + assert_eq!(d.dropped(), 1); + assert_eq!(e.dropped(), 1); +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_into_iter_drop_leak_kv_panic_in_key() { + let a_k = CrashTestDummy::new(0); + let a_v = CrashTestDummy::new(1); + let b_k = CrashTestDummy::new(2); + let b_v = CrashTestDummy::new(3); + let c_k = CrashTestDummy::new(4); + let c_v = CrashTestDummy::new(5); + let mut map = BTreeMap::new(); + map.insert(a_k.spawn(Panic::Never), a_v.spawn(Panic::Never)); + map.insert(b_k.spawn(Panic::InDrop), b_v.spawn(Panic::Never)); + map.insert(c_k.spawn(Panic::Never), c_v.spawn(Panic::Never)); + + catch_unwind(move || drop(map.into_iter())).unwrap_err(); + + assert_eq!(a_k.dropped(), 1); + assert_eq!(a_v.dropped(), 1); + assert_eq!(b_k.dropped(), 1); + assert_eq!(b_v.dropped(), 1); + assert_eq!(c_k.dropped(), 1); + assert_eq!(c_v.dropped(), 1); +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_into_iter_drop_leak_kv_panic_in_val() { + let a_k = CrashTestDummy::new(0); + let a_v = CrashTestDummy::new(1); + let b_k = CrashTestDummy::new(2); + let b_v = CrashTestDummy::new(3); + let c_k = CrashTestDummy::new(4); + let c_v = CrashTestDummy::new(5); + let mut map = BTreeMap::new(); + map.insert(a_k.spawn(Panic::Never), a_v.spawn(Panic::Never)); + map.insert(b_k.spawn(Panic::Never), b_v.spawn(Panic::InDrop)); + map.insert(c_k.spawn(Panic::Never), c_v.spawn(Panic::Never)); + + catch_unwind(move || drop(map.into_iter())).unwrap_err(); + + assert_eq!(a_k.dropped(), 1); + assert_eq!(a_v.dropped(), 1); + assert_eq!(b_k.dropped(), 1); + assert_eq!(b_v.dropped(), 1); + assert_eq!(c_k.dropped(), 1); + assert_eq!(c_v.dropped(), 1); +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_into_iter_drop_leak_height_1() { + let size = MIN_INSERTS_HEIGHT_1; + for panic_point in vec![0, 1, size - 2, size - 1] { + let dummies = Vec::from_iter((0..size).map(|i| CrashTestDummy::new(i))); + let map = BTreeMap::from_iter((0..size).map(|i| { + let panic = if i == panic_point { Panic::InDrop } else { Panic::Never }; + (dummies[i].spawn(Panic::Never), dummies[i].spawn(panic)) + })); + catch_unwind(move || drop(map.into_iter())).unwrap_err(); + for i in 0..size { + assert_eq!(dummies[i].dropped(), 2); + } + } +} + +#[test] +fn test_into_keys() { + let map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let keys = Vec::from_iter(map.into_keys()); + + assert_eq!(keys.len(), 3); + assert!(keys.contains(&1)); + assert!(keys.contains(&2)); + assert!(keys.contains(&3)); +} + +#[test] +fn test_into_values() { + let map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let values = Vec::from_iter(map.into_values()); + + assert_eq!(values.len(), 3); + assert!(values.contains(&'a')); + assert!(values.contains(&'b')); + assert!(values.contains(&'c')); +} + +#[test] +fn test_insert_remove_intertwined() { + let loops = if cfg!(miri) { 100 } else { 1_000_000 }; + let mut map = BTreeMap::new(); + let mut i = 1; + let offset = 165; // somewhat arbitrarily chosen to cover some code paths + for _ in 0..loops { + i = (i + offset) & 0xFF; + map.insert(i, i); + map.remove(&(0xFF - i)); + } + map.check(); +} + +#[test] +fn test_insert_remove_intertwined_ord_chaos() { + let loops = if cfg!(miri) { 100 } else { 1_000_000 }; + let gov = Governor::new(); + let mut map = BTreeMap::new(); + let mut i = 1; + let offset = 165; // more arbitrarily copied from above + for _ in 0..loops { + i = (i + offset) & 0xFF; + map.insert(Governed(i, &gov), ()); + map.remove(&Governed(0xFF - i, &gov)); + gov.flip(); + } + map.check_invariants(); +} + +#[test] +fn from_array() { + let map = BTreeMap::from([(1, 2), (3, 4)]); + let unordered_duplicates = BTreeMap::from([(3, 4), (1, 2), (1, 2)]); + assert_eq!(map, unordered_duplicates); +} + +#[test] +fn test_cursor() { + let map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + + let mut cur = map.lower_bound(Bound::Unbounded); + assert_eq!(cur.peek_next(), Some((&1, &'a'))); + assert_eq!(cur.peek_prev(), None); + assert_eq!(cur.prev(), None); + assert_eq!(cur.next(), Some((&1, &'a'))); + + assert_eq!(cur.next(), Some((&2, &'b'))); + + assert_eq!(cur.peek_next(), Some((&3, &'c'))); + assert_eq!(cur.prev(), Some((&2, &'b'))); + assert_eq!(cur.peek_prev(), Some((&1, &'a'))); + + let mut cur = map.upper_bound(Bound::Excluded(&1)); + assert_eq!(cur.peek_prev(), None); + assert_eq!(cur.next(), Some((&1, &'a'))); + assert_eq!(cur.prev(), Some((&1, &'a'))); +} + +#[test] +fn test_cursor_mut() { + let mut map = BTreeMap::from([(1, 'a'), (3, 'c'), (5, 'e')]); + let mut cur = map.lower_bound_mut(Bound::Excluded(&3)); + assert_eq!(cur.peek_next(), Some((&5, &mut 'e'))); + assert_eq!(cur.peek_prev(), Some((&3, &mut 'c'))); + + cur.insert_before(4, 'd').unwrap(); + assert_eq!(cur.peek_next(), Some((&5, &mut 'e'))); + assert_eq!(cur.peek_prev(), Some((&4, &mut 'd'))); + + assert_eq!(cur.next(), Some((&5, &mut 'e'))); + assert_eq!(cur.peek_next(), None); + assert_eq!(cur.peek_prev(), Some((&5, &mut 'e'))); + cur.insert_before(6, 'f').unwrap(); + assert_eq!(cur.peek_next(), None); + assert_eq!(cur.peek_prev(), Some((&6, &mut 'f'))); + assert_eq!(cur.remove_prev(), Some((6, 'f'))); + assert_eq!(cur.remove_prev(), Some((5, 'e'))); + assert_eq!(cur.remove_next(), None); + assert_eq!(map, BTreeMap::from([(1, 'a'), (3, 'c'), (4, 'd')])); + + let mut cur = map.upper_bound_mut(Bound::Included(&5)); + assert_eq!(cur.peek_next(), None); + assert_eq!(cur.prev(), Some((&4, &mut 'd'))); + assert_eq!(cur.peek_next(), Some((&4, &mut 'd'))); + assert_eq!(cur.peek_prev(), Some((&3, &mut 'c'))); + assert_eq!(cur.remove_next(), Some((4, 'd'))); + assert_eq!(map, BTreeMap::from([(1, 'a'), (3, 'c')])); +} + +#[test] +fn test_cursor_mut_key() { + let mut map = BTreeMap::from([(1, 'a'), (3, 'c'), (5, 'e')]); + let mut cur = unsafe { map.lower_bound_mut(Bound::Excluded(&3)).with_mutable_key() }; + assert_eq!(cur.peek_next(), Some((&mut 5, &mut 'e'))); + assert_eq!(cur.peek_prev(), Some((&mut 3, &mut 'c'))); + + cur.insert_before(4, 'd').unwrap(); + assert_eq!(cur.peek_next(), Some((&mut 5, &mut 'e'))); + assert_eq!(cur.peek_prev(), Some((&mut 4, &mut 'd'))); + + assert_eq!(cur.next(), Some((&mut 5, &mut 'e'))); + assert_eq!(cur.peek_next(), None); + assert_eq!(cur.peek_prev(), Some((&mut 5, &mut 'e'))); + cur.insert_before(6, 'f').unwrap(); + assert_eq!(cur.peek_next(), None); + assert_eq!(cur.peek_prev(), Some((&mut 6, &mut 'f'))); + assert_eq!(cur.remove_prev(), Some((6, 'f'))); + assert_eq!(cur.remove_prev(), Some((5, 'e'))); + assert_eq!(cur.remove_next(), None); + assert_eq!(map, BTreeMap::from([(1, 'a'), (3, 'c'), (4, 'd')])); + + let mut cur = unsafe { map.upper_bound_mut(Bound::Included(&5)).with_mutable_key() }; + assert_eq!(cur.peek_next(), None); + assert_eq!(cur.prev(), Some((&mut 4, &mut 'd'))); + assert_eq!(cur.peek_next(), Some((&mut 4, &mut 'd'))); + assert_eq!(cur.peek_prev(), Some((&mut 3, &mut 'c'))); + assert_eq!(cur.remove_next(), Some((4, 'd'))); + assert_eq!(map, BTreeMap::from([(1, 'a'), (3, 'c')])); +} + +#[test] +fn test_cursor_empty() { + let mut map = BTreeMap::new(); + let mut cur = map.lower_bound_mut(Bound::Excluded(&3)); + assert_eq!(cur.peek_next(), None); + assert_eq!(cur.peek_prev(), None); + cur.insert_after(0, 0).unwrap(); + assert_eq!(cur.peek_next(), Some((&0, &mut 0))); + assert_eq!(cur.peek_prev(), None); + assert_eq!(map, BTreeMap::from([(0, 0)])); +} + +#[test] +fn test_cursor_mut_insert_before_1() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_before(0, 'd').unwrap_err(); +} + +#[test] +fn test_cursor_mut_insert_before_2() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_before(1, 'd').unwrap_err(); +} + +#[test] +fn test_cursor_mut_insert_before_3() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_before(2, 'd').unwrap_err(); +} + +#[test] +fn test_cursor_mut_insert_before_4() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_before(3, 'd').unwrap_err(); +} + +#[test] +fn test_cursor_mut_insert_after_1() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_after(1, 'd').unwrap_err(); +} + +#[test] +fn test_cursor_mut_insert_after_2() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_after(2, 'd').unwrap_err(); +} + +#[test] +fn test_cursor_mut_insert_after_3() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_after(3, 'd').unwrap_err(); +} + +#[test] +fn test_cursor_mut_insert_after_4() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_after(4, 'd').unwrap_err(); +} + +#[test] +fn cursor_peek_prev_agrees_with_cursor_mut() { + let mut map = BTreeMap::from([(1, 1), (2, 2), (3, 3)]); + + let cursor = map.lower_bound(Bound::Excluded(&3)); + assert!(cursor.peek_next().is_none()); + + let prev = cursor.peek_prev(); + assert_matches!(prev, Some((&3, _))); + + // Shadow names so the two parts of this test match. + let mut cursor = map.lower_bound_mut(Bound::Excluded(&3)); + assert!(cursor.peek_next().is_none()); + + let prev = cursor.peek_prev(); + assert_matches!(prev, Some((&3, _))); +} diff --git a/CoqOfRust/alloc/collections/btree/mem.rs b/CoqOfRust/alloc/collections/btree/mem.rs new file mode 100644 index 000000000..d738c5c47 --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/mem.rs @@ -0,0 +1,33 @@ +use core::{intrinsics, mem, ptr}; + +/// This replaces the value behind the `v` unique reference by calling the +/// relevant function. +/// +/// If a panic occurs in the `change` closure, the entire process will be aborted. +#[allow(dead_code)] // keep as illustration and for future use +#[inline] +pub fn take_mut(v: &mut T, change: impl FnOnce(T) -> T) { + replace(v, |value| (change(value), ())) +} + +/// This replaces the value behind the `v` unique reference by calling the +/// relevant function, and returns a result obtained along the way. +/// +/// If a panic occurs in the `change` closure, the entire process will be aborted. +#[inline] +pub fn replace(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R { + struct PanicGuard; + impl Drop for PanicGuard { + fn drop(&mut self) { + intrinsics::abort() + } + } + let guard = PanicGuard; + let value = unsafe { ptr::read(v) }; + let (new_value, ret) = change(value); + unsafe { + ptr::write(v, new_value); + } + mem::forget(guard); + ret +} diff --git a/CoqOfRust/alloc/collections/btree/merge_iter.rs b/CoqOfRust/alloc/collections/btree/merge_iter.rs new file mode 100644 index 000000000..7f23d93b9 --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/merge_iter.rs @@ -0,0 +1,98 @@ +use core::cmp::Ordering; +use core::fmt::{self, Debug}; +use core::iter::FusedIterator; + +/// Core of an iterator that merges the output of two strictly ascending iterators, +/// for instance a union or a symmetric difference. +pub struct MergeIterInner { + a: I, + b: I, + peeked: Option>, +} + +/// Benchmarks faster than wrapping both iterators in a Peekable, +/// probably because we can afford to impose a FusedIterator bound. +#[derive(Clone, Debug)] +enum Peeked { + A(I::Item), + B(I::Item), +} + +impl Clone for MergeIterInner +where + I: Clone, + I::Item: Clone, +{ + fn clone(&self) -> Self { + Self { a: self.a.clone(), b: self.b.clone(), peeked: self.peeked.clone() } + } +} + +impl Debug for MergeIterInner +where + I: Debug, + I::Item: Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("MergeIterInner").field(&self.a).field(&self.b).field(&self.peeked).finish() + } +} + +impl MergeIterInner { + /// Creates a new core for an iterator merging a pair of sources. + pub fn new(a: I, b: I) -> Self { + MergeIterInner { a, b, peeked: None } + } + + /// Returns the next pair of items stemming from the pair of sources + /// being merged. If both returned options contain a value, that value + /// is equal and occurs in both sources. If one of the returned options + /// contains a value, that value doesn't occur in the other source (or + /// the sources are not strictly ascending). If neither returned option + /// contains a value, iteration has finished and subsequent calls will + /// return the same empty pair. + pub fn nexts Ordering>( + &mut self, + cmp: Cmp, + ) -> (Option, Option) + where + I: FusedIterator, + { + let mut a_next; + let mut b_next; + match self.peeked.take() { + Some(Peeked::A(next)) => { + a_next = Some(next); + b_next = self.b.next(); + } + Some(Peeked::B(next)) => { + b_next = Some(next); + a_next = self.a.next(); + } + None => { + a_next = self.a.next(); + b_next = self.b.next(); + } + } + if let (Some(ref a1), Some(ref b1)) = (&a_next, &b_next) { + match cmp(a1, b1) { + Ordering::Less => self.peeked = b_next.take().map(Peeked::B), + Ordering::Greater => self.peeked = a_next.take().map(Peeked::A), + Ordering::Equal => (), + } + } + (a_next, b_next) + } + + /// Returns a pair of upper bounds for the `size_hint` of the final iterator. + pub fn lens(&self) -> (usize, usize) + where + I: ExactSizeIterator, + { + match self.peeked { + Some(Peeked::A(_)) => (1 + self.a.len(), self.b.len()), + Some(Peeked::B(_)) => (self.a.len(), 1 + self.b.len()), + _ => (self.a.len(), self.b.len()), + } + } +} diff --git a/CoqOfRust/alloc/collections/btree/mod.rs b/CoqOfRust/alloc/collections/btree/mod.rs new file mode 100644 index 000000000..b8667d09c --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/mod.rs @@ -0,0 +1,14 @@ +mod append; +mod borrow; +mod dedup_sorted_iter; +mod fix; +pub mod map; +mod mem; +mod merge_iter; +mod navigate; +mod node; +mod remove; +mod search; +pub mod set; +mod set_val; +mod split; diff --git a/CoqOfRust/alloc/collections/btree/navigate.rs b/CoqOfRust/alloc/collections/btree/navigate.rs new file mode 100644 index 000000000..14b7d4ad7 --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/navigate.rs @@ -0,0 +1,781 @@ +use core::borrow::Borrow; +use core::ops::RangeBounds; +use core::{hint, ptr}; + +use super::node::ForceResult::*; +use super::node::{Handle, NodeRef, marker}; +use super::search::SearchBound; +use crate::alloc::Allocator; +// `front` and `back` are always both `None` or both `Some`. +pub struct LeafRange { + front: Option, marker::Edge>>, + back: Option, marker::Edge>>, +} + +impl<'a, K: 'a, V: 'a> Clone for LeafRange, K, V> { + fn clone(&self) -> Self { + LeafRange { front: self.front.clone(), back: self.back.clone() } + } +} + +impl Default for LeafRange { + fn default() -> Self { + LeafRange { front: None, back: None } + } +} + +impl LeafRange { + pub fn none() -> Self { + LeafRange { front: None, back: None } + } + + fn is_empty(&self) -> bool { + self.front == self.back + } + + /// Temporarily takes out another, immutable equivalent of the same range. + pub fn reborrow(&self) -> LeafRange, K, V> { + LeafRange { + front: self.front.as_ref().map(|f| f.reborrow()), + back: self.back.as_ref().map(|b| b.reborrow()), + } + } +} + +impl<'a, K, V> LeafRange, K, V> { + #[inline] + pub fn next_checked(&mut self) -> Option<(&'a K, &'a V)> { + self.perform_next_checked(|kv| kv.into_kv()) + } + + #[inline] + pub fn next_back_checked(&mut self) -> Option<(&'a K, &'a V)> { + self.perform_next_back_checked(|kv| kv.into_kv()) + } +} + +impl<'a, K, V> LeafRange, K, V> { + #[inline] + pub fn next_checked(&mut self) -> Option<(&'a K, &'a mut V)> { + self.perform_next_checked(|kv| unsafe { ptr::read(kv) }.into_kv_valmut()) + } + + #[inline] + pub fn next_back_checked(&mut self) -> Option<(&'a K, &'a mut V)> { + self.perform_next_back_checked(|kv| unsafe { ptr::read(kv) }.into_kv_valmut()) + } +} + +impl LeafRange { + /// If possible, extract some result from the following KV and move to the edge beyond it. + fn perform_next_checked(&mut self, f: F) -> Option + where + F: Fn(&Handle, marker::KV>) -> R, + { + if self.is_empty() { + None + } else { + super::mem::replace(self.front.as_mut().unwrap(), |front| { + let kv = front.next_kv().ok().unwrap(); + let result = f(&kv); + (kv.next_leaf_edge(), Some(result)) + }) + } + } + + /// If possible, extract some result from the preceding KV and move to the edge beyond it. + fn perform_next_back_checked(&mut self, f: F) -> Option + where + F: Fn(&Handle, marker::KV>) -> R, + { + if self.is_empty() { + None + } else { + super::mem::replace(self.back.as_mut().unwrap(), |back| { + let kv = back.next_back_kv().ok().unwrap(); + let result = f(&kv); + (kv.next_back_leaf_edge(), Some(result)) + }) + } + } +} + +enum LazyLeafHandle { + Root(NodeRef), // not yet descended + Edge(Handle, marker::Edge>), +} + +impl<'a, K: 'a, V: 'a> Clone for LazyLeafHandle, K, V> { + fn clone(&self) -> Self { + match self { + LazyLeafHandle::Root(root) => LazyLeafHandle::Root(*root), + LazyLeafHandle::Edge(edge) => LazyLeafHandle::Edge(*edge), + } + } +} + +impl LazyLeafHandle { + fn reborrow(&self) -> LazyLeafHandle, K, V> { + match self { + LazyLeafHandle::Root(root) => LazyLeafHandle::Root(root.reborrow()), + LazyLeafHandle::Edge(edge) => LazyLeafHandle::Edge(edge.reborrow()), + } + } +} + +// `front` and `back` are always both `None` or both `Some`. +pub struct LazyLeafRange { + front: Option>, + back: Option>, +} + +impl Default for LazyLeafRange { + fn default() -> Self { + LazyLeafRange { front: None, back: None } + } +} + +impl<'a, K: 'a, V: 'a> Clone for LazyLeafRange, K, V> { + fn clone(&self) -> Self { + LazyLeafRange { front: self.front.clone(), back: self.back.clone() } + } +} + +impl LazyLeafRange { + pub fn none() -> Self { + LazyLeafRange { front: None, back: None } + } + + /// Temporarily takes out another, immutable equivalent of the same range. + pub fn reborrow(&self) -> LazyLeafRange, K, V> { + LazyLeafRange { + front: self.front.as_ref().map(|f| f.reborrow()), + back: self.back.as_ref().map(|b| b.reborrow()), + } + } +} + +impl<'a, K, V> LazyLeafRange, K, V> { + #[inline] + pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { + unsafe { self.init_front().unwrap().next_unchecked() } + } + + #[inline] + pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { + unsafe { self.init_back().unwrap().next_back_unchecked() } + } +} + +impl<'a, K, V> LazyLeafRange, K, V> { + #[inline] + pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { + unsafe { self.init_front().unwrap().next_unchecked() } + } + + #[inline] + pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { + unsafe { self.init_back().unwrap().next_back_unchecked() } + } +} + +impl LazyLeafRange { + fn take_front( + &mut self, + ) -> Option, marker::Edge>> { + match self.front.take()? { + LazyLeafHandle::Root(root) => Some(root.first_leaf_edge()), + LazyLeafHandle::Edge(edge) => Some(edge), + } + } + + #[inline] + pub unsafe fn deallocating_next_unchecked( + &mut self, + alloc: A, + ) -> Handle, marker::KV> { + debug_assert!(self.front.is_some()); + let front = self.init_front().unwrap(); + unsafe { front.deallocating_next_unchecked(alloc) } + } + + #[inline] + pub unsafe fn deallocating_next_back_unchecked( + &mut self, + alloc: A, + ) -> Handle, marker::KV> { + debug_assert!(self.back.is_some()); + let back = self.init_back().unwrap(); + unsafe { back.deallocating_next_back_unchecked(alloc) } + } + + #[inline] + pub fn deallocating_end(&mut self, alloc: A) { + if let Some(front) = self.take_front() { + front.deallocating_end(alloc) + } + } +} + +impl LazyLeafRange { + fn init_front( + &mut self, + ) -> Option<&mut Handle, marker::Edge>> { + if let Some(LazyLeafHandle::Root(root)) = &self.front { + self.front = Some(LazyLeafHandle::Edge(unsafe { ptr::read(root) }.first_leaf_edge())); + } + match &mut self.front { + None => None, + Some(LazyLeafHandle::Edge(edge)) => Some(edge), + // SAFETY: the code above would have replaced it. + Some(LazyLeafHandle::Root(_)) => unsafe { hint::unreachable_unchecked() }, + } + } + + fn init_back( + &mut self, + ) -> Option<&mut Handle, marker::Edge>> { + if let Some(LazyLeafHandle::Root(root)) = &self.back { + self.back = Some(LazyLeafHandle::Edge(unsafe { ptr::read(root) }.last_leaf_edge())); + } + match &mut self.back { + None => None, + Some(LazyLeafHandle::Edge(edge)) => Some(edge), + // SAFETY: the code above would have replaced it. + Some(LazyLeafHandle::Root(_)) => unsafe { hint::unreachable_unchecked() }, + } + } +} + +impl NodeRef { + /// Finds the distinct leaf edges delimiting a specified range in a tree. + /// + /// If such distinct edges exist, returns them in ascending order, meaning + /// that a non-zero number of calls to `next_unchecked` on the `front` of + /// the result and/or calls to `next_back_unchecked` on the `back` of the + /// result will eventually reach the same edge. + /// + /// If there are no such edges, i.e., if the tree contains no key within + /// the range, returns an empty `front` and `back`. + /// + /// # Safety + /// Unless `BorrowType` is `Immut`, do not use the handles to visit the same + /// KV twice. + unsafe fn find_leaf_edges_spanning_range( + self, + range: R, + ) -> LeafRange + where + Q: Ord, + K: Borrow, + R: RangeBounds, + { + match self.search_tree_for_bifurcation(&range) { + Err(_) => LeafRange::none(), + Ok(( + node, + lower_edge_idx, + upper_edge_idx, + mut lower_child_bound, + mut upper_child_bound, + )) => { + let mut lower_edge = unsafe { Handle::new_edge(ptr::read(&node), lower_edge_idx) }; + let mut upper_edge = unsafe { Handle::new_edge(node, upper_edge_idx) }; + loop { + match (lower_edge.force(), upper_edge.force()) { + (Leaf(f), Leaf(b)) => return LeafRange { front: Some(f), back: Some(b) }, + (Internal(f), Internal(b)) => { + (lower_edge, lower_child_bound) = + f.descend().find_lower_bound_edge(lower_child_bound); + (upper_edge, upper_child_bound) = + b.descend().find_upper_bound_edge(upper_child_bound); + } + _ => unreachable!("BTreeMap has different depths"), + } + } + } + } + } +} + +fn full_range( + root1: NodeRef, + root2: NodeRef, +) -> LazyLeafRange { + LazyLeafRange { + front: Some(LazyLeafHandle::Root(root1)), + back: Some(LazyLeafHandle::Root(root2)), + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + /// Finds the pair of leaf edges delimiting a specific range in a tree. + /// + /// The result is meaningful only if the tree is ordered by key, like the tree + /// in a `BTreeMap` is. + pub fn range_search(self, range: R) -> LeafRange, K, V> + where + Q: ?Sized + Ord, + K: Borrow, + R: RangeBounds, + { + // SAFETY: our borrow type is immutable. + unsafe { self.find_leaf_edges_spanning_range(range) } + } + + /// Finds the pair of leaf edges delimiting an entire tree. + pub fn full_range(self) -> LazyLeafRange, K, V> { + full_range(self, self) + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + /// Splits a unique reference into a pair of leaf edges delimiting a specified range. + /// The result are non-unique references allowing (some) mutation, which must be used + /// carefully. + /// + /// The result is meaningful only if the tree is ordered by key, like the tree + /// in a `BTreeMap` is. + /// + /// # Safety + /// Do not use the duplicate handles to visit the same KV twice. + pub fn range_search(self, range: R) -> LeafRange, K, V> + where + Q: ?Sized + Ord, + K: Borrow, + R: RangeBounds, + { + unsafe { self.find_leaf_edges_spanning_range(range) } + } + + /// Splits a unique reference into a pair of leaf edges delimiting the full range of the tree. + /// The results are non-unique references allowing mutation (of values only), so must be used + /// with care. + pub fn full_range(self) -> LazyLeafRange, K, V> { + // We duplicate the root NodeRef here -- we will never visit the same KV + // twice, and never end up with overlapping value references. + let self2 = unsafe { ptr::read(&self) }; + full_range(self, self2) + } +} + +impl NodeRef { + /// Splits a unique reference into a pair of leaf edges delimiting the full range of the tree. + /// The results are non-unique references allowing massively destructive mutation, so must be + /// used with the utmost care. + pub fn full_range(self) -> LazyLeafRange { + // We duplicate the root NodeRef here -- we will never access it in a way + // that overlaps references obtained from the root. + let self2 = unsafe { ptr::read(&self) }; + full_range(self, self2) + } +} + +impl + Handle, marker::Edge> +{ + /// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV + /// on the right side, which is either in the same leaf node or in an ancestor node. + /// If the leaf edge is the last one in the tree, returns [`Result::Err`] with the root node. + pub fn next_kv( + self, + ) -> Result< + Handle, marker::KV>, + NodeRef, + > { + let mut edge = self.forget_node_type(); + loop { + edge = match edge.right_kv() { + Ok(kv) => return Ok(kv), + Err(last_edge) => match last_edge.into_node().ascend() { + Ok(parent_edge) => parent_edge.forget_node_type(), + Err(root) => return Err(root), + }, + } + } + } + + /// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV + /// on the left side, which is either in the same leaf node or in an ancestor node. + /// If the leaf edge is the first one in the tree, returns [`Result::Err`] with the root node. + pub fn next_back_kv( + self, + ) -> Result< + Handle, marker::KV>, + NodeRef, + > { + let mut edge = self.forget_node_type(); + loop { + edge = match edge.left_kv() { + Ok(kv) => return Ok(kv), + Err(last_edge) => match last_edge.into_node().ascend() { + Ok(parent_edge) => parent_edge.forget_node_type(), + Err(root) => return Err(root), + }, + } + } + } +} + +impl + Handle, marker::Edge> +{ + /// Given an internal edge handle, returns [`Result::Ok`] with a handle to the neighboring KV + /// on the right side, which is either in the same internal node or in an ancestor node. + /// If the internal edge is the last one in the tree, returns [`Result::Err`] with the root node. + fn next_kv( + self, + ) -> Result< + Handle, marker::KV>, + NodeRef, + > { + let mut edge = self; + loop { + edge = match edge.right_kv() { + Ok(internal_kv) => return Ok(internal_kv), + Err(last_edge) => match last_edge.into_node().ascend() { + Ok(parent_edge) => parent_edge, + Err(root) => return Err(root), + }, + } + } + } +} + +impl Handle, marker::Edge> { + /// Given a leaf edge handle into a dying tree, returns the next leaf edge + /// on the right side, and the key-value pair in between, if they exist. + /// + /// If the given edge is the last one in a leaf, this method deallocates + /// the leaf, as well as any ancestor nodes whose last edge was reached. + /// This implies that if no more key-value pair follows, the entire tree + /// will have been deallocated and there is nothing left to return. + /// + /// # Safety + /// - The given edge must not have been previously returned by counterpart + /// `deallocating_next_back`. + /// - The returned KV handle is only valid to access the key and value, + /// and only valid until the next call to a `deallocating_` method. + unsafe fn deallocating_next( + self, + alloc: A, + ) -> Option<(Self, Handle, marker::KV>)> + { + let mut edge = self.forget_node_type(); + loop { + edge = match edge.right_kv() { + Ok(kv) => return Some((unsafe { ptr::read(&kv) }.next_leaf_edge(), kv)), + Err(last_edge) => { + match unsafe { last_edge.into_node().deallocate_and_ascend(alloc.clone()) } { + Some(parent_edge) => parent_edge.forget_node_type(), + None => return None, + } + } + } + } + } + + /// Given a leaf edge handle into a dying tree, returns the next leaf edge + /// on the left side, and the key-value pair in between, if they exist. + /// + /// If the given edge is the first one in a leaf, this method deallocates + /// the leaf, as well as any ancestor nodes whose first edge was reached. + /// This implies that if no more key-value pair follows, the entire tree + /// will have been deallocated and there is nothing left to return. + /// + /// # Safety + /// - The given edge must not have been previously returned by counterpart + /// `deallocating_next`. + /// - The returned KV handle is only valid to access the key and value, + /// and only valid until the next call to a `deallocating_` method. + unsafe fn deallocating_next_back( + self, + alloc: A, + ) -> Option<(Self, Handle, marker::KV>)> + { + let mut edge = self.forget_node_type(); + loop { + edge = match edge.left_kv() { + Ok(kv) => return Some((unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv)), + Err(last_edge) => { + match unsafe { last_edge.into_node().deallocate_and_ascend(alloc.clone()) } { + Some(parent_edge) => parent_edge.forget_node_type(), + None => return None, + } + } + } + } + } + + /// Deallocates a pile of nodes from the leaf up to the root. + /// This is the only way to deallocate the remainder of a tree after + /// `deallocating_next` and `deallocating_next_back` have been nibbling at + /// both sides of the tree, and have hit the same edge. As it is intended + /// only to be called when all keys and values have been returned, + /// no cleanup is done on any of the keys or values. + fn deallocating_end(self, alloc: A) { + let mut edge = self.forget_node_type(); + while let Some(parent_edge) = + unsafe { edge.into_node().deallocate_and_ascend(alloc.clone()) } + { + edge = parent_edge.forget_node_type(); + } + } +} + +impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge> { + /// Moves the leaf edge handle to the next leaf edge and returns references to the + /// key and value in between. + /// + /// # Safety + /// There must be another KV in the direction travelled. + unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { + super::mem::replace(self, |leaf_edge| { + let kv = leaf_edge.next_kv().ok().unwrap(); + (kv.next_leaf_edge(), kv.into_kv()) + }) + } + + /// Moves the leaf edge handle to the previous leaf edge and returns references to the + /// key and value in between. + /// + /// # Safety + /// There must be another KV in the direction travelled. + unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { + super::mem::replace(self, |leaf_edge| { + let kv = leaf_edge.next_back_kv().ok().unwrap(); + (kv.next_back_leaf_edge(), kv.into_kv()) + }) + } +} + +impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge> { + /// Moves the leaf edge handle to the next leaf edge and returns references to the + /// key and value in between. + /// + /// # Safety + /// There must be another KV in the direction travelled. + unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { + let kv = super::mem::replace(self, |leaf_edge| { + let kv = leaf_edge.next_kv().ok().unwrap(); + (unsafe { ptr::read(&kv) }.next_leaf_edge(), kv) + }); + // Doing this last is faster, according to benchmarks. + kv.into_kv_valmut() + } + + /// Moves the leaf edge handle to the previous leaf and returns references to the + /// key and value in between. + /// + /// # Safety + /// There must be another KV in the direction travelled. + unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { + let kv = super::mem::replace(self, |leaf_edge| { + let kv = leaf_edge.next_back_kv().ok().unwrap(); + (unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv) + }); + // Doing this last is faster, according to benchmarks. + kv.into_kv_valmut() + } +} + +impl Handle, marker::Edge> { + /// Moves the leaf edge handle to the next leaf edge and returns the key and value + /// in between, deallocating any node left behind while leaving the corresponding + /// edge in its parent node dangling. + /// + /// # Safety + /// - There must be another KV in the direction travelled. + /// - That KV was not previously returned by counterpart + /// `deallocating_next_back_unchecked` on any copy of the handles + /// being used to traverse the tree. + /// + /// The only safe way to proceed with the updated handle is to compare it, drop it, + /// or call this method or counterpart `deallocating_next_back_unchecked` again. + unsafe fn deallocating_next_unchecked( + &mut self, + alloc: A, + ) -> Handle, marker::KV> { + super::mem::replace(self, |leaf_edge| unsafe { + leaf_edge.deallocating_next(alloc).unwrap() + }) + } + + /// Moves the leaf edge handle to the previous leaf edge and returns the key and value + /// in between, deallocating any node left behind while leaving the corresponding + /// edge in its parent node dangling. + /// + /// # Safety + /// - There must be another KV in the direction travelled. + /// - That leaf edge was not previously returned by counterpart + /// `deallocating_next_unchecked` on any copy of the handles + /// being used to traverse the tree. + /// + /// The only safe way to proceed with the updated handle is to compare it, drop it, + /// or call this method or counterpart `deallocating_next_unchecked` again. + unsafe fn deallocating_next_back_unchecked( + &mut self, + alloc: A, + ) -> Handle, marker::KV> { + super::mem::replace(self, |leaf_edge| unsafe { + leaf_edge.deallocating_next_back(alloc).unwrap() + }) + } +} + +impl NodeRef { + /// Returns the leftmost leaf edge in or underneath a node - in other words, the edge + /// you need first when navigating forward (or last when navigating backward). + #[inline] + pub fn first_leaf_edge(self) -> Handle, marker::Edge> { + let mut node = self; + loop { + match node.force() { + Leaf(leaf) => return leaf.first_edge(), + Internal(internal) => node = internal.first_edge().descend(), + } + } + } + + /// Returns the rightmost leaf edge in or underneath a node - in other words, the edge + /// you need last when navigating forward (or first when navigating backward). + #[inline] + pub fn last_leaf_edge(self) -> Handle, marker::Edge> { + let mut node = self; + loop { + match node.force() { + Leaf(leaf) => return leaf.last_edge(), + Internal(internal) => node = internal.last_edge().descend(), + } + } + } +} + +pub enum Position { + Leaf(NodeRef), + Internal(NodeRef), + InternalKV, +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + /// Visits leaf nodes and internal KVs in order of ascending keys, and also + /// visits internal nodes as a whole in a depth first order, meaning that + /// internal nodes precede their individual KVs and their child nodes. + pub fn visit_nodes_in_order(self, mut visit: F) + where + F: FnMut(Position, K, V>), + { + match self.force() { + Leaf(leaf) => visit(Position::Leaf(leaf)), + Internal(internal) => { + visit(Position::Internal(internal)); + let mut edge = internal.first_edge(); + loop { + edge = match edge.descend().force() { + Leaf(leaf) => { + visit(Position::Leaf(leaf)); + match edge.next_kv() { + Ok(kv) => { + visit(Position::InternalKV); + kv.right_edge() + } + Err(_) => return, + } + } + Internal(internal) => { + visit(Position::Internal(internal)); + internal.first_edge() + } + } + } + } + } + } + + /// Calculates the number of elements in a (sub)tree. + pub fn calc_length(self) -> usize { + let mut result = 0; + self.visit_nodes_in_order(|pos| match pos { + Position::Leaf(node) => result += node.len(), + Position::Internal(node) => result += node.len(), + Position::InternalKV => (), + }); + result + } +} + +impl + Handle, marker::KV> +{ + /// Returns the leaf edge closest to a KV for forward navigation. + pub fn next_leaf_edge(self) -> Handle, marker::Edge> { + match self.force() { + Leaf(leaf_kv) => leaf_kv.right_edge(), + Internal(internal_kv) => { + let next_internal_edge = internal_kv.right_edge(); + next_internal_edge.descend().first_leaf_edge() + } + } + } + + /// Returns the leaf edge closest to a KV for backward navigation. + pub fn next_back_leaf_edge( + self, + ) -> Handle, marker::Edge> { + match self.force() { + Leaf(leaf_kv) => leaf_kv.left_edge(), + Internal(internal_kv) => { + let next_internal_edge = internal_kv.left_edge(); + next_internal_edge.descend().last_leaf_edge() + } + } + } +} + +impl NodeRef { + /// Returns the leaf edge corresponding to the first point at which the + /// given bound is true. + pub fn lower_bound( + self, + mut bound: SearchBound<&Q>, + ) -> Handle, marker::Edge> + where + Q: Ord, + K: Borrow, + { + let mut node = self; + loop { + let (edge, new_bound) = node.find_lower_bound_edge(bound); + match edge.force() { + Leaf(edge) => return edge, + Internal(edge) => { + node = edge.descend(); + bound = new_bound; + } + } + } + } + + /// Returns the leaf edge corresponding to the last point at which the + /// given bound is true. + pub fn upper_bound( + self, + mut bound: SearchBound<&Q>, + ) -> Handle, marker::Edge> + where + Q: Ord, + K: Borrow, + { + let mut node = self; + loop { + let (edge, new_bound) = node.find_upper_bound_edge(bound); + match edge.force() { + Leaf(edge) => return edge, + Internal(edge) => { + node = edge.descend(); + bound = new_bound; + } + } + } + } +} diff --git a/CoqOfRust/alloc/collections/btree/node.rs b/CoqOfRust/alloc/collections/btree/node.rs new file mode 100644 index 000000000..0c93eff0d --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/node.rs @@ -0,0 +1,1860 @@ +// This is an attempt at an implementation following the ideal +// +// ``` +// struct BTreeMap { +// height: usize, +// root: Option>> +// } +// +// struct Node { +// keys: [K; 2 * B - 1], +// vals: [V; 2 * B - 1], +// edges: [if height > 0 { Box> } else { () }; 2 * B], +// parent: Option<(NonNull>, u16)>, +// len: u16, +// } +// ``` +// +// Since Rust doesn't actually have dependent types and polymorphic recursion, +// we make do with lots of unsafety. + +// A major goal of this module is to avoid complexity by treating the tree as a generic (if +// weirdly shaped) container and avoiding dealing with most of the B-Tree invariants. As such, +// this module doesn't care whether the entries are sorted, which nodes can be underfull, or +// even what underfull means. However, we do rely on a few invariants: +// +// - Trees must have uniform depth/height. This means that every path down to a leaf from a +// given node has exactly the same length. +// - A node of length `n` has `n` keys, `n` values, and `n + 1` edges. +// This implies that even an empty node has at least one edge. +// For a leaf node, "having an edge" only means we can identify a position in the node, +// since leaf edges are empty and need no data representation. In an internal node, +// an edge both identifies a position and contains a pointer to a child node. + +use core::marker::PhantomData; +use core::mem::{self, MaybeUninit}; +use core::ptr::{self, NonNull}; +use core::slice::SliceIndex; + +use crate::alloc::{Allocator, Layout}; +use crate::boxed::Box; + +const B: usize = 6; +pub const CAPACITY: usize = 2 * B - 1; +pub const MIN_LEN_AFTER_SPLIT: usize = B - 1; +const KV_IDX_CENTER: usize = B - 1; +const EDGE_IDX_LEFT_OF_CENTER: usize = B - 1; +const EDGE_IDX_RIGHT_OF_CENTER: usize = B; + +/// The underlying representation of leaf nodes and part of the representation of internal nodes. +struct LeafNode { + /// We want to be covariant in `K` and `V`. + parent: Option>>, + + /// This node's index into the parent node's `edges` array. + /// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`. + /// This is only guaranteed to be initialized when `parent` is non-null. + parent_idx: MaybeUninit, + + /// The number of keys and values this node stores. + len: u16, + + /// The arrays storing the actual data of the node. Only the first `len` elements of each + /// array are initialized and valid. + keys: [MaybeUninit; CAPACITY], + vals: [MaybeUninit; CAPACITY], +} + +impl LeafNode { + /// Initializes a new `LeafNode` in-place. + unsafe fn init(this: *mut Self) { + // As a general policy, we leave fields uninitialized if they can be, as this should + // be both slightly faster and easier to track in Valgrind. + unsafe { + // parent_idx, keys, and vals are all MaybeUninit + (&raw mut (*this).parent).write(None); + (&raw mut (*this).len).write(0); + } + } + + /// Creates a new boxed `LeafNode`. + fn new(alloc: A) -> Box { + unsafe { + let mut leaf = Box::new_uninit_in(alloc); + LeafNode::init(leaf.as_mut_ptr()); + leaf.assume_init() + } + } +} + +/// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden +/// behind `BoxedNode`s to prevent dropping uninitialized keys and values. Any pointer to an +/// `InternalNode` can be directly cast to a pointer to the underlying `LeafNode` portion of the +/// node, allowing code to act on leaf and internal nodes generically without having to even check +/// which of the two a pointer is pointing at. This property is enabled by the use of `repr(C)`. +#[repr(C)] +// gdb_providers.py uses this type name for introspection. +struct InternalNode { + data: LeafNode, + + /// The pointers to the children of this node. `len + 1` of these are considered + /// initialized and valid, except that near the end, while the tree is held + /// through borrow type `Dying`, some of these pointers are dangling. + edges: [MaybeUninit>; 2 * B], +} + +impl InternalNode { + /// Creates a new boxed `InternalNode`. + /// + /// # Safety + /// An invariant of internal nodes is that they have at least one + /// initialized and valid edge. This function does not set up + /// such an edge. + unsafe fn new(alloc: A) -> Box { + unsafe { + let mut node = Box::::new_uninit_in(alloc); + // We only need to initialize the data; the edges are MaybeUninit. + LeafNode::init(&raw mut (*node.as_mut_ptr()).data); + node.assume_init() + } + } +} + +/// A managed, non-null pointer to a node. This is either an owned pointer to +/// `LeafNode` or an owned pointer to `InternalNode`. +/// +/// However, `BoxedNode` contains no information as to which of the two types +/// of nodes it actually contains, and, partially due to this lack of information, +/// is not a separate type and has no destructor. +type BoxedNode = NonNull>; + +// N.B. `NodeRef` is always covariant in `K` and `V`, even when the `BorrowType` +// is `Mut`. This is technically wrong, but cannot result in any unsafety due to +// internal use of `NodeRef` because we stay completely generic over `K` and `V`. +// However, whenever a public type wraps `NodeRef`, make sure that it has the +// correct variance. +/// +/// A reference to a node. +/// +/// This type has a number of parameters that controls how it acts: +/// - `BorrowType`: A dummy type that describes the kind of borrow and carries a lifetime. +/// - When this is `Immut<'a>`, the `NodeRef` acts roughly like `&'a Node`. +/// - When this is `ValMut<'a>`, the `NodeRef` acts roughly like `&'a Node` +/// with respect to keys and tree structure, but also allows many +/// mutable references to values throughout the tree to coexist. +/// - When this is `Mut<'a>`, the `NodeRef` acts roughly like `&'a mut Node`, +/// although insert methods allow a mutable pointer to a value to coexist. +/// - When this is `Owned`, the `NodeRef` acts roughly like `Box`, +/// but does not have a destructor, and must be cleaned up manually. +/// - When this is `Dying`, the `NodeRef` still acts roughly like `Box`, +/// but has methods to destroy the tree bit by bit, and ordinary methods, +/// while not marked as unsafe to call, can invoke UB if called incorrectly. +/// Since any `NodeRef` allows navigating through the tree, `BorrowType` +/// effectively applies to the entire tree, not just to the node itself. +/// - `K` and `V`: These are the types of keys and values stored in the nodes. +/// - `Type`: This can be `Leaf`, `Internal`, or `LeafOrInternal`. When this is +/// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the +/// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the +/// `NodeRef` could be pointing to either type of node. +/// `Type` is named `NodeType` when used outside `NodeRef`. +/// +/// Both `BorrowType` and `NodeType` restrict what methods we implement, to +/// exploit static type safety. There are limitations in the way we can apply +/// such restrictions: +/// - For each type parameter, we can only define a method either generically +/// or for one particular type. For example, we cannot define a method like +/// `into_kv` generically for all `BorrowType`, or once for all types that +/// carry a lifetime, because we want it to return `&'a` references. +/// Therefore, we define it only for the least powerful type `Immut<'a>`. +/// - We cannot get implicit coercion from say `Mut<'a>` to `Immut<'a>`. +/// Therefore, we have to explicitly call `reborrow` on a more powerful +/// `NodeRef` in order to reach a method like `into_kv`. +/// +/// All methods on `NodeRef` that return some kind of reference, either: +/// - Take `self` by value, and return the lifetime carried by `BorrowType`. +/// Sometimes, to invoke such a method, we need to call `reborrow_mut`. +/// - Take `self` by reference, and (implicitly) return that reference's +/// lifetime, instead of the lifetime carried by `BorrowType`. That way, +/// the borrow checker guarantees that the `NodeRef` remains borrowed as long +/// as the returned reference is used. +/// The methods supporting insert bend this rule by returning a raw pointer, +/// i.e., a reference without any lifetime. +pub struct NodeRef { + /// The number of levels that the node and the level of leaves are apart, a + /// constant of the node that cannot be entirely described by `Type`, and that + /// the node itself does not store. We only need to store the height of the root + /// node, and derive every other node's height from it. + /// Must be zero if `Type` is `Leaf` and non-zero if `Type` is `Internal`. + height: usize, + /// The pointer to the leaf or internal node. The definition of `InternalNode` + /// ensures that the pointer is valid either way. + node: NonNull>, + _marker: PhantomData<(BorrowType, Type)>, +} + +/// The root node of an owned tree. +/// +/// Note that this does not have a destructor, and must be cleaned up manually. +pub type Root = NodeRef; + +impl<'a, K: 'a, V: 'a, Type> Copy for NodeRef, K, V, Type> {} +impl<'a, K: 'a, V: 'a, Type> Clone for NodeRef, K, V, Type> { + fn clone(&self) -> Self { + *self + } +} + +unsafe impl Sync for NodeRef {} + +unsafe impl Send for NodeRef, K, V, Type> {} +unsafe impl Send for NodeRef, K, V, Type> {} +unsafe impl Send for NodeRef, K, V, Type> {} +unsafe impl Send for NodeRef {} +unsafe impl Send for NodeRef {} + +impl NodeRef { + pub fn new_leaf(alloc: A) -> Self { + Self::from_new_leaf(LeafNode::new(alloc)) + } + + fn from_new_leaf(leaf: Box, A>) -> Self { + NodeRef { height: 0, node: NonNull::from(Box::leak(leaf)), _marker: PhantomData } + } +} + +impl NodeRef { + fn new_internal(child: Root, alloc: A) -> Self { + let mut new_node = unsafe { InternalNode::new(alloc) }; + new_node.edges[0].write(child.node); + unsafe { NodeRef::from_new_internal(new_node, child.height + 1) } + } + + /// # Safety + /// `height` must not be zero. + unsafe fn from_new_internal( + internal: Box, A>, + height: usize, + ) -> Self { + debug_assert!(height > 0); + let node = NonNull::from(Box::leak(internal)).cast(); + let mut this = NodeRef { height, node, _marker: PhantomData }; + this.borrow_mut().correct_all_childrens_parent_links(); + this + } +} + +impl NodeRef { + /// Unpack a node reference that was packed as `NodeRef::parent`. + fn from_internal(node: NonNull>, height: usize) -> Self { + debug_assert!(height > 0); + NodeRef { height, node: node.cast(), _marker: PhantomData } + } +} + +impl NodeRef { + /// Exposes the data of an internal node. + /// + /// Returns a raw ptr to avoid invalidating other references to this node. + fn as_internal_ptr(this: &Self) -> *mut InternalNode { + // SAFETY: the static node type is `Internal`. + this.node.as_ptr() as *mut InternalNode + } +} + +impl<'a, K, V> NodeRef, K, V, marker::Internal> { + /// Borrows exclusive access to the data of an internal node. + fn as_internal_mut(&mut self) -> &mut InternalNode { + let ptr = Self::as_internal_ptr(self); + unsafe { &mut *ptr } + } +} + +impl NodeRef { + /// Finds the length of the node. This is the number of keys or values. + /// The number of edges is `len() + 1`. + /// Note that, despite being safe, calling this function can have the side effect + /// of invalidating mutable references that unsafe code has created. + pub fn len(&self) -> usize { + // Crucially, we only access the `len` field here. If BorrowType is marker::ValMut, + // there might be outstanding mutable references to values that we must not invalidate. + unsafe { usize::from((*Self::as_leaf_ptr(self)).len) } + } + + /// Returns the number of levels that the node and leaves are apart. Zero + /// height means the node is a leaf itself. If you picture trees with the + /// root on top, the number says at which elevation the node appears. + /// If you picture trees with leaves on top, the number says how high + /// the tree extends above the node. + pub fn height(&self) -> usize { + self.height + } + + /// Temporarily takes out another, immutable reference to the same node. + pub fn reborrow(&self) -> NodeRef, K, V, Type> { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Exposes the leaf portion of any leaf or internal node. + /// + /// Returns a raw ptr to avoid invalidating other references to this node. + fn as_leaf_ptr(this: &Self) -> *mut LeafNode { + // The node must be valid for at least the LeafNode portion. + // This is not a reference in the NodeRef type because we don't know if + // it should be unique or shared. + this.node.as_ptr() + } +} + +impl NodeRef { + /// Finds the parent of the current node. Returns `Ok(handle)` if the current + /// node actually has a parent, where `handle` points to the edge of the parent + /// that points to the current node. Returns `Err(self)` if the current node has + /// no parent, giving back the original `NodeRef`. + /// + /// The method name assumes you picture trees with the root node on top. + /// + /// `edge.descend().ascend().unwrap()` and `node.ascend().unwrap().descend()` should + /// both, upon success, do nothing. + pub fn ascend( + self, + ) -> Result, marker::Edge>, Self> { + const { + assert!(BorrowType::TRAVERSAL_PERMIT); + } + + // We need to use raw pointers to nodes because, if BorrowType is marker::ValMut, + // there might be outstanding mutable references to values that we must not invalidate. + let leaf_ptr: *const _ = Self::as_leaf_ptr(&self); + unsafe { (*leaf_ptr).parent } + .as_ref() + .map(|parent| Handle { + node: NodeRef::from_internal(*parent, self.height + 1), + idx: unsafe { usize::from((*leaf_ptr).parent_idx.assume_init()) }, + _marker: PhantomData, + }) + .ok_or(self) + } + + pub fn first_edge(self) -> Handle { + unsafe { Handle::new_edge(self, 0) } + } + + pub fn last_edge(self) -> Handle { + let len = self.len(); + unsafe { Handle::new_edge(self, len) } + } + + /// Note that `self` must be nonempty. + pub fn first_kv(self) -> Handle { + let len = self.len(); + assert!(len > 0); + unsafe { Handle::new_kv(self, 0) } + } + + /// Note that `self` must be nonempty. + pub fn last_kv(self) -> Handle { + let len = self.len(); + assert!(len > 0); + unsafe { Handle::new_kv(self, len - 1) } + } +} + +impl NodeRef { + /// Could be a public implementation of PartialEq, but only used in this module. + fn eq(&self, other: &Self) -> bool { + let Self { node, height, _marker } = self; + if node.eq(&other.node) { + debug_assert_eq!(*height, other.height); + true + } else { + false + } + } +} + +impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { + /// Exposes the leaf portion of any leaf or internal node in an immutable tree. + fn into_leaf(self) -> &'a LeafNode { + let ptr = Self::as_leaf_ptr(&self); + // SAFETY: there can be no mutable references into this tree borrowed as `Immut`. + unsafe { &*ptr } + } + + /// Borrows a view into the keys stored in the node. + pub fn keys(&self) -> &[K] { + let leaf = self.into_leaf(); + unsafe { + MaybeUninit::slice_assume_init_ref(leaf.keys.get_unchecked(..usize::from(leaf.len))) + } + } +} + +impl NodeRef { + /// Similar to `ascend`, gets a reference to a node's parent node, but also + /// deallocates the current node in the process. This is unsafe because the + /// current node will still be accessible despite being deallocated. + pub unsafe fn deallocate_and_ascend( + self, + alloc: A, + ) -> Option, marker::Edge>> { + let height = self.height; + let node = self.node; + let ret = self.ascend().ok(); + unsafe { + alloc.deallocate( + node.cast(), + if height > 0 { + Layout::new::>() + } else { + Layout::new::>() + }, + ); + } + ret + } +} + +impl<'a, K, V, Type> NodeRef, K, V, Type> { + /// Temporarily takes out another mutable reference to the same node. Beware, as + /// this method is very dangerous, doubly so since it might not immediately appear + /// dangerous. + /// + /// Because mutable pointers can roam anywhere around the tree, the returned + /// pointer can easily be used to make the original pointer dangling, out of + /// bounds, or invalid under stacked borrow rules. + // FIXME(@gereeter) consider adding yet another type parameter to `NodeRef` + // that restricts the use of navigation methods on reborrowed pointers, + // preventing this unsafety. + unsafe fn reborrow_mut(&mut self) -> NodeRef, K, V, Type> { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Borrows exclusive access to the leaf portion of a leaf or internal node. + fn as_leaf_mut(&mut self) -> &mut LeafNode { + let ptr = Self::as_leaf_ptr(self); + // SAFETY: we have exclusive access to the entire node. + unsafe { &mut *ptr } + } + + /// Offers exclusive access to the leaf portion of a leaf or internal node. + fn into_leaf_mut(mut self) -> &'a mut LeafNode { + let ptr = Self::as_leaf_ptr(&mut self); + // SAFETY: we have exclusive access to the entire node. + unsafe { &mut *ptr } + } + + /// Returns a dormant copy of this node with its lifetime erased which can + /// be reawakened later. + pub fn dormant(&self) -> NodeRef { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + +impl NodeRef { + /// Revert to the unique borrow initially captured. + /// + /// # Safety + /// + /// The reborrow must have ended, i.e., the reference returned by `new` and + /// all pointers and references derived from it, must not be used anymore. + pub unsafe fn awaken<'a>(self) -> NodeRef, K, V, Type> { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + +impl NodeRef { + /// Borrows exclusive access to the leaf portion of a dying leaf or internal node. + fn as_leaf_dying(&mut self) -> &mut LeafNode { + let ptr = Self::as_leaf_ptr(self); + // SAFETY: we have exclusive access to the entire node. + unsafe { &mut *ptr } + } +} + +impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { + /// Borrows exclusive access to an element of the key storage area. + /// + /// # Safety + /// `index` is in bounds of 0..CAPACITY + unsafe fn key_area_mut(&mut self, index: I) -> &mut Output + where + I: SliceIndex<[MaybeUninit], Output = Output>, + { + // SAFETY: the caller will not be able to call further methods on self + // until the key slice reference is dropped, as we have unique access + // for the lifetime of the borrow. + unsafe { self.as_leaf_mut().keys.as_mut_slice().get_unchecked_mut(index) } + } + + /// Borrows exclusive access to an element or slice of the node's value storage area. + /// + /// # Safety + /// `index` is in bounds of 0..CAPACITY + unsafe fn val_area_mut(&mut self, index: I) -> &mut Output + where + I: SliceIndex<[MaybeUninit], Output = Output>, + { + // SAFETY: the caller will not be able to call further methods on self + // until the value slice reference is dropped, as we have unique access + // for the lifetime of the borrow. + unsafe { self.as_leaf_mut().vals.as_mut_slice().get_unchecked_mut(index) } + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { + /// Borrows exclusive access to an element or slice of the node's storage area for edge contents. + /// + /// # Safety + /// `index` is in bounds of 0..CAPACITY + 1 + unsafe fn edge_area_mut(&mut self, index: I) -> &mut Output + where + I: SliceIndex<[MaybeUninit>], Output = Output>, + { + // SAFETY: the caller will not be able to call further methods on self + // until the edge slice reference is dropped, as we have unique access + // for the lifetime of the borrow. + unsafe { self.as_internal_mut().edges.as_mut_slice().get_unchecked_mut(index) } + } +} + +impl<'a, K, V, Type> NodeRef, K, V, Type> { + /// # Safety + /// - The node has more than `idx` initialized elements. + unsafe fn into_key_val_mut_at(mut self, idx: usize) -> (&'a K, &'a mut V) { + // We only create a reference to the one element we are interested in, + // to avoid aliasing with outstanding references to other elements, + // in particular, those returned to the caller in earlier iterations. + let leaf = Self::as_leaf_ptr(&mut self); + let keys = unsafe { &raw const (*leaf).keys }; + let vals = unsafe { &raw mut (*leaf).vals }; + // We must coerce to unsized array pointers because of Rust issue #74679. + let keys: *const [_] = keys; + let vals: *mut [_] = vals; + let key = unsafe { (&*keys.get_unchecked(idx)).assume_init_ref() }; + let val = unsafe { (&mut *vals.get_unchecked_mut(idx)).assume_init_mut() }; + (key, val) + } +} + +impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { + /// Borrows exclusive access to the length of the node. + pub fn len_mut(&mut self) -> &mut u16 { + &mut self.as_leaf_mut().len + } +} + +impl<'a, K, V> NodeRef, K, V, marker::Internal> { + /// # Safety + /// Every item returned by `range` is a valid edge index for the node. + unsafe fn correct_childrens_parent_links>(&mut self, range: R) { + for i in range { + debug_assert!(i <= self.len()); + unsafe { Handle::new_edge(self.reborrow_mut(), i) }.correct_parent_link(); + } + } + + fn correct_all_childrens_parent_links(&mut self) { + let len = self.len(); + unsafe { self.correct_childrens_parent_links(0..=len) }; + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + /// Sets the node's link to its parent edge, + /// without invalidating other references to the node. + fn set_parent_link(&mut self, parent: NonNull>, parent_idx: usize) { + let leaf = Self::as_leaf_ptr(self); + unsafe { (*leaf).parent = Some(parent) }; + unsafe { (*leaf).parent_idx.write(parent_idx as u16) }; + } +} + +impl NodeRef { + /// Clears the root's link to its parent edge. + fn clear_parent_link(&mut self) { + let mut root_node = self.borrow_mut(); + let leaf = root_node.as_leaf_mut(); + leaf.parent = None; + } +} + +impl NodeRef { + /// Returns a new owned tree, with its own root node that is initially empty. + pub fn new(alloc: A) -> Self { + NodeRef::new_leaf(alloc).forget_type() + } + + /// Adds a new internal node with a single edge pointing to the previous root node, + /// make that new node the root node, and return it. This increases the height by 1 + /// and is the opposite of `pop_internal_level`. + pub fn push_internal_level( + &mut self, + alloc: A, + ) -> NodeRef, K, V, marker::Internal> { + super::mem::take_mut(self, |old_root| NodeRef::new_internal(old_root, alloc).forget_type()); + + // `self.borrow_mut()`, except that we just forgot we're internal now: + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Removes the internal root node, using its first child as the new root node. + /// As it is intended only to be called when the root node has only one child, + /// no cleanup is done on any of the keys, values and other children. + /// This decreases the height by 1 and is the opposite of `push_internal_level`. + /// + /// Requires exclusive access to the `NodeRef` object but not to the root node; + /// it will not invalidate other handles or references to the root node. + /// + /// Panics if there is no internal level, i.e., if the root node is a leaf. + pub fn pop_internal_level(&mut self, alloc: A) { + assert!(self.height > 0); + + let top = self.node; + + // SAFETY: we asserted to be internal. + let internal_self = unsafe { self.borrow_mut().cast_to_internal_unchecked() }; + // SAFETY: we borrowed `self` exclusively and its borrow type is exclusive. + let internal_node = unsafe { &mut *NodeRef::as_internal_ptr(&internal_self) }; + // SAFETY: the first edge is always initialized. + self.node = unsafe { internal_node.edges[0].assume_init_read() }; + self.height -= 1; + self.clear_parent_link(); + + unsafe { + alloc.deallocate(top.cast(), Layout::new::>()); + } + } +} + +impl NodeRef { + /// Mutably borrows the owned root node. Unlike `reborrow_mut`, this is safe + /// because the return value cannot be used to destroy the root, and there + /// cannot be other references to the tree. + pub fn borrow_mut(&mut self) -> NodeRef, K, V, Type> { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Slightly mutably borrows the owned root node. + pub fn borrow_valmut(&mut self) -> NodeRef, K, V, Type> { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Irreversibly transitions to a reference that permits traversal and offers + /// destructive methods and little else. + pub fn into_dying(self) -> NodeRef { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Leaf> { + /// Adds a key-value pair to the end of the node, and returns + /// a handle to the inserted value. + /// + /// # Safety + /// + /// The returned handle has an unbound lifetime. + pub unsafe fn push_with_handle<'b>( + &mut self, + key: K, + val: V, + ) -> Handle, K, V, marker::Leaf>, marker::KV> { + let len = self.len_mut(); + let idx = usize::from(*len); + assert!(idx < CAPACITY); + *len += 1; + unsafe { + self.key_area_mut(idx).write(key); + self.val_area_mut(idx).write(val); + Handle::new_kv( + NodeRef { height: self.height, node: self.node, _marker: PhantomData }, + idx, + ) + } + } + + /// Adds a key-value pair to the end of the node, and returns + /// the mutable reference of the inserted value. + pub fn push(&mut self, key: K, val: V) -> *mut V { + // SAFETY: The unbound handle is no longer accessible. + unsafe { self.push_with_handle(key, val).into_val_mut() } + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { + /// Adds a key-value pair, and an edge to go to the right of that pair, + /// to the end of the node. + pub fn push(&mut self, key: K, val: V, edge: Root) { + assert!(edge.height == self.height - 1); + + let len = self.len_mut(); + let idx = usize::from(*len); + assert!(idx < CAPACITY); + *len += 1; + unsafe { + self.key_area_mut(idx).write(key); + self.val_area_mut(idx).write(val); + self.edge_area_mut(idx + 1).write(edge.node); + Handle::new_edge(self.reborrow_mut(), idx + 1).correct_parent_link(); + } + } +} + +impl NodeRef { + /// Removes any static information asserting that this node is a `Leaf` node. + pub fn forget_type(self) -> NodeRef { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + +impl NodeRef { + /// Removes any static information asserting that this node is an `Internal` node. + pub fn forget_type(self) -> NodeRef { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + +impl NodeRef { + /// Checks whether a node is an `Internal` node or a `Leaf` node. + pub fn force( + self, + ) -> ForceResult< + NodeRef, + NodeRef, + > { + if self.height == 0 { + ForceResult::Leaf(NodeRef { + height: self.height, + node: self.node, + _marker: PhantomData, + }) + } else { + ForceResult::Internal(NodeRef { + height: self.height, + node: self.node, + _marker: PhantomData, + }) + } + } +} + +impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { + /// Unsafely asserts to the compiler the static information that this node is a `Leaf`. + pub unsafe fn cast_to_leaf_unchecked(self) -> NodeRef, K, V, marker::Leaf> { + debug_assert!(self.height == 0); + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Unsafely asserts to the compiler the static information that this node is an `Internal`. + unsafe fn cast_to_internal_unchecked(self) -> NodeRef, K, V, marker::Internal> { + debug_assert!(self.height > 0); + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + +/// A reference to a specific key-value pair or edge within a node. The `Node` parameter +/// must be a `NodeRef`, while the `Type` can either be `KV` (signifying a handle on a key-value +/// pair) or `Edge` (signifying a handle on an edge). +/// +/// Note that even `Leaf` nodes can have `Edge` handles. Instead of representing a pointer to +/// a child node, these represent the spaces where child pointers would go between the key-value +/// pairs. For example, in a node with length 2, there would be 3 possible edge locations - one +/// to the left of the node, one between the two pairs, and one at the right of the node. +pub struct Handle { + node: Node, + idx: usize, + _marker: PhantomData, +} + +impl Copy for Handle {} +// We don't need the full generality of `#[derive(Clone)]`, as the only time `Node` will be +// `Clone`able is when it is an immutable reference and therefore `Copy`. +impl Clone for Handle { + fn clone(&self) -> Self { + *self + } +} + +impl Handle { + /// Retrieves the node that contains the edge or key-value pair this handle points to. + pub fn into_node(self) -> Node { + self.node + } + + /// Returns the position of this handle in the node. + pub fn idx(&self) -> usize { + self.idx + } +} + +impl Handle, marker::KV> { + /// Creates a new handle to a key-value pair in `node`. + /// Unsafe because the caller must ensure that `idx < node.len()`. + pub unsafe fn new_kv(node: NodeRef, idx: usize) -> Self { + debug_assert!(idx < node.len()); + + Handle { node, idx, _marker: PhantomData } + } + + pub fn left_edge(self) -> Handle, marker::Edge> { + unsafe { Handle::new_edge(self.node, self.idx) } + } + + pub fn right_edge(self) -> Handle, marker::Edge> { + unsafe { Handle::new_edge(self.node, self.idx + 1) } + } +} + +impl PartialEq + for Handle, HandleType> +{ + fn eq(&self, other: &Self) -> bool { + let Self { node, idx, _marker } = self; + node.eq(&other.node) && *idx == other.idx + } +} + +impl + Handle, HandleType> +{ + /// Temporarily takes out another immutable handle on the same location. + pub fn reborrow(&self) -> Handle, K, V, NodeType>, HandleType> { + // We can't use Handle::new_kv or Handle::new_edge because we don't know our type + Handle { node: self.node.reborrow(), idx: self.idx, _marker: PhantomData } + } +} + +impl<'a, K, V, NodeType, HandleType> Handle, K, V, NodeType>, HandleType> { + /// Temporarily takes out another mutable handle on the same location. Beware, as + /// this method is very dangerous, doubly so since it might not immediately appear + /// dangerous. + /// + /// For details, see `NodeRef::reborrow_mut`. + pub unsafe fn reborrow_mut( + &mut self, + ) -> Handle, K, V, NodeType>, HandleType> { + // We can't use Handle::new_kv or Handle::new_edge because we don't know our type + Handle { node: unsafe { self.node.reborrow_mut() }, idx: self.idx, _marker: PhantomData } + } + + /// Returns a dormant copy of this handle which can be reawakened later. + /// + /// See `DormantMutRef` for more details. + pub fn dormant(&self) -> Handle, HandleType> { + Handle { node: self.node.dormant(), idx: self.idx, _marker: PhantomData } + } +} + +impl Handle, HandleType> { + /// Revert to the unique borrow initially captured. + /// + /// # Safety + /// + /// The reborrow must have ended, i.e., the reference returned by `new` and + /// all pointers and references derived from it, must not be used anymore. + pub unsafe fn awaken<'a>(self) -> Handle, K, V, NodeType>, HandleType> { + Handle { node: unsafe { self.node.awaken() }, idx: self.idx, _marker: PhantomData } + } +} + +impl Handle, marker::Edge> { + /// Creates a new handle to an edge in `node`. + /// Unsafe because the caller must ensure that `idx <= node.len()`. + pub unsafe fn new_edge(node: NodeRef, idx: usize) -> Self { + debug_assert!(idx <= node.len()); + + Handle { node, idx, _marker: PhantomData } + } + + pub fn left_kv(self) -> Result, marker::KV>, Self> { + if self.idx > 0 { + Ok(unsafe { Handle::new_kv(self.node, self.idx - 1) }) + } else { + Err(self) + } + } + + pub fn right_kv(self) -> Result, marker::KV>, Self> { + if self.idx < self.node.len() { + Ok(unsafe { Handle::new_kv(self.node, self.idx) }) + } else { + Err(self) + } + } +} + +pub enum LeftOrRight { + Left(T), + Right(T), +} + +/// Given an edge index where we want to insert into a node filled to capacity, +/// computes a sensible KV index of a split point and where to perform the insertion. +/// The goal of the split point is for its key and value to end up in a parent node; +/// the keys, values and edges to the left of the split point become the left child; +/// the keys, values and edges to the right of the split point become the right child. +fn splitpoint(edge_idx: usize) -> (usize, LeftOrRight) { + debug_assert!(edge_idx <= CAPACITY); + // Rust issue #74834 tries to explain these symmetric rules. + match edge_idx { + 0..EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER - 1, LeftOrRight::Left(edge_idx)), + EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER, LeftOrRight::Left(edge_idx)), + EDGE_IDX_RIGHT_OF_CENTER => (KV_IDX_CENTER, LeftOrRight::Right(0)), + _ => (KV_IDX_CENTER + 1, LeftOrRight::Right(edge_idx - (KV_IDX_CENTER + 1 + 1))), + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, marker::Edge> { + /// Inserts a new key-value pair between the key-value pairs to the right and left of + /// this edge. This method assumes that there is enough space in the node for the new + /// pair to fit. + unsafe fn insert_fit( + mut self, + key: K, + val: V, + ) -> Handle, K, V, marker::Leaf>, marker::KV> { + debug_assert!(self.node.len() < CAPACITY); + let new_len = self.node.len() + 1; + + unsafe { + slice_insert(self.node.key_area_mut(..new_len), self.idx, key); + slice_insert(self.node.val_area_mut(..new_len), self.idx, val); + *self.node.len_mut() = new_len as u16; + + Handle::new_kv(self.node, self.idx) + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, marker::Edge> { + /// Inserts a new key-value pair between the key-value pairs to the right and left of + /// this edge. This method splits the node if there isn't enough room. + /// + /// Returns a dormant handle to the inserted node which can be reawakened + /// once splitting is complete. + fn insert( + self, + key: K, + val: V, + alloc: A, + ) -> ( + Option>, + Handle, marker::KV>, + ) { + if self.node.len() < CAPACITY { + // SAFETY: There is enough space in the node for insertion. + let handle = unsafe { self.insert_fit(key, val) }; + (None, handle.dormant()) + } else { + let (middle_kv_idx, insertion) = splitpoint(self.idx); + let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) }; + let mut result = middle.split(alloc); + let insertion_edge = match insertion { + LeftOrRight::Left(insert_idx) => unsafe { + Handle::new_edge(result.left.reborrow_mut(), insert_idx) + }, + LeftOrRight::Right(insert_idx) => unsafe { + Handle::new_edge(result.right.borrow_mut(), insert_idx) + }, + }; + // SAFETY: We just split the node, so there is enough space for + // insertion. + let handle = unsafe { insertion_edge.insert_fit(key, val).dormant() }; + (Some(result), handle) + } + } +} + +impl<'a, K, V> Handle, K, V, marker::Internal>, marker::Edge> { + /// Fixes the parent pointer and index in the child node that this edge + /// links to. This is useful when the ordering of edges has been changed, + fn correct_parent_link(self) { + // Create backpointer without invalidating other references to the node. + let ptr = unsafe { NonNull::new_unchecked(NodeRef::as_internal_ptr(&self.node)) }; + let idx = self.idx; + let mut child = self.descend(); + child.set_parent_link(ptr, idx); + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, marker::Edge> { + /// Inserts a new key-value pair and an edge that will go to the right of that new pair + /// between this edge and the key-value pair to the right of this edge. This method assumes + /// that there is enough space in the node for the new pair to fit. + fn insert_fit(&mut self, key: K, val: V, edge: Root) { + debug_assert!(self.node.len() < CAPACITY); + debug_assert!(edge.height == self.node.height - 1); + let new_len = self.node.len() + 1; + + unsafe { + slice_insert(self.node.key_area_mut(..new_len), self.idx, key); + slice_insert(self.node.val_area_mut(..new_len), self.idx, val); + slice_insert(self.node.edge_area_mut(..new_len + 1), self.idx + 1, edge.node); + *self.node.len_mut() = new_len as u16; + + self.node.correct_childrens_parent_links(self.idx + 1..new_len + 1); + } + } + + /// Inserts a new key-value pair and an edge that will go to the right of that new pair + /// between this edge and the key-value pair to the right of this edge. This method splits + /// the node if there isn't enough room. + fn insert( + mut self, + key: K, + val: V, + edge: Root, + alloc: A, + ) -> Option> { + assert!(edge.height == self.node.height - 1); + + if self.node.len() < CAPACITY { + self.insert_fit(key, val, edge); + None + } else { + let (middle_kv_idx, insertion) = splitpoint(self.idx); + let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) }; + let mut result = middle.split(alloc); + let mut insertion_edge = match insertion { + LeftOrRight::Left(insert_idx) => unsafe { + Handle::new_edge(result.left.reborrow_mut(), insert_idx) + }, + LeftOrRight::Right(insert_idx) => unsafe { + Handle::new_edge(result.right.borrow_mut(), insert_idx) + }, + }; + insertion_edge.insert_fit(key, val, edge); + Some(result) + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, marker::Edge> { + /// Inserts a new key-value pair between the key-value pairs to the right and left of + /// this edge. This method splits the node if there isn't enough room, and tries to + /// insert the split off portion into the parent node recursively, until the root is reached. + /// + /// If the returned result is some `SplitResult`, the `left` field will be the root node. + /// The returned pointer points to the inserted value, which in the case of `SplitResult` + /// is in the `left` or `right` tree. + pub fn insert_recursing( + self, + key: K, + value: V, + alloc: A, + split_root: impl FnOnce(SplitResult<'a, K, V, marker::LeafOrInternal>), + ) -> Handle, K, V, marker::Leaf>, marker::KV> { + let (mut split, handle) = match self.insert(key, value, alloc.clone()) { + // SAFETY: we have finished splitting and can now re-awaken the + // handle to the inserted element. + (None, handle) => return unsafe { handle.awaken() }, + (Some(split), handle) => (split.forget_node_type(), handle), + }; + + loop { + split = match split.left.ascend() { + Ok(parent) => { + match parent.insert(split.kv.0, split.kv.1, split.right, alloc.clone()) { + // SAFETY: we have finished splitting and can now re-awaken the + // handle to the inserted element. + None => return unsafe { handle.awaken() }, + Some(split) => split.forget_node_type(), + } + } + Err(root) => { + split_root(SplitResult { left: root, ..split }); + // SAFETY: we have finished splitting and can now re-awaken the + // handle to the inserted element. + return unsafe { handle.awaken() }; + } + }; + } + } +} + +impl + Handle, marker::Edge> +{ + /// Finds the node pointed to by this edge. + /// + /// The method name assumes you picture trees with the root node on top. + /// + /// `edge.descend().ascend().unwrap()` and `node.ascend().unwrap().descend()` should + /// both, upon success, do nothing. + pub fn descend(self) -> NodeRef { + const { + assert!(BorrowType::TRAVERSAL_PERMIT); + } + + // We need to use raw pointers to nodes because, if BorrowType is + // marker::ValMut, there might be outstanding mutable references to + // values that we must not invalidate. There's no worry accessing the + // height field because that value is copied. Beware that, once the + // node pointer is dereferenced, we access the edges array with a + // reference (Rust issue #73987) and invalidate any other references + // to or inside the array, should any be around. + let parent_ptr = NodeRef::as_internal_ptr(&self.node); + let node = unsafe { (*parent_ptr).edges.get_unchecked(self.idx).assume_init_read() }; + NodeRef { node, height: self.node.height - 1, _marker: PhantomData } + } +} + +impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { + pub fn into_kv(self) -> (&'a K, &'a V) { + debug_assert!(self.idx < self.node.len()); + let leaf = self.node.into_leaf(); + let k = unsafe { leaf.keys.get_unchecked(self.idx).assume_init_ref() }; + let v = unsafe { leaf.vals.get_unchecked(self.idx).assume_init_ref() }; + (k, v) + } +} + +impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { + pub fn key_mut(&mut self) -> &mut K { + unsafe { self.node.key_area_mut(self.idx).assume_init_mut() } + } + + pub fn into_val_mut(self) -> &'a mut V { + debug_assert!(self.idx < self.node.len()); + let leaf = self.node.into_leaf_mut(); + unsafe { leaf.vals.get_unchecked_mut(self.idx).assume_init_mut() } + } + + pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) { + debug_assert!(self.idx < self.node.len()); + let leaf = self.node.into_leaf_mut(); + let k = unsafe { leaf.keys.get_unchecked_mut(self.idx).assume_init_mut() }; + let v = unsafe { leaf.vals.get_unchecked_mut(self.idx).assume_init_mut() }; + (k, v) + } +} + +impl<'a, K, V, NodeType> Handle, K, V, NodeType>, marker::KV> { + pub fn into_kv_valmut(self) -> (&'a K, &'a mut V) { + unsafe { self.node.into_key_val_mut_at(self.idx) } + } +} + +impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { + pub fn kv_mut(&mut self) -> (&mut K, &mut V) { + debug_assert!(self.idx < self.node.len()); + // We cannot call separate key and value methods, because calling the second one + // invalidates the reference returned by the first. + unsafe { + let leaf = self.node.as_leaf_mut(); + let key = leaf.keys.get_unchecked_mut(self.idx).assume_init_mut(); + let val = leaf.vals.get_unchecked_mut(self.idx).assume_init_mut(); + (key, val) + } + } + + /// Replaces the key and value that the KV handle refers to. + pub fn replace_kv(&mut self, k: K, v: V) -> (K, V) { + let (key, val) = self.kv_mut(); + (mem::replace(key, k), mem::replace(val, v)) + } +} + +impl Handle, marker::KV> { + /// Extracts the key and value that the KV handle refers to. + /// # Safety + /// The node that the handle refers to must not yet have been deallocated. + pub unsafe fn into_key_val(mut self) -> (K, V) { + debug_assert!(self.idx < self.node.len()); + let leaf = self.node.as_leaf_dying(); + unsafe { + let key = leaf.keys.get_unchecked_mut(self.idx).assume_init_read(); + let val = leaf.vals.get_unchecked_mut(self.idx).assume_init_read(); + (key, val) + } + } + + /// Drops the key and value that the KV handle refers to. + /// # Safety + /// The node that the handle refers to must not yet have been deallocated. + #[inline] + pub unsafe fn drop_key_val(mut self) { + // Run the destructor of the value even if the destructor of the key panics. + struct Dropper<'a, T>(&'a mut MaybeUninit); + impl Drop for Dropper<'_, T> { + #[inline] + fn drop(&mut self) { + unsafe { + self.0.assume_init_drop(); + } + } + } + + debug_assert!(self.idx < self.node.len()); + let leaf = self.node.as_leaf_dying(); + unsafe { + let key = leaf.keys.get_unchecked_mut(self.idx); + let val = leaf.vals.get_unchecked_mut(self.idx); + let _guard = Dropper(val); + key.assume_init_drop(); + // dropping the guard will drop the value + } + } +} + +impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { + /// Helps implementations of `split` for a particular `NodeType`, + /// by taking care of leaf data. + fn split_leaf_data(&mut self, new_node: &mut LeafNode) -> (K, V) { + debug_assert!(self.idx < self.node.len()); + let old_len = self.node.len(); + let new_len = old_len - self.idx - 1; + new_node.len = new_len as u16; + unsafe { + let k = self.node.key_area_mut(self.idx).assume_init_read(); + let v = self.node.val_area_mut(self.idx).assume_init_read(); + + move_to_slice( + self.node.key_area_mut(self.idx + 1..old_len), + &mut new_node.keys[..new_len], + ); + move_to_slice( + self.node.val_area_mut(self.idx + 1..old_len), + &mut new_node.vals[..new_len], + ); + + *self.node.len_mut() = self.idx as u16; + (k, v) + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, marker::KV> { + /// Splits the underlying node into three parts: + /// + /// - The node is truncated to only contain the key-value pairs to the left of + /// this handle. + /// - The key and value pointed to by this handle are extracted. + /// - All the key-value pairs to the right of this handle are put into a newly + /// allocated node. + pub fn split(mut self, alloc: A) -> SplitResult<'a, K, V, marker::Leaf> { + let mut new_node = LeafNode::new(alloc); + + let kv = self.split_leaf_data(&mut new_node); + + let right = NodeRef::from_new_leaf(new_node); + SplitResult { left: self.node, kv, right } + } + + /// Removes the key-value pair pointed to by this handle and returns it, along with the edge + /// that the key-value pair collapsed into. + pub fn remove( + mut self, + ) -> ((K, V), Handle, K, V, marker::Leaf>, marker::Edge>) { + let old_len = self.node.len(); + unsafe { + let k = slice_remove(self.node.key_area_mut(..old_len), self.idx); + let v = slice_remove(self.node.val_area_mut(..old_len), self.idx); + *self.node.len_mut() = (old_len - 1) as u16; + ((k, v), self.left_edge()) + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, marker::KV> { + /// Splits the underlying node into three parts: + /// + /// - The node is truncated to only contain the edges and key-value pairs to the + /// left of this handle. + /// - The key and value pointed to by this handle are extracted. + /// - All the edges and key-value pairs to the right of this handle are put into + /// a newly allocated node. + pub fn split( + mut self, + alloc: A, + ) -> SplitResult<'a, K, V, marker::Internal> { + let old_len = self.node.len(); + unsafe { + let mut new_node = InternalNode::new(alloc); + let kv = self.split_leaf_data(&mut new_node.data); + let new_len = usize::from(new_node.data.len); + move_to_slice( + self.node.edge_area_mut(self.idx + 1..old_len + 1), + &mut new_node.edges[..new_len + 1], + ); + + let height = self.node.height; + let right = NodeRef::from_new_internal(new_node, height); + + SplitResult { left: self.node, kv, right } + } + } +} + +/// Represents a session for evaluating and performing a balancing operation +/// around an internal key-value pair. +pub struct BalancingContext<'a, K, V> { + parent: Handle, K, V, marker::Internal>, marker::KV>, + left_child: NodeRef, K, V, marker::LeafOrInternal>, + right_child: NodeRef, K, V, marker::LeafOrInternal>, +} + +impl<'a, K, V> Handle, K, V, marker::Internal>, marker::KV> { + pub fn consider_for_balancing(self) -> BalancingContext<'a, K, V> { + let self1 = unsafe { ptr::read(&self) }; + let self2 = unsafe { ptr::read(&self) }; + BalancingContext { + parent: self, + left_child: self1.left_edge().descend(), + right_child: self2.right_edge().descend(), + } + } +} + +impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { + /// Chooses a balancing context involving the node as a child, thus between + /// the KV immediately to the left or to the right in the parent node. + /// Returns an `Err` if there is no parent. + /// Panics if the parent is empty. + /// + /// Prefers the left side, to be optimal if the given node is somehow + /// underfull, meaning here only that it has fewer elements than its left + /// sibling and than its right sibling, if they exist. In that case, + /// merging with the left sibling is faster, since we only need to move + /// the node's N elements, instead of shifting them to the right and moving + /// more than N elements in front. Stealing from the left sibling is also + /// typically faster, since we only need to shift the node's N elements to + /// the right, instead of shifting at least N of the sibling's elements to + /// the left. + pub fn choose_parent_kv(self) -> Result>, Self> { + match unsafe { ptr::read(&self) }.ascend() { + Ok(parent_edge) => match parent_edge.left_kv() { + Ok(left_parent_kv) => Ok(LeftOrRight::Left(BalancingContext { + parent: unsafe { ptr::read(&left_parent_kv) }, + left_child: left_parent_kv.left_edge().descend(), + right_child: self, + })), + Err(parent_edge) => match parent_edge.right_kv() { + Ok(right_parent_kv) => Ok(LeftOrRight::Right(BalancingContext { + parent: unsafe { ptr::read(&right_parent_kv) }, + left_child: self, + right_child: right_parent_kv.right_edge().descend(), + })), + Err(_) => unreachable!("empty internal node"), + }, + }, + Err(root) => Err(root), + } + } +} + +impl<'a, K, V> BalancingContext<'a, K, V> { + pub fn left_child_len(&self) -> usize { + self.left_child.len() + } + + pub fn right_child_len(&self) -> usize { + self.right_child.len() + } + + pub fn into_left_child(self) -> NodeRef, K, V, marker::LeafOrInternal> { + self.left_child + } + + pub fn into_right_child(self) -> NodeRef, K, V, marker::LeafOrInternal> { + self.right_child + } + + /// Returns whether merging is possible, i.e., whether there is enough room + /// in a node to combine the central KV with both adjacent child nodes. + pub fn can_merge(&self) -> bool { + self.left_child.len() + 1 + self.right_child.len() <= CAPACITY + } +} + +impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { + /// Performs a merge and lets a closure decide what to return. + fn do_merge< + F: FnOnce( + NodeRef, K, V, marker::Internal>, + NodeRef, K, V, marker::LeafOrInternal>, + ) -> R, + R, + A: Allocator, + >( + self, + result: F, + alloc: A, + ) -> R { + let Handle { node: mut parent_node, idx: parent_idx, _marker } = self.parent; + let old_parent_len = parent_node.len(); + let mut left_node = self.left_child; + let old_left_len = left_node.len(); + let mut right_node = self.right_child; + let right_len = right_node.len(); + let new_left_len = old_left_len + 1 + right_len; + + assert!(new_left_len <= CAPACITY); + + unsafe { + *left_node.len_mut() = new_left_len as u16; + + let parent_key = slice_remove(parent_node.key_area_mut(..old_parent_len), parent_idx); + left_node.key_area_mut(old_left_len).write(parent_key); + move_to_slice( + right_node.key_area_mut(..right_len), + left_node.key_area_mut(old_left_len + 1..new_left_len), + ); + + let parent_val = slice_remove(parent_node.val_area_mut(..old_parent_len), parent_idx); + left_node.val_area_mut(old_left_len).write(parent_val); + move_to_slice( + right_node.val_area_mut(..right_len), + left_node.val_area_mut(old_left_len + 1..new_left_len), + ); + + slice_remove(&mut parent_node.edge_area_mut(..old_parent_len + 1), parent_idx + 1); + parent_node.correct_childrens_parent_links(parent_idx + 1..old_parent_len); + *parent_node.len_mut() -= 1; + + if parent_node.height > 1 { + // SAFETY: the height of the nodes being merged is one below the height + // of the node of this edge, thus above zero, so they are internal. + let mut left_node = left_node.reborrow_mut().cast_to_internal_unchecked(); + let mut right_node = right_node.cast_to_internal_unchecked(); + move_to_slice( + right_node.edge_area_mut(..right_len + 1), + left_node.edge_area_mut(old_left_len + 1..new_left_len + 1), + ); + + left_node.correct_childrens_parent_links(old_left_len + 1..new_left_len + 1); + + alloc.deallocate(right_node.node.cast(), Layout::new::>()); + } else { + alloc.deallocate(right_node.node.cast(), Layout::new::>()); + } + } + result(parent_node, left_node) + } + + /// Merges the parent's key-value pair and both adjacent child nodes into + /// the left child node and returns the shrunk parent node. + /// + /// Panics unless we `.can_merge()`. + pub fn merge_tracking_parent( + self, + alloc: A, + ) -> NodeRef, K, V, marker::Internal> { + self.do_merge(|parent, _child| parent, alloc) + } + + /// Merges the parent's key-value pair and both adjacent child nodes into + /// the left child node and returns that child node. + /// + /// Panics unless we `.can_merge()`. + pub fn merge_tracking_child( + self, + alloc: A, + ) -> NodeRef, K, V, marker::LeafOrInternal> { + self.do_merge(|_parent, child| child, alloc) + } + + /// Merges the parent's key-value pair and both adjacent child nodes into + /// the left child node and returns the edge handle in that child node + /// where the tracked child edge ended up, + /// + /// Panics unless we `.can_merge()`. + pub fn merge_tracking_child_edge( + self, + track_edge_idx: LeftOrRight, + alloc: A, + ) -> Handle, K, V, marker::LeafOrInternal>, marker::Edge> { + let old_left_len = self.left_child.len(); + let right_len = self.right_child.len(); + assert!(match track_edge_idx { + LeftOrRight::Left(idx) => idx <= old_left_len, + LeftOrRight::Right(idx) => idx <= right_len, + }); + let child = self.merge_tracking_child(alloc); + let new_idx = match track_edge_idx { + LeftOrRight::Left(idx) => idx, + LeftOrRight::Right(idx) => old_left_len + 1 + idx, + }; + unsafe { Handle::new_edge(child, new_idx) } + } + + /// Removes a key-value pair from the left child and places it in the key-value storage + /// of the parent, while pushing the old parent key-value pair into the right child. + /// Returns a handle to the edge in the right child corresponding to where the original + /// edge specified by `track_right_edge_idx` ended up. + pub fn steal_left( + mut self, + track_right_edge_idx: usize, + ) -> Handle, K, V, marker::LeafOrInternal>, marker::Edge> { + self.bulk_steal_left(1); + unsafe { Handle::new_edge(self.right_child, 1 + track_right_edge_idx) } + } + + /// Removes a key-value pair from the right child and places it in the key-value storage + /// of the parent, while pushing the old parent key-value pair onto the left child. + /// Returns a handle to the edge in the left child specified by `track_left_edge_idx`, + /// which didn't move. + pub fn steal_right( + mut self, + track_left_edge_idx: usize, + ) -> Handle, K, V, marker::LeafOrInternal>, marker::Edge> { + self.bulk_steal_right(1); + unsafe { Handle::new_edge(self.left_child, track_left_edge_idx) } + } + + /// This does stealing similar to `steal_left` but steals multiple elements at once. + pub fn bulk_steal_left(&mut self, count: usize) { + assert!(count > 0); + unsafe { + let left_node = &mut self.left_child; + let old_left_len = left_node.len(); + let right_node = &mut self.right_child; + let old_right_len = right_node.len(); + + // Make sure that we may steal safely. + assert!(old_right_len + count <= CAPACITY); + assert!(old_left_len >= count); + + let new_left_len = old_left_len - count; + let new_right_len = old_right_len + count; + *left_node.len_mut() = new_left_len as u16; + *right_node.len_mut() = new_right_len as u16; + + // Move leaf data. + { + // Make room for stolen elements in the right child. + slice_shr(right_node.key_area_mut(..new_right_len), count); + slice_shr(right_node.val_area_mut(..new_right_len), count); + + // Move elements from the left child to the right one. + move_to_slice( + left_node.key_area_mut(new_left_len + 1..old_left_len), + right_node.key_area_mut(..count - 1), + ); + move_to_slice( + left_node.val_area_mut(new_left_len + 1..old_left_len), + right_node.val_area_mut(..count - 1), + ); + + // Move the leftmost stolen pair to the parent. + let k = left_node.key_area_mut(new_left_len).assume_init_read(); + let v = left_node.val_area_mut(new_left_len).assume_init_read(); + let (k, v) = self.parent.replace_kv(k, v); + + // Move parent's key-value pair to the right child. + right_node.key_area_mut(count - 1).write(k); + right_node.val_area_mut(count - 1).write(v); + } + + match (left_node.reborrow_mut().force(), right_node.reborrow_mut().force()) { + (ForceResult::Internal(mut left), ForceResult::Internal(mut right)) => { + // Make room for stolen edges. + slice_shr(right.edge_area_mut(..new_right_len + 1), count); + + // Steal edges. + move_to_slice( + left.edge_area_mut(new_left_len + 1..old_left_len + 1), + right.edge_area_mut(..count), + ); + + right.correct_childrens_parent_links(0..new_right_len + 1); + } + (ForceResult::Leaf(_), ForceResult::Leaf(_)) => {} + _ => unreachable!(), + } + } + } + + /// The symmetric clone of `bulk_steal_left`. + pub fn bulk_steal_right(&mut self, count: usize) { + assert!(count > 0); + unsafe { + let left_node = &mut self.left_child; + let old_left_len = left_node.len(); + let right_node = &mut self.right_child; + let old_right_len = right_node.len(); + + // Make sure that we may steal safely. + assert!(old_left_len + count <= CAPACITY); + assert!(old_right_len >= count); + + let new_left_len = old_left_len + count; + let new_right_len = old_right_len - count; + *left_node.len_mut() = new_left_len as u16; + *right_node.len_mut() = new_right_len as u16; + + // Move leaf data. + { + // Move the rightmost stolen pair to the parent. + let k = right_node.key_area_mut(count - 1).assume_init_read(); + let v = right_node.val_area_mut(count - 1).assume_init_read(); + let (k, v) = self.parent.replace_kv(k, v); + + // Move parent's key-value pair to the left child. + left_node.key_area_mut(old_left_len).write(k); + left_node.val_area_mut(old_left_len).write(v); + + // Move elements from the right child to the left one. + move_to_slice( + right_node.key_area_mut(..count - 1), + left_node.key_area_mut(old_left_len + 1..new_left_len), + ); + move_to_slice( + right_node.val_area_mut(..count - 1), + left_node.val_area_mut(old_left_len + 1..new_left_len), + ); + + // Fill gap where stolen elements used to be. + slice_shl(right_node.key_area_mut(..old_right_len), count); + slice_shl(right_node.val_area_mut(..old_right_len), count); + } + + match (left_node.reborrow_mut().force(), right_node.reborrow_mut().force()) { + (ForceResult::Internal(mut left), ForceResult::Internal(mut right)) => { + // Steal edges. + move_to_slice( + right.edge_area_mut(..count), + left.edge_area_mut(old_left_len + 1..new_left_len + 1), + ); + + // Fill gap where stolen edges used to be. + slice_shl(right.edge_area_mut(..old_right_len + 1), count); + + left.correct_childrens_parent_links(old_left_len + 1..new_left_len + 1); + right.correct_childrens_parent_links(0..new_right_len + 1); + } + (ForceResult::Leaf(_), ForceResult::Leaf(_)) => {} + _ => unreachable!(), + } + } + } +} + +impl Handle, marker::Edge> { + pub fn forget_node_type( + self, + ) -> Handle, marker::Edge> { + unsafe { Handle::new_edge(self.node.forget_type(), self.idx) } + } +} + +impl Handle, marker::Edge> { + pub fn forget_node_type( + self, + ) -> Handle, marker::Edge> { + unsafe { Handle::new_edge(self.node.forget_type(), self.idx) } + } +} + +impl Handle, marker::KV> { + pub fn forget_node_type( + self, + ) -> Handle, marker::KV> { + unsafe { Handle::new_kv(self.node.forget_type(), self.idx) } + } +} + +impl Handle, Type> { + /// Checks whether the underlying node is an `Internal` node or a `Leaf` node. + pub fn force( + self, + ) -> ForceResult< + Handle, Type>, + Handle, Type>, + > { + match self.node.force() { + ForceResult::Leaf(node) => { + ForceResult::Leaf(Handle { node, idx: self.idx, _marker: PhantomData }) + } + ForceResult::Internal(node) => { + ForceResult::Internal(Handle { node, idx: self.idx, _marker: PhantomData }) + } + } + } +} + +impl<'a, K, V, Type> Handle, K, V, marker::LeafOrInternal>, Type> { + /// Unsafely asserts to the compiler the static information that the handle's node is a `Leaf`. + pub unsafe fn cast_to_leaf_unchecked( + self, + ) -> Handle, K, V, marker::Leaf>, Type> { + let node = unsafe { self.node.cast_to_leaf_unchecked() }; + Handle { node, idx: self.idx, _marker: PhantomData } + } +} + +impl<'a, K, V> Handle, K, V, marker::LeafOrInternal>, marker::Edge> { + /// Move the suffix after `self` from one node to another one. `right` must be empty. + /// The first edge of `right` remains unchanged. + pub fn move_suffix( + &mut self, + right: &mut NodeRef, K, V, marker::LeafOrInternal>, + ) { + unsafe { + let new_left_len = self.idx; + let mut left_node = self.reborrow_mut().into_node(); + let old_left_len = left_node.len(); + + let new_right_len = old_left_len - new_left_len; + let mut right_node = right.reborrow_mut(); + + assert!(right_node.len() == 0); + assert!(left_node.height == right_node.height); + + if new_right_len > 0 { + *left_node.len_mut() = new_left_len as u16; + *right_node.len_mut() = new_right_len as u16; + + move_to_slice( + left_node.key_area_mut(new_left_len..old_left_len), + right_node.key_area_mut(..new_right_len), + ); + move_to_slice( + left_node.val_area_mut(new_left_len..old_left_len), + right_node.val_area_mut(..new_right_len), + ); + match (left_node.force(), right_node.force()) { + (ForceResult::Internal(mut left), ForceResult::Internal(mut right)) => { + move_to_slice( + left.edge_area_mut(new_left_len + 1..old_left_len + 1), + right.edge_area_mut(1..new_right_len + 1), + ); + right.correct_childrens_parent_links(1..new_right_len + 1); + } + (ForceResult::Leaf(_), ForceResult::Leaf(_)) => {} + _ => unreachable!(), + } + } + } + } +} + +pub enum ForceResult { + Leaf(Leaf), + Internal(Internal), +} + +/// Result of insertion, when a node needed to expand beyond its capacity. +pub struct SplitResult<'a, K, V, NodeType> { + // Altered node in existing tree with elements and edges that belong to the left of `kv`. + pub left: NodeRef, K, V, NodeType>, + // Some key and value that existed before and were split off, to be inserted elsewhere. + pub kv: (K, V), + // Owned, unattached, new node with elements and edges that belong to the right of `kv`. + pub right: NodeRef, +} + +impl<'a, K, V> SplitResult<'a, K, V, marker::Leaf> { + pub fn forget_node_type(self) -> SplitResult<'a, K, V, marker::LeafOrInternal> { + SplitResult { left: self.left.forget_type(), kv: self.kv, right: self.right.forget_type() } + } +} + +impl<'a, K, V> SplitResult<'a, K, V, marker::Internal> { + pub fn forget_node_type(self) -> SplitResult<'a, K, V, marker::LeafOrInternal> { + SplitResult { left: self.left.forget_type(), kv: self.kv, right: self.right.forget_type() } + } +} + +pub mod marker { + use core::marker::PhantomData; + + pub enum Leaf {} + pub enum Internal {} + pub enum LeafOrInternal {} + + pub enum Owned {} + pub enum Dying {} + pub enum DormantMut {} + pub struct Immut<'a>(PhantomData<&'a ()>); + pub struct Mut<'a>(PhantomData<&'a mut ()>); + pub struct ValMut<'a>(PhantomData<&'a mut ()>); + + pub trait BorrowType { + /// If node references of this borrow type allow traversing to other + /// nodes in the tree, this constant is set to `true`. It can be used + /// for a compile-time assertion. + const TRAVERSAL_PERMIT: bool = true; + } + impl BorrowType for Owned { + /// Reject traversal, because it isn't needed. Instead traversal + /// happens using the result of `borrow_mut`. + /// By disabling traversal, and only creating new references to roots, + /// we know that every reference of the `Owned` type is to a root node. + const TRAVERSAL_PERMIT: bool = false; + } + impl BorrowType for Dying {} + impl<'a> BorrowType for Immut<'a> {} + impl<'a> BorrowType for Mut<'a> {} + impl<'a> BorrowType for ValMut<'a> {} + impl BorrowType for DormantMut {} + + pub enum KV {} + pub enum Edge {} +} + +/// Inserts a value into a slice of initialized elements followed by one uninitialized element. +/// +/// # Safety +/// The slice has more than `idx` elements. +unsafe fn slice_insert(slice: &mut [MaybeUninit], idx: usize, val: T) { + unsafe { + let len = slice.len(); + debug_assert!(len > idx); + let slice_ptr = slice.as_mut_ptr(); + if len > idx + 1 { + ptr::copy(slice_ptr.add(idx), slice_ptr.add(idx + 1), len - idx - 1); + } + (*slice_ptr.add(idx)).write(val); + } +} + +/// Removes and returns a value from a slice of all initialized elements, leaving behind one +/// trailing uninitialized element. +/// +/// # Safety +/// The slice has more than `idx` elements. +unsafe fn slice_remove(slice: &mut [MaybeUninit], idx: usize) -> T { + unsafe { + let len = slice.len(); + debug_assert!(idx < len); + let slice_ptr = slice.as_mut_ptr(); + let ret = (*slice_ptr.add(idx)).assume_init_read(); + ptr::copy(slice_ptr.add(idx + 1), slice_ptr.add(idx), len - idx - 1); + ret + } +} + +/// Shifts the elements in a slice `distance` positions to the left. +/// +/// # Safety +/// The slice has at least `distance` elements. +unsafe fn slice_shl(slice: &mut [MaybeUninit], distance: usize) { + unsafe { + let slice_ptr = slice.as_mut_ptr(); + ptr::copy(slice_ptr.add(distance), slice_ptr, slice.len() - distance); + } +} + +/// Shifts the elements in a slice `distance` positions to the right. +/// +/// # Safety +/// The slice has at least `distance` elements. +unsafe fn slice_shr(slice: &mut [MaybeUninit], distance: usize) { + unsafe { + let slice_ptr = slice.as_mut_ptr(); + ptr::copy(slice_ptr, slice_ptr.add(distance), slice.len() - distance); + } +} + +/// Moves all values from a slice of initialized elements to a slice +/// of uninitialized elements, leaving behind `src` as all uninitialized. +/// Works like `dst.copy_from_slice(src)` but does not require `T` to be `Copy`. +fn move_to_slice(src: &mut [MaybeUninit], dst: &mut [MaybeUninit]) { + assert!(src.len() == dst.len()); + unsafe { + ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len()); + } +} + +#[cfg(test)] +mod tests; diff --git a/CoqOfRust/alloc/collections/btree/node/tests.rs b/CoqOfRust/alloc/collections/btree/node/tests.rs new file mode 100644 index 000000000..4d2fa0f09 --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/node/tests.rs @@ -0,0 +1,99 @@ +use super::super::navigate; +use super::*; +use crate::alloc::Global; +use crate::fmt::Debug; +use crate::string::String; + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + // Asserts that the back pointer in each reachable node points to its parent. + pub fn assert_back_pointers(self) { + if let ForceResult::Internal(node) = self.force() { + for idx in 0..=node.len() { + let edge = unsafe { Handle::new_edge(node, idx) }; + let child = edge.descend(); + assert!(child.ascend().ok() == Some(edge)); + child.assert_back_pointers(); + } + } + } + + // Renders a multi-line display of the keys in order and in tree hierarchy, + // picturing the tree growing sideways from its root on the left to its + // leaves on the right. + pub fn dump_keys(self) -> String + where + K: Debug, + { + let mut result = String::new(); + self.visit_nodes_in_order(|pos| match pos { + navigate::Position::Leaf(leaf) => { + let depth = self.height(); + let indent = " ".repeat(depth); + result += &format!("\n{}{:?}", indent, leaf.keys()); + } + navigate::Position::Internal(_) => {} + navigate::Position::InternalKV => {} + }); + result + } +} + +#[test] +fn test_splitpoint() { + for idx in 0..=CAPACITY { + let (middle_kv_idx, insertion) = splitpoint(idx); + + // Simulate performing the split: + let mut left_len = middle_kv_idx; + let mut right_len = CAPACITY - middle_kv_idx - 1; + match insertion { + LeftOrRight::Left(edge_idx) => { + assert!(edge_idx <= left_len); + left_len += 1; + } + LeftOrRight::Right(edge_idx) => { + assert!(edge_idx <= right_len); + right_len += 1; + } + } + assert!(left_len >= MIN_LEN_AFTER_SPLIT); + assert!(right_len >= MIN_LEN_AFTER_SPLIT); + assert!(left_len + right_len == CAPACITY); + } +} + +#[test] +fn test_partial_eq() { + let mut root1 = NodeRef::new_leaf(Global); + root1.borrow_mut().push(1, ()); + let mut root1 = NodeRef::new_internal(root1.forget_type(), Global).forget_type(); + let root2 = Root::new(Global); + root1.reborrow().assert_back_pointers(); + root2.reborrow().assert_back_pointers(); + + let leaf_edge_1a = root1.reborrow().first_leaf_edge().forget_node_type(); + let leaf_edge_1b = root1.reborrow().last_leaf_edge().forget_node_type(); + let top_edge_1 = root1.reborrow().first_edge(); + let top_edge_2 = root2.reborrow().first_edge(); + + assert!(leaf_edge_1a == leaf_edge_1a); + assert!(leaf_edge_1a != leaf_edge_1b); + assert!(leaf_edge_1a != top_edge_1); + assert!(leaf_edge_1a != top_edge_2); + assert!(top_edge_1 == top_edge_1); + assert!(top_edge_1 != top_edge_2); + + root1.pop_internal_level(Global); + unsafe { root1.into_dying().deallocate_and_ascend(Global) }; + unsafe { root2.into_dying().deallocate_and_ascend(Global) }; +} + +#[test] +#[cfg(target_arch = "x86_64")] +#[cfg_attr(any(miri, randomized_layouts), ignore)] // We'd like to run Miri with layout randomization +fn test_sizes() { + assert_eq!(core::mem::size_of::>(), 16); + assert_eq!(core::mem::size_of::>(), 16 + CAPACITY * 2 * 8); + assert_eq!(core::mem::size_of::>(), 16 + (CAPACITY + 1) * 8); + assert_eq!(core::mem::size_of::>(), 16 + (CAPACITY * 3 + 1) * 8); +} diff --git a/CoqOfRust/alloc/collections/btree/remove.rs b/CoqOfRust/alloc/collections/btree/remove.rs new file mode 100644 index 000000000..56f2824b7 --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/remove.rs @@ -0,0 +1,98 @@ +use core::alloc::Allocator; + +use super::map::MIN_LEN; +use super::node::ForceResult::*; +use super::node::LeftOrRight::*; +use super::node::{Handle, NodeRef, marker}; + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::LeafOrInternal>, marker::KV> { + /// Removes a key-value pair from the tree, and returns that pair, as well as + /// the leaf edge corresponding to that former pair. It's possible this empties + /// a root node that is internal, which the caller should pop from the map + /// holding the tree. The caller should also decrement the map's length. + pub fn remove_kv_tracking( + self, + handle_emptied_internal_root: F, + alloc: A, + ) -> ((K, V), Handle, K, V, marker::Leaf>, marker::Edge>) { + match self.force() { + Leaf(node) => node.remove_leaf_kv(handle_emptied_internal_root, alloc), + Internal(node) => node.remove_internal_kv(handle_emptied_internal_root, alloc), + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, marker::KV> { + fn remove_leaf_kv( + self, + handle_emptied_internal_root: F, + alloc: A, + ) -> ((K, V), Handle, K, V, marker::Leaf>, marker::Edge>) { + let (old_kv, mut pos) = self.remove(); + let len = pos.reborrow().into_node().len(); + if len < MIN_LEN { + let idx = pos.idx(); + // We have to temporarily forget the child type, because there is no + // distinct node type for the immediate parents of a leaf. + let new_pos = match pos.into_node().forget_type().choose_parent_kv() { + Ok(Left(left_parent_kv)) => { + debug_assert!(left_parent_kv.right_child_len() == MIN_LEN - 1); + if left_parent_kv.can_merge() { + left_parent_kv.merge_tracking_child_edge(Right(idx), alloc.clone()) + } else { + debug_assert!(left_parent_kv.left_child_len() > MIN_LEN); + left_parent_kv.steal_left(idx) + } + } + Ok(Right(right_parent_kv)) => { + debug_assert!(right_parent_kv.left_child_len() == MIN_LEN - 1); + if right_parent_kv.can_merge() { + right_parent_kv.merge_tracking_child_edge(Left(idx), alloc.clone()) + } else { + debug_assert!(right_parent_kv.right_child_len() > MIN_LEN); + right_parent_kv.steal_right(idx) + } + } + Err(pos) => unsafe { Handle::new_edge(pos, idx) }, + }; + // SAFETY: `new_pos` is the leaf we started from or a sibling. + pos = unsafe { new_pos.cast_to_leaf_unchecked() }; + + // Only if we merged, the parent (if any) has shrunk, but skipping + // the following step otherwise does not pay off in benchmarks. + // + // SAFETY: We won't destroy or rearrange the leaf where `pos` is at + // by handling its parent recursively; at worst we will destroy or + // rearrange the parent through the grandparent, thus change the + // link to the parent inside the leaf. + if let Ok(parent) = unsafe { pos.reborrow_mut() }.into_node().ascend() { + if !parent.into_node().forget_type().fix_node_and_affected_ancestors(alloc) { + handle_emptied_internal_root(); + } + } + } + (old_kv, pos) + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, marker::KV> { + fn remove_internal_kv( + self, + handle_emptied_internal_root: F, + alloc: A, + ) -> ((K, V), Handle, K, V, marker::Leaf>, marker::Edge>) { + // Remove an adjacent KV from its leaf and then put it back in place of + // the element we were asked to remove. Prefer the left adjacent KV, + // for the reasons listed in `choose_parent_kv`. + let left_leaf_kv = self.left_edge().descend().last_leaf_edge().left_kv(); + let left_leaf_kv = unsafe { left_leaf_kv.ok().unwrap_unchecked() }; + let (left_kv, left_hole) = left_leaf_kv.remove_leaf_kv(handle_emptied_internal_root, alloc); + + // The internal node may have been stolen from or merged. Go back right + // to find where the original KV ended up. + let mut internal = unsafe { left_hole.next_kv().ok().unwrap_unchecked() }; + let old_kv = internal.replace_kv(left_kv.0, left_kv.1); + let pos = internal.next_leaf_edge(); + (old_kv, pos) + } +} diff --git a/CoqOfRust/alloc/collections/btree/search.rs b/CoqOfRust/alloc/collections/btree/search.rs new file mode 100644 index 000000000..22e015eda --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/search.rs @@ -0,0 +1,286 @@ +use core::borrow::Borrow; +use core::cmp::Ordering; +use core::ops::{Bound, RangeBounds}; + +use SearchBound::*; +use SearchResult::*; + +use super::node::ForceResult::*; +use super::node::{Handle, NodeRef, marker}; + +pub enum SearchBound { + /// An inclusive bound to look for, just like `Bound::Included(T)`. + Included(T), + /// An exclusive bound to look for, just like `Bound::Excluded(T)`. + Excluded(T), + /// An unconditional inclusive bound, just like `Bound::Unbounded`. + AllIncluded, + /// An unconditional exclusive bound. + AllExcluded, +} + +impl SearchBound { + pub fn from_range(range_bound: Bound) -> Self { + match range_bound { + Bound::Included(t) => Included(t), + Bound::Excluded(t) => Excluded(t), + Bound::Unbounded => AllIncluded, + } + } +} + +pub enum SearchResult { + Found(Handle, marker::KV>), + GoDown(Handle, marker::Edge>), +} + +pub enum IndexResult { + KV(usize), + Edge(usize), +} + +impl NodeRef { + /// Looks up a given key in a (sub)tree headed by the node, recursively. + /// Returns a `Found` with the handle of the matching KV, if any. Otherwise, + /// returns a `GoDown` with the handle of the leaf edge where the key belongs. + /// + /// The result is meaningful only if the tree is ordered by key, like the tree + /// in a `BTreeMap` is. + pub fn search_tree( + mut self, + key: &Q, + ) -> SearchResult + where + Q: Ord, + K: Borrow, + { + loop { + self = match self.search_node(key) { + Found(handle) => return Found(handle), + GoDown(handle) => match handle.force() { + Leaf(leaf) => return GoDown(leaf), + Internal(internal) => internal.descend(), + }, + } + } + } + + /// Descends to the nearest node where the edge matching the lower bound + /// of the range is different from the edge matching the upper bound, i.e., + /// the nearest node that has at least one key contained in the range. + /// + /// If found, returns an `Ok` with that node, the strictly ascending pair of + /// edge indices in the node delimiting the range, and the corresponding + /// pair of bounds for continuing the search in the child nodes, in case + /// the node is internal. + /// + /// If not found, returns an `Err` with the leaf edge matching the entire + /// range. + /// + /// As a diagnostic service, panics if the range specifies impossible bounds. + /// + /// The result is meaningful only if the tree is ordered by key. + pub fn search_tree_for_bifurcation<'r, Q: ?Sized, R>( + mut self, + range: &'r R, + ) -> Result< + ( + NodeRef, + usize, + usize, + SearchBound<&'r Q>, + SearchBound<&'r Q>, + ), + Handle, marker::Edge>, + > + where + Q: Ord, + K: Borrow, + R: RangeBounds, + { + // Determine if map or set is being searched + let is_set = ::is_set_val(); + + // Inlining these variables should be avoided. We assume the bounds reported by `range` + // remain the same, but an adversarial implementation could change between calls (#81138). + let (start, end) = (range.start_bound(), range.end_bound()); + match (start, end) { + (Bound::Excluded(s), Bound::Excluded(e)) if s == e => { + if is_set { + panic!("range start and end are equal and excluded in BTreeSet") + } else { + panic!("range start and end are equal and excluded in BTreeMap") + } + } + (Bound::Included(s) | Bound::Excluded(s), Bound::Included(e) | Bound::Excluded(e)) + if s > e => + { + if is_set { + panic!("range start is greater than range end in BTreeSet") + } else { + panic!("range start is greater than range end in BTreeMap") + } + } + _ => {} + } + let mut lower_bound = SearchBound::from_range(start); + let mut upper_bound = SearchBound::from_range(end); + loop { + let (lower_edge_idx, lower_child_bound) = self.find_lower_bound_index(lower_bound); + let (upper_edge_idx, upper_child_bound) = + unsafe { self.find_upper_bound_index(upper_bound, lower_edge_idx) }; + if lower_edge_idx < upper_edge_idx { + return Ok(( + self, + lower_edge_idx, + upper_edge_idx, + lower_child_bound, + upper_child_bound, + )); + } + debug_assert_eq!(lower_edge_idx, upper_edge_idx); + let common_edge = unsafe { Handle::new_edge(self, lower_edge_idx) }; + match common_edge.force() { + Leaf(common_edge) => return Err(common_edge), + Internal(common_edge) => { + self = common_edge.descend(); + lower_bound = lower_child_bound; + upper_bound = upper_child_bound; + } + } + } + } + + /// Finds an edge in the node delimiting the lower bound of a range. + /// Also returns the lower bound to be used for continuing the search in + /// the matching child node, if `self` is an internal node. + /// + /// The result is meaningful only if the tree is ordered by key. + pub fn find_lower_bound_edge<'r, Q>( + self, + bound: SearchBound<&'r Q>, + ) -> (Handle, SearchBound<&'r Q>) + where + Q: ?Sized + Ord, + K: Borrow, + { + let (edge_idx, bound) = self.find_lower_bound_index(bound); + let edge = unsafe { Handle::new_edge(self, edge_idx) }; + (edge, bound) + } + + /// Clone of `find_lower_bound_edge` for the upper bound. + pub fn find_upper_bound_edge<'r, Q>( + self, + bound: SearchBound<&'r Q>, + ) -> (Handle, SearchBound<&'r Q>) + where + Q: ?Sized + Ord, + K: Borrow, + { + let (edge_idx, bound) = unsafe { self.find_upper_bound_index(bound, 0) }; + let edge = unsafe { Handle::new_edge(self, edge_idx) }; + (edge, bound) + } +} + +impl NodeRef { + /// Looks up a given key in the node, without recursion. + /// Returns a `Found` with the handle of the matching KV, if any. Otherwise, + /// returns a `GoDown` with the handle of the edge where the key might be found + /// (if the node is internal) or where the key can be inserted. + /// + /// The result is meaningful only if the tree is ordered by key, like the tree + /// in a `BTreeMap` is. + pub fn search_node(self, key: &Q) -> SearchResult + where + Q: Ord, + K: Borrow, + { + match unsafe { self.find_key_index(key, 0) } { + IndexResult::KV(idx) => Found(unsafe { Handle::new_kv(self, idx) }), + IndexResult::Edge(idx) => GoDown(unsafe { Handle::new_edge(self, idx) }), + } + } + + /// Returns either the KV index in the node at which the key (or an equivalent) + /// exists, or the edge index where the key belongs, starting from a particular index. + /// + /// The result is meaningful only if the tree is ordered by key, like the tree + /// in a `BTreeMap` is. + /// + /// # Safety + /// `start_index` must be a valid edge index for the node. + unsafe fn find_key_index(&self, key: &Q, start_index: usize) -> IndexResult + where + Q: Ord, + K: Borrow, + { + let node = self.reborrow(); + let keys = node.keys(); + debug_assert!(start_index <= keys.len()); + for (offset, k) in unsafe { keys.get_unchecked(start_index..) }.iter().enumerate() { + match key.cmp(k.borrow()) { + Ordering::Greater => {} + Ordering::Equal => return IndexResult::KV(start_index + offset), + Ordering::Less => return IndexResult::Edge(start_index + offset), + } + } + IndexResult::Edge(keys.len()) + } + + /// Finds an edge index in the node delimiting the lower bound of a range. + /// Also returns the lower bound to be used for continuing the search in + /// the matching child node, if `self` is an internal node. + /// + /// The result is meaningful only if the tree is ordered by key. + fn find_lower_bound_index<'r, Q>( + &self, + bound: SearchBound<&'r Q>, + ) -> (usize, SearchBound<&'r Q>) + where + Q: ?Sized + Ord, + K: Borrow, + { + match bound { + Included(key) => match unsafe { self.find_key_index(key, 0) } { + IndexResult::KV(idx) => (idx, AllExcluded), + IndexResult::Edge(idx) => (idx, bound), + }, + Excluded(key) => match unsafe { self.find_key_index(key, 0) } { + IndexResult::KV(idx) => (idx + 1, AllIncluded), + IndexResult::Edge(idx) => (idx, bound), + }, + AllIncluded => (0, AllIncluded), + AllExcluded => (self.len(), AllExcluded), + } + } + + /// Mirror image of `find_lower_bound_index` for the upper bound, + /// with an additional parameter to skip part of the key array. + /// + /// # Safety + /// `start_index` must be a valid edge index for the node. + unsafe fn find_upper_bound_index<'r, Q>( + &self, + bound: SearchBound<&'r Q>, + start_index: usize, + ) -> (usize, SearchBound<&'r Q>) + where + Q: ?Sized + Ord, + K: Borrow, + { + match bound { + Included(key) => match unsafe { self.find_key_index(key, start_index) } { + IndexResult::KV(idx) => (idx + 1, AllExcluded), + IndexResult::Edge(idx) => (idx, bound), + }, + Excluded(key) => match unsafe { self.find_key_index(key, start_index) } { + IndexResult::KV(idx) => (idx, AllIncluded), + IndexResult::Edge(idx) => (idx, bound), + }, + AllIncluded => (self.len(), AllIncluded), + AllExcluded => (start_index, AllExcluded), + } + } +} diff --git a/CoqOfRust/alloc/collections/btree/set.rs b/CoqOfRust/alloc/collections/btree/set.rs new file mode 100644 index 000000000..6f8c3b2d1 --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/set.rs @@ -0,0 +1,2509 @@ +use core::borrow::Borrow; +use core::cmp::Ordering::{self, Equal, Greater, Less}; +use core::cmp::{max, min}; +use core::fmt::{self, Debug}; +use core::hash::{Hash, Hasher}; +use core::iter::{FusedIterator, Peekable}; +use core::mem::ManuallyDrop; +use core::ops::{BitAnd, BitOr, BitXor, Bound, RangeBounds, Sub}; + +use super::map::{self, BTreeMap, Keys}; +use super::merge_iter::MergeIterInner; +use super::set_val::SetValZST; +use crate::alloc::{Allocator, Global}; +use crate::vec::Vec; + +mod entry; + +#[unstable(feature = "btree_set_entry", issue = "133549")] +pub use self::entry::{Entry, OccupiedEntry, VacantEntry}; + +/// An ordered set based on a B-Tree. +/// +/// See [`BTreeMap`]'s documentation for a detailed discussion of this collection's performance +/// benefits and drawbacks. +/// +/// It is a logic error for an item to be modified in such a way that the item's ordering relative +/// to any other item, as determined by the [`Ord`] trait, changes while it is in the set. This is +/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. +/// The behavior resulting from such a logic error is not specified, but will be encapsulated to the +/// `BTreeSet` that observed the logic error and not result in undefined behavior. This could +/// include panics, incorrect results, aborts, memory leaks, and non-termination. +/// +/// Iterators returned by [`BTreeSet::iter`] and [`BTreeSet::into_iter`] produce their items in order, and take worst-case +/// logarithmic and amortized constant time per item returned. +/// +/// [`Cell`]: core::cell::Cell +/// [`RefCell`]: core::cell::RefCell +/// +/// # Examples +/// +/// ``` +/// use std::collections::BTreeSet; +/// +/// // Type inference lets us omit an explicit type signature (which +/// // would be `BTreeSet<&str>` in this example). +/// let mut books = BTreeSet::new(); +/// +/// // Add some books. +/// books.insert("A Dance With Dragons"); +/// books.insert("To Kill a Mockingbird"); +/// books.insert("The Odyssey"); +/// books.insert("The Great Gatsby"); +/// +/// // Check for a specific one. +/// if !books.contains("The Winds of Winter") { +/// println!("We have {} books, but The Winds of Winter ain't one.", +/// books.len()); +/// } +/// +/// // Remove a book. +/// books.remove("The Odyssey"); +/// +/// // Iterate over everything. +/// for book in &books { +/// println!("{book}"); +/// } +/// ``` +/// +/// A `BTreeSet` with a known list of items can be initialized from an array: +/// +/// ``` +/// use std::collections::BTreeSet; +/// +/// let set = BTreeSet::from([1, 2, 3]); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeSet")] +pub struct BTreeSet< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + map: BTreeMap, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for BTreeSet { + fn hash(&self, state: &mut H) { + self.map.hash(state) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for BTreeSet { + fn eq(&self, other: &BTreeSet) -> bool { + self.map.eq(&other.map) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for BTreeSet {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for BTreeSet { + fn partial_cmp(&self, other: &BTreeSet) -> Option { + self.map.partial_cmp(&other.map) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for BTreeSet { + fn cmp(&self, other: &BTreeSet) -> Ordering { + self.map.cmp(&other.map) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for BTreeSet { + fn clone(&self) -> Self { + BTreeSet { map: self.map.clone() } + } + + fn clone_from(&mut self, source: &Self) { + self.map.clone_from(&source.map); + } +} + +/// An iterator over the items of a `BTreeSet`. +/// +/// This `struct` is created by the [`iter`] method on [`BTreeSet`]. +/// See its documentation for more. +/// +/// [`iter`]: BTreeSet::iter +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Iter<'a, T: 'a> { + iter: Keys<'a, T, SetValZST>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Iter<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Iter").field(&self.iter.clone()).finish() + } +} + +/// An owning iterator over the items of a `BTreeSet` in ascending order. +/// +/// This `struct` is created by the [`into_iter`] method on [`BTreeSet`] +/// (provided by the [`IntoIterator`] trait). See its documentation for more. +/// +/// [`into_iter`]: BTreeSet#method.into_iter +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct IntoIter< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + iter: super::map::IntoIter, +} + +/// An iterator over a sub-range of items in a `BTreeSet`. +/// +/// This `struct` is created by the [`range`] method on [`BTreeSet`]. +/// See its documentation for more. +/// +/// [`range`]: BTreeSet::range +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[derive(Debug)] +#[stable(feature = "btree_range", since = "1.17.0")] +pub struct Range<'a, T: 'a> { + iter: super::map::Range<'a, T, SetValZST>, +} + +/// A lazy iterator producing elements in the difference of `BTreeSet`s. +/// +/// This `struct` is created by the [`difference`] method on [`BTreeSet`]. +/// See its documentation for more. +/// +/// [`difference`]: BTreeSet::difference +#[must_use = "this returns the difference as an iterator, \ + without modifying either input set"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Difference< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + inner: DifferenceInner<'a, T, A>, +} +enum DifferenceInner<'a, T: 'a, A: Allocator + Clone> { + Stitch { + // iterate all of `self` and some of `other`, spotting matches along the way + self_iter: Iter<'a, T>, + other_iter: Peekable>, + }, + Search { + // iterate `self`, look up in `other` + self_iter: Iter<'a, T>, + other_set: &'a BTreeSet, + }, + Iterate(Iter<'a, T>), // simply produce all elements in `self` +} + +// Explicit Debug impl necessary because of issue #26925 +impl Debug for DifferenceInner<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + DifferenceInner::Stitch { self_iter, other_iter } => f + .debug_struct("Stitch") + .field("self_iter", self_iter) + .field("other_iter", other_iter) + .finish(), + DifferenceInner::Search { self_iter, other_set } => f + .debug_struct("Search") + .field("self_iter", self_iter) + .field("other_iter", other_set) + .finish(), + DifferenceInner::Iterate(x) => f.debug_tuple("Iterate").field(x).finish(), + } + } +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Difference<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Difference").field(&self.inner).finish() + } +} + +/// A lazy iterator producing elements in the symmetric difference of `BTreeSet`s. +/// +/// This `struct` is created by the [`symmetric_difference`] method on +/// [`BTreeSet`]. See its documentation for more. +/// +/// [`symmetric_difference`]: BTreeSet::symmetric_difference +#[must_use = "this returns the difference as an iterator, \ + without modifying either input set"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct SymmetricDifference<'a, T: 'a>(MergeIterInner>); + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for SymmetricDifference<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("SymmetricDifference").field(&self.0).finish() + } +} + +/// A lazy iterator producing elements in the intersection of `BTreeSet`s. +/// +/// This `struct` is created by the [`intersection`] method on [`BTreeSet`]. +/// See its documentation for more. +/// +/// [`intersection`]: BTreeSet::intersection +#[must_use = "this returns the intersection as an iterator, \ + without modifying either input set"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Intersection< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + inner: IntersectionInner<'a, T, A>, +} +enum IntersectionInner<'a, T: 'a, A: Allocator + Clone> { + Stitch { + // iterate similarly sized sets jointly, spotting matches along the way + a: Iter<'a, T>, + b: Iter<'a, T>, + }, + Search { + // iterate a small set, look up in the large set + small_iter: Iter<'a, T>, + large_set: &'a BTreeSet, + }, + Answer(Option<&'a T>), // return a specific element or emptiness +} + +// Explicit Debug impl necessary because of issue #26925 +impl Debug for IntersectionInner<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + IntersectionInner::Stitch { a, b } => { + f.debug_struct("Stitch").field("a", a).field("b", b).finish() + } + IntersectionInner::Search { small_iter, large_set } => f + .debug_struct("Search") + .field("small_iter", small_iter) + .field("large_set", large_set) + .finish(), + IntersectionInner::Answer(x) => f.debug_tuple("Answer").field(x).finish(), + } + } +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl Debug for Intersection<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Intersection").field(&self.inner).finish() + } +} + +/// A lazy iterator producing elements in the union of `BTreeSet`s. +/// +/// This `struct` is created by the [`union`] method on [`BTreeSet`]. +/// See its documentation for more. +/// +/// [`union`]: BTreeSet::union +#[must_use = "this returns the union as an iterator, \ + without modifying either input set"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Union<'a, T: 'a>(MergeIterInner>); + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Union<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Union").field(&self.0).finish() + } +} + +// This constant is used by functions that compare two sets. +// It estimates the relative size at which searching performs better +// than iterating, based on the benchmarks in +// https://github.com/ssomers/rust_bench_btreeset_intersection. +// It's used to divide rather than multiply sizes, to rule out overflow, +// and it's a power of two to make that division cheap. +const ITER_PERFORMANCE_TIPPING_SIZE_DIFF: usize = 16; + +impl BTreeSet { + /// Makes a new, empty `BTreeSet`. + /// + /// Does not allocate anything on its own. + /// + /// # Examples + /// + /// ``` + /// # #![allow(unused_mut)] + /// use std::collections::BTreeSet; + /// + /// let mut set: BTreeSet = BTreeSet::new(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_btree_new", since = "1.66.0")] + #[must_use] + pub const fn new() -> BTreeSet { + BTreeSet { map: BTreeMap::new() } + } +} + +impl BTreeSet { + /// Makes a new `BTreeSet` with a reasonable choice of B. + /// + /// # Examples + /// + /// ``` + /// # #![allow(unused_mut)] + /// # #![feature(allocator_api)] + /// # #![feature(btreemap_alloc)] + /// use std::collections::BTreeSet; + /// use std::alloc::Global; + /// + /// let mut set: BTreeSet = BTreeSet::new_in(Global); + /// ``` + #[unstable(feature = "btreemap_alloc", issue = "32838")] + pub const fn new_in(alloc: A) -> BTreeSet { + BTreeSet { map: BTreeMap::new_in(alloc) } + } + + /// Constructs a double-ended iterator over a sub-range of elements in the set. + /// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will + /// yield elements from min (inclusive) to max (exclusive). + /// The range may also be entered as `(Bound, Bound)`, so for example + /// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive + /// range from 4 to 10. + /// + /// # Panics + /// + /// Panics if range `start > end`. + /// Panics if range `start == end` and both bounds are `Excluded`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// use std::ops::Bound::Included; + /// + /// let mut set = BTreeSet::new(); + /// set.insert(3); + /// set.insert(5); + /// set.insert(8); + /// for &elem in set.range((Included(&4), Included(&8))) { + /// println!("{elem}"); + /// } + /// assert_eq!(Some(&5), set.range(4..).next()); + /// ``` + #[stable(feature = "btree_range", since = "1.17.0")] + pub fn range(&self, range: R) -> Range<'_, T> + where + K: Ord, + T: Borrow + Ord, + R: RangeBounds, + { + Range { iter: self.map.range(range) } + } + + /// Visits the elements representing the difference, + /// i.e., the elements that are in `self` but not in `other`, + /// in ascending order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut a = BTreeSet::new(); + /// a.insert(1); + /// a.insert(2); + /// + /// let mut b = BTreeSet::new(); + /// b.insert(2); + /// b.insert(3); + /// + /// let diff: Vec<_> = a.difference(&b).cloned().collect(); + /// assert_eq!(diff, [1]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn difference<'a>(&'a self, other: &'a BTreeSet) -> Difference<'a, T, A> + where + T: Ord, + { + let (self_min, self_max) = + if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) { + (self_min, self_max) + } else { + return Difference { inner: DifferenceInner::Iterate(self.iter()) }; + }; + let (other_min, other_max) = + if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) { + (other_min, other_max) + } else { + return Difference { inner: DifferenceInner::Iterate(self.iter()) }; + }; + Difference { + inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) { + (Greater, _) | (_, Less) => DifferenceInner::Iterate(self.iter()), + (Equal, _) => { + let mut self_iter = self.iter(); + self_iter.next(); + DifferenceInner::Iterate(self_iter) + } + (_, Equal) => { + let mut self_iter = self.iter(); + self_iter.next_back(); + DifferenceInner::Iterate(self_iter) + } + _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { + DifferenceInner::Search { self_iter: self.iter(), other_set: other } + } + _ => DifferenceInner::Stitch { + self_iter: self.iter(), + other_iter: other.iter().peekable(), + }, + }, + } + } + + /// Visits the elements representing the symmetric difference, + /// i.e., the elements that are in `self` or in `other` but not in both, + /// in ascending order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut a = BTreeSet::new(); + /// a.insert(1); + /// a.insert(2); + /// + /// let mut b = BTreeSet::new(); + /// b.insert(2); + /// b.insert(3); + /// + /// let sym_diff: Vec<_> = a.symmetric_difference(&b).cloned().collect(); + /// assert_eq!(sym_diff, [1, 3]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn symmetric_difference<'a>( + &'a self, + other: &'a BTreeSet, + ) -> SymmetricDifference<'a, T> + where + T: Ord, + { + SymmetricDifference(MergeIterInner::new(self.iter(), other.iter())) + } + + /// Visits the elements representing the intersection, + /// i.e., the elements that are both in `self` and `other`, + /// in ascending order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut a = BTreeSet::new(); + /// a.insert(1); + /// a.insert(2); + /// + /// let mut b = BTreeSet::new(); + /// b.insert(2); + /// b.insert(3); + /// + /// let intersection: Vec<_> = a.intersection(&b).cloned().collect(); + /// assert_eq!(intersection, [2]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn intersection<'a>(&'a self, other: &'a BTreeSet) -> Intersection<'a, T, A> + where + T: Ord, + { + let (self_min, self_max) = + if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) { + (self_min, self_max) + } else { + return Intersection { inner: IntersectionInner::Answer(None) }; + }; + let (other_min, other_max) = + if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) { + (other_min, other_max) + } else { + return Intersection { inner: IntersectionInner::Answer(None) }; + }; + Intersection { + inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) { + (Greater, _) | (_, Less) => IntersectionInner::Answer(None), + (Equal, _) => IntersectionInner::Answer(Some(self_min)), + (_, Equal) => IntersectionInner::Answer(Some(self_max)), + _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { + IntersectionInner::Search { small_iter: self.iter(), large_set: other } + } + _ if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { + IntersectionInner::Search { small_iter: other.iter(), large_set: self } + } + _ => IntersectionInner::Stitch { a: self.iter(), b: other.iter() }, + }, + } + } + + /// Visits the elements representing the union, + /// i.e., all the elements in `self` or `other`, without duplicates, + /// in ascending order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut a = BTreeSet::new(); + /// a.insert(1); + /// + /// let mut b = BTreeSet::new(); + /// b.insert(2); + /// + /// let union: Vec<_> = a.union(&b).cloned().collect(); + /// assert_eq!(union, [1, 2]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn union<'a>(&'a self, other: &'a BTreeSet) -> Union<'a, T> + where + T: Ord, + { + Union(MergeIterInner::new(self.iter(), other.iter())) + } + + /// Clears the set, removing all elements. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut v = BTreeSet::new(); + /// v.insert(1); + /// v.clear(); + /// assert!(v.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) + where + A: Clone, + { + self.map.clear() + } + + /// Returns `true` if the set contains an element equal to the value. + /// + /// The value may be any borrowed form of the set's element type, + /// but the ordering on the borrowed form *must* match the + /// ordering on the element type. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let set = BTreeSet::from([1, 2, 3]); + /// assert_eq!(set.contains(&1), true); + /// assert_eq!(set.contains(&4), false); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn contains(&self, value: &Q) -> bool + where + T: Borrow + Ord, + Q: Ord, + { + self.map.contains_key(value) + } + + /// Returns a reference to the element in the set, if any, that is equal to + /// the value. + /// + /// The value may be any borrowed form of the set's element type, + /// but the ordering on the borrowed form *must* match the + /// ordering on the element type. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let set = BTreeSet::from([1, 2, 3]); + /// assert_eq!(set.get(&2), Some(&2)); + /// assert_eq!(set.get(&4), None); + /// ``` + #[stable(feature = "set_recovery", since = "1.9.0")] + pub fn get(&self, value: &Q) -> Option<&T> + where + T: Borrow + Ord, + Q: Ord, + { + self.map.get_key_value(value).map(|(k, _)| k) + } + + /// Returns `true` if `self` has no elements in common with `other`. + /// This is equivalent to checking for an empty intersection. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let a = BTreeSet::from([1, 2, 3]); + /// let mut b = BTreeSet::new(); + /// + /// assert_eq!(a.is_disjoint(&b), true); + /// b.insert(4); + /// assert_eq!(a.is_disjoint(&b), true); + /// b.insert(1); + /// assert_eq!(a.is_disjoint(&b), false); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_disjoint(&self, other: &BTreeSet) -> bool + where + T: Ord, + { + self.intersection(other).next().is_none() + } + + /// Returns `true` if the set is a subset of another, + /// i.e., `other` contains at least all the elements in `self`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let sup = BTreeSet::from([1, 2, 3]); + /// let mut set = BTreeSet::new(); + /// + /// assert_eq!(set.is_subset(&sup), true); + /// set.insert(2); + /// assert_eq!(set.is_subset(&sup), true); + /// set.insert(4); + /// assert_eq!(set.is_subset(&sup), false); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_subset(&self, other: &BTreeSet) -> bool + where + T: Ord, + { + // Same result as self.difference(other).next().is_none() + // but the code below is faster (hugely in some cases). + if self.len() > other.len() { + return false; + } + let (self_min, self_max) = + if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) { + (self_min, self_max) + } else { + return true; // self is empty + }; + let (other_min, other_max) = + if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) { + (other_min, other_max) + } else { + return false; // other is empty + }; + let mut self_iter = self.iter(); + match self_min.cmp(other_min) { + Less => return false, + Equal => { + self_iter.next(); + } + Greater => (), + } + match self_max.cmp(other_max) { + Greater => return false, + Equal => { + self_iter.next_back(); + } + Less => (), + } + if self_iter.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { + for next in self_iter { + if !other.contains(next) { + return false; + } + } + } else { + let mut other_iter = other.iter(); + other_iter.next(); + other_iter.next_back(); + let mut self_next = self_iter.next(); + while let Some(self1) = self_next { + match other_iter.next().map_or(Less, |other1| self1.cmp(other1)) { + Less => return false, + Equal => self_next = self_iter.next(), + Greater => (), + } + } + } + true + } + + /// Returns `true` if the set is a superset of another, + /// i.e., `self` contains at least all the elements in `other`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let sub = BTreeSet::from([1, 2]); + /// let mut set = BTreeSet::new(); + /// + /// assert_eq!(set.is_superset(&sub), false); + /// + /// set.insert(0); + /// set.insert(1); + /// assert_eq!(set.is_superset(&sub), false); + /// + /// set.insert(2); + /// assert_eq!(set.is_superset(&sub), true); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_superset(&self, other: &BTreeSet) -> bool + where + T: Ord, + { + other.is_subset(self) + } + + /// Returns a reference to the first element in the set, if any. + /// This element is always the minimum of all elements in the set. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// assert_eq!(set.first(), None); + /// set.insert(1); + /// assert_eq!(set.first(), Some(&1)); + /// set.insert(2); + /// assert_eq!(set.first(), Some(&1)); + /// ``` + #[must_use] + #[stable(feature = "map_first_last", since = "1.66.0")] + #[rustc_confusables("front")] + pub fn first(&self) -> Option<&T> + where + T: Ord, + { + self.map.first_key_value().map(|(k, _)| k) + } + + /// Returns a reference to the last element in the set, if any. + /// This element is always the maximum of all elements in the set. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// assert_eq!(set.last(), None); + /// set.insert(1); + /// assert_eq!(set.last(), Some(&1)); + /// set.insert(2); + /// assert_eq!(set.last(), Some(&2)); + /// ``` + #[must_use] + #[stable(feature = "map_first_last", since = "1.66.0")] + #[rustc_confusables("back")] + pub fn last(&self) -> Option<&T> + where + T: Ord, + { + self.map.last_key_value().map(|(k, _)| k) + } + + /// Removes the first element from the set and returns it, if any. + /// The first element is always the minimum element in the set. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// set.insert(1); + /// while let Some(n) = set.pop_first() { + /// assert_eq!(n, 1); + /// } + /// assert!(set.is_empty()); + /// ``` + #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn pop_first(&mut self) -> Option + where + T: Ord, + { + self.map.pop_first().map(|kv| kv.0) + } + + /// Removes the last element from the set and returns it, if any. + /// The last element is always the maximum element in the set. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// set.insert(1); + /// while let Some(n) = set.pop_last() { + /// assert_eq!(n, 1); + /// } + /// assert!(set.is_empty()); + /// ``` + #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn pop_last(&mut self) -> Option + where + T: Ord, + { + self.map.pop_last().map(|kv| kv.0) + } + + /// Adds a value to the set. + /// + /// Returns whether the value was newly inserted. That is: + /// + /// - If the set did not previously contain an equal value, `true` is + /// returned. + /// - If the set already contained an equal value, `false` is returned, and + /// the entry is not updated. + /// + /// See the [module-level documentation] for more. + /// + /// [module-level documentation]: index.html#insert-and-complex-keys + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// assert_eq!(set.insert(2), true); + /// assert_eq!(set.insert(2), false); + /// assert_eq!(set.len(), 1); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push", "put")] + pub fn insert(&mut self, value: T) -> bool + where + T: Ord, + { + self.map.insert(value, SetValZST::default()).is_none() + } + + /// Adds a value to the set, replacing the existing element, if any, that is + /// equal to the value. Returns the replaced element. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// set.insert(Vec::::new()); + /// + /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 0); + /// set.replace(Vec::with_capacity(10)); + /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10); + /// ``` + #[stable(feature = "set_recovery", since = "1.9.0")] + #[rustc_confusables("swap")] + pub fn replace(&mut self, value: T) -> Option + where + T: Ord, + { + self.map.replace(value) + } + + /// Inserts the given `value` into the set if it is not present, then + /// returns a reference to the value in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::from([1, 2, 3]); + /// assert_eq!(set.len(), 3); + /// assert_eq!(set.get_or_insert(2), &2); + /// assert_eq!(set.get_or_insert(100), &100); + /// assert_eq!(set.len(), 4); // 100 was inserted + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn get_or_insert(&mut self, value: T) -> &T + where + T: Ord, + { + self.map.entry(value).insert_entry(SetValZST).into_key() + } + + /// Inserts a value computed from `f` into the set if the given `value` is + /// not present, then returns a reference to the value in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set: BTreeSet = ["cat", "dog", "horse"] + /// .iter().map(|&pet| pet.to_owned()).collect(); + /// + /// assert_eq!(set.len(), 3); + /// for &pet in &["cat", "dog", "fish"] { + /// let value = set.get_or_insert_with(pet, str::to_owned); + /// assert_eq!(value, pet); + /// } + /// assert_eq!(set.len(), 4); // a new "fish" was inserted + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn get_or_insert_with(&mut self, value: &Q, f: F) -> &T + where + T: Borrow + Ord, + Q: Ord, + F: FnOnce(&Q) -> T, + { + self.map.get_or_insert_with(value, f) + } + + /// Gets the given value's corresponding entry in the set for in-place manipulation. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// use std::collections::btree_set::Entry::*; + /// + /// let mut singles = BTreeSet::new(); + /// let mut dupes = BTreeSet::new(); + /// + /// for ch in "a short treatise on fungi".chars() { + /// if let Vacant(dupe_entry) = dupes.entry(ch) { + /// // We haven't already seen a duplicate, so + /// // check if we've at least seen it once. + /// match singles.entry(ch) { + /// Vacant(single_entry) => { + /// // We found a new character for the first time. + /// single_entry.insert() + /// } + /// Occupied(single_entry) => { + /// // We've already seen this once, "move" it to dupes. + /// single_entry.remove(); + /// dupe_entry.insert(); + /// } + /// } + /// } + /// } + /// + /// assert!(!singles.contains(&'t') && dupes.contains(&'t')); + /// assert!(singles.contains(&'u') && !dupes.contains(&'u')); + /// assert!(!singles.contains(&'v') && !dupes.contains(&'v')); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn entry(&mut self, value: T) -> Entry<'_, T, A> + where + T: Ord, + { + match self.map.entry(value) { + map::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { inner: entry }), + map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { inner: entry }), + } + } + + /// If the set contains an element equal to the value, removes it from the + /// set and drops it. Returns whether such an element was present. + /// + /// The value may be any borrowed form of the set's element type, + /// but the ordering on the borrowed form *must* match the + /// ordering on the element type. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// set.insert(2); + /// assert_eq!(set.remove(&2), true); + /// assert_eq!(set.remove(&2), false); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn remove(&mut self, value: &Q) -> bool + where + T: Borrow + Ord, + Q: Ord, + { + self.map.remove(value).is_some() + } + + /// Removes and returns the element in the set, if any, that is equal to + /// the value. + /// + /// The value may be any borrowed form of the set's element type, + /// but the ordering on the borrowed form *must* match the + /// ordering on the element type. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::from([1, 2, 3]); + /// assert_eq!(set.take(&2), Some(2)); + /// assert_eq!(set.take(&2), None); + /// ``` + #[stable(feature = "set_recovery", since = "1.9.0")] + pub fn take(&mut self, value: &Q) -> Option + where + T: Borrow + Ord, + Q: Ord, + { + self.map.remove_entry(value).map(|(k, _)| k) + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` for which `f(&e)` returns `false`. + /// The elements are visited in ascending order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::from([1, 2, 3, 4, 5, 6]); + /// // Keep only the even numbers. + /// set.retain(|&k| k % 2 == 0); + /// assert!(set.iter().eq([2, 4, 6].iter())); + /// ``` + #[stable(feature = "btree_retain", since = "1.53.0")] + pub fn retain(&mut self, mut f: F) + where + T: Ord, + F: FnMut(&T) -> bool, + { + self.extract_if(|v| !f(v)).for_each(drop); + } + + /// Moves all elements from `other` into `self`, leaving `other` empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut a = BTreeSet::new(); + /// a.insert(1); + /// a.insert(2); + /// a.insert(3); + /// + /// let mut b = BTreeSet::new(); + /// b.insert(3); + /// b.insert(4); + /// b.insert(5); + /// + /// a.append(&mut b); + /// + /// assert_eq!(a.len(), 5); + /// assert_eq!(b.len(), 0); + /// + /// assert!(a.contains(&1)); + /// assert!(a.contains(&2)); + /// assert!(a.contains(&3)); + /// assert!(a.contains(&4)); + /// assert!(a.contains(&5)); + /// ``` + #[stable(feature = "btree_append", since = "1.11.0")] + pub fn append(&mut self, other: &mut Self) + where + T: Ord, + A: Clone, + { + self.map.append(&mut other.map); + } + + /// Splits the collection into two at the value. Returns a new collection + /// with all elements greater than or equal to the value. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut a = BTreeSet::new(); + /// a.insert(1); + /// a.insert(2); + /// a.insert(3); + /// a.insert(17); + /// a.insert(41); + /// + /// let b = a.split_off(&3); + /// + /// assert_eq!(a.len(), 2); + /// assert_eq!(b.len(), 3); + /// + /// assert!(a.contains(&1)); + /// assert!(a.contains(&2)); + /// + /// assert!(b.contains(&3)); + /// assert!(b.contains(&17)); + /// assert!(b.contains(&41)); + /// ``` + #[stable(feature = "btree_split_off", since = "1.11.0")] + pub fn split_off(&mut self, value: &Q) -> Self + where + T: Borrow + Ord, + A: Clone, + { + BTreeSet { map: self.map.split_off(value) } + } + + /// Creates an iterator that visits all elements in ascending order and + /// uses a closure to determine if an element should be removed. + /// + /// If the closure returns `true`, the element is removed from the set and + /// yielded. If the closure returns `false`, or panics, the element remains + /// in the set and will not be yielded. + /// + /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating + /// or the iteration short-circuits, then the remaining elements will be retained. + /// Use [`retain`] with a negated predicate if you do not need the returned iterator. + /// + /// [`retain`]: BTreeSet::retain + /// # Examples + /// + /// Splitting a set into even and odd values, reusing the original set: + /// + /// ``` + /// #![feature(btree_extract_if)] + /// use std::collections::BTreeSet; + /// + /// let mut set: BTreeSet = (0..8).collect(); + /// let evens: BTreeSet<_> = set.extract_if(|v| v % 2 == 0).collect(); + /// let odds = set; + /// assert_eq!(evens.into_iter().collect::>(), vec![0, 2, 4, 6]); + /// assert_eq!(odds.into_iter().collect::>(), vec![1, 3, 5, 7]); + /// ``` + #[unstable(feature = "btree_extract_if", issue = "70530")] + pub fn extract_if<'a, F>(&'a mut self, pred: F) -> ExtractIf<'a, T, F, A> + where + T: Ord, + F: 'a + FnMut(&T) -> bool, + { + let (inner, alloc) = self.map.extract_if_inner(); + ExtractIf { pred, inner, alloc } + } + + /// Gets an iterator that visits the elements in the `BTreeSet` in ascending + /// order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let set = BTreeSet::from([3, 1, 2]); + /// let mut set_iter = set.iter(); + /// assert_eq!(set_iter.next(), Some(&1)); + /// assert_eq!(set_iter.next(), Some(&2)); + /// assert_eq!(set_iter.next(), Some(&3)); + /// assert_eq!(set_iter.next(), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "btreeset_iter")] + pub fn iter(&self) -> Iter<'_, T> { + Iter { iter: self.map.keys() } + } + + /// Returns the number of elements in the set. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut v = BTreeSet::new(); + /// assert_eq!(v.len(), 0); + /// v.insert(1); + /// assert_eq!(v.len(), 1); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable( + feature = "const_btree_len", + issue = "71835", + implied_by = "const_btree_new" + )] + #[rustc_confusables("length", "size")] + pub const fn len(&self) -> usize { + self.map.len() + } + + /// Returns `true` if the set contains no elements. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut v = BTreeSet::new(); + /// assert!(v.is_empty()); + /// v.insert(1); + /// assert!(!v.is_empty()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable( + feature = "const_btree_len", + issue = "71835", + implied_by = "const_btree_new" + )] + pub const fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Returns a [`Cursor`] pointing at the gap before the smallest element + /// greater than the given bound. + /// + /// Passing `Bound::Included(x)` will return a cursor pointing to the + /// gap before the smallest element greater than or equal to `x`. + /// + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the + /// gap before the smallest element greater than `x`. + /// + /// Passing `Bound::Unbounded` will return a cursor pointing to the + /// gap before the smallest element in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_cursors)] + /// + /// use std::collections::BTreeSet; + /// use std::ops::Bound; + /// + /// let set = BTreeSet::from([1, 2, 3, 4]); + /// + /// let cursor = set.lower_bound(Bound::Included(&2)); + /// assert_eq!(cursor.peek_prev(), Some(&1)); + /// assert_eq!(cursor.peek_next(), Some(&2)); + /// + /// let cursor = set.lower_bound(Bound::Excluded(&2)); + /// assert_eq!(cursor.peek_prev(), Some(&2)); + /// assert_eq!(cursor.peek_next(), Some(&3)); + /// + /// let cursor = set.lower_bound(Bound::Unbounded); + /// assert_eq!(cursor.peek_prev(), None); + /// assert_eq!(cursor.peek_next(), Some(&1)); + /// ``` + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn lower_bound(&self, bound: Bound<&Q>) -> Cursor<'_, T> + where + T: Borrow + Ord, + Q: Ord, + { + Cursor { inner: self.map.lower_bound(bound) } + } + + /// Returns a [`CursorMut`] pointing at the gap before the smallest element + /// greater than the given bound. + /// + /// Passing `Bound::Included(x)` will return a cursor pointing to the + /// gap before the smallest element greater than or equal to `x`. + /// + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the + /// gap before the smallest element greater than `x`. + /// + /// Passing `Bound::Unbounded` will return a cursor pointing to the + /// gap before the smallest element in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_cursors)] + /// + /// use std::collections::BTreeSet; + /// use std::ops::Bound; + /// + /// let mut set = BTreeSet::from([1, 2, 3, 4]); + /// + /// let mut cursor = set.lower_bound_mut(Bound::Included(&2)); + /// assert_eq!(cursor.peek_prev(), Some(&1)); + /// assert_eq!(cursor.peek_next(), Some(&2)); + /// + /// let mut cursor = set.lower_bound_mut(Bound::Excluded(&2)); + /// assert_eq!(cursor.peek_prev(), Some(&2)); + /// assert_eq!(cursor.peek_next(), Some(&3)); + /// + /// let mut cursor = set.lower_bound_mut(Bound::Unbounded); + /// assert_eq!(cursor.peek_prev(), None); + /// assert_eq!(cursor.peek_next(), Some(&1)); + /// ``` + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn lower_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A> + where + T: Borrow + Ord, + Q: Ord, + { + CursorMut { inner: self.map.lower_bound_mut(bound) } + } + + /// Returns a [`Cursor`] pointing at the gap after the greatest element + /// smaller than the given bound. + /// + /// Passing `Bound::Included(x)` will return a cursor pointing to the + /// gap after the greatest element smaller than or equal to `x`. + /// + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the + /// gap after the greatest element smaller than `x`. + /// + /// Passing `Bound::Unbounded` will return a cursor pointing to the + /// gap after the greatest element in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_cursors)] + /// + /// use std::collections::BTreeSet; + /// use std::ops::Bound; + /// + /// let set = BTreeSet::from([1, 2, 3, 4]); + /// + /// let cursor = set.upper_bound(Bound::Included(&3)); + /// assert_eq!(cursor.peek_prev(), Some(&3)); + /// assert_eq!(cursor.peek_next(), Some(&4)); + /// + /// let cursor = set.upper_bound(Bound::Excluded(&3)); + /// assert_eq!(cursor.peek_prev(), Some(&2)); + /// assert_eq!(cursor.peek_next(), Some(&3)); + /// + /// let cursor = set.upper_bound(Bound::Unbounded); + /// assert_eq!(cursor.peek_prev(), Some(&4)); + /// assert_eq!(cursor.peek_next(), None); + /// ``` + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn upper_bound(&self, bound: Bound<&Q>) -> Cursor<'_, T> + where + T: Borrow + Ord, + Q: Ord, + { + Cursor { inner: self.map.upper_bound(bound) } + } + + /// Returns a [`CursorMut`] pointing at the gap after the greatest element + /// smaller than the given bound. + /// + /// Passing `Bound::Included(x)` will return a cursor pointing to the + /// gap after the greatest element smaller than or equal to `x`. + /// + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the + /// gap after the greatest element smaller than `x`. + /// + /// Passing `Bound::Unbounded` will return a cursor pointing to the + /// gap after the greatest element in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_cursors)] + /// + /// use std::collections::BTreeSet; + /// use std::ops::Bound; + /// + /// let mut set = BTreeSet::from([1, 2, 3, 4]); + /// + /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Included(&3)) }; + /// assert_eq!(cursor.peek_prev(), Some(&3)); + /// assert_eq!(cursor.peek_next(), Some(&4)); + /// + /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Excluded(&3)) }; + /// assert_eq!(cursor.peek_prev(), Some(&2)); + /// assert_eq!(cursor.peek_next(), Some(&3)); + /// + /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Unbounded) }; + /// assert_eq!(cursor.peek_prev(), Some(&4)); + /// assert_eq!(cursor.peek_next(), None); + /// ``` + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn upper_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A> + where + T: Borrow + Ord, + Q: Ord, + { + CursorMut { inner: self.map.upper_bound_mut(bound) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for BTreeSet { + fn from_iter>(iter: I) -> BTreeSet { + let mut inputs: Vec<_> = iter.into_iter().collect(); + + if inputs.is_empty() { + return BTreeSet::new(); + } + + // use stable sort to preserve the insertion order. + inputs.sort(); + BTreeSet::from_sorted_iter(inputs.into_iter(), Global) + } +} + +impl BTreeSet { + fn from_sorted_iter>(iter: I, alloc: A) -> BTreeSet { + let iter = iter.map(|k| (k, SetValZST::default())); + let map = BTreeMap::bulk_build_from_sorted_iter(iter, alloc); + BTreeSet { map } + } +} + +#[stable(feature = "std_collections_from_array", since = "1.56.0")] +impl From<[T; N]> for BTreeSet { + /// Converts a `[T; N]` into a `BTreeSet`. + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let set1 = BTreeSet::from([1, 2, 3, 4]); + /// let set2: BTreeSet<_> = [1, 2, 3, 4].into(); + /// assert_eq!(set1, set2); + /// ``` + fn from(mut arr: [T; N]) -> Self { + if N == 0 { + return BTreeSet::new(); + } + + // use stable sort to preserve the insertion order. + arr.sort(); + let iter = IntoIterator::into_iter(arr).map(|k| (k, SetValZST::default())); + let map = BTreeMap::bulk_build_from_sorted_iter(iter, Global); + BTreeSet { map } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for BTreeSet { + type Item = T; + type IntoIter = IntoIter; + + /// Gets an iterator for moving out the `BTreeSet`'s contents in ascending order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let set = BTreeSet::from([1, 2, 3, 4]); + /// + /// let v: Vec<_> = set.into_iter().collect(); + /// assert_eq!(v, [1, 2, 3, 4]); + /// ``` + fn into_iter(self) -> IntoIter { + IntoIter { iter: self.map.into_iter() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, A: Allocator + Clone> IntoIterator for &'a BTreeSet { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +/// An iterator produced by calling `extract_if` on BTreeSet. +#[unstable(feature = "btree_extract_if", issue = "70530")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct ExtractIf< + 'a, + T, + F, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> where + T: 'a, + F: 'a + FnMut(&T) -> bool, +{ + pred: F, + inner: super::map::ExtractIfInner<'a, T, SetValZST>, + /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`. + alloc: A, +} + +#[unstable(feature = "btree_extract_if", issue = "70530")] +impl fmt::Debug for ExtractIf<'_, T, F, A> +where + T: fmt::Debug, + F: FnMut(&T) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("ExtractIf").field(&self.inner.peek().map(|(k, _)| k)).finish() + } +} + +#[unstable(feature = "btree_extract_if", issue = "70530")] +impl<'a, T, F, A: Allocator + Clone> Iterator for ExtractIf<'_, T, F, A> +where + F: 'a + FnMut(&T) -> bool, +{ + type Item = T; + + fn next(&mut self) -> Option { + let pred = &mut self.pred; + let mut mapped_pred = |k: &T, _v: &mut SetValZST| pred(k); + self.inner.next(&mut mapped_pred, self.alloc.clone()).map(|(k, _)| k) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +#[unstable(feature = "btree_extract_if", issue = "70530")] +impl FusedIterator for ExtractIf<'_, T, F, A> where F: FnMut(&T) -> bool {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for BTreeSet { + #[inline] + fn extend>(&mut self, iter: Iter) { + iter.into_iter().for_each(move |elem| { + self.insert(elem); + }); + } + + #[inline] + fn extend_one(&mut self, elem: T) { + self.insert(elem); + } +} + +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, T: 'a + Ord + Copy, A: Allocator + Clone> Extend<&'a T> for BTreeSet { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()); + } + + #[inline] + fn extend_one(&mut self, &elem: &'a T) { + self.insert(elem); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for BTreeSet { + /// Creates an empty `BTreeSet`. + fn default() -> BTreeSet { + BTreeSet::new() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Sub<&BTreeSet> for &BTreeSet { + type Output = BTreeSet; + + /// Returns the difference of `self` and `rhs` as a new `BTreeSet`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let a = BTreeSet::from([1, 2, 3]); + /// let b = BTreeSet::from([3, 4, 5]); + /// + /// let result = &a - &b; + /// assert_eq!(result, BTreeSet::from([1, 2])); + /// ``` + fn sub(self, rhs: &BTreeSet) -> BTreeSet { + BTreeSet::from_sorted_iter( + self.difference(rhs).cloned(), + ManuallyDrop::into_inner(self.map.alloc.clone()), + ) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl BitXor<&BTreeSet> for &BTreeSet { + type Output = BTreeSet; + + /// Returns the symmetric difference of `self` and `rhs` as a new `BTreeSet`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let a = BTreeSet::from([1, 2, 3]); + /// let b = BTreeSet::from([2, 3, 4]); + /// + /// let result = &a ^ &b; + /// assert_eq!(result, BTreeSet::from([1, 4])); + /// ``` + fn bitxor(self, rhs: &BTreeSet) -> BTreeSet { + BTreeSet::from_sorted_iter( + self.symmetric_difference(rhs).cloned(), + ManuallyDrop::into_inner(self.map.alloc.clone()), + ) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl BitAnd<&BTreeSet> for &BTreeSet { + type Output = BTreeSet; + + /// Returns the intersection of `self` and `rhs` as a new `BTreeSet`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let a = BTreeSet::from([1, 2, 3]); + /// let b = BTreeSet::from([2, 3, 4]); + /// + /// let result = &a & &b; + /// assert_eq!(result, BTreeSet::from([2, 3])); + /// ``` + fn bitand(self, rhs: &BTreeSet) -> BTreeSet { + BTreeSet::from_sorted_iter( + self.intersection(rhs).cloned(), + ManuallyDrop::into_inner(self.map.alloc.clone()), + ) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl BitOr<&BTreeSet> for &BTreeSet { + type Output = BTreeSet; + + /// Returns the union of `self` and `rhs` as a new `BTreeSet`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let a = BTreeSet::from([1, 2, 3]); + /// let b = BTreeSet::from([3, 4, 5]); + /// + /// let result = &a | &b; + /// assert_eq!(result, BTreeSet::from([1, 2, 3, 4, 5])); + /// ``` + fn bitor(self, rhs: &BTreeSet) -> BTreeSet { + BTreeSet::from_sorted_iter( + self.union(rhs).cloned(), + ManuallyDrop::into_inner(self.map.alloc.clone()), + ) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for BTreeSet { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_set().entries(self.iter()).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Iter<'_, T> { + fn clone(&self) -> Self { + Iter { iter: self.iter.clone() } + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option<&'a T> { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + fn last(mut self) -> Option<&'a T> { + self.next_back() + } + + fn min(mut self) -> Option<&'a T> + where + &'a T: Ord, + { + self.next() + } + + fn max(mut self) -> Option<&'a T> + where + &'a T: Ord, + { + self.next_back() + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for Iter<'a, T> { + fn next_back(&mut self) -> Option<&'a T> { + self.iter.next_back() + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Iter<'_, T> { + fn len(&self) -> usize { + self.iter.len() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Iter<'_, T> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + fn next(&mut self) -> Option { + self.iter.next().map(|(k, _)| k) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for Iter<'_, T> { + /// Creates an empty `btree_set::Iter`. + /// + /// ``` + /// # use std::collections::btree_set; + /// let iter: btree_set::Iter<'_, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Iter { iter: Default::default() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|(k, _)| k) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + fn len(&self) -> usize { + self.iter.len() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for IntoIter +where + A: Allocator + Default + Clone, +{ + /// Creates an empty `btree_set::IntoIter`. + /// + /// ``` + /// # use std::collections::btree_set; + /// let iter: btree_set::IntoIter = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + IntoIter { iter: Default::default() } + } +} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl Clone for Range<'_, T> { + fn clone(&self) -> Self { + Range { iter: self.iter.clone() } + } +} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl<'a, T> Iterator for Range<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option<&'a T> { + self.iter.next().map(|(k, _)| k) + } + + fn last(mut self) -> Option<&'a T> { + self.next_back() + } + + fn min(mut self) -> Option<&'a T> + where + &'a T: Ord, + { + self.next() + } + + fn max(mut self) -> Option<&'a T> + where + &'a T: Ord, + { + self.next_back() + } +} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl<'a, T> DoubleEndedIterator for Range<'a, T> { + fn next_back(&mut self) -> Option<&'a T> { + self.iter.next_back().map(|(k, _)| k) + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Range<'_, T> {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for Range<'_, T> { + /// Creates an empty `btree_set::Range`. + /// + /// ``` + /// # use std::collections::btree_set; + /// let iter: btree_set::Range<'_, u8> = Default::default(); + /// assert_eq!(iter.count(), 0); + /// ``` + fn default() -> Self { + Range { iter: Default::default() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Difference<'_, T, A> { + fn clone(&self) -> Self { + Difference { + inner: match &self.inner { + DifferenceInner::Stitch { self_iter, other_iter } => DifferenceInner::Stitch { + self_iter: self_iter.clone(), + other_iter: other_iter.clone(), + }, + DifferenceInner::Search { self_iter, other_set } => { + DifferenceInner::Search { self_iter: self_iter.clone(), other_set } + } + DifferenceInner::Iterate(iter) => DifferenceInner::Iterate(iter.clone()), + }, + } + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: Ord, A: Allocator + Clone> Iterator for Difference<'a, T, A> { + type Item = &'a T; + + fn next(&mut self) -> Option<&'a T> { + match &mut self.inner { + DifferenceInner::Stitch { self_iter, other_iter } => { + let mut self_next = self_iter.next()?; + loop { + match other_iter.peek().map_or(Less, |other_next| self_next.cmp(other_next)) { + Less => return Some(self_next), + Equal => { + self_next = self_iter.next()?; + other_iter.next(); + } + Greater => { + other_iter.next(); + } + } + } + } + DifferenceInner::Search { self_iter, other_set } => loop { + let self_next = self_iter.next()?; + if !other_set.contains(&self_next) { + return Some(self_next); + } + }, + DifferenceInner::Iterate(iter) => iter.next(), + } + } + + fn size_hint(&self) -> (usize, Option) { + let (self_len, other_len) = match &self.inner { + DifferenceInner::Stitch { self_iter, other_iter } => { + (self_iter.len(), other_iter.len()) + } + DifferenceInner::Search { self_iter, other_set } => (self_iter.len(), other_set.len()), + DifferenceInner::Iterate(iter) => (iter.len(), 0), + }; + (self_len.saturating_sub(other_len), Some(self_len)) + } + + fn min(mut self) -> Option<&'a T> { + self.next() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Difference<'_, T, A> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for SymmetricDifference<'_, T> { + fn clone(&self) -> Self { + SymmetricDifference(self.0.clone()) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option<&'a T> { + loop { + let (a_next, b_next) = self.0.nexts(Self::Item::cmp); + if a_next.and(b_next).is_none() { + return a_next.or(b_next); + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let (a_len, b_len) = self.0.lens(); + // No checked_add, because even if a and b refer to the same set, + // and T is a zero-sized type, the storage overhead of sets limits + // the number of elements to less than half the range of usize. + (0, Some(a_len + b_len)) + } + + fn min(mut self) -> Option<&'a T> { + self.next() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for SymmetricDifference<'_, T> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Intersection<'_, T, A> { + fn clone(&self) -> Self { + Intersection { + inner: match &self.inner { + IntersectionInner::Stitch { a, b } => { + IntersectionInner::Stitch { a: a.clone(), b: b.clone() } + } + IntersectionInner::Search { small_iter, large_set } => { + IntersectionInner::Search { small_iter: small_iter.clone(), large_set } + } + IntersectionInner::Answer(answer) => IntersectionInner::Answer(*answer), + }, + } + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: Ord, A: Allocator + Clone> Iterator for Intersection<'a, T, A> { + type Item = &'a T; + + fn next(&mut self) -> Option<&'a T> { + match &mut self.inner { + IntersectionInner::Stitch { a, b } => { + let mut a_next = a.next()?; + let mut b_next = b.next()?; + loop { + match a_next.cmp(b_next) { + Less => a_next = a.next()?, + Greater => b_next = b.next()?, + Equal => return Some(a_next), + } + } + } + IntersectionInner::Search { small_iter, large_set } => loop { + let small_next = small_iter.next()?; + if large_set.contains(&small_next) { + return Some(small_next); + } + }, + IntersectionInner::Answer(answer) => answer.take(), + } + } + + fn size_hint(&self) -> (usize, Option) { + match &self.inner { + IntersectionInner::Stitch { a, b } => (0, Some(min(a.len(), b.len()))), + IntersectionInner::Search { small_iter, .. } => (0, Some(small_iter.len())), + IntersectionInner::Answer(None) => (0, Some(0)), + IntersectionInner::Answer(Some(_)) => (1, Some(1)), + } + } + + fn min(mut self) -> Option<&'a T> { + self.next() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Intersection<'_, T, A> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Union<'_, T> { + fn clone(&self) -> Self { + Union(self.0.clone()) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: Ord> Iterator for Union<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option<&'a T> { + let (a_next, b_next) = self.0.nexts(Self::Item::cmp); + a_next.or(b_next) + } + + fn size_hint(&self) -> (usize, Option) { + let (a_len, b_len) = self.0.lens(); + // No checked_add - see SymmetricDifference::size_hint. + (max(a_len, b_len), Some(a_len + b_len)) + } + + fn min(mut self) -> Option<&'a T> { + self.next() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Union<'_, T> {} + +/// A cursor over a `BTreeSet`. +/// +/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth. +/// +/// Cursors always point to a gap between two elements in the set, and can +/// operate on the two immediately adjacent elements. +/// +/// A `Cursor` is created with the [`BTreeSet::lower_bound`] and [`BTreeSet::upper_bound`] methods. +#[derive(Clone)] +#[unstable(feature = "btree_cursors", issue = "107540")] +pub struct Cursor<'a, K: 'a> { + inner: super::map::Cursor<'a, K, SetValZST>, +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl Debug for Cursor<'_, K> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Cursor") + } +} + +/// A cursor over a `BTreeSet` with editing operations. +/// +/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can +/// safely mutate the set during iteration. This is because the lifetime of its yielded +/// references is tied to its own lifetime, instead of just the underlying map. This means +/// cursors cannot yield multiple elements at once. +/// +/// Cursors always point to a gap between two elements in the set, and can +/// operate on the two immediately adjacent elements. +/// +/// A `CursorMut` is created with the [`BTreeSet::lower_bound_mut`] and [`BTreeSet::upper_bound_mut`] +/// methods. +#[unstable(feature = "btree_cursors", issue = "107540")] +pub struct CursorMut<'a, K: 'a, #[unstable(feature = "allocator_api", issue = "32838")] A = Global> +{ + inner: super::map::CursorMut<'a, K, SetValZST, A>, +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl Debug for CursorMut<'_, K, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("CursorMut") + } +} + +/// A cursor over a `BTreeSet` with editing operations, and which allows +/// mutating elements. +/// +/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can +/// safely mutate the set during iteration. This is because the lifetime of its yielded +/// references is tied to its own lifetime, instead of just the underlying set. This means +/// cursors cannot yield multiple elements at once. +/// +/// Cursors always point to a gap between two elements in the set, and can +/// operate on the two immediately adjacent elements. +/// +/// A `CursorMutKey` is created from a [`CursorMut`] with the +/// [`CursorMut::with_mutable_key`] method. +/// +/// # Safety +/// +/// Since this cursor allows mutating elements, you must ensure that the +/// `BTreeSet` invariants are maintained. Specifically: +/// +/// * The newly inserted element must be unique in the tree. +/// * All elements in the tree must remain in sorted order. +#[unstable(feature = "btree_cursors", issue = "107540")] +pub struct CursorMutKey< + 'a, + K: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A = Global, +> { + inner: super::map::CursorMutKey<'a, K, SetValZST, A>, +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl Debug for CursorMutKey<'_, K, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("CursorMutKey") + } +} + +impl<'a, K> Cursor<'a, K> { + /// Advances the cursor to the next gap, returning the element that it + /// moved over. + /// + /// If the cursor is already at the end of the set then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn next(&mut self) -> Option<&'a K> { + self.inner.next().map(|(k, _)| k) + } + + /// Advances the cursor to the previous gap, returning the element that it + /// moved over. + /// + /// If the cursor is already at the start of the set then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn prev(&mut self) -> Option<&'a K> { + self.inner.prev().map(|(k, _)| k) + } + + /// Returns a reference to next element without moving the cursor. + /// + /// If the cursor is at the end of the set then `None` is returned + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_next(&self) -> Option<&'a K> { + self.inner.peek_next().map(|(k, _)| k) + } + + /// Returns a reference to the previous element without moving the cursor. + /// + /// If the cursor is at the start of the set then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_prev(&self) -> Option<&'a K> { + self.inner.peek_prev().map(|(k, _)| k) + } +} + +impl<'a, T, A> CursorMut<'a, T, A> { + /// Advances the cursor to the next gap, returning the element that it + /// moved over. + /// + /// If the cursor is already at the end of the set then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn next(&mut self) -> Option<&T> { + self.inner.next().map(|(k, _)| k) + } + + /// Advances the cursor to the previous gap, returning the element that it + /// moved over. + /// + /// If the cursor is already at the start of the set then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn prev(&mut self) -> Option<&T> { + self.inner.prev().map(|(k, _)| k) + } + + /// Returns a reference to the next element without moving the cursor. + /// + /// If the cursor is at the end of the set then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_next(&mut self) -> Option<&T> { + self.inner.peek_next().map(|(k, _)| k) + } + + /// Returns a reference to the previous element without moving the cursor. + /// + /// If the cursor is at the start of the set then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_prev(&mut self) -> Option<&T> { + self.inner.peek_prev().map(|(k, _)| k) + } + + /// Returns a read-only cursor pointing to the same location as the + /// `CursorMut`. + /// + /// The lifetime of the returned `Cursor` is bound to that of the + /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the + /// `CursorMut` is frozen for the lifetime of the `Cursor`. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn as_cursor(&self) -> Cursor<'_, T> { + Cursor { inner: self.inner.as_cursor() } + } + + /// Converts the cursor into a [`CursorMutKey`], which allows mutating + /// elements in the tree. + /// + /// # Safety + /// + /// Since this cursor allows mutating elements, you must ensure that the + /// `BTreeSet` invariants are maintained. Specifically: + /// + /// * The newly inserted element must be unique in the tree. + /// * All elements in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn with_mutable_key(self) -> CursorMutKey<'a, T, A> { + CursorMutKey { inner: unsafe { self.inner.with_mutable_key() } } + } +} + +impl<'a, T, A> CursorMutKey<'a, T, A> { + /// Advances the cursor to the next gap, returning the element that it + /// moved over. + /// + /// If the cursor is already at the end of the set then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn next(&mut self) -> Option<&mut T> { + self.inner.next().map(|(k, _)| k) + } + + /// Advances the cursor to the previous gap, returning the element that it + /// moved over. + /// + /// If the cursor is already at the start of the set then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn prev(&mut self) -> Option<&mut T> { + self.inner.prev().map(|(k, _)| k) + } + + /// Returns a reference to the next element without moving the cursor. + /// + /// If the cursor is at the end of the set then `None` is returned + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_next(&mut self) -> Option<&mut T> { + self.inner.peek_next().map(|(k, _)| k) + } + + /// Returns a reference to the previous element without moving the cursor. + /// + /// If the cursor is at the start of the set then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_prev(&mut self) -> Option<&mut T> { + self.inner.peek_prev().map(|(k, _)| k) + } + + /// Returns a read-only cursor pointing to the same location as the + /// `CursorMutKey`. + /// + /// The lifetime of the returned `Cursor` is bound to that of the + /// `CursorMutKey`, which means it cannot outlive the `CursorMutKey` and that the + /// `CursorMutKey` is frozen for the lifetime of the `Cursor`. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn as_cursor(&self) -> Cursor<'_, T> { + Cursor { inner: self.inner.as_cursor() } + } +} + +impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap before the + /// newly inserted element. + /// + /// # Safety + /// + /// You must ensure that the `BTreeSet` invariants are maintained. + /// Specifically: + /// + /// * The newly inserted element must be unique in the tree. + /// * All elements in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn insert_after_unchecked(&mut self, value: T) { + unsafe { self.inner.insert_after_unchecked(value, SetValZST) } + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// # Safety + /// + /// You must ensure that the `BTreeSet` invariants are maintained. + /// Specifically: + /// + /// * The newly inserted element must be unique in the tree. + /// * All elements in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn insert_before_unchecked(&mut self, value: T) { + unsafe { self.inner.insert_before_unchecked(value, SetValZST) } + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap before the + /// newly inserted element. + /// + /// If the inserted element is not greater than the element before the + /// cursor (if any), or if it not less than the element after the cursor (if + /// any), then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the elements of the set. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn insert_after(&mut self, value: T) -> Result<(), UnorderedKeyError> { + self.inner.insert_after(value, SetValZST) + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// If the inserted element is not greater than the element before the + /// cursor (if any), or if it not less than the element after the cursor (if + /// any), then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the elements of the set. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn insert_before(&mut self, value: T) -> Result<(), UnorderedKeyError> { + self.inner.insert_before(value, SetValZST) + } + + /// Removes the next element from the `BTreeSet`. + /// + /// The element that was removed is returned. The cursor position is + /// unchanged (before the removed element). + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn remove_next(&mut self) -> Option { + self.inner.remove_next().map(|(k, _)| k) + } + + /// Removes the preceding element from the `BTreeSet`. + /// + /// The element that was removed is returned. The cursor position is + /// unchanged (after the removed element). + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn remove_prev(&mut self) -> Option { + self.inner.remove_prev().map(|(k, _)| k) + } +} + +impl<'a, T: Ord, A: Allocator + Clone> CursorMutKey<'a, T, A> { + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap before the + /// newly inserted element. + /// + /// # Safety + /// + /// You must ensure that the `BTreeSet` invariants are maintained. + /// Specifically: + /// + /// * The key of the newly inserted element must be unique in the tree. + /// * All elements in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn insert_after_unchecked(&mut self, value: T) { + unsafe { self.inner.insert_after_unchecked(value, SetValZST) } + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// # Safety + /// + /// You must ensure that the `BTreeSet` invariants are maintained. + /// Specifically: + /// + /// * The newly inserted element must be unique in the tree. + /// * All elements in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn insert_before_unchecked(&mut self, value: T) { + unsafe { self.inner.insert_before_unchecked(value, SetValZST) } + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap before the + /// newly inserted element. + /// + /// If the inserted element is not greater than the element before the + /// cursor (if any), or if it not less than the element after the cursor (if + /// any), then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the elements of the set. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn insert_after(&mut self, value: T) -> Result<(), UnorderedKeyError> { + self.inner.insert_after(value, SetValZST) + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// If the inserted element is not greater than the element before the + /// cursor (if any), or if it not less than the element after the cursor (if + /// any), then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the elements of the set. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn insert_before(&mut self, value: T) -> Result<(), UnorderedKeyError> { + self.inner.insert_before(value, SetValZST) + } + + /// Removes the next element from the `BTreeSet`. + /// + /// The element that was removed is returned. The cursor position is + /// unchanged (before the removed element). + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn remove_next(&mut self) -> Option { + self.inner.remove_next().map(|(k, _)| k) + } + + /// Removes the preceding element from the `BTreeSet`. + /// + /// The element that was removed is returned. The cursor position is + /// unchanged (after the removed element). + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn remove_prev(&mut self) -> Option { + self.inner.remove_prev().map(|(k, _)| k) + } +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +pub use super::map::UnorderedKeyError; + +#[cfg(test)] +mod tests; diff --git a/CoqOfRust/alloc/collections/btree/set/entry.rs b/CoqOfRust/alloc/collections/btree/set/entry.rs new file mode 100644 index 000000000..a60d22f9e --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/set/entry.rs @@ -0,0 +1,388 @@ +use core::fmt::{self, Debug}; + +use Entry::*; + +use super::{SetValZST, map}; +use crate::alloc::{Allocator, Global}; + +/// A view into a single entry in a set, which may either be vacant or occupied. +/// +/// This `enum` is constructed from the [`entry`] method on [`BTreeSet`]. +/// +/// [`BTreeSet`]: super::BTreeSet +/// [`entry`]: super::BTreeSet::entry +/// +/// # Examples +/// +/// ``` +/// #![feature(btree_set_entry)] +/// +/// use std::collections::btree_set::BTreeSet; +/// +/// let mut set = BTreeSet::new(); +/// set.extend(["a", "b", "c"]); +/// assert_eq!(set.len(), 3); +/// +/// // Existing value (insert) +/// let entry = set.entry("a"); +/// let _raw_o = entry.insert(); +/// assert_eq!(set.len(), 3); +/// // Nonexistent value (insert) +/// set.entry("d").insert(); +/// +/// // Existing value (or_insert) +/// set.entry("b").or_insert(); +/// // Nonexistent value (or_insert) +/// set.entry("e").or_insert(); +/// +/// println!("Our BTreeSet: {:?}", set); +/// assert!(set.iter().eq(&["a", "b", "c", "d", "e"])); +/// ``` +#[unstable(feature = "btree_set_entry", issue = "133549")] +pub enum Entry< + 'a, + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + /// An occupied entry. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::btree_set::{Entry, BTreeSet}; + /// + /// let mut set = BTreeSet::from(["a", "b"]); + /// + /// match set.entry("a") { + /// Entry::Vacant(_) => unreachable!(), + /// Entry::Occupied(_) => { } + /// } + /// ``` + #[unstable(feature = "btree_set_entry", issue = "133549")] + Occupied(OccupiedEntry<'a, T, A>), + + /// A vacant entry. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::btree_set::{Entry, BTreeSet}; + /// + /// let mut set = BTreeSet::new(); + /// + /// match set.entry("a") { + /// Entry::Occupied(_) => unreachable!(), + /// Entry::Vacant(_) => { } + /// } + /// ``` + #[unstable(feature = "btree_set_entry", issue = "133549")] + Vacant(VacantEntry<'a, T, A>), +} + +#[unstable(feature = "btree_set_entry", issue = "133549")] +impl Debug for Entry<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(), + Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(), + } + } +} + +/// A view into an occupied entry in a `BTreeSet`. +/// It is part of the [`Entry`] enum. +/// +/// # Examples +/// +/// ``` +/// #![feature(btree_set_entry)] +/// +/// use std::collections::btree_set::{Entry, BTreeSet}; +/// +/// let mut set = BTreeSet::new(); +/// set.extend(["a", "b", "c"]); +/// +/// let _entry_o = set.entry("a").insert(); +/// assert_eq!(set.len(), 3); +/// +/// // Existing key +/// match set.entry("a") { +/// Entry::Vacant(_) => unreachable!(), +/// Entry::Occupied(view) => { +/// assert_eq!(view.get(), &"a"); +/// } +/// } +/// +/// assert_eq!(set.len(), 3); +/// +/// // Existing key (take) +/// match set.entry("c") { +/// Entry::Vacant(_) => unreachable!(), +/// Entry::Occupied(view) => { +/// assert_eq!(view.remove(), "c"); +/// } +/// } +/// assert_eq!(set.get(&"c"), None); +/// assert_eq!(set.len(), 2); +/// ``` +#[unstable(feature = "btree_set_entry", issue = "133549")] +pub struct OccupiedEntry< + 'a, + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + pub(super) inner: map::OccupiedEntry<'a, T, SetValZST, A>, +} + +#[unstable(feature = "btree_set_entry", issue = "133549")] +impl Debug for OccupiedEntry<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OccupiedEntry").field("value", self.get()).finish() + } +} + +/// A view into a vacant entry in a `BTreeSet`. +/// It is part of the [`Entry`] enum. +/// +/// # Examples +/// +/// ``` +/// #![feature(btree_set_entry)] +/// +/// use std::collections::btree_set::{Entry, BTreeSet}; +/// +/// let mut set = BTreeSet::<&str>::new(); +/// +/// let entry_v = match set.entry("a") { +/// Entry::Vacant(view) => view, +/// Entry::Occupied(_) => unreachable!(), +/// }; +/// entry_v.insert(); +/// assert!(set.contains("a") && set.len() == 1); +/// +/// // Nonexistent key (insert) +/// match set.entry("b") { +/// Entry::Vacant(view) => view.insert(), +/// Entry::Occupied(_) => unreachable!(), +/// } +/// assert!(set.contains("b") && set.len() == 2); +/// ``` +#[unstable(feature = "btree_set_entry", issue = "133549")] +pub struct VacantEntry< + 'a, + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + pub(super) inner: map::VacantEntry<'a, T, SetValZST, A>, +} + +#[unstable(feature = "btree_set_entry", issue = "133549")] +impl Debug for VacantEntry<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("VacantEntry").field(self.get()).finish() + } +} + +impl<'a, T: Ord, A: Allocator + Clone> Entry<'a, T, A> { + /// Sets the value of the entry, and returns an `OccupiedEntry`. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// let entry = set.entry("horseyland").insert(); + /// + /// assert_eq!(entry.get(), &"horseyland"); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn insert(self) -> OccupiedEntry<'a, T, A> { + match self { + Occupied(entry) => entry, + Vacant(entry) => entry.insert_entry(), + } + } + + /// Ensures a value is in the entry by inserting if it was vacant. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// // nonexistent key + /// set.entry("poneyland").or_insert(); + /// assert!(set.contains("poneyland")); + /// + /// // existing key + /// set.entry("poneyland").or_insert(); + /// assert!(set.contains("poneyland")); + /// assert_eq!(set.len(), 1); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn or_insert(self) { + if let Vacant(entry) = self { + entry.insert(); + } + } + + /// Returns a reference to this entry's value. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// set.entry("poneyland").or_insert(); + /// + /// // existing key + /// assert_eq!(set.entry("poneyland").get(), &"poneyland"); + /// // nonexistent key + /// assert_eq!(set.entry("horseland").get(), &"horseland"); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn get(&self) -> &T { + match *self { + Occupied(ref entry) => entry.get(), + Vacant(ref entry) => entry.get(), + } + } +} + +impl<'a, T: Ord, A: Allocator + Clone> OccupiedEntry<'a, T, A> { + /// Gets a reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::btree_set::{Entry, BTreeSet}; + /// + /// let mut set = BTreeSet::new(); + /// set.entry("poneyland").or_insert(); + /// + /// match set.entry("poneyland") { + /// Entry::Vacant(_) => panic!(), + /// Entry::Occupied(entry) => assert_eq!(entry.get(), &"poneyland"), + /// } + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn get(&self) -> &T { + self.inner.key() + } + + /// Takes the value out of the entry, and returns it. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// use std::collections::btree_set::Entry; + /// + /// let mut set = BTreeSet::new(); + /// set.entry("poneyland").or_insert(); + /// + /// if let Entry::Occupied(o) = set.entry("poneyland") { + /// assert_eq!(o.remove(), "poneyland"); + /// } + /// + /// assert_eq!(set.contains("poneyland"), false); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn remove(self) -> T { + self.inner.remove_entry().0 + } +} + +impl<'a, T: Ord, A: Allocator + Clone> VacantEntry<'a, T, A> { + /// Gets a reference to the value that would be used when inserting + /// through the `VacantEntry`. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// assert_eq!(set.entry("poneyland").get(), &"poneyland"); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn get(&self) -> &T { + self.inner.key() + } + + /// Take ownership of the value. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::btree_set::{Entry, BTreeSet}; + /// + /// let mut set = BTreeSet::new(); + /// + /// match set.entry("poneyland") { + /// Entry::Occupied(_) => panic!(), + /// Entry::Vacant(v) => assert_eq!(v.into_value(), "poneyland"), + /// } + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn into_value(self) -> T { + self.inner.into_key() + } + + /// Sets the value of the entry with the VacantEntry's value. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// use std::collections::btree_set::Entry; + /// + /// let mut set = BTreeSet::new(); + /// + /// if let Entry::Vacant(o) = set.entry("poneyland") { + /// o.insert(); + /// } + /// assert!(set.contains("poneyland")); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "133549")] + pub fn insert(self) { + self.inner.insert(SetValZST); + } + + #[inline] + fn insert_entry(self) -> OccupiedEntry<'a, T, A> { + OccupiedEntry { inner: self.inner.insert_entry(SetValZST) } + } +} diff --git a/CoqOfRust/alloc/collections/btree/set/tests.rs b/CoqOfRust/alloc/collections/btree/set/tests.rs new file mode 100644 index 000000000..990044e06 --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/set/tests.rs @@ -0,0 +1,852 @@ +use std::ops::Bound::{Excluded, Included}; +use std::panic::{AssertUnwindSafe, catch_unwind}; + +use super::*; +use crate::testing::crash_test::{CrashTestDummy, Panic}; +use crate::testing::rng::DeterministicRng; + +#[test] +fn test_clone_eq() { + let mut m = BTreeSet::new(); + + m.insert(1); + m.insert(2); + + assert_eq!(m.clone(), m); +} + +#[test] +fn test_iter_min_max() { + let mut a = BTreeSet::new(); + assert_eq!(a.iter().min(), None); + assert_eq!(a.iter().max(), None); + assert_eq!(a.range(..).min(), None); + assert_eq!(a.range(..).max(), None); + assert_eq!(a.difference(&BTreeSet::new()).min(), None); + assert_eq!(a.difference(&BTreeSet::new()).max(), None); + assert_eq!(a.intersection(&a).min(), None); + assert_eq!(a.intersection(&a).max(), None); + assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), None); + assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), None); + assert_eq!(a.union(&a).min(), None); + assert_eq!(a.union(&a).max(), None); + a.insert(1); + a.insert(2); + assert_eq!(a.iter().min(), Some(&1)); + assert_eq!(a.iter().max(), Some(&2)); + assert_eq!(a.range(..).min(), Some(&1)); + assert_eq!(a.range(..).max(), Some(&2)); + assert_eq!(a.difference(&BTreeSet::new()).min(), Some(&1)); + assert_eq!(a.difference(&BTreeSet::new()).max(), Some(&2)); + assert_eq!(a.intersection(&a).min(), Some(&1)); + assert_eq!(a.intersection(&a).max(), Some(&2)); + assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), Some(&1)); + assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), Some(&2)); + assert_eq!(a.union(&a).min(), Some(&1)); + assert_eq!(a.union(&a).max(), Some(&2)); +} + +fn check(a: &[i32], b: &[i32], expected: &[i32], f: F) +where + F: FnOnce(&BTreeSet, &BTreeSet, &mut dyn FnMut(&i32) -> bool) -> bool, +{ + let mut set_a = BTreeSet::new(); + let mut set_b = BTreeSet::new(); + + for x in a { + assert!(set_a.insert(*x)) + } + for y in b { + assert!(set_b.insert(*y)) + } + + let mut i = 0; + f(&set_a, &set_b, &mut |&x| { + if i < expected.len() { + assert_eq!(x, expected[i]); + } + i += 1; + true + }); + assert_eq!(i, expected.len()); +} + +#[test] +fn test_intersection() { + fn check_intersection(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.intersection(y).all(f)) + } + + check_intersection(&[], &[], &[]); + check_intersection(&[1, 2, 3], &[], &[]); + check_intersection(&[], &[1, 2, 3], &[]); + check_intersection(&[2], &[1, 2, 3], &[2]); + check_intersection(&[1, 2, 3], &[2], &[2]); + check_intersection(&[11, 1, 3, 77, 103, 5, -5], &[2, 11, 77, -9, -42, 5, 3], &[3, 5, 11, 77]); + + if cfg!(miri) { + // Miri is too slow + return; + } + + let large = Vec::from_iter(0..100); + check_intersection(&[], &large, &[]); + check_intersection(&large, &[], &[]); + check_intersection(&[-1], &large, &[]); + check_intersection(&large, &[-1], &[]); + check_intersection(&[0], &large, &[0]); + check_intersection(&large, &[0], &[0]); + check_intersection(&[99], &large, &[99]); + check_intersection(&large, &[99], &[99]); + check_intersection(&[100], &large, &[]); + check_intersection(&large, &[100], &[]); + check_intersection(&[11, 5000, 1, 3, 77, 8924], &large, &[1, 3, 11, 77]); +} + +#[test] +fn test_intersection_size_hint() { + let x = BTreeSet::from([3, 4]); + let y = BTreeSet::from([1, 2, 3]); + let mut iter = x.intersection(&y); + assert_eq!(iter.size_hint(), (1, Some(1))); + assert_eq!(iter.next(), Some(&3)); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + + iter = y.intersection(&y); + assert_eq!(iter.size_hint(), (0, Some(3))); + assert_eq!(iter.next(), Some(&1)); + assert_eq!(iter.size_hint(), (0, Some(2))); +} + +#[test] +fn test_difference() { + fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.difference(y).all(f)) + } + + check_difference(&[], &[], &[]); + check_difference(&[1, 12], &[], &[1, 12]); + check_difference(&[], &[1, 2, 3, 9], &[]); + check_difference(&[1, 3, 5, 9, 11], &[3, 9], &[1, 5, 11]); + check_difference(&[1, 3, 5, 9, 11], &[3, 6, 9], &[1, 5, 11]); + check_difference(&[1, 3, 5, 9, 11], &[0, 1], &[3, 5, 9, 11]); + check_difference(&[1, 3, 5, 9, 11], &[11, 12], &[1, 3, 5, 9]); + check_difference(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 14, 23, 34, 38, 39, 50], &[ + 11, 22, 33, 40, 42, + ]); + + if cfg!(miri) { + // Miri is too slow + return; + } + + let large = Vec::from_iter(0..100); + check_difference(&[], &large, &[]); + check_difference(&[-1], &large, &[-1]); + check_difference(&[0], &large, &[]); + check_difference(&[99], &large, &[]); + check_difference(&[100], &large, &[100]); + check_difference(&[11, 5000, 1, 3, 77, 8924], &large, &[5000, 8924]); + check_difference(&large, &[], &large); + check_difference(&large, &[-1], &large); + check_difference(&large, &[100], &large); +} + +#[test] +fn test_difference_size_hint() { + let s246 = BTreeSet::from([2, 4, 6]); + let s23456 = BTreeSet::from_iter(2..=6); + let mut iter = s246.difference(&s23456); + assert_eq!(iter.size_hint(), (0, Some(3))); + assert_eq!(iter.next(), None); + + let s12345 = BTreeSet::from_iter(1..=5); + iter = s246.difference(&s12345); + assert_eq!(iter.size_hint(), (0, Some(3))); + assert_eq!(iter.next(), Some(&6)); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + + let s34567 = BTreeSet::from_iter(3..=7); + iter = s246.difference(&s34567); + assert_eq!(iter.size_hint(), (0, Some(3))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (0, Some(2))); + assert_eq!(iter.next(), None); + + let s1 = BTreeSet::from_iter(-9..=1); + iter = s246.difference(&s1); + assert_eq!(iter.size_hint(), (3, Some(3))); + + let s2 = BTreeSet::from_iter(-9..=2); + iter = s246.difference(&s2); + assert_eq!(iter.size_hint(), (2, Some(2))); + assert_eq!(iter.next(), Some(&4)); + assert_eq!(iter.size_hint(), (1, Some(1))); + + let s23 = BTreeSet::from([2, 3]); + iter = s246.difference(&s23); + assert_eq!(iter.size_hint(), (1, Some(3))); + assert_eq!(iter.next(), Some(&4)); + assert_eq!(iter.size_hint(), (1, Some(1))); + + let s4 = BTreeSet::from([4]); + iter = s246.difference(&s4); + assert_eq!(iter.size_hint(), (2, Some(3))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (1, Some(2))); + assert_eq!(iter.next(), Some(&6)); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + + let s56 = BTreeSet::from([5, 6]); + iter = s246.difference(&s56); + assert_eq!(iter.size_hint(), (1, Some(3))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (0, Some(2))); + + let s6 = BTreeSet::from_iter(6..=19); + iter = s246.difference(&s6); + assert_eq!(iter.size_hint(), (2, Some(2))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (1, Some(1))); + + let s7 = BTreeSet::from_iter(7..=19); + iter = s246.difference(&s7); + assert_eq!(iter.size_hint(), (3, Some(3))); +} + +#[test] +fn test_symmetric_difference() { + fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f)) + } + + check_symmetric_difference(&[], &[], &[]); + check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]); + check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]); + check_symmetric_difference(&[1, 3, 5, 9, 11], &[-2, 3, 9, 14, 22], &[-2, 1, 5, 11, 14, 22]); +} + +#[test] +fn test_symmetric_difference_size_hint() { + let x = BTreeSet::from([2, 4]); + let y = BTreeSet::from([1, 2, 3]); + let mut iter = x.symmetric_difference(&y); + assert_eq!(iter.size_hint(), (0, Some(5))); + assert_eq!(iter.next(), Some(&1)); + assert_eq!(iter.size_hint(), (0, Some(4))); + assert_eq!(iter.next(), Some(&3)); + assert_eq!(iter.size_hint(), (0, Some(1))); +} + +#[test] +fn test_union() { + fn check_union(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.union(y).all(f)) + } + + check_union(&[], &[], &[]); + check_union(&[1, 2, 3], &[2], &[1, 2, 3]); + check_union(&[2], &[1, 2, 3], &[1, 2, 3]); + check_union(&[1, 3, 5, 9, 11, 16, 19, 24], &[-2, 1, 5, 9, 13, 19], &[ + -2, 1, 3, 5, 9, 11, 13, 16, 19, 24, + ]); +} + +#[test] +fn test_union_size_hint() { + let x = BTreeSet::from([2, 4]); + let y = BTreeSet::from([1, 2, 3]); + let mut iter = x.union(&y); + assert_eq!(iter.size_hint(), (3, Some(5))); + assert_eq!(iter.next(), Some(&1)); + assert_eq!(iter.size_hint(), (2, Some(4))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (1, Some(2))); +} + +#[test] +// Only tests the simple function definition with respect to intersection +fn test_is_disjoint() { + let one = BTreeSet::from([1]); + let two = BTreeSet::from([2]); + assert!(one.is_disjoint(&two)); +} + +#[test] +// Also implicitly tests the trivial function definition of is_superset +fn test_is_subset() { + fn is_subset(a: &[i32], b: &[i32]) -> bool { + let set_a = BTreeSet::from_iter(a.iter()); + let set_b = BTreeSet::from_iter(b.iter()); + set_a.is_subset(&set_b) + } + + assert_eq!(is_subset(&[], &[]), true); + assert_eq!(is_subset(&[], &[1, 2]), true); + assert_eq!(is_subset(&[0], &[1, 2]), false); + assert_eq!(is_subset(&[1], &[1, 2]), true); + assert_eq!(is_subset(&[2], &[1, 2]), true); + assert_eq!(is_subset(&[3], &[1, 2]), false); + assert_eq!(is_subset(&[1, 2], &[1]), false); + assert_eq!(is_subset(&[1, 2], &[1, 2]), true); + assert_eq!(is_subset(&[1, 2], &[2, 3]), false); + assert_eq!( + is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 33, 34, 38, 39, 40, 42]), + true + ); + assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 34, 38]), false); + + if cfg!(miri) { + // Miri is too slow + return; + } + + let large = Vec::from_iter(0..100); + assert_eq!(is_subset(&[], &large), true); + assert_eq!(is_subset(&large, &[]), false); + assert_eq!(is_subset(&[-1], &large), false); + assert_eq!(is_subset(&[0], &large), true); + assert_eq!(is_subset(&[1, 2], &large), true); + assert_eq!(is_subset(&[99, 100], &large), false); +} + +#[test] +fn test_is_superset() { + fn is_superset(a: &[i32], b: &[i32]) -> bool { + let set_a = BTreeSet::from_iter(a.iter()); + let set_b = BTreeSet::from_iter(b.iter()); + set_a.is_superset(&set_b) + } + + assert_eq!(is_superset(&[], &[]), true); + assert_eq!(is_superset(&[], &[1, 2]), false); + assert_eq!(is_superset(&[0], &[1, 2]), false); + assert_eq!(is_superset(&[1], &[1, 2]), false); + assert_eq!(is_superset(&[4], &[1, 2]), false); + assert_eq!(is_superset(&[1, 4], &[1, 2]), false); + assert_eq!(is_superset(&[1, 2], &[1, 2]), true); + assert_eq!(is_superset(&[1, 2, 3], &[1, 3]), true); + assert_eq!(is_superset(&[1, 2, 3], &[]), true); + assert_eq!(is_superset(&[-1, 1, 2, 3], &[-1, 3]), true); + + if cfg!(miri) { + // Miri is too slow + return; + } + + let large = Vec::from_iter(0..100); + assert_eq!(is_superset(&[], &large), false); + assert_eq!(is_superset(&large, &[]), true); + assert_eq!(is_superset(&large, &[1]), true); + assert_eq!(is_superset(&large, &[50, 99]), true); + assert_eq!(is_superset(&large, &[100]), false); + assert_eq!(is_superset(&large, &[0, 99]), true); + assert_eq!(is_superset(&[-1], &large), false); + assert_eq!(is_superset(&[0], &large), false); + assert_eq!(is_superset(&[99, 100], &large), false); +} + +#[test] +fn test_retain() { + let mut set = BTreeSet::from([1, 2, 3, 4, 5, 6]); + set.retain(|&k| k % 2 == 0); + assert_eq!(set.len(), 3); + assert!(set.contains(&2)); + assert!(set.contains(&4)); + assert!(set.contains(&6)); +} + +#[test] +fn test_extract_if() { + let mut x = BTreeSet::from([1]); + let mut y = BTreeSet::from([1]); + + x.extract_if(|_| true).for_each(drop); + y.extract_if(|_| false).for_each(drop); + assert_eq!(x.len(), 0); + assert_eq!(y.len(), 1); +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_extract_if_drop_panic_leak() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut set = BTreeSet::new(); + set.insert(a.spawn(Panic::Never)); + set.insert(b.spawn(Panic::InDrop)); + set.insert(c.spawn(Panic::Never)); + + catch_unwind(move || set.extract_if(|dummy| dummy.query(true)).for_each(drop)).ok(); + + assert_eq!(a.queried(), 1); + assert_eq!(b.queried(), 1); + assert_eq!(c.queried(), 0); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); + assert_eq!(c.dropped(), 1); +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_extract_if_pred_panic_leak() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut set = BTreeSet::new(); + set.insert(a.spawn(Panic::Never)); + set.insert(b.spawn(Panic::InQuery)); + set.insert(c.spawn(Panic::InQuery)); + + catch_unwind(AssertUnwindSafe(|| set.extract_if(|dummy| dummy.query(true)).for_each(drop))) + .ok(); + + assert_eq!(a.queried(), 1); + assert_eq!(b.queried(), 1); + assert_eq!(c.queried(), 0); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 0); + assert_eq!(set.len(), 2); + assert_eq!(set.first().unwrap().id(), 1); + assert_eq!(set.last().unwrap().id(), 2); +} + +#[test] +fn test_clear() { + let mut x = BTreeSet::new(); + x.insert(1); + + x.clear(); + assert!(x.is_empty()); +} +#[test] +fn test_remove() { + let mut x = BTreeSet::new(); + assert!(x.is_empty()); + + x.insert(1); + x.insert(2); + x.insert(3); + x.insert(4); + + assert_eq!(x.remove(&2), true); + assert_eq!(x.remove(&0), false); + assert_eq!(x.remove(&5), false); + assert_eq!(x.remove(&1), true); + assert_eq!(x.remove(&2), false); + assert_eq!(x.remove(&3), true); + assert_eq!(x.remove(&4), true); + assert_eq!(x.remove(&4), false); + assert!(x.is_empty()); +} + +#[test] +fn test_zip() { + let mut x = BTreeSet::new(); + x.insert(5); + x.insert(12); + x.insert(11); + + let mut y = BTreeSet::new(); + y.insert("foo"); + y.insert("bar"); + + let x = x; + let y = y; + let mut z = x.iter().zip(&y); + + assert_eq!(z.next().unwrap(), (&5, &("bar"))); + assert_eq!(z.next().unwrap(), (&11, &("foo"))); + assert!(z.next().is_none()); +} + +#[test] +fn test_from_iter() { + let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + + let set = BTreeSet::from_iter(xs.iter()); + + for x in &xs { + assert!(set.contains(x)); + } +} + +#[test] +fn test_show() { + let mut set = BTreeSet::new(); + let empty = BTreeSet::::new(); + + set.insert(1); + set.insert(2); + + let set_str = format!("{set:?}"); + + assert_eq!(set_str, "{1, 2}"); + assert_eq!(format!("{empty:?}"), "{}"); +} + +#[test] +fn test_extend_ref() { + let mut a = BTreeSet::new(); + a.insert(1); + + a.extend(&[2, 3, 4]); + + assert_eq!(a.len(), 4); + assert!(a.contains(&1)); + assert!(a.contains(&2)); + assert!(a.contains(&3)); + assert!(a.contains(&4)); + + let mut b = BTreeSet::new(); + b.insert(5); + b.insert(6); + + a.extend(&b); + + assert_eq!(a.len(), 6); + assert!(a.contains(&1)); + assert!(a.contains(&2)); + assert!(a.contains(&3)); + assert!(a.contains(&4)); + assert!(a.contains(&5)); + assert!(a.contains(&6)); +} + +#[test] +fn test_recovery() { + #[derive(Debug)] + struct Foo(&'static str, #[allow(dead_code)] i32); + + impl PartialEq for Foo { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } + } + + impl Eq for Foo {} + + impl PartialOrd for Foo { + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } + } + + impl Ord for Foo { + fn cmp(&self, other: &Self) -> Ordering { + self.0.cmp(&other.0) + } + } + + let mut s = BTreeSet::new(); + assert_eq!(s.replace(Foo("a", 1)), None); + assert_eq!(s.len(), 1); + assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1))); + assert_eq!(s.len(), 1); + + { + let mut it = s.iter(); + assert_eq!(it.next(), Some(&Foo("a", 2))); + assert_eq!(it.next(), None); + } + + assert_eq!(s.get(&Foo("a", 1)), Some(&Foo("a", 2))); + assert_eq!(s.take(&Foo("a", 1)), Some(Foo("a", 2))); + assert_eq!(s.len(), 0); + + assert_eq!(s.get(&Foo("a", 1)), None); + assert_eq!(s.take(&Foo("a", 1)), None); + + assert_eq!(s.iter().next(), None); +} + +#[allow(dead_code)] +fn assert_covariance() { + fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> { + v + } + fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> { + v + } + fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> { + v + } + fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> { + v + } + // not applied to Difference, Intersection, SymmetricDifference, Union +} + +#[allow(dead_code)] +fn assert_sync() { + fn set(v: &BTreeSet) -> impl Sync + '_ { + v + } + + fn iter(v: &BTreeSet) -> impl Sync + '_ { + v.iter() + } + + fn into_iter(v: BTreeSet) -> impl Sync { + v.into_iter() + } + + fn range(v: &BTreeSet) -> impl Sync + '_ { + v.range(..) + } + + fn extract_if(v: &mut BTreeSet) -> impl Sync + '_ { + v.extract_if(|_| false) + } + + fn difference(v: &BTreeSet) -> impl Sync + '_ { + v.difference(&v) + } + + fn intersection(v: &BTreeSet) -> impl Sync + '_ { + v.intersection(&v) + } + + fn symmetric_difference(v: &BTreeSet) -> impl Sync + '_ { + v.symmetric_difference(&v) + } + + fn union(v: &BTreeSet) -> impl Sync + '_ { + v.union(&v) + } +} + +#[allow(dead_code)] +fn assert_send() { + fn set(v: BTreeSet) -> impl Send { + v + } + + fn iter(v: &BTreeSet) -> impl Send + '_ { + v.iter() + } + + fn into_iter(v: BTreeSet) -> impl Send { + v.into_iter() + } + + fn range(v: &BTreeSet) -> impl Send + '_ { + v.range(..) + } + + fn extract_if(v: &mut BTreeSet) -> impl Send + '_ { + v.extract_if(|_| false) + } + + fn difference(v: &BTreeSet) -> impl Send + '_ { + v.difference(&v) + } + + fn intersection(v: &BTreeSet) -> impl Send + '_ { + v.intersection(&v) + } + + fn symmetric_difference(v: &BTreeSet) -> impl Send + '_ { + v.symmetric_difference(&v) + } + + fn union(v: &BTreeSet) -> impl Send + '_ { + v.union(&v) + } +} + +#[allow(dead_code)] +// Check that the member-like functions conditionally provided by #[derive()] +// are not overridden by genuine member functions with a different signature. +fn assert_derives() { + fn hash(v: BTreeSet, state: &mut H) { + v.hash(state); + // Tested much more thoroughly outside the crate in btree_set_hash.rs + } + fn eq(v: BTreeSet) { + let _ = v.eq(&v); + } + fn ne(v: BTreeSet) { + let _ = v.ne(&v); + } + fn cmp(v: BTreeSet) { + let _ = v.cmp(&v); + } + fn min(v: BTreeSet, w: BTreeSet) { + let _ = v.min(w); + } + fn max(v: BTreeSet, w: BTreeSet) { + let _ = v.max(w); + } + fn clamp(v: BTreeSet, w: BTreeSet, x: BTreeSet) { + let _ = v.clamp(w, x); + } + fn partial_cmp(v: &BTreeSet) { + let _ = v.partial_cmp(&v); + } +} + +#[test] +fn test_ord_absence() { + fn set(mut set: BTreeSet) { + let _ = set.is_empty(); + let _ = set.len(); + set.clear(); + let _ = set.iter(); + let _ = set.into_iter(); + } + + fn set_debug(set: BTreeSet) { + let _ = format!("{set:?}"); + let _ = format!("{:?}", set.iter()); + let _ = format!("{:?}", set.into_iter()); + } + + fn set_clone(mut set: BTreeSet) { + set.clone_from(&set.clone()); + } + + #[derive(Debug, Clone)] + struct NonOrd; + set(BTreeSet::::new()); + set_debug(BTreeSet::::new()); + set_clone(BTreeSet::::default()); +} + +#[test] +fn test_append() { + let mut a = BTreeSet::new(); + a.insert(1); + a.insert(2); + a.insert(3); + + let mut b = BTreeSet::new(); + b.insert(3); + b.insert(4); + b.insert(5); + + a.append(&mut b); + + assert_eq!(a.len(), 5); + assert_eq!(b.len(), 0); + + assert_eq!(a.contains(&1), true); + assert_eq!(a.contains(&2), true); + assert_eq!(a.contains(&3), true); + assert_eq!(a.contains(&4), true); + assert_eq!(a.contains(&5), true); +} + +#[test] +fn test_first_last() { + let mut a = BTreeSet::new(); + assert_eq!(a.first(), None); + assert_eq!(a.last(), None); + a.insert(1); + assert_eq!(a.first(), Some(&1)); + assert_eq!(a.last(), Some(&1)); + a.insert(2); + assert_eq!(a.first(), Some(&1)); + assert_eq!(a.last(), Some(&2)); + for i in 3..=12 { + a.insert(i); + } + assert_eq!(a.first(), Some(&1)); + assert_eq!(a.last(), Some(&12)); + assert_eq!(a.pop_first(), Some(1)); + assert_eq!(a.pop_last(), Some(12)); + assert_eq!(a.pop_first(), Some(2)); + assert_eq!(a.pop_last(), Some(11)); + assert_eq!(a.pop_first(), Some(3)); + assert_eq!(a.pop_last(), Some(10)); + assert_eq!(a.pop_first(), Some(4)); + assert_eq!(a.pop_first(), Some(5)); + assert_eq!(a.pop_first(), Some(6)); + assert_eq!(a.pop_first(), Some(7)); + assert_eq!(a.pop_first(), Some(8)); + assert_eq!(a.clone().pop_last(), Some(9)); + assert_eq!(a.pop_first(), Some(9)); + assert_eq!(a.pop_first(), None); + assert_eq!(a.pop_last(), None); +} + +// Unlike the function with the same name in map/tests, returns no values. +// Which also means it returns different predetermined pseudo-random keys, +// and the test cases using this function explore slightly different trees. +fn rand_data(len: usize) -> Vec { + let mut rng = DeterministicRng::new(); + Vec::from_iter((0..len).map(|_| rng.next())) +} + +#[test] +fn test_split_off_empty_right() { + let mut data = rand_data(173); + + let mut set = BTreeSet::from_iter(data.clone()); + let right = set.split_off(&(data.iter().max().unwrap() + 1)); + + data.sort(); + assert!(set.into_iter().eq(data)); + assert!(right.into_iter().eq(None)); +} + +#[test] +fn test_split_off_empty_left() { + let mut data = rand_data(314); + + let mut set = BTreeSet::from_iter(data.clone()); + let right = set.split_off(data.iter().min().unwrap()); + + data.sort(); + assert!(set.into_iter().eq(None)); + assert!(right.into_iter().eq(data)); +} + +#[test] +fn test_split_off_large_random_sorted() { + // Miri is too slow + let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) }; + // special case with maximum height. + data.sort(); + + let mut set = BTreeSet::from_iter(data.clone()); + let key = data[data.len() / 2]; + let right = set.split_off(&key); + + assert!(set.into_iter().eq(data.clone().into_iter().filter(|x| *x < key))); + assert!(right.into_iter().eq(data.into_iter().filter(|x| *x >= key))); +} + +#[test] +fn from_array() { + let set = BTreeSet::from([1, 2, 3, 4]); + let unordered_duplicates = BTreeSet::from([4, 1, 4, 3, 2]); + assert_eq!(set, unordered_duplicates); +} + +#[should_panic(expected = "range start is greater than range end in BTreeSet")] +#[test] +fn test_range_panic_1() { + let mut set = BTreeSet::new(); + set.insert(3); + set.insert(5); + set.insert(8); + + let _invalid_range = set.range((Included(&8), Included(&3))); +} + +#[should_panic(expected = "range start and end are equal and excluded in BTreeSet")] +#[test] +fn test_range_panic_2() { + let mut set = BTreeSet::new(); + set.insert(3); + set.insert(5); + set.insert(8); + + let _invalid_range = set.range((Excluded(&5), Excluded(&5))); +} diff --git a/CoqOfRust/alloc/collections/btree/set_val.rs b/CoqOfRust/alloc/collections/btree/set_val.rs new file mode 100644 index 000000000..cf30160bf --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/set_val.rs @@ -0,0 +1,29 @@ +/// Zero-Sized Type (ZST) for internal `BTreeSet` values. +/// Used instead of `()` to differentiate between: +/// * `BTreeMap` (possible user-defined map) +/// * `BTreeMap` (internal set representation) +#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Default)] +pub(super) struct SetValZST; + +/// A trait to differentiate between `BTreeMap` and `BTreeSet` values. +/// Returns `true` only for type `SetValZST`, `false` for all other types (blanket implementation). +/// `TypeId` requires a `'static` lifetime, use of this trait avoids that restriction. +/// +/// [`TypeId`]: std::any::TypeId +pub(super) trait IsSetVal { + fn is_set_val() -> bool; +} + +// Blanket implementation +impl IsSetVal for V { + default fn is_set_val() -> bool { + false + } +} + +// Specialization +impl IsSetVal for SetValZST { + fn is_set_val() -> bool { + true + } +} diff --git a/CoqOfRust/alloc/collections/btree/split.rs b/CoqOfRust/alloc/collections/btree/split.rs new file mode 100644 index 000000000..c188ed1da --- /dev/null +++ b/CoqOfRust/alloc/collections/btree/split.rs @@ -0,0 +1,75 @@ +use core::alloc::Allocator; +use core::borrow::Borrow; + +use super::node::ForceResult::*; +use super::node::Root; +use super::search::SearchResult::*; + +impl Root { + /// Calculates the length of both trees that result from splitting up + /// a given number of distinct key-value pairs. + pub fn calc_split_length( + total_num: usize, + root_a: &Root, + root_b: &Root, + ) -> (usize, usize) { + let (length_a, length_b); + if root_a.height() < root_b.height() { + length_a = root_a.reborrow().calc_length(); + length_b = total_num - length_a; + debug_assert_eq!(length_b, root_b.reborrow().calc_length()); + } else { + length_b = root_b.reborrow().calc_length(); + length_a = total_num - length_b; + debug_assert_eq!(length_a, root_a.reborrow().calc_length()); + } + (length_a, length_b) + } + + /// Split off a tree with key-value pairs at and after the given key. + /// The result is meaningful only if the tree is ordered by key, + /// and if the ordering of `Q` corresponds to that of `K`. + /// If `self` respects all `BTreeMap` tree invariants, then both + /// `self` and the returned tree will respect those invariants. + pub fn split_off(&mut self, key: &Q, alloc: A) -> Self + where + K: Borrow, + { + let left_root = self; + let mut right_root = Root::new_pillar(left_root.height(), alloc.clone()); + let mut left_node = left_root.borrow_mut(); + let mut right_node = right_root.borrow_mut(); + + loop { + let mut split_edge = match left_node.search_node(key) { + // key is going to the right tree + Found(kv) => kv.left_edge(), + GoDown(edge) => edge, + }; + + split_edge.move_suffix(&mut right_node); + + match (split_edge.force(), right_node.force()) { + (Internal(edge), Internal(node)) => { + left_node = edge.descend(); + right_node = node.first_edge().descend(); + } + (Leaf(_), Leaf(_)) => break, + _ => unreachable!(), + } + } + + left_root.fix_right_border(alloc.clone()); + right_root.fix_left_border(alloc); + right_root + } + + /// Creates a tree consisting of empty nodes. + fn new_pillar(height: usize, alloc: A) -> Self { + let mut root = Root::new(alloc.clone()); + for _ in 0..height { + root.push_internal_level(alloc.clone()); + } + root + } +} diff --git a/CoqOfRust/alloc/collections/linked_list.rs b/CoqOfRust/alloc/collections/linked_list.rs new file mode 100644 index 000000000..ca0ea1ec8 --- /dev/null +++ b/CoqOfRust/alloc/collections/linked_list.rs @@ -0,0 +1,2243 @@ +//! A doubly-linked list with owned nodes. +//! +//! The `LinkedList` allows pushing and popping elements at either end +//! in constant time. +//! +//! NOTE: It is almost always better to use [`Vec`] or [`VecDeque`] because +//! array-based containers are generally faster, +//! more memory efficient, and make better use of CPU cache. +//! +//! [`Vec`]: crate::vec::Vec +//! [`VecDeque`]: super::vec_deque::VecDeque + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::cmp::Ordering; +use core::hash::{Hash, Hasher}; +use core::iter::FusedIterator; +use core::marker::PhantomData; +use core::ptr::NonNull; +use core::{fmt, mem}; + +use super::SpecExtend; +use crate::alloc::{Allocator, Global}; +use crate::boxed::Box; + +#[cfg(test)] +mod tests; + +/// A doubly-linked list with owned nodes. +/// +/// The `LinkedList` allows pushing and popping elements at either end +/// in constant time. +/// +/// A `LinkedList` with a known list of items can be initialized from an array: +/// ``` +/// use std::collections::LinkedList; +/// +/// let list = LinkedList::from([1, 2, 3]); +/// ``` +/// +/// NOTE: It is almost always better to use [`Vec`] or [`VecDeque`] because +/// array-based containers are generally faster, +/// more memory efficient, and make better use of CPU cache. +/// +/// [`Vec`]: crate::vec::Vec +/// [`VecDeque`]: super::vec_deque::VecDeque +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "LinkedList")] +#[rustc_insignificant_dtor] +pub struct LinkedList< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + head: Option>>, + tail: Option>>, + len: usize, + alloc: A, + marker: PhantomData, A>>, +} + +struct Node { + next: Option>>, + prev: Option>>, + element: T, +} + +/// An iterator over the elements of a `LinkedList`. +/// +/// This `struct` is created by [`LinkedList::iter()`]. See its +/// documentation for more. +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Iter<'a, T: 'a> { + head: Option>>, + tail: Option>>, + len: usize, + marker: PhantomData<&'a Node>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Iter<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Iter") + .field(&*mem::ManuallyDrop::new(LinkedList { + head: self.head, + tail: self.tail, + len: self.len, + alloc: Global, + marker: PhantomData, + })) + .field(&self.len) + .finish() + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Iter<'_, T> { + fn clone(&self) -> Self { + Iter { ..*self } + } +} + +/// A mutable iterator over the elements of a `LinkedList`. +/// +/// This `struct` is created by [`LinkedList::iter_mut()`]. See its +/// documentation for more. +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IterMut<'a, T: 'a> { + head: Option>>, + tail: Option>>, + len: usize, + marker: PhantomData<&'a mut Node>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for IterMut<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IterMut") + .field(&*mem::ManuallyDrop::new(LinkedList { + head: self.head, + tail: self.tail, + len: self.len, + alloc: Global, + marker: PhantomData, + })) + .field(&self.len) + .finish() + } +} + +/// An owning iterator over the elements of a `LinkedList`. +/// +/// This `struct` is created by the [`into_iter`] method on [`LinkedList`] +/// (provided by the [`IntoIterator`] trait). See its documentation for more. +/// +/// [`into_iter`]: LinkedList::into_iter +#[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IntoIter< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + list: LinkedList, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoIter").field(&self.list).finish() + } +} + +impl Node { + fn new(element: T) -> Self { + Node { next: None, prev: None, element } + } + + fn into_element(self: Box) -> T { + self.element + } +} + +// private methods +impl LinkedList { + /// Adds the given node to the front of the list. + /// + /// # Safety + /// `node` must point to a valid node that was boxed and leaked using the list's allocator. + /// This method takes ownership of the node, so the pointer should not be used again. + #[inline] + unsafe fn push_front_node(&mut self, node: NonNull>) { + // This method takes care not to create mutable references to whole nodes, + // to maintain validity of aliasing pointers into `element`. + unsafe { + (*node.as_ptr()).next = self.head; + (*node.as_ptr()).prev = None; + let node = Some(node); + + match self.head { + None => self.tail = node, + // Not creating new mutable (unique!) references overlapping `element`. + Some(head) => (*head.as_ptr()).prev = node, + } + + self.head = node; + self.len += 1; + } + } + + /// Removes and returns the node at the front of the list. + #[inline] + fn pop_front_node(&mut self) -> Option, &A>> { + // This method takes care not to create mutable references to whole nodes, + // to maintain validity of aliasing pointers into `element`. + self.head.map(|node| unsafe { + let node = Box::from_raw_in(node.as_ptr(), &self.alloc); + self.head = node.next; + + match self.head { + None => self.tail = None, + // Not creating new mutable (unique!) references overlapping `element`. + Some(head) => (*head.as_ptr()).prev = None, + } + + self.len -= 1; + node + }) + } + + /// Adds the given node to the back of the list. + /// + /// # Safety + /// `node` must point to a valid node that was boxed and leaked using the list's allocator. + /// This method takes ownership of the node, so the pointer should not be used again. + #[inline] + unsafe fn push_back_node(&mut self, node: NonNull>) { + // This method takes care not to create mutable references to whole nodes, + // to maintain validity of aliasing pointers into `element`. + unsafe { + (*node.as_ptr()).next = None; + (*node.as_ptr()).prev = self.tail; + let node = Some(node); + + match self.tail { + None => self.head = node, + // Not creating new mutable (unique!) references overlapping `element`. + Some(tail) => (*tail.as_ptr()).next = node, + } + + self.tail = node; + self.len += 1; + } + } + + /// Removes and returns the node at the back of the list. + #[inline] + fn pop_back_node(&mut self) -> Option, &A>> { + // This method takes care not to create mutable references to whole nodes, + // to maintain validity of aliasing pointers into `element`. + self.tail.map(|node| unsafe { + let node = Box::from_raw_in(node.as_ptr(), &self.alloc); + self.tail = node.prev; + + match self.tail { + None => self.head = None, + // Not creating new mutable (unique!) references overlapping `element`. + Some(tail) => (*tail.as_ptr()).next = None, + } + + self.len -= 1; + node + }) + } + + /// Unlinks the specified node from the current list. + /// + /// Warning: this will not check that the provided node belongs to the current list. + /// + /// This method takes care not to create mutable references to `element`, to + /// maintain validity of aliasing pointers. + #[inline] + unsafe fn unlink_node(&mut self, mut node: NonNull>) { + let node = unsafe { node.as_mut() }; // this one is ours now, we can create an &mut. + + // Not creating new mutable (unique!) references overlapping `element`. + match node.prev { + Some(prev) => unsafe { (*prev.as_ptr()).next = node.next }, + // this node is the head node + None => self.head = node.next, + }; + + match node.next { + Some(next) => unsafe { (*next.as_ptr()).prev = node.prev }, + // this node is the tail node + None => self.tail = node.prev, + }; + + self.len -= 1; + } + + /// Splices a series of nodes between two existing nodes. + /// + /// Warning: this will not check that the provided node belongs to the two existing lists. + #[inline] + unsafe fn splice_nodes( + &mut self, + existing_prev: Option>>, + existing_next: Option>>, + mut splice_start: NonNull>, + mut splice_end: NonNull>, + splice_length: usize, + ) { + // This method takes care not to create multiple mutable references to whole nodes at the same time, + // to maintain validity of aliasing pointers into `element`. + if let Some(mut existing_prev) = existing_prev { + unsafe { + existing_prev.as_mut().next = Some(splice_start); + } + } else { + self.head = Some(splice_start); + } + if let Some(mut existing_next) = existing_next { + unsafe { + existing_next.as_mut().prev = Some(splice_end); + } + } else { + self.tail = Some(splice_end); + } + unsafe { + splice_start.as_mut().prev = existing_prev; + splice_end.as_mut().next = existing_next; + } + + self.len += splice_length; + } + + /// Detaches all nodes from a linked list as a series of nodes. + #[inline] + fn detach_all_nodes(mut self) -> Option<(NonNull>, NonNull>, usize)> { + let head = self.head.take(); + let tail = self.tail.take(); + let len = mem::replace(&mut self.len, 0); + if let Some(head) = head { + // SAFETY: In a LinkedList, either both the head and tail are None because + // the list is empty, or both head and tail are Some because the list is populated. + // Since we have verified the head is Some, we are sure the tail is Some too. + let tail = unsafe { tail.unwrap_unchecked() }; + Some((head, tail, len)) + } else { + None + } + } + + #[inline] + unsafe fn split_off_before_node( + &mut self, + split_node: Option>>, + at: usize, + ) -> Self + where + A: Clone, + { + // The split node is the new head node of the second part + if let Some(mut split_node) = split_node { + let first_part_head; + let first_part_tail; + unsafe { + first_part_tail = split_node.as_mut().prev.take(); + } + if let Some(mut tail) = first_part_tail { + unsafe { + tail.as_mut().next = None; + } + first_part_head = self.head; + } else { + first_part_head = None; + } + + let first_part = LinkedList { + head: first_part_head, + tail: first_part_tail, + len: at, + alloc: self.alloc.clone(), + marker: PhantomData, + }; + + // Fix the head ptr of the second part + self.head = Some(split_node); + self.len = self.len - at; + + first_part + } else { + mem::replace(self, LinkedList::new_in(self.alloc.clone())) + } + } + + #[inline] + unsafe fn split_off_after_node( + &mut self, + split_node: Option>>, + at: usize, + ) -> Self + where + A: Clone, + { + // The split node is the new tail node of the first part and owns + // the head of the second part. + if let Some(mut split_node) = split_node { + let second_part_head; + let second_part_tail; + unsafe { + second_part_head = split_node.as_mut().next.take(); + } + if let Some(mut head) = second_part_head { + unsafe { + head.as_mut().prev = None; + } + second_part_tail = self.tail; + } else { + second_part_tail = None; + } + + let second_part = LinkedList { + head: second_part_head, + tail: second_part_tail, + len: self.len - at, + alloc: self.alloc.clone(), + marker: PhantomData, + }; + + // Fix the tail ptr of the first part + self.tail = Some(split_node); + self.len = at; + + second_part + } else { + mem::replace(self, LinkedList::new_in(self.alloc.clone())) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for LinkedList { + /// Creates an empty `LinkedList`. + #[inline] + fn default() -> Self { + Self::new() + } +} + +impl LinkedList { + /// Creates an empty `LinkedList`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let list: LinkedList = LinkedList::new(); + /// ``` + #[inline] + #[rustc_const_stable(feature = "const_linked_list_new", since = "1.39.0")] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub const fn new() -> Self { + LinkedList { head: None, tail: None, len: 0, alloc: Global, marker: PhantomData } + } + + /// Moves all elements from `other` to the end of the list. + /// + /// This reuses all the nodes from `other` and moves them into `self`. After + /// this operation, `other` becomes empty. + /// + /// This operation should compute in *O*(1) time and *O*(1) memory. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut list1 = LinkedList::new(); + /// list1.push_back('a'); + /// + /// let mut list2 = LinkedList::new(); + /// list2.push_back('b'); + /// list2.push_back('c'); + /// + /// list1.append(&mut list2); + /// + /// let mut iter = list1.iter(); + /// assert_eq!(iter.next(), Some(&'a')); + /// assert_eq!(iter.next(), Some(&'b')); + /// assert_eq!(iter.next(), Some(&'c')); + /// assert!(iter.next().is_none()); + /// + /// assert!(list2.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn append(&mut self, other: &mut Self) { + match self.tail { + None => mem::swap(self, other), + Some(mut tail) => { + // `as_mut` is okay here because we have exclusive access to the entirety + // of both lists. + if let Some(mut other_head) = other.head.take() { + unsafe { + tail.as_mut().next = Some(other_head); + other_head.as_mut().prev = Some(tail); + } + + self.tail = other.tail.take(); + self.len += mem::replace(&mut other.len, 0); + } + } + } + } +} + +impl LinkedList { + /// Constructs an empty `LinkedList`. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// use std::collections::LinkedList; + /// + /// let list: LinkedList = LinkedList::new_in(System); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub const fn new_in(alloc: A) -> Self { + LinkedList { head: None, tail: None, len: 0, alloc, marker: PhantomData } + } + /// Provides a forward iterator. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut list: LinkedList = LinkedList::new(); + /// + /// list.push_back(0); + /// list.push_back(1); + /// list.push_back(2); + /// + /// let mut iter = list.iter(); + /// assert_eq!(iter.next(), Some(&0)); + /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter(&self) -> Iter<'_, T> { + Iter { head: self.head, tail: self.tail, len: self.len, marker: PhantomData } + } + + /// Provides a forward iterator with mutable references. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut list: LinkedList = LinkedList::new(); + /// + /// list.push_back(0); + /// list.push_back(1); + /// list.push_back(2); + /// + /// for element in list.iter_mut() { + /// *element += 10; + /// } + /// + /// let mut iter = list.iter(); + /// assert_eq!(iter.next(), Some(&10)); + /// assert_eq!(iter.next(), Some(&11)); + /// assert_eq!(iter.next(), Some(&12)); + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter_mut(&mut self) -> IterMut<'_, T> { + IterMut { head: self.head, tail: self.tail, len: self.len, marker: PhantomData } + } + + /// Provides a cursor at the front element. + /// + /// The cursor is pointing to the "ghost" non-element if the list is empty. + #[inline] + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn cursor_front(&self) -> Cursor<'_, T, A> { + Cursor { index: 0, current: self.head, list: self } + } + + /// Provides a cursor with editing operations at the front element. + /// + /// The cursor is pointing to the "ghost" non-element if the list is empty. + #[inline] + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T, A> { + CursorMut { index: 0, current: self.head, list: self } + } + + /// Provides a cursor at the back element. + /// + /// The cursor is pointing to the "ghost" non-element if the list is empty. + #[inline] + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn cursor_back(&self) -> Cursor<'_, T, A> { + Cursor { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self } + } + + /// Provides a cursor with editing operations at the back element. + /// + /// The cursor is pointing to the "ghost" non-element if the list is empty. + #[inline] + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T, A> { + CursorMut { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self } + } + + /// Returns `true` if the `LinkedList` is empty. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// assert!(dl.is_empty()); + /// + /// dl.push_front("foo"); + /// assert!(!dl.is_empty()); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + self.head.is_none() + } + + /// Returns the length of the `LinkedList`. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// + /// dl.push_front(2); + /// assert_eq!(dl.len(), 1); + /// + /// dl.push_front(1); + /// assert_eq!(dl.len(), 2); + /// + /// dl.push_back(3); + /// assert_eq!(dl.len(), 3); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("length", "size")] + pub fn len(&self) -> usize { + self.len + } + + /// Removes all elements from the `LinkedList`. + /// + /// This operation should compute in *O*(*n*) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// + /// dl.push_front(2); + /// dl.push_front(1); + /// assert_eq!(dl.len(), 2); + /// assert_eq!(dl.front(), Some(&1)); + /// + /// dl.clear(); + /// assert_eq!(dl.len(), 0); + /// assert_eq!(dl.front(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + // We need to drop the nodes while keeping self.alloc + // We can do this by moving (head, tail, len) into a new list that borrows self.alloc + drop(LinkedList { + head: self.head.take(), + tail: self.tail.take(), + len: mem::take(&mut self.len), + alloc: &self.alloc, + marker: PhantomData, + }); + } + + /// Returns `true` if the `LinkedList` contains an element equal to the + /// given value. + /// + /// This operation should compute linearly in *O*(*n*) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut list: LinkedList = LinkedList::new(); + /// + /// list.push_back(0); + /// list.push_back(1); + /// list.push_back(2); + /// + /// assert_eq!(list.contains(&0), true); + /// assert_eq!(list.contains(&10), false); + /// ``` + #[stable(feature = "linked_list_contains", since = "1.12.0")] + pub fn contains(&self, x: &T) -> bool + where + T: PartialEq, + { + self.iter().any(|e| e == x) + } + + /// Provides a reference to the front element, or `None` if the list is + /// empty. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// assert_eq!(dl.front(), None); + /// + /// dl.push_front(1); + /// assert_eq!(dl.front(), Some(&1)); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("first")] + pub fn front(&self) -> Option<&T> { + unsafe { self.head.as_ref().map(|node| &node.as_ref().element) } + } + + /// Provides a mutable reference to the front element, or `None` if the list + /// is empty. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// assert_eq!(dl.front(), None); + /// + /// dl.push_front(1); + /// assert_eq!(dl.front(), Some(&1)); + /// + /// match dl.front_mut() { + /// None => {}, + /// Some(x) => *x = 5, + /// } + /// assert_eq!(dl.front(), Some(&5)); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn front_mut(&mut self) -> Option<&mut T> { + unsafe { self.head.as_mut().map(|node| &mut node.as_mut().element) } + } + + /// Provides a reference to the back element, or `None` if the list is + /// empty. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// assert_eq!(dl.back(), None); + /// + /// dl.push_back(1); + /// assert_eq!(dl.back(), Some(&1)); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn back(&self) -> Option<&T> { + unsafe { self.tail.as_ref().map(|node| &node.as_ref().element) } + } + + /// Provides a mutable reference to the back element, or `None` if the list + /// is empty. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// assert_eq!(dl.back(), None); + /// + /// dl.push_back(1); + /// assert_eq!(dl.back(), Some(&1)); + /// + /// match dl.back_mut() { + /// None => {}, + /// Some(x) => *x = 5, + /// } + /// assert_eq!(dl.back(), Some(&5)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn back_mut(&mut self) -> Option<&mut T> { + unsafe { self.tail.as_mut().map(|node| &mut node.as_mut().element) } + } + + /// Adds an element first in the list. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// + /// dl.push_front(2); + /// assert_eq!(dl.front().unwrap(), &2); + /// + /// dl.push_front(1); + /// assert_eq!(dl.front().unwrap(), &1); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push_front(&mut self, elt: T) { + let node = Box::new_in(Node::new(elt), &self.alloc); + let node_ptr = NonNull::from(Box::leak(node)); + // SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc and leaked + unsafe { + self.push_front_node(node_ptr); + } + } + + /// Removes the first element and returns it, or `None` if the list is + /// empty. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// assert_eq!(d.pop_front(), None); + /// + /// d.push_front(1); + /// d.push_front(3); + /// assert_eq!(d.pop_front(), Some(3)); + /// assert_eq!(d.pop_front(), Some(1)); + /// assert_eq!(d.pop_front(), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop_front(&mut self) -> Option { + self.pop_front_node().map(Node::into_element) + } + + /// Appends an element to the back of a list. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// d.push_back(1); + /// d.push_back(3); + /// assert_eq!(3, *d.back().unwrap()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push", "append")] + pub fn push_back(&mut self, elt: T) { + let node = Box::new_in(Node::new(elt), &self.alloc); + let node_ptr = NonNull::from(Box::leak(node)); + // SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc and leaked + unsafe { + self.push_back_node(node_ptr); + } + } + + /// Removes the last element from a list and returns it, or `None` if + /// it is empty. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// assert_eq!(d.pop_back(), None); + /// d.push_back(1); + /// d.push_back(3); + /// assert_eq!(d.pop_back(), Some(3)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop_back(&mut self) -> Option { + self.pop_back_node().map(Node::into_element) + } + + /// Splits the list into two at the given index. Returns everything after the given index, + /// including the index. + /// + /// This operation should compute in *O*(*n*) time. + /// + /// # Panics + /// + /// Panics if `at > len`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// + /// d.push_front(1); + /// d.push_front(2); + /// d.push_front(3); + /// + /// let mut split = d.split_off(2); + /// + /// assert_eq!(split.pop_front(), Some(1)); + /// assert_eq!(split.pop_front(), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn split_off(&mut self, at: usize) -> LinkedList + where + A: Clone, + { + let len = self.len(); + assert!(at <= len, "Cannot split off at a nonexistent index"); + if at == 0 { + return mem::replace(self, Self::new_in(self.alloc.clone())); + } else if at == len { + return Self::new_in(self.alloc.clone()); + } + + // Below, we iterate towards the `i-1`th node, either from the start or the end, + // depending on which would be faster. + let split_node = if at - 1 <= len - 1 - (at - 1) { + let mut iter = self.iter_mut(); + // instead of skipping using .skip() (which creates a new struct), + // we skip manually so we can access the head field without + // depending on implementation details of Skip + for _ in 0..at - 1 { + iter.next(); + } + iter.head + } else { + // better off starting from the end + let mut iter = self.iter_mut(); + for _ in 0..len - 1 - (at - 1) { + iter.next_back(); + } + iter.tail + }; + unsafe { self.split_off_after_node(split_node, at) } + } + + /// Removes the element at the given index and returns it. + /// + /// This operation should compute in *O*(*n*) time. + /// + /// # Panics + /// Panics if at >= len + /// + /// # Examples + /// + /// ``` + /// #![feature(linked_list_remove)] + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// + /// d.push_front(1); + /// d.push_front(2); + /// d.push_front(3); + /// + /// assert_eq!(d.remove(1), 2); + /// assert_eq!(d.remove(0), 3); + /// assert_eq!(d.remove(0), 1); + /// ``` + #[unstable(feature = "linked_list_remove", issue = "69210")] + #[rustc_confusables("delete", "take")] + pub fn remove(&mut self, at: usize) -> T { + let len = self.len(); + assert!(at < len, "Cannot remove at an index outside of the list bounds"); + + // Below, we iterate towards the node at the given index, either from + // the start or the end, depending on which would be faster. + let offset_from_end = len - at - 1; + if at <= offset_from_end { + let mut cursor = self.cursor_front_mut(); + for _ in 0..at { + cursor.move_next(); + } + cursor.remove_current().unwrap() + } else { + let mut cursor = self.cursor_back_mut(); + for _ in 0..offset_from_end { + cursor.move_prev(); + } + cursor.remove_current().unwrap() + } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` for which `f(&e)` returns false. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// #![feature(linked_list_retain)] + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// + /// d.push_front(1); + /// d.push_front(2); + /// d.push_front(3); + /// + /// d.retain(|&x| x % 2 == 0); + /// + /// assert_eq!(d.pop_front(), Some(2)); + /// assert_eq!(d.pop_front(), None); + /// ``` + /// + /// Because the elements are visited exactly once in the original order, + /// external state may be used to decide which elements to keep. + /// + /// ``` + /// #![feature(linked_list_retain)] + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// + /// d.push_front(1); + /// d.push_front(2); + /// d.push_front(3); + /// + /// let keep = [false, true, false]; + /// let mut iter = keep.iter(); + /// d.retain(|_| *iter.next().unwrap()); + /// assert_eq!(d.pop_front(), Some(2)); + /// assert_eq!(d.pop_front(), None); + /// ``` + #[unstable(feature = "linked_list_retain", issue = "114135")] + pub fn retain(&mut self, mut f: F) + where + F: FnMut(&T) -> bool, + { + self.retain_mut(|elem| f(elem)); + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` for which `f(&mut e)` returns false. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// #![feature(linked_list_retain)] + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// + /// d.push_front(1); + /// d.push_front(2); + /// d.push_front(3); + /// + /// d.retain_mut(|x| if *x % 2 == 0 { + /// *x += 1; + /// true + /// } else { + /// false + /// }); + /// assert_eq!(d.pop_front(), Some(3)); + /// assert_eq!(d.pop_front(), None); + /// ``` + #[unstable(feature = "linked_list_retain", issue = "114135")] + pub fn retain_mut(&mut self, mut f: F) + where + F: FnMut(&mut T) -> bool, + { + let mut cursor = self.cursor_front_mut(); + while let Some(node) = cursor.current() { + if !f(node) { + cursor.remove_current().unwrap(); + } else { + cursor.move_next(); + } + } + } + + /// Creates an iterator which uses a closure to determine if an element should be removed. + /// + /// If the closure returns true, then the element is removed and yielded. + /// If the closure returns false, the element will remain in the list and will not be yielded + /// by the iterator. + /// + /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating + /// or the iteration short-circuits, then the remaining elements will be retained. + /// Use `extract_if().for_each(drop)` if you do not need the returned iterator. + /// + /// Note that `extract_if` lets you mutate every element in the filter closure, regardless of + /// whether you choose to keep or remove it. + /// + /// # Examples + /// + /// Splitting a list into evens and odds, reusing the original list: + /// + /// ``` + /// #![feature(extract_if)] + /// use std::collections::LinkedList; + /// + /// let mut numbers: LinkedList = LinkedList::new(); + /// numbers.extend(&[1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]); + /// + /// let evens = numbers.extract_if(|x| *x % 2 == 0).collect::>(); + /// let odds = numbers; + /// + /// assert_eq!(evens.into_iter().collect::>(), vec![2, 4, 6, 8, 14]); + /// assert_eq!(odds.into_iter().collect::>(), vec![1, 3, 5, 9, 11, 13, 15]); + /// ``` + #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] + pub fn extract_if(&mut self, filter: F) -> ExtractIf<'_, T, F, A> + where + F: FnMut(&mut T) -> bool, + { + // avoid borrow issues. + let it = self.head; + let old_len = self.len; + + ExtractIf { list: self, it, pred: filter, idx: 0, old_len } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T, A: Allocator> Drop for LinkedList { + fn drop(&mut self) { + struct DropGuard<'a, T, A: Allocator>(&'a mut LinkedList); + + impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> { + fn drop(&mut self) { + // Continue the same loop we do below. This only runs when a destructor has + // panicked. If another one panics this will abort. + while self.0.pop_front_node().is_some() {} + } + } + + // Wrap self so that if a destructor panics, we can try to keep looping + let guard = DropGuard(self); + while guard.0.pop_front_node().is_some() {} + mem::forget(guard); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + + #[inline] + fn next(&mut self) -> Option<&'a T> { + if self.len == 0 { + None + } else { + self.head.map(|node| unsafe { + // Need an unbound lifetime to get 'a + let node = &*node.as_ptr(); + self.len -= 1; + self.head = node.next; + &node.element + }) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) + } + + #[inline] + fn last(mut self) -> Option<&'a T> { + self.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for Iter<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a T> { + if self.len == 0 { + None + } else { + self.tail.map(|node| unsafe { + // Need an unbound lifetime to get 'a + let node = &*node.as_ptr(); + self.len -= 1; + self.tail = node.prev; + &node.element + }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Iter<'_, T> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Iter<'_, T> {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for Iter<'_, T> { + /// Creates an empty `linked_list::Iter`. + /// + /// ``` + /// # use std::collections::linked_list; + /// let iter: linked_list::Iter<'_, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Iter { head: None, tail: None, len: 0, marker: Default::default() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for IterMut<'a, T> { + type Item = &'a mut T; + + #[inline] + fn next(&mut self) -> Option<&'a mut T> { + if self.len == 0 { + None + } else { + self.head.map(|node| unsafe { + // Need an unbound lifetime to get 'a + let node = &mut *node.as_ptr(); + self.len -= 1; + self.head = node.next; + &mut node.element + }) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) + } + + #[inline] + fn last(mut self) -> Option<&'a mut T> { + self.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a mut T> { + if self.len == 0 { + None + } else { + self.tail.map(|node| unsafe { + // Need an unbound lifetime to get 'a + let node = &mut *node.as_ptr(); + self.len -= 1; + self.tail = node.prev; + &mut node.element + }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IterMut<'_, T> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IterMut<'_, T> {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for IterMut<'_, T> { + fn default() -> Self { + IterMut { head: None, tail: None, len: 0, marker: Default::default() } + } +} + +/// A cursor over a `LinkedList`. +/// +/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth. +/// +/// Cursors always rest between two elements in the list, and index in a logically circular way. +/// To accommodate this, there is a "ghost" non-element that yields `None` between the head and +/// tail of the list. +/// +/// When created, cursors start at the front of the list, or the "ghost" non-element if the list is empty. +#[unstable(feature = "linked_list_cursors", issue = "58533")] +pub struct Cursor< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + index: usize, + current: Option>>, + list: &'a LinkedList, +} + +#[unstable(feature = "linked_list_cursors", issue = "58533")] +impl Clone for Cursor<'_, T, A> { + fn clone(&self) -> Self { + let Cursor { index, current, list } = *self; + Cursor { index, current, list } + } +} + +#[unstable(feature = "linked_list_cursors", issue = "58533")] +impl fmt::Debug for Cursor<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Cursor").field(&self.list).field(&self.index()).finish() + } +} + +/// A cursor over a `LinkedList` with editing operations. +/// +/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can +/// safely mutate the list during iteration. This is because the lifetime of its yielded +/// references is tied to its own lifetime, instead of just the underlying list. This means +/// cursors cannot yield multiple elements at once. +/// +/// Cursors always rest between two elements in the list, and index in a logically circular way. +/// To accommodate this, there is a "ghost" non-element that yields `None` between the head and +/// tail of the list. +#[unstable(feature = "linked_list_cursors", issue = "58533")] +pub struct CursorMut< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + index: usize, + current: Option>>, + list: &'a mut LinkedList, +} + +#[unstable(feature = "linked_list_cursors", issue = "58533")] +impl fmt::Debug for CursorMut<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("CursorMut").field(&self.list).field(&self.index()).finish() + } +} + +impl<'a, T, A: Allocator> Cursor<'a, T, A> { + /// Returns the cursor position index within the `LinkedList`. + /// + /// This returns `None` if the cursor is currently pointing to the + /// "ghost" non-element. + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn index(&self) -> Option { + let _ = self.current?; + Some(self.index) + } + + /// Moves the cursor to the next element of the `LinkedList`. + /// + /// If the cursor is pointing to the "ghost" non-element then this will move it to + /// the first element of the `LinkedList`. If it is pointing to the last + /// element of the `LinkedList` then this will move it to the "ghost" non-element. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn move_next(&mut self) { + match self.current.take() { + // We had no current element; the cursor was sitting at the start position + // Next element should be the head of the list + None => { + self.current = self.list.head; + self.index = 0; + } + // We had a previous element, so let's go to its next + Some(current) => unsafe { + self.current = current.as_ref().next; + self.index += 1; + }, + } + } + + /// Moves the cursor to the previous element of the `LinkedList`. + /// + /// If the cursor is pointing to the "ghost" non-element then this will move it to + /// the last element of the `LinkedList`. If it is pointing to the first + /// element of the `LinkedList` then this will move it to the "ghost" non-element. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn move_prev(&mut self) { + match self.current.take() { + // No current. We're at the start of the list. Yield None and jump to the end. + None => { + self.current = self.list.tail; + self.index = self.list.len().checked_sub(1).unwrap_or(0); + } + // Have a prev. Yield it and go to the previous element. + Some(current) => unsafe { + self.current = current.as_ref().prev; + self.index = self.index.checked_sub(1).unwrap_or_else(|| self.list.len()); + }, + } + } + + /// Returns a reference to the element that the cursor is currently + /// pointing to. + /// + /// This returns `None` if the cursor is currently pointing to the + /// "ghost" non-element. + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn current(&self) -> Option<&'a T> { + unsafe { self.current.map(|current| &(*current.as_ptr()).element) } + } + + /// Returns a reference to the next element. + /// + /// If the cursor is pointing to the "ghost" non-element then this returns + /// the first element of the `LinkedList`. If it is pointing to the last + /// element of the `LinkedList` then this returns `None`. + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn peek_next(&self) -> Option<&'a T> { + unsafe { + let next = match self.current { + None => self.list.head, + Some(current) => current.as_ref().next, + }; + next.map(|next| &(*next.as_ptr()).element) + } + } + + /// Returns a reference to the previous element. + /// + /// If the cursor is pointing to the "ghost" non-element then this returns + /// the last element of the `LinkedList`. If it is pointing to the first + /// element of the `LinkedList` then this returns `None`. + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn peek_prev(&self) -> Option<&'a T> { + unsafe { + let prev = match self.current { + None => self.list.tail, + Some(current) => current.as_ref().prev, + }; + prev.map(|prev| &(*prev.as_ptr()).element) + } + } + + /// Provides a reference to the front element of the cursor's parent list, + /// or None if the list is empty. + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + #[rustc_confusables("first")] + pub fn front(&self) -> Option<&'a T> { + self.list.front() + } + + /// Provides a reference to the back element of the cursor's parent list, + /// or None if the list is empty. + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + #[rustc_confusables("last")] + pub fn back(&self) -> Option<&'a T> { + self.list.back() + } + + /// Provides a reference to the cursor's parent list. + #[must_use] + #[inline(always)] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn as_list(&self) -> &'a LinkedList { + self.list + } +} + +impl<'a, T, A: Allocator> CursorMut<'a, T, A> { + /// Returns the cursor position index within the `LinkedList`. + /// + /// This returns `None` if the cursor is currently pointing to the + /// "ghost" non-element. + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn index(&self) -> Option { + let _ = self.current?; + Some(self.index) + } + + /// Moves the cursor to the next element of the `LinkedList`. + /// + /// If the cursor is pointing to the "ghost" non-element then this will move it to + /// the first element of the `LinkedList`. If it is pointing to the last + /// element of the `LinkedList` then this will move it to the "ghost" non-element. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn move_next(&mut self) { + match self.current.take() { + // We had no current element; the cursor was sitting at the start position + // Next element should be the head of the list + None => { + self.current = self.list.head; + self.index = 0; + } + // We had a previous element, so let's go to its next + Some(current) => unsafe { + self.current = current.as_ref().next; + self.index += 1; + }, + } + } + + /// Moves the cursor to the previous element of the `LinkedList`. + /// + /// If the cursor is pointing to the "ghost" non-element then this will move it to + /// the last element of the `LinkedList`. If it is pointing to the first + /// element of the `LinkedList` then this will move it to the "ghost" non-element. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn move_prev(&mut self) { + match self.current.take() { + // No current. We're at the start of the list. Yield None and jump to the end. + None => { + self.current = self.list.tail; + self.index = self.list.len().checked_sub(1).unwrap_or(0); + } + // Have a prev. Yield it and go to the previous element. + Some(current) => unsafe { + self.current = current.as_ref().prev; + self.index = self.index.checked_sub(1).unwrap_or_else(|| self.list.len()); + }, + } + } + + /// Returns a reference to the element that the cursor is currently + /// pointing to. + /// + /// This returns `None` if the cursor is currently pointing to the + /// "ghost" non-element. + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn current(&mut self) -> Option<&mut T> { + unsafe { self.current.map(|current| &mut (*current.as_ptr()).element) } + } + + /// Returns a reference to the next element. + /// + /// If the cursor is pointing to the "ghost" non-element then this returns + /// the first element of the `LinkedList`. If it is pointing to the last + /// element of the `LinkedList` then this returns `None`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn peek_next(&mut self) -> Option<&mut T> { + unsafe { + let next = match self.current { + None => self.list.head, + Some(current) => current.as_ref().next, + }; + next.map(|next| &mut (*next.as_ptr()).element) + } + } + + /// Returns a reference to the previous element. + /// + /// If the cursor is pointing to the "ghost" non-element then this returns + /// the last element of the `LinkedList`. If it is pointing to the first + /// element of the `LinkedList` then this returns `None`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn peek_prev(&mut self) -> Option<&mut T> { + unsafe { + let prev = match self.current { + None => self.list.tail, + Some(current) => current.as_ref().prev, + }; + prev.map(|prev| &mut (*prev.as_ptr()).element) + } + } + + /// Returns a read-only cursor pointing to the current element. + /// + /// The lifetime of the returned `Cursor` is bound to that of the + /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the + /// `CursorMut` is frozen for the lifetime of the `Cursor`. + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn as_cursor(&self) -> Cursor<'_, T, A> { + Cursor { list: self.list, current: self.current, index: self.index } + } + + /// Provides a read-only reference to the cursor's parent list. + /// + /// The lifetime of the returned reference is bound to that of the + /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the + /// `CursorMut` is frozen for the lifetime of the reference. + #[must_use] + #[inline(always)] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn as_list(&self) -> &LinkedList { + self.list + } +} + +// Now the list editing operations + +impl<'a, T> CursorMut<'a, T> { + /// Inserts the elements from the given `LinkedList` after the current one. + /// + /// If the cursor is pointing at the "ghost" non-element then the new elements are + /// inserted at the start of the `LinkedList`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn splice_after(&mut self, list: LinkedList) { + unsafe { + let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() { + Some(parts) => parts, + _ => return, + }; + let node_next = match self.current { + None => self.list.head, + Some(node) => node.as_ref().next, + }; + self.list.splice_nodes(self.current, node_next, splice_head, splice_tail, splice_len); + if self.current.is_none() { + // The "ghost" non-element's index has changed. + self.index = self.list.len; + } + } + } + + /// Inserts the elements from the given `LinkedList` before the current one. + /// + /// If the cursor is pointing at the "ghost" non-element then the new elements are + /// inserted at the end of the `LinkedList`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn splice_before(&mut self, list: LinkedList) { + unsafe { + let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() { + Some(parts) => parts, + _ => return, + }; + let node_prev = match self.current { + None => self.list.tail, + Some(node) => node.as_ref().prev, + }; + self.list.splice_nodes(node_prev, self.current, splice_head, splice_tail, splice_len); + self.index += splice_len; + } + } +} + +impl<'a, T, A: Allocator> CursorMut<'a, T, A> { + /// Inserts a new element into the `LinkedList` after the current one. + /// + /// If the cursor is pointing at the "ghost" non-element then the new element is + /// inserted at the front of the `LinkedList`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn insert_after(&mut self, item: T) { + unsafe { + let spliced_node = Box::leak(Box::new_in(Node::new(item), &self.list.alloc)).into(); + let node_next = match self.current { + None => self.list.head, + Some(node) => node.as_ref().next, + }; + self.list.splice_nodes(self.current, node_next, spliced_node, spliced_node, 1); + if self.current.is_none() { + // The "ghost" non-element's index has changed. + self.index = self.list.len; + } + } + } + + /// Inserts a new element into the `LinkedList` before the current one. + /// + /// If the cursor is pointing at the "ghost" non-element then the new element is + /// inserted at the end of the `LinkedList`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn insert_before(&mut self, item: T) { + unsafe { + let spliced_node = Box::leak(Box::new_in(Node::new(item), &self.list.alloc)).into(); + let node_prev = match self.current { + None => self.list.tail, + Some(node) => node.as_ref().prev, + }; + self.list.splice_nodes(node_prev, self.current, spliced_node, spliced_node, 1); + self.index += 1; + } + } + + /// Removes the current element from the `LinkedList`. + /// + /// The element that was removed is returned, and the cursor is + /// moved to point to the next element in the `LinkedList`. + /// + /// If the cursor is currently pointing to the "ghost" non-element then no element + /// is removed and `None` is returned. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn remove_current(&mut self) -> Option { + let unlinked_node = self.current?; + unsafe { + self.current = unlinked_node.as_ref().next; + self.list.unlink_node(unlinked_node); + let unlinked_node = Box::from_raw_in(unlinked_node.as_ptr(), &self.list.alloc); + Some(unlinked_node.element) + } + } + + /// Removes the current element from the `LinkedList` without deallocating the list node. + /// + /// The node that was removed is returned as a new `LinkedList` containing only this node. + /// The cursor is moved to point to the next element in the current `LinkedList`. + /// + /// If the cursor is currently pointing to the "ghost" non-element then no element + /// is removed and `None` is returned. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn remove_current_as_list(&mut self) -> Option> + where + A: Clone, + { + let mut unlinked_node = self.current?; + unsafe { + self.current = unlinked_node.as_ref().next; + self.list.unlink_node(unlinked_node); + + unlinked_node.as_mut().prev = None; + unlinked_node.as_mut().next = None; + Some(LinkedList { + head: Some(unlinked_node), + tail: Some(unlinked_node), + len: 1, + alloc: self.list.alloc.clone(), + marker: PhantomData, + }) + } + } + + /// Splits the list into two after the current element. This will return a + /// new list consisting of everything after the cursor, with the original + /// list retaining everything before. + /// + /// If the cursor is pointing at the "ghost" non-element then the entire contents + /// of the `LinkedList` are moved. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn split_after(&mut self) -> LinkedList + where + A: Clone, + { + let split_off_idx = if self.index == self.list.len { 0 } else { self.index + 1 }; + if self.index == self.list.len { + // The "ghost" non-element's index has changed to 0. + self.index = 0; + } + unsafe { self.list.split_off_after_node(self.current, split_off_idx) } + } + + /// Splits the list into two before the current element. This will return a + /// new list consisting of everything before the cursor, with the original + /// list retaining everything after. + /// + /// If the cursor is pointing at the "ghost" non-element then the entire contents + /// of the `LinkedList` are moved. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn split_before(&mut self) -> LinkedList + where + A: Clone, + { + let split_off_idx = self.index; + self.index = 0; + unsafe { self.list.split_off_before_node(self.current, split_off_idx) } + } + + /// Appends an element to the front of the cursor's parent list. The node + /// that the cursor points to is unchanged, even if it is the "ghost" node. + /// + /// This operation should compute in *O*(1) time. + // `push_front` continues to point to "ghost" when it adds a node to mimic + // the behavior of `insert_before` on an empty list. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn push_front(&mut self, elt: T) { + // Safety: We know that `push_front` does not change the position in + // memory of other nodes. This ensures that `self.current` remains + // valid. + self.list.push_front(elt); + self.index += 1; + } + + /// Appends an element to the back of the cursor's parent list. The node + /// that the cursor points to is unchanged, even if it is the "ghost" node. + /// + /// This operation should compute in *O*(1) time. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + #[rustc_confusables("push", "append")] + pub fn push_back(&mut self, elt: T) { + // Safety: We know that `push_back` does not change the position in + // memory of other nodes. This ensures that `self.current` remains + // valid. + self.list.push_back(elt); + if self.current().is_none() { + // The index of "ghost" is the length of the list, so we just need + // to increment self.index to reflect the new length of the list. + self.index += 1; + } + } + + /// Removes the first element from the cursor's parent list and returns it, + /// or None if the list is empty. The element the cursor points to remains + /// unchanged, unless it was pointing to the front element. In that case, it + /// points to the new front element. + /// + /// This operation should compute in *O*(1) time. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn pop_front(&mut self) -> Option { + // We can't check if current is empty, we must check the list directly. + // It is possible for `self.current == None` and the list to be + // non-empty. + if self.list.is_empty() { + None + } else { + // We can't point to the node that we pop. Copying the behavior of + // `remove_current`, we move on to the next node in the sequence. + // If the list is of length 1 then we end pointing to the "ghost" + // node at index 0, which is expected. + if self.list.head == self.current { + self.move_next(); + } else { + self.index -= 1; + } + self.list.pop_front() + } + } + + /// Removes the last element from the cursor's parent list and returns it, + /// or None if the list is empty. The element the cursor points to remains + /// unchanged, unless it was pointing to the back element. In that case, it + /// points to the "ghost" element. + /// + /// This operation should compute in *O*(1) time. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + #[rustc_confusables("pop")] + pub fn pop_back(&mut self) -> Option { + if self.list.is_empty() { + None + } else { + if self.list.tail == self.current { + // The index now reflects the length of the list. It was the + // length of the list minus 1, but now the list is 1 smaller. No + // change is needed for `index`. + self.current = None; + } else if self.current.is_none() { + self.index = self.list.len - 1; + } + self.list.pop_back() + } + } + + /// Provides a reference to the front element of the cursor's parent list, + /// or None if the list is empty. + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + #[rustc_confusables("first")] + pub fn front(&self) -> Option<&T> { + self.list.front() + } + + /// Provides a mutable reference to the front element of the cursor's + /// parent list, or None if the list is empty. + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn front_mut(&mut self) -> Option<&mut T> { + self.list.front_mut() + } + + /// Provides a reference to the back element of the cursor's parent list, + /// or None if the list is empty. + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + #[rustc_confusables("last")] + pub fn back(&self) -> Option<&T> { + self.list.back() + } + + /// Provides a mutable reference to back element of the cursor's parent + /// list, or `None` if the list is empty. + /// + /// # Examples + /// Building and mutating a list with a cursor, then getting the back element: + /// ``` + /// #![feature(linked_list_cursors)] + /// use std::collections::LinkedList; + /// let mut dl = LinkedList::new(); + /// dl.push_front(3); + /// dl.push_front(2); + /// dl.push_front(1); + /// let mut cursor = dl.cursor_front_mut(); + /// *cursor.current().unwrap() = 99; + /// *cursor.back_mut().unwrap() = 0; + /// let mut contents = dl.into_iter(); + /// assert_eq!(contents.next(), Some(99)); + /// assert_eq!(contents.next(), Some(2)); + /// assert_eq!(contents.next(), Some(0)); + /// assert_eq!(contents.next(), None); + /// ``` + #[must_use] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn back_mut(&mut self) -> Option<&mut T> { + self.list.back_mut() + } +} + +/// An iterator produced by calling `extract_if` on LinkedList. +#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct ExtractIf< + 'a, + T: 'a, + F: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> where + F: FnMut(&mut T) -> bool, +{ + list: &'a mut LinkedList, + it: Option>>, + pred: F, + idx: usize, + old_len: usize, +} + +#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] +impl Iterator for ExtractIf<'_, T, F, A> +where + F: FnMut(&mut T) -> bool, +{ + type Item = T; + + fn next(&mut self) -> Option { + while let Some(mut node) = self.it { + unsafe { + self.it = node.as_ref().next; + self.idx += 1; + + if (self.pred)(&mut node.as_mut().element) { + // `unlink_node` is okay with aliasing `element` references. + self.list.unlink_node(node); + return Some(Box::from_raw_in(node.as_ptr(), &self.list.alloc).element); + } + } + } + + None + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.old_len - self.idx)) + } +} + +#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] +impl fmt::Debug for ExtractIf<'_, T, F> +where + F: FnMut(&mut T) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("ExtractIf").field(&self.list).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.list.pop_front() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (self.list.len, Some(self.list.len)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + self.list.pop_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for IntoIter { + /// Creates an empty `linked_list::IntoIter`. + /// + /// ``` + /// # use std::collections::linked_list; + /// let iter: linked_list::IntoIter = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + LinkedList::new().into_iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for LinkedList { + fn from_iter>(iter: I) -> Self { + let mut list = Self::new(); + list.extend(iter); + list + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for LinkedList { + type Item = T; + type IntoIter = IntoIter; + + /// Consumes the list into an iterator yielding elements by value. + #[inline] + fn into_iter(self) -> IntoIter { + IntoIter { list: self } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, A: Allocator> IntoIterator for &'a LinkedList { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, A: Allocator> IntoIterator for &'a mut LinkedList { + type Item = &'a mut T; + type IntoIter = IterMut<'a, T>; + + fn into_iter(self) -> IterMut<'a, T> { + self.iter_mut() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for LinkedList { + fn extend>(&mut self, iter: I) { + >::spec_extend(self, iter); + } + + #[inline] + fn extend_one(&mut self, elem: T) { + self.push_back(elem); + } +} + +impl SpecExtend for LinkedList { + default fn spec_extend(&mut self, iter: I) { + iter.into_iter().for_each(move |elt| self.push_back(elt)); + } +} + +impl SpecExtend> for LinkedList { + fn spec_extend(&mut self, ref mut other: LinkedList) { + self.append(other); + } +} + +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, T: 'a + Copy, A: Allocator> Extend<&'a T> for LinkedList { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()); + } + + #[inline] + fn extend_one(&mut self, &elem: &'a T) { + self.push_back(elem); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for LinkedList { + fn eq(&self, other: &Self) -> bool { + self.len() == other.len() && self.iter().eq(other) + } + + fn ne(&self, other: &Self) -> bool { + self.len() != other.len() || self.iter().ne(other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for LinkedList {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for LinkedList { + fn partial_cmp(&self, other: &Self) -> Option { + self.iter().partial_cmp(other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for LinkedList { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.iter().cmp(other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for LinkedList { + fn clone(&self) -> Self { + let mut list = Self::new_in(self.alloc.clone()); + list.extend(self.iter().cloned()); + list + } + + /// Overwrites the contents of `self` with a clone of the contents of `source`. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids reallocation of the nodes of the linked list. Additionally, + /// if the element type `T` overrides `clone_from()`, this will reuse the + /// resources of `self`'s elements as well. + fn clone_from(&mut self, source: &Self) { + let mut source_iter = source.iter(); + if self.len() > source.len() { + self.split_off(source.len()); + } + for (elem, source_elem) in self.iter_mut().zip(&mut source_iter) { + elem.clone_from(source_elem); + } + if !source_iter.is_empty() { + self.extend(source_iter.cloned()); + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for LinkedList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for LinkedList { + fn hash(&self, state: &mut H) { + state.write_length_prefix(self.len()); + for elt in self { + elt.hash(state); + } + } +} + +#[stable(feature = "std_collections_from_array", since = "1.56.0")] +impl From<[T; N]> for LinkedList { + /// Converts a `[T; N]` into a `LinkedList`. + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let list1 = LinkedList::from([1, 2, 3, 4]); + /// let list2: LinkedList<_> = [1, 2, 3, 4].into(); + /// assert_eq!(list1, list2); + /// ``` + fn from(arr: [T; N]) -> Self { + Self::from_iter(arr) + } +} + +// Ensure that `LinkedList` and its read-only iterators are covariant in their type parameters. +#[allow(dead_code)] +fn assert_covariance() { + fn a<'a>(x: LinkedList<&'static str>) -> LinkedList<&'a str> { + x + } + fn b<'i, 'a>(x: Iter<'i, &'static str>) -> Iter<'i, &'a str> { + x + } + fn c<'a>(x: IntoIter<&'static str>) -> IntoIter<&'a str> { + x + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for LinkedList {} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for LinkedList {} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for Iter<'_, T> {} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for Iter<'_, T> {} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for IterMut<'_, T> {} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for IterMut<'_, T> {} + +#[unstable(feature = "linked_list_cursors", issue = "58533")] +unsafe impl Send for Cursor<'_, T, A> {} + +#[unstable(feature = "linked_list_cursors", issue = "58533")] +unsafe impl Sync for Cursor<'_, T, A> {} + +#[unstable(feature = "linked_list_cursors", issue = "58533")] +unsafe impl Send for CursorMut<'_, T, A> {} + +#[unstable(feature = "linked_list_cursors", issue = "58533")] +unsafe impl Sync for CursorMut<'_, T, A> {} diff --git a/CoqOfRust/alloc/collections/linked_list/tests.rs b/CoqOfRust/alloc/collections/linked_list/tests.rs new file mode 100644 index 000000000..b7d4f8512 --- /dev/null +++ b/CoqOfRust/alloc/collections/linked_list/tests.rs @@ -0,0 +1,1202 @@ +// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] + +use std::panic::{AssertUnwindSafe, catch_unwind}; +use std::thread; + +use rand::RngCore; + +use super::*; +use crate::testing::crash_test::{CrashTestDummy, Panic}; +use crate::vec::Vec; + +#[test] +fn test_basic() { + let mut m = LinkedList::>::new(); + assert_eq!(m.pop_front(), None); + assert_eq!(m.pop_back(), None); + assert_eq!(m.pop_front(), None); + m.push_front(Box::new(1)); + assert_eq!(m.pop_front(), Some(Box::new(1))); + m.push_back(Box::new(2)); + m.push_back(Box::new(3)); + assert_eq!(m.len(), 2); + assert_eq!(m.pop_front(), Some(Box::new(2))); + assert_eq!(m.pop_front(), Some(Box::new(3))); + assert_eq!(m.len(), 0); + assert_eq!(m.pop_front(), None); + m.push_back(Box::new(1)); + m.push_back(Box::new(3)); + m.push_back(Box::new(5)); + m.push_back(Box::new(7)); + assert_eq!(m.pop_front(), Some(Box::new(1))); + + let mut n = LinkedList::new(); + n.push_front(2); + n.push_front(3); + { + assert_eq!(n.front().unwrap(), &3); + let x = n.front_mut().unwrap(); + assert_eq!(*x, 3); + *x = 0; + } + { + assert_eq!(n.back().unwrap(), &2); + let y = n.back_mut().unwrap(); + assert_eq!(*y, 2); + *y = 1; + } + assert_eq!(n.pop_front(), Some(0)); + assert_eq!(n.pop_front(), Some(1)); +} + +fn generate_test() -> LinkedList { + list_from(&[0, 1, 2, 3, 4, 5, 6]) +} + +fn list_from(v: &[T]) -> LinkedList { + v.iter().cloned().collect() +} + +pub fn check_links(list: &LinkedList) { + unsafe { + let mut len = 0; + let mut last_ptr: Option<&Node> = None; + let mut node_ptr: &Node; + match list.head { + None => { + // tail node should also be None. + assert!(list.tail.is_none()); + assert_eq!(0, list.len); + return; + } + Some(node) => node_ptr = &*node.as_ptr(), + } + loop { + match (last_ptr, node_ptr.prev) { + (None, None) => {} + (None, _) => panic!("prev link for head"), + (Some(p), Some(pptr)) => { + assert_eq!(p as *const Node, pptr.as_ptr() as *const Node); + } + _ => panic!("prev link is none, not good"), + } + match node_ptr.next { + Some(next) => { + last_ptr = Some(node_ptr); + node_ptr = &*next.as_ptr(); + len += 1; + } + None => { + len += 1; + break; + } + } + } + + // verify that the tail node points to the last node. + let tail = list.tail.as_ref().expect("some tail node").as_ref(); + assert_eq!(tail as *const Node, node_ptr as *const Node); + // check that len matches interior links. + assert_eq!(len, list.len); + } +} + +#[test] +fn test_append() { + // Empty to empty + { + let mut m = LinkedList::::new(); + let mut n = LinkedList::new(); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 0); + assert_eq!(n.len(), 0); + } + // Non-empty to empty + { + let mut m = LinkedList::new(); + let mut n = LinkedList::new(); + n.push_back(2); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + assert_eq!(n.len(), 0); + check_links(&m); + } + // Empty to non-empty + { + let mut m = LinkedList::new(); + let mut n = LinkedList::new(); + m.push_back(2); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + check_links(&m); + } + + // Non-empty to non-empty + let v = vec![1, 2, 3, 4, 5]; + let u = vec![9, 8, 1, 2, 3, 4, 5]; + let mut m = list_from(&v); + let mut n = list_from(&u); + m.append(&mut n); + check_links(&m); + let mut sum = v; + sum.extend_from_slice(&u); + assert_eq!(sum.len(), m.len()); + for elt in sum { + assert_eq!(m.pop_front(), Some(elt)) + } + assert_eq!(n.len(), 0); + // Let's make sure it's working properly, since we + // did some direct changes to private members. + n.push_back(3); + assert_eq!(n.len(), 1); + assert_eq!(n.pop_front(), Some(3)); + check_links(&n); +} + +#[test] +fn test_iterator() { + let m = generate_test(); + for (i, elt) in m.iter().enumerate() { + assert_eq!(i as i32, *elt); + } + let mut n = LinkedList::new(); + assert_eq!(n.iter().next(), None); + n.push_front(4); + let mut it = n.iter(); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_iterator_clone() { + let mut n = LinkedList::new(); + n.push_back(2); + n.push_back(3); + n.push_back(4); + let mut it = n.iter(); + it.next(); + let mut jt = it.clone(); + assert_eq!(it.next(), jt.next()); + assert_eq!(it.next_back(), jt.next_back()); + assert_eq!(it.next(), jt.next()); +} + +#[test] +fn test_iterator_double_end() { + let mut n = LinkedList::new(); + assert_eq!(n.iter().next(), None); + n.push_front(4); + n.push_front(5); + n.push_front(6); + let mut it = n.iter(); + assert_eq!(it.size_hint(), (3, Some(3))); + assert_eq!(it.next().unwrap(), &6); + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(it.next_back().unwrap(), &4); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next_back().unwrap(), &5); + assert_eq!(it.next_back(), None); + assert_eq!(it.next(), None); +} + +#[test] +fn test_rev_iter() { + let m = generate_test(); + for (i, elt) in m.iter().rev().enumerate() { + assert_eq!((6 - i) as i32, *elt); + } + let mut n = LinkedList::new(); + assert_eq!(n.iter().rev().next(), None); + n.push_front(4); + let mut it = n.iter().rev(); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_mut_iter() { + let mut m = generate_test(); + let mut len = m.len(); + for (i, elt) in m.iter_mut().enumerate() { + assert_eq!(i as i32, *elt); + len -= 1; + } + assert_eq!(len, 0); + let mut n = LinkedList::new(); + assert!(n.iter_mut().next().is_none()); + n.push_front(4); + n.push_back(5); + let mut it = n.iter_mut(); + assert_eq!(it.size_hint(), (2, Some(2))); + assert!(it.next().is_some()); + assert!(it.next().is_some()); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); +} + +#[test] +fn test_iterator_mut_double_end() { + let mut n = LinkedList::new(); + assert!(n.iter_mut().next_back().is_none()); + n.push_front(4); + n.push_front(5); + n.push_front(6); + let mut it = n.iter_mut(); + assert_eq!(it.size_hint(), (3, Some(3))); + assert_eq!(*it.next().unwrap(), 6); + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(*it.next_back().unwrap(), 4); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(*it.next_back().unwrap(), 5); + assert!(it.next_back().is_none()); + assert!(it.next().is_none()); +} + +#[test] +fn test_mut_rev_iter() { + let mut m = generate_test(); + for (i, elt) in m.iter_mut().rev().enumerate() { + assert_eq!((6 - i) as i32, *elt); + } + let mut n = LinkedList::new(); + assert!(n.iter_mut().rev().next().is_none()); + n.push_front(4); + let mut it = n.iter_mut().rev(); + assert!(it.next().is_some()); + assert!(it.next().is_none()); +} + +#[test] +fn test_clone_from() { + // Short cloned from long + { + let v = vec![1, 2, 3, 4, 5]; + let u = vec![8, 7, 6, 2, 3, 4, 5]; + let mut m = list_from(&v); + let n = list_from(&u); + m.clone_from(&n); + check_links(&m); + assert_eq!(m, n); + for elt in u { + assert_eq!(m.pop_front(), Some(elt)) + } + } + // Long cloned from short + { + let v = vec![1, 2, 3, 4, 5]; + let u = vec![6, 7, 8]; + let mut m = list_from(&v); + let n = list_from(&u); + m.clone_from(&n); + check_links(&m); + assert_eq!(m, n); + for elt in u { + assert_eq!(m.pop_front(), Some(elt)) + } + } + // Two equal length lists + { + let v = vec![1, 2, 3, 4, 5]; + let u = vec![9, 8, 1, 2, 3]; + let mut m = list_from(&v); + let n = list_from(&u); + m.clone_from(&n); + check_links(&m); + assert_eq!(m, n); + for elt in u { + assert_eq!(m.pop_front(), Some(elt)) + } + } +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_send() { + let n = list_from(&[1, 2, 3]); + thread::spawn(move || { + check_links(&n); + let a: &[_] = &[&1, &2, &3]; + assert_eq!(a, &*n.iter().collect::>()); + }) + .join() + .ok() + .unwrap(); +} + +#[test] +fn test_eq() { + let mut n = list_from(&[]); + let mut m = list_from(&[]); + assert!(n == m); + n.push_front(1); + assert!(n != m); + m.push_back(1); + assert!(n == m); + + let n = list_from(&[2, 3, 4]); + let m = list_from(&[1, 2, 3]); + assert!(n != m); +} + +#[test] +fn test_ord() { + let n = list_from(&[]); + let m = list_from(&[1, 2, 3]); + assert!(n < m); + assert!(m > n); + assert!(n <= n); + assert!(n >= n); +} + +#[test] +fn test_ord_nan() { + let nan = 0.0f64 / 0.0; + let n = list_from(&[nan]); + let m = list_from(&[nan]); + assert!(!(n < m)); + assert!(!(n > m)); + assert!(!(n <= m)); + assert!(!(n >= m)); + + let n = list_from(&[nan]); + let one = list_from(&[1.0f64]); + assert!(!(n < one)); + assert!(!(n > one)); + assert!(!(n <= one)); + assert!(!(n >= one)); + + let u = list_from(&[1.0f64, 2.0, nan]); + let v = list_from(&[1.0f64, 2.0, 3.0]); + assert!(!(u < v)); + assert!(!(u > v)); + assert!(!(u <= v)); + assert!(!(u >= v)); + + let s = list_from(&[1.0f64, 2.0, 4.0, 2.0]); + let t = list_from(&[1.0f64, 2.0, 3.0, 2.0]); + assert!(!(s < t)); + assert!(s > one); + assert!(!(s <= one)); + assert!(s >= one); +} + +#[test] +fn test_26021() { + // There was a bug in split_off that failed to null out the RHS's head's prev ptr. + // This caused the RHS's dtor to walk up into the LHS at drop and delete all of + // its nodes. + // + // https://github.com/rust-lang/rust/issues/26021 + let mut v1 = LinkedList::new(); + v1.push_front(1); + v1.push_front(1); + v1.push_front(1); + v1.push_front(1); + let _ = v1.split_off(3); // Dropping this now should not cause laundry consumption + assert_eq!(v1.len(), 3); + + assert_eq!(v1.iter().len(), 3); + assert_eq!(v1.iter().collect::>().len(), 3); +} + +#[test] +fn test_split_off() { + let mut v1 = LinkedList::new(); + v1.push_front(1); + v1.push_front(1); + v1.push_front(1); + v1.push_front(1); + + // test all splits + for ix in 0..1 + v1.len() { + let mut a = v1.clone(); + let b = a.split_off(ix); + check_links(&a); + check_links(&b); + a.extend(b); + assert_eq!(v1, a); + } +} + +#[test] +fn test_split_off_2() { + // singleton + { + let mut m = LinkedList::new(); + m.push_back(1); + + let p = m.split_off(0); + assert_eq!(m.len(), 0); + assert_eq!(p.len(), 1); + assert_eq!(p.back(), Some(&1)); + assert_eq!(p.front(), Some(&1)); + } + + // not singleton, forwards + { + let u = vec![1, 2, 3, 4, 5]; + let mut m = list_from(&u); + let mut n = m.split_off(2); + assert_eq!(m.len(), 2); + assert_eq!(n.len(), 3); + for elt in 1..3 { + assert_eq!(m.pop_front(), Some(elt)); + } + for elt in 3..6 { + assert_eq!(n.pop_front(), Some(elt)); + } + } + // not singleton, backwards + { + let u = vec![1, 2, 3, 4, 5]; + let mut m = list_from(&u); + let mut n = m.split_off(4); + assert_eq!(m.len(), 4); + assert_eq!(n.len(), 1); + for elt in 1..5 { + assert_eq!(m.pop_front(), Some(elt)); + } + for elt in 5..6 { + assert_eq!(n.pop_front(), Some(elt)); + } + } + + // no-op on the last index + { + let mut m = LinkedList::new(); + m.push_back(1); + + let p = m.split_off(1); + assert_eq!(m.len(), 1); + assert_eq!(p.len(), 0); + assert_eq!(m.back(), Some(&1)); + assert_eq!(m.front(), Some(&1)); + } +} + +fn fuzz_test(sz: i32, rng: &mut impl RngCore) { + let mut m: LinkedList<_> = LinkedList::new(); + let mut v = vec![]; + for i in 0..sz { + check_links(&m); + let r: u8 = rng.next_u32() as u8; + match r % 6 { + 0 => { + m.pop_back(); + v.pop(); + } + 1 => { + if !v.is_empty() { + m.pop_front(); + v.remove(0); + } + } + 2 | 4 => { + m.push_front(-i); + v.insert(0, -i); + } + 3 | 5 | _ => { + m.push_back(i); + v.push(i); + } + } + } + + check_links(&m); + + let mut i = 0; + for (a, &b) in m.into_iter().zip(&v) { + i += 1; + assert_eq!(a, b); + } + assert_eq!(i, v.len()); +} + +#[test] +fn test_fuzz() { + let mut rng = crate::test_helpers::test_rng(); + for _ in 0..25 { + fuzz_test(3, &mut rng); + fuzz_test(16, &mut rng); + #[cfg(not(miri))] // Miri is too slow + fuzz_test(189, &mut rng); + } +} + +#[test] +fn test_show() { + let list: LinkedList<_> = (0..10).collect(); + assert_eq!(format!("{list:?}"), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); + + let list: LinkedList<_> = ["just", "one", "test", "more"].into_iter().collect(); + assert_eq!(format!("{list:?}"), "[\"just\", \"one\", \"test\", \"more\"]"); +} + +#[test] +fn extract_if_test() { + let mut m: LinkedList = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let deleted = m.extract_if(|v| *v < 4).collect::>(); + + check_links(&m); + + assert_eq!(deleted, &[1, 2, 3]); + assert_eq!(m.into_iter().collect::>(), &[4, 5, 6]); +} + +#[test] +fn drain_to_empty_test() { + let mut m: LinkedList = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let deleted = m.extract_if(|_| true).collect::>(); + + check_links(&m); + + assert_eq!(deleted, &[1, 2, 3, 4, 5, 6]); + assert_eq!(m.into_iter().collect::>(), &[]); +} + +#[test] +fn test_cursor_move_peek() { + let mut m: LinkedList = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let mut cursor = m.cursor_front(); + assert_eq!(cursor.current(), Some(&1)); + assert_eq!(cursor.peek_next(), Some(&2)); + assert_eq!(cursor.peek_prev(), None); + assert_eq!(cursor.index(), Some(0)); + cursor.move_prev(); + assert_eq!(cursor.current(), None); + assert_eq!(cursor.peek_next(), Some(&1)); + assert_eq!(cursor.peek_prev(), Some(&6)); + assert_eq!(cursor.index(), None); + cursor.move_next(); + cursor.move_next(); + assert_eq!(cursor.current(), Some(&2)); + assert_eq!(cursor.peek_next(), Some(&3)); + assert_eq!(cursor.peek_prev(), Some(&1)); + assert_eq!(cursor.index(), Some(1)); + + let mut cursor = m.cursor_back(); + assert_eq!(cursor.current(), Some(&6)); + assert_eq!(cursor.peek_next(), None); + assert_eq!(cursor.peek_prev(), Some(&5)); + assert_eq!(cursor.index(), Some(5)); + cursor.move_next(); + assert_eq!(cursor.current(), None); + assert_eq!(cursor.peek_next(), Some(&1)); + assert_eq!(cursor.peek_prev(), Some(&6)); + assert_eq!(cursor.index(), None); + cursor.move_prev(); + cursor.move_prev(); + assert_eq!(cursor.current(), Some(&5)); + assert_eq!(cursor.peek_next(), Some(&6)); + assert_eq!(cursor.peek_prev(), Some(&4)); + assert_eq!(cursor.index(), Some(4)); + + let mut m: LinkedList = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let mut cursor = m.cursor_front_mut(); + assert_eq!(cursor.current(), Some(&mut 1)); + assert_eq!(cursor.peek_next(), Some(&mut 2)); + assert_eq!(cursor.peek_prev(), None); + assert_eq!(cursor.index(), Some(0)); + cursor.move_prev(); + assert_eq!(cursor.current(), None); + assert_eq!(cursor.peek_next(), Some(&mut 1)); + assert_eq!(cursor.peek_prev(), Some(&mut 6)); + assert_eq!(cursor.index(), None); + cursor.move_next(); + cursor.move_next(); + assert_eq!(cursor.current(), Some(&mut 2)); + assert_eq!(cursor.peek_next(), Some(&mut 3)); + assert_eq!(cursor.peek_prev(), Some(&mut 1)); + assert_eq!(cursor.index(), Some(1)); + let mut cursor2 = cursor.as_cursor(); + assert_eq!(cursor2.current(), Some(&2)); + assert_eq!(cursor2.index(), Some(1)); + cursor2.move_next(); + assert_eq!(cursor2.current(), Some(&3)); + assert_eq!(cursor2.index(), Some(2)); + assert_eq!(cursor.current(), Some(&mut 2)); + assert_eq!(cursor.index(), Some(1)); + + let mut m: LinkedList = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let mut cursor = m.cursor_back_mut(); + assert_eq!(cursor.current(), Some(&mut 6)); + assert_eq!(cursor.peek_next(), None); + assert_eq!(cursor.peek_prev(), Some(&mut 5)); + assert_eq!(cursor.index(), Some(5)); + cursor.move_next(); + assert_eq!(cursor.current(), None); + assert_eq!(cursor.peek_next(), Some(&mut 1)); + assert_eq!(cursor.peek_prev(), Some(&mut 6)); + assert_eq!(cursor.index(), None); + cursor.move_prev(); + cursor.move_prev(); + assert_eq!(cursor.current(), Some(&mut 5)); + assert_eq!(cursor.peek_next(), Some(&mut 6)); + assert_eq!(cursor.peek_prev(), Some(&mut 4)); + assert_eq!(cursor.index(), Some(4)); + let mut cursor2 = cursor.as_cursor(); + assert_eq!(cursor2.current(), Some(&5)); + assert_eq!(cursor2.index(), Some(4)); + cursor2.move_prev(); + assert_eq!(cursor2.current(), Some(&4)); + assert_eq!(cursor2.index(), Some(3)); + assert_eq!(cursor.current(), Some(&mut 5)); + assert_eq!(cursor.index(), Some(4)); +} + +#[test] +fn test_cursor_mut_insert() { + let mut m: LinkedList = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let mut cursor = m.cursor_front_mut(); + cursor.insert_before(7); + cursor.insert_after(8); + check_links(&m); + assert_eq!(m.iter().cloned().collect::>(), &[7, 1, 8, 2, 3, 4, 5, 6]); + let mut cursor = m.cursor_front_mut(); + cursor.move_prev(); + cursor.insert_before(9); + cursor.insert_after(10); + check_links(&m); + assert_eq!(m.iter().cloned().collect::>(), &[10, 7, 1, 8, 2, 3, 4, 5, 6, 9]); + let mut cursor = m.cursor_front_mut(); + cursor.move_prev(); + assert_eq!(cursor.remove_current(), None); + cursor.move_next(); + cursor.move_next(); + assert_eq!(cursor.remove_current(), Some(7)); + cursor.move_prev(); + cursor.move_prev(); + cursor.move_prev(); + assert_eq!(cursor.remove_current(), Some(9)); + cursor.move_next(); + assert_eq!(cursor.remove_current(), Some(10)); + check_links(&m); + assert_eq!(m.iter().cloned().collect::>(), &[1, 8, 2, 3, 4, 5, 6]); + let mut cursor = m.cursor_front_mut(); + let mut p: LinkedList = LinkedList::new(); + p.extend(&[100, 101, 102, 103]); + let mut q: LinkedList = LinkedList::new(); + q.extend(&[200, 201, 202, 203]); + cursor.splice_after(p); + cursor.splice_before(q); + check_links(&m); + assert_eq!(m.iter().cloned().collect::>(), &[ + 200, 201, 202, 203, 1, 100, 101, 102, 103, 8, 2, 3, 4, 5, 6 + ]); + let mut cursor = m.cursor_front_mut(); + cursor.move_prev(); + let tmp = cursor.split_before(); + assert_eq!(m.into_iter().collect::>(), &[]); + m = tmp; + let mut cursor = m.cursor_front_mut(); + cursor.move_next(); + cursor.move_next(); + cursor.move_next(); + cursor.move_next(); + cursor.move_next(); + cursor.move_next(); + let tmp = cursor.split_after(); + assert_eq!(tmp.into_iter().collect::>(), &[102, 103, 8, 2, 3, 4, 5, 6]); + check_links(&m); + assert_eq!(m.iter().cloned().collect::>(), &[200, 201, 202, 203, 1, 100, 101]); +} + +#[test] +fn test_cursor_push_front_back() { + let mut ll: LinkedList = LinkedList::new(); + ll.extend(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + let mut c = ll.cursor_front_mut(); + assert_eq!(c.current(), Some(&mut 1)); + assert_eq!(c.index(), Some(0)); + c.push_front(0); + assert_eq!(c.current(), Some(&mut 1)); + assert_eq!(c.peek_prev(), Some(&mut 0)); + assert_eq!(c.index(), Some(1)); + c.push_back(11); + drop(c); + let p = ll.cursor_back().front().unwrap(); + assert_eq!(p, &0); + assert_eq!(ll, (0..12).collect()); + check_links(&ll); +} + +#[test] +fn test_cursor_pop_front_back() { + let mut ll: LinkedList = LinkedList::new(); + ll.extend(&[1, 2, 3, 4, 5, 6]); + let mut c = ll.cursor_back_mut(); + assert_eq!(c.pop_front(), Some(1)); + c.move_prev(); + c.move_prev(); + c.move_prev(); + assert_eq!(c.pop_back(), Some(6)); + let c = c.as_cursor(); + assert_eq!(c.front(), Some(&2)); + assert_eq!(c.back(), Some(&5)); + assert_eq!(c.index(), Some(1)); + drop(c); + assert_eq!(ll, (2..6).collect()); + check_links(&ll); + let mut c = ll.cursor_back_mut(); + assert_eq!(c.current(), Some(&mut 5)); + assert_eq!(c.index, 3); + assert_eq!(c.pop_back(), Some(5)); + assert_eq!(c.current(), None); + assert_eq!(c.index, 3); + assert_eq!(c.pop_back(), Some(4)); + assert_eq!(c.current(), None); + assert_eq!(c.index, 2); +} + +#[test] +fn test_extend_ref() { + let mut a = LinkedList::new(); + a.push_back(1); + + a.extend(&[2, 3, 4]); + + assert_eq!(a.len(), 4); + assert_eq!(a, list_from(&[1, 2, 3, 4])); + + let mut b = LinkedList::new(); + b.push_back(5); + b.push_back(6); + a.extend(&b); + + assert_eq!(a.len(), 6); + assert_eq!(a, list_from(&[1, 2, 3, 4, 5, 6])); +} + +#[test] +fn test_extend() { + let mut a = LinkedList::new(); + a.push_back(1); + a.extend(vec![2, 3, 4]); // uses iterator + + assert_eq!(a.len(), 4); + assert!(a.iter().eq(&[1, 2, 3, 4])); + + let b: LinkedList<_> = [5, 6, 7].into_iter().collect(); + a.extend(b); // specializes to `append` + + assert_eq!(a.len(), 7); + assert!(a.iter().eq(&[1, 2, 3, 4, 5, 6, 7])); +} + +#[test] +fn test_contains() { + let mut l = LinkedList::new(); + l.extend(&[2, 3, 4]); + + assert!(l.contains(&3)); + assert!(!l.contains(&1)); + + l.clear(); + + assert!(!l.contains(&3)); +} + +#[test] +fn extract_if_empty() { + let mut list: LinkedList = LinkedList::new(); + + { + let mut iter = list.extract_if(|_| true); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(list.len(), 0); + assert_eq!(list.into_iter().collect::>(), vec![]); +} + +#[test] +fn extract_if_zst() { + let mut list: LinkedList<_> = [(), (), (), (), ()].into_iter().collect(); + let initial_len = list.len(); + let mut count = 0; + + { + let mut iter = list.extract_if(|_| true); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + while let Some(_) = iter.next() { + count += 1; + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, initial_len); + assert_eq!(list.len(), 0); + assert_eq!(list.into_iter().collect::>(), vec![]); +} + +#[test] +fn extract_if_false() { + let mut list: LinkedList<_> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + let initial_len = list.len(); + let mut count = 0; + + { + let mut iter = list.extract_if(|_| false); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + for _ in iter.by_ref() { + count += 1; + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, 0); + assert_eq!(list.len(), initial_len); + assert_eq!(list.into_iter().collect::>(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); +} + +#[test] +fn extract_if_true() { + let mut list: LinkedList<_> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + let initial_len = list.len(); + let mut count = 0; + + { + let mut iter = list.extract_if(|_| true); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + while let Some(_) = iter.next() { + count += 1; + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, initial_len); + assert_eq!(list.len(), 0); + assert_eq!(list.into_iter().collect::>(), vec![]); +} + +#[test] +fn extract_if_complex() { + { + // [+xxx++++++xxxxx++++x+x++] + let mut list = [ + 1, 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, + 39, + ] + .into_iter() + .collect::>(); + + let removed = list.extract_if(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(list.len(), 14); + assert_eq!(list.into_iter().collect::>(), vec![ + 1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39 + ]); + } + + { + // [xxx++++++xxxxx++++x+x++] + let mut list = + [2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39] + .into_iter() + .collect::>(); + + let removed = list.extract_if(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(list.len(), 13); + assert_eq!(list.into_iter().collect::>(), vec![ + 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39 + ]); + } + + { + // [xxx++++++xxxxx++++x+x] + let mut list = + [2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36] + .into_iter() + .collect::>(); + + let removed = list.extract_if(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(list.len(), 11); + assert_eq!(list.into_iter().collect::>(), vec![ + 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35 + ]); + } + + { + // [xxxxxxxxxx+++++++++++] + let mut list = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19] + .into_iter() + .collect::>(); + + let removed = list.extract_if(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + assert_eq!(list.len(), 10); + assert_eq!(list.into_iter().collect::>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); + } + + { + // [+++++++++++xxxxxxxxxx] + let mut list = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] + .into_iter() + .collect::>(); + + let removed = list.extract_if(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + assert_eq!(list.len(), 10); + assert_eq!(list.into_iter().collect::>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); + } +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn extract_if_drop_panic_leak() { + let d0 = CrashTestDummy::new(0); + let d1 = CrashTestDummy::new(1); + let d2 = CrashTestDummy::new(2); + let d3 = CrashTestDummy::new(3); + let d4 = CrashTestDummy::new(4); + let d5 = CrashTestDummy::new(5); + let d6 = CrashTestDummy::new(6); + let d7 = CrashTestDummy::new(7); + let mut q = LinkedList::new(); + q.push_back(d3.spawn(Panic::Never)); + q.push_back(d4.spawn(Panic::Never)); + q.push_back(d5.spawn(Panic::Never)); + q.push_back(d6.spawn(Panic::Never)); + q.push_back(d7.spawn(Panic::Never)); + q.push_front(d2.spawn(Panic::Never)); + q.push_front(d1.spawn(Panic::InDrop)); + q.push_front(d0.spawn(Panic::Never)); + + catch_unwind(AssertUnwindSafe(|| q.extract_if(|_| true).for_each(drop))).unwrap_err(); + + assert_eq!(d0.dropped(), 1); + assert_eq!(d1.dropped(), 1); + assert_eq!(d2.dropped(), 0); + assert_eq!(d3.dropped(), 0); + assert_eq!(d4.dropped(), 0); + assert_eq!(d5.dropped(), 0); + assert_eq!(d6.dropped(), 0); + assert_eq!(d7.dropped(), 0); + drop(q); + assert_eq!(d2.dropped(), 1); + assert_eq!(d3.dropped(), 1); + assert_eq!(d4.dropped(), 1); + assert_eq!(d5.dropped(), 1); + assert_eq!(d6.dropped(), 1); + assert_eq!(d7.dropped(), 1); +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn extract_if_pred_panic_leak() { + static mut DROPS: i32 = 0; + + #[derive(Debug)] + struct D(u32); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut q = LinkedList::new(); + q.push_back(D(3)); + q.push_back(D(4)); + q.push_back(D(5)); + q.push_back(D(6)); + q.push_back(D(7)); + q.push_front(D(2)); + q.push_front(D(1)); + q.push_front(D(0)); + + catch_unwind(AssertUnwindSafe(|| { + q.extract_if(|item| if item.0 >= 2 { panic!() } else { true }).for_each(drop) + })) + .ok(); + + assert_eq!(unsafe { DROPS }, 2); // 0 and 1 + assert_eq!(q.len(), 6); +} + +#[test] +fn test_drop() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = LinkedList::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + drop(ring); + + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +fn test_drop_with_pop() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = LinkedList::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + + drop(ring.pop_back()); + drop(ring.pop_front()); + assert_eq!(unsafe { DROPS }, 2); + + drop(ring); + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +fn test_drop_clear() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = LinkedList::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + ring.clear(); + assert_eq!(unsafe { DROPS }, 4); + + drop(ring); + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn test_drop_panic() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let mut q = LinkedList::new(); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_front(D(false)); + q.push_front(D(false)); + q.push_front(D(true)); + + catch_unwind(move || drop(q)).ok(); + + assert_eq!(unsafe { DROPS }, 8); +} + +#[test] +fn test_allocator() { + use core::alloc::{AllocError, Allocator, Layout}; + use core::cell::Cell; + + struct A { + has_allocated: Cell, + has_deallocated: Cell, + } + + unsafe impl Allocator for A { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + assert!(!self.has_allocated.get()); + self.has_allocated.set(true); + + Global.allocate(layout) + } + + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + assert!(!self.has_deallocated.get()); + self.has_deallocated.set(true); + + unsafe { Global.deallocate(ptr, layout) } + } + } + + let alloc = &A { has_allocated: Cell::new(false), has_deallocated: Cell::new(false) }; + { + let mut list = LinkedList::new_in(alloc); + list.push_back(5u32); + list.remove(0); + } + + assert!(alloc.has_allocated.get()); + assert!(alloc.has_deallocated.get()); +} diff --git a/CoqOfRust/alloc/collections/mod.rs b/CoqOfRust/alloc/collections/mod.rs new file mode 100644 index 000000000..020cf4d73 --- /dev/null +++ b/CoqOfRust/alloc/collections/mod.rs @@ -0,0 +1,155 @@ +//! Collection types. + +#![stable(feature = "rust1", since = "1.0.0")] + +#[cfg(not(no_global_oom_handling))] +pub mod binary_heap; +#[cfg(not(no_global_oom_handling))] +mod btree; +#[cfg(not(no_global_oom_handling))] +pub mod linked_list; +#[cfg(not(no_global_oom_handling))] +pub mod vec_deque; + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +pub mod btree_map { + //! An ordered map based on a B-Tree. + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::btree::map::*; +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +pub mod btree_set { + //! An ordered set based on a B-Tree. + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::btree::set::*; +} + +use core::fmt::Display; + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] +pub use binary_heap::BinaryHeap; +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] +pub use btree_map::BTreeMap; +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] +pub use btree_set::BTreeSet; +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] +pub use linked_list::LinkedList; +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] +pub use vec_deque::VecDeque; + +use crate::alloc::{Layout, LayoutError}; + +/// The error type for `try_reserve` methods. +#[derive(Clone, PartialEq, Eq, Debug)] +#[stable(feature = "try_reserve", since = "1.57.0")] +pub struct TryReserveError { + kind: TryReserveErrorKind, +} + +impl TryReserveError { + /// Details about the allocation that caused the error + #[inline] + #[must_use] + #[unstable( + feature = "try_reserve_kind", + reason = "Uncertain how much info should be exposed", + issue = "48043" + )] + pub fn kind(&self) -> TryReserveErrorKind { + self.kind.clone() + } +} + +/// Details of the allocation that caused a `TryReserveError` +#[derive(Clone, PartialEq, Eq, Debug)] +#[unstable( + feature = "try_reserve_kind", + reason = "Uncertain how much info should be exposed", + issue = "48043" +)] +pub enum TryReserveErrorKind { + /// Error due to the computed capacity exceeding the collection's maximum + /// (usually `isize::MAX` bytes). + CapacityOverflow, + + /// The memory allocator returned an error + AllocError { + /// The layout of allocation request that failed + layout: Layout, + + #[doc(hidden)] + #[unstable( + feature = "container_error_extra", + issue = "none", + reason = "\ + Enable exposing the allocator’s custom error value \ + if an associated type is added in the future: \ + https://github.com/rust-lang/wg-allocators/issues/23" + )] + non_exhaustive: (), + }, +} + +#[unstable( + feature = "try_reserve_kind", + reason = "Uncertain how much info should be exposed", + issue = "48043" +)] +impl From for TryReserveError { + #[inline] + fn from(kind: TryReserveErrorKind) -> Self { + Self { kind } + } +} + +#[unstable(feature = "try_reserve_kind", reason = "new API", issue = "48043")] +impl From for TryReserveErrorKind { + /// Always evaluates to [`TryReserveErrorKind::CapacityOverflow`]. + #[inline] + fn from(_: LayoutError) -> Self { + TryReserveErrorKind::CapacityOverflow + } +} + +#[stable(feature = "try_reserve", since = "1.57.0")] +impl Display for TryReserveError { + fn fmt( + &self, + fmt: &mut core::fmt::Formatter<'_>, + ) -> core::result::Result<(), core::fmt::Error> { + fmt.write_str("memory allocation failed")?; + let reason = match self.kind { + TryReserveErrorKind::CapacityOverflow => { + " because the computed capacity exceeded the collection's maximum" + } + TryReserveErrorKind::AllocError { .. } => { + " because the memory allocator returned an error" + } + }; + fmt.write_str(reason) + } +} + +/// An intermediate trait for specialization of `Extend`. +#[doc(hidden)] +#[cfg(not(no_global_oom_handling))] +trait SpecExtend { + /// Extends `self` with the contents of the given iterator. + fn spec_extend(&mut self, iter: I); +} + +#[stable(feature = "try_reserve", since = "1.57.0")] +impl core::error::Error for TryReserveError {} diff --git a/CoqOfRust/alloc/collections/vec_deque/drain.rs b/CoqOfRust/alloc/collections/vec_deque/drain.rs new file mode 100644 index 000000000..44fcef4ed --- /dev/null +++ b/CoqOfRust/alloc/collections/vec_deque/drain.rs @@ -0,0 +1,274 @@ +use core::iter::FusedIterator; +use core::marker::PhantomData; +use core::mem::{self, SizedTypeProperties}; +use core::ptr::NonNull; +use core::{fmt, ptr}; + +use super::VecDeque; +use crate::alloc::{Allocator, Global}; + +/// A draining iterator over the elements of a `VecDeque`. +/// +/// This `struct` is created by the [`drain`] method on [`VecDeque`]. See its +/// documentation for more. +/// +/// [`drain`]: VecDeque::drain +#[stable(feature = "drain", since = "1.6.0")] +pub struct Drain< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + // We can't just use a &mut VecDeque, as that would make Drain invariant over T + // and we want it to be covariant instead + deque: NonNull>, + // drain_start is stored in deque.len + drain_len: usize, + // index into the logical array, not the physical one (always lies in [0..deque.len)) + idx: usize, + // number of elements remaining after dropping the drain + new_len: usize, + remaining: usize, + // Needed to make Drain covariant over T + _marker: PhantomData<&'a T>, +} + +impl<'a, T, A: Allocator> Drain<'a, T, A> { + pub(super) unsafe fn new( + deque: &'a mut VecDeque, + drain_start: usize, + drain_len: usize, + ) -> Self { + let orig_len = mem::replace(&mut deque.len, drain_start); + let new_len = orig_len - drain_len; + Drain { + deque: NonNull::from(deque), + drain_len, + idx: drain_start, + new_len, + remaining: drain_len, + _marker: PhantomData, + } + } + + // Only returns pointers to the slices, as that's all we need + // to drop them. May only be called if `self.remaining != 0`. + unsafe fn as_slices(&self) -> (*mut [T], *mut [T]) { + unsafe { + let deque = self.deque.as_ref(); + + // We know that `self.idx + self.remaining <= deque.len <= usize::MAX`, so this won't overflow. + let logical_remaining_range = self.idx..self.idx + self.remaining; + + // SAFETY: `logical_remaining_range` represents the + // range into the logical buffer of elements that + // haven't been drained yet, so they're all initialized, + // and `slice::range(start..end, end) == start..end`, + // so the preconditions for `slice_ranges` are met. + let (a_range, b_range) = + deque.slice_ranges(logical_remaining_range.clone(), logical_remaining_range.end); + (deque.buffer_range(a_range), deque.buffer_range(b_range)) + } + } +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Drain<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Drain") + .field(&self.drain_len) + .field(&self.idx) + .field(&self.new_len) + .field(&self.remaining) + .finish() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Sync for Drain<'_, T, A> {} +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Send for Drain<'_, T, A> {} + +#[stable(feature = "drain", since = "1.6.0")] +impl Drop for Drain<'_, T, A> { + fn drop(&mut self) { + struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); + + let guard = DropGuard(self); + + if mem::needs_drop::() && guard.0.remaining != 0 { + unsafe { + // SAFETY: We just checked that `self.remaining != 0`. + let (front, back) = guard.0.as_slices(); + // since idx is a logical index, we don't need to worry about wrapping. + guard.0.idx += front.len(); + guard.0.remaining -= front.len(); + ptr::drop_in_place(front); + guard.0.remaining = 0; + ptr::drop_in_place(back); + } + } + + // Dropping `guard` handles moving the remaining elements into place. + impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { + #[inline] + fn drop(&mut self) { + if mem::needs_drop::() && self.0.remaining != 0 { + unsafe { + // SAFETY: We just checked that `self.remaining != 0`. + let (front, back) = self.0.as_slices(); + ptr::drop_in_place(front); + ptr::drop_in_place(back); + } + } + + let source_deque = unsafe { self.0.deque.as_mut() }; + + let drain_len = self.0.drain_len; + let new_len = self.0.new_len; + + if T::IS_ZST { + // no need to copy around any memory if T is a ZST + source_deque.len = new_len; + return; + } + + let head_len = source_deque.len; // #elements in front of the drain + let tail_len = new_len - head_len; // #elements behind the drain + + // Next, we will fill the hole left by the drain with as few writes as possible. + // The code below handles the following control flow and reduces the amount of + // branches under the assumption that `head_len == 0 || tail_len == 0`, i.e. + // draining at the front or at the back of the dequeue is especially common. + // + // H = "head index" = `deque.head` + // h = elements in front of the drain + // d = elements in the drain + // t = elements behind the drain + // + // Note that the buffer may wrap at any point and the wrapping is handled by + // `wrap_copy` and `to_physical_idx`. + // + // Case 1: if `head_len == 0 && tail_len == 0` + // Everything was drained, reset the head index back to 0. + // H + // [ . . . . . d d d d . . . . . ] + // H + // [ . . . . . . . . . . . . . . ] + // + // Case 2: else if `tail_len == 0` + // Don't move data or the head index. + // H + // [ . . . h h h h d d d d . . . ] + // H + // [ . . . h h h h . . . . . . . ] + // + // Case 3: else if `head_len == 0` + // Don't move data, but move the head index. + // H + // [ . . . d d d d t t t t . . . ] + // H + // [ . . . . . . . t t t t . . . ] + // + // Case 4: else if `tail_len <= head_len` + // Move data, but not the head index. + // H + // [ . . h h h h d d d d t t . . ] + // H + // [ . . h h h h t t . . . . . . ] + // + // Case 5: else + // Move data and the head index. + // H + // [ . . h h d d d d t t t t . . ] + // H + // [ . . . . . . h h t t t t . . ] + + // When draining at the front (`.drain(..n)`) or at the back (`.drain(n..)`), + // we don't need to copy any data. The number of elements copied would be 0. + if head_len != 0 && tail_len != 0 { + join_head_and_tail_wrapping(source_deque, drain_len, head_len, tail_len); + // Marking this function as cold helps LLVM to eliminate it entirely if + // this branch is never taken. + // We use `#[cold]` instead of `#[inline(never)]`, because inlining this + // function into the general case (`.drain(n..m)`) is fine. + // See `tests/codegen/vecdeque-drain.rs` for a test. + #[cold] + fn join_head_and_tail_wrapping( + source_deque: &mut VecDeque, + drain_len: usize, + head_len: usize, + tail_len: usize, + ) { + // Pick whether to move the head or the tail here. + let (src, dst, len); + if head_len < tail_len { + src = source_deque.head; + dst = source_deque.to_physical_idx(drain_len); + len = head_len; + } else { + src = source_deque.to_physical_idx(head_len + drain_len); + dst = source_deque.to_physical_idx(head_len); + len = tail_len; + }; + + unsafe { + source_deque.wrap_copy(src, dst, len); + } + } + } + + if new_len == 0 { + // Special case: If the entire dequeue was drained, reset the head back to 0, + // like `.clear()` does. + source_deque.head = 0; + } else if head_len < tail_len { + // If we moved the head above, then we need to adjust the head index here. + source_deque.head = source_deque.to_physical_idx(drain_len); + } + source_deque.len = new_len; + } + } + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl Iterator for Drain<'_, T, A> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + if self.remaining == 0 { + return None; + } + let wrapped_idx = unsafe { self.deque.as_ref().to_physical_idx(self.idx) }; + self.idx += 1; + self.remaining -= 1; + Some(unsafe { self.deque.as_mut().buffer_read(wrapped_idx) }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.remaining; + (len, Some(len)) + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl DoubleEndedIterator for Drain<'_, T, A> { + #[inline] + fn next_back(&mut self) -> Option { + if self.remaining == 0 { + return None; + } + self.remaining -= 1; + let wrapped_idx = unsafe { self.deque.as_ref().to_physical_idx(self.idx + self.remaining) }; + Some(unsafe { self.deque.as_mut().buffer_read(wrapped_idx) }) + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl ExactSizeIterator for Drain<'_, T, A> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Drain<'_, T, A> {} diff --git a/CoqOfRust/alloc/collections/vec_deque/into_iter.rs b/CoqOfRust/alloc/collections/vec_deque/into_iter.rs new file mode 100644 index 000000000..2b09a5e7d --- /dev/null +++ b/CoqOfRust/alloc/collections/vec_deque/into_iter.rs @@ -0,0 +1,260 @@ +use core::iter::{FusedIterator, TrustedLen}; +use core::mem::MaybeUninit; +use core::num::NonZero; +use core::ops::Try; +use core::{array, fmt, ptr}; + +use super::VecDeque; +use crate::alloc::{Allocator, Global}; + +/// An owning iterator over the elements of a `VecDeque`. +/// +/// This `struct` is created by the [`into_iter`] method on [`VecDeque`] +/// (provided by the [`IntoIterator`] trait). See its documentation for more. +/// +/// [`into_iter`]: VecDeque::into_iter +#[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IntoIter< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + inner: VecDeque, +} + +impl IntoIter { + pub(super) fn new(inner: VecDeque) -> Self { + IntoIter { inner } + } + + pub(super) fn into_vecdeque(self) -> VecDeque { + self.inner + } +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoIter").field(&self.inner).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.inner.pop_front() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.inner.len(); + (len, Some(len)) + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + let len = self.inner.len; + let rem = if len < n { + self.inner.clear(); + n - len + } else { + self.inner.drain(..n); + 0 + }; + NonZero::new(rem).map_or(Ok(()), Err) + } + + #[inline] + fn count(self) -> usize { + self.inner.len + } + + fn try_fold(&mut self, mut init: B, mut f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + struct Guard<'a, T, A: Allocator> { + deque: &'a mut VecDeque, + // `consumed <= deque.len` always holds. + consumed: usize, + } + + impl<'a, T, A: Allocator> Drop for Guard<'a, T, A> { + fn drop(&mut self) { + self.deque.len -= self.consumed; + self.deque.head = self.deque.to_physical_idx(self.consumed); + } + } + + let mut guard = Guard { deque: &mut self.inner, consumed: 0 }; + + let (head, tail) = guard.deque.as_slices(); + + init = head + .iter() + .map(|elem| { + guard.consumed += 1; + // SAFETY: Because we incremented `guard.consumed`, the + // deque effectively forgot the element, so we can take + // ownership + unsafe { ptr::read(elem) } + }) + .try_fold(init, &mut f)?; + + tail.iter() + .map(|elem| { + guard.consumed += 1; + // SAFETY: Same as above. + unsafe { ptr::read(elem) } + }) + .try_fold(init, &mut f) + } + + #[inline] + fn fold(mut self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + match self.try_fold(init, |b, item| Ok::(f(b, item))) { + Ok(b) => b, + } + } + + #[inline] + fn last(mut self) -> Option { + self.inner.pop_back() + } + + fn next_chunk( + &mut self, + ) -> Result<[Self::Item; N], array::IntoIter> { + let mut raw_arr = [const { MaybeUninit::uninit() }; N]; + let raw_arr_ptr = raw_arr.as_mut_ptr().cast(); + let (head, tail) = self.inner.as_slices(); + + if head.len() >= N { + // SAFETY: By manually adjusting the head and length of the deque, we effectively + // make it forget the first `N` elements, so taking ownership of them is safe. + unsafe { ptr::copy_nonoverlapping(head.as_ptr(), raw_arr_ptr, N) }; + self.inner.head = self.inner.to_physical_idx(N); + self.inner.len -= N; + // SAFETY: We initialized the entire array with items from `head` + return Ok(unsafe { raw_arr.transpose().assume_init() }); + } + + // SAFETY: Same argument as above. + unsafe { ptr::copy_nonoverlapping(head.as_ptr(), raw_arr_ptr, head.len()) }; + let remaining = N - head.len(); + + if tail.len() >= remaining { + // SAFETY: Same argument as above. + unsafe { + ptr::copy_nonoverlapping(tail.as_ptr(), raw_arr_ptr.add(head.len()), remaining) + }; + self.inner.head = self.inner.to_physical_idx(N); + self.inner.len -= N; + // SAFETY: We initialized the entire array with items from `head` and `tail` + Ok(unsafe { raw_arr.transpose().assume_init() }) + } else { + // SAFETY: Same argument as above. + unsafe { + ptr::copy_nonoverlapping(tail.as_ptr(), raw_arr_ptr.add(head.len()), tail.len()) + }; + let init = head.len() + tail.len(); + // We completely drained all the deques elements. + self.inner.head = 0; + self.inner.len = 0; + // SAFETY: We copied all elements from both slices to the beginning of the array, so + // the given range is initialized. + Err(unsafe { array::IntoIter::new_unchecked(raw_arr, 0..init) }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + self.inner.pop_back() + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + let len = self.inner.len; + let rem = if len < n { + self.inner.clear(); + n - len + } else { + self.inner.truncate(len - n); + 0 + }; + NonZero::new(rem).map_or(Ok(()), Err) + } + + fn try_rfold(&mut self, mut init: B, mut f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + struct Guard<'a, T, A: Allocator> { + deque: &'a mut VecDeque, + // `consumed <= deque.len` always holds. + consumed: usize, + } + + impl<'a, T, A: Allocator> Drop for Guard<'a, T, A> { + fn drop(&mut self) { + self.deque.len -= self.consumed; + } + } + + let mut guard = Guard { deque: &mut self.inner, consumed: 0 }; + + let (head, tail) = guard.deque.as_slices(); + + init = tail + .iter() + .map(|elem| { + guard.consumed += 1; + // SAFETY: See `try_fold`'s safety comment. + unsafe { ptr::read(elem) } + }) + .try_rfold(init, &mut f)?; + + head.iter() + .map(|elem| { + guard.consumed += 1; + // SAFETY: Same as above. + unsafe { ptr::read(elem) } + }) + .try_rfold(init, &mut f) + } + + #[inline] + fn rfold(mut self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + match self.try_rfold(init, |b, item| Ok::(f(b, item))) { + Ok(b) => b, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + #[inline] + fn is_empty(&self) -> bool { + self.inner.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIter {} diff --git a/CoqOfRust/alloc/collections/vec_deque/iter.rs b/CoqOfRust/alloc/collections/vec_deque/iter.rs new file mode 100644 index 000000000..d3dbd10c8 --- /dev/null +++ b/CoqOfRust/alloc/collections/vec_deque/iter.rs @@ -0,0 +1,232 @@ +use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; +use core::num::NonZero; +use core::ops::Try; +use core::{fmt, mem, slice}; + +/// An iterator over the elements of a `VecDeque`. +/// +/// This `struct` is created by the [`iter`] method on [`super::VecDeque`]. See its +/// documentation for more. +/// +/// [`iter`]: super::VecDeque::iter +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Iter<'a, T: 'a> { + i1: slice::Iter<'a, T>, + i2: slice::Iter<'a, T>, +} + +impl<'a, T> Iter<'a, T> { + pub(super) fn new(i1: slice::Iter<'a, T>, i2: slice::Iter<'a, T>) -> Self { + Self { i1, i2 } + } + + /// Views the underlying data as a pair of subslices of the original data. + /// + /// The slices contain, in order, the contents of the deque not yet yielded + /// by the iterator. + /// + /// This has the same lifetime as the original `VecDeque`, and so the + /// iterator can continue to be used while this exists. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_deque_iter_as_slices)] + /// + /// use std::collections::VecDeque; + /// + /// let mut deque = VecDeque::new(); + /// deque.push_back(0); + /// deque.push_back(1); + /// deque.push_back(2); + /// deque.push_front(10); + /// deque.push_front(9); + /// deque.push_front(8); + /// + /// let mut iter = deque.iter(); + /// iter.next(); + /// iter.next_back(); + /// + /// assert_eq!(iter.as_slices(), (&[9, 10][..], &[0, 1][..])); + /// ``` + #[unstable(feature = "vec_deque_iter_as_slices", issue = "123947")] + pub fn as_slices(&self) -> (&'a [T], &'a [T]) { + (self.i1.as_slice(), self.i2.as_slice()) + } +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Iter<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Iter").field(&self.i1.as_slice()).field(&self.i2.as_slice()).finish() + } +} + +#[stable(feature = "default_iters_sequel", since = "1.82.0")] +impl Default for Iter<'_, T> { + /// Creates an empty `vec_deque::Iter`. + /// + /// ``` + /// # use std::collections::vec_deque; + /// let iter: vec_deque::Iter<'_, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Iter { i1: Default::default(), i2: Default::default() } + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Iter<'_, T> { + fn clone(&self) -> Self { + Iter { i1: self.i1.clone(), i2: self.i2.clone() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + + #[inline] + fn next(&mut self) -> Option<&'a T> { + match self.i1.next() { + Some(val) => Some(val), + None => { + // most of the time, the iterator will either always + // call next(), or always call next_back(). By swapping + // the iterators once the first one is empty, we ensure + // that the first branch is taken as often as possible, + // without sacrificing correctness, as i1 is empty anyways + mem::swap(&mut self.i1, &mut self.i2); + self.i1.next() + } + } + } + + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + let remaining = self.i1.advance_by(n); + match remaining { + Ok(()) => Ok(()), + Err(n) => { + mem::swap(&mut self.i1, &mut self.i2); + self.i1.advance_by(n.get()) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } + + fn fold(self, accum: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let accum = self.i1.fold(accum, &mut f); + self.i2.fold(accum, &mut f) + } + + fn try_fold(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let acc = self.i1.try_fold(init, &mut f)?; + self.i2.try_fold(acc, &mut f) + } + + #[inline] + fn last(mut self) -> Option<&'a T> { + self.next_back() + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + // Safety: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + unsafe { + let i1_len = self.i1.len(); + if idx < i1_len { + self.i1.__iterator_get_unchecked(idx) + } else { + self.i2.__iterator_get_unchecked(idx - i1_len) + } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for Iter<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a T> { + match self.i2.next_back() { + Some(val) => Some(val), + None => { + // most of the time, the iterator will either always + // call next(), or always call next_back(). By swapping + // the iterators once the second one is empty, we ensure + // that the first branch is taken as often as possible, + // without sacrificing correctness, as i2 is empty anyways + mem::swap(&mut self.i1, &mut self.i2); + self.i2.next_back() + } + } + } + + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + match self.i2.advance_back_by(n) { + Ok(()) => Ok(()), + Err(n) => { + mem::swap(&mut self.i1, &mut self.i2); + self.i2.advance_back_by(n.get()) + } + } + } + + fn rfold(self, accum: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let accum = self.i2.rfold(accum, &mut f); + self.i1.rfold(accum, &mut f) + } + + fn try_rfold(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let acc = self.i2.try_rfold(init, &mut f)?; + self.i1.try_rfold(acc, &mut f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Iter<'_, T> { + fn len(&self) -> usize { + self.i1.len() + self.i2.len() + } + + fn is_empty(&self) -> bool { + self.i1.is_empty() && self.i2.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Iter<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Iter<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for Iter<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccessNoCoerce for Iter<'_, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} diff --git a/CoqOfRust/alloc/collections/vec_deque/iter_mut.rs b/CoqOfRust/alloc/collections/vec_deque/iter_mut.rs new file mode 100644 index 000000000..0c5f06e75 --- /dev/null +++ b/CoqOfRust/alloc/collections/vec_deque/iter_mut.rs @@ -0,0 +1,296 @@ +use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; +use core::num::NonZero; +use core::ops::Try; +use core::{fmt, mem, slice}; + +/// A mutable iterator over the elements of a `VecDeque`. +/// +/// This `struct` is created by the [`iter_mut`] method on [`super::VecDeque`]. See its +/// documentation for more. +/// +/// [`iter_mut`]: super::VecDeque::iter_mut +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IterMut<'a, T: 'a> { + i1: slice::IterMut<'a, T>, + i2: slice::IterMut<'a, T>, +} + +impl<'a, T> IterMut<'a, T> { + pub(super) fn new(i1: slice::IterMut<'a, T>, i2: slice::IterMut<'a, T>) -> Self { + Self { i1, i2 } + } + + /// Views the underlying data as a pair of subslices of the original data. + /// + /// The slices contain, in order, the contents of the deque not yet yielded + /// by the iterator. + /// + /// To avoid creating `&mut` references that alias, this is forced to + /// consume the iterator. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_deque_iter_as_slices)] + /// + /// use std::collections::VecDeque; + /// + /// let mut deque = VecDeque::new(); + /// deque.push_back(0); + /// deque.push_back(1); + /// deque.push_back(2); + /// deque.push_front(10); + /// deque.push_front(9); + /// deque.push_front(8); + /// + /// let mut iter = deque.iter_mut(); + /// iter.next(); + /// iter.next_back(); + /// + /// let slices = iter.into_slices(); + /// slices.0[0] = 42; + /// slices.1[0] = 24; + /// assert_eq!(deque.as_slices(), (&[8, 42, 10][..], &[24, 1, 2][..])); + /// ``` + #[unstable(feature = "vec_deque_iter_as_slices", issue = "123947")] + pub fn into_slices(self) -> (&'a mut [T], &'a mut [T]) { + (self.i1.into_slice(), self.i2.into_slice()) + } + + /// Views the underlying data as a pair of subslices of the original data. + /// + /// The slices contain, in order, the contents of the deque not yet yielded + /// by the iterator. + /// + /// To avoid creating `&mut [T]` references that alias, the returned slices + /// borrow their lifetimes from the iterator the method is applied on. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_deque_iter_as_slices)] + /// + /// use std::collections::VecDeque; + /// + /// let mut deque = VecDeque::new(); + /// deque.push_back(0); + /// deque.push_back(1); + /// deque.push_back(2); + /// deque.push_front(10); + /// deque.push_front(9); + /// deque.push_front(8); + /// + /// let mut iter = deque.iter_mut(); + /// iter.next(); + /// iter.next_back(); + /// + /// assert_eq!(iter.as_slices(), (&[9, 10][..], &[0, 1][..])); + /// ``` + #[unstable(feature = "vec_deque_iter_as_slices", issue = "123947")] + pub fn as_slices(&self) -> (&[T], &[T]) { + (self.i1.as_slice(), self.i2.as_slice()) + } + + /// Views the underlying data as a pair of subslices of the original data. + /// + /// The slices contain, in order, the contents of the deque not yet yielded + /// by the iterator. + /// + /// To avoid creating `&mut [T]` references that alias, the returned slices + /// borrow their lifetimes from the iterator the method is applied on. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_deque_iter_as_slices)] + /// + /// use std::collections::VecDeque; + /// + /// let mut deque = VecDeque::new(); + /// deque.push_back(0); + /// deque.push_back(1); + /// deque.push_back(2); + /// deque.push_front(10); + /// deque.push_front(9); + /// deque.push_front(8); + /// + /// let mut iter = deque.iter_mut(); + /// iter.next(); + /// iter.next_back(); + /// + /// iter.as_mut_slices().0[0] = 42; + /// iter.as_mut_slices().1[0] = 24; + /// assert_eq!(deque.as_slices(), (&[8, 42, 10][..], &[24, 1, 2][..])); + /// ``` + #[unstable(feature = "vec_deque_iter_as_slices", issue = "123947")] + pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) { + (self.i1.as_mut_slice(), self.i2.as_mut_slice()) + } +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for IterMut<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IterMut").field(&self.i1.as_slice()).field(&self.i2.as_slice()).finish() + } +} + +#[stable(feature = "default_iters_sequel", since = "1.82.0")] +impl Default for IterMut<'_, T> { + /// Creates an empty `vec_deque::IterMut`. + /// + /// ``` + /// # use std::collections::vec_deque; + /// let iter: vec_deque::IterMut<'_, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + IterMut { i1: Default::default(), i2: Default::default() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for IterMut<'a, T> { + type Item = &'a mut T; + + #[inline] + fn next(&mut self) -> Option<&'a mut T> { + match self.i1.next() { + Some(val) => Some(val), + None => { + // most of the time, the iterator will either always + // call next(), or always call next_back(). By swapping + // the iterators once the first one is empty, we ensure + // that the first branch is taken as often as possible, + // without sacrificing correctness, as i1 is empty anyways + mem::swap(&mut self.i1, &mut self.i2); + self.i1.next() + } + } + } + + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + match self.i1.advance_by(n) { + Ok(()) => Ok(()), + Err(remaining) => { + mem::swap(&mut self.i1, &mut self.i2); + self.i1.advance_by(remaining.get()) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } + + fn fold(self, accum: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let accum = self.i1.fold(accum, &mut f); + self.i2.fold(accum, &mut f) + } + + fn try_fold(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let acc = self.i1.try_fold(init, &mut f)?; + self.i2.try_fold(acc, &mut f) + } + + #[inline] + fn last(mut self) -> Option<&'a mut T> { + self.next_back() + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + // Safety: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + unsafe { + let i1_len = self.i1.len(); + if idx < i1_len { + self.i1.__iterator_get_unchecked(idx) + } else { + self.i2.__iterator_get_unchecked(idx - i1_len) + } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a mut T> { + match self.i2.next_back() { + Some(val) => Some(val), + None => { + // most of the time, the iterator will either always + // call next(), or always call next_back(). By swapping + // the iterators once the first one is empty, we ensure + // that the first branch is taken as often as possible, + // without sacrificing correctness, as i2 is empty anyways + mem::swap(&mut self.i1, &mut self.i2); + self.i2.next_back() + } + } + } + + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + match self.i2.advance_back_by(n) { + Ok(()) => Ok(()), + Err(remaining) => { + mem::swap(&mut self.i1, &mut self.i2); + self.i2.advance_back_by(remaining.get()) + } + } + } + + fn rfold(self, accum: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let accum = self.i2.rfold(accum, &mut f); + self.i1.rfold(accum, &mut f) + } + + fn try_rfold(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let acc = self.i2.try_rfold(init, &mut f)?; + self.i1.try_rfold(acc, &mut f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IterMut<'_, T> { + fn len(&self) -> usize { + self.i1.len() + self.i2.len() + } + + fn is_empty(&self) -> bool { + self.i1.is_empty() && self.i2.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IterMut<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IterMut<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for IterMut<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccessNoCoerce for IterMut<'_, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} diff --git a/CoqOfRust/alloc/collections/vec_deque/macros.rs b/CoqOfRust/alloc/collections/vec_deque/macros.rs new file mode 100644 index 000000000..5c7913073 --- /dev/null +++ b/CoqOfRust/alloc/collections/vec_deque/macros.rs @@ -0,0 +1,19 @@ +macro_rules! __impl_slice_eq1 { + ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { + #[stable(feature = "vec_deque_partial_eq_slice", since = "1.17.0")] + impl PartialEq<$rhs> for $lhs + where + T: PartialEq, + $($constraints)* + { + fn eq(&self, other: &$rhs) -> bool { + if self.len() != other.len() { + return false; + } + let (sa, sb) = self.as_slices(); + let (oa, ob) = other[..].split_at(sa.len()); + sa == oa && sb == ob + } + } + } +} diff --git a/CoqOfRust/alloc/collections/vec_deque/mod.rs b/CoqOfRust/alloc/collections/vec_deque/mod.rs new file mode 100644 index 000000000..cf51a84bb --- /dev/null +++ b/CoqOfRust/alloc/collections/vec_deque/mod.rs @@ -0,0 +1,3081 @@ +//! A double-ended queue (deque) implemented with a growable ring buffer. +//! +//! This queue has *O*(1) amortized inserts and removals from both ends of the +//! container. It also has *O*(1) indexing like a vector. The contained elements +//! are not required to be copyable, and the queue will be sendable if the +//! contained type is sendable. + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::cmp::{self, Ordering}; +use core::hash::{Hash, Hasher}; +use core::iter::{ByRefSized, repeat_n, repeat_with}; +// This is used in a bunch of intra-doc links. +// FIXME: For some reason, `#[cfg(doc)]` wasn't sufficient, resulting in +// failures in linkchecker even though rustdoc built the docs just fine. +#[allow(unused_imports)] +use core::mem; +use core::mem::{ManuallyDrop, SizedTypeProperties}; +use core::ops::{Index, IndexMut, Range, RangeBounds}; +use core::{fmt, ptr, slice}; + +use crate::alloc::{Allocator, Global}; +use crate::collections::{TryReserveError, TryReserveErrorKind}; +use crate::raw_vec::RawVec; +use crate::vec::Vec; + +#[macro_use] +mod macros; + +#[stable(feature = "drain", since = "1.6.0")] +pub use self::drain::Drain; + +mod drain; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::iter_mut::IterMut; + +mod iter_mut; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::into_iter::IntoIter; + +mod into_iter; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::iter::Iter; + +mod iter; + +use self::spec_extend::SpecExtend; + +mod spec_extend; + +use self::spec_from_iter::SpecFromIter; + +mod spec_from_iter; + +#[cfg(test)] +mod tests; + +/// A double-ended queue implemented with a growable ring buffer. +/// +/// The "default" usage of this type as a queue is to use [`push_back`] to add to +/// the queue, and [`pop_front`] to remove from the queue. [`extend`] and [`append`] +/// push onto the back in this manner, and iterating over `VecDeque` goes front +/// to back. +/// +/// A `VecDeque` with a known list of items can be initialized from an array: +/// +/// ``` +/// use std::collections::VecDeque; +/// +/// let deq = VecDeque::from([-1, 0, 1]); +/// ``` +/// +/// Since `VecDeque` is a ring buffer, its elements are not necessarily contiguous +/// in memory. If you want to access the elements as a single slice, such as for +/// efficient sorting, you can use [`make_contiguous`]. It rotates the `VecDeque` +/// so that its elements do not wrap, and returns a mutable slice to the +/// now-contiguous element sequence. +/// +/// [`push_back`]: VecDeque::push_back +/// [`pop_front`]: VecDeque::pop_front +/// [`extend`]: VecDeque::extend +/// [`append`]: VecDeque::append +/// [`make_contiguous`]: VecDeque::make_contiguous +#[cfg_attr(not(test), rustc_diagnostic_item = "VecDeque")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_insignificant_dtor] +pub struct VecDeque< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + // `self[0]`, if it exists, is `buf[head]`. + // `head < buf.capacity()`, unless `buf.capacity() == 0` when `head == 0`. + head: usize, + // the number of initialized elements, starting from the one at `head` and potentially wrapping around. + // if `len == 0`, the exact value of `head` is unimportant. + // if `T` is zero-Sized, then `self.len <= usize::MAX`, otherwise `self.len <= isize::MAX as usize`. + len: usize, + buf: RawVec, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for VecDeque { + #[track_caller] + fn clone(&self) -> Self { + let mut deq = Self::with_capacity_in(self.len(), self.allocator().clone()); + deq.extend(self.iter().cloned()); + deq + } + + /// Overwrites the contents of `self` with a clone of the contents of `source`. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids reallocation if possible. + #[track_caller] + fn clone_from(&mut self, source: &Self) { + self.clear(); + self.extend(source.iter().cloned()); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T, A: Allocator> Drop for VecDeque { + fn drop(&mut self) { + /// Runs the destructor for all items in the slice when it gets dropped (normally or + /// during unwinding). + struct Dropper<'a, T>(&'a mut [T]); + + impl<'a, T> Drop for Dropper<'a, T> { + fn drop(&mut self) { + unsafe { + ptr::drop_in_place(self.0); + } + } + } + + let (front, back) = self.as_mut_slices(); + unsafe { + let _back_dropper = Dropper(back); + // use drop for [T] + ptr::drop_in_place(front); + } + // RawVec handles deallocation + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for VecDeque { + /// Creates an empty deque. + #[inline] + fn default() -> VecDeque { + VecDeque::new() + } +} + +impl VecDeque { + /// Marginally more convenient + #[inline] + fn ptr(&self) -> *mut T { + self.buf.ptr() + } + + /// Appends an element to the buffer. + /// + /// # Safety + /// + /// May only be called if `deque.len() < deque.capacity()` + #[inline] + unsafe fn push_unchecked(&mut self, element: T) { + // SAFETY: Because of the precondition, it's guaranteed that there is space + // in the logical array after the last element. + unsafe { self.buffer_write(self.to_physical_idx(self.len), element) }; + // This can't overflow because `deque.len() < deque.capacity() <= usize::MAX`. + self.len += 1; + } + + /// Moves an element out of the buffer + #[inline] + unsafe fn buffer_read(&mut self, off: usize) -> T { + unsafe { ptr::read(self.ptr().add(off)) } + } + + /// Writes an element into the buffer, moving it. + #[inline] + unsafe fn buffer_write(&mut self, off: usize, value: T) { + unsafe { + ptr::write(self.ptr().add(off), value); + } + } + + /// Returns a slice pointer into the buffer. + /// `range` must lie inside `0..self.capacity()`. + #[inline] + unsafe fn buffer_range(&self, range: Range) -> *mut [T] { + unsafe { + ptr::slice_from_raw_parts_mut(self.ptr().add(range.start), range.end - range.start) + } + } + + /// Returns `true` if the buffer is at full capacity. + #[inline] + fn is_full(&self) -> bool { + self.len == self.capacity() + } + + /// Returns the index in the underlying buffer for a given logical element + /// index + addend. + #[inline] + fn wrap_add(&self, idx: usize, addend: usize) -> usize { + wrap_index(idx.wrapping_add(addend), self.capacity()) + } + + #[inline] + fn to_physical_idx(&self, idx: usize) -> usize { + self.wrap_add(self.head, idx) + } + + /// Returns the index in the underlying buffer for a given logical element + /// index - subtrahend. + #[inline] + fn wrap_sub(&self, idx: usize, subtrahend: usize) -> usize { + wrap_index(idx.wrapping_sub(subtrahend).wrapping_add(self.capacity()), self.capacity()) + } + + /// Copies a contiguous block of memory len long from src to dst + #[inline] + unsafe fn copy(&mut self, src: usize, dst: usize, len: usize) { + debug_assert!( + dst + len <= self.capacity(), + "cpy dst={} src={} len={} cap={}", + dst, + src, + len, + self.capacity() + ); + debug_assert!( + src + len <= self.capacity(), + "cpy dst={} src={} len={} cap={}", + dst, + src, + len, + self.capacity() + ); + unsafe { + ptr::copy(self.ptr().add(src), self.ptr().add(dst), len); + } + } + + /// Copies a contiguous block of memory len long from src to dst + #[inline] + unsafe fn copy_nonoverlapping(&mut self, src: usize, dst: usize, len: usize) { + debug_assert!( + dst + len <= self.capacity(), + "cno dst={} src={} len={} cap={}", + dst, + src, + len, + self.capacity() + ); + debug_assert!( + src + len <= self.capacity(), + "cno dst={} src={} len={} cap={}", + dst, + src, + len, + self.capacity() + ); + unsafe { + ptr::copy_nonoverlapping(self.ptr().add(src), self.ptr().add(dst), len); + } + } + + /// Copies a potentially wrapping block of memory len long from src to dest. + /// (abs(dst - src) + len) must be no larger than capacity() (There must be at + /// most one continuous overlapping region between src and dest). + unsafe fn wrap_copy(&mut self, src: usize, dst: usize, len: usize) { + debug_assert!( + cmp::min(src.abs_diff(dst), self.capacity() - src.abs_diff(dst)) + len + <= self.capacity(), + "wrc dst={} src={} len={} cap={}", + dst, + src, + len, + self.capacity() + ); + + // If T is a ZST, don't do any copying. + if T::IS_ZST || src == dst || len == 0 { + return; + } + + let dst_after_src = self.wrap_sub(dst, src) < len; + + let src_pre_wrap_len = self.capacity() - src; + let dst_pre_wrap_len = self.capacity() - dst; + let src_wraps = src_pre_wrap_len < len; + let dst_wraps = dst_pre_wrap_len < len; + + match (dst_after_src, src_wraps, dst_wraps) { + (_, false, false) => { + // src doesn't wrap, dst doesn't wrap + // + // S . . . + // 1 [_ _ A A B B C C _] + // 2 [_ _ A A A A B B _] + // D . . . + // + unsafe { + self.copy(src, dst, len); + } + } + (false, false, true) => { + // dst before src, src doesn't wrap, dst wraps + // + // S . . . + // 1 [A A B B _ _ _ C C] + // 2 [A A B B _ _ _ A A] + // 3 [B B B B _ _ _ A A] + // . . D . + // + unsafe { + self.copy(src, dst, dst_pre_wrap_len); + self.copy(src + dst_pre_wrap_len, 0, len - dst_pre_wrap_len); + } + } + (true, false, true) => { + // src before dst, src doesn't wrap, dst wraps + // + // S . . . + // 1 [C C _ _ _ A A B B] + // 2 [B B _ _ _ A A B B] + // 3 [B B _ _ _ A A A A] + // . . D . + // + unsafe { + self.copy(src + dst_pre_wrap_len, 0, len - dst_pre_wrap_len); + self.copy(src, dst, dst_pre_wrap_len); + } + } + (false, true, false) => { + // dst before src, src wraps, dst doesn't wrap + // + // . . S . + // 1 [C C _ _ _ A A B B] + // 2 [C C _ _ _ B B B B] + // 3 [C C _ _ _ B B C C] + // D . . . + // + unsafe { + self.copy(src, dst, src_pre_wrap_len); + self.copy(0, dst + src_pre_wrap_len, len - src_pre_wrap_len); + } + } + (true, true, false) => { + // src before dst, src wraps, dst doesn't wrap + // + // . . S . + // 1 [A A B B _ _ _ C C] + // 2 [A A A A _ _ _ C C] + // 3 [C C A A _ _ _ C C] + // D . . . + // + unsafe { + self.copy(0, dst + src_pre_wrap_len, len - src_pre_wrap_len); + self.copy(src, dst, src_pre_wrap_len); + } + } + (false, true, true) => { + // dst before src, src wraps, dst wraps + // + // . . . S . + // 1 [A B C D _ E F G H] + // 2 [A B C D _ E G H H] + // 3 [A B C D _ E G H A] + // 4 [B C C D _ E G H A] + // . . D . . + // + debug_assert!(dst_pre_wrap_len > src_pre_wrap_len); + let delta = dst_pre_wrap_len - src_pre_wrap_len; + unsafe { + self.copy(src, dst, src_pre_wrap_len); + self.copy(0, dst + src_pre_wrap_len, delta); + self.copy(delta, 0, len - dst_pre_wrap_len); + } + } + (true, true, true) => { + // src before dst, src wraps, dst wraps + // + // . . S . . + // 1 [A B C D _ E F G H] + // 2 [A A B D _ E F G H] + // 3 [H A B D _ E F G H] + // 4 [H A B D _ E F F G] + // . . . D . + // + debug_assert!(src_pre_wrap_len > dst_pre_wrap_len); + let delta = src_pre_wrap_len - dst_pre_wrap_len; + unsafe { + self.copy(0, delta, len - src_pre_wrap_len); + self.copy(self.capacity() - delta, 0, delta); + self.copy(src, dst, dst_pre_wrap_len); + } + } + } + } + + /// Copies all values from `src` to `dst`, wrapping around if needed. + /// Assumes capacity is sufficient. + #[inline] + unsafe fn copy_slice(&mut self, dst: usize, src: &[T]) { + debug_assert!(src.len() <= self.capacity()); + let head_room = self.capacity() - dst; + if src.len() <= head_room { + unsafe { + ptr::copy_nonoverlapping(src.as_ptr(), self.ptr().add(dst), src.len()); + } + } else { + let (left, right) = src.split_at(head_room); + unsafe { + ptr::copy_nonoverlapping(left.as_ptr(), self.ptr().add(dst), left.len()); + ptr::copy_nonoverlapping(right.as_ptr(), self.ptr(), right.len()); + } + } + } + + /// Writes all values from `iter` to `dst`. + /// + /// # Safety + /// + /// Assumes no wrapping around happens. + /// Assumes capacity is sufficient. + #[inline] + unsafe fn write_iter( + &mut self, + dst: usize, + iter: impl Iterator, + written: &mut usize, + ) { + iter.enumerate().for_each(|(i, element)| unsafe { + self.buffer_write(dst + i, element); + *written += 1; + }); + } + + /// Writes all values from `iter` to `dst`, wrapping + /// at the end of the buffer and returns the number + /// of written values. + /// + /// # Safety + /// + /// Assumes that `iter` yields at most `len` items. + /// Assumes capacity is sufficient. + unsafe fn write_iter_wrapping( + &mut self, + dst: usize, + mut iter: impl Iterator, + len: usize, + ) -> usize { + struct Guard<'a, T, A: Allocator> { + deque: &'a mut VecDeque, + written: usize, + } + + impl<'a, T, A: Allocator> Drop for Guard<'a, T, A> { + fn drop(&mut self) { + self.deque.len += self.written; + } + } + + let head_room = self.capacity() - dst; + + let mut guard = Guard { deque: self, written: 0 }; + + if head_room >= len { + unsafe { guard.deque.write_iter(dst, iter, &mut guard.written) }; + } else { + unsafe { + guard.deque.write_iter( + dst, + ByRefSized(&mut iter).take(head_room), + &mut guard.written, + ); + guard.deque.write_iter(0, iter, &mut guard.written) + }; + } + + guard.written + } + + /// Frobs the head and tail sections around to handle the fact that we + /// just reallocated. Unsafe because it trusts old_capacity. + #[inline] + unsafe fn handle_capacity_increase(&mut self, old_capacity: usize) { + let new_capacity = self.capacity(); + debug_assert!(new_capacity >= old_capacity); + + // Move the shortest contiguous section of the ring buffer + // + // H := head + // L := last element (`self.to_physical_idx(self.len - 1)`) + // + // H L + // [o o o o o o o o ] + // H L + // A [o o o o o o o o . . . . . . . . ] + // L H + // [o o o o o o o o ] + // H L + // B [. . . o o o o o o o o . . . . . ] + // L H + // [o o o o o o o o ] + // L H + // C [o o o o o o . . . . . . . . o o ] + + // can't use is_contiguous() because the capacity is already updated. + if self.head <= old_capacity - self.len { + // A + // Nop + } else { + let head_len = old_capacity - self.head; + let tail_len = self.len - head_len; + if head_len > tail_len && new_capacity - old_capacity >= tail_len { + // B + unsafe { + self.copy_nonoverlapping(0, old_capacity, tail_len); + } + } else { + // C + let new_head = new_capacity - head_len; + unsafe { + // can't use copy_nonoverlapping here, because if e.g. head_len = 2 + // and new_capacity = old_capacity + 1, then the heads overlap. + self.copy(self.head, new_head, head_len); + } + self.head = new_head; + } + } + debug_assert!(self.head < self.capacity() || self.capacity() == 0); + } +} + +impl VecDeque { + /// Creates an empty deque. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque = VecDeque::new(); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_vec_deque_new", since = "1.68.0")] + #[must_use] + pub const fn new() -> VecDeque { + // FIXME(const-hack): This should just be `VecDeque::new_in(Global)` once that hits stable. + VecDeque { head: 0, len: 0, buf: RawVec::new() } + } + + /// Creates an empty deque with space for at least `capacity` elements. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque = VecDeque::with_capacity(10); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + #[track_caller] + pub fn with_capacity(capacity: usize) -> VecDeque { + Self::with_capacity_in(capacity, Global) + } + + /// Creates an empty deque with space for at least `capacity` elements. + /// + /// # Errors + /// + /// Returns an error if the capacity exceeds `isize::MAX` _bytes_, + /// or if the allocator reports allocation failure. + /// + /// # Examples + /// + /// ``` + /// # #![feature(try_with_capacity)] + /// # #[allow(unused)] + /// # fn example() -> Result<(), std::collections::TryReserveError> { + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque = VecDeque::try_with_capacity(10)?; + /// # Ok(()) } + /// ``` + #[inline] + #[unstable(feature = "try_with_capacity", issue = "91913")] + pub fn try_with_capacity(capacity: usize) -> Result, TryReserveError> { + Ok(VecDeque { head: 0, len: 0, buf: RawVec::try_with_capacity_in(capacity, Global)? }) + } +} + +impl VecDeque { + /// Creates an empty deque. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque = VecDeque::new(); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub const fn new_in(alloc: A) -> VecDeque { + VecDeque { head: 0, len: 0, buf: RawVec::new_in(alloc) } + } + + /// Creates an empty deque with space for at least `capacity` elements. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque = VecDeque::with_capacity(10); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[track_caller] + pub fn with_capacity_in(capacity: usize, alloc: A) -> VecDeque { + VecDeque { head: 0, len: 0, buf: RawVec::with_capacity_in(capacity, alloc) } + } + + /// Creates a `VecDeque` from a raw allocation, when the initialized + /// part of that allocation forms a *contiguous* subslice thereof. + /// + /// For use by `vec::IntoIter::into_vecdeque` + /// + /// # Safety + /// + /// All the usual requirements on the allocated memory like in + /// `Vec::from_raw_parts_in`, but takes a *range* of elements that are + /// initialized rather than only supporting `0..len`. Requires that + /// `initialized.start` ≤ `initialized.end` ≤ `capacity`. + #[inline] + pub(crate) unsafe fn from_contiguous_raw_parts_in( + ptr: *mut T, + initialized: Range, + capacity: usize, + alloc: A, + ) -> Self { + debug_assert!(initialized.start <= initialized.end); + debug_assert!(initialized.end <= capacity); + + // SAFETY: Our safety precondition guarantees the range length won't wrap, + // and that the allocation is valid for use in `RawVec`. + unsafe { + VecDeque { + head: initialized.start, + len: initialized.end.unchecked_sub(initialized.start), + buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), + } + } + } + + /// Provides a reference to the element at the given index. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(3); + /// buf.push_back(4); + /// buf.push_back(5); + /// buf.push_back(6); + /// assert_eq!(buf.get(1), Some(&4)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get(&self, index: usize) -> Option<&T> { + if index < self.len { + let idx = self.to_physical_idx(index); + unsafe { Some(&*self.ptr().add(idx)) } + } else { + None + } + } + + /// Provides a mutable reference to the element at the given index. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(3); + /// buf.push_back(4); + /// buf.push_back(5); + /// buf.push_back(6); + /// assert_eq!(buf[1], 4); + /// if let Some(elem) = buf.get_mut(1) { + /// *elem = 7; + /// } + /// assert_eq!(buf[1], 7); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { + if index < self.len { + let idx = self.to_physical_idx(index); + unsafe { Some(&mut *self.ptr().add(idx)) } + } else { + None + } + } + + /// Swaps elements at indices `i` and `j`. + /// + /// `i` and `j` may be equal. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Panics + /// + /// Panics if either index is out of bounds. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(3); + /// buf.push_back(4); + /// buf.push_back(5); + /// assert_eq!(buf, [3, 4, 5]); + /// buf.swap(0, 2); + /// assert_eq!(buf, [5, 4, 3]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn swap(&mut self, i: usize, j: usize) { + assert!(i < self.len()); + assert!(j < self.len()); + let ri = self.to_physical_idx(i); + let rj = self.to_physical_idx(j); + unsafe { ptr::swap(self.ptr().add(ri), self.ptr().add(rj)) } + } + + /// Returns the number of elements the deque can hold without + /// reallocating. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let buf: VecDeque = VecDeque::with_capacity(10); + /// assert!(buf.capacity() >= 10); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn capacity(&self) -> usize { + if T::IS_ZST { usize::MAX } else { self.buf.capacity() } + } + + /// Reserves the minimum capacity for at least `additional` more elements to be inserted in the + /// given deque. Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it requests. Therefore + /// capacity can not be relied upon to be precisely minimal. Prefer [`reserve`] if future + /// insertions are expected. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque = [1].into(); + /// buf.reserve_exact(10); + /// assert!(buf.capacity() >= 11); + /// ``` + /// + /// [`reserve`]: VecDeque::reserve + #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] + pub fn reserve_exact(&mut self, additional: usize) { + let new_cap = self.len.checked_add(additional).expect("capacity overflow"); + let old_cap = self.capacity(); + + if new_cap > old_cap { + self.buf.reserve_exact(self.len, additional); + unsafe { + self.handle_capacity_increase(old_cap); + } + } + } + + /// Reserves capacity for at least `additional` more elements to be inserted in the given + /// deque. The collection may reserve more space to speculatively avoid frequent reallocations. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque = [1].into(); + /// buf.reserve(10); + /// assert!(buf.capacity() >= 11); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] + pub fn reserve(&mut self, additional: usize) { + let new_cap = self.len.checked_add(additional).expect("capacity overflow"); + let old_cap = self.capacity(); + + if new_cap > old_cap { + // we don't need to reserve_exact(), as the size doesn't have + // to be a power of 2. + self.buf.reserve(self.len, additional); + unsafe { + self.handle_capacity_increase(old_cap); + } + } + } + + /// Tries to reserve the minimum capacity for at least `additional` more elements to + /// be inserted in the given deque. After calling `try_reserve_exact`, + /// capacity will be greater than or equal to `self.len() + additional` if + /// it returns `Ok(())`. Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer [`try_reserve`] if future insertions are expected. + /// + /// [`try_reserve`]: VecDeque::try_reserve + /// + /// # Errors + /// + /// If the capacity overflows `usize`, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// use std::collections::TryReserveError; + /// use std::collections::VecDeque; + /// + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { + /// let mut output = VecDeque::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve_exact(data.len())?; + /// + /// // Now we know this can't OOM(Out-Of-Memory) in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[stable(feature = "try_reserve", since = "1.57.0")] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + let new_cap = + self.len.checked_add(additional).ok_or(TryReserveErrorKind::CapacityOverflow)?; + let old_cap = self.capacity(); + + if new_cap > old_cap { + self.buf.try_reserve_exact(self.len, additional)?; + unsafe { + self.handle_capacity_increase(old_cap); + } + } + Ok(()) + } + + /// Tries to reserve capacity for at least `additional` more elements to be inserted + /// in the given deque. The collection may reserve more space to speculatively avoid + /// frequent reallocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional` if it returns + /// `Ok(())`. Does nothing if capacity is already sufficient. This method + /// preserves the contents even if an error occurs. + /// + /// # Errors + /// + /// If the capacity overflows `usize`, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// use std::collections::TryReserveError; + /// use std::collections::VecDeque; + /// + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { + /// let mut output = VecDeque::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[stable(feature = "try_reserve", since = "1.57.0")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + let new_cap = + self.len.checked_add(additional).ok_or(TryReserveErrorKind::CapacityOverflow)?; + let old_cap = self.capacity(); + + if new_cap > old_cap { + self.buf.try_reserve(self.len, additional)?; + unsafe { + self.handle_capacity_increase(old_cap); + } + } + Ok(()) + } + + /// Shrinks the capacity of the deque as much as possible. + /// + /// It will drop down as close as possible to the length but the allocator may still inform the + /// deque that there is space for a few more elements. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::with_capacity(15); + /// buf.extend(0..4); + /// assert_eq!(buf.capacity(), 15); + /// buf.shrink_to_fit(); + /// assert!(buf.capacity() >= 4); + /// ``` + #[stable(feature = "deque_extras_15", since = "1.5.0")] + #[track_caller] + pub fn shrink_to_fit(&mut self) { + self.shrink_to(0); + } + + /// Shrinks the capacity of the deque with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// If the current capacity is less than the lower limit, this is a no-op. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::with_capacity(15); + /// buf.extend(0..4); + /// assert_eq!(buf.capacity(), 15); + /// buf.shrink_to(6); + /// assert!(buf.capacity() >= 6); + /// buf.shrink_to(0); + /// assert!(buf.capacity() >= 4); + /// ``` + #[stable(feature = "shrink_to", since = "1.56.0")] + #[track_caller] + pub fn shrink_to(&mut self, min_capacity: usize) { + let target_cap = min_capacity.max(self.len); + + // never shrink ZSTs + if T::IS_ZST || self.capacity() <= target_cap { + return; + } + + // There are three cases of interest: + // All elements are out of desired bounds + // Elements are contiguous, and tail is out of desired bounds + // Elements are discontiguous + // + // At all other times, element positions are unaffected. + + // `head` and `len` are at most `isize::MAX` and `target_cap < self.capacity()`, so nothing can + // overflow. + let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len)); + // Used in the drop guard below. + let old_head = self.head; + + if self.len == 0 { + self.head = 0; + } else if self.head >= target_cap && tail_outside { + // Head and tail are both out of bounds, so copy all of them to the front. + // + // H := head + // L := last element + // H L + // [. . . . . . . . o o o o o o o . ] + // H L + // [o o o o o o o . ] + unsafe { + // nonoverlapping because `self.head >= target_cap >= self.len`. + self.copy_nonoverlapping(self.head, 0, self.len); + } + self.head = 0; + } else if self.head < target_cap && tail_outside { + // Head is in bounds, tail is out of bounds. + // Copy the overflowing part to the beginning of the + // buffer. This won't overlap because `target_cap >= self.len`. + // + // H := head + // L := last element + // H L + // [. . . o o o o o o o . . . . . . ] + // L H + // [o o . o o o o o ] + let len = self.head + self.len - target_cap; + unsafe { + self.copy_nonoverlapping(target_cap, 0, len); + } + } else if !self.is_contiguous() { + // The head slice is at least partially out of bounds, tail is in bounds. + // Copy the head backwards so it lines up with the target capacity. + // This won't overlap because `target_cap >= self.len`. + // + // H := head + // L := last element + // L H + // [o o o o o . . . . . . . . . o o ] + // L H + // [o o o o o . o o ] + let head_len = self.capacity() - self.head; + let new_head = target_cap - head_len; + unsafe { + // can't use `copy_nonoverlapping()` here because the new and old + // regions for the head might overlap. + self.copy(self.head, new_head, head_len); + } + self.head = new_head; + } + + struct Guard<'a, T, A: Allocator> { + deque: &'a mut VecDeque, + old_head: usize, + target_cap: usize, + } + + impl Drop for Guard<'_, T, A> { + #[cold] + fn drop(&mut self) { + unsafe { + // SAFETY: This is only called if `buf.shrink_to_fit` unwinds, + // which is the only time it's safe to call `abort_shrink`. + self.deque.abort_shrink(self.old_head, self.target_cap) + } + } + } + + let guard = Guard { deque: self, old_head, target_cap }; + + guard.deque.buf.shrink_to_fit(target_cap); + + // Don't drop the guard if we didn't unwind. + mem::forget(guard); + + debug_assert!(self.head < self.capacity() || self.capacity() == 0); + debug_assert!(self.len <= self.capacity()); + } + + /// Reverts the deque back into a consistent state in case `shrink_to` failed. + /// This is necessary to prevent UB if the backing allocator returns an error + /// from `shrink` and `handle_alloc_error` subsequently unwinds (see #123369). + /// + /// `old_head` refers to the head index before `shrink_to` was called. `target_cap` + /// is the capacity that it was trying to shrink to. + unsafe fn abort_shrink(&mut self, old_head: usize, target_cap: usize) { + // Moral equivalent of self.head + self.len <= target_cap. Won't overflow + // because `self.len <= target_cap`. + if self.head <= target_cap - self.len { + // The deque's buffer is contiguous, so no need to copy anything around. + return; + } + + // `shrink_to` already copied the head to fit into the new capacity, so this won't overflow. + let head_len = target_cap - self.head; + // `self.head > target_cap - self.len` => `self.len > target_cap - self.head =: head_len` so this must be positive. + let tail_len = self.len - head_len; + + if tail_len <= cmp::min(head_len, self.capacity() - target_cap) { + // There's enough spare capacity to copy the tail to the back (because `tail_len < self.capacity() - target_cap`), + // and copying the tail should be cheaper than copying the head (because `tail_len <= head_len`). + + unsafe { + // The old tail and the new tail can't overlap because the head slice lies between them. The + // head slice ends at `target_cap`, so that's where we copy to. + self.copy_nonoverlapping(0, target_cap, tail_len); + } + } else { + // Either there's not enough spare capacity to make the deque contiguous, or the head is shorter than the tail + // (and therefore hopefully cheaper to copy). + unsafe { + // The old and the new head slice can overlap, so we can't use `copy_nonoverlapping` here. + self.copy(self.head, old_head, head_len); + self.head = old_head; + } + } + } + + /// Shortens the deque, keeping the first `len` elements and dropping + /// the rest. + /// + /// If `len` is greater or equal to the deque's current length, this has + /// no effect. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(5); + /// buf.push_back(10); + /// buf.push_back(15); + /// assert_eq!(buf, [5, 10, 15]); + /// buf.truncate(1); + /// assert_eq!(buf, [5]); + /// ``` + #[stable(feature = "deque_extras", since = "1.16.0")] + pub fn truncate(&mut self, len: usize) { + /// Runs the destructor for all items in the slice when it gets dropped (normally or + /// during unwinding). + struct Dropper<'a, T>(&'a mut [T]); + + impl<'a, T> Drop for Dropper<'a, T> { + fn drop(&mut self) { + unsafe { + ptr::drop_in_place(self.0); + } + } + } + + // Safe because: + // + // * Any slice passed to `drop_in_place` is valid; the second case has + // `len <= front.len()` and returning on `len > self.len()` ensures + // `begin <= back.len()` in the first case + // * The head of the VecDeque is moved before calling `drop_in_place`, + // so no value is dropped twice if `drop_in_place` panics + unsafe { + if len >= self.len { + return; + } + + let (front, back) = self.as_mut_slices(); + if len > front.len() { + let begin = len - front.len(); + let drop_back = back.get_unchecked_mut(begin..) as *mut _; + self.len = len; + ptr::drop_in_place(drop_back); + } else { + let drop_back = back as *mut _; + let drop_front = front.get_unchecked_mut(len..) as *mut _; + self.len = len; + + // Make sure the second half is dropped even when a destructor + // in the first one panics. + let _back_dropper = Dropper(&mut *drop_back); + ptr::drop_in_place(drop_front); + } + } + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + self.buf.allocator() + } + + /// Returns a front-to-back iterator. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(5); + /// buf.push_back(3); + /// buf.push_back(4); + /// let b: &[_] = &[&5, &3, &4]; + /// let c: Vec<&i32> = buf.iter().collect(); + /// assert_eq!(&c[..], b); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "vecdeque_iter")] + pub fn iter(&self) -> Iter<'_, T> { + let (a, b) = self.as_slices(); + Iter::new(a.iter(), b.iter()) + } + + /// Returns a front-to-back iterator that returns mutable references. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(5); + /// buf.push_back(3); + /// buf.push_back(4); + /// for num in buf.iter_mut() { + /// *num = *num - 2; + /// } + /// let b: &[_] = &[&mut 3, &mut 1, &mut 2]; + /// assert_eq!(&buf.iter_mut().collect::>()[..], b); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter_mut(&mut self) -> IterMut<'_, T> { + let (a, b) = self.as_mut_slices(); + IterMut::new(a.iter_mut(), b.iter_mut()) + } + + /// Returns a pair of slices which contain, in order, the contents of the + /// deque. + /// + /// If [`make_contiguous`] was previously called, all elements of the + /// deque will be in the first slice and the second slice will be empty. + /// + /// [`make_contiguous`]: VecDeque::make_contiguous + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut deque = VecDeque::new(); + /// + /// deque.push_back(0); + /// deque.push_back(1); + /// deque.push_back(2); + /// + /// assert_eq!(deque.as_slices(), (&[0, 1, 2][..], &[][..])); + /// + /// deque.push_front(10); + /// deque.push_front(9); + /// + /// assert_eq!(deque.as_slices(), (&[9, 10][..], &[0, 1, 2][..])); + /// ``` + #[inline] + #[stable(feature = "deque_extras_15", since = "1.5.0")] + pub fn as_slices(&self) -> (&[T], &[T]) { + let (a_range, b_range) = self.slice_ranges(.., self.len); + // SAFETY: `slice_ranges` always returns valid ranges into + // the physical buffer. + unsafe { (&*self.buffer_range(a_range), &*self.buffer_range(b_range)) } + } + + /// Returns a pair of slices which contain, in order, the contents of the + /// deque. + /// + /// If [`make_contiguous`] was previously called, all elements of the + /// deque will be in the first slice and the second slice will be empty. + /// + /// [`make_contiguous`]: VecDeque::make_contiguous + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut deque = VecDeque::new(); + /// + /// deque.push_back(0); + /// deque.push_back(1); + /// + /// deque.push_front(10); + /// deque.push_front(9); + /// + /// deque.as_mut_slices().0[0] = 42; + /// deque.as_mut_slices().1[0] = 24; + /// assert_eq!(deque.as_slices(), (&[42, 10][..], &[24, 1][..])); + /// ``` + #[inline] + #[stable(feature = "deque_extras_15", since = "1.5.0")] + pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) { + let (a_range, b_range) = self.slice_ranges(.., self.len); + // SAFETY: `slice_ranges` always returns valid ranges into + // the physical buffer. + unsafe { (&mut *self.buffer_range(a_range), &mut *self.buffer_range(b_range)) } + } + + /// Returns the number of elements in the deque. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut deque = VecDeque::new(); + /// assert_eq!(deque.len(), 0); + /// deque.push_back(1); + /// assert_eq!(deque.len(), 1); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("length", "size")] + pub fn len(&self) -> usize { + self.len + } + + /// Returns `true` if the deque is empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut deque = VecDeque::new(); + /// assert!(deque.is_empty()); + /// deque.push_front(1); + /// assert!(!deque.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + self.len == 0 + } + + /// Given a range into the logical buffer of the deque, this function + /// return two ranges into the physical buffer that correspond to + /// the given range. The `len` parameter should usually just be `self.len`; + /// the reason it's passed explicitly is that if the deque is wrapped in + /// a `Drain`, then `self.len` is not actually the length of the deque. + /// + /// # Safety + /// + /// This function is always safe to call. For the resulting ranges to be valid + /// ranges into the physical buffer, the caller must ensure that the result of + /// calling `slice::range(range, ..len)` represents a valid range into the + /// logical buffer, and that all elements in that range are initialized. + fn slice_ranges(&self, range: R, len: usize) -> (Range, Range) + where + R: RangeBounds, + { + let Range { start, end } = slice::range(range, ..len); + let len = end - start; + + if len == 0 { + (0..0, 0..0) + } else { + // `slice::range` guarantees that `start <= end <= len`. + // because `len != 0`, we know that `start < end`, so `start < len` + // and the indexing is valid. + let wrapped_start = self.to_physical_idx(start); + + // this subtraction can never overflow because `wrapped_start` is + // at most `self.capacity()` (and if `self.capacity != 0`, then `wrapped_start` is strictly less + // than `self.capacity`). + let head_len = self.capacity() - wrapped_start; + + if head_len >= len { + // we know that `len + wrapped_start <= self.capacity <= usize::MAX`, so this addition can't overflow + (wrapped_start..wrapped_start + len, 0..0) + } else { + // can't overflow because of the if condition + let tail_len = len - head_len; + (wrapped_start..self.capacity(), 0..tail_len) + } + } + } + + /// Creates an iterator that covers the specified range in the deque. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the deque. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque<_> = [1, 2, 3].into(); + /// let range = deque.range(2..).copied().collect::>(); + /// assert_eq!(range, [3]); + /// + /// // A full range covers all contents + /// let all = deque.range(..); + /// assert_eq!(all.len(), 3); + /// ``` + #[inline] + #[stable(feature = "deque_range", since = "1.51.0")] + pub fn range(&self, range: R) -> Iter<'_, T> + where + R: RangeBounds, + { + let (a_range, b_range) = self.slice_ranges(range, self.len); + // SAFETY: The ranges returned by `slice_ranges` + // are valid ranges into the physical buffer, so + // it's ok to pass them to `buffer_range` and + // dereference the result. + let a = unsafe { &*self.buffer_range(a_range) }; + let b = unsafe { &*self.buffer_range(b_range) }; + Iter::new(a.iter(), b.iter()) + } + + /// Creates an iterator that covers the specified mutable range in the deque. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the deque. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut deque: VecDeque<_> = [1, 2, 3].into(); + /// for v in deque.range_mut(2..) { + /// *v *= 2; + /// } + /// assert_eq!(deque, [1, 2, 6]); + /// + /// // A full range covers all contents + /// for v in deque.range_mut(..) { + /// *v *= 2; + /// } + /// assert_eq!(deque, [2, 4, 12]); + /// ``` + #[inline] + #[stable(feature = "deque_range", since = "1.51.0")] + pub fn range_mut(&mut self, range: R) -> IterMut<'_, T> + where + R: RangeBounds, + { + let (a_range, b_range) = self.slice_ranges(range, self.len); + // SAFETY: The ranges returned by `slice_ranges` + // are valid ranges into the physical buffer, so + // it's ok to pass them to `buffer_range` and + // dereference the result. + let a = unsafe { &mut *self.buffer_range(a_range) }; + let b = unsafe { &mut *self.buffer_range(b_range) }; + IterMut::new(a.iter_mut(), b.iter_mut()) + } + + /// Removes the specified range from the deque in bulk, returning all + /// removed elements as an iterator. If the iterator is dropped before + /// being fully consumed, it drops the remaining removed elements. + /// + /// The returned iterator keeps a mutable borrow on the queue to optimize + /// its implementation. + /// + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the deque. + /// + /// # Leaking + /// + /// If the returned iterator goes out of scope without being dropped (due to + /// [`mem::forget`], for example), the deque may have lost and leaked + /// elements arbitrarily, including elements outside the range. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut deque: VecDeque<_> = [1, 2, 3].into(); + /// let drained = deque.drain(2..).collect::>(); + /// assert_eq!(drained, [3]); + /// assert_eq!(deque, [1, 2]); + /// + /// // A full range clears all contents, like `clear()` does + /// deque.drain(..); + /// assert!(deque.is_empty()); + /// ``` + #[inline] + #[stable(feature = "drain", since = "1.6.0")] + pub fn drain(&mut self, range: R) -> Drain<'_, T, A> + where + R: RangeBounds, + { + // Memory safety + // + // When the Drain is first created, the source deque is shortened to + // make sure no uninitialized or moved-from elements are accessible at + // all if the Drain's destructor never gets to run. + // + // Drain will ptr::read out the values to remove. + // When finished, the remaining data will be copied back to cover the hole, + // and the head/tail values will be restored correctly. + // + let Range { start, end } = slice::range(range, ..self.len); + let drain_start = start; + let drain_len = end - start; + + // The deque's elements are parted into three segments: + // * 0 -> drain_start + // * drain_start -> drain_start+drain_len + // * drain_start+drain_len -> self.len + // + // H = self.head; T = self.head+self.len; t = drain_start+drain_len; h = drain_head + // + // We store drain_start as self.len, and drain_len and self.len as + // drain_len and orig_len respectively on the Drain. This also + // truncates the effective array such that if the Drain is leaked, we + // have forgotten about the potentially moved values after the start of + // the drain. + // + // H h t T + // [. . . o o x x o o . . .] + // + // "forget" about the values after the start of the drain until after + // the drain is complete and the Drain destructor is run. + + unsafe { Drain::new(self, drain_start, drain_len) } + } + + /// Clears the deque, removing all values. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut deque = VecDeque::new(); + /// deque.push_back(1); + /// deque.clear(); + /// assert!(deque.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn clear(&mut self) { + self.truncate(0); + // Not strictly necessary, but leaves things in a more consistent/predictable state. + self.head = 0; + } + + /// Returns `true` if the deque contains an element equal to the + /// given value. + /// + /// This operation is *O*(*n*). + /// + /// Note that if you have a sorted `VecDeque`, [`binary_search`] may be faster. + /// + /// [`binary_search`]: VecDeque::binary_search + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut deque: VecDeque = VecDeque::new(); + /// + /// deque.push_back(0); + /// deque.push_back(1); + /// + /// assert_eq!(deque.contains(&1), true); + /// assert_eq!(deque.contains(&10), false); + /// ``` + #[stable(feature = "vec_deque_contains", since = "1.12.0")] + pub fn contains(&self, x: &T) -> bool + where + T: PartialEq, + { + let (a, b) = self.as_slices(); + a.contains(x) || b.contains(x) + } + + /// Provides a reference to the front element, or `None` if the deque is + /// empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut d = VecDeque::new(); + /// assert_eq!(d.front(), None); + /// + /// d.push_back(1); + /// d.push_back(2); + /// assert_eq!(d.front(), Some(&1)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("first")] + pub fn front(&self) -> Option<&T> { + self.get(0) + } + + /// Provides a mutable reference to the front element, or `None` if the + /// deque is empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut d = VecDeque::new(); + /// assert_eq!(d.front_mut(), None); + /// + /// d.push_back(1); + /// d.push_back(2); + /// match d.front_mut() { + /// Some(x) => *x = 9, + /// None => (), + /// } + /// assert_eq!(d.front(), Some(&9)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn front_mut(&mut self) -> Option<&mut T> { + self.get_mut(0) + } + + /// Provides a reference to the back element, or `None` if the deque is + /// empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut d = VecDeque::new(); + /// assert_eq!(d.back(), None); + /// + /// d.push_back(1); + /// d.push_back(2); + /// assert_eq!(d.back(), Some(&2)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("last")] + pub fn back(&self) -> Option<&T> { + self.get(self.len.wrapping_sub(1)) + } + + /// Provides a mutable reference to the back element, or `None` if the + /// deque is empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut d = VecDeque::new(); + /// assert_eq!(d.back(), None); + /// + /// d.push_back(1); + /// d.push_back(2); + /// match d.back_mut() { + /// Some(x) => *x = 9, + /// None => (), + /// } + /// assert_eq!(d.back(), Some(&9)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn back_mut(&mut self) -> Option<&mut T> { + self.get_mut(self.len.wrapping_sub(1)) + } + + /// Removes the first element and returns it, or `None` if the deque is + /// empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut d = VecDeque::new(); + /// d.push_back(1); + /// d.push_back(2); + /// + /// assert_eq!(d.pop_front(), Some(1)); + /// assert_eq!(d.pop_front(), Some(2)); + /// assert_eq!(d.pop_front(), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop_front(&mut self) -> Option { + if self.is_empty() { + None + } else { + let old_head = self.head; + self.head = self.to_physical_idx(1); + self.len -= 1; + unsafe { + core::hint::assert_unchecked(self.len < self.capacity()); + Some(self.buffer_read(old_head)) + } + } + } + + /// Removes the last element from the deque and returns it, or `None` if + /// it is empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// assert_eq!(buf.pop_back(), None); + /// buf.push_back(1); + /// buf.push_back(3); + /// assert_eq!(buf.pop_back(), Some(3)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop_back(&mut self) -> Option { + if self.is_empty() { + None + } else { + self.len -= 1; + unsafe { + core::hint::assert_unchecked(self.len < self.capacity()); + Some(self.buffer_read(self.to_physical_idx(self.len))) + } + } + } + + /// Prepends an element to the deque. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut d = VecDeque::new(); + /// d.push_front(1); + /// d.push_front(2); + /// assert_eq!(d.front(), Some(&2)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] + pub fn push_front(&mut self, value: T) { + if self.is_full() { + self.grow(); + } + + self.head = self.wrap_sub(self.head, 1); + self.len += 1; + + unsafe { + self.buffer_write(self.head, value); + } + } + + /// Appends an element to the back of the deque. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(1); + /// buf.push_back(3); + /// assert_eq!(3, *buf.back().unwrap()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push", "put", "append")] + #[track_caller] + pub fn push_back(&mut self, value: T) { + if self.is_full() { + self.grow(); + } + + unsafe { self.buffer_write(self.to_physical_idx(self.len), value) } + self.len += 1; + } + + #[inline] + fn is_contiguous(&self) -> bool { + // Do the calculation like this to avoid overflowing if len + head > usize::MAX + self.head <= self.capacity() - self.len + } + + /// Removes an element from anywhere in the deque and returns it, + /// replacing it with the first element. + /// + /// This does not preserve ordering, but is *O*(1). + /// + /// Returns `None` if `index` is out of bounds. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// assert_eq!(buf.swap_remove_front(0), None); + /// buf.push_back(1); + /// buf.push_back(2); + /// buf.push_back(3); + /// assert_eq!(buf, [1, 2, 3]); + /// + /// assert_eq!(buf.swap_remove_front(2), Some(3)); + /// assert_eq!(buf, [2, 1]); + /// ``` + #[stable(feature = "deque_extras_15", since = "1.5.0")] + pub fn swap_remove_front(&mut self, index: usize) -> Option { + let length = self.len; + if index < length && index != 0 { + self.swap(index, 0); + } else if index >= length { + return None; + } + self.pop_front() + } + + /// Removes an element from anywhere in the deque and returns it, + /// replacing it with the last element. + /// + /// This does not preserve ordering, but is *O*(1). + /// + /// Returns `None` if `index` is out of bounds. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// assert_eq!(buf.swap_remove_back(0), None); + /// buf.push_back(1); + /// buf.push_back(2); + /// buf.push_back(3); + /// assert_eq!(buf, [1, 2, 3]); + /// + /// assert_eq!(buf.swap_remove_back(0), Some(1)); + /// assert_eq!(buf, [3, 2]); + /// ``` + #[stable(feature = "deque_extras_15", since = "1.5.0")] + pub fn swap_remove_back(&mut self, index: usize) -> Option { + let length = self.len; + if length > 0 && index < length - 1 { + self.swap(index, length - 1); + } else if index >= length { + return None; + } + self.pop_back() + } + + /// Inserts an element at `index` within the deque, shifting all elements + /// with indices greater than or equal to `index` towards the back. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Panics + /// + /// Panics if `index` is greater than deque's length + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut vec_deque = VecDeque::new(); + /// vec_deque.push_back('a'); + /// vec_deque.push_back('b'); + /// vec_deque.push_back('c'); + /// assert_eq!(vec_deque, &['a', 'b', 'c']); + /// + /// vec_deque.insert(1, 'd'); + /// assert_eq!(vec_deque, &['a', 'd', 'b', 'c']); + /// ``` + #[stable(feature = "deque_extras_15", since = "1.5.0")] + #[track_caller] + pub fn insert(&mut self, index: usize, value: T) { + assert!(index <= self.len(), "index out of bounds"); + if self.is_full() { + self.grow(); + } + + let k = self.len - index; + if k < index { + // `index + 1` can't overflow, because if index was usize::MAX, then either the + // assert would've failed, or the deque would've tried to grow past usize::MAX + // and panicked. + unsafe { + // see `remove()` for explanation why this wrap_copy() call is safe. + self.wrap_copy(self.to_physical_idx(index), self.to_physical_idx(index + 1), k); + self.buffer_write(self.to_physical_idx(index), value); + self.len += 1; + } + } else { + let old_head = self.head; + self.head = self.wrap_sub(self.head, 1); + unsafe { + self.wrap_copy(old_head, self.head, index); + self.buffer_write(self.to_physical_idx(index), value); + self.len += 1; + } + } + } + + /// Removes and returns the element at `index` from the deque. + /// Whichever end is closer to the removal point will be moved to make + /// room, and all the affected elements will be moved to new positions. + /// Returns `None` if `index` is out of bounds. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(1); + /// buf.push_back(2); + /// buf.push_back(3); + /// assert_eq!(buf, [1, 2, 3]); + /// + /// assert_eq!(buf.remove(1), Some(2)); + /// assert_eq!(buf, [1, 3]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("delete", "take")] + pub fn remove(&mut self, index: usize) -> Option { + if self.len <= index { + return None; + } + + let wrapped_idx = self.to_physical_idx(index); + + let elem = unsafe { Some(self.buffer_read(wrapped_idx)) }; + + let k = self.len - index - 1; + // safety: due to the nature of the if-condition, whichever wrap_copy gets called, + // its length argument will be at most `self.len / 2`, so there can't be more than + // one overlapping area. + if k < index { + unsafe { self.wrap_copy(self.wrap_add(wrapped_idx, 1), wrapped_idx, k) }; + self.len -= 1; + } else { + let old_head = self.head; + self.head = self.to_physical_idx(1); + unsafe { self.wrap_copy(old_head, self.head, index) }; + self.len -= 1; + } + + elem + } + + /// Splits the deque into two at the given index. + /// + /// Returns a newly allocated `VecDeque`. `self` contains elements `[0, at)`, + /// and the returned deque contains elements `[at, len)`. + /// + /// Note that the capacity of `self` does not change. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Panics + /// + /// Panics if `at > len`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = [1, 2, 3].into(); + /// let buf2 = buf.split_off(1); + /// assert_eq!(buf, [1]); + /// assert_eq!(buf2, [2, 3]); + /// ``` + #[inline] + #[must_use = "use `.truncate()` if you don't need the other half"] + #[stable(feature = "split_off", since = "1.4.0")] + #[track_caller] + pub fn split_off(&mut self, at: usize) -> Self + where + A: Clone, + { + let len = self.len; + assert!(at <= len, "`at` out of bounds"); + + let other_len = len - at; + let mut other = VecDeque::with_capacity_in(other_len, self.allocator().clone()); + + unsafe { + let (first_half, second_half) = self.as_slices(); + + let first_len = first_half.len(); + let second_len = second_half.len(); + if at < first_len { + // `at` lies in the first half. + let amount_in_first = first_len - at; + + ptr::copy_nonoverlapping(first_half.as_ptr().add(at), other.ptr(), amount_in_first); + + // just take all of the second half. + ptr::copy_nonoverlapping( + second_half.as_ptr(), + other.ptr().add(amount_in_first), + second_len, + ); + } else { + // `at` lies in the second half, need to factor in the elements we skipped + // in the first half. + let offset = at - first_len; + let amount_in_second = second_len - offset; + ptr::copy_nonoverlapping( + second_half.as_ptr().add(offset), + other.ptr(), + amount_in_second, + ); + } + } + + // Cleanup where the ends of the buffers are + self.len = at; + other.len = other_len; + + other + } + + /// Moves all the elements of `other` into `self`, leaving `other` empty. + /// + /// # Panics + /// + /// Panics if the new number of elements in self overflows a `usize`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = [1, 2].into(); + /// let mut buf2: VecDeque<_> = [3, 4].into(); + /// buf.append(&mut buf2); + /// assert_eq!(buf, [1, 2, 3, 4]); + /// assert_eq!(buf2, []); + /// ``` + #[inline] + #[stable(feature = "append", since = "1.4.0")] + #[track_caller] + pub fn append(&mut self, other: &mut Self) { + if T::IS_ZST { + self.len = self.len.checked_add(other.len).expect("capacity overflow"); + other.len = 0; + other.head = 0; + return; + } + + self.reserve(other.len); + unsafe { + let (left, right) = other.as_slices(); + self.copy_slice(self.to_physical_idx(self.len), left); + // no overflow, because self.capacity() >= old_cap + left.len() >= self.len + left.len() + self.copy_slice(self.to_physical_idx(self.len + left.len()), right); + } + // SAFETY: Update pointers after copying to avoid leaving doppelganger + // in case of panics. + self.len += other.len; + // Now that we own its values, forget everything in `other`. + other.len = 0; + other.head = 0; + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` for which `f(&e)` returns false. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.extend(1..5); + /// buf.retain(|&x| x % 2 == 0); + /// assert_eq!(buf, [2, 4]); + /// ``` + /// + /// Because the elements are visited exactly once in the original order, + /// external state may be used to decide which elements to keep. + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.extend(1..6); + /// + /// let keep = [false, true, true, false, true]; + /// let mut iter = keep.iter(); + /// buf.retain(|_| *iter.next().unwrap()); + /// assert_eq!(buf, [2, 3, 5]); + /// ``` + #[stable(feature = "vec_deque_retain", since = "1.4.0")] + pub fn retain(&mut self, mut f: F) + where + F: FnMut(&T) -> bool, + { + self.retain_mut(|elem| f(elem)); + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` for which `f(&mut e)` returns false. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.extend(1..5); + /// buf.retain_mut(|x| if *x % 2 == 0 { + /// *x += 1; + /// true + /// } else { + /// false + /// }); + /// assert_eq!(buf, [3, 5]); + /// ``` + #[stable(feature = "vec_retain_mut", since = "1.61.0")] + pub fn retain_mut(&mut self, mut f: F) + where + F: FnMut(&mut T) -> bool, + { + let len = self.len; + let mut idx = 0; + let mut cur = 0; + + // Stage 1: All values are retained. + while cur < len { + if !f(&mut self[cur]) { + cur += 1; + break; + } + cur += 1; + idx += 1; + } + // Stage 2: Swap retained value into current idx. + while cur < len { + if !f(&mut self[cur]) { + cur += 1; + continue; + } + + self.swap(idx, cur); + cur += 1; + idx += 1; + } + // Stage 3: Truncate all values after idx. + if cur != idx { + self.truncate(idx); + } + } + + // Double the buffer size. This method is inline(never), so we expect it to only + // be called in cold paths. + // This may panic or abort + #[inline(never)] + #[track_caller] + fn grow(&mut self) { + // Extend or possibly remove this assertion when valid use-cases for growing the + // buffer without it being full emerge + debug_assert!(self.is_full()); + let old_cap = self.capacity(); + self.buf.grow_one(); + unsafe { + self.handle_capacity_increase(old_cap); + } + debug_assert!(!self.is_full()); + } + + /// Modifies the deque in-place so that `len()` is equal to `new_len`, + /// either by removing excess elements from the back or by appending + /// elements generated by calling `generator` to the back. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(5); + /// buf.push_back(10); + /// buf.push_back(15); + /// assert_eq!(buf, [5, 10, 15]); + /// + /// buf.resize_with(5, Default::default); + /// assert_eq!(buf, [5, 10, 15, 0, 0]); + /// + /// buf.resize_with(2, || unreachable!()); + /// assert_eq!(buf, [5, 10]); + /// + /// let mut state = 100; + /// buf.resize_with(5, || { state += 1; state }); + /// assert_eq!(buf, [5, 10, 101, 102, 103]); + /// ``` + #[stable(feature = "vec_resize_with", since = "1.33.0")] + #[track_caller] + pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut() -> T) { + let len = self.len; + + if new_len > len { + self.extend(repeat_with(generator).take(new_len - len)) + } else { + self.truncate(new_len); + } + } + + /// Rearranges the internal storage of this deque so it is one contiguous + /// slice, which is then returned. + /// + /// This method does not allocate and does not change the order of the + /// inserted elements. As it returns a mutable slice, this can be used to + /// sort a deque. + /// + /// Once the internal storage is contiguous, the [`as_slices`] and + /// [`as_mut_slices`] methods will return the entire contents of the + /// deque in a single slice. + /// + /// [`as_slices`]: VecDeque::as_slices + /// [`as_mut_slices`]: VecDeque::as_mut_slices + /// + /// # Examples + /// + /// Sorting the content of a deque. + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::with_capacity(15); + /// + /// buf.push_back(2); + /// buf.push_back(1); + /// buf.push_front(3); + /// + /// // sorting the deque + /// buf.make_contiguous().sort(); + /// assert_eq!(buf.as_slices(), (&[1, 2, 3] as &[_], &[] as &[_])); + /// + /// // sorting it in reverse order + /// buf.make_contiguous().sort_by(|a, b| b.cmp(a)); + /// assert_eq!(buf.as_slices(), (&[3, 2, 1] as &[_], &[] as &[_])); + /// ``` + /// + /// Getting immutable access to the contiguous slice. + /// + /// ```rust + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// + /// buf.push_back(2); + /// buf.push_back(1); + /// buf.push_front(3); + /// + /// buf.make_contiguous(); + /// if let (slice, &[]) = buf.as_slices() { + /// // we can now be sure that `slice` contains all elements of the deque, + /// // while still having immutable access to `buf`. + /// assert_eq!(buf.len(), slice.len()); + /// assert_eq!(slice, &[3, 2, 1] as &[_]); + /// } + /// ``` + #[stable(feature = "deque_make_contiguous", since = "1.48.0")] + pub fn make_contiguous(&mut self) -> &mut [T] { + if T::IS_ZST { + self.head = 0; + } + + if self.is_contiguous() { + unsafe { return slice::from_raw_parts_mut(self.ptr().add(self.head), self.len) } + } + + let &mut Self { head, len, .. } = self; + let ptr = self.ptr(); + let cap = self.capacity(); + + let free = cap - len; + let head_len = cap - head; + let tail = len - head_len; + let tail_len = tail; + + if free >= head_len { + // there is enough free space to copy the head in one go, + // this means that we first shift the tail backwards, and then + // copy the head to the correct position. + // + // from: DEFGH....ABC + // to: ABCDEFGH.... + unsafe { + self.copy(0, head_len, tail_len); + // ...DEFGH.ABC + self.copy_nonoverlapping(head, 0, head_len); + // ABCDEFGH.... + } + + self.head = 0; + } else if free >= tail_len { + // there is enough free space to copy the tail in one go, + // this means that we first shift the head forwards, and then + // copy the tail to the correct position. + // + // from: FGH....ABCDE + // to: ...ABCDEFGH. + unsafe { + self.copy(head, tail, head_len); + // FGHABCDE.... + self.copy_nonoverlapping(0, tail + head_len, tail_len); + // ...ABCDEFGH. + } + + self.head = tail; + } else { + // `free` is smaller than both `head_len` and `tail_len`. + // the general algorithm for this first moves the slices + // right next to each other and then uses `slice::rotate` + // to rotate them into place: + // + // initially: HIJK..ABCDEFG + // step 1: ..HIJKABCDEFG + // step 2: ..ABCDEFGHIJK + // + // or: + // + // initially: FGHIJK..ABCDE + // step 1: FGHIJKABCDE.. + // step 2: ABCDEFGHIJK.. + + // pick the shorter of the 2 slices to reduce the amount + // of memory that needs to be moved around. + if head_len > tail_len { + // tail is shorter, so: + // 1. copy tail forwards + // 2. rotate used part of the buffer + // 3. update head to point to the new beginning (which is just `free`) + + unsafe { + // if there is no free space in the buffer, then the slices are already + // right next to each other and we don't need to move any memory. + if free != 0 { + // because we only move the tail forward as much as there's free space + // behind it, we don't overwrite any elements of the head slice, and + // the slices end up right next to each other. + self.copy(0, free, tail_len); + } + + // We just copied the tail right next to the head slice, + // so all of the elements in the range are initialized + let slice = &mut *self.buffer_range(free..self.capacity()); + + // because the deque wasn't contiguous, we know that `tail_len < self.len == slice.len()`, + // so this will never panic. + slice.rotate_left(tail_len); + + // the used part of the buffer now is `free..self.capacity()`, so set + // `head` to the beginning of that range. + self.head = free; + } + } else { + // head is shorter so: + // 1. copy head backwards + // 2. rotate used part of the buffer + // 3. update head to point to the new beginning (which is the beginning of the buffer) + + unsafe { + // if there is no free space in the buffer, then the slices are already + // right next to each other and we don't need to move any memory. + if free != 0 { + // copy the head slice to lie right behind the tail slice. + self.copy(self.head, tail_len, head_len); + } + + // because we copied the head slice so that both slices lie right + // next to each other, all the elements in the range are initialized. + let slice = &mut *self.buffer_range(0..self.len); + + // because the deque wasn't contiguous, we know that `head_len < self.len == slice.len()` + // so this will never panic. + slice.rotate_right(head_len); + + // the used part of the buffer now is `0..self.len`, so set + // `head` to the beginning of that range. + self.head = 0; + } + } + } + + unsafe { slice::from_raw_parts_mut(ptr.add(self.head), self.len) } + } + + /// Rotates the double-ended queue `n` places to the left. + /// + /// Equivalently, + /// - Rotates item `n` into the first position. + /// - Pops the first `n` items and pushes them to the end. + /// - Rotates `len() - n` places to the right. + /// + /// # Panics + /// + /// If `n` is greater than `len()`. Note that `n == len()` + /// does _not_ panic and is a no-op rotation. + /// + /// # Complexity + /// + /// Takes `*O*(min(n, len() - n))` time and no extra space. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = (0..10).collect(); + /// + /// buf.rotate_left(3); + /// assert_eq!(buf, [3, 4, 5, 6, 7, 8, 9, 0, 1, 2]); + /// + /// for i in 1..10 { + /// assert_eq!(i * 3 % 10, buf[0]); + /// buf.rotate_left(3); + /// } + /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// ``` + #[stable(feature = "vecdeque_rotate", since = "1.36.0")] + pub fn rotate_left(&mut self, n: usize) { + assert!(n <= self.len()); + let k = self.len - n; + if n <= k { + unsafe { self.rotate_left_inner(n) } + } else { + unsafe { self.rotate_right_inner(k) } + } + } + + /// Rotates the double-ended queue `n` places to the right. + /// + /// Equivalently, + /// - Rotates the first item into position `n`. + /// - Pops the last `n` items and pushes them to the front. + /// - Rotates `len() - n` places to the left. + /// + /// # Panics + /// + /// If `n` is greater than `len()`. Note that `n == len()` + /// does _not_ panic and is a no-op rotation. + /// + /// # Complexity + /// + /// Takes `*O*(min(n, len() - n))` time and no extra space. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = (0..10).collect(); + /// + /// buf.rotate_right(3); + /// assert_eq!(buf, [7, 8, 9, 0, 1, 2, 3, 4, 5, 6]); + /// + /// for i in 1..10 { + /// assert_eq!(0, buf[i * 3 % 10]); + /// buf.rotate_right(3); + /// } + /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// ``` + #[stable(feature = "vecdeque_rotate", since = "1.36.0")] + pub fn rotate_right(&mut self, n: usize) { + assert!(n <= self.len()); + let k = self.len - n; + if n <= k { + unsafe { self.rotate_right_inner(n) } + } else { + unsafe { self.rotate_left_inner(k) } + } + } + + // SAFETY: the following two methods require that the rotation amount + // be less than half the length of the deque. + // + // `wrap_copy` requires that `min(x, capacity() - x) + copy_len <= capacity()`, + // but then `min` is never more than half the capacity, regardless of x, + // so it's sound to call here because we're calling with something + // less than half the length, which is never above half the capacity. + + unsafe fn rotate_left_inner(&mut self, mid: usize) { + debug_assert!(mid * 2 <= self.len()); + unsafe { + self.wrap_copy(self.head, self.to_physical_idx(self.len), mid); + } + self.head = self.to_physical_idx(mid); + } + + unsafe fn rotate_right_inner(&mut self, k: usize) { + debug_assert!(k * 2 <= self.len()); + self.head = self.wrap_sub(self.head, k); + unsafe { + self.wrap_copy(self.to_physical_idx(self.len), self.head, k); + } + } + + /// Binary searches this `VecDeque` for a given element. + /// If the `VecDeque` is not sorted, the returned result is unspecified and + /// meaningless. + /// + /// If the value is found then [`Result::Ok`] is returned, containing the + /// index of the matching element. If there are multiple matches, then any + /// one of the matches could be returned. If the value is not found then + /// [`Result::Err`] is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// See also [`binary_search_by`], [`binary_search_by_key`], and [`partition_point`]. + /// + /// [`binary_search_by`]: VecDeque::binary_search_by + /// [`binary_search_by_key`]: VecDeque::binary_search_by_key + /// [`partition_point`]: VecDeque::partition_point + /// + /// # Examples + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1, 4]`. + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque<_> = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into(); + /// + /// assert_eq!(deque.binary_search(&13), Ok(9)); + /// assert_eq!(deque.binary_search(&4), Err(7)); + /// assert_eq!(deque.binary_search(&100), Err(13)); + /// let r = deque.binary_search(&1); + /// assert!(matches!(r, Ok(1..=4))); + /// ``` + /// + /// If you want to insert an item to a sorted deque, while maintaining + /// sort order, consider using [`partition_point`]: + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut deque: VecDeque<_> = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into(); + /// let num = 42; + /// let idx = deque.partition_point(|&x| x <= num); + /// // If `num` is unique, `s.partition_point(|&x| x < num)` (with `<`) is equivalent to + /// // `s.binary_search(&num).unwrap_or_else(|x| x)`, but using `<=` may allow `insert` + /// // to shift less elements. + /// deque.insert(idx, num); + /// assert_eq!(deque, &[0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]); + /// ``` + #[stable(feature = "vecdeque_binary_search", since = "1.54.0")] + #[inline] + pub fn binary_search(&self, x: &T) -> Result + where + T: Ord, + { + self.binary_search_by(|e| e.cmp(x)) + } + + /// Binary searches this `VecDeque` with a comparator function. + /// + /// The comparator function should return an order code that indicates + /// whether its argument is `Less`, `Equal` or `Greater` the desired + /// target. + /// If the `VecDeque` is not sorted or if the comparator function does not + /// implement an order consistent with the sort order of the underlying + /// `VecDeque`, the returned result is unspecified and meaningless. + /// + /// If the value is found then [`Result::Ok`] is returned, containing the + /// index of the matching element. If there are multiple matches, then any + /// one of the matches could be returned. If the value is not found then + /// [`Result::Err`] is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// See also [`binary_search`], [`binary_search_by_key`], and [`partition_point`]. + /// + /// [`binary_search`]: VecDeque::binary_search + /// [`binary_search_by_key`]: VecDeque::binary_search_by_key + /// [`partition_point`]: VecDeque::partition_point + /// + /// # Examples + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1, 4]`. + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque<_> = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into(); + /// + /// assert_eq!(deque.binary_search_by(|x| x.cmp(&13)), Ok(9)); + /// assert_eq!(deque.binary_search_by(|x| x.cmp(&4)), Err(7)); + /// assert_eq!(deque.binary_search_by(|x| x.cmp(&100)), Err(13)); + /// let r = deque.binary_search_by(|x| x.cmp(&1)); + /// assert!(matches!(r, Ok(1..=4))); + /// ``` + #[stable(feature = "vecdeque_binary_search", since = "1.54.0")] + pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result + where + F: FnMut(&'a T) -> Ordering, + { + let (front, back) = self.as_slices(); + let cmp_back = back.first().map(|elem| f(elem)); + + if let Some(Ordering::Equal) = cmp_back { + Ok(front.len()) + } else if let Some(Ordering::Less) = cmp_back { + back.binary_search_by(f).map(|idx| idx + front.len()).map_err(|idx| idx + front.len()) + } else { + front.binary_search_by(f) + } + } + + /// Binary searches this `VecDeque` with a key extraction function. + /// + /// Assumes that the deque is sorted by the key, for instance with + /// [`make_contiguous().sort_by_key()`] using the same key extraction function. + /// If the deque is not sorted by the key, the returned result is + /// unspecified and meaningless. + /// + /// If the value is found then [`Result::Ok`] is returned, containing the + /// index of the matching element. If there are multiple matches, then any + /// one of the matches could be returned. If the value is not found then + /// [`Result::Err`] is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// See also [`binary_search`], [`binary_search_by`], and [`partition_point`]. + /// + /// [`make_contiguous().sort_by_key()`]: VecDeque::make_contiguous + /// [`binary_search`]: VecDeque::binary_search + /// [`binary_search_by`]: VecDeque::binary_search_by + /// [`partition_point`]: VecDeque::partition_point + /// + /// # Examples + /// + /// Looks up a series of four elements in a slice of pairs sorted by + /// their second elements. The first is found, with a uniquely + /// determined position; the second and third are not found; the + /// fourth could match any position in `[1, 4]`. + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque<_> = [(0, 0), (2, 1), (4, 1), (5, 1), + /// (3, 1), (1, 2), (2, 3), (4, 5), (5, 8), (3, 13), + /// (1, 21), (2, 34), (4, 55)].into(); + /// + /// assert_eq!(deque.binary_search_by_key(&13, |&(a, b)| b), Ok(9)); + /// assert_eq!(deque.binary_search_by_key(&4, |&(a, b)| b), Err(7)); + /// assert_eq!(deque.binary_search_by_key(&100, |&(a, b)| b), Err(13)); + /// let r = deque.binary_search_by_key(&1, |&(a, b)| b); + /// assert!(matches!(r, Ok(1..=4))); + /// ``` + #[stable(feature = "vecdeque_binary_search", since = "1.54.0")] + #[inline] + pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result + where + F: FnMut(&'a T) -> B, + B: Ord, + { + self.binary_search_by(|k| f(k).cmp(b)) + } + + /// Returns the index of the partition point according to the given predicate + /// (the index of the first element of the second partition). + /// + /// The deque is assumed to be partitioned according to the given predicate. + /// This means that all elements for which the predicate returns true are at the start of the deque + /// and all elements for which the predicate returns false are at the end. + /// For example, `[7, 15, 3, 5, 4, 12, 6]` is partitioned under the predicate `x % 2 != 0` + /// (all odd numbers are at the start, all even at the end). + /// + /// If the deque is not partitioned, the returned result is unspecified and meaningless, + /// as this method performs a kind of binary search. + /// + /// See also [`binary_search`], [`binary_search_by`], and [`binary_search_by_key`]. + /// + /// [`binary_search`]: VecDeque::binary_search + /// [`binary_search_by`]: VecDeque::binary_search_by + /// [`binary_search_by_key`]: VecDeque::binary_search_by_key + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque<_> = [1, 2, 3, 3, 5, 6, 7].into(); + /// let i = deque.partition_point(|&x| x < 5); + /// + /// assert_eq!(i, 4); + /// assert!(deque.iter().take(i).all(|&x| x < 5)); + /// assert!(deque.iter().skip(i).all(|&x| !(x < 5))); + /// ``` + /// + /// If you want to insert an item to a sorted deque, while maintaining + /// sort order: + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut deque: VecDeque<_> = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into(); + /// let num = 42; + /// let idx = deque.partition_point(|&x| x < num); + /// deque.insert(idx, num); + /// assert_eq!(deque, &[0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]); + /// ``` + #[stable(feature = "vecdeque_binary_search", since = "1.54.0")] + pub fn partition_point

AsyncIterator for Pin

+where + P: DerefMut, + P::Target: AsyncIterator, +{ + type Item = ::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ::poll_next(self.as_deref_mut(), cx) + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } +} + +#[unstable(feature = "async_gen_internals", issue = "none")] +impl Poll> { + /// A helper function for internal desugaring -- produces `Ready(Some(t))`, + /// which corresponds to the async iterator yielding a value. + #[doc(hidden)] + #[unstable(feature = "async_gen_internals", issue = "none")] + #[lang = "AsyncGenReady"] + pub fn async_gen_ready(t: T) -> Self { + Poll::Ready(Some(t)) + } + + /// A helper constant for internal desugaring -- produces `Pending`, + /// which corresponds to the async iterator pending on an `.await`. + #[doc(hidden)] + #[unstable(feature = "async_gen_internals", issue = "none")] + #[lang = "AsyncGenPending"] + // FIXME(gen_blocks): This probably could be deduplicated. + pub const PENDING: Self = Poll::Pending; + + /// A helper constant for internal desugaring -- produces `Ready(None)`, + /// which corresponds to the async iterator finishing its iteration. + #[doc(hidden)] + #[unstable(feature = "async_gen_internals", issue = "none")] + #[lang = "AsyncGenFinished"] + pub const FINISHED: Self = Poll::Ready(None); +} + +/// Converts something into an async iterator +#[unstable(feature = "async_iterator", issue = "79024")] +pub trait IntoAsyncIterator { + /// The type of the item yielded by the iterator + type Item; + /// The type of the resulting iterator + type IntoAsyncIter: AsyncIterator; + + /// Converts `self` into an async iterator + #[lang = "into_async_iter_into_iter"] + fn into_async_iter(self) -> Self::IntoAsyncIter; +} + +#[unstable(feature = "async_iterator", issue = "79024")] +impl IntoAsyncIterator for I { + type Item = I::Item; + type IntoAsyncIter = I; + + fn into_async_iter(self) -> Self::IntoAsyncIter { + self + } +} diff --git a/CoqOfRust/core/async_iter/from_iter.rs b/CoqOfRust/core/async_iter/from_iter.rs new file mode 100644 index 000000000..f4e10bdff --- /dev/null +++ b/CoqOfRust/core/async_iter/from_iter.rs @@ -0,0 +1,37 @@ +use crate::async_iter::AsyncIterator; +use crate::pin::Pin; +use crate::task::{Context, Poll}; + +/// An async iterator that was created from iterator. +/// +/// This async iterator is created by the [`from_iter`] function. +/// See it documentation for more. +/// +/// [`from_iter`]: fn.from_iter.html +#[unstable(feature = "async_iter_from_iter", issue = "81798")] +#[derive(Clone, Debug)] +pub struct FromIter { + iter: I, +} + +#[unstable(feature = "async_iter_from_iter", issue = "81798")] +impl Unpin for FromIter {} + +/// Converts an iterator into an async iterator. +#[unstable(feature = "async_iter_from_iter", issue = "81798")] +pub fn from_iter(iter: I) -> FromIter { + FromIter { iter: iter.into_iter() } +} + +#[unstable(feature = "async_iter_from_iter", issue = "81798")] +impl AsyncIterator for FromIter { + type Item = I::Item; + + fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + Poll::Ready(self.iter.next()) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} diff --git a/CoqOfRust/core/async_iter/mod.rs b/CoqOfRust/core/async_iter/mod.rs new file mode 100644 index 000000000..a5b03b7dd --- /dev/null +++ b/CoqOfRust/core/async_iter/mod.rs @@ -0,0 +1,128 @@ +//! Composable asynchronous iteration. +//! +//! If you've found yourself with an asynchronous collection of some kind, +//! and needed to perform an operation on the elements of said collection, +//! you'll quickly run into 'async iterators'. Async Iterators are heavily used in +//! idiomatic asynchronous Rust code, so it's worth becoming familiar with them. +//! +//! Before explaining more, let's talk about how this module is structured: +//! +//! # Organization +//! +//! This module is largely organized by type: +//! +//! * [Traits] are the core portion: these traits define what kind of async iterators +//! exist and what you can do with them. The methods of these traits are worth +//! putting some extra study time into. +//! * Functions provide some helpful ways to create some basic async iterators. +//! * Structs are often the return types of the various methods on this +//! module's traits. You'll usually want to look at the method that creates +//! the `struct`, rather than the `struct` itself. For more detail about why, +//! see '[Implementing Async Iterator](#implementing-async-iterator)'. +//! +//! [Traits]: #traits +//! +//! That's it! Let's dig into async iterators. +//! +//! # Async Iterators +//! +//! The heart and soul of this module is the [`AsyncIterator`] trait. The core of +//! [`AsyncIterator`] looks like this: +//! +//! ``` +//! # use core::task::{Context, Poll}; +//! # use core::pin::Pin; +//! trait AsyncIterator { +//! type Item; +//! fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; +//! } +//! ``` +//! +//! Unlike `Iterator`, `AsyncIterator` makes a distinction between the [`poll_next`] +//! method which is used when implementing an `AsyncIterator`, and a (to-be-implemented) +//! `next` method which is used when consuming an async iterator. Consumers of `AsyncIterator` +//! only need to consider `next`, which when called, returns a future which +//! yields `Option`. +//! +//! The future returned by `next` will yield `Some(Item)` as long as there are +//! elements, and once they've all been exhausted, will yield `None` to indicate +//! that iteration is finished. If we're waiting on something asynchronous to +//! resolve, the future will wait until the async iterator is ready to yield again. +//! +//! Individual async iterators may choose to resume iteration, and so calling `next` +//! again may or may not eventually yield `Some(Item)` again at some point. +//! +//! [`AsyncIterator`]'s full definition includes a number of other methods as well, +//! but they are default methods, built on top of [`poll_next`], and so you get +//! them for free. +//! +//! [`Poll`]: super::task::Poll +//! [`poll_next`]: AsyncIterator::poll_next +//! +//! # Implementing Async Iterator +//! +//! Creating an async iterator of your own involves two steps: creating a `struct` to +//! hold the async iterator's state, and then implementing [`AsyncIterator`] for that +//! `struct`. +//! +//! Let's make an async iterator named `Counter` which counts from `1` to `5`: +//! +//! ```no_run +//! #![feature(async_iterator)] +//! # use core::async_iter::AsyncIterator; +//! # use core::task::{Context, Poll}; +//! # use core::pin::Pin; +//! +//! // First, the struct: +//! +//! /// An async iterator which counts from one to five +//! struct Counter { +//! count: usize, +//! } +//! +//! // we want our count to start at one, so let's add a new() method to help. +//! // This isn't strictly necessary, but is convenient. Note that we start +//! // `count` at zero, we'll see why in `poll_next()`'s implementation below. +//! impl Counter { +//! fn new() -> Counter { +//! Counter { count: 0 } +//! } +//! } +//! +//! // Then, we implement `AsyncIterator` for our `Counter`: +//! +//! impl AsyncIterator for Counter { +//! // we will be counting with usize +//! type Item = usize; +//! +//! // poll_next() is the only required method +//! fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { +//! // Increment our count. This is why we started at zero. +//! self.count += 1; +//! +//! // Check to see if we've finished counting or not. +//! if self.count < 6 { +//! Poll::Ready(Some(self.count)) +//! } else { +//! Poll::Ready(None) +//! } +//! } +//! } +//! ``` +//! +//! # Laziness +//! +//! Async iterators are *lazy*. This means that just creating an async iterator doesn't +//! _do_ a whole lot. Nothing really happens until you call `poll_next`. This is +//! sometimes a source of confusion when creating an async iterator solely for its side +//! effects. The compiler will warn us about this kind of behavior: +//! +//! ```text +//! warning: unused result that must be used: async iterators do nothing unless polled +//! ``` + +mod async_iter; +mod from_iter; + +pub use async_iter::{AsyncIterator, IntoAsyncIterator}; +pub use from_iter::{FromIter, from_iter}; diff --git a/CoqOfRust/core/bool.rs b/CoqOfRust/core/bool.rs new file mode 100644 index 000000000..58a870d2e --- /dev/null +++ b/CoqOfRust/core/bool.rs @@ -0,0 +1,63 @@ +//! impl bool {} + +impl bool { + /// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html), + /// or `None` otherwise. + /// + /// Arguments passed to `then_some` are eagerly evaluated; if you are + /// passing the result of a function call, it is recommended to use + /// [`then`], which is lazily evaluated. + /// + /// [`then`]: bool::then + /// + /// # Examples + /// + /// ``` + /// assert_eq!(false.then_some(0), None); + /// assert_eq!(true.then_some(0), Some(0)); + /// ``` + /// + /// ``` + /// let mut a = 0; + /// let mut function_with_side_effects = || { a += 1; }; + /// + /// true.then_some(function_with_side_effects()); + /// false.then_some(function_with_side_effects()); + /// + /// // `a` is incremented twice because the value passed to `then_some` is + /// // evaluated eagerly. + /// assert_eq!(a, 2); + /// ``` + #[stable(feature = "bool_to_option", since = "1.62.0")] + #[inline] + pub fn then_some(self, t: T) -> Option { + if self { Some(t) } else { None } + } + + /// Returns `Some(f())` if the `bool` is [`true`](../std/keyword.true.html), + /// or `None` otherwise. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(false.then(|| 0), None); + /// assert_eq!(true.then(|| 0), Some(0)); + /// ``` + /// + /// ``` + /// let mut a = 0; + /// + /// true.then(|| { a += 1; }); + /// false.then(|| { a += 1; }); + /// + /// // `a` is incremented once because the closure is evaluated lazily by + /// // `then`. + /// assert_eq!(a, 1); + /// ``` + #[stable(feature = "lazy_bool_to_option", since = "1.50.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "bool_then")] + #[inline] + pub fn then T>(self, f: F) -> Option { + if self { Some(f()) } else { None } + } +} diff --git a/CoqOfRust/core/borrow.rs b/CoqOfRust/core/borrow.rs new file mode 100644 index 000000000..ccb1cc4e9 --- /dev/null +++ b/CoqOfRust/core/borrow.rs @@ -0,0 +1,242 @@ +//! Utilities for working with borrowed data. + +#![stable(feature = "rust1", since = "1.0.0")] + +/// A trait for borrowing data. +/// +/// In Rust, it is common to provide different representations of a type for +/// different use cases. For instance, storage location and management for a +/// value can be specifically chosen as appropriate for a particular use via +/// pointer types such as [`Box`] or [`Rc`]. Beyond these generic +/// wrappers that can be used with any type, some types provide optional +/// facets providing potentially costly functionality. An example for such a +/// type is [`String`] which adds the ability to extend a string to the basic +/// [`str`]. This requires keeping additional information unnecessary for a +/// simple, immutable string. +/// +/// These types provide access to the underlying data through references +/// to the type of that data. They are said to be ‘borrowed as’ that type. +/// For instance, a [`Box`] can be borrowed as `T` while a [`String`] +/// can be borrowed as `str`. +/// +/// Types express that they can be borrowed as some type `T` by implementing +/// `Borrow`, providing a reference to a `T` in the trait’s +/// [`borrow`] method. A type is free to borrow as several different types. +/// If it wishes to mutably borrow as the type, allowing the underlying data +/// to be modified, it can additionally implement [`BorrowMut`]. +/// +/// Further, when providing implementations for additional traits, it needs +/// to be considered whether they should behave identically to those of the +/// underlying type as a consequence of acting as a representation of that +/// underlying type. Generic code typically uses `Borrow` when it relies +/// on the identical behavior of these additional trait implementations. +/// These traits will likely appear as additional trait bounds. +/// +/// In particular `Eq`, `Ord` and `Hash` must be equivalent for +/// borrowed and owned values: `x.borrow() == y.borrow()` should give the +/// same result as `x == y`. +/// +/// If generic code merely needs to work for all types that can +/// provide a reference to related type `T`, it is often better to use +/// [`AsRef`] as more types can safely implement it. +/// +/// [`Box`]: ../../std/boxed/struct.Box.html +/// [`Mutex`]: ../../std/sync/struct.Mutex.html +/// [`Rc`]: ../../std/rc/struct.Rc.html +/// [`String`]: ../../std/string/struct.String.html +/// [`borrow`]: Borrow::borrow +/// +/// # Examples +/// +/// As a data collection, [`HashMap`] owns both keys and values. If +/// the key’s actual data is wrapped in a managing type of some kind, it +/// should, however, still be possible to search for a value using a +/// reference to the key’s data. For instance, if the key is a string, then +/// it is likely stored with the hash map as a [`String`], while it should +/// be possible to search using a [`&str`][`str`]. Thus, `insert` needs to +/// operate on a `String` while `get` needs to be able to use a `&str`. +/// +/// Slightly simplified, the relevant parts of `HashMap` look like +/// this: +/// +/// ``` +/// use std::borrow::Borrow; +/// use std::hash::Hash; +/// +/// pub struct HashMap { +/// # marker: ::std::marker::PhantomData<(K, V)>, +/// // fields omitted +/// } +/// +/// impl HashMap { +/// pub fn insert(&self, key: K, value: V) -> Option +/// where K: Hash + Eq +/// { +/// # unimplemented!() +/// // ... +/// } +/// +/// pub fn get(&self, k: &Q) -> Option<&V> +/// where +/// K: Borrow, +/// Q: Hash + Eq + ?Sized +/// { +/// # unimplemented!() +/// // ... +/// } +/// } +/// ``` +/// +/// The entire hash map is generic over a key type `K`. Because these keys +/// are stored with the hash map, this type has to own the key’s data. +/// When inserting a key-value pair, the map is given such a `K` and needs +/// to find the correct hash bucket and check if the key is already present +/// based on that `K`. It therefore requires `K: Hash + Eq`. +/// +/// When searching for a value in the map, however, having to provide a +/// reference to a `K` as the key to search for would require to always +/// create such an owned value. For string keys, this would mean a `String` +/// value needs to be created just for the search for cases where only a +/// `str` is available. +/// +/// Instead, the `get` method is generic over the type of the underlying key +/// data, called `Q` in the method signature above. It states that `K` +/// borrows as a `Q` by requiring that `K: Borrow`. By additionally +/// requiring `Q: Hash + Eq`, it signals the requirement that `K` and `Q` +/// have implementations of the `Hash` and `Eq` traits that produce identical +/// results. +/// +/// The implementation of `get` relies in particular on identical +/// implementations of `Hash` by determining the key’s hash bucket by calling +/// `Hash::hash` on the `Q` value even though it inserted the key based on +/// the hash value calculated from the `K` value. +/// +/// As a consequence, the hash map breaks if a `K` wrapping a `Q` value +/// produces a different hash than `Q`. For instance, imagine you have a +/// type that wraps a string but compares ASCII letters ignoring their case: +/// +/// ``` +/// pub struct CaseInsensitiveString(String); +/// +/// impl PartialEq for CaseInsensitiveString { +/// fn eq(&self, other: &Self) -> bool { +/// self.0.eq_ignore_ascii_case(&other.0) +/// } +/// } +/// +/// impl Eq for CaseInsensitiveString { } +/// ``` +/// +/// Because two equal values need to produce the same hash value, the +/// implementation of `Hash` needs to ignore ASCII case, too: +/// +/// ``` +/// # use std::hash::{Hash, Hasher}; +/// # pub struct CaseInsensitiveString(String); +/// impl Hash for CaseInsensitiveString { +/// fn hash(&self, state: &mut H) { +/// for c in self.0.as_bytes() { +/// c.to_ascii_lowercase().hash(state) +/// } +/// } +/// } +/// ``` +/// +/// Can `CaseInsensitiveString` implement `Borrow`? It certainly can +/// provide a reference to a string slice via its contained owned string. +/// But because its `Hash` implementation differs, it behaves differently +/// from `str` and therefore must not, in fact, implement `Borrow`. +/// If it wants to allow others access to the underlying `str`, it can do +/// that via `AsRef` which doesn’t carry any extra requirements. +/// +/// [`Hash`]: crate::hash::Hash +/// [`HashMap`]: ../../std/collections/struct.HashMap.html +/// [`String`]: ../../std/string/struct.String.html +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Borrow"] +pub trait Borrow { + /// Immutably borrows from an owned value. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::Borrow; + /// + /// fn check>(s: T) { + /// assert_eq!("Hello", s.borrow()); + /// } + /// + /// let s = "Hello".to_string(); + /// + /// check(s); + /// + /// let s = "Hello"; + /// + /// check(s); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn borrow(&self) -> &Borrowed; +} + +/// A trait for mutably borrowing data. +/// +/// As a companion to [`Borrow`] this trait allows a type to borrow as +/// an underlying type by providing a mutable reference. See [`Borrow`] +/// for more information on borrowing as another type. +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "BorrowMut"] +pub trait BorrowMut: Borrow { + /// Mutably borrows from an owned value. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::BorrowMut; + /// + /// fn check>(mut v: T) { + /// assert_eq!(&mut [1, 2, 3], v.borrow_mut()); + /// } + /// + /// let v = vec![1, 2, 3]; + /// + /// check(v); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn borrow_mut(&mut self) -> &mut Borrowed; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow for T { + #[rustc_diagnostic_item = "noop_method_borrow"] + fn borrow(&self) -> &T { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl BorrowMut for T { + fn borrow_mut(&mut self) -> &mut T { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow for &T { + fn borrow(&self) -> &T { + &**self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow for &mut T { + fn borrow(&self) -> &T { + &**self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl BorrowMut for &mut T { + fn borrow_mut(&mut self) -> &mut T { + &mut **self + } +} diff --git a/CoqOfRust/core/cell.rs b/CoqOfRust/core/cell.rs new file mode 100644 index 000000000..cfa4c1fb5 --- /dev/null +++ b/CoqOfRust/core/cell.rs @@ -0,0 +1,2396 @@ +//! Shareable mutable containers. +//! +//! Rust memory safety is based on this rule: Given an object `T`, it is only possible to +//! have one of the following: +//! +//! - Several immutable references (`&T`) to the object (also known as **aliasing**). +//! - One mutable reference (`&mut T`) to the object (also known as **mutability**). +//! +//! This is enforced by the Rust compiler. However, there are situations where this rule is not +//! flexible enough. Sometimes it is required to have multiple references to an object and yet +//! mutate it. +//! +//! Shareable mutable containers exist to permit mutability in a controlled manner, even in the +//! presence of aliasing. [`Cell`], [`RefCell`], and [`OnceCell`] allow doing this in +//! a single-threaded way—they do not implement [`Sync`]. (If you need to do aliasing and +//! mutation among multiple threads, [`Mutex`], [`RwLock`], [`OnceLock`] or [`atomic`] +//! types are the correct data structures to do so). +//! +//! Values of the `Cell`, `RefCell`, and `OnceCell` types may be mutated through shared +//! references (i.e. the common `&T` type), whereas most Rust types can only be mutated through +//! unique (`&mut T`) references. We say these cell types provide 'interior mutability' +//! (mutable via `&T`), in contrast with typical Rust types that exhibit 'inherited mutability' +//! (mutable only via `&mut T`). +//! +//! Cell types come in three flavors: `Cell`, `RefCell`, and `OnceCell`. Each provides +//! a different way of providing safe interior mutability. +//! +//! ## `Cell` +//! +//! [`Cell`] implements interior mutability by moving values in and out of the cell. That is, an +//! `&mut T` to the inner value can never be obtained, and the value itself cannot be directly +//! obtained without replacing it with something else. Both of these rules ensure that there is +//! never more than one reference pointing to the inner value. This type provides the following +//! methods: +//! +//! - For types that implement [`Copy`], the [`get`](Cell::get) method retrieves the current +//! interior value by duplicating it. +//! - For types that implement [`Default`], the [`take`](Cell::take) method replaces the current +//! interior value with [`Default::default()`] and returns the replaced value. +//! - All types have: +//! - [`replace`](Cell::replace): replaces the current interior value and returns the replaced +//! value. +//! - [`into_inner`](Cell::into_inner): this method consumes the `Cell` and returns the +//! interior value. +//! - [`set`](Cell::set): this method replaces the interior value, dropping the replaced value. +//! +//! `Cell` is typically used for more simple types where copying or moving values isn't too +//! resource intensive (e.g. numbers), and should usually be preferred over other cell types when +//! possible. For larger and non-copy types, `RefCell` provides some advantages. +//! +//! ## `RefCell` +//! +//! [`RefCell`] uses Rust's lifetimes to implement "dynamic borrowing", a process whereby one can +//! claim temporary, exclusive, mutable access to the inner value. Borrows for `RefCell`s are +//! tracked at _runtime_, unlike Rust's native reference types which are entirely tracked +//! statically, at compile time. +//! +//! An immutable reference to a `RefCell`'s inner value (`&T`) can be obtained with +//! [`borrow`](`RefCell::borrow`), and a mutable borrow (`&mut T`) can be obtained with +//! [`borrow_mut`](`RefCell::borrow_mut`). When these functions are called, they first verify that +//! Rust's borrow rules will be satisfied: any number of immutable borrows are allowed or a +//! single mutable borrow is allowed, but never both. If a borrow is attempted that would violate +//! these rules, the thread will panic. +//! +//! The corresponding [`Sync`] version of `RefCell` is [`RwLock`]. +//! +//! ## `OnceCell` +//! +//! [`OnceCell`] is somewhat of a hybrid of `Cell` and `RefCell` that works for values that +//! typically only need to be set once. This means that a reference `&T` can be obtained without +//! moving or copying the inner value (unlike `Cell`) but also without runtime checks (unlike +//! `RefCell`). However, its value can also not be updated once set unless you have a mutable +//! reference to the `OnceCell`. +//! +//! `OnceCell` provides the following methods: +//! +//! - [`get`](OnceCell::get): obtain a reference to the inner value +//! - [`set`](OnceCell::set): set the inner value if it is unset (returns a `Result`) +//! - [`get_or_init`](OnceCell::get_or_init): return the inner value, initializing it if needed +//! - [`get_mut`](OnceCell::get_mut): provide a mutable reference to the inner value, only available +//! if you have a mutable reference to the cell itself. +//! +//! The corresponding [`Sync`] version of `OnceCell` is [`OnceLock`]. +//! +//! ## `LazyCell` +//! +//! A common pattern with OnceCell is, for a given OnceCell, to use the same function on every +//! call to [`OnceCell::get_or_init`] with that cell. This is what is offered by [`LazyCell`], +//! which pairs cells of `T` with functions of `F`, and always calls `F` before it yields `&T`. +//! This happens implicitly by simply attempting to dereference the LazyCell to get its contents, +//! so its use is much more transparent with a place which has been initialized by a constant. +//! +//! More complicated patterns that don't fit this description can be built on `OnceCell` instead. +//! +//! `LazyCell` works by providing an implementation of `impl Deref` that calls the function, +//! so you can just use it by dereference (e.g. `*lazy_cell` or `lazy_cell.deref()`). +//! +//! The corresponding [`Sync`] version of `LazyCell` is [`LazyLock`]. +//! +//! # When to choose interior mutability +//! +//! The more common inherited mutability, where one must have unique access to mutate a value, is +//! one of the key language elements that enables Rust to reason strongly about pointer aliasing, +//! statically preventing crash bugs. Because of that, inherited mutability is preferred, and +//! interior mutability is something of a last resort. Since cell types enable mutation where it +//! would otherwise be disallowed though, there are occasions when interior mutability might be +//! appropriate, or even *must* be used, e.g. +//! +//! * Introducing mutability 'inside' of something immutable +//! * Implementation details of logically-immutable methods. +//! * Mutating implementations of [`Clone`]. +//! +//! ## Introducing mutability 'inside' of something immutable +//! +//! Many shared smart pointer types, including [`Rc`] and [`Arc`], provide containers that can +//! be cloned and shared between multiple parties. Because the contained values may be +//! multiply-aliased, they can only be borrowed with `&`, not `&mut`. Without cells it would be +//! impossible to mutate data inside of these smart pointers at all. +//! +//! It's very common then to put a `RefCell` inside shared pointer types to reintroduce +//! mutability: +//! +//! ``` +//! use std::cell::{RefCell, RefMut}; +//! use std::collections::HashMap; +//! use std::rc::Rc; +//! +//! fn main() { +//! let shared_map: Rc> = Rc::new(RefCell::new(HashMap::new())); +//! // Create a new block to limit the scope of the dynamic borrow +//! { +//! let mut map: RefMut<'_, _> = shared_map.borrow_mut(); +//! map.insert("africa", 92388); +//! map.insert("kyoto", 11837); +//! map.insert("piccadilly", 11826); +//! map.insert("marbles", 38); +//! } +//! +//! // Note that if we had not let the previous borrow of the cache fall out +//! // of scope then the subsequent borrow would cause a dynamic thread panic. +//! // This is the major hazard of using `RefCell`. +//! let total: i32 = shared_map.borrow().values().sum(); +//! println!("{total}"); +//! } +//! ``` +//! +//! Note that this example uses `Rc` and not `Arc`. `RefCell`s are for single-threaded +//! scenarios. Consider using [`RwLock`] or [`Mutex`] if you need shared mutability in a +//! multi-threaded situation. +//! +//! ## Implementation details of logically-immutable methods +//! +//! Occasionally it may be desirable not to expose in an API that there is mutation happening +//! "under the hood". This may be because logically the operation is immutable, but e.g., caching +//! forces the implementation to perform mutation; or because you must employ mutation to implement +//! a trait method that was originally defined to take `&self`. +//! +//! ``` +//! # #![allow(dead_code)] +//! use std::cell::OnceCell; +//! +//! struct Graph { +//! edges: Vec<(i32, i32)>, +//! span_tree_cache: OnceCell> +//! } +//! +//! impl Graph { +//! fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> { +//! self.span_tree_cache +//! .get_or_init(|| self.calc_span_tree()) +//! .clone() +//! } +//! +//! fn calc_span_tree(&self) -> Vec<(i32, i32)> { +//! // Expensive computation goes here +//! vec![] +//! } +//! } +//! ``` +//! +//! ## Mutating implementations of `Clone` +//! +//! This is simply a special - but common - case of the previous: hiding mutability for operations +//! that appear to be immutable. The [`clone`](Clone::clone) method is expected to not change the +//! source value, and is declared to take `&self`, not `&mut self`. Therefore, any mutation that +//! happens in the `clone` method must use cell types. For example, [`Rc`] maintains its +//! reference counts within a `Cell`. +//! +//! ``` +//! use std::cell::Cell; +//! use std::ptr::NonNull; +//! use std::process::abort; +//! use std::marker::PhantomData; +//! +//! struct Rc { +//! ptr: NonNull>, +//! phantom: PhantomData>, +//! } +//! +//! struct RcInner { +//! strong: Cell, +//! refcount: Cell, +//! value: T, +//! } +//! +//! impl Clone for Rc { +//! fn clone(&self) -> Rc { +//! self.inc_strong(); +//! Rc { +//! ptr: self.ptr, +//! phantom: PhantomData, +//! } +//! } +//! } +//! +//! trait RcInnerPtr { +//! +//! fn inner(&self) -> &RcInner; +//! +//! fn strong(&self) -> usize { +//! self.inner().strong.get() +//! } +//! +//! fn inc_strong(&self) { +//! self.inner() +//! .strong +//! .set(self.strong() +//! .checked_add(1) +//! .unwrap_or_else(|| abort() )); +//! } +//! } +//! +//! impl RcInnerPtr for Rc { +//! fn inner(&self) -> &RcInner { +//! unsafe { +//! self.ptr.as_ref() +//! } +//! } +//! } +//! ``` +//! +//! [`Arc`]: ../../std/sync/struct.Arc.html +//! [`Rc`]: ../../std/rc/struct.Rc.html +//! [`RwLock`]: ../../std/sync/struct.RwLock.html +//! [`Mutex`]: ../../std/sync/struct.Mutex.html +//! [`OnceLock`]: ../../std/sync/struct.OnceLock.html +//! [`LazyLock`]: ../../std/sync/struct.LazyLock.html +//! [`Sync`]: ../../std/marker/trait.Sync.html +//! [`atomic`]: crate::sync::atomic + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::cmp::Ordering; +use crate::fmt::{self, Debug, Display}; +use crate::marker::{PhantomData, Unsize}; +use crate::mem; +use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; +use crate::pin::PinCoerceUnsized; +use crate::ptr::{self, NonNull}; + +mod lazy; +mod once; + +#[stable(feature = "lazy_cell", since = "1.80.0")] +pub use lazy::LazyCell; +#[stable(feature = "once_cell", since = "1.70.0")] +pub use once::OnceCell; + +/// A mutable memory location. +/// +/// # Memory layout +/// +/// `Cell` has the same [memory layout and caveats as +/// `UnsafeCell`](UnsafeCell#memory-layout). In particular, this means that +/// `Cell` has the same in-memory representation as its inner type `T`. +/// +/// # Examples +/// +/// In this example, you can see that `Cell` enables mutation inside an +/// immutable struct. In other words, it enables "interior mutability". +/// +/// ``` +/// use std::cell::Cell; +/// +/// struct SomeStruct { +/// regular_field: u8, +/// special_field: Cell, +/// } +/// +/// let my_struct = SomeStruct { +/// regular_field: 0, +/// special_field: Cell::new(1), +/// }; +/// +/// let new_value = 100; +/// +/// // ERROR: `my_struct` is immutable +/// // my_struct.regular_field = new_value; +/// +/// // WORKS: although `my_struct` is immutable, `special_field` is a `Cell`, +/// // which can always be mutated +/// my_struct.special_field.set(new_value); +/// assert_eq!(my_struct.special_field.get(), new_value); +/// ``` +/// +/// See the [module-level documentation](self) for more. +#[cfg_attr(not(test), rustc_diagnostic_item = "Cell")] +#[stable(feature = "rust1", since = "1.0.0")] +#[repr(transparent)] +#[rustc_pub_transparent] +pub struct Cell { + value: UnsafeCell, +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for Cell where T: Send {} + +// Note that this negative impl isn't strictly necessary for correctness, +// as `Cell` wraps `UnsafeCell`, which is itself `!Sync`. +// However, given how important `Cell`'s `!Sync`-ness is, +// having an explicit negative impl is nice for documentation purposes +// and results in nicer error messages. +#[stable(feature = "rust1", since = "1.0.0")] +impl !Sync for Cell {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Cell { + #[inline] + fn clone(&self) -> Cell { + Cell::new(self.get()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Cell { + /// Creates a `Cell`, with the `Default` value for T. + #[inline] + fn default() -> Cell { + Cell::new(Default::default()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for Cell { + #[inline] + fn eq(&self, other: &Cell) -> bool { + self.get() == other.get() + } +} + +#[stable(feature = "cell_eq", since = "1.2.0")] +impl Eq for Cell {} + +#[stable(feature = "cell_ord", since = "1.10.0")] +impl PartialOrd for Cell { + #[inline] + fn partial_cmp(&self, other: &Cell) -> Option { + self.get().partial_cmp(&other.get()) + } + + #[inline] + fn lt(&self, other: &Cell) -> bool { + self.get() < other.get() + } + + #[inline] + fn le(&self, other: &Cell) -> bool { + self.get() <= other.get() + } + + #[inline] + fn gt(&self, other: &Cell) -> bool { + self.get() > other.get() + } + + #[inline] + fn ge(&self, other: &Cell) -> bool { + self.get() >= other.get() + } +} + +#[stable(feature = "cell_ord", since = "1.10.0")] +impl Ord for Cell { + #[inline] + fn cmp(&self, other: &Cell) -> Ordering { + self.get().cmp(&other.get()) + } +} + +#[stable(feature = "cell_from", since = "1.12.0")] +impl From for Cell { + /// Creates a new `Cell` containing the given value. + fn from(t: T) -> Cell { + Cell::new(t) + } +} + +impl Cell { + /// Creates a new `Cell` containing the given value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_cell_new", since = "1.24.0")] + #[inline] + pub const fn new(value: T) -> Cell { + Cell { value: UnsafeCell::new(value) } + } + + /// Sets the contained value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// c.set(10); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn set(&self, val: T) { + self.replace(val); + } + + /// Swaps the values of two `Cell`s. + /// + /// The difference with `std::mem::swap` is that this function doesn't + /// require a `&mut` reference. + /// + /// # Panics + /// + /// This function will panic if `self` and `other` are different `Cell`s that partially overlap. + /// (Using just standard library methods, it is impossible to create such partially overlapping `Cell`s. + /// However, unsafe code is allowed to e.g. create two `&Cell<[i32; 2]>` that partially overlap.) + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c1 = Cell::new(5i32); + /// let c2 = Cell::new(10i32); + /// c1.swap(&c2); + /// assert_eq!(10, c1.get()); + /// assert_eq!(5, c2.get()); + /// ``` + #[inline] + #[stable(feature = "move_cell", since = "1.17.0")] + pub fn swap(&self, other: &Self) { + // This function documents that it *will* panic, and intrinsics::is_nonoverlapping doesn't + // do the check in const, so trying to use it here would be inviting unnecessary fragility. + fn is_nonoverlapping(src: *const T, dst: *const T) -> bool { + let src_usize = src.addr(); + let dst_usize = dst.addr(); + let diff = src_usize.abs_diff(dst_usize); + diff >= size_of::() + } + + if ptr::eq(self, other) { + // Swapping wouldn't change anything. + return; + } + if !is_nonoverlapping(self, other) { + // See for why we need to stop here. + panic!("`Cell::swap` on overlapping non-identical `Cell`s"); + } + // SAFETY: This can be risky if called from separate threads, but `Cell` + // is `!Sync` so this won't happen. This also won't invalidate any + // pointers since `Cell` makes sure nothing else will be pointing into + // either of these `Cell`s. We also excluded shenanigans like partially overlapping `Cell`s, + // so `swap` will just properly copy two full values of type `T` back and forth. + unsafe { + mem::swap(&mut *self.value.get(), &mut *other.value.get()); + } + } + + /// Replaces the contained value with `val`, and returns the old contained value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let cell = Cell::new(5); + /// assert_eq!(cell.get(), 5); + /// assert_eq!(cell.replace(10), 5); + /// assert_eq!(cell.get(), 10); + /// ``` + #[inline] + #[stable(feature = "move_cell", since = "1.17.0")] + #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_confusables("swap")] + pub const fn replace(&self, val: T) -> T { + // SAFETY: This can cause data races if called from a separate thread, + // but `Cell` is `!Sync` so this won't happen. + mem::replace(unsafe { &mut *self.value.get() }, val) + } + + /// Unwraps the value, consuming the cell. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// let five = c.into_inner(); + /// + /// assert_eq!(five, 5); + /// ``` + #[stable(feature = "move_cell", since = "1.17.0")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + pub const fn into_inner(self) -> T { + self.value.into_inner() + } +} + +impl Cell { + /// Returns a copy of the contained value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// let five = c.get(); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + pub const fn get(&self) -> T { + // SAFETY: This can cause data races if called from a separate thread, + // but `Cell` is `!Sync` so this won't happen. + unsafe { *self.value.get() } + } + + /// Updates the contained value using a function and returns the new value. + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_update)] + /// + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// let new = c.update(|x| x + 1); + /// + /// assert_eq!(new, 6); + /// assert_eq!(c.get(), 6); + /// ``` + #[inline] + #[unstable(feature = "cell_update", issue = "50186")] + pub fn update(&self, f: F) -> T + where + F: FnOnce(T) -> T, + { + let old = self.get(); + let new = f(old); + self.set(new); + new + } +} + +impl Cell { + /// Returns a raw pointer to the underlying data in this cell. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// let ptr = c.as_ptr(); + /// ``` + #[inline] + #[stable(feature = "cell_as_ptr", since = "1.12.0")] + #[rustc_const_stable(feature = "const_cell_as_ptr", since = "1.32.0")] + #[rustc_as_ptr] + #[rustc_never_returns_null_ptr] + pub const fn as_ptr(&self) -> *mut T { + self.value.get() + } + + /// Returns a mutable reference to the underlying data. + /// + /// This call borrows `Cell` mutably (at compile-time) which guarantees + /// that we possess the only reference. + /// + /// However be cautious: this method expects `self` to be mutable, which is + /// generally not the case when using a `Cell`. If you require interior + /// mutability by reference, consider using `RefCell` which provides + /// run-time checked mutable borrows through its [`borrow_mut`] method. + /// + /// [`borrow_mut`]: RefCell::borrow_mut() + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let mut c = Cell::new(5); + /// *c.get_mut() += 1; + /// + /// assert_eq!(c.get(), 6); + /// ``` + #[inline] + #[stable(feature = "cell_get_mut", since = "1.11.0")] + #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + pub const fn get_mut(&mut self) -> &mut T { + self.value.get_mut() + } + + /// Returns a `&Cell` from a `&mut T` + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let slice: &mut [i32] = &mut [1, 2, 3]; + /// let cell_slice: &Cell<[i32]> = Cell::from_mut(slice); + /// let slice_cell: &[Cell] = cell_slice.as_slice_of_cells(); + /// + /// assert_eq!(slice_cell.len(), 3); + /// ``` + #[inline] + #[stable(feature = "as_cell", since = "1.37.0")] + #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + pub const fn from_mut(t: &mut T) -> &Cell { + // SAFETY: `&mut` ensures unique access. + unsafe { &*(t as *mut T as *const Cell) } + } +} + +impl Cell { + /// Takes the value of the cell, leaving `Default::default()` in its place. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// let five = c.take(); + /// + /// assert_eq!(five, 5); + /// assert_eq!(c.into_inner(), 0); + /// ``` + #[stable(feature = "move_cell", since = "1.17.0")] + pub fn take(&self) -> T { + self.replace(Default::default()) + } +} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U> CoerceUnsized> for Cell {} + +// Allow types that wrap `Cell` to also implement `DispatchFromDyn` +// and become dyn-compatible method receivers. +// Note that currently `Cell` itself cannot be a method receiver +// because it does not implement Deref. +// In other words: +// `self: Cell<&Self>` won't work +// `self: CellWrapper` becomes possible +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U> DispatchFromDyn> for Cell {} + +impl Cell<[T]> { + /// Returns a `&[Cell]` from a `&Cell<[T]>` + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let slice: &mut [i32] = &mut [1, 2, 3]; + /// let cell_slice: &Cell<[i32]> = Cell::from_mut(slice); + /// let slice_cell: &[Cell] = cell_slice.as_slice_of_cells(); + /// + /// assert_eq!(slice_cell.len(), 3); + /// ``` + #[stable(feature = "as_cell", since = "1.37.0")] + #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + pub const fn as_slice_of_cells(&self) -> &[Cell] { + // SAFETY: `Cell` has the same memory layout as `T`. + unsafe { &*(self as *const Cell<[T]> as *const [Cell]) } + } +} + +impl Cell<[T; N]> { + /// Returns a `&[Cell; N]` from a `&Cell<[T; N]>` + /// + /// # Examples + /// + /// ``` + /// #![feature(as_array_of_cells)] + /// use std::cell::Cell; + /// + /// let mut array: [i32; 3] = [1, 2, 3]; + /// let cell_array: &Cell<[i32; 3]> = Cell::from_mut(&mut array); + /// let array_cell: &[Cell; 3] = cell_array.as_array_of_cells(); + /// ``` + #[unstable(feature = "as_array_of_cells", issue = "88248")] + pub const fn as_array_of_cells(&self) -> &[Cell; N] { + // SAFETY: `Cell` has the same memory layout as `T`. + unsafe { &*(self as *const Cell<[T; N]> as *const [Cell; N]) } + } +} + +/// A mutable memory location with dynamically checked borrow rules +/// +/// See the [module-level documentation](self) for more. +#[cfg_attr(not(test), rustc_diagnostic_item = "RefCell")] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RefCell { + borrow: Cell, + // Stores the location of the earliest currently active borrow. + // This gets updated whenever we go from having zero borrows + // to having a single borrow. When a borrow occurs, this gets included + // in the generated `BorrowError`/`BorrowMutError` + #[cfg(feature = "debug_refcell")] + borrowed_at: Cell>>, + value: UnsafeCell, +} + +/// An error returned by [`RefCell::try_borrow`]. +#[stable(feature = "try_borrow", since = "1.13.0")] +#[non_exhaustive] +pub struct BorrowError { + #[cfg(feature = "debug_refcell")] + location: &'static crate::panic::Location<'static>, +} + +#[stable(feature = "try_borrow", since = "1.13.0")] +impl Debug for BorrowError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut builder = f.debug_struct("BorrowError"); + + #[cfg(feature = "debug_refcell")] + builder.field("location", self.location); + + builder.finish() + } +} + +#[stable(feature = "try_borrow", since = "1.13.0")] +impl Display for BorrowError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt("already mutably borrowed", f) + } +} + +/// An error returned by [`RefCell::try_borrow_mut`]. +#[stable(feature = "try_borrow", since = "1.13.0")] +#[non_exhaustive] +pub struct BorrowMutError { + #[cfg(feature = "debug_refcell")] + location: &'static crate::panic::Location<'static>, +} + +#[stable(feature = "try_borrow", since = "1.13.0")] +impl Debug for BorrowMutError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut builder = f.debug_struct("BorrowMutError"); + + #[cfg(feature = "debug_refcell")] + builder.field("location", self.location); + + builder.finish() + } +} + +#[stable(feature = "try_borrow", since = "1.13.0")] +impl Display for BorrowMutError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt("already borrowed", f) + } +} + +// This ensures the panicking code is outlined from `borrow_mut` for `RefCell`. +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[track_caller] +#[cold] +fn panic_already_borrowed(err: BorrowMutError) -> ! { + panic!("already borrowed: {:?}", err) +} + +// This ensures the panicking code is outlined from `borrow` for `RefCell`. +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[track_caller] +#[cold] +fn panic_already_mutably_borrowed(err: BorrowError) -> ! { + panic!("already mutably borrowed: {:?}", err) +} + +// Positive values represent the number of `Ref` active. Negative values +// represent the number of `RefMut` active. Multiple `RefMut`s can only be +// active at a time if they refer to distinct, nonoverlapping components of a +// `RefCell` (e.g., different ranges of a slice). +// +// `Ref` and `RefMut` are both two words in size, and so there will likely never +// be enough `Ref`s or `RefMut`s in existence to overflow half of the `usize` +// range. Thus, a `BorrowFlag` will probably never overflow or underflow. +// However, this is not a guarantee, as a pathological program could repeatedly +// create and then mem::forget `Ref`s or `RefMut`s. Thus, all code must +// explicitly check for overflow and underflow in order to avoid unsafety, or at +// least behave correctly in the event that overflow or underflow happens (e.g., +// see BorrowRef::new). +type BorrowFlag = isize; +const UNUSED: BorrowFlag = 0; + +#[inline(always)] +fn is_writing(x: BorrowFlag) -> bool { + x < UNUSED +} + +#[inline(always)] +fn is_reading(x: BorrowFlag) -> bool { + x > UNUSED +} + +impl RefCell { + /// Creates a new `RefCell` containing `value`. + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_refcell_new", since = "1.24.0")] + #[inline] + pub const fn new(value: T) -> RefCell { + RefCell { + value: UnsafeCell::new(value), + borrow: Cell::new(UNUSED), + #[cfg(feature = "debug_refcell")] + borrowed_at: Cell::new(None), + } + } + + /// Consumes the `RefCell`, returning the wrapped value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// + /// let five = c.into_inner(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[inline] + pub const fn into_inner(self) -> T { + // Since this function takes `self` (the `RefCell`) by value, the + // compiler statically verifies that it is not currently borrowed. + self.value.into_inner() + } + + /// Replaces the wrapped value with a new one, returning the old value, + /// without deinitializing either one. + /// + /// This function corresponds to [`std::mem::replace`](../mem/fn.replace.html). + /// + /// # Panics + /// + /// Panics if the value is currently borrowed. + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// let cell = RefCell::new(5); + /// let old_value = cell.replace(6); + /// assert_eq!(old_value, 5); + /// assert_eq!(cell, RefCell::new(6)); + /// ``` + #[inline] + #[stable(feature = "refcell_replace", since = "1.24.0")] + #[track_caller] + #[rustc_confusables("swap")] + pub fn replace(&self, t: T) -> T { + mem::replace(&mut *self.borrow_mut(), t) + } + + /// Replaces the wrapped value with a new one computed from `f`, returning + /// the old value, without deinitializing either one. + /// + /// # Panics + /// + /// Panics if the value is currently borrowed. + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// let cell = RefCell::new(5); + /// let old_value = cell.replace_with(|&mut old| old + 1); + /// assert_eq!(old_value, 5); + /// assert_eq!(cell, RefCell::new(6)); + /// ``` + #[inline] + #[stable(feature = "refcell_replace_swap", since = "1.35.0")] + #[track_caller] + pub fn replace_with T>(&self, f: F) -> T { + let mut_borrow = &mut *self.borrow_mut(); + let replacement = f(mut_borrow); + mem::replace(mut_borrow, replacement) + } + + /// Swaps the wrapped value of `self` with the wrapped value of `other`, + /// without deinitializing either one. + /// + /// This function corresponds to [`std::mem::swap`](../mem/fn.swap.html). + /// + /// # Panics + /// + /// Panics if the value in either `RefCell` is currently borrowed, or + /// if `self` and `other` point to the same `RefCell`. + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// let c = RefCell::new(5); + /// let d = RefCell::new(6); + /// c.swap(&d); + /// assert_eq!(c, RefCell::new(6)); + /// assert_eq!(d, RefCell::new(5)); + /// ``` + #[inline] + #[stable(feature = "refcell_swap", since = "1.24.0")] + pub fn swap(&self, other: &Self) { + mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut()) + } +} + +impl RefCell { + /// Immutably borrows the wrapped value. + /// + /// The borrow lasts until the returned `Ref` exits scope. Multiple + /// immutable borrows can be taken out at the same time. + /// + /// # Panics + /// + /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use + /// [`try_borrow`](#method.try_borrow). + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// + /// let borrowed_five = c.borrow(); + /// let borrowed_five2 = c.borrow(); + /// ``` + /// + /// An example of panic: + /// + /// ```should_panic + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// + /// let m = c.borrow_mut(); + /// let b = c.borrow(); // this causes a panic + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[track_caller] + pub fn borrow(&self) -> Ref<'_, T> { + match self.try_borrow() { + Ok(b) => b, + Err(err) => panic_already_mutably_borrowed(err), + } + } + + /// Immutably borrows the wrapped value, returning an error if the value is currently mutably + /// borrowed. + /// + /// The borrow lasts until the returned `Ref` exits scope. Multiple immutable borrows can be + /// taken out at the same time. + /// + /// This is the non-panicking variant of [`borrow`](#method.borrow). + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// + /// { + /// let m = c.borrow_mut(); + /// assert!(c.try_borrow().is_err()); + /// } + /// + /// { + /// let m = c.borrow(); + /// assert!(c.try_borrow().is_ok()); + /// } + /// ``` + #[stable(feature = "try_borrow", since = "1.13.0")] + #[inline] + #[cfg_attr(feature = "debug_refcell", track_caller)] + pub fn try_borrow(&self) -> Result, BorrowError> { + match BorrowRef::new(&self.borrow) { + Some(b) => { + #[cfg(feature = "debug_refcell")] + { + // `borrowed_at` is always the *first* active borrow + if b.borrow.get() == 1 { + self.borrowed_at.set(Some(crate::panic::Location::caller())); + } + } + + // SAFETY: `BorrowRef` ensures that there is only immutable access + // to the value while borrowed. + let value = unsafe { NonNull::new_unchecked(self.value.get()) }; + Ok(Ref { value, borrow: b }) + } + None => Err(BorrowError { + // If a borrow occurred, then we must already have an outstanding borrow, + // so `borrowed_at` will be `Some` + #[cfg(feature = "debug_refcell")] + location: self.borrowed_at.get().unwrap(), + }), + } + } + + /// Mutably borrows the wrapped value. + /// + /// The borrow lasts until the returned `RefMut` or all `RefMut`s derived + /// from it exit scope. The value cannot be borrowed while this borrow is + /// active. + /// + /// # Panics + /// + /// Panics if the value is currently borrowed. For a non-panicking variant, use + /// [`try_borrow_mut`](#method.try_borrow_mut). + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new("hello".to_owned()); + /// + /// *c.borrow_mut() = "bonjour".to_owned(); + /// + /// assert_eq!(&*c.borrow(), "bonjour"); + /// ``` + /// + /// An example of panic: + /// + /// ```should_panic + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// let m = c.borrow(); + /// + /// let b = c.borrow_mut(); // this causes a panic + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[track_caller] + pub fn borrow_mut(&self) -> RefMut<'_, T> { + match self.try_borrow_mut() { + Ok(b) => b, + Err(err) => panic_already_borrowed(err), + } + } + + /// Mutably borrows the wrapped value, returning an error if the value is currently borrowed. + /// + /// The borrow lasts until the returned `RefMut` or all `RefMut`s derived + /// from it exit scope. The value cannot be borrowed while this borrow is + /// active. + /// + /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut). + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// + /// { + /// let m = c.borrow(); + /// assert!(c.try_borrow_mut().is_err()); + /// } + /// + /// assert!(c.try_borrow_mut().is_ok()); + /// ``` + #[stable(feature = "try_borrow", since = "1.13.0")] + #[inline] + #[cfg_attr(feature = "debug_refcell", track_caller)] + pub fn try_borrow_mut(&self) -> Result, BorrowMutError> { + match BorrowRefMut::new(&self.borrow) { + Some(b) => { + #[cfg(feature = "debug_refcell")] + { + self.borrowed_at.set(Some(crate::panic::Location::caller())); + } + + // SAFETY: `BorrowRefMut` guarantees unique access. + let value = unsafe { NonNull::new_unchecked(self.value.get()) }; + Ok(RefMut { value, borrow: b, marker: PhantomData }) + } + None => Err(BorrowMutError { + // If a borrow occurred, then we must already have an outstanding borrow, + // so `borrowed_at` will be `Some` + #[cfg(feature = "debug_refcell")] + location: self.borrowed_at.get().unwrap(), + }), + } + } + + /// Returns a raw pointer to the underlying data in this cell. + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// + /// let ptr = c.as_ptr(); + /// ``` + #[inline] + #[stable(feature = "cell_as_ptr", since = "1.12.0")] + #[rustc_as_ptr] + #[rustc_never_returns_null_ptr] + pub fn as_ptr(&self) -> *mut T { + self.value.get() + } + + /// Returns a mutable reference to the underlying data. + /// + /// Since this method borrows `RefCell` mutably, it is statically guaranteed + /// that no borrows to the underlying data exist. The dynamic checks inherent + /// in [`borrow_mut`] and most other methods of `RefCell` are therefore + /// unnecessary. + /// + /// This method can only be called if `RefCell` can be mutably borrowed, + /// which in general is only the case directly after the `RefCell` has + /// been created. In these situations, skipping the aforementioned dynamic + /// borrowing checks may yield better ergonomics and runtime-performance. + /// + /// In most situations where `RefCell` is used, it can't be borrowed mutably. + /// Use [`borrow_mut`] to get mutable access to the underlying data then. + /// + /// [`borrow_mut`]: RefCell::borrow_mut() + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let mut c = RefCell::new(5); + /// *c.get_mut() += 1; + /// + /// assert_eq!(c, RefCell::new(6)); + /// ``` + #[inline] + #[stable(feature = "cell_get_mut", since = "1.11.0")] + pub fn get_mut(&mut self) -> &mut T { + self.value.get_mut() + } + + /// Undo the effect of leaked guards on the borrow state of the `RefCell`. + /// + /// This call is similar to [`get_mut`] but more specialized. It borrows `RefCell` mutably to + /// ensure no borrows exist and then resets the state tracking shared borrows. This is relevant + /// if some `Ref` or `RefMut` borrows have been leaked. + /// + /// [`get_mut`]: RefCell::get_mut() + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_leak)] + /// use std::cell::RefCell; + /// + /// let mut c = RefCell::new(0); + /// std::mem::forget(c.borrow_mut()); + /// + /// assert!(c.try_borrow().is_err()); + /// c.undo_leak(); + /// assert!(c.try_borrow().is_ok()); + /// ``` + #[unstable(feature = "cell_leak", issue = "69099")] + pub fn undo_leak(&mut self) -> &mut T { + *self.borrow.get_mut() = UNUSED; + self.get_mut() + } + + /// Immutably borrows the wrapped value, returning an error if the value is + /// currently mutably borrowed. + /// + /// # Safety + /// + /// Unlike `RefCell::borrow`, this method is unsafe because it does not + /// return a `Ref`, thus leaving the borrow flag untouched. Mutably + /// borrowing the `RefCell` while the reference returned by this method + /// is alive is undefined behavior. + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// + /// { + /// let m = c.borrow_mut(); + /// assert!(unsafe { c.try_borrow_unguarded() }.is_err()); + /// } + /// + /// { + /// let m = c.borrow(); + /// assert!(unsafe { c.try_borrow_unguarded() }.is_ok()); + /// } + /// ``` + #[stable(feature = "borrow_state", since = "1.37.0")] + #[inline] + pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> { + if !is_writing(self.borrow.get()) { + // SAFETY: We check that nobody is actively writing now, but it is + // the caller's responsibility to ensure that nobody writes until + // the returned reference is no longer in use. + // Also, `self.value.get()` refers to the value owned by `self` + // and is thus guaranteed to be valid for the lifetime of `self`. + Ok(unsafe { &*self.value.get() }) + } else { + Err(BorrowError { + // If a borrow occurred, then we must already have an outstanding borrow, + // so `borrowed_at` will be `Some` + #[cfg(feature = "debug_refcell")] + location: self.borrowed_at.get().unwrap(), + }) + } + } +} + +impl RefCell { + /// Takes the wrapped value, leaving `Default::default()` in its place. + /// + /// # Panics + /// + /// Panics if the value is currently borrowed. + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// let five = c.take(); + /// + /// assert_eq!(five, 5); + /// assert_eq!(c.into_inner(), 0); + /// ``` + #[stable(feature = "refcell_take", since = "1.50.0")] + pub fn take(&self) -> T { + self.replace(Default::default()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for RefCell where T: Send {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl !Sync for RefCell {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for RefCell { + /// # Panics + /// + /// Panics if the value is currently mutably borrowed. + #[inline] + #[track_caller] + fn clone(&self) -> RefCell { + RefCell::new(self.borrow().clone()) + } + + /// # Panics + /// + /// Panics if `source` is currently mutably borrowed. + #[inline] + #[track_caller] + fn clone_from(&mut self, source: &Self) { + self.get_mut().clone_from(&source.borrow()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for RefCell { + /// Creates a `RefCell`, with the `Default` value for T. + #[inline] + fn default() -> RefCell { + RefCell::new(Default::default()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for RefCell { + /// # Panics + /// + /// Panics if the value in either `RefCell` is currently mutably borrowed. + #[inline] + fn eq(&self, other: &RefCell) -> bool { + *self.borrow() == *other.borrow() + } +} + +#[stable(feature = "cell_eq", since = "1.2.0")] +impl Eq for RefCell {} + +#[stable(feature = "cell_ord", since = "1.10.0")] +impl PartialOrd for RefCell { + /// # Panics + /// + /// Panics if the value in either `RefCell` is currently mutably borrowed. + #[inline] + fn partial_cmp(&self, other: &RefCell) -> Option { + self.borrow().partial_cmp(&*other.borrow()) + } + + /// # Panics + /// + /// Panics if the value in either `RefCell` is currently mutably borrowed. + #[inline] + fn lt(&self, other: &RefCell) -> bool { + *self.borrow() < *other.borrow() + } + + /// # Panics + /// + /// Panics if the value in either `RefCell` is currently mutably borrowed. + #[inline] + fn le(&self, other: &RefCell) -> bool { + *self.borrow() <= *other.borrow() + } + + /// # Panics + /// + /// Panics if the value in either `RefCell` is currently mutably borrowed. + #[inline] + fn gt(&self, other: &RefCell) -> bool { + *self.borrow() > *other.borrow() + } + + /// # Panics + /// + /// Panics if the value in either `RefCell` is currently mutably borrowed. + #[inline] + fn ge(&self, other: &RefCell) -> bool { + *self.borrow() >= *other.borrow() + } +} + +#[stable(feature = "cell_ord", since = "1.10.0")] +impl Ord for RefCell { + /// # Panics + /// + /// Panics if the value in either `RefCell` is currently mutably borrowed. + #[inline] + fn cmp(&self, other: &RefCell) -> Ordering { + self.borrow().cmp(&*other.borrow()) + } +} + +#[stable(feature = "cell_from", since = "1.12.0")] +impl From for RefCell { + /// Creates a new `RefCell` containing the given value. + fn from(t: T) -> RefCell { + RefCell::new(t) + } +} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U> CoerceUnsized> for RefCell {} + +struct BorrowRef<'b> { + borrow: &'b Cell, +} + +impl<'b> BorrowRef<'b> { + #[inline] + fn new(borrow: &'b Cell) -> Option> { + let b = borrow.get().wrapping_add(1); + if !is_reading(b) { + // Incrementing borrow can result in a non-reading value (<= 0) in these cases: + // 1. It was < 0, i.e. there are writing borrows, so we can't allow a read borrow + // due to Rust's reference aliasing rules + // 2. It was isize::MAX (the max amount of reading borrows) and it overflowed + // into isize::MIN (the max amount of writing borrows) so we can't allow + // an additional read borrow because isize can't represent so many read borrows + // (this can only happen if you mem::forget more than a small constant amount of + // `Ref`s, which is not good practice) + None + } else { + // Incrementing borrow can result in a reading value (> 0) in these cases: + // 1. It was = 0, i.e. it wasn't borrowed, and we are taking the first read borrow + // 2. It was > 0 and < isize::MAX, i.e. there were read borrows, and isize + // is large enough to represent having one more read borrow + borrow.set(b); + Some(BorrowRef { borrow }) + } + } +} + +impl Drop for BorrowRef<'_> { + #[inline] + fn drop(&mut self) { + let borrow = self.borrow.get(); + debug_assert!(is_reading(borrow)); + self.borrow.set(borrow - 1); + } +} + +impl Clone for BorrowRef<'_> { + #[inline] + fn clone(&self) -> Self { + // Since this Ref exists, we know the borrow flag + // is a reading borrow. + let borrow = self.borrow.get(); + debug_assert!(is_reading(borrow)); + // Prevent the borrow counter from overflowing into + // a writing borrow. + assert!(borrow != BorrowFlag::MAX); + self.borrow.set(borrow + 1); + BorrowRef { borrow: self.borrow } + } +} + +/// Wraps a borrowed reference to a value in a `RefCell` box. +/// A wrapper type for an immutably borrowed value from a `RefCell`. +/// +/// See the [module-level documentation](self) for more. +#[stable(feature = "rust1", since = "1.0.0")] +#[must_not_suspend = "holding a Ref across suspend points can cause BorrowErrors"] +#[rustc_diagnostic_item = "RefCellRef"] +pub struct Ref<'b, T: ?Sized + 'b> { + // NB: we use a pointer instead of `&'b T` to avoid `noalias` violations, because a + // `Ref` argument doesn't hold immutability for its whole scope, only until it drops. + // `NonNull` is also covariant over `T`, just like we would have with `&T`. + value: NonNull, + borrow: BorrowRef<'b>, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for Ref<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + // SAFETY: the value is accessible as long as we hold our borrow. + unsafe { self.value.as_ref() } + } +} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for Ref<'_, T> {} + +impl<'b, T: ?Sized> Ref<'b, T> { + /// Copies a `Ref`. + /// + /// The `RefCell` is already immutably borrowed, so this cannot fail. + /// + /// This is an associated function that needs to be used as + /// `Ref::clone(...)`. A `Clone` implementation or a method would interfere + /// with the widespread use of `r.borrow().clone()` to clone the contents of + /// a `RefCell`. + #[stable(feature = "cell_extras", since = "1.15.0")] + #[must_use] + #[inline] + pub fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> { + Ref { value: orig.value, borrow: orig.borrow.clone() } + } + + /// Makes a new `Ref` for a component of the borrowed data. + /// + /// The `RefCell` is already immutably borrowed, so this cannot fail. + /// + /// This is an associated function that needs to be used as `Ref::map(...)`. + /// A method would interfere with methods of the same name on the contents + /// of a `RefCell` used through `Deref`. + /// + /// # Examples + /// + /// ``` + /// use std::cell::{RefCell, Ref}; + /// + /// let c = RefCell::new((5, 'b')); + /// let b1: Ref<'_, (u32, char)> = c.borrow(); + /// let b2: Ref<'_, u32> = Ref::map(b1, |t| &t.0); + /// assert_eq!(*b2, 5) + /// ``` + #[stable(feature = "cell_map", since = "1.8.0")] + #[inline] + pub fn map(orig: Ref<'b, T>, f: F) -> Ref<'b, U> + where + F: FnOnce(&T) -> &U, + { + Ref { value: NonNull::from(f(&*orig)), borrow: orig.borrow } + } + + /// Makes a new `Ref` for an optional component of the borrowed data. The + /// original guard is returned as an `Err(..)` if the closure returns + /// `None`. + /// + /// The `RefCell` is already immutably borrowed, so this cannot fail. + /// + /// This is an associated function that needs to be used as + /// `Ref::filter_map(...)`. A method would interfere with methods of the same + /// name on the contents of a `RefCell` used through `Deref`. + /// + /// # Examples + /// + /// ``` + /// use std::cell::{RefCell, Ref}; + /// + /// let c = RefCell::new(vec![1, 2, 3]); + /// let b1: Ref<'_, Vec> = c.borrow(); + /// let b2: Result, _> = Ref::filter_map(b1, |v| v.get(1)); + /// assert_eq!(*b2.unwrap(), 2); + /// ``` + #[stable(feature = "cell_filter_map", since = "1.63.0")] + #[inline] + pub fn filter_map(orig: Ref<'b, T>, f: F) -> Result, Self> + where + F: FnOnce(&T) -> Option<&U>, + { + match f(&*orig) { + Some(value) => Ok(Ref { value: NonNull::from(value), borrow: orig.borrow }), + None => Err(orig), + } + } + + /// Splits a `Ref` into multiple `Ref`s for different components of the + /// borrowed data. + /// + /// The `RefCell` is already immutably borrowed, so this cannot fail. + /// + /// This is an associated function that needs to be used as + /// `Ref::map_split(...)`. A method would interfere with methods of the same + /// name on the contents of a `RefCell` used through `Deref`. + /// + /// # Examples + /// + /// ``` + /// use std::cell::{Ref, RefCell}; + /// + /// let cell = RefCell::new([1, 2, 3, 4]); + /// let borrow = cell.borrow(); + /// let (begin, end) = Ref::map_split(borrow, |slice| slice.split_at(2)); + /// assert_eq!(*begin, [1, 2]); + /// assert_eq!(*end, [3, 4]); + /// ``` + #[stable(feature = "refcell_map_split", since = "1.35.0")] + #[inline] + pub fn map_split(orig: Ref<'b, T>, f: F) -> (Ref<'b, U>, Ref<'b, V>) + where + F: FnOnce(&T) -> (&U, &V), + { + let (a, b) = f(&*orig); + let borrow = orig.borrow.clone(); + (Ref { value: NonNull::from(a), borrow }, Ref { + value: NonNull::from(b), + borrow: orig.borrow, + }) + } + + /// Converts into a reference to the underlying data. + /// + /// The underlying `RefCell` can never be mutably borrowed from again and will always appear + /// already immutably borrowed. It is not a good idea to leak more than a constant number of + /// references. The `RefCell` can be immutably borrowed again if only a smaller number of leaks + /// have occurred in total. + /// + /// This is an associated function that needs to be used as + /// `Ref::leak(...)`. A method would interfere with methods of the + /// same name on the contents of a `RefCell` used through `Deref`. + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_leak)] + /// use std::cell::{RefCell, Ref}; + /// let cell = RefCell::new(0); + /// + /// let value = Ref::leak(cell.borrow()); + /// assert_eq!(*value, 0); + /// + /// assert!(cell.try_borrow().is_ok()); + /// assert!(cell.try_borrow_mut().is_err()); + /// ``` + #[unstable(feature = "cell_leak", issue = "69099")] + pub fn leak(orig: Ref<'b, T>) -> &'b T { + // By forgetting this Ref we ensure that the borrow counter in the RefCell can't go back to + // UNUSED within the lifetime `'b`. Resetting the reference tracking state would require a + // unique reference to the borrowed RefCell. No further mutable references can be created + // from the original cell. + mem::forget(orig.borrow); + // SAFETY: after forgetting, we can form a reference for the rest of lifetime `'b`. + unsafe { orig.value.as_ref() } + } +} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl<'b, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for Ref<'b, T> {} + +#[stable(feature = "std_guard_impls", since = "1.20.0")] +impl fmt::Display for Ref<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +impl<'b, T: ?Sized> RefMut<'b, T> { + /// Makes a new `RefMut` for a component of the borrowed data, e.g., an enum + /// variant. + /// + /// The `RefCell` is already mutably borrowed, so this cannot fail. + /// + /// This is an associated function that needs to be used as + /// `RefMut::map(...)`. A method would interfere with methods of the same + /// name on the contents of a `RefCell` used through `Deref`. + /// + /// # Examples + /// + /// ``` + /// use std::cell::{RefCell, RefMut}; + /// + /// let c = RefCell::new((5, 'b')); + /// { + /// let b1: RefMut<'_, (u32, char)> = c.borrow_mut(); + /// let mut b2: RefMut<'_, u32> = RefMut::map(b1, |t| &mut t.0); + /// assert_eq!(*b2, 5); + /// *b2 = 42; + /// } + /// assert_eq!(*c.borrow(), (42, 'b')); + /// ``` + #[stable(feature = "cell_map", since = "1.8.0")] + #[inline] + pub fn map(mut orig: RefMut<'b, T>, f: F) -> RefMut<'b, U> + where + F: FnOnce(&mut T) -> &mut U, + { + let value = NonNull::from(f(&mut *orig)); + RefMut { value, borrow: orig.borrow, marker: PhantomData } + } + + /// Makes a new `RefMut` for an optional component of the borrowed data. The + /// original guard is returned as an `Err(..)` if the closure returns + /// `None`. + /// + /// The `RefCell` is already mutably borrowed, so this cannot fail. + /// + /// This is an associated function that needs to be used as + /// `RefMut::filter_map(...)`. A method would interfere with methods of the + /// same name on the contents of a `RefCell` used through `Deref`. + /// + /// # Examples + /// + /// ``` + /// use std::cell::{RefCell, RefMut}; + /// + /// let c = RefCell::new(vec![1, 2, 3]); + /// + /// { + /// let b1: RefMut<'_, Vec> = c.borrow_mut(); + /// let mut b2: Result, _> = RefMut::filter_map(b1, |v| v.get_mut(1)); + /// + /// if let Ok(mut b2) = b2 { + /// *b2 += 2; + /// } + /// } + /// + /// assert_eq!(*c.borrow(), vec![1, 4, 3]); + /// ``` + #[stable(feature = "cell_filter_map", since = "1.63.0")] + #[inline] + pub fn filter_map(mut orig: RefMut<'b, T>, f: F) -> Result, Self> + where + F: FnOnce(&mut T) -> Option<&mut U>, + { + // SAFETY: function holds onto an exclusive reference for the duration + // of its call through `orig`, and the pointer is only de-referenced + // inside of the function call never allowing the exclusive reference to + // escape. + match f(&mut *orig) { + Some(value) => { + Ok(RefMut { value: NonNull::from(value), borrow: orig.borrow, marker: PhantomData }) + } + None => Err(orig), + } + } + + /// Splits a `RefMut` into multiple `RefMut`s for different components of the + /// borrowed data. + /// + /// The underlying `RefCell` will remain mutably borrowed until both + /// returned `RefMut`s go out of scope. + /// + /// The `RefCell` is already mutably borrowed, so this cannot fail. + /// + /// This is an associated function that needs to be used as + /// `RefMut::map_split(...)`. A method would interfere with methods of the + /// same name on the contents of a `RefCell` used through `Deref`. + /// + /// # Examples + /// + /// ``` + /// use std::cell::{RefCell, RefMut}; + /// + /// let cell = RefCell::new([1, 2, 3, 4]); + /// let borrow = cell.borrow_mut(); + /// let (mut begin, mut end) = RefMut::map_split(borrow, |slice| slice.split_at_mut(2)); + /// assert_eq!(*begin, [1, 2]); + /// assert_eq!(*end, [3, 4]); + /// begin.copy_from_slice(&[4, 3]); + /// end.copy_from_slice(&[2, 1]); + /// ``` + #[stable(feature = "refcell_map_split", since = "1.35.0")] + #[inline] + pub fn map_split( + mut orig: RefMut<'b, T>, + f: F, + ) -> (RefMut<'b, U>, RefMut<'b, V>) + where + F: FnOnce(&mut T) -> (&mut U, &mut V), + { + let borrow = orig.borrow.clone(); + let (a, b) = f(&mut *orig); + (RefMut { value: NonNull::from(a), borrow, marker: PhantomData }, RefMut { + value: NonNull::from(b), + borrow: orig.borrow, + marker: PhantomData, + }) + } + + /// Converts into a mutable reference to the underlying data. + /// + /// The underlying `RefCell` can not be borrowed from again and will always appear already + /// mutably borrowed, making the returned reference the only to the interior. + /// + /// This is an associated function that needs to be used as + /// `RefMut::leak(...)`. A method would interfere with methods of the + /// same name on the contents of a `RefCell` used through `Deref`. + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_leak)] + /// use std::cell::{RefCell, RefMut}; + /// let cell = RefCell::new(0); + /// + /// let value = RefMut::leak(cell.borrow_mut()); + /// assert_eq!(*value, 0); + /// *value = 1; + /// + /// assert!(cell.try_borrow_mut().is_err()); + /// ``` + #[unstable(feature = "cell_leak", issue = "69099")] + pub fn leak(mut orig: RefMut<'b, T>) -> &'b mut T { + // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell can't + // go back to UNUSED within the lifetime `'b`. Resetting the reference tracking state would + // require a unique reference to the borrowed RefCell. No further references can be created + // from the original cell within that lifetime, making the current borrow the only + // reference for the remaining lifetime. + mem::forget(orig.borrow); + // SAFETY: after forgetting, we can form a reference for the rest of lifetime `'b`. + unsafe { orig.value.as_mut() } + } +} + +struct BorrowRefMut<'b> { + borrow: &'b Cell, +} + +impl Drop for BorrowRefMut<'_> { + #[inline] + fn drop(&mut self) { + let borrow = self.borrow.get(); + debug_assert!(is_writing(borrow)); + self.borrow.set(borrow + 1); + } +} + +impl<'b> BorrowRefMut<'b> { + #[inline] + fn new(borrow: &'b Cell) -> Option> { + // NOTE: Unlike BorrowRefMut::clone, new is called to create the initial + // mutable reference, and so there must currently be no existing + // references. Thus, while clone increments the mutable refcount, here + // we explicitly only allow going from UNUSED to UNUSED - 1. + match borrow.get() { + UNUSED => { + borrow.set(UNUSED - 1); + Some(BorrowRefMut { borrow }) + } + _ => None, + } + } + + // Clones a `BorrowRefMut`. + // + // This is only valid if each `BorrowRefMut` is used to track a mutable + // reference to a distinct, nonoverlapping range of the original object. + // This isn't in a Clone impl so that code doesn't call this implicitly. + #[inline] + fn clone(&self) -> BorrowRefMut<'b> { + let borrow = self.borrow.get(); + debug_assert!(is_writing(borrow)); + // Prevent the borrow counter from underflowing. + assert!(borrow != BorrowFlag::MIN); + self.borrow.set(borrow - 1); + BorrowRefMut { borrow: self.borrow } + } +} + +/// A wrapper type for a mutably borrowed value from a `RefCell`. +/// +/// See the [module-level documentation](self) for more. +#[stable(feature = "rust1", since = "1.0.0")] +#[must_not_suspend = "holding a RefMut across suspend points can cause BorrowErrors"] +#[rustc_diagnostic_item = "RefCellRefMut"] +pub struct RefMut<'b, T: ?Sized + 'b> { + // NB: we use a pointer instead of `&'b mut T` to avoid `noalias` violations, because a + // `RefMut` argument doesn't hold exclusivity for its whole scope, only until it drops. + value: NonNull, + borrow: BorrowRefMut<'b>, + // `NonNull` is covariant over `T`, so we need to reintroduce invariance. + marker: PhantomData<&'b mut T>, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for RefMut<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + // SAFETY: the value is accessible as long as we hold our borrow. + unsafe { self.value.as_ref() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DerefMut for RefMut<'_, T> { + #[inline] + fn deref_mut(&mut self) -> &mut T { + // SAFETY: the value is accessible as long as we hold our borrow. + unsafe { self.value.as_mut() } + } +} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for RefMut<'_, T> {} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl<'b, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for RefMut<'b, T> {} + +#[stable(feature = "std_guard_impls", since = "1.20.0")] +impl fmt::Display for RefMut<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +/// The core primitive for interior mutability in Rust. +/// +/// If you have a reference `&T`, then normally in Rust the compiler performs optimizations based on +/// the knowledge that `&T` points to immutable data. Mutating that data, for example through an +/// alias or by transmuting a `&T` into a `&mut T`, is considered undefined behavior. +/// `UnsafeCell` opts-out of the immutability guarantee for `&T`: a shared reference +/// `&UnsafeCell` may point to data that is being mutated. This is called "interior mutability". +/// +/// All other types that allow internal mutability, such as [`Cell`] and [`RefCell`], internally +/// use `UnsafeCell` to wrap their data. +/// +/// Note that only the immutability guarantee for shared references is affected by `UnsafeCell`. The +/// uniqueness guarantee for mutable references is unaffected. There is *no* legal way to obtain +/// aliasing `&mut`, not even with `UnsafeCell`. +/// +/// `UnsafeCell` does nothing to avoid data races; they are still undefined behavior. If multiple +/// threads have access to the same `UnsafeCell`, they must follow the usual rules of the +/// [concurrent memory model]: conflicting non-synchronized accesses must be done via the APIs in +/// [`core::sync::atomic`]. +/// +/// The `UnsafeCell` API itself is technically very simple: [`.get()`] gives you a raw pointer +/// `*mut T` to its contents. It is up to _you_ as the abstraction designer to use that raw pointer +/// correctly. +/// +/// [`.get()`]: `UnsafeCell::get` +/// [concurrent memory model]: ../sync/atomic/index.html#memory-model-for-atomic-accesses +/// +/// The precise Rust aliasing rules are somewhat in flux, but the main points are not contentious: +/// +/// - If you create a safe reference with lifetime `'a` (either a `&T` or `&mut T` reference), then +/// you must not access the data in any way that contradicts that reference for the remainder of +/// `'a`. For example, this means that if you take the `*mut T` from an `UnsafeCell` and cast it +/// to an `&T`, then the data in `T` must remain immutable (modulo any `UnsafeCell` data found +/// within `T`, of course) until that reference's lifetime expires. Similarly, if you create a `&mut +/// T` reference that is released to safe code, then you must not access the data within the +/// `UnsafeCell` until that reference expires. +/// +/// - For both `&T` without `UnsafeCell<_>` and `&mut T`, you must also not deallocate the data +/// until the reference expires. As a special exception, given an `&T`, any part of it that is +/// inside an `UnsafeCell<_>` may be deallocated during the lifetime of the reference, after the +/// last time the reference is used (dereferenced or reborrowed). Since you cannot deallocate a part +/// of what a reference points to, this means the memory an `&T` points to can be deallocated only if +/// *every part of it* (including padding) is inside an `UnsafeCell`. +/// +/// However, whenever a `&UnsafeCell` is constructed or dereferenced, it must still point to +/// live memory and the compiler is allowed to insert spurious reads if it can prove that this +/// memory has not yet been deallocated. +/// +/// To assist with proper design, the following scenarios are explicitly declared legal +/// for single-threaded code: +/// +/// 1. A `&T` reference can be released to safe code and there it can co-exist with other `&T` +/// references, but not with a `&mut T` +/// +/// 2. A `&mut T` reference may be released to safe code provided neither other `&mut T` nor `&T` +/// co-exist with it. A `&mut T` must always be unique. +/// +/// Note that whilst mutating the contents of an `&UnsafeCell` (even while other +/// `&UnsafeCell` references alias the cell) is +/// ok (provided you enforce the above invariants some other way), it is still undefined behavior +/// to have multiple `&mut UnsafeCell` aliases. That is, `UnsafeCell` is a wrapper +/// designed to have a special interaction with _shared_ accesses (_i.e._, through an +/// `&UnsafeCell<_>` reference); there is no magic whatsoever when dealing with _exclusive_ +/// accesses (_e.g._, through a `&mut UnsafeCell<_>`): neither the cell nor the wrapped value +/// may be aliased for the duration of that `&mut` borrow. +/// This is showcased by the [`.get_mut()`] accessor, which is a _safe_ getter that yields +/// a `&mut T`. +/// +/// [`.get_mut()`]: `UnsafeCell::get_mut` +/// +/// # Memory layout +/// +/// `UnsafeCell` has the same in-memory representation as its inner type `T`. A consequence +/// of this guarantee is that it is possible to convert between `T` and `UnsafeCell`. +/// Special care has to be taken when converting a nested `T` inside of an `Outer` type +/// to an `Outer>` type: this is not sound when the `Outer` type enables [niche] +/// optimizations. For example, the type `Option>` is typically 8 bytes large on +/// 64-bit platforms, but the type `Option>>` takes up 16 bytes of space. +/// Therefore this is not a valid conversion, despite `NonNull` and `UnsafeCell>>` +/// having the same memory layout. This is because `UnsafeCell` disables niche optimizations in +/// order to avoid its interior mutability property from spreading from `T` into the `Outer` type, +/// thus this can cause distortions in the type size in these cases. +/// +/// Note that the only valid way to obtain a `*mut T` pointer to the contents of a +/// _shared_ `UnsafeCell` is through [`.get()`] or [`.raw_get()`]. A `&mut T` reference +/// can be obtained by either dereferencing this pointer or by calling [`.get_mut()`] +/// on an _exclusive_ `UnsafeCell`. Even though `T` and `UnsafeCell` have the +/// same memory layout, the following is not allowed and undefined behavior: +/// +/// ```rust,compile_fail +/// # use std::cell::UnsafeCell; +/// unsafe fn not_allowed(ptr: &UnsafeCell) -> &mut T { +/// let t = ptr as *const UnsafeCell as *mut T; +/// // This is undefined behavior, because the `*mut T` pointer +/// // was not obtained through `.get()` nor `.raw_get()`: +/// unsafe { &mut *t } +/// } +/// ``` +/// +/// Instead, do this: +/// +/// ```rust +/// # use std::cell::UnsafeCell; +/// // Safety: the caller must ensure that there are no references that +/// // point to the *contents* of the `UnsafeCell`. +/// unsafe fn get_mut(ptr: &UnsafeCell) -> &mut T { +/// unsafe { &mut *ptr.get() } +/// } +/// ``` +/// +/// Converting in the other direction from a `&mut T` +/// to an `&UnsafeCell` is allowed: +/// +/// ```rust +/// # use std::cell::UnsafeCell; +/// fn get_shared(ptr: &mut T) -> &UnsafeCell { +/// let t = ptr as *mut T as *const UnsafeCell; +/// // SAFETY: `T` and `UnsafeCell` have the same memory layout +/// unsafe { &*t } +/// } +/// ``` +/// +/// [niche]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#niche +/// [`.raw_get()`]: `UnsafeCell::raw_get` +/// +/// # Examples +/// +/// Here is an example showcasing how to soundly mutate the contents of an `UnsafeCell<_>` despite +/// there being multiple references aliasing the cell: +/// +/// ``` +/// use std::cell::UnsafeCell; +/// +/// let x: UnsafeCell = 42.into(); +/// // Get multiple / concurrent / shared references to the same `x`. +/// let (p1, p2): (&UnsafeCell, &UnsafeCell) = (&x, &x); +/// +/// unsafe { +/// // SAFETY: within this scope there are no other references to `x`'s contents, +/// // so ours is effectively unique. +/// let p1_exclusive: &mut i32 = &mut *p1.get(); // -- borrow --+ +/// *p1_exclusive += 27; // | +/// } // <---------- cannot go beyond this point -------------------+ +/// +/// unsafe { +/// // SAFETY: within this scope nobody expects to have exclusive access to `x`'s contents, +/// // so we can have multiple shared accesses concurrently. +/// let p2_shared: &i32 = &*p2.get(); +/// assert_eq!(*p2_shared, 42 + 27); +/// let p1_shared: &i32 = &*p1.get(); +/// assert_eq!(*p1_shared, *p2_shared); +/// } +/// ``` +/// +/// The following example showcases the fact that exclusive access to an `UnsafeCell` +/// implies exclusive access to its `T`: +/// +/// ```rust +/// #![forbid(unsafe_code)] // with exclusive accesses, +/// // `UnsafeCell` is a transparent no-op wrapper, +/// // so no need for `unsafe` here. +/// use std::cell::UnsafeCell; +/// +/// let mut x: UnsafeCell = 42.into(); +/// +/// // Get a compile-time-checked unique reference to `x`. +/// let p_unique: &mut UnsafeCell = &mut x; +/// // With an exclusive reference, we can mutate the contents for free. +/// *p_unique.get_mut() = 0; +/// // Or, equivalently: +/// x = UnsafeCell::new(0); +/// +/// // When we own the value, we can extract the contents for free. +/// let contents: i32 = x.into_inner(); +/// assert_eq!(contents, 0); +/// ``` +#[lang = "unsafe_cell"] +#[stable(feature = "rust1", since = "1.0.0")] +#[repr(transparent)] +#[rustc_pub_transparent] +pub struct UnsafeCell { + value: T, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl !Sync for UnsafeCell {} + +impl UnsafeCell { + /// Constructs a new instance of `UnsafeCell` which will wrap the specified + /// value. + /// + /// All access to the inner value through `&UnsafeCell` requires `unsafe` code. + /// + /// # Examples + /// + /// ``` + /// use std::cell::UnsafeCell; + /// + /// let uc = UnsafeCell::new(5); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_unsafe_cell_new", since = "1.32.0")] + #[inline(always)] + pub const fn new(value: T) -> UnsafeCell { + UnsafeCell { value } + } + + /// Unwraps the value, consuming the cell. + /// + /// # Examples + /// + /// ``` + /// use std::cell::UnsafeCell; + /// + /// let uc = UnsafeCell::new(5); + /// + /// let five = uc.into_inner(); + /// ``` + #[inline(always)] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + pub const fn into_inner(self) -> T { + self.value + } +} + +impl UnsafeCell { + /// Converts from `&mut T` to `&mut UnsafeCell`. + /// + /// # Examples + /// + /// ``` + /// use std::cell::UnsafeCell; + /// + /// let mut val = 42; + /// let uc = UnsafeCell::from_mut(&mut val); + /// + /// *uc.get_mut() -= 1; + /// assert_eq!(*uc.get_mut(), 41); + /// ``` + #[inline(always)] + #[stable(feature = "unsafe_cell_from_mut", since = "1.84.0")] + #[rustc_const_stable(feature = "unsafe_cell_from_mut", since = "1.84.0")] + pub const fn from_mut(value: &mut T) -> &mut UnsafeCell { + // SAFETY: `UnsafeCell` has the same memory layout as `T` due to #[repr(transparent)]. + unsafe { &mut *(value as *mut T as *mut UnsafeCell) } + } + + /// Gets a mutable pointer to the wrapped value. + /// + /// This can be cast to a pointer of any kind. + /// Ensure that the access is unique (no active references, mutable or not) + /// when casting to `&mut T`, and ensure that there are no mutations + /// or mutable aliases going on when casting to `&T` + /// + /// # Examples + /// + /// ``` + /// use std::cell::UnsafeCell; + /// + /// let uc = UnsafeCell::new(5); + /// + /// let five = uc.get(); + /// ``` + #[inline(always)] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")] + #[rustc_as_ptr] + #[rustc_never_returns_null_ptr] + pub const fn get(&self) -> *mut T { + // We can just cast the pointer from `UnsafeCell` to `T` because of + // #[repr(transparent)]. This exploits std's special status, there is + // no guarantee for user code that this will work in future versions of the compiler! + self as *const UnsafeCell as *const T as *mut T + } + + /// Returns a mutable reference to the underlying data. + /// + /// This call borrows the `UnsafeCell` mutably (at compile-time) which + /// guarantees that we possess the only reference. + /// + /// # Examples + /// + /// ``` + /// use std::cell::UnsafeCell; + /// + /// let mut c = UnsafeCell::new(5); + /// *c.get_mut() += 1; + /// + /// assert_eq!(*c.get_mut(), 6); + /// ``` + #[inline(always)] + #[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")] + #[rustc_const_stable(feature = "const_unsafecell_get_mut", since = "1.83.0")] + pub const fn get_mut(&mut self) -> &mut T { + &mut self.value + } + + /// Gets a mutable pointer to the wrapped value. + /// The difference from [`get`] is that this function accepts a raw pointer, + /// which is useful to avoid the creation of temporary references. + /// + /// The result can be cast to a pointer of any kind. + /// Ensure that the access is unique (no active references, mutable or not) + /// when casting to `&mut T`, and ensure that there are no mutations + /// or mutable aliases going on when casting to `&T`. + /// + /// [`get`]: UnsafeCell::get() + /// + /// # Examples + /// + /// Gradual initialization of an `UnsafeCell` requires `raw_get`, as + /// calling `get` would require creating a reference to uninitialized data: + /// + /// ``` + /// use std::cell::UnsafeCell; + /// use std::mem::MaybeUninit; + /// + /// let m = MaybeUninit::>::uninit(); + /// unsafe { UnsafeCell::raw_get(m.as_ptr()).write(5); } + /// // avoid below which references to uninitialized data + /// // unsafe { UnsafeCell::get(&*m.as_ptr()).write(5); } + /// let uc = unsafe { m.assume_init() }; + /// + /// assert_eq!(uc.into_inner(), 5); + /// ``` + #[inline(always)] + #[stable(feature = "unsafe_cell_raw_get", since = "1.56.0")] + #[rustc_const_stable(feature = "unsafe_cell_raw_get", since = "1.56.0")] + #[rustc_diagnostic_item = "unsafe_cell_raw_get"] + pub const fn raw_get(this: *const Self) -> *mut T { + // We can just cast the pointer from `UnsafeCell` to `T` because of + // #[repr(transparent)]. This exploits std's special status, there is + // no guarantee for user code that this will work in future versions of the compiler! + this as *const T as *mut T + } +} + +#[stable(feature = "unsafe_cell_default", since = "1.10.0")] +impl Default for UnsafeCell { + /// Creates an `UnsafeCell`, with the `Default` value for T. + fn default() -> UnsafeCell { + UnsafeCell::new(Default::default()) + } +} + +#[stable(feature = "cell_from", since = "1.12.0")] +impl From for UnsafeCell { + /// Creates a new `UnsafeCell` containing the given value. + fn from(t: T) -> UnsafeCell { + UnsafeCell::new(t) + } +} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U> CoerceUnsized> for UnsafeCell {} + +// Allow types that wrap `UnsafeCell` to also implement `DispatchFromDyn` +// and become dyn-compatible method receivers. +// Note that currently `UnsafeCell` itself cannot be a method receiver +// because it does not implement Deref. +// In other words: +// `self: UnsafeCell<&Self>` won't work +// `self: UnsafeCellWrapper` becomes possible +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U> DispatchFromDyn> for UnsafeCell {} + +/// [`UnsafeCell`], but [`Sync`]. +/// +/// This is just an `UnsafeCell`, except it implements `Sync` +/// if `T` implements `Sync`. +/// +/// `UnsafeCell` doesn't implement `Sync`, to prevent accidental mis-use. +/// You can use `SyncUnsafeCell` instead of `UnsafeCell` to allow it to be +/// shared between threads, if that's intentional. +/// Providing proper synchronization is still the task of the user, +/// making this type just as unsafe to use. +/// +/// See [`UnsafeCell`] for details. +#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +#[repr(transparent)] +#[rustc_diagnostic_item = "SyncUnsafeCell"] +#[rustc_pub_transparent] +pub struct SyncUnsafeCell { + value: UnsafeCell, +} + +#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +unsafe impl Sync for SyncUnsafeCell {} + +#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +impl SyncUnsafeCell { + /// Constructs a new instance of `SyncUnsafeCell` which will wrap the specified value. + #[inline] + pub const fn new(value: T) -> Self { + Self { value: UnsafeCell { value } } + } + + /// Unwraps the value, consuming the cell. + #[inline] + #[rustc_const_unstable(feature = "sync_unsafe_cell", issue = "95439")] + pub const fn into_inner(self) -> T { + self.value.into_inner() + } +} + +#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +impl SyncUnsafeCell { + /// Gets a mutable pointer to the wrapped value. + /// + /// This can be cast to a pointer of any kind. + /// Ensure that the access is unique (no active references, mutable or not) + /// when casting to `&mut T`, and ensure that there are no mutations + /// or mutable aliases going on when casting to `&T` + #[inline] + #[rustc_as_ptr] + #[rustc_never_returns_null_ptr] + pub const fn get(&self) -> *mut T { + self.value.get() + } + + /// Returns a mutable reference to the underlying data. + /// + /// This call borrows the `SyncUnsafeCell` mutably (at compile-time) which + /// guarantees that we possess the only reference. + #[inline] + pub const fn get_mut(&mut self) -> &mut T { + self.value.get_mut() + } + + /// Gets a mutable pointer to the wrapped value. + /// + /// See [`UnsafeCell::get`] for details. + #[inline] + pub const fn raw_get(this: *const Self) -> *mut T { + // We can just cast the pointer from `SyncUnsafeCell` to `T` because + // of #[repr(transparent)] on both SyncUnsafeCell and UnsafeCell. + // See UnsafeCell::raw_get. + this as *const T as *mut T + } +} + +#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +impl Default for SyncUnsafeCell { + /// Creates an `SyncUnsafeCell`, with the `Default` value for T. + fn default() -> SyncUnsafeCell { + SyncUnsafeCell::new(Default::default()) + } +} + +#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +impl From for SyncUnsafeCell { + /// Creates a new `SyncUnsafeCell` containing the given value. + fn from(t: T) -> SyncUnsafeCell { + SyncUnsafeCell::new(t) + } +} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +//#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +impl, U> CoerceUnsized> for SyncUnsafeCell {} + +// Allow types that wrap `SyncUnsafeCell` to also implement `DispatchFromDyn` +// and become dyn-compatible method receivers. +// Note that currently `SyncUnsafeCell` itself cannot be a method receiver +// because it does not implement Deref. +// In other words: +// `self: SyncUnsafeCell<&Self>` won't work +// `self: SyncUnsafeCellWrapper` becomes possible +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +//#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +impl, U> DispatchFromDyn> for SyncUnsafeCell {} + +#[allow(unused)] +fn assert_coerce_unsized( + a: UnsafeCell<&i32>, + b: SyncUnsafeCell<&i32>, + c: Cell<&i32>, + d: RefCell<&i32>, +) { + let _: UnsafeCell<&dyn Send> = a; + let _: SyncUnsafeCell<&dyn Send> = b; + let _: Cell<&dyn Send> = c; + let _: RefCell<&dyn Send> = d; +} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for UnsafeCell {} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for SyncUnsafeCell {} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Cell {} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for RefCell {} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl<'b, T: ?Sized> PinCoerceUnsized for Ref<'b, T> {} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl<'b, T: ?Sized> PinCoerceUnsized for RefMut<'b, T> {} diff --git a/CoqOfRust/core/cell/lazy.rs b/CoqOfRust/core/cell/lazy.rs new file mode 100644 index 000000000..5ac335166 --- /dev/null +++ b/CoqOfRust/core/cell/lazy.rs @@ -0,0 +1,312 @@ +use super::UnsafeCell; +use crate::hint::unreachable_unchecked; +use crate::ops::Deref; +use crate::{fmt, mem}; + +enum State { + Uninit(F), + Init(T), + Poisoned, +} + +/// A value which is initialized on the first access. +/// +/// For a thread-safe version of this struct, see [`std::sync::LazyLock`]. +/// +/// [`std::sync::LazyLock`]: ../../std/sync/struct.LazyLock.html +/// +/// # Examples +/// +/// ``` +/// use std::cell::LazyCell; +/// +/// let lazy: LazyCell = LazyCell::new(|| { +/// println!("initializing"); +/// 92 +/// }); +/// println!("ready"); +/// println!("{}", *lazy); +/// println!("{}", *lazy); +/// +/// // Prints: +/// // ready +/// // initializing +/// // 92 +/// // 92 +/// ``` +#[stable(feature = "lazy_cell", since = "1.80.0")] +pub struct LazyCell T> { + state: UnsafeCell>, +} + +impl T> LazyCell { + /// Creates a new lazy value with the given initializing function. + /// + /// # Examples + /// + /// ``` + /// use std::cell::LazyCell; + /// + /// let hello = "Hello, World!".to_string(); + /// + /// let lazy = LazyCell::new(|| hello.to_uppercase()); + /// + /// assert_eq!(&*lazy, "HELLO, WORLD!"); + /// ``` + #[inline] + #[stable(feature = "lazy_cell", since = "1.80.0")] + #[rustc_const_stable(feature = "lazy_cell", since = "1.80.0")] + pub const fn new(f: F) -> LazyCell { + LazyCell { state: UnsafeCell::new(State::Uninit(f)) } + } + + /// Consumes this `LazyCell` returning the stored value. + /// + /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(lazy_cell_into_inner)] + /// + /// use std::cell::LazyCell; + /// + /// let hello = "Hello, World!".to_string(); + /// + /// let lazy = LazyCell::new(|| hello.to_uppercase()); + /// + /// assert_eq!(&*lazy, "HELLO, WORLD!"); + /// assert_eq!(LazyCell::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string())); + /// ``` + #[unstable(feature = "lazy_cell_into_inner", issue = "125623")] + #[rustc_const_unstable(feature = "lazy_cell_into_inner", issue = "125623")] + pub const fn into_inner(this: Self) -> Result { + match this.state.into_inner() { + State::Init(data) => Ok(data), + State::Uninit(f) => Err(f), + State::Poisoned => panic_poisoned(), + } + } + + /// Forces the evaluation of this lazy value and returns a reference to + /// the result. + /// + /// This is equivalent to the `Deref` impl, but is explicit. + /// + /// # Examples + /// + /// ``` + /// use std::cell::LazyCell; + /// + /// let lazy = LazyCell::new(|| 92); + /// + /// assert_eq!(LazyCell::force(&lazy), &92); + /// assert_eq!(&*lazy, &92); + /// ``` + #[inline] + #[stable(feature = "lazy_cell", since = "1.80.0")] + pub fn force(this: &LazyCell) -> &T { + // SAFETY: + // This invalidates any mutable references to the data. The resulting + // reference lives either until the end of the borrow of `this` (in the + // initialized case) or is invalidated in `really_init` (in the + // uninitialized case; `really_init` will create and return a fresh reference). + let state = unsafe { &*this.state.get() }; + match state { + State::Init(data) => data, + // SAFETY: The state is uninitialized. + State::Uninit(_) => unsafe { LazyCell::really_init(this) }, + State::Poisoned => panic_poisoned(), + } + } + + /// Forces the evaluation of this lazy value and returns a mutable reference to + /// the result. + /// + /// # Examples + /// + /// ``` + /// #![feature(lazy_get)] + /// use std::cell::LazyCell; + /// + /// let mut lazy = LazyCell::new(|| 92); + /// + /// let p = LazyCell::force_mut(&mut lazy); + /// assert_eq!(*p, 92); + /// *p = 44; + /// assert_eq!(*lazy, 44); + /// ``` + #[inline] + #[unstable(feature = "lazy_get", issue = "129333")] + pub fn force_mut(this: &mut LazyCell) -> &mut T { + #[cold] + /// # Safety + /// May only be called when the state is `Uninit`. + unsafe fn really_init_mut T>(state: &mut State) -> &mut T { + // INVARIANT: Always valid, but the value may not be dropped. + struct PoisonOnPanic(*mut State); + impl Drop for PoisonOnPanic { + #[inline] + fn drop(&mut self) { + // SAFETY: Invariant states it is valid, and we don't drop the old value. + unsafe { + self.0.write(State::Poisoned); + } + } + } + + let State::Uninit(f) = state else { + // `unreachable!()` here won't optimize out because the function is cold. + // SAFETY: Precondition. + unsafe { unreachable_unchecked() }; + }; + // SAFETY: We never drop the state after we read `f`, and we write a valid value back + // in any case, panic or success. `f` can't access the `LazyCell` because it is mutably + // borrowed. + let f = unsafe { core::ptr::read(f) }; + // INVARIANT: Initiated from mutable reference, don't drop because we read it. + let guard = PoisonOnPanic(state); + let data = f(); + // SAFETY: `PoisonOnPanic` invariant, and we don't drop the old value. + unsafe { + core::ptr::write(guard.0, State::Init(data)); + } + core::mem::forget(guard); + let State::Init(data) = state else { unreachable!() }; + data + } + + let state = this.state.get_mut(); + match state { + State::Init(data) => data, + // SAFETY: `state` is `Uninit`. + State::Uninit(_) => unsafe { really_init_mut(state) }, + State::Poisoned => panic_poisoned(), + } + } + + /// # Safety + /// May only be called when the state is `Uninit`. + #[cold] + unsafe fn really_init(this: &LazyCell) -> &T { + // SAFETY: + // This function is only called when the state is uninitialized, + // so no references to `state` can exist except for the reference + // in `force`, which is invalidated here and not accessed again. + let state = unsafe { &mut *this.state.get() }; + // Temporarily mark the state as poisoned. This prevents reentrant + // accesses and correctly poisons the cell if the closure panicked. + let State::Uninit(f) = mem::replace(state, State::Poisoned) else { unreachable!() }; + + let data = f(); + + // SAFETY: + // If the closure accessed the cell through something like a reentrant + // mutex, but caught the panic resulting from the state being poisoned, + // the mutable borrow for `state` will be invalidated, so we need to + // go through the `UnsafeCell` pointer here. The state can only be + // poisoned at this point, so using `write` to skip the destructor + // of `State` should help the optimizer. + unsafe { this.state.get().write(State::Init(data)) }; + + // SAFETY: + // The previous references were invalidated by the `write` call above, + // so do a new shared borrow of the state instead. + let state = unsafe { &*this.state.get() }; + let State::Init(data) = state else { unreachable!() }; + data + } +} + +impl LazyCell { + /// Returns a reference to the value if initialized, or `None` if not. + /// + /// # Examples + /// + /// ``` + /// #![feature(lazy_get)] + /// + /// use std::cell::LazyCell; + /// + /// let mut lazy = LazyCell::new(|| 92); + /// + /// assert_eq!(LazyCell::get_mut(&mut lazy), None); + /// let _ = LazyCell::force(&lazy); + /// *LazyCell::get_mut(&mut lazy).unwrap() = 44; + /// assert_eq!(*lazy, 44); + /// ``` + #[inline] + #[unstable(feature = "lazy_get", issue = "129333")] + pub fn get_mut(this: &mut LazyCell) -> Option<&mut T> { + let state = this.state.get_mut(); + match state { + State::Init(data) => Some(data), + _ => None, + } + } + + /// Returns a mutable reference to the value if initialized, or `None` if not. + /// + /// # Examples + /// + /// ``` + /// #![feature(lazy_get)] + /// + /// use std::cell::LazyCell; + /// + /// let lazy = LazyCell::new(|| 92); + /// + /// assert_eq!(LazyCell::get(&lazy), None); + /// let _ = LazyCell::force(&lazy); + /// assert_eq!(LazyCell::get(&lazy), Some(&92)); + /// ``` + #[inline] + #[unstable(feature = "lazy_get", issue = "129333")] + pub fn get(this: &LazyCell) -> Option<&T> { + // SAFETY: + // This is sound for the same reason as in `force`: once the state is + // initialized, it will not be mutably accessed again, so this reference + // will stay valid for the duration of the borrow to `self`. + let state = unsafe { &*this.state.get() }; + match state { + State::Init(data) => Some(data), + _ => None, + } + } +} + +#[stable(feature = "lazy_cell", since = "1.80.0")] +impl T> Deref for LazyCell { + type Target = T; + #[inline] + fn deref(&self) -> &T { + LazyCell::force(self) + } +} + +#[stable(feature = "lazy_cell", since = "1.80.0")] +impl Default for LazyCell { + /// Creates a new lazy value using `Default` as the initializing function. + #[inline] + fn default() -> LazyCell { + LazyCell::new(T::default) + } +} + +#[stable(feature = "lazy_cell", since = "1.80.0")] +impl fmt::Debug for LazyCell { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut d = f.debug_tuple("LazyCell"); + match LazyCell::get(self) { + Some(data) => d.field(data), + None => d.field(&format_args!("")), + }; + d.finish() + } +} + +#[cold] +#[inline(never)] +const fn panic_poisoned() -> ! { + panic!("LazyCell instance has previously been poisoned") +} diff --git a/CoqOfRust/core/cell/once.rs b/CoqOfRust/core/cell/once.rs new file mode 100644 index 000000000..c14afe0f4 --- /dev/null +++ b/CoqOfRust/core/cell/once.rs @@ -0,0 +1,403 @@ +use crate::cell::UnsafeCell; +use crate::{fmt, mem}; + +/// A cell which can nominally be written to only once. +/// +/// This allows obtaining a shared `&T` reference to its inner value without copying or replacing +/// it (unlike [`Cell`]), and without runtime borrow checks (unlike [`RefCell`]). However, +/// only immutable references can be obtained unless one has a mutable reference to the cell +/// itself. In the same vein, the cell can only be re-initialized with such a mutable reference. +/// +/// For a thread-safe version of this struct, see [`std::sync::OnceLock`]. +/// +/// [`RefCell`]: crate::cell::RefCell +/// [`Cell`]: crate::cell::Cell +/// [`std::sync::OnceLock`]: ../../std/sync/struct.OnceLock.html +/// +/// # Examples +/// +/// ``` +/// use std::cell::OnceCell; +/// +/// let cell = OnceCell::new(); +/// assert!(cell.get().is_none()); +/// +/// let value: &String = cell.get_or_init(|| { +/// "Hello, World!".to_string() +/// }); +/// assert_eq!(value, "Hello, World!"); +/// assert!(cell.get().is_some()); +/// ``` +#[stable(feature = "once_cell", since = "1.70.0")] +pub struct OnceCell { + // Invariant: written to at most once. + inner: UnsafeCell>, +} + +impl OnceCell { + /// Creates a new empty cell. + #[inline] + #[must_use] + #[stable(feature = "once_cell", since = "1.70.0")] + #[rustc_const_stable(feature = "once_cell", since = "1.70.0")] + pub const fn new() -> OnceCell { + OnceCell { inner: UnsafeCell::new(None) } + } + + /// Gets the reference to the underlying value. + /// + /// Returns `None` if the cell is empty. + #[inline] + #[stable(feature = "once_cell", since = "1.70.0")] + pub fn get(&self) -> Option<&T> { + // SAFETY: Safe due to `inner`'s invariant + unsafe { &*self.inner.get() }.as_ref() + } + + /// Gets the mutable reference to the underlying value. + /// + /// Returns `None` if the cell is empty. + #[inline] + #[stable(feature = "once_cell", since = "1.70.0")] + pub fn get_mut(&mut self) -> Option<&mut T> { + self.inner.get_mut().as_mut() + } + + /// Sets the contents of the cell to `value`. + /// + /// # Errors + /// + /// This method returns `Ok(())` if the cell was empty and `Err(value)` if + /// it was full. + /// + /// # Examples + /// + /// ``` + /// use std::cell::OnceCell; + /// + /// let cell = OnceCell::new(); + /// assert!(cell.get().is_none()); + /// + /// assert_eq!(cell.set(92), Ok(())); + /// assert_eq!(cell.set(62), Err(62)); + /// + /// assert!(cell.get().is_some()); + /// ``` + #[inline] + #[stable(feature = "once_cell", since = "1.70.0")] + pub fn set(&self, value: T) -> Result<(), T> { + match self.try_insert(value) { + Ok(_) => Ok(()), + Err((_, value)) => Err(value), + } + } + + /// Sets the contents of the cell to `value` if the cell was empty, then + /// returns a reference to it. + /// + /// # Errors + /// + /// This method returns `Ok(&value)` if the cell was empty and + /// `Err(¤t_value, value)` if it was full. + /// + /// # Examples + /// + /// ``` + /// #![feature(once_cell_try_insert)] + /// + /// use std::cell::OnceCell; + /// + /// let cell = OnceCell::new(); + /// assert!(cell.get().is_none()); + /// + /// assert_eq!(cell.try_insert(92), Ok(&92)); + /// assert_eq!(cell.try_insert(62), Err((&92, 62))); + /// + /// assert!(cell.get().is_some()); + /// ``` + #[inline] + #[unstable(feature = "once_cell_try_insert", issue = "116693")] + pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> { + if let Some(old) = self.get() { + return Err((old, value)); + } + + // SAFETY: This is the only place where we set the slot, no races + // due to reentrancy/concurrency are possible, and we've + // checked that slot is currently `None`, so this write + // maintains the `inner`'s invariant. + let slot = unsafe { &mut *self.inner.get() }; + Ok(slot.insert(value)) + } + + /// Gets the contents of the cell, initializing it with `f` + /// if the cell was empty. + /// + /// # Panics + /// + /// If `f` panics, the panic is propagated to the caller, and the cell + /// remains uninitialized. + /// + /// It is an error to reentrantly initialize the cell from `f`. Doing + /// so results in a panic. + /// + /// # Examples + /// + /// ``` + /// use std::cell::OnceCell; + /// + /// let cell = OnceCell::new(); + /// let value = cell.get_or_init(|| 92); + /// assert_eq!(value, &92); + /// let value = cell.get_or_init(|| unreachable!()); + /// assert_eq!(value, &92); + /// ``` + #[inline] + #[stable(feature = "once_cell", since = "1.70.0")] + pub fn get_or_init(&self, f: F) -> &T + where + F: FnOnce() -> T, + { + match self.get_or_try_init(|| Ok::(f())) { + Ok(val) => val, + } + } + + /// Gets the mutable reference of the contents of the cell, + /// initializing it with `f` if the cell was empty. + /// + /// # Panics + /// + /// If `f` panics, the panic is propagated to the caller, and the cell + /// remains uninitialized. + /// + /// # Examples + /// + /// ``` + /// #![feature(once_cell_get_mut)] + /// + /// use std::cell::OnceCell; + /// + /// let mut cell = OnceCell::new(); + /// let value = cell.get_mut_or_init(|| 92); + /// assert_eq!(*value, 92); + /// + /// *value += 2; + /// assert_eq!(*value, 94); + /// + /// let value = cell.get_mut_or_init(|| unreachable!()); + /// assert_eq!(*value, 94); + /// ``` + #[inline] + #[unstable(feature = "once_cell_get_mut", issue = "121641")] + pub fn get_mut_or_init(&mut self, f: F) -> &mut T + where + F: FnOnce() -> T, + { + match self.get_mut_or_try_init(|| Ok::(f())) { + Ok(val) => val, + } + } + + /// Gets the contents of the cell, initializing it with `f` if + /// the cell was empty. If the cell was empty and `f` failed, an + /// error is returned. + /// + /// # Panics + /// + /// If `f` panics, the panic is propagated to the caller, and the cell + /// remains uninitialized. + /// + /// It is an error to reentrantly initialize the cell from `f`. Doing + /// so results in a panic. + /// + /// # Examples + /// + /// ``` + /// #![feature(once_cell_try)] + /// + /// use std::cell::OnceCell; + /// + /// let cell = OnceCell::new(); + /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); + /// assert!(cell.get().is_none()); + /// let value = cell.get_or_try_init(|| -> Result { + /// Ok(92) + /// }); + /// assert_eq!(value, Ok(&92)); + /// assert_eq!(cell.get(), Some(&92)) + /// ``` + #[unstable(feature = "once_cell_try", issue = "109737")] + pub fn get_or_try_init(&self, f: F) -> Result<&T, E> + where + F: FnOnce() -> Result, + { + if let Some(val) = self.get() { + return Ok(val); + } + self.try_init(f) + } + + /// Gets the mutable reference of the contents of the cell, initializing + /// it with `f` if the cell was empty. If the cell was empty and `f` failed, + /// an error is returned. + /// + /// # Panics + /// + /// If `f` panics, the panic is propagated to the caller, and the cell + /// remains uninitialized. + /// + /// # Examples + /// + /// ``` + /// #![feature(once_cell_get_mut)] + /// + /// use std::cell::OnceCell; + /// + /// let mut cell: OnceCell = OnceCell::new(); + /// + /// // Failed initializers do not change the value + /// assert!(cell.get_mut_or_try_init(|| "not a number!".parse()).is_err()); + /// assert!(cell.get().is_none()); + /// + /// let value = cell.get_mut_or_try_init(|| "1234".parse()); + /// assert_eq!(value, Ok(&mut 1234)); + /// *value.unwrap() += 2; + /// assert_eq!(cell.get(), Some(&1236)) + /// ``` + #[unstable(feature = "once_cell_get_mut", issue = "121641")] + pub fn get_mut_or_try_init(&mut self, f: F) -> Result<&mut T, E> + where + F: FnOnce() -> Result, + { + if self.get().is_none() { + self.try_init(f)?; + } + Ok(self.get_mut().unwrap()) + } + + // Avoid inlining the initialization closure into the common path that fetches + // the already initialized value + #[cold] + fn try_init(&self, f: F) -> Result<&T, E> + where + F: FnOnce() -> Result, + { + let val = f()?; + // Note that *some* forms of reentrant initialization might lead to + // UB (see `reentrant_init` test). I believe that just removing this + // `panic`, while keeping `try_insert` would be sound, but it seems + // better to panic, rather than to silently use an old value. + if let Ok(val) = self.try_insert(val) { Ok(val) } else { panic!("reentrant init") } + } + + /// Consumes the cell, returning the wrapped value. + /// + /// Returns `None` if the cell was empty. + /// + /// # Examples + /// + /// ``` + /// use std::cell::OnceCell; + /// + /// let cell: OnceCell = OnceCell::new(); + /// assert_eq!(cell.into_inner(), None); + /// + /// let cell = OnceCell::new(); + /// cell.set("hello".to_string()).unwrap(); + /// assert_eq!(cell.into_inner(), Some("hello".to_string())); + /// ``` + #[inline] + #[stable(feature = "once_cell", since = "1.70.0")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + pub const fn into_inner(self) -> Option { + // Because `into_inner` takes `self` by value, the compiler statically verifies + // that it is not currently borrowed. So it is safe to move out `Option`. + self.inner.into_inner() + } + + /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state. + /// + /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized. + /// + /// Safety is guaranteed by requiring a mutable reference. + /// + /// # Examples + /// + /// ``` + /// use std::cell::OnceCell; + /// + /// let mut cell: OnceCell = OnceCell::new(); + /// assert_eq!(cell.take(), None); + /// + /// let mut cell = OnceCell::new(); + /// cell.set("hello".to_string()).unwrap(); + /// assert_eq!(cell.take(), Some("hello".to_string())); + /// assert_eq!(cell.get(), None); + /// ``` + #[inline] + #[stable(feature = "once_cell", since = "1.70.0")] + pub fn take(&mut self) -> Option { + mem::take(self).into_inner() + } +} + +#[stable(feature = "once_cell", since = "1.70.0")] +impl Default for OnceCell { + #[inline] + fn default() -> Self { + Self::new() + } +} + +#[stable(feature = "once_cell", since = "1.70.0")] +impl fmt::Debug for OnceCell { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut d = f.debug_tuple("OnceCell"); + match self.get() { + Some(v) => d.field(v), + None => d.field(&format_args!("")), + }; + d.finish() + } +} + +#[stable(feature = "once_cell", since = "1.70.0")] +impl Clone for OnceCell { + #[inline] + fn clone(&self) -> OnceCell { + let res = OnceCell::new(); + if let Some(value) = self.get() { + match res.set(value.clone()) { + Ok(()) => (), + Err(_) => unreachable!(), + } + } + res + } +} + +#[stable(feature = "once_cell", since = "1.70.0")] +impl PartialEq for OnceCell { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.get() == other.get() + } +} + +#[stable(feature = "once_cell", since = "1.70.0")] +impl Eq for OnceCell {} + +#[stable(feature = "once_cell", since = "1.70.0")] +impl From for OnceCell { + /// Creates a new `OnceCell` which already contains the given `value`. + #[inline] + fn from(value: T) -> Self { + OnceCell { inner: UnsafeCell::new(Some(value)) } + } +} + +// Just like for `Cell` this isn't needed, but results in nicer error messages. +#[stable(feature = "once_cell", since = "1.70.0")] +impl !Sync for OnceCell {} diff --git a/CoqOfRust/core/char/convert.rs b/CoqOfRust/core/char/convert.rs new file mode 100644 index 000000000..73ab4f1e5 --- /dev/null +++ b/CoqOfRust/core/char/convert.rs @@ -0,0 +1,292 @@ +//! Character conversions. + +use crate::char::TryFromCharError; +use crate::error::Error; +use crate::fmt; +use crate::mem::transmute; +use crate::str::FromStr; +use crate::ub_checks::assert_unsafe_precondition; + +/// Converts a `u32` to a `char`. See [`char::from_u32`]. +#[must_use] +#[inline] +pub(super) const fn from_u32(i: u32) -> Option { + // FIXME(const-hack): once Result::ok is const fn, use it here + match char_try_from_u32(i) { + Ok(c) => Some(c), + Err(_) => None, + } +} + +/// Converts a `u32` to a `char`, ignoring validity. See [`char::from_u32_unchecked`]. +#[inline] +#[must_use] +pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char { + // SAFETY: the caller must guarantee that `i` is a valid char value. + unsafe { + assert_unsafe_precondition!( + check_language_ub, + "invalid value for `char`", + (i: u32 = i) => char_try_from_u32(i).is_ok() + ); + transmute(i) + } +} + +#[stable(feature = "char_convert", since = "1.13.0")] +impl From for u32 { + /// Converts a [`char`] into a [`u32`]. + /// + /// # Examples + /// + /// ``` + /// use std::mem; + /// + /// let c = 'c'; + /// let u = u32::from(c); + /// assert!(4 == mem::size_of_val(&u)) + /// ``` + #[inline] + fn from(c: char) -> Self { + c as u32 + } +} + +#[stable(feature = "more_char_conversions", since = "1.51.0")] +impl From for u64 { + /// Converts a [`char`] into a [`u64`]. + /// + /// # Examples + /// + /// ``` + /// use std::mem; + /// + /// let c = '👤'; + /// let u = u64::from(c); + /// assert!(8 == mem::size_of_val(&u)) + /// ``` + #[inline] + fn from(c: char) -> Self { + // The char is casted to the value of the code point, then zero-extended to 64 bit. + // See [https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics] + c as u64 + } +} + +#[stable(feature = "more_char_conversions", since = "1.51.0")] +impl From for u128 { + /// Converts a [`char`] into a [`u128`]. + /// + /// # Examples + /// + /// ``` + /// use std::mem; + /// + /// let c = '⚙'; + /// let u = u128::from(c); + /// assert!(16 == mem::size_of_val(&u)) + /// ``` + #[inline] + fn from(c: char) -> Self { + // The char is casted to the value of the code point, then zero-extended to 128 bit. + // See [https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics] + c as u128 + } +} + +/// Maps a `char` with code point in U+0000..=U+00FF to a byte in 0x00..=0xFF with same value, +/// failing if the code point is greater than U+00FF. +/// +/// See [`impl From for char`](char#impl-From-for-char) for details on the encoding. +#[stable(feature = "u8_from_char", since = "1.59.0")] +impl TryFrom for u8 { + type Error = TryFromCharError; + + /// Tries to convert a [`char`] into a [`u8`]. + /// + /// # Examples + /// + /// ``` + /// let a = 'ÿ'; // U+00FF + /// let b = 'Ā'; // U+0100 + /// assert_eq!(u8::try_from(a), Ok(0xFF_u8)); + /// assert!(u8::try_from(b).is_err()); + /// ``` + #[inline] + fn try_from(c: char) -> Result { + u8::try_from(u32::from(c)).map_err(|_| TryFromCharError(())) + } +} + +/// Maps a `char` with code point in U+0000..=U+FFFF to a `u16` in 0x0000..=0xFFFF with same value, +/// failing if the code point is greater than U+FFFF. +/// +/// This corresponds to the UCS-2 encoding, as specified in ISO/IEC 10646:2003. +#[stable(feature = "u16_from_char", since = "1.74.0")] +impl TryFrom for u16 { + type Error = TryFromCharError; + + /// Tries to convert a [`char`] into a [`u16`]. + /// + /// # Examples + /// + /// ``` + /// let trans_rights = '⚧'; // U+26A7 + /// let ninjas = '🥷'; // U+1F977 + /// assert_eq!(u16::try_from(trans_rights), Ok(0x26A7_u16)); + /// assert!(u16::try_from(ninjas).is_err()); + /// ``` + #[inline] + fn try_from(c: char) -> Result { + u16::try_from(u32::from(c)).map_err(|_| TryFromCharError(())) + } +} + +/// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF. +/// +/// Unicode is designed such that this effectively decodes bytes +/// with the character encoding that IANA calls ISO-8859-1. +/// This encoding is compatible with ASCII. +/// +/// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hyphen), +/// which leaves some "blanks", byte values that are not assigned to any character. +/// ISO-8859-1 (the IANA one) assigns them to the C0 and C1 control codes. +/// +/// Note that this is *also* different from Windows-1252 a.k.a. code page 1252, +/// which is a superset ISO/IEC 8859-1 that assigns some (not all!) blanks +/// to punctuation and various Latin characters. +/// +/// To confuse things further, [on the Web](https://encoding.spec.whatwg.org/) +/// `ascii`, `iso-8859-1`, and `windows-1252` are all aliases +/// for a superset of Windows-1252 that fills the remaining blanks with corresponding +/// C0 and C1 control codes. +#[stable(feature = "char_convert", since = "1.13.0")] +impl From for char { + /// Converts a [`u8`] into a [`char`]. + /// + /// # Examples + /// + /// ``` + /// use std::mem; + /// + /// let u = 32 as u8; + /// let c = char::from(u); + /// assert!(4 == mem::size_of_val(&c)) + /// ``` + #[inline] + fn from(i: u8) -> Self { + i as char + } +} + +/// An error which can be returned when parsing a char. +/// +/// This `struct` is created when using the [`char::from_str`] method. +#[stable(feature = "char_from_str", since = "1.20.0")] +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ParseCharError { + kind: CharErrorKind, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +enum CharErrorKind { + EmptyString, + TooManyChars, +} + +#[stable(feature = "char_from_str", since = "1.20.0")] +impl Error for ParseCharError { + #[allow(deprecated)] + fn description(&self) -> &str { + match self.kind { + CharErrorKind::EmptyString => "cannot parse char from empty string", + CharErrorKind::TooManyChars => "too many characters in string", + } + } +} + +#[stable(feature = "char_from_str", since = "1.20.0")] +impl fmt::Display for ParseCharError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + #[allow(deprecated)] + self.description().fmt(f) + } +} + +#[stable(feature = "char_from_str", since = "1.20.0")] +impl FromStr for char { + type Err = ParseCharError; + + #[inline] + fn from_str(s: &str) -> Result { + let mut chars = s.chars(); + match (chars.next(), chars.next()) { + (None, _) => Err(ParseCharError { kind: CharErrorKind::EmptyString }), + (Some(c), None) => Ok(c), + _ => Err(ParseCharError { kind: CharErrorKind::TooManyChars }), + } + } +} + +#[inline] +const fn char_try_from_u32(i: u32) -> Result { + // This is an optimized version of the check + // (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF), + // which can also be written as + // i >= 0x110000 || (i >= 0xD800 && i < 0xE000). + // + // The XOR with 0xD800 permutes the ranges such that 0xD800..0xE000 is + // mapped to 0x0000..0x0800, while keeping all the high bits outside 0xFFFF the same. + // In particular, numbers >= 0x110000 stay in this range. + // + // Subtracting 0x800 causes 0x0000..0x0800 to wrap, meaning that a single + // unsigned comparison against 0x110000 - 0x800 will detect both the wrapped + // surrogate range as well as the numbers originally larger than 0x110000. + // + if (i ^ 0xD800).wrapping_sub(0x800) >= 0x110000 - 0x800 { + Err(CharTryFromError(())) + } else { + // SAFETY: checked that it's a legal unicode value + Ok(unsafe { transmute(i) }) + } +} + +#[stable(feature = "try_from", since = "1.34.0")] +impl TryFrom for char { + type Error = CharTryFromError; + + #[inline] + fn try_from(i: u32) -> Result { + char_try_from_u32(i) + } +} + +/// The error type returned when a conversion from [`prim@u32`] to [`prim@char`] fails. +/// +/// This `struct` is created by the [`char::try_from`](char#impl-TryFrom-for-char) method. +/// See its documentation for more. +#[stable(feature = "try_from", since = "1.34.0")] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct CharTryFromError(()); + +#[stable(feature = "try_from", since = "1.34.0")] +impl fmt::Display for CharTryFromError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + "converted integer out of range for `char`".fmt(f) + } +} + +/// Converts a digit in the given radix to a `char`. See [`char::from_digit`]. +#[inline] +#[must_use] +pub(super) const fn from_digit(num: u32, radix: u32) -> Option { + if radix > 36 { + panic!("from_digit: radix is too high (maximum 36)"); + } + if num < radix { + let num = num as u8; + if num < 10 { Some((b'0' + num) as char) } else { Some((b'a' + num - 10) as char) } + } else { + None + } +} diff --git a/CoqOfRust/core/char/decode.rs b/CoqOfRust/core/char/decode.rs new file mode 100644 index 000000000..23319fbe5 --- /dev/null +++ b/CoqOfRust/core/char/decode.rs @@ -0,0 +1,134 @@ +//! UTF-8 and UTF-16 decoding iterators + +use crate::error::Error; +use crate::fmt; +use crate::iter::FusedIterator; + +/// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s. +/// +/// This `struct` is created by the [`decode_utf16`] method on [`char`]. See its +/// documentation for more. +/// +/// [`decode_utf16`]: char::decode_utf16 +#[stable(feature = "decode_utf16", since = "1.9.0")] +#[derive(Clone, Debug)] +pub struct DecodeUtf16 +where + I: Iterator, +{ + iter: I, + buf: Option, +} + +/// An error that can be returned when decoding UTF-16 code points. +/// +/// This `struct` is created when using the [`DecodeUtf16`] type. +#[stable(feature = "decode_utf16", since = "1.9.0")] +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct DecodeUtf16Error { + code: u16, +} + +/// Creates an iterator over the UTF-16 encoded code points in `iter`, +/// returning unpaired surrogates as `Err`s. See [`char::decode_utf16`]. +#[inline] +pub(super) fn decode_utf16>(iter: I) -> DecodeUtf16 { + DecodeUtf16 { iter: iter.into_iter(), buf: None } +} + +#[stable(feature = "decode_utf16", since = "1.9.0")] +impl> Iterator for DecodeUtf16 { + type Item = Result; + + fn next(&mut self) -> Option> { + let u = match self.buf.take() { + Some(buf) => buf, + None => self.iter.next()?, + }; + + if !u.is_utf16_surrogate() { + // SAFETY: not a surrogate + Some(Ok(unsafe { char::from_u32_unchecked(u as u32) })) + } else if u >= 0xDC00 { + // a trailing surrogate + Some(Err(DecodeUtf16Error { code: u })) + } else { + let u2 = match self.iter.next() { + Some(u2) => u2, + // eof + None => return Some(Err(DecodeUtf16Error { code: u })), + }; + if u2 < 0xDC00 || u2 > 0xDFFF { + // not a trailing surrogate so we're not a valid + // surrogate pair, so rewind to redecode u2 next time. + self.buf = Some(u2); + return Some(Err(DecodeUtf16Error { code: u })); + } + + // all ok, so lets decode it. + let c = (((u & 0x3ff) as u32) << 10 | (u2 & 0x3ff) as u32) + 0x1_0000; + // SAFETY: we checked that it's a legal unicode value + Some(Ok(unsafe { char::from_u32_unchecked(c) })) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (low, high) = self.iter.size_hint(); + + let (low_buf, high_buf) = match self.buf { + // buf is empty, no additional elements from it. + None => (0, 0), + // `u` is a non surrogate, so it's always an additional character. + Some(u) if !u.is_utf16_surrogate() => (1, 1), + // `u` is a leading surrogate (it can never be a trailing surrogate and + // it's a surrogate due to the previous branch) and `self.iter` is empty. + // + // `u` can't be paired, since the `self.iter` is empty, + // so it will always become an additional element (error). + Some(_u) if high == Some(0) => (1, 1), + // `u` is a leading surrogate and `iter` may be non-empty. + // + // `u` can either pair with a trailing surrogate, in which case no additional elements + // are produced, or it can become an error, in which case it's an additional character (error). + Some(_u) => (0, 1), + }; + + // `self.iter` could contain entirely valid surrogates (2 elements per + // char), or entirely non-surrogates (1 element per char). + // + // On odd lower bound, at least one element must stay unpaired + // (with other elements from `self.iter`), so we round up. + let low = low.div_ceil(2) + low_buf; + let high = high.and_then(|h| h.checked_add(high_buf)); + + (low, high) + } +} + +#[stable(feature = "decode_utf16_fused_iterator", since = "1.75.0")] +impl + FusedIterator> FusedIterator for DecodeUtf16 {} + +impl DecodeUtf16Error { + /// Returns the unpaired surrogate which caused this error. + #[must_use] + #[stable(feature = "decode_utf16", since = "1.9.0")] + pub fn unpaired_surrogate(&self) -> u16 { + self.code + } +} + +#[stable(feature = "decode_utf16", since = "1.9.0")] +impl fmt::Display for DecodeUtf16Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "unpaired surrogate found: {:x}", self.code) + } +} + +#[stable(feature = "decode_utf16", since = "1.9.0")] +impl Error for DecodeUtf16Error { + #[allow(deprecated)] + fn description(&self) -> &str { + "unpaired surrogate found" + } +} diff --git a/CoqOfRust/core/char/methods.rs b/CoqOfRust/core/char/methods.rs new file mode 100644 index 000000000..7d3376587 --- /dev/null +++ b/CoqOfRust/core/char/methods.rs @@ -0,0 +1,1863 @@ +//! impl char {} + +use super::*; +use crate::panic::const_panic; +use crate::slice; +use crate::str::from_utf8_unchecked_mut; +use crate::unicode::printable::is_printable; +use crate::unicode::{self, conversions}; + +impl char { + /// The lowest valid code point a `char` can have, `'\0'`. + /// + /// Unlike integer types, `char` actually has a gap in the middle, + /// meaning that the range of possible `char`s is smaller than you + /// might expect. Ranges of `char` will automatically hop this gap + /// for you: + /// + /// ``` + /// let dist = u32::from(char::MAX) - u32::from(char::MIN); + /// let size = (char::MIN..=char::MAX).count() as u32; + /// assert!(size < dist); + /// ``` + /// + /// Despite this gap, the `MIN` and [`MAX`] values can be used as bounds for + /// all `char` values. + /// + /// [`MAX`]: char::MAX + /// + /// # Examples + /// + /// ``` + /// # fn something_which_returns_char() -> char { 'a' } + /// let c: char = something_which_returns_char(); + /// assert!(char::MIN <= c); + /// + /// let value_at_min = u32::from(char::MIN); + /// assert_eq!(char::from_u32(value_at_min), Some('\0')); + /// ``` + #[stable(feature = "char_min", since = "1.83.0")] + pub const MIN: char = '\0'; + + /// The highest valid code point a `char` can have, `'\u{10FFFF}'`. + /// + /// Unlike integer types, `char` actually has a gap in the middle, + /// meaning that the range of possible `char`s is smaller than you + /// might expect. Ranges of `char` will automatically hop this gap + /// for you: + /// + /// ``` + /// let dist = u32::from(char::MAX) - u32::from(char::MIN); + /// let size = (char::MIN..=char::MAX).count() as u32; + /// assert!(size < dist); + /// ``` + /// + /// Despite this gap, the [`MIN`] and `MAX` values can be used as bounds for + /// all `char` values. + /// + /// [`MIN`]: char::MIN + /// + /// # Examples + /// + /// ``` + /// # fn something_which_returns_char() -> char { 'a' } + /// let c: char = something_which_returns_char(); + /// assert!(c <= char::MAX); + /// + /// let value_at_max = u32::from(char::MAX); + /// assert_eq!(char::from_u32(value_at_max), Some('\u{10FFFF}')); + /// assert_eq!(char::from_u32(value_at_max + 1), None); + /// ``` + #[stable(feature = "assoc_char_consts", since = "1.52.0")] + pub const MAX: char = '\u{10FFFF}'; + + /// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a + /// decoding error. + /// + /// It can occur, for example, when giving ill-formed UTF-8 bytes to + /// [`String::from_utf8_lossy`](../std/string/struct.String.html#method.from_utf8_lossy). + #[stable(feature = "assoc_char_consts", since = "1.52.0")] + pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}'; + + /// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of + /// `char` and `str` methods are based on. + /// + /// New versions of Unicode are released regularly and subsequently all methods + /// in the standard library depending on Unicode are updated. Therefore the + /// behavior of some `char` and `str` methods and the value of this constant + /// changes over time. This is *not* considered to be a breaking change. + /// + /// The version numbering scheme is explained in + /// [Unicode 11.0 or later, Section 3.1 Versions of the Unicode Standard](https://www.unicode.org/versions/Unicode11.0.0/ch03.pdf#page=4). + #[stable(feature = "assoc_char_consts", since = "1.52.0")] + pub const UNICODE_VERSION: (u8, u8, u8) = crate::unicode::UNICODE_VERSION; + + /// Creates an iterator over the UTF-16 encoded code points in `iter`, + /// returning unpaired surrogates as `Err`s. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // 𝄞music + /// let v = [ + /// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834, + /// ]; + /// + /// assert_eq!( + /// char::decode_utf16(v) + /// .map(|r| r.map_err(|e| e.unpaired_surrogate())) + /// .collect::>(), + /// vec![ + /// Ok('𝄞'), + /// Ok('m'), Ok('u'), Ok('s'), + /// Err(0xDD1E), + /// Ok('i'), Ok('c'), + /// Err(0xD834) + /// ] + /// ); + /// ``` + /// + /// A lossy decoder can be obtained by replacing `Err` results with the replacement character: + /// + /// ``` + /// // 𝄞music + /// let v = [ + /// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834, + /// ]; + /// + /// assert_eq!( + /// char::decode_utf16(v) + /// .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)) + /// .collect::(), + /// "𝄞mus�ic�" + /// ); + /// ``` + #[stable(feature = "assoc_char_funcs", since = "1.52.0")] + #[inline] + pub fn decode_utf16>(iter: I) -> DecodeUtf16 { + super::decode::decode_utf16(iter) + } + + /// Converts a `u32` to a `char`. + /// + /// Note that all `char`s are valid [`u32`]s, and can be cast to one with + /// [`as`](../std/keyword.as.html): + /// + /// ``` + /// let c = '💯'; + /// let i = c as u32; + /// + /// assert_eq!(128175, i); + /// ``` + /// + /// However, the reverse is not true: not all valid [`u32`]s are valid + /// `char`s. `from_u32()` will return `None` if the input is not a valid value + /// for a `char`. + /// + /// For an unsafe version of this function which ignores these checks, see + /// [`from_u32_unchecked`]. + /// + /// [`from_u32_unchecked`]: #method.from_u32_unchecked + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let c = char::from_u32(0x2764); + /// + /// assert_eq!(Some('❤'), c); + /// ``` + /// + /// Returning `None` when the input is not a valid `char`: + /// + /// ``` + /// let c = char::from_u32(0x110000); + /// + /// assert_eq!(None, c); + /// ``` + #[stable(feature = "assoc_char_funcs", since = "1.52.0")] + #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] + #[must_use] + #[inline] + pub const fn from_u32(i: u32) -> Option { + super::convert::from_u32(i) + } + + /// Converts a `u32` to a `char`, ignoring validity. + /// + /// Note that all `char`s are valid [`u32`]s, and can be cast to one with + /// `as`: + /// + /// ``` + /// let c = '💯'; + /// let i = c as u32; + /// + /// assert_eq!(128175, i); + /// ``` + /// + /// However, the reverse is not true: not all valid [`u32`]s are valid + /// `char`s. `from_u32_unchecked()` will ignore this, and blindly cast to + /// `char`, possibly creating an invalid one. + /// + /// # Safety + /// + /// This function is unsafe, as it may construct invalid `char` values. + /// + /// For a safe version of this function, see the [`from_u32`] function. + /// + /// [`from_u32`]: #method.from_u32 + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let c = unsafe { char::from_u32_unchecked(0x2764) }; + /// + /// assert_eq!('❤', c); + /// ``` + #[stable(feature = "assoc_char_funcs", since = "1.52.0")] + #[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")] + #[must_use] + #[inline] + pub const unsafe fn from_u32_unchecked(i: u32) -> char { + // SAFETY: the safety contract must be upheld by the caller. + unsafe { super::convert::from_u32_unchecked(i) } + } + + /// Converts a digit in the given radix to a `char`. + /// + /// A 'radix' here is sometimes also called a 'base'. A radix of two + /// indicates a binary number, a radix of ten, decimal, and a radix of + /// sixteen, hexadecimal, to give some common values. Arbitrary + /// radices are supported. + /// + /// `from_digit()` will return `None` if the input is not a digit in + /// the given radix. + /// + /// # Panics + /// + /// Panics if given a radix larger than 36. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let c = char::from_digit(4, 10); + /// + /// assert_eq!(Some('4'), c); + /// + /// // Decimal 11 is a single digit in base 16 + /// let c = char::from_digit(11, 16); + /// + /// assert_eq!(Some('b'), c); + /// ``` + /// + /// Returning `None` when the input is not a digit: + /// + /// ``` + /// let c = char::from_digit(20, 10); + /// + /// assert_eq!(None, c); + /// ``` + /// + /// Passing a large radix, causing a panic: + /// + /// ```should_panic + /// // this panics + /// let _c = char::from_digit(1, 37); + /// ``` + #[stable(feature = "assoc_char_funcs", since = "1.52.0")] + #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] + #[must_use] + #[inline] + pub const fn from_digit(num: u32, radix: u32) -> Option { + super::convert::from_digit(num, radix) + } + + /// Checks if a `char` is a digit in the given radix. + /// + /// A 'radix' here is sometimes also called a 'base'. A radix of two + /// indicates a binary number, a radix of ten, decimal, and a radix of + /// sixteen, hexadecimal, to give some common values. Arbitrary + /// radices are supported. + /// + /// Compared to [`is_numeric()`], this function only recognizes the characters + /// `0-9`, `a-z` and `A-Z`. + /// + /// 'Digit' is defined to be only the following characters: + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// For a more comprehensive understanding of 'digit', see [`is_numeric()`]. + /// + /// [`is_numeric()`]: #method.is_numeric + /// + /// # Panics + /// + /// Panics if given a radix smaller than 2 or larger than 36. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!('1'.is_digit(10)); + /// assert!('f'.is_digit(16)); + /// assert!(!'f'.is_digit(10)); + /// ``` + /// + /// Passing a large radix, causing a panic: + /// + /// ```should_panic + /// // this panics + /// '1'.is_digit(37); + /// ``` + /// + /// Passing a small radix, causing a panic: + /// + /// ```should_panic + /// // this panics + /// '1'.is_digit(1); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_char_classify", issue = "132241")] + #[inline] + pub const fn is_digit(self, radix: u32) -> bool { + self.to_digit(radix).is_some() + } + + /// Converts a `char` to a digit in the given radix. + /// + /// A 'radix' here is sometimes also called a 'base'. A radix of two + /// indicates a binary number, a radix of ten, decimal, and a radix of + /// sixteen, hexadecimal, to give some common values. Arbitrary + /// radices are supported. + /// + /// 'Digit' is defined to be only the following characters: + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Errors + /// + /// Returns `None` if the `char` does not refer to a digit in the given radix. + /// + /// # Panics + /// + /// Panics if given a radix smaller than 2 or larger than 36. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!('1'.to_digit(10), Some(1)); + /// assert_eq!('f'.to_digit(16), Some(15)); + /// ``` + /// + /// Passing a non-digit results in failure: + /// + /// ``` + /// assert_eq!('f'.to_digit(10), None); + /// assert_eq!('z'.to_digit(16), None); + /// ``` + /// + /// Passing a large radix, causing a panic: + /// + /// ```should_panic + /// // this panics + /// let _ = '1'.to_digit(37); + /// ``` + /// Passing a small radix, causing a panic: + /// + /// ```should_panic + /// // this panics + /// let _ = '1'.to_digit(1); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_digit(self, radix: u32) -> Option { + assert!( + radix >= 2 && radix <= 36, + "to_digit: invalid radix -- radix must be in the range 2 to 36 inclusive" + ); + // check radix to remove letter handling code when radix is a known constant + let value = if self > '9' && radix > 10 { + // convert ASCII letters to lowercase + let lower = self as u32 | 0x20; + // convert an ASCII letter to the corresponding value, + // non-letters convert to values > 36 + lower.wrapping_sub('a' as u32) as u64 + 10 + } else { + // convert digit to value, non-digits wrap to values > 36 + (self as u32).wrapping_sub('0' as u32) as u64 + }; + // FIXME(const-hack): once then_some is const fn, use it here + if value < radix as u64 { Some(value as u32) } else { None } + } + + /// Returns an iterator that yields the hexadecimal Unicode escape of a + /// character as `char`s. + /// + /// This will escape characters with the Rust syntax of the form + /// `\u{NNNNNN}` where `NNNNNN` is a hexadecimal representation. + /// + /// # Examples + /// + /// As an iterator: + /// + /// ``` + /// for c in '❤'.escape_unicode() { + /// print!("{c}"); + /// } + /// println!(); + /// ``` + /// + /// Using `println!` directly: + /// + /// ``` + /// println!("{}", '❤'.escape_unicode()); + /// ``` + /// + /// Both are equivalent to: + /// + /// ``` + /// println!("\\u{{2764}}"); + /// ``` + /// + /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string): + /// + /// ``` + /// assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}"); + /// ``` + #[must_use = "this returns the escaped char as an iterator, \ + without modifying the original"] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn escape_unicode(self) -> EscapeUnicode { + EscapeUnicode::new(self) + } + + /// An extended version of `escape_debug` that optionally permits escaping + /// Extended Grapheme codepoints, single quotes, and double quotes. This + /// allows us to format characters like nonspacing marks better when they're + /// at the start of a string, and allows escaping single quotes in + /// characters, and double quotes in strings. + #[inline] + pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug { + match self { + '\0' => EscapeDebug::backslash(ascii::Char::Digit0), + '\t' => EscapeDebug::backslash(ascii::Char::SmallT), + '\r' => EscapeDebug::backslash(ascii::Char::SmallR), + '\n' => EscapeDebug::backslash(ascii::Char::SmallN), + '\\' => EscapeDebug::backslash(ascii::Char::ReverseSolidus), + '\"' if args.escape_double_quote => EscapeDebug::backslash(ascii::Char::QuotationMark), + '\'' if args.escape_single_quote => EscapeDebug::backslash(ascii::Char::Apostrophe), + _ if args.escape_grapheme_extended && self.is_grapheme_extended() => { + EscapeDebug::unicode(self) + } + _ if is_printable(self) => EscapeDebug::printable(self), + _ => EscapeDebug::unicode(self), + } + } + + /// Returns an iterator that yields the literal escape code of a character + /// as `char`s. + /// + /// This will escape the characters similar to the [`Debug`](core::fmt::Debug) implementations + /// of `str` or `char`. + /// + /// # Examples + /// + /// As an iterator: + /// + /// ``` + /// for c in '\n'.escape_debug() { + /// print!("{c}"); + /// } + /// println!(); + /// ``` + /// + /// Using `println!` directly: + /// + /// ``` + /// println!("{}", '\n'.escape_debug()); + /// ``` + /// + /// Both are equivalent to: + /// + /// ``` + /// println!("\\n"); + /// ``` + /// + /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string): + /// + /// ``` + /// assert_eq!('\n'.escape_debug().to_string(), "\\n"); + /// ``` + #[must_use = "this returns the escaped char as an iterator, \ + without modifying the original"] + #[stable(feature = "char_escape_debug", since = "1.20.0")] + #[inline] + pub fn escape_debug(self) -> EscapeDebug { + self.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL) + } + + /// Returns an iterator that yields the literal escape code of a character + /// as `char`s. + /// + /// The default is chosen with a bias toward producing literals that are + /// legal in a variety of languages, including C++11 and similar C-family + /// languages. The exact rules are: + /// + /// * Tab is escaped as `\t`. + /// * Carriage return is escaped as `\r`. + /// * Line feed is escaped as `\n`. + /// * Single quote is escaped as `\'`. + /// * Double quote is escaped as `\"`. + /// * Backslash is escaped as `\\`. + /// * Any character in the 'printable ASCII' range `0x20` .. `0x7e` + /// inclusive is not escaped. + /// * All other characters are given hexadecimal Unicode escapes; see + /// [`escape_unicode`]. + /// + /// [`escape_unicode`]: #method.escape_unicode + /// + /// # Examples + /// + /// As an iterator: + /// + /// ``` + /// for c in '"'.escape_default() { + /// print!("{c}"); + /// } + /// println!(); + /// ``` + /// + /// Using `println!` directly: + /// + /// ``` + /// println!("{}", '"'.escape_default()); + /// ``` + /// + /// Both are equivalent to: + /// + /// ``` + /// println!("\\\""); + /// ``` + /// + /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string): + /// + /// ``` + /// assert_eq!('"'.escape_default().to_string(), "\\\""); + /// ``` + #[must_use = "this returns the escaped char as an iterator, \ + without modifying the original"] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn escape_default(self) -> EscapeDefault { + match self { + '\t' => EscapeDefault::backslash(ascii::Char::SmallT), + '\r' => EscapeDefault::backslash(ascii::Char::SmallR), + '\n' => EscapeDefault::backslash(ascii::Char::SmallN), + '\\' | '\'' | '\"' => EscapeDefault::backslash(self.as_ascii().unwrap()), + '\x20'..='\x7e' => EscapeDefault::printable(self.as_ascii().unwrap()), + _ => EscapeDefault::unicode(self), + } + } + + /// Returns the number of bytes this `char` would need if encoded in UTF-8. + /// + /// That number of bytes is always between 1 and 4, inclusive. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let len = 'A'.len_utf8(); + /// assert_eq!(len, 1); + /// + /// let len = 'ß'.len_utf8(); + /// assert_eq!(len, 2); + /// + /// let len = 'ℝ'.len_utf8(); + /// assert_eq!(len, 3); + /// + /// let len = '💣'.len_utf8(); + /// assert_eq!(len, 4); + /// ``` + /// + /// The `&str` type guarantees that its contents are UTF-8, and so we can compare the length it + /// would take if each code point was represented as a `char` vs in the `&str` itself: + /// + /// ``` + /// // as chars + /// let eastern = '東'; + /// let capital = '京'; + /// + /// // both can be represented as three bytes + /// assert_eq!(3, eastern.len_utf8()); + /// assert_eq!(3, capital.len_utf8()); + /// + /// // as a &str, these two are encoded in UTF-8 + /// let tokyo = "東京"; + /// + /// let len = eastern.len_utf8() + capital.len_utf8(); + /// + /// // we can see that they take six bytes total... + /// assert_eq!(6, tokyo.len()); + /// + /// // ... just like the &str + /// assert_eq!(len, tokyo.len()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_char_len_utf", since = "1.52.0")] + #[inline] + #[must_use] + pub const fn len_utf8(self) -> usize { + len_utf8(self as u32) + } + + /// Returns the number of 16-bit code units this `char` would need if + /// encoded in UTF-16. + /// + /// That number of code units is always either 1 or 2, for unicode scalar values in + /// the [basic multilingual plane] or [supplementary planes] respectively. + /// + /// See the documentation for [`len_utf8()`] for more explanation of this + /// concept. This function is a mirror, but for UTF-16 instead of UTF-8. + /// + /// [basic multilingual plane]: http://www.unicode.org/glossary/#basic_multilingual_plane + /// [supplementary planes]: http://www.unicode.org/glossary/#supplementary_planes + /// [`len_utf8()`]: #method.len_utf8 + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let n = 'ß'.len_utf16(); + /// assert_eq!(n, 1); + /// + /// let len = '💣'.len_utf16(); + /// assert_eq!(len, 2); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_char_len_utf", since = "1.52.0")] + #[inline] + #[must_use] + pub const fn len_utf16(self) -> usize { + len_utf16(self as u32) + } + + /// Encodes this character as UTF-8 into the provided byte buffer, + /// and then returns the subslice of the buffer that contains the encoded character. + /// + /// # Panics + /// + /// Panics if the buffer is not large enough. + /// A buffer of length four is large enough to encode any `char`. + /// + /// # Examples + /// + /// In both of these examples, 'ß' takes two bytes to encode. + /// + /// ``` + /// let mut b = [0; 2]; + /// + /// let result = 'ß'.encode_utf8(&mut b); + /// + /// assert_eq!(result, "ß"); + /// + /// assert_eq!(result.len(), 2); + /// ``` + /// + /// A buffer that's too small: + /// + /// ```should_panic + /// let mut b = [0; 1]; + /// + /// // this panics + /// 'ß'.encode_utf8(&mut b); + /// ``` + #[stable(feature = "unicode_encode_char", since = "1.15.0")] + #[rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0")] + #[inline] + pub const fn encode_utf8(self, dst: &mut [u8]) -> &mut str { + // SAFETY: `char` is not a surrogate, so this is valid UTF-8. + unsafe { from_utf8_unchecked_mut(encode_utf8_raw(self as u32, dst)) } + } + + /// Encodes this character as UTF-16 into the provided `u16` buffer, + /// and then returns the subslice of the buffer that contains the encoded character. + /// + /// # Panics + /// + /// Panics if the buffer is not large enough. + /// A buffer of length 2 is large enough to encode any `char`. + /// + /// # Examples + /// + /// In both of these examples, '𝕊' takes two `u16`s to encode. + /// + /// ``` + /// let mut b = [0; 2]; + /// + /// let result = '𝕊'.encode_utf16(&mut b); + /// + /// assert_eq!(result.len(), 2); + /// ``` + /// + /// A buffer that's too small: + /// + /// ```should_panic + /// let mut b = [0; 1]; + /// + /// // this panics + /// '𝕊'.encode_utf16(&mut b); + /// ``` + #[stable(feature = "unicode_encode_char", since = "1.15.0")] + #[rustc_const_stable(feature = "const_char_encode_utf16", since = "1.84.0")] + #[inline] + pub const fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] { + encode_utf16_raw(self as u32, dst) + } + + /// Returns `true` if this `char` has the `Alphabetic` property. + /// + /// `Alphabetic` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and + /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!('a'.is_alphabetic()); + /// assert!('京'.is_alphabetic()); + /// + /// let c = '💝'; + /// // love is many things, but it is not alphabetic + /// assert!(!c.is_alphabetic()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_alphabetic(self) -> bool { + match self { + 'a'..='z' | 'A'..='Z' => true, + c => c > '\x7f' && unicode::Alphabetic(c), + } + } + + /// Returns `true` if this `char` has the `Lowercase` property. + /// + /// `Lowercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and + /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!('a'.is_lowercase()); + /// assert!('δ'.is_lowercase()); + /// assert!(!'A'.is_lowercase()); + /// assert!(!'Δ'.is_lowercase()); + /// + /// // The various Chinese scripts and punctuation do not have case, and so: + /// assert!(!'中'.is_lowercase()); + /// assert!(!' '.is_lowercase()); + /// ``` + /// + /// In a const context: + /// + /// ``` + /// const CAPITAL_DELTA_IS_LOWERCASE: bool = 'Δ'.is_lowercase(); + /// assert!(!CAPITAL_DELTA_IS_LOWERCASE); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0")] + #[inline] + pub const fn is_lowercase(self) -> bool { + match self { + 'a'..='z' => true, + c => c > '\x7f' && unicode::Lowercase(c), + } + } + + /// Returns `true` if this `char` has the `Uppercase` property. + /// + /// `Uppercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and + /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!(!'a'.is_uppercase()); + /// assert!(!'δ'.is_uppercase()); + /// assert!('A'.is_uppercase()); + /// assert!('Δ'.is_uppercase()); + /// + /// // The various Chinese scripts and punctuation do not have case, and so: + /// assert!(!'中'.is_uppercase()); + /// assert!(!' '.is_uppercase()); + /// ``` + /// + /// In a const context: + /// + /// ``` + /// const CAPITAL_DELTA_IS_UPPERCASE: bool = 'Δ'.is_uppercase(); + /// assert!(CAPITAL_DELTA_IS_UPPERCASE); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0")] + #[inline] + pub const fn is_uppercase(self) -> bool { + match self { + 'A'..='Z' => true, + c => c > '\x7f' && unicode::Uppercase(c), + } + } + + /// Returns `true` if this `char` has the `White_Space` property. + /// + /// `White_Space` is specified in the [Unicode Character Database][ucd] [`PropList.txt`]. + /// + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`PropList.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!(' '.is_whitespace()); + /// + /// // line break + /// assert!('\n'.is_whitespace()); + /// + /// // a non-breaking space + /// assert!('\u{A0}'.is_whitespace()); + /// + /// assert!(!'越'.is_whitespace()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_char_classify", issue = "132241")] + #[inline] + pub const fn is_whitespace(self) -> bool { + match self { + ' ' | '\x09'..='\x0d' => true, + c => c > '\x7f' && unicode::White_Space(c), + } + } + + /// Returns `true` if this `char` satisfies either [`is_alphabetic()`] or [`is_numeric()`]. + /// + /// [`is_alphabetic()`]: #method.is_alphabetic + /// [`is_numeric()`]: #method.is_numeric + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!('٣'.is_alphanumeric()); + /// assert!('7'.is_alphanumeric()); + /// assert!('৬'.is_alphanumeric()); + /// assert!('¾'.is_alphanumeric()); + /// assert!('①'.is_alphanumeric()); + /// assert!('K'.is_alphanumeric()); + /// assert!('و'.is_alphanumeric()); + /// assert!('藏'.is_alphanumeric()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_alphanumeric(self) -> bool { + self.is_alphabetic() || self.is_numeric() + } + + /// Returns `true` if this `char` has the general category for control codes. + /// + /// Control codes (code points with the general category of `Cc`) are described in Chapter 4 + /// (Character Properties) of the [Unicode Standard] and specified in the [Unicode Character + /// Database][ucd] [`UnicodeData.txt`]. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // U+009C, STRING TERMINATOR + /// assert!('œ'.is_control()); + /// assert!(!'q'.is_control()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_control(self) -> bool { + unicode::Cc(self) + } + + /// Returns `true` if this `char` has the `Grapheme_Extend` property. + /// + /// `Grapheme_Extend` is described in [Unicode Standard Annex #29 (Unicode Text + /// Segmentation)][uax29] and specified in the [Unicode Character Database][ucd] + /// [`DerivedCoreProperties.txt`]. + /// + /// [uax29]: https://www.unicode.org/reports/tr29/ + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt + #[must_use] + #[inline] + pub(crate) fn is_grapheme_extended(self) -> bool { + unicode::Grapheme_Extend(self) + } + + /// Returns `true` if this `char` has one of the general categories for numbers. + /// + /// The general categories for numbers (`Nd` for decimal digits, `Nl` for letter-like numeric + /// characters, and `No` for other numeric characters) are specified in the [Unicode Character + /// Database][ucd] [`UnicodeData.txt`]. + /// + /// This method doesn't cover everything that could be considered a number, e.g. ideographic numbers like '三'. + /// If you want everything including characters with overlapping purposes then you might want to use + /// a unicode or language-processing library that exposes the appropriate character properties instead + /// of looking at the unicode categories. + /// + /// If you want to parse ASCII decimal digits (0-9) or ASCII base-N, use + /// `is_ascii_digit` or `is_digit` instead. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!('٣'.is_numeric()); + /// assert!('7'.is_numeric()); + /// assert!('৬'.is_numeric()); + /// assert!('¾'.is_numeric()); + /// assert!('①'.is_numeric()); + /// assert!(!'K'.is_numeric()); + /// assert!(!'و'.is_numeric()); + /// assert!(!'藏'.is_numeric()); + /// assert!(!'三'.is_numeric()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_numeric(self) -> bool { + match self { + '0'..='9' => true, + c => c > '\x7f' && unicode::N(c), + } + } + + /// Returns an iterator that yields the lowercase mapping of this `char` as one or more + /// `char`s. + /// + /// If this `char` does not have a lowercase mapping, the iterator yields the same `char`. + /// + /// If this `char` has a one-to-one lowercase mapping given by the [Unicode Character + /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`. + /// + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + /// + /// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields + /// the `char`(s) given by [`SpecialCasing.txt`]. + /// + /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt + /// + /// This operation performs an unconditional mapping without tailoring. That is, the conversion + /// is independent of context and language. + /// + /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in + /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// + /// # Examples + /// + /// As an iterator: + /// + /// ``` + /// for c in 'İ'.to_lowercase() { + /// print!("{c}"); + /// } + /// println!(); + /// ``` + /// + /// Using `println!` directly: + /// + /// ``` + /// println!("{}", 'İ'.to_lowercase()); + /// ``` + /// + /// Both are equivalent to: + /// + /// ``` + /// println!("i\u{307}"); + /// ``` + /// + /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string): + /// + /// ``` + /// assert_eq!('C'.to_lowercase().to_string(), "c"); + /// + /// // Sometimes the result is more than one character: + /// assert_eq!('İ'.to_lowercase().to_string(), "i\u{307}"); + /// + /// // Characters that do not have both uppercase and lowercase + /// // convert into themselves. + /// assert_eq!('山'.to_lowercase().to_string(), "山"); + /// ``` + #[must_use = "this returns the lowercase character as a new iterator, \ + without modifying the original"] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_lowercase(self) -> ToLowercase { + ToLowercase(CaseMappingIter::new(conversions::to_lower(self))) + } + + /// Returns an iterator that yields the uppercase mapping of this `char` as one or more + /// `char`s. + /// + /// If this `char` does not have an uppercase mapping, the iterator yields the same `char`. + /// + /// If this `char` has a one-to-one uppercase mapping given by the [Unicode Character + /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`. + /// + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + /// + /// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields + /// the `char`(s) given by [`SpecialCasing.txt`]. + /// + /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt + /// + /// This operation performs an unconditional mapping without tailoring. That is, the conversion + /// is independent of context and language. + /// + /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in + /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// + /// # Examples + /// + /// As an iterator: + /// + /// ``` + /// for c in 'ß'.to_uppercase() { + /// print!("{c}"); + /// } + /// println!(); + /// ``` + /// + /// Using `println!` directly: + /// + /// ``` + /// println!("{}", 'ß'.to_uppercase()); + /// ``` + /// + /// Both are equivalent to: + /// + /// ``` + /// println!("SS"); + /// ``` + /// + /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string): + /// + /// ``` + /// assert_eq!('c'.to_uppercase().to_string(), "C"); + /// + /// // Sometimes the result is more than one character: + /// assert_eq!('ß'.to_uppercase().to_string(), "SS"); + /// + /// // Characters that do not have both uppercase and lowercase + /// // convert into themselves. + /// assert_eq!('山'.to_uppercase().to_string(), "山"); + /// ``` + /// + /// # Note on locale + /// + /// In Turkish, the equivalent of 'i' in Latin has five forms instead of two: + /// + /// * 'Dotless': I / ı, sometimes written ï + /// * 'Dotted': İ / i + /// + /// Note that the lowercase dotted 'i' is the same as the Latin. Therefore: + /// + /// ``` + /// let upper_i = 'i'.to_uppercase().to_string(); + /// ``` + /// + /// The value of `upper_i` here relies on the language of the text: if we're + /// in `en-US`, it should be `"I"`, but if we're in `tr_TR`, it should + /// be `"İ"`. `to_uppercase()` does not take this into account, and so: + /// + /// ``` + /// let upper_i = 'i'.to_uppercase().to_string(); + /// + /// assert_eq!(upper_i, "I"); + /// ``` + /// + /// holds across languages. + #[must_use = "this returns the uppercase character as a new iterator, \ + without modifying the original"] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_uppercase(self) -> ToUppercase { + ToUppercase(CaseMappingIter::new(conversions::to_upper(self))) + } + + /// Checks if the value is within the ASCII range. + /// + /// # Examples + /// + /// ``` + /// let ascii = 'a'; + /// let non_ascii = '❤'; + /// + /// assert!(ascii.is_ascii()); + /// assert!(!non_ascii.is_ascii()); + /// ``` + #[must_use] + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_char_is_ascii", since = "1.32.0")] + #[inline] + pub const fn is_ascii(&self) -> bool { + *self as u32 <= 0x7F + } + + /// Returns `Some` if the value is within the ASCII range, + /// or `None` if it's not. + /// + /// This is preferred to [`Self::is_ascii`] when you're passing the value + /// along to something else that can take [`ascii::Char`] rather than + /// needing to check again for itself whether the value is in ASCII. + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_ascii(&self) -> Option { + if self.is_ascii() { + // SAFETY: Just checked that this is ASCII. + Some(unsafe { ascii::Char::from_u8_unchecked(*self as u8) }) + } else { + None + } + } + + /// Makes a copy of the value in its ASCII upper case equivalent. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To uppercase the value in-place, use [`make_ascii_uppercase()`]. + /// + /// To uppercase ASCII characters in addition to non-ASCII characters, use + /// [`to_uppercase()`]. + /// + /// # Examples + /// + /// ``` + /// let ascii = 'a'; + /// let non_ascii = '❤'; + /// + /// assert_eq!('A', ascii.to_ascii_uppercase()); + /// assert_eq!('❤', non_ascii.to_ascii_uppercase()); + /// ``` + /// + /// [`make_ascii_uppercase()`]: #method.make_ascii_uppercase + /// [`to_uppercase()`]: #method.to_uppercase + #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"] + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] + #[inline] + pub const fn to_ascii_uppercase(&self) -> char { + if self.is_ascii_lowercase() { + (*self as u8).ascii_change_case_unchecked() as char + } else { + *self + } + } + + /// Makes a copy of the value in its ASCII lower case equivalent. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To lowercase the value in-place, use [`make_ascii_lowercase()`]. + /// + /// To lowercase ASCII characters in addition to non-ASCII characters, use + /// [`to_lowercase()`]. + /// + /// # Examples + /// + /// ``` + /// let ascii = 'A'; + /// let non_ascii = '❤'; + /// + /// assert_eq!('a', ascii.to_ascii_lowercase()); + /// assert_eq!('❤', non_ascii.to_ascii_lowercase()); + /// ``` + /// + /// [`make_ascii_lowercase()`]: #method.make_ascii_lowercase + /// [`to_lowercase()`]: #method.to_lowercase + #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"] + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] + #[inline] + pub const fn to_ascii_lowercase(&self) -> char { + if self.is_ascii_uppercase() { + (*self as u8).ascii_change_case_unchecked() as char + } else { + *self + } + } + + /// Checks that two values are an ASCII case-insensitive match. + /// + /// Equivalent to [to_ascii_lowercase]\(a) == [to_ascii_lowercase]\(b). + /// + /// # Examples + /// + /// ``` + /// let upper_a = 'A'; + /// let lower_a = 'a'; + /// let lower_z = 'z'; + /// + /// assert!(upper_a.eq_ignore_ascii_case(&lower_a)); + /// assert!(upper_a.eq_ignore_ascii_case(&upper_a)); + /// assert!(!upper_a.eq_ignore_ascii_case(&lower_z)); + /// ``` + /// + /// [to_ascii_lowercase]: #method.to_ascii_lowercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] + #[inline] + pub const fn eq_ignore_ascii_case(&self, other: &char) -> bool { + self.to_ascii_lowercase() == other.to_ascii_lowercase() + } + + /// Converts this type to its ASCII upper case equivalent in-place. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new uppercased value without modifying the existing one, use + /// [`to_ascii_uppercase()`]. + /// + /// # Examples + /// + /// ``` + /// let mut ascii = 'a'; + /// + /// ascii.make_ascii_uppercase(); + /// + /// assert_eq!('A', ascii); + /// ``` + /// + /// [`to_ascii_uppercase()`]: #method.to_ascii_uppercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] + #[inline] + pub const fn make_ascii_uppercase(&mut self) { + *self = self.to_ascii_uppercase(); + } + + /// Converts this type to its ASCII lower case equivalent in-place. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new lowercased value without modifying the existing one, use + /// [`to_ascii_lowercase()`]. + /// + /// # Examples + /// + /// ``` + /// let mut ascii = 'A'; + /// + /// ascii.make_ascii_lowercase(); + /// + /// assert_eq!('a', ascii); + /// ``` + /// + /// [`to_ascii_lowercase()`]: #method.to_ascii_lowercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] + #[inline] + pub const fn make_ascii_lowercase(&mut self) { + *self = self.to_ascii_lowercase(); + } + + /// Checks if the value is an ASCII alphabetic character: + /// + /// - U+0041 'A' ..= U+005A 'Z', or + /// - U+0061 'a' ..= U+007A 'z'. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = 'A'; + /// let uppercase_g = 'G'; + /// let a = 'a'; + /// let g = 'g'; + /// let zero = '0'; + /// let percent = '%'; + /// let space = ' '; + /// let lf = '\n'; + /// let esc = '\x1b'; + /// + /// assert!(uppercase_a.is_ascii_alphabetic()); + /// assert!(uppercase_g.is_ascii_alphabetic()); + /// assert!(a.is_ascii_alphabetic()); + /// assert!(g.is_ascii_alphabetic()); + /// assert!(!zero.is_ascii_alphabetic()); + /// assert!(!percent.is_ascii_alphabetic()); + /// assert!(!space.is_ascii_alphabetic()); + /// assert!(!lf.is_ascii_alphabetic()); + /// assert!(!esc.is_ascii_alphabetic()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_alphabetic(&self) -> bool { + matches!(*self, 'A'..='Z' | 'a'..='z') + } + + /// Checks if the value is an ASCII uppercase character: + /// U+0041 'A' ..= U+005A 'Z'. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = 'A'; + /// let uppercase_g = 'G'; + /// let a = 'a'; + /// let g = 'g'; + /// let zero = '0'; + /// let percent = '%'; + /// let space = ' '; + /// let lf = '\n'; + /// let esc = '\x1b'; + /// + /// assert!(uppercase_a.is_ascii_uppercase()); + /// assert!(uppercase_g.is_ascii_uppercase()); + /// assert!(!a.is_ascii_uppercase()); + /// assert!(!g.is_ascii_uppercase()); + /// assert!(!zero.is_ascii_uppercase()); + /// assert!(!percent.is_ascii_uppercase()); + /// assert!(!space.is_ascii_uppercase()); + /// assert!(!lf.is_ascii_uppercase()); + /// assert!(!esc.is_ascii_uppercase()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_uppercase(&self) -> bool { + matches!(*self, 'A'..='Z') + } + + /// Checks if the value is an ASCII lowercase character: + /// U+0061 'a' ..= U+007A 'z'. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = 'A'; + /// let uppercase_g = 'G'; + /// let a = 'a'; + /// let g = 'g'; + /// let zero = '0'; + /// let percent = '%'; + /// let space = ' '; + /// let lf = '\n'; + /// let esc = '\x1b'; + /// + /// assert!(!uppercase_a.is_ascii_lowercase()); + /// assert!(!uppercase_g.is_ascii_lowercase()); + /// assert!(a.is_ascii_lowercase()); + /// assert!(g.is_ascii_lowercase()); + /// assert!(!zero.is_ascii_lowercase()); + /// assert!(!percent.is_ascii_lowercase()); + /// assert!(!space.is_ascii_lowercase()); + /// assert!(!lf.is_ascii_lowercase()); + /// assert!(!esc.is_ascii_lowercase()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_lowercase(&self) -> bool { + matches!(*self, 'a'..='z') + } + + /// Checks if the value is an ASCII alphanumeric character: + /// + /// - U+0041 'A' ..= U+005A 'Z', or + /// - U+0061 'a' ..= U+007A 'z', or + /// - U+0030 '0' ..= U+0039 '9'. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = 'A'; + /// let uppercase_g = 'G'; + /// let a = 'a'; + /// let g = 'g'; + /// let zero = '0'; + /// let percent = '%'; + /// let space = ' '; + /// let lf = '\n'; + /// let esc = '\x1b'; + /// + /// assert!(uppercase_a.is_ascii_alphanumeric()); + /// assert!(uppercase_g.is_ascii_alphanumeric()); + /// assert!(a.is_ascii_alphanumeric()); + /// assert!(g.is_ascii_alphanumeric()); + /// assert!(zero.is_ascii_alphanumeric()); + /// assert!(!percent.is_ascii_alphanumeric()); + /// assert!(!space.is_ascii_alphanumeric()); + /// assert!(!lf.is_ascii_alphanumeric()); + /// assert!(!esc.is_ascii_alphanumeric()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_alphanumeric(&self) -> bool { + matches!(*self, '0'..='9') | matches!(*self, 'A'..='Z') | matches!(*self, 'a'..='z') + } + + /// Checks if the value is an ASCII decimal digit: + /// U+0030 '0' ..= U+0039 '9'. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = 'A'; + /// let uppercase_g = 'G'; + /// let a = 'a'; + /// let g = 'g'; + /// let zero = '0'; + /// let percent = '%'; + /// let space = ' '; + /// let lf = '\n'; + /// let esc = '\x1b'; + /// + /// assert!(!uppercase_a.is_ascii_digit()); + /// assert!(!uppercase_g.is_ascii_digit()); + /// assert!(!a.is_ascii_digit()); + /// assert!(!g.is_ascii_digit()); + /// assert!(zero.is_ascii_digit()); + /// assert!(!percent.is_ascii_digit()); + /// assert!(!space.is_ascii_digit()); + /// assert!(!lf.is_ascii_digit()); + /// assert!(!esc.is_ascii_digit()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_digit(&self) -> bool { + matches!(*self, '0'..='9') + } + + /// Checks if the value is an ASCII octal digit: + /// U+0030 '0' ..= U+0037 '7'. + /// + /// # Examples + /// + /// ``` + /// #![feature(is_ascii_octdigit)] + /// + /// let uppercase_a = 'A'; + /// let a = 'a'; + /// let zero = '0'; + /// let seven = '7'; + /// let nine = '9'; + /// let percent = '%'; + /// let lf = '\n'; + /// + /// assert!(!uppercase_a.is_ascii_octdigit()); + /// assert!(!a.is_ascii_octdigit()); + /// assert!(zero.is_ascii_octdigit()); + /// assert!(seven.is_ascii_octdigit()); + /// assert!(!nine.is_ascii_octdigit()); + /// assert!(!percent.is_ascii_octdigit()); + /// assert!(!lf.is_ascii_octdigit()); + /// ``` + #[must_use] + #[unstable(feature = "is_ascii_octdigit", issue = "101288")] + #[inline] + pub const fn is_ascii_octdigit(&self) -> bool { + matches!(*self, '0'..='7') + } + + /// Checks if the value is an ASCII hexadecimal digit: + /// + /// - U+0030 '0' ..= U+0039 '9', or + /// - U+0041 'A' ..= U+0046 'F', or + /// - U+0061 'a' ..= U+0066 'f'. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = 'A'; + /// let uppercase_g = 'G'; + /// let a = 'a'; + /// let g = 'g'; + /// let zero = '0'; + /// let percent = '%'; + /// let space = ' '; + /// let lf = '\n'; + /// let esc = '\x1b'; + /// + /// assert!(uppercase_a.is_ascii_hexdigit()); + /// assert!(!uppercase_g.is_ascii_hexdigit()); + /// assert!(a.is_ascii_hexdigit()); + /// assert!(!g.is_ascii_hexdigit()); + /// assert!(zero.is_ascii_hexdigit()); + /// assert!(!percent.is_ascii_hexdigit()); + /// assert!(!space.is_ascii_hexdigit()); + /// assert!(!lf.is_ascii_hexdigit()); + /// assert!(!esc.is_ascii_hexdigit()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_hexdigit(&self) -> bool { + matches!(*self, '0'..='9') | matches!(*self, 'A'..='F') | matches!(*self, 'a'..='f') + } + + /// Checks if the value is an ASCII punctuation character: + /// + /// - U+0021 ..= U+002F `! " # $ % & ' ( ) * + , - . /`, or + /// - U+003A ..= U+0040 `: ; < = > ? @`, or + /// - U+005B ..= U+0060 ``[ \ ] ^ _ ` ``, or + /// - U+007B ..= U+007E `{ | } ~` + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = 'A'; + /// let uppercase_g = 'G'; + /// let a = 'a'; + /// let g = 'g'; + /// let zero = '0'; + /// let percent = '%'; + /// let space = ' '; + /// let lf = '\n'; + /// let esc = '\x1b'; + /// + /// assert!(!uppercase_a.is_ascii_punctuation()); + /// assert!(!uppercase_g.is_ascii_punctuation()); + /// assert!(!a.is_ascii_punctuation()); + /// assert!(!g.is_ascii_punctuation()); + /// assert!(!zero.is_ascii_punctuation()); + /// assert!(percent.is_ascii_punctuation()); + /// assert!(!space.is_ascii_punctuation()); + /// assert!(!lf.is_ascii_punctuation()); + /// assert!(!esc.is_ascii_punctuation()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_punctuation(&self) -> bool { + matches!(*self, '!'..='/') + | matches!(*self, ':'..='@') + | matches!(*self, '['..='`') + | matches!(*self, '{'..='~') + } + + /// Checks if the value is an ASCII graphic character: + /// U+0021 '!' ..= U+007E '~'. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = 'A'; + /// let uppercase_g = 'G'; + /// let a = 'a'; + /// let g = 'g'; + /// let zero = '0'; + /// let percent = '%'; + /// let space = ' '; + /// let lf = '\n'; + /// let esc = '\x1b'; + /// + /// assert!(uppercase_a.is_ascii_graphic()); + /// assert!(uppercase_g.is_ascii_graphic()); + /// assert!(a.is_ascii_graphic()); + /// assert!(g.is_ascii_graphic()); + /// assert!(zero.is_ascii_graphic()); + /// assert!(percent.is_ascii_graphic()); + /// assert!(!space.is_ascii_graphic()); + /// assert!(!lf.is_ascii_graphic()); + /// assert!(!esc.is_ascii_graphic()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_graphic(&self) -> bool { + matches!(*self, '!'..='~') + } + + /// Checks if the value is an ASCII whitespace character: + /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED, + /// U+000C FORM FEED, or U+000D CARRIAGE RETURN. + /// + /// Rust uses the WhatWG Infra Standard's [definition of ASCII + /// whitespace][infra-aw]. There are several other definitions in + /// wide use. For instance, [the POSIX locale][pct] includes + /// U+000B VERTICAL TAB as well as all the above characters, + /// but—from the very same specification—[the default rule for + /// "field splitting" in the Bourne shell][bfs] considers *only* + /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace. + /// + /// If you are writing a program that will process an existing + /// file format, check what that format's definition of whitespace is + /// before using this function. + /// + /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace + /// [pct]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01 + /// [bfs]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = 'A'; + /// let uppercase_g = 'G'; + /// let a = 'a'; + /// let g = 'g'; + /// let zero = '0'; + /// let percent = '%'; + /// let space = ' '; + /// let lf = '\n'; + /// let esc = '\x1b'; + /// + /// assert!(!uppercase_a.is_ascii_whitespace()); + /// assert!(!uppercase_g.is_ascii_whitespace()); + /// assert!(!a.is_ascii_whitespace()); + /// assert!(!g.is_ascii_whitespace()); + /// assert!(!zero.is_ascii_whitespace()); + /// assert!(!percent.is_ascii_whitespace()); + /// assert!(space.is_ascii_whitespace()); + /// assert!(lf.is_ascii_whitespace()); + /// assert!(!esc.is_ascii_whitespace()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_whitespace(&self) -> bool { + matches!(*self, '\t' | '\n' | '\x0C' | '\r' | ' ') + } + + /// Checks if the value is an ASCII control character: + /// U+0000 NUL ..= U+001F UNIT SEPARATOR, or U+007F DELETE. + /// Note that most ASCII whitespace characters are control + /// characters, but SPACE is not. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = 'A'; + /// let uppercase_g = 'G'; + /// let a = 'a'; + /// let g = 'g'; + /// let zero = '0'; + /// let percent = '%'; + /// let space = ' '; + /// let lf = '\n'; + /// let esc = '\x1b'; + /// + /// assert!(!uppercase_a.is_ascii_control()); + /// assert!(!uppercase_g.is_ascii_control()); + /// assert!(!a.is_ascii_control()); + /// assert!(!g.is_ascii_control()); + /// assert!(!zero.is_ascii_control()); + /// assert!(!percent.is_ascii_control()); + /// assert!(!space.is_ascii_control()); + /// assert!(lf.is_ascii_control()); + /// assert!(esc.is_ascii_control()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_control(&self) -> bool { + matches!(*self, '\0'..='\x1F' | '\x7F') + } +} + +pub(crate) struct EscapeDebugExtArgs { + /// Escape Extended Grapheme codepoints? + pub(crate) escape_grapheme_extended: bool, + + /// Escape single quotes? + pub(crate) escape_single_quote: bool, + + /// Escape double quotes? + pub(crate) escape_double_quote: bool, +} + +impl EscapeDebugExtArgs { + pub(crate) const ESCAPE_ALL: Self = Self { + escape_grapheme_extended: true, + escape_single_quote: true, + escape_double_quote: true, + }; +} + +#[inline] +#[must_use] +const fn len_utf8(code: u32) -> usize { + match code { + ..MAX_ONE_B => 1, + ..MAX_TWO_B => 2, + ..MAX_THREE_B => 3, + _ => 4, + } +} + +#[inline] +#[must_use] +const fn len_utf16(code: u32) -> usize { + if (code & 0xFFFF) == code { 1 } else { 2 } +} + +/// Encodes a raw `u32` value as UTF-8 into the provided byte buffer, +/// and then returns the subslice of the buffer that contains the encoded character. +/// +/// Unlike `char::encode_utf8`, this method also handles codepoints in the surrogate range. +/// (Creating a `char` in the surrogate range is UB.) +/// The result is valid [generalized UTF-8] but not valid UTF-8. +/// +/// [generalized UTF-8]: https://simonsapin.github.io/wtf-8/#generalized-utf8 +/// +/// # Panics +/// +/// Panics if the buffer is not large enough. +/// A buffer of length four is large enough to encode any `char`. +#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] +#[doc(hidden)] +#[inline] +pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { + let len = len_utf8(code); + match (len, &mut *dst) { + (1, [a, ..]) => { + *a = code as u8; + } + (2, [a, b, ..]) => { + *a = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; + *b = (code & 0x3F) as u8 | TAG_CONT; + } + (3, [a, b, c, ..]) => { + *a = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; + *b = (code >> 6 & 0x3F) as u8 | TAG_CONT; + *c = (code & 0x3F) as u8 | TAG_CONT; + } + (4, [a, b, c, d, ..]) => { + *a = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; + *b = (code >> 12 & 0x3F) as u8 | TAG_CONT; + *c = (code >> 6 & 0x3F) as u8 | TAG_CONT; + *d = (code & 0x3F) as u8 | TAG_CONT; + } + _ => { + const_panic!( + "encode_utf8: buffer does not have enough bytes to encode code point", + "encode_utf8: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}", + code: u32 = code, + len: usize = len, + dst_len: usize = dst.len(), + ) + } + }; + // SAFETY: `<&mut [u8]>::as_mut_ptr` is guaranteed to return a valid pointer and `len` has been tested to be within bounds. + unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr(), len) } +} + +/// Encodes a raw `u32` value as UTF-16 into the provided `u16` buffer, +/// and then returns the subslice of the buffer that contains the encoded character. +/// +/// Unlike `char::encode_utf16`, this method also handles codepoints in the surrogate range. +/// (Creating a `char` in the surrogate range is UB.) +/// +/// # Panics +/// +/// Panics if the buffer is not large enough. +/// A buffer of length 2 is large enough to encode any `char`. +#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] +#[doc(hidden)] +#[inline] +pub const fn encode_utf16_raw(mut code: u32, dst: &mut [u16]) -> &mut [u16] { + let len = len_utf16(code); + match (len, &mut *dst) { + (1, [a, ..]) => { + *a = code as u16; + } + (2, [a, b, ..]) => { + code -= 0x1_0000; + *a = (code >> 10) as u16 | 0xD800; + *b = (code & 0x3FF) as u16 | 0xDC00; + } + _ => { + const_panic!( + "encode_utf16: buffer does not have enough bytes to encode code point", + "encode_utf16: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}", + code: u32 = code, + len: usize = len, + dst_len: usize = dst.len(), + ) + } + }; + // SAFETY: `<&mut [u16]>::as_mut_ptr` is guaranteed to return a valid pointer and `len` has been tested to be within bounds. + unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr(), len) } +} diff --git a/CoqOfRust/core/char/mod.rs b/CoqOfRust/core/char/mod.rs new file mode 100644 index 000000000..59fd7250e --- /dev/null +++ b/CoqOfRust/core/char/mod.rs @@ -0,0 +1,619 @@ +//! Utilities for the `char` primitive type. +//! +//! *[See also the `char` primitive type](primitive@char).* +//! +//! The `char` type represents a single character. More specifically, since +//! 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode +//! scalar value]', which is similar to, but not the same as, a '[Unicode code +//! point]'. +//! +//! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value +//! [Unicode code point]: https://www.unicode.org/glossary/#code_point +//! +//! This module exists for technical reasons, the primary documentation for +//! `char` is directly on [the `char` primitive type][char] itself. +//! +//! This module is the home of the iterator implementations for the iterators +//! implemented on `char`, as well as some useful constants and conversion +//! functions that convert various types to `char`. + +#![allow(non_snake_case)] +#![stable(feature = "rust1", since = "1.0.0")] + +mod convert; +mod decode; +mod methods; + +// stable re-exports +#[rustfmt::skip] +#[stable(feature = "try_from", since = "1.34.0")] +pub use self::convert::CharTryFromError; +#[stable(feature = "char_from_str", since = "1.20.0")] +pub use self::convert::ParseCharError; +#[stable(feature = "decode_utf16", since = "1.9.0")] +pub use self::decode::{DecodeUtf16, DecodeUtf16Error}; + +// perma-unstable re-exports +#[rustfmt::skip] +#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] +pub use self::methods::encode_utf16_raw; // perma-unstable +#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] +pub use self::methods::encode_utf8_raw; // perma-unstable + +#[rustfmt::skip] +use crate::ascii; +pub(crate) use self::methods::EscapeDebugExtArgs; +use crate::error::Error; +use crate::escape; +use crate::fmt::{self, Write}; +use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; +use crate::num::NonZero; + +// UTF-8 ranges and tags for encoding characters +const TAG_CONT: u8 = 0b1000_0000; +const TAG_TWO_B: u8 = 0b1100_0000; +const TAG_THREE_B: u8 = 0b1110_0000; +const TAG_FOUR_B: u8 = 0b1111_0000; +const MAX_ONE_B: u32 = 0x80; +const MAX_TWO_B: u32 = 0x800; +const MAX_THREE_B: u32 = 0x10000; + +/* + Lu Uppercase_Letter an uppercase letter + Ll Lowercase_Letter a lowercase letter + Lt Titlecase_Letter a digraphic character, with first part uppercase + Lm Modifier_Letter a modifier letter + Lo Other_Letter other letters, including syllables and ideographs + Mn Nonspacing_Mark a nonspacing combining mark (zero advance width) + Mc Spacing_Mark a spacing combining mark (positive advance width) + Me Enclosing_Mark an enclosing combining mark + Nd Decimal_Number a decimal digit + Nl Letter_Number a letterlike numeric character + No Other_Number a numeric character of other type + Pc Connector_Punctuation a connecting punctuation mark, like a tie + Pd Dash_Punctuation a dash or hyphen punctuation mark + Ps Open_Punctuation an opening punctuation mark (of a pair) + Pe Close_Punctuation a closing punctuation mark (of a pair) + Pi Initial_Punctuation an initial quotation mark + Pf Final_Punctuation a final quotation mark + Po Other_Punctuation a punctuation mark of other type + Sm Math_Symbol a symbol of primarily mathematical use + Sc Currency_Symbol a currency sign + Sk Modifier_Symbol a non-letterlike modifier symbol + So Other_Symbol a symbol of other type + Zs Space_Separator a space character (of various non-zero widths) + Zl Line_Separator U+2028 LINE SEPARATOR only + Zp Paragraph_Separator U+2029 PARAGRAPH SEPARATOR only + Cc Control a C0 or C1 control code + Cf Format a format control character + Cs Surrogate a surrogate code point + Co Private_Use a private-use character + Cn Unassigned a reserved unassigned code point or a noncharacter +*/ + +/// The highest valid code point a `char` can have, `'\u{10FFFF}'`. Use [`char::MAX`] instead. +#[stable(feature = "rust1", since = "1.0.0")] +pub const MAX: char = char::MAX; + +/// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a +/// decoding error. Use [`char::REPLACEMENT_CHARACTER`] instead. +#[stable(feature = "decode_utf16", since = "1.9.0")] +pub const REPLACEMENT_CHARACTER: char = char::REPLACEMENT_CHARACTER; + +/// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of +/// `char` and `str` methods are based on. Use [`char::UNICODE_VERSION`] instead. +#[stable(feature = "unicode_version", since = "1.45.0")] +pub const UNICODE_VERSION: (u8, u8, u8) = char::UNICODE_VERSION; + +/// Creates an iterator over the UTF-16 encoded code points in `iter`, returning +/// unpaired surrogates as `Err`s. Use [`char::decode_utf16`] instead. +#[stable(feature = "decode_utf16", since = "1.9.0")] +#[inline] +pub fn decode_utf16>(iter: I) -> DecodeUtf16 { + self::decode::decode_utf16(iter) +} + +/// Converts a `u32` to a `char`. Use [`char::from_u32`] instead. +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] +#[must_use] +#[inline] +pub const fn from_u32(i: u32) -> Option { + self::convert::from_u32(i) +} + +/// Converts a `u32` to a `char`, ignoring validity. Use [`char::from_u32_unchecked`] +/// instead. +#[stable(feature = "char_from_unchecked", since = "1.5.0")] +#[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")] +#[must_use] +#[inline] +pub const unsafe fn from_u32_unchecked(i: u32) -> char { + // SAFETY: the safety contract must be upheld by the caller. + unsafe { self::convert::from_u32_unchecked(i) } +} + +/// Converts a digit in the given radix to a `char`. Use [`char::from_digit`] instead. +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] +#[must_use] +#[inline] +pub const fn from_digit(num: u32, radix: u32) -> Option { + self::convert::from_digit(num, radix) +} + +/// Returns an iterator that yields the hexadecimal Unicode escape of a +/// character, as `char`s. +/// +/// This `struct` is created by the [`escape_unicode`] method on [`char`]. See +/// its documentation for more. +/// +/// [`escape_unicode`]: char::escape_unicode +#[derive(Clone, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct EscapeUnicode(escape::EscapeIterInner<10>); + +impl EscapeUnicode { + #[inline] + const fn new(c: char) -> Self { + Self(escape::EscapeIterInner::unicode(c)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for EscapeUnicode { + type Item = char; + + #[inline] + fn next(&mut self) -> Option { + self.0.next().map(char::from) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let n = self.0.len(); + (n, Some(n)) + } + + #[inline] + fn count(self) -> usize { + self.0.len() + } + + #[inline] + fn last(mut self) -> Option { + self.0.next_back().map(char::from) + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.0.advance_by(n) + } +} + +#[stable(feature = "exact_size_escape", since = "1.11.0")] +impl ExactSizeIterator for EscapeUnicode { + #[inline] + fn len(&self) -> usize { + self.0.len() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for EscapeUnicode {} + +#[stable(feature = "char_struct_display", since = "1.16.0")] +impl fmt::Display for EscapeUnicode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.0.as_str()) + } +} + +/// An iterator that yields the literal escape code of a `char`. +/// +/// This `struct` is created by the [`escape_default`] method on [`char`]. See +/// its documentation for more. +/// +/// [`escape_default`]: char::escape_default +#[derive(Clone, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct EscapeDefault(escape::EscapeIterInner<10>); + +impl EscapeDefault { + #[inline] + const fn printable(c: ascii::Char) -> Self { + Self(escape::EscapeIterInner::ascii(c.to_u8())) + } + + #[inline] + const fn backslash(c: ascii::Char) -> Self { + Self(escape::EscapeIterInner::backslash(c)) + } + + #[inline] + const fn unicode(c: char) -> Self { + Self(escape::EscapeIterInner::unicode(c)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for EscapeDefault { + type Item = char; + + #[inline] + fn next(&mut self) -> Option { + self.0.next().map(char::from) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let n = self.0.len(); + (n, Some(n)) + } + + #[inline] + fn count(self) -> usize { + self.0.len() + } + + #[inline] + fn last(mut self) -> Option { + self.0.next_back().map(char::from) + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.0.advance_by(n) + } +} + +#[stable(feature = "exact_size_escape", since = "1.11.0")] +impl ExactSizeIterator for EscapeDefault { + #[inline] + fn len(&self) -> usize { + self.0.len() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for EscapeDefault {} + +#[stable(feature = "char_struct_display", since = "1.16.0")] +impl fmt::Display for EscapeDefault { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.0.as_str()) + } +} + +/// An iterator that yields the literal escape code of a `char`. +/// +/// This `struct` is created by the [`escape_debug`] method on [`char`]. See its +/// documentation for more. +/// +/// [`escape_debug`]: char::escape_debug +#[stable(feature = "char_escape_debug", since = "1.20.0")] +#[derive(Clone, Debug)] +pub struct EscapeDebug(EscapeDebugInner); + +#[derive(Clone, Debug)] +// Note: It’s possible to manually encode the EscapeDebugInner inside of +// EscapeIterInner (e.g. with alive=254..255 indicating that data[0..4] holds +// a char) which would likely result in a more optimised code. For now we use +// the option easier to implement. +enum EscapeDebugInner { + Bytes(escape::EscapeIterInner<10>), + Char(char), +} + +impl EscapeDebug { + #[inline] + const fn printable(chr: char) -> Self { + Self(EscapeDebugInner::Char(chr)) + } + + #[inline] + const fn backslash(c: ascii::Char) -> Self { + Self(EscapeDebugInner::Bytes(escape::EscapeIterInner::backslash(c))) + } + + #[inline] + const fn unicode(c: char) -> Self { + Self(EscapeDebugInner::Bytes(escape::EscapeIterInner::unicode(c))) + } + + #[inline] + fn clear(&mut self) { + self.0 = EscapeDebugInner::Bytes(escape::EscapeIterInner::empty()); + } +} + +#[stable(feature = "char_escape_debug", since = "1.20.0")] +impl Iterator for EscapeDebug { + type Item = char; + + #[inline] + fn next(&mut self) -> Option { + match self.0 { + EscapeDebugInner::Bytes(ref mut bytes) => bytes.next().map(char::from), + EscapeDebugInner::Char(chr) => { + self.clear(); + Some(chr) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let n = self.len(); + (n, Some(n)) + } + + #[inline] + fn count(self) -> usize { + self.len() + } +} + +#[stable(feature = "char_escape_debug", since = "1.20.0")] +impl ExactSizeIterator for EscapeDebug { + fn len(&self) -> usize { + match &self.0 { + EscapeDebugInner::Bytes(bytes) => bytes.len(), + EscapeDebugInner::Char(_) => 1, + } + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for EscapeDebug {} + +#[stable(feature = "char_escape_debug", since = "1.20.0")] +impl fmt::Display for EscapeDebug { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match &self.0 { + EscapeDebugInner::Bytes(bytes) => f.write_str(bytes.as_str()), + EscapeDebugInner::Char(chr) => f.write_char(*chr), + } + } +} + +macro_rules! casemappingiter_impls { + ($(#[$attr:meta])* $ITER_NAME:ident) => { + $(#[$attr])* + #[stable(feature = "rust1", since = "1.0.0")] + #[derive(Debug, Clone)] + pub struct $ITER_NAME(CaseMappingIter); + + #[stable(feature = "rust1", since = "1.0.0")] + impl Iterator for $ITER_NAME { + type Item = char; + fn next(&mut self) -> Option { + self.0.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.0.fold(init, fold) + } + + fn count(self) -> usize { + self.0.count() + } + + fn last(self) -> Option { + self.0.last() + } + + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.0.advance_by(n) + } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + // SAFETY: just forwarding requirements to caller + unsafe { self.0.__iterator_get_unchecked(idx) } + } + } + + #[stable(feature = "case_mapping_double_ended", since = "1.59.0")] + impl DoubleEndedIterator for $ITER_NAME { + fn next_back(&mut self) -> Option { + self.0.next_back() + } + + fn rfold(self, init: Acc, rfold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.0.rfold(init, rfold) + } + + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.0.advance_back_by(n) + } + } + + #[stable(feature = "fused", since = "1.26.0")] + impl FusedIterator for $ITER_NAME {} + + #[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")] + impl ExactSizeIterator for $ITER_NAME { + fn len(&self) -> usize { + self.0.len() + } + + fn is_empty(&self) -> bool { + self.0.is_empty() + } + } + + // SAFETY: forwards to inner `array::IntoIter` + #[unstable(feature = "trusted_len", issue = "37572")] + unsafe impl TrustedLen for $ITER_NAME {} + + // SAFETY: forwards to inner `array::IntoIter` + #[doc(hidden)] + #[unstable(feature = "std_internals", issue = "none")] + unsafe impl TrustedRandomAccessNoCoerce for $ITER_NAME { + const MAY_HAVE_SIDE_EFFECT: bool = false; + } + + // SAFETY: this iter has no subtypes/supertypes + #[doc(hidden)] + #[unstable(feature = "std_internals", issue = "none")] + unsafe impl TrustedRandomAccess for $ITER_NAME {} + + #[stable(feature = "char_struct_display", since = "1.16.0")] + impl fmt::Display for $ITER_NAME { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } + } + } +} + +casemappingiter_impls! { + /// Returns an iterator that yields the lowercase equivalent of a `char`. + /// + /// This `struct` is created by the [`to_lowercase`] method on [`char`]. See + /// its documentation for more. + /// + /// [`to_lowercase`]: char::to_lowercase + ToLowercase +} + +casemappingiter_impls! { + /// Returns an iterator that yields the uppercase equivalent of a `char`. + /// + /// This `struct` is created by the [`to_uppercase`] method on [`char`]. See + /// its documentation for more. + /// + /// [`to_uppercase`]: char::to_uppercase + ToUppercase +} + +#[derive(Debug, Clone)] +struct CaseMappingIter(core::array::IntoIter); + +impl CaseMappingIter { + #[inline] + fn new(chars: [char; 3]) -> CaseMappingIter { + let mut iter = chars.into_iter(); + if chars[2] == '\0' { + iter.next_back(); + if chars[1] == '\0' { + iter.next_back(); + + // Deliberately don't check `chars[0]`, + // as '\0' lowercases to itself + } + } + CaseMappingIter(iter) + } +} + +impl Iterator for CaseMappingIter { + type Item = char; + + fn next(&mut self) -> Option { + self.0.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.0.fold(init, fold) + } + + fn count(self) -> usize { + self.0.count() + } + + fn last(self) -> Option { + self.0.last() + } + + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.0.advance_by(n) + } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + // SAFETY: just forwarding requirements to caller + unsafe { self.0.__iterator_get_unchecked(idx) } + } +} + +impl DoubleEndedIterator for CaseMappingIter { + fn next_back(&mut self) -> Option { + self.0.next_back() + } + + fn rfold(self, init: Acc, rfold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.0.rfold(init, rfold) + } + + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.0.advance_back_by(n) + } +} + +impl ExactSizeIterator for CaseMappingIter { + fn len(&self) -> usize { + self.0.len() + } + + fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +impl FusedIterator for CaseMappingIter {} + +// SAFETY: forwards to inner `array::IntoIter` +unsafe impl TrustedLen for CaseMappingIter {} + +// SAFETY: forwards to inner `array::IntoIter` +unsafe impl TrustedRandomAccessNoCoerce for CaseMappingIter { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +// SAFETY: `CaseMappingIter` has no subtypes/supertypes +unsafe impl TrustedRandomAccess for CaseMappingIter {} + +impl fmt::Display for CaseMappingIter { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for c in self.0.clone() { + f.write_char(c)?; + } + Ok(()) + } +} + +/// The error type returned when a checked char conversion fails. +#[stable(feature = "u8_from_char", since = "1.59.0")] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct TryFromCharError(pub(crate) ()); + +#[stable(feature = "u8_from_char", since = "1.59.0")] +impl fmt::Display for TryFromCharError { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + "unicode code point out of range".fmt(fmt) + } +} + +#[stable(feature = "u8_from_char", since = "1.59.0")] +impl Error for TryFromCharError {} diff --git a/CoqOfRust/core/clone.rs b/CoqOfRust/core/clone.rs new file mode 100644 index 000000000..ec1aed53e --- /dev/null +++ b/CoqOfRust/core/clone.rs @@ -0,0 +1,378 @@ +//! The `Clone` trait for types that cannot be 'implicitly copied'. +//! +//! In Rust, some simple types are "implicitly copyable" and when you +//! assign them or pass them as arguments, the receiver will get a copy, +//! leaving the original value in place. These types do not require +//! allocation to copy and do not have finalizers (i.e., they do not +//! contain owned boxes or implement [`Drop`]), so the compiler considers +//! them cheap and safe to copy. For other types copies must be made +//! explicitly, by convention implementing the [`Clone`] trait and calling +//! the [`clone`] method. +//! +//! [`clone`]: Clone::clone +//! +//! Basic usage example: +//! +//! ``` +//! let s = String::new(); // String type implements Clone +//! let copy = s.clone(); // so we can clone it +//! ``` +//! +//! To easily implement the Clone trait, you can also use +//! `#[derive(Clone)]`. Example: +//! +//! ``` +//! #[derive(Clone)] // we add the Clone trait to Morpheus struct +//! struct Morpheus { +//! blue_pill: f32, +//! red_pill: i64, +//! } +//! +//! fn main() { +//! let f = Morpheus { blue_pill: 0.0, red_pill: 0 }; +//! let copy = f.clone(); // and now we can clone it! +//! } +//! ``` + +#![stable(feature = "rust1", since = "1.0.0")] + +mod uninit; + +/// A common trait for the ability to explicitly duplicate an object. +/// +/// Differs from [`Copy`] in that [`Copy`] is implicit and an inexpensive bit-wise copy, while +/// `Clone` is always explicit and may or may not be expensive. In order to enforce +/// these characteristics, Rust does not allow you to reimplement [`Copy`], but you +/// may reimplement `Clone` and run arbitrary code. +/// +/// Since `Clone` is more general than [`Copy`], you can automatically make anything +/// [`Copy`] be `Clone` as well. +/// +/// ## Derivable +/// +/// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d +/// implementation of [`Clone`] calls [`clone`] on each field. +/// +/// [`clone`]: Clone::clone +/// +/// For a generic struct, `#[derive]` implements `Clone` conditionally by adding bound `Clone` on +/// generic parameters. +/// +/// ``` +/// // `derive` implements Clone for Reading when T is Clone. +/// #[derive(Clone)] +/// struct Reading { +/// frequency: T, +/// } +/// ``` +/// +/// ## How can I implement `Clone`? +/// +/// Types that are [`Copy`] should have a trivial implementation of `Clone`. More formally: +/// if `T: Copy`, `x: T`, and `y: &T`, then `let x = y.clone();` is equivalent to `let x = *y;`. +/// Manual implementations should be careful to uphold this invariant; however, unsafe code +/// must not rely on it to ensure memory safety. +/// +/// An example is a generic struct holding a function pointer. In this case, the +/// implementation of `Clone` cannot be `derive`d, but can be implemented as: +/// +/// ``` +/// struct Generate(fn() -> T); +/// +/// impl Copy for Generate {} +/// +/// impl Clone for Generate { +/// fn clone(&self) -> Self { +/// *self +/// } +/// } +/// ``` +/// +/// If we `derive`: +/// +/// ``` +/// #[derive(Copy, Clone)] +/// struct Generate(fn() -> T); +/// ``` +/// +/// the auto-derived implementations will have unnecessary `T: Copy` and `T: Clone` bounds: +/// +/// ``` +/// # struct Generate(fn() -> T); +/// +/// // Automatically derived +/// impl Copy for Generate { } +/// +/// // Automatically derived +/// impl Clone for Generate { +/// fn clone(&self) -> Generate { +/// Generate(Clone::clone(&self.0)) +/// } +/// } +/// ``` +/// +/// The bounds are unnecessary because clearly the function itself should be +/// copy- and cloneable even if its return type is not: +/// +/// ```compile_fail,E0599 +/// #[derive(Copy, Clone)] +/// struct Generate(fn() -> T); +/// +/// struct NotCloneable; +/// +/// fn generate_not_cloneable() -> NotCloneable { +/// NotCloneable +/// } +/// +/// Generate(generate_not_cloneable).clone(); // error: trait bounds were not satisfied +/// // Note: With the manual implementations the above line will compile. +/// ``` +/// +/// ## Additional implementors +/// +/// In addition to the [implementors listed below][impls], +/// the following types also implement `Clone`: +/// +/// * Function item types (i.e., the distinct types defined for each function) +/// * Function pointer types (e.g., `fn() -> i32`) +/// * Closure types, if they capture no value from the environment +/// or if all such captured values implement `Clone` themselves. +/// Note that variables captured by shared reference always implement `Clone` +/// (even if the referent doesn't), +/// while variables captured by mutable reference never implement `Clone`. +/// +/// [impls]: #implementors +#[stable(feature = "rust1", since = "1.0.0")] +#[lang = "clone"] +#[rustc_diagnostic_item = "Clone"] +#[rustc_trivial_field_reads] +pub trait Clone: Sized { + /// Returns a copy of the value. + /// + /// # Examples + /// + /// ``` + /// # #![allow(noop_method_call)] + /// let hello = "Hello"; // &str implements Clone + /// + /// assert_eq!("Hello", hello.clone()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "cloning is often expensive and is not expected to have side effects"] + // Clone::clone is special because the compiler generates MIR to implement it for some types. + // See InstanceKind::CloneShim. + #[lang = "clone_fn"] + fn clone(&self) -> Self; + + /// Performs copy-assignment from `source`. + /// + /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality, + /// but can be overridden to reuse the resources of `a` to avoid unnecessary + /// allocations. + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn clone_from(&mut self, source: &Self) { + *self = source.clone() + } +} + +/// Derive macro generating an impl of the trait `Clone`. +#[rustc_builtin_macro] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics, derive_clone_copy)] +pub macro Clone($item:item) { + /* compiler built-in */ +} + +// FIXME(aburka): these structs are used solely by #[derive] to +// assert that every component of a type implements Clone or Copy. +// +// These structs should never appear in user code. +#[doc(hidden)] +#[allow(missing_debug_implementations)] +#[unstable( + feature = "derive_clone_copy", + reason = "deriving hack, should not be public", + issue = "none" +)] +pub struct AssertParamIsClone { + _field: crate::marker::PhantomData, +} +#[doc(hidden)] +#[allow(missing_debug_implementations)] +#[unstable( + feature = "derive_clone_copy", + reason = "deriving hack, should not be public", + issue = "none" +)] +pub struct AssertParamIsCopy { + _field: crate::marker::PhantomData, +} + +/// A generalization of [`Clone`] to dynamically-sized types stored in arbitrary containers. +/// +/// This trait is implemented for all types implementing [`Clone`], and also [slices](slice) of all +/// such types. You may also implement this trait to enable cloning trait objects and custom DSTs +/// (structures containing dynamically-sized fields). +/// +/// # Safety +/// +/// Implementations must ensure that when `.clone_to_uninit(dst)` returns normally rather than +/// panicking, it always leaves `*dst` initialized as a valid value of type `Self`. +/// +/// # See also +/// +/// * [`Clone::clone_from`] is a safe function which may be used instead when `Self` is a [`Sized`] +/// and the destination is already initialized; it may be able to reuse allocations owned by +/// the destination. +/// * [`ToOwned`], which allocates a new destination container. +/// +/// [`ToOwned`]: ../../std/borrow/trait.ToOwned.html +#[unstable(feature = "clone_to_uninit", issue = "126799")] +pub unsafe trait CloneToUninit { + /// Performs copy-assignment from `self` to `dst`. + /// + /// This is analogous to `std::ptr::write(dst.cast(), self.clone())`, + /// except that `self` may be a dynamically-sized type ([`!Sized`](Sized)). + /// + /// Before this function is called, `dst` may point to uninitialized memory. + /// After this function is called, `dst` will point to initialized memory; it will be + /// sound to create a `&Self` reference from the pointer with the [pointer metadata] + /// from `self`. + /// + /// # Safety + /// + /// Behavior is undefined if any of the following conditions are violated: + /// + /// * `dst` must be [valid] for writes for `std::mem::size_of_val(self)` bytes. + /// * `dst` must be properly aligned to `std::mem::align_of_val(self)`. + /// + /// [valid]: crate::ptr#safety + /// [pointer metadata]: crate::ptr::metadata() + /// + /// # Panics + /// + /// This function may panic. (For example, it might panic if memory allocation for a clone + /// of a value owned by `self` fails.) + /// If the call panics, then `*dst` should be treated as uninitialized memory; it must not be + /// read or dropped, because even if it was previously valid, it may have been partially + /// overwritten. + /// + /// The caller may also need to take care to deallocate the allocation pointed to by `dst`, + /// if applicable, to avoid a memory leak, and may need to take other precautions to ensure + /// soundness in the presence of unwinding. + /// + /// Implementors should avoid leaking values by, upon unwinding, dropping all component values + /// that might have already been created. (For example, if a `[Foo]` of length 3 is being + /// cloned, and the second of the three calls to `Foo::clone()` unwinds, then the first `Foo` + /// cloned should be dropped.) + unsafe fn clone_to_uninit(&self, dst: *mut u8); +} + +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl CloneToUninit for T { + #[inline] + unsafe fn clone_to_uninit(&self, dst: *mut u8) { + // SAFETY: we're calling a specialization with the same contract + unsafe { ::clone_one(self, dst.cast::()) } + } +} + +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl CloneToUninit for [T] { + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_to_uninit(&self, dst: *mut u8) { + let dst: *mut [T] = dst.with_metadata_of(self); + // SAFETY: we're calling a specialization with the same contract + unsafe { ::clone_slice(self, dst) } + } +} + +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl CloneToUninit for str { + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_to_uninit(&self, dst: *mut u8) { + // SAFETY: str is just a [u8] with UTF-8 invariant + unsafe { self.as_bytes().clone_to_uninit(dst) } + } +} + +#[unstable(feature = "clone_to_uninit", issue = "126799")] +unsafe impl CloneToUninit for crate::ffi::CStr { + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_to_uninit(&self, dst: *mut u8) { + // SAFETY: For now, CStr is just a #[repr(trasnsparent)] [c_char] with some invariants. + // And we can cast [c_char] to [u8] on all supported platforms (see: to_bytes_with_nul). + // The pointer metadata properly preserves the length (so NUL is also copied). + // See: `cstr_metadata_is_length_with_nul` in tests. + unsafe { self.to_bytes_with_nul().clone_to_uninit(dst) } + } +} + +/// Implementations of `Clone` for primitive types. +/// +/// Implementations that cannot be described in Rust +/// are implemented in `traits::SelectionContext::copy_clone_conditions()` +/// in `rustc_trait_selection`. +mod impls { + macro_rules! impl_clone { + ($($t:ty)*) => { + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl Clone for $t { + #[inline(always)] + fn clone(&self) -> Self { + *self + } + } + )* + } + } + + impl_clone! { + usize u8 u16 u32 u64 u128 + isize i8 i16 i32 i64 i128 + f16 f32 f64 f128 + bool char + } + + #[unstable(feature = "never_type", issue = "35121")] + impl Clone for ! { + #[inline] + fn clone(&self) -> Self { + *self + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Clone for *const T { + #[inline(always)] + fn clone(&self) -> Self { + *self + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Clone for *mut T { + #[inline(always)] + fn clone(&self) -> Self { + *self + } + } + + /// Shared references can be cloned, but mutable references *cannot*! + #[stable(feature = "rust1", since = "1.0.0")] + impl Clone for &T { + #[inline(always)] + #[rustc_diagnostic_item = "noop_method_clone"] + fn clone(&self) -> Self { + *self + } + } + + /// Shared references can be cloned, but mutable references *cannot*! + #[stable(feature = "rust1", since = "1.0.0")] + impl !Clone for &mut T {} +} diff --git a/CoqOfRust/core/clone/uninit.rs b/CoqOfRust/core/clone/uninit.rs new file mode 100644 index 000000000..8b738bec7 --- /dev/null +++ b/CoqOfRust/core/clone/uninit.rs @@ -0,0 +1,128 @@ +use crate::mem::{self, MaybeUninit}; +use crate::ptr; + +/// Private specialization trait used by CloneToUninit, as per +/// [the dev guide](https://std-dev-guide.rust-lang.org/policy/specialization.html). +pub(super) unsafe trait CopySpec: Clone { + unsafe fn clone_one(src: &Self, dst: *mut Self); + unsafe fn clone_slice(src: &[Self], dst: *mut [Self]); +} + +unsafe impl CopySpec for T { + #[inline] + default unsafe fn clone_one(src: &Self, dst: *mut Self) { + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of + // ptr::write(). + unsafe { + // We hope the optimizer will figure out to create the cloned value in-place, + // skipping ever storing it on the stack and the copy to the destination. + ptr::write(dst, src.clone()); + } + } + + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + default unsafe fn clone_slice(src: &[Self], dst: *mut [Self]) { + let len = src.len(); + // This is the most likely mistake to make, so check it as a debug assertion. + debug_assert_eq!( + len, + dst.len(), + "clone_to_uninit() source and destination must have equal lengths", + ); + + // SAFETY: The produced `&mut` is valid because: + // * The caller is obligated to provide a pointer which is valid for writes. + // * All bytes pointed to are in MaybeUninit, so we don't care about the memory's + // initialization status. + let uninit_ref = unsafe { &mut *(dst as *mut [MaybeUninit]) }; + + // Copy the elements + let mut initializing = InitializingSlice::from_fully_uninit(uninit_ref); + for element_ref in src { + // If the clone() panics, `initializing` will take care of the cleanup. + initializing.push(element_ref.clone()); + } + // If we reach here, then the entire slice is initialized, and we've satisfied our + // responsibilities to the caller. Disarm the cleanup guard by forgetting it. + mem::forget(initializing); + } +} + +// Specialized implementation for types that are [`Copy`], not just [`Clone`], +// and can therefore be copied bitwise. +unsafe impl CopySpec for T { + #[inline] + unsafe fn clone_one(src: &Self, dst: *mut Self) { + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of + // ptr::copy_nonoverlapping(). + unsafe { + ptr::copy_nonoverlapping(src, dst, 1); + } + } + + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_slice(src: &[Self], dst: *mut [Self]) { + let len = src.len(); + // This is the most likely mistake to make, so check it as a debug assertion. + debug_assert_eq!( + len, + dst.len(), + "clone_to_uninit() source and destination must have equal lengths", + ); + + // SAFETY: The safety conditions of clone_to_uninit() are a superset of those of + // ptr::copy_nonoverlapping(). + unsafe { + ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), len); + } + } +} + +/// Ownership of a collection of values stored in a non-owned `[MaybeUninit]`, some of which +/// are not yet initialized. This is sort of like a `Vec` that doesn't own its allocation. +/// Its responsibility is to provide cleanup on unwind by dropping the values that *are* +/// initialized, unless disarmed by forgetting. +/// +/// This is a helper for `impl CloneToUninit for [T]`. +struct InitializingSlice<'a, T> { + data: &'a mut [MaybeUninit], + /// Number of elements of `*self.data` that are initialized. + initialized_len: usize, +} + +impl<'a, T> InitializingSlice<'a, T> { + #[inline] + fn from_fully_uninit(data: &'a mut [MaybeUninit]) -> Self { + Self { data, initialized_len: 0 } + } + + /// Push a value onto the end of the initialized part of the slice. + /// + /// # Panics + /// + /// Panics if the slice is already fully initialized. + #[inline] + fn push(&mut self, value: T) { + MaybeUninit::write(&mut self.data[self.initialized_len], value); + self.initialized_len += 1; + } +} + +impl<'a, T> Drop for InitializingSlice<'a, T> { + #[cold] // will only be invoked on unwind + fn drop(&mut self) { + let initialized_slice = ptr::slice_from_raw_parts_mut( + MaybeUninit::slice_as_mut_ptr(self.data), + self.initialized_len, + ); + // SAFETY: + // * the pointer is valid because it was made from a mutable reference + // * `initialized_len` counts the initialized elements as an invariant of this type, + // so each of the pointed-to elements is initialized and may be dropped. + unsafe { + ptr::drop_in_place::<[T]>(initialized_slice); + } + } +} diff --git a/CoqOfRust/core/cmp.rs b/CoqOfRust/core/cmp.rs new file mode 100644 index 000000000..5a3b9365c --- /dev/null +++ b/CoqOfRust/core/cmp.rs @@ -0,0 +1,1948 @@ +//! Utilities for comparing and ordering values. +//! +//! This module contains various tools for comparing and ordering values. In +//! summary: +//! +//! * [`PartialEq`] overloads the `==` and `!=` operators. In cases where +//! `Rhs` (the right hand side's type) is `Self`, this trait corresponds to a +//! partial equivalence relation. +//! * [`Eq`] indicates that the overloaded `==` operator corresponds to an +//! equivalence relation. +//! * [`Ord`] and [`PartialOrd`] are traits that allow you to define total and +//! partial orderings between values, respectively. Implementing them overloads +//! the `<`, `<=`, `>`, and `>=` operators. +//! * [`Ordering`] is an enum returned by the main functions of [`Ord`] and +//! [`PartialOrd`], and describes an ordering of two values (less, equal, or +//! greater). +//! * [`Reverse`] is a struct that allows you to easily reverse an ordering. +//! * [`max`] and [`min`] are functions that build off of [`Ord`] and allow you +//! to find the maximum or minimum of two values. +//! +//! For more details, see the respective documentation of each item in the list. +//! +//! [`max`]: Ord::max +//! [`min`]: Ord::min + +#![stable(feature = "rust1", since = "1.0.0")] + +mod bytewise; +pub(crate) use bytewise::BytewiseEq; + +use self::Ordering::*; + +/// Trait for comparisons using the equality operator. +/// +/// Implementing this trait for types provides the `==` and `!=` operators for +/// those types. +/// +/// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`. +/// We use the easier-to-read infix notation in the remainder of this documentation. +/// +/// This trait allows for comparisons using the equality operator, for types +/// that do not have a full equivalence relation. For example, in floating point +/// numbers `NaN != NaN`, so floating point types implement `PartialEq` but not +/// [`trait@Eq`]. Formally speaking, when `Rhs == Self`, this trait corresponds +/// to a [partial equivalence relation]. +/// +/// [partial equivalence relation]: https://en.wikipedia.org/wiki/Partial_equivalence_relation +/// +/// Implementations must ensure that `eq` and `ne` are consistent with each other: +/// +/// - `a != b` if and only if `!(a == b)`. +/// +/// The default implementation of `ne` provides this consistency and is almost +/// always sufficient. It should not be overridden without very good reason. +/// +/// If [`PartialOrd`] or [`Ord`] are also implemented for `Self` and `Rhs`, their methods must also +/// be consistent with `PartialEq` (see the documentation of those traits for the exact +/// requirements). It's easy to accidentally make them disagree by deriving some of the traits and +/// manually implementing others. +/// +/// The equality relation `==` must satisfy the following conditions +/// (for all `a`, `b`, `c` of type `A`, `B`, `C`): +/// +/// - **Symmetry**: if `A: PartialEq` and `B: PartialEq`, then **`a == b` +/// implies `b == a`**; and +/// +/// - **Transitivity**: if `A: PartialEq` and `B: PartialEq` and `A: +/// PartialEq`, then **`a == b` and `b == c` implies `a == c`**. +/// This must also work for longer chains, such as when `A: PartialEq`, `B: PartialEq`, +/// `C: PartialEq`, and `A: PartialEq` all exist. +/// +/// Note that the `B: PartialEq` (symmetric) and `A: PartialEq` +/// (transitive) impls are not forced to exist, but these requirements apply +/// whenever they do exist. +/// +/// Violating these requirements is a logic error. The behavior resulting from a logic error is not +/// specified, but users of the trait must ensure that such logic errors do *not* result in +/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these +/// methods. +/// +/// ## Cross-crate considerations +/// +/// Upholding the requirements stated above can become tricky when one crate implements `PartialEq` +/// for a type of another crate (i.e., to allow comparing one of its own types with a type from the +/// standard library). The recommendation is to never implement this trait for a foreign type. In +/// other words, such a crate should do `impl PartialEq for LocalType`, but it should +/// *not* do `impl PartialEq for ForeignType`. +/// +/// This avoids the problem of transitive chains that criss-cross crate boundaries: for all local +/// types `T`, you may assume that no other crate will add `impl`s that allow comparing `T == U`. In +/// other words, if other crates add `impl`s that allow building longer transitive chains `U1 == ... +/// == T == V1 == ...`, then all the types that appear to the right of `T` must be types that the +/// crate defining `T` already knows about. This rules out transitive chains where downstream crates +/// can add new `impl`s that "stitch together" comparisons of foreign types in ways that violate +/// transitivity. +/// +/// Not having such foreign `impl`s also avoids forward compatibility issues where one crate adding +/// more `PartialEq` implementations can cause build failures in downstream crates. +/// +/// ## Derivable +/// +/// This trait can be used with `#[derive]`. When `derive`d on structs, two +/// instances are equal if all fields are equal, and not equal if any fields +/// are not equal. When `derive`d on enums, two instances are equal if they +/// are the same variant and all fields are equal. +/// +/// ## How can I implement `PartialEq`? +/// +/// An example implementation for a domain in which two books are considered +/// the same book if their ISBN matches, even if the formats differ: +/// +/// ``` +/// enum BookFormat { +/// Paperback, +/// Hardback, +/// Ebook, +/// } +/// +/// struct Book { +/// isbn: i32, +/// format: BookFormat, +/// } +/// +/// impl PartialEq for Book { +/// fn eq(&self, other: &Self) -> bool { +/// self.isbn == other.isbn +/// } +/// } +/// +/// let b1 = Book { isbn: 3, format: BookFormat::Paperback }; +/// let b2 = Book { isbn: 3, format: BookFormat::Ebook }; +/// let b3 = Book { isbn: 10, format: BookFormat::Paperback }; +/// +/// assert!(b1 == b2); +/// assert!(b1 != b3); +/// ``` +/// +/// ## How can I compare two different types? +/// +/// The type you can compare with is controlled by `PartialEq`'s type parameter. +/// For example, let's tweak our previous code a bit: +/// +/// ``` +/// // The derive implements == comparisons +/// #[derive(PartialEq)] +/// enum BookFormat { +/// Paperback, +/// Hardback, +/// Ebook, +/// } +/// +/// struct Book { +/// isbn: i32, +/// format: BookFormat, +/// } +/// +/// // Implement == comparisons +/// impl PartialEq for Book { +/// fn eq(&self, other: &BookFormat) -> bool { +/// self.format == *other +/// } +/// } +/// +/// // Implement == comparisons +/// impl PartialEq for BookFormat { +/// fn eq(&self, other: &Book) -> bool { +/// *self == other.format +/// } +/// } +/// +/// let b1 = Book { isbn: 3, format: BookFormat::Paperback }; +/// +/// assert!(b1 == BookFormat::Paperback); +/// assert!(BookFormat::Ebook != b1); +/// ``` +/// +/// By changing `impl PartialEq for Book` to `impl PartialEq for Book`, +/// we allow `BookFormat`s to be compared with `Book`s. +/// +/// A comparison like the one above, which ignores some fields of the struct, +/// can be dangerous. It can easily lead to an unintended violation of the +/// requirements for a partial equivalence relation. For example, if we kept +/// the above implementation of `PartialEq` for `BookFormat` and added an +/// implementation of `PartialEq` for `Book` (either via a `#[derive]` or +/// via the manual implementation from the first example) then the result would +/// violate transitivity: +/// +/// ```should_panic +/// #[derive(PartialEq)] +/// enum BookFormat { +/// Paperback, +/// Hardback, +/// Ebook, +/// } +/// +/// #[derive(PartialEq)] +/// struct Book { +/// isbn: i32, +/// format: BookFormat, +/// } +/// +/// impl PartialEq for Book { +/// fn eq(&self, other: &BookFormat) -> bool { +/// self.format == *other +/// } +/// } +/// +/// impl PartialEq for BookFormat { +/// fn eq(&self, other: &Book) -> bool { +/// *self == other.format +/// } +/// } +/// +/// fn main() { +/// let b1 = Book { isbn: 1, format: BookFormat::Paperback }; +/// let b2 = Book { isbn: 2, format: BookFormat::Paperback }; +/// +/// assert!(b1 == BookFormat::Paperback); +/// assert!(BookFormat::Paperback == b2); +/// +/// // The following should hold by transitivity but doesn't. +/// assert!(b1 == b2); // <-- PANICS +/// } +/// ``` +/// +/// # Examples +/// +/// ``` +/// let x: u32 = 0; +/// let y: u32 = 1; +/// +/// assert_eq!(x == y, false); +/// assert_eq!(x.eq(&y), false); +/// ``` +/// +/// [`eq`]: PartialEq::eq +/// [`ne`]: PartialEq::ne +#[lang = "eq"] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "==")] +#[doc(alias = "!=")] +#[rustc_on_unimplemented( + message = "can't compare `{Self}` with `{Rhs}`", + label = "no implementation for `{Self} == {Rhs}`", + append_const_msg +)] +#[rustc_diagnostic_item = "PartialEq"] +pub trait PartialEq { + /// Tests for `self` and `other` values to be equal, and is used by `==`. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "cmp_partialeq_eq"] + fn eq(&self, other: &Rhs) -> bool; + + /// Tests for `!=`. The default implementation is almost always sufficient, + /// and should not be overridden without very good reason. + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "cmp_partialeq_ne"] + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } +} + +/// Derive macro generating an impl of the trait [`PartialEq`]. +/// The behavior of this macro is described in detail [here](PartialEq#derivable). +#[rustc_builtin_macro] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics, structural_match)] +pub macro PartialEq($item:item) { + /* compiler built-in */ +} + +/// Trait for comparisons corresponding to [equivalence relations]( +/// https://en.wikipedia.org/wiki/Equivalence_relation). +/// +/// The primary difference to [`PartialEq`] is the additional requirement for reflexivity. A type +/// that implements [`PartialEq`] guarantees that for all `a`, `b` and `c`: +/// +/// - symmetric: `a == b` implies `b == a` and `a != b` implies `!(a == b)` +/// - transitive: `a == b` and `b == c` implies `a == c` +/// +/// `Eq`, which builds on top of [`PartialEq`] also implies: +/// +/// - reflexive: `a == a` +/// +/// This property cannot be checked by the compiler, and therefore `Eq` is a trait without methods. +/// +/// Violating this property is a logic error. The behavior resulting from a logic error is not +/// specified, but users of the trait must ensure that such logic errors do *not* result in +/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these +/// methods. +/// +/// Floating point types such as [`f32`] and [`f64`] implement only [`PartialEq`] but *not* `Eq` +/// because `NaN` != `NaN`. +/// +/// ## Derivable +/// +/// This trait can be used with `#[derive]`. When `derive`d, because `Eq` has no extra methods, it +/// is only informing the compiler that this is an equivalence relation rather than a partial +/// equivalence relation. Note that the `derive` strategy requires all fields are `Eq`, which isn't +/// always desired. +/// +/// ## How can I implement `Eq`? +/// +/// If you cannot use the `derive` strategy, specify that your type implements `Eq`, which has no +/// extra methods: +/// +/// ``` +/// enum BookFormat { +/// Paperback, +/// Hardback, +/// Ebook, +/// } +/// +/// struct Book { +/// isbn: i32, +/// format: BookFormat, +/// } +/// +/// impl PartialEq for Book { +/// fn eq(&self, other: &Self) -> bool { +/// self.isbn == other.isbn +/// } +/// } +/// +/// impl Eq for Book {} +/// ``` +#[doc(alias = "==")] +#[doc(alias = "!=")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Eq"] +pub trait Eq: PartialEq { + // this method is used solely by `impl Eq or #[derive(Eq)]` to assert that every component of a + // type implements `Eq` itself. The current deriving infrastructure means doing this assertion + // without using a method on this trait is nearly impossible. + // + // This should never be implemented by hand. + #[doc(hidden)] + #[coverage(off)] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn assert_receiver_is_total_eq(&self) {} +} + +/// Derive macro generating an impl of the trait [`Eq`]. +#[rustc_builtin_macro] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match)] +#[allow_internal_unstable(coverage_attribute)] +pub macro Eq($item:item) { + /* compiler built-in */ +} + +// FIXME: this struct is used solely by #[derive] to +// assert that every component of a type implements Eq. +// +// This struct should never appear in user code. +#[doc(hidden)] +#[allow(missing_debug_implementations)] +#[unstable(feature = "derive_eq", reason = "deriving hack, should not be public", issue = "none")] +pub struct AssertParamIsEq { + _field: crate::marker::PhantomData, +} + +/// An `Ordering` is the result of a comparison between two values. +/// +/// # Examples +/// +/// ``` +/// use std::cmp::Ordering; +/// +/// assert_eq!(1.cmp(&2), Ordering::Less); +/// +/// assert_eq!(1.cmp(&1), Ordering::Equal); +/// +/// assert_eq!(2.cmp(&1), Ordering::Greater); +/// ``` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +#[stable(feature = "rust1", since = "1.0.0")] +// This is a lang item only so that `BinOp::Cmp` in MIR can return it. +// It has no special behavior, but does require that the three variants +// `Less`/`Equal`/`Greater` remain `-1_i8`/`0_i8`/`+1_i8` respectively. +#[lang = "Ordering"] +#[repr(i8)] +pub enum Ordering { + /// An ordering where a compared value is less than another. + #[stable(feature = "rust1", since = "1.0.0")] + Less = -1, + /// An ordering where a compared value is equal to another. + #[stable(feature = "rust1", since = "1.0.0")] + Equal = 0, + /// An ordering where a compared value is greater than another. + #[stable(feature = "rust1", since = "1.0.0")] + Greater = 1, +} + +impl Ordering { + /// Returns `true` if the ordering is the `Equal` variant. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(Ordering::Less.is_eq(), false); + /// assert_eq!(Ordering::Equal.is_eq(), true); + /// assert_eq!(Ordering::Greater.is_eq(), false); + /// ``` + #[inline] + #[must_use] + #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] + #[stable(feature = "ordering_helpers", since = "1.53.0")] + pub const fn is_eq(self) -> bool { + matches!(self, Equal) + } + + /// Returns `true` if the ordering is not the `Equal` variant. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(Ordering::Less.is_ne(), true); + /// assert_eq!(Ordering::Equal.is_ne(), false); + /// assert_eq!(Ordering::Greater.is_ne(), true); + /// ``` + #[inline] + #[must_use] + #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] + #[stable(feature = "ordering_helpers", since = "1.53.0")] + pub const fn is_ne(self) -> bool { + !matches!(self, Equal) + } + + /// Returns `true` if the ordering is the `Less` variant. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(Ordering::Less.is_lt(), true); + /// assert_eq!(Ordering::Equal.is_lt(), false); + /// assert_eq!(Ordering::Greater.is_lt(), false); + /// ``` + #[inline] + #[must_use] + #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] + #[stable(feature = "ordering_helpers", since = "1.53.0")] + pub const fn is_lt(self) -> bool { + matches!(self, Less) + } + + /// Returns `true` if the ordering is the `Greater` variant. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(Ordering::Less.is_gt(), false); + /// assert_eq!(Ordering::Equal.is_gt(), false); + /// assert_eq!(Ordering::Greater.is_gt(), true); + /// ``` + #[inline] + #[must_use] + #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] + #[stable(feature = "ordering_helpers", since = "1.53.0")] + pub const fn is_gt(self) -> bool { + matches!(self, Greater) + } + + /// Returns `true` if the ordering is either the `Less` or `Equal` variant. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(Ordering::Less.is_le(), true); + /// assert_eq!(Ordering::Equal.is_le(), true); + /// assert_eq!(Ordering::Greater.is_le(), false); + /// ``` + #[inline] + #[must_use] + #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] + #[stable(feature = "ordering_helpers", since = "1.53.0")] + pub const fn is_le(self) -> bool { + !matches!(self, Greater) + } + + /// Returns `true` if the ordering is either the `Greater` or `Equal` variant. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(Ordering::Less.is_ge(), false); + /// assert_eq!(Ordering::Equal.is_ge(), true); + /// assert_eq!(Ordering::Greater.is_ge(), true); + /// ``` + #[inline] + #[must_use] + #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] + #[stable(feature = "ordering_helpers", since = "1.53.0")] + pub const fn is_ge(self) -> bool { + !matches!(self, Less) + } + + /// Reverses the `Ordering`. + /// + /// * `Less` becomes `Greater`. + /// * `Greater` becomes `Less`. + /// * `Equal` becomes `Equal`. + /// + /// # Examples + /// + /// Basic behavior: + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(Ordering::Less.reverse(), Ordering::Greater); + /// assert_eq!(Ordering::Equal.reverse(), Ordering::Equal); + /// assert_eq!(Ordering::Greater.reverse(), Ordering::Less); + /// ``` + /// + /// This method can be used to reverse a comparison: + /// + /// ``` + /// let data: &mut [_] = &mut [2, 10, 5, 8]; + /// + /// // sort the array from largest to smallest. + /// data.sort_by(|a, b| a.cmp(b).reverse()); + /// + /// let b: &mut [_] = &mut [10, 8, 5, 2]; + /// assert!(data == b); + /// ``` + #[inline] + #[must_use] + #[rustc_const_stable(feature = "const_ordering", since = "1.48.0")] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn reverse(self) -> Ordering { + match self { + Less => Greater, + Equal => Equal, + Greater => Less, + } + } + + /// Chains two orderings. + /// + /// Returns `self` when it's not `Equal`. Otherwise returns `other`. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// let result = Ordering::Equal.then(Ordering::Less); + /// assert_eq!(result, Ordering::Less); + /// + /// let result = Ordering::Less.then(Ordering::Equal); + /// assert_eq!(result, Ordering::Less); + /// + /// let result = Ordering::Less.then(Ordering::Greater); + /// assert_eq!(result, Ordering::Less); + /// + /// let result = Ordering::Equal.then(Ordering::Equal); + /// assert_eq!(result, Ordering::Equal); + /// + /// let x: (i64, i64, i64) = (1, 2, 7); + /// let y: (i64, i64, i64) = (1, 5, 3); + /// let result = x.0.cmp(&y.0).then(x.1.cmp(&y.1)).then(x.2.cmp(&y.2)); + /// + /// assert_eq!(result, Ordering::Less); + /// ``` + #[inline] + #[must_use] + #[rustc_const_stable(feature = "const_ordering", since = "1.48.0")] + #[stable(feature = "ordering_chaining", since = "1.17.0")] + pub const fn then(self, other: Ordering) -> Ordering { + match self { + Equal => other, + _ => self, + } + } + + /// Chains the ordering with the given function. + /// + /// Returns `self` when it's not `Equal`. Otherwise calls `f` and returns + /// the result. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// let result = Ordering::Equal.then_with(|| Ordering::Less); + /// assert_eq!(result, Ordering::Less); + /// + /// let result = Ordering::Less.then_with(|| Ordering::Equal); + /// assert_eq!(result, Ordering::Less); + /// + /// let result = Ordering::Less.then_with(|| Ordering::Greater); + /// assert_eq!(result, Ordering::Less); + /// + /// let result = Ordering::Equal.then_with(|| Ordering::Equal); + /// assert_eq!(result, Ordering::Equal); + /// + /// let x: (i64, i64, i64) = (1, 2, 7); + /// let y: (i64, i64, i64) = (1, 5, 3); + /// let result = x.0.cmp(&y.0).then_with(|| x.1.cmp(&y.1)).then_with(|| x.2.cmp(&y.2)); + /// + /// assert_eq!(result, Ordering::Less); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "ordering_chaining", since = "1.17.0")] + pub fn then_with Ordering>(self, f: F) -> Ordering { + match self { + Equal => f(), + _ => self, + } + } +} + +/// A helper struct for reverse ordering. +/// +/// This struct is a helper to be used with functions like [`Vec::sort_by_key`] and +/// can be used to reverse order a part of a key. +/// +/// [`Vec::sort_by_key`]: ../../std/vec/struct.Vec.html#method.sort_by_key +/// +/// # Examples +/// +/// ``` +/// use std::cmp::Reverse; +/// +/// let mut v = vec![1, 2, 3, 4, 5, 6]; +/// v.sort_by_key(|&num| (num > 3, Reverse(num))); +/// assert_eq!(v, vec![3, 2, 1, 6, 5, 4]); +/// ``` +#[derive(PartialEq, Eq, Debug, Copy, Default, Hash)] +#[stable(feature = "reverse_cmp_key", since = "1.19.0")] +#[repr(transparent)] +pub struct Reverse(#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub T); + +#[stable(feature = "reverse_cmp_key", since = "1.19.0")] +impl PartialOrd for Reverse { + #[inline] + fn partial_cmp(&self, other: &Reverse) -> Option { + other.0.partial_cmp(&self.0) + } + + #[inline] + fn lt(&self, other: &Self) -> bool { + other.0 < self.0 + } + #[inline] + fn le(&self, other: &Self) -> bool { + other.0 <= self.0 + } + #[inline] + fn gt(&self, other: &Self) -> bool { + other.0 > self.0 + } + #[inline] + fn ge(&self, other: &Self) -> bool { + other.0 >= self.0 + } +} + +#[stable(feature = "reverse_cmp_key", since = "1.19.0")] +impl Ord for Reverse { + #[inline] + fn cmp(&self, other: &Reverse) -> Ordering { + other.0.cmp(&self.0) + } +} + +#[stable(feature = "reverse_cmp_key", since = "1.19.0")] +impl Clone for Reverse { + #[inline] + fn clone(&self) -> Reverse { + Reverse(self.0.clone()) + } + + #[inline] + fn clone_from(&mut self, source: &Self) { + self.0.clone_from(&source.0) + } +} + +/// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order). +/// +/// Implementations must be consistent with the [`PartialOrd`] implementation, and ensure `max`, +/// `min`, and `clamp` are consistent with `cmp`: +/// +/// - `partial_cmp(a, b) == Some(cmp(a, b))`. +/// - `max(a, b) == max_by(a, b, cmp)` (ensured by the default implementation). +/// - `min(a, b) == min_by(a, b, cmp)` (ensured by the default implementation). +/// - For `a.clamp(min, max)`, see the [method docs](#method.clamp) (ensured by the default +/// implementation). +/// +/// Violating these requirements is a logic error. The behavior resulting from a logic error is not +/// specified, but users of the trait must ensure that such logic errors do *not* result in +/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these +/// methods. +/// +/// ## Corollaries +/// +/// From the above and the requirements of `PartialOrd`, it follows that for all `a`, `b` and `c`: +/// +/// - exactly one of `a < b`, `a == b` or `a > b` is true; and +/// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and +/// `>`. +/// +/// Mathematically speaking, the `<` operator defines a strict [weak order]. In cases where `==` +/// conforms to mathematical equality, it also defines a strict [total order]. +/// +/// [weak order]: https://en.wikipedia.org/wiki/Weak_ordering +/// [total order]: https://en.wikipedia.org/wiki/Total_order +/// +/// ## Derivable +/// +/// This trait can be used with `#[derive]`. +/// +/// When `derive`d on structs, it will produce a +/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering based on the +/// top-to-bottom declaration order of the struct's members. +/// +/// When `derive`d on enums, variants are ordered primarily by their discriminants. Secondarily, +/// they are ordered by their fields. By default, the discriminant is smallest for variants at the +/// top, and largest for variants at the bottom. Here's an example: +/// +/// ``` +/// #[derive(PartialEq, Eq, PartialOrd, Ord)] +/// enum E { +/// Top, +/// Bottom, +/// } +/// +/// assert!(E::Top < E::Bottom); +/// ``` +/// +/// However, manually setting the discriminants can override this default behavior: +/// +/// ``` +/// #[derive(PartialEq, Eq, PartialOrd, Ord)] +/// enum E { +/// Top = 2, +/// Bottom = 1, +/// } +/// +/// assert!(E::Bottom < E::Top); +/// ``` +/// +/// ## Lexicographical comparison +/// +/// Lexicographical comparison is an operation with the following properties: +/// - Two sequences are compared element by element. +/// - The first mismatching element defines which sequence is lexicographically less or greater +/// than the other. +/// - If one sequence is a prefix of another, the shorter sequence is lexicographically less than +/// the other. +/// - If two sequences have equivalent elements and are of the same length, then the sequences are +/// lexicographically equal. +/// - An empty sequence is lexicographically less than any non-empty sequence. +/// - Two empty sequences are lexicographically equal. +/// +/// ## How can I implement `Ord`? +/// +/// `Ord` requires that the type also be [`PartialOrd`], [`PartialEq`], and [`Eq`]. +/// +/// Because `Ord` implies a stronger ordering relationship than [`PartialOrd`], and both `Ord` and +/// [`PartialOrd`] must agree, you must choose how to implement `Ord` **first**. You can choose to +/// derive it, or implement it manually. If you derive it, you should derive all four traits. If you +/// implement it manually, you should manually implement all four traits, based on the +/// implementation of `Ord`. +/// +/// Here's an example where you want to define the `Character` comparison by `health` and +/// `experience` only, disregarding the field `mana`: +/// +/// ``` +/// use std::cmp::Ordering; +/// +/// struct Character { +/// health: u32, +/// experience: u32, +/// mana: f32, +/// } +/// +/// impl Ord for Character { +/// fn cmp(&self, other: &Self) -> std::cmp::Ordering { +/// self.experience +/// .cmp(&other.experience) +/// .then(self.health.cmp(&other.health)) +/// } +/// } +/// +/// impl PartialOrd for Character { +/// fn partial_cmp(&self, other: &Self) -> Option { +/// Some(self.cmp(other)) +/// } +/// } +/// +/// impl PartialEq for Character { +/// fn eq(&self, other: &Self) -> bool { +/// self.health == other.health && self.experience == other.experience +/// } +/// } +/// +/// impl Eq for Character {} +/// ``` +/// +/// If all you need is to `slice::sort` a type by a field value, it can be simpler to use +/// `slice::sort_by_key`. +/// +/// ## Examples of incorrect `Ord` implementations +/// +/// ``` +/// use std::cmp::Ordering; +/// +/// #[derive(Debug)] +/// struct Character { +/// health: f32, +/// } +/// +/// impl Ord for Character { +/// fn cmp(&self, other: &Self) -> std::cmp::Ordering { +/// if self.health < other.health { +/// Ordering::Less +/// } else if self.health > other.health { +/// Ordering::Greater +/// } else { +/// Ordering::Equal +/// } +/// } +/// } +/// +/// impl PartialOrd for Character { +/// fn partial_cmp(&self, other: &Self) -> Option { +/// Some(self.cmp(other)) +/// } +/// } +/// +/// impl PartialEq for Character { +/// fn eq(&self, other: &Self) -> bool { +/// self.health == other.health +/// } +/// } +/// +/// impl Eq for Character {} +/// +/// let a = Character { health: 4.5 }; +/// let b = Character { health: f32::NAN }; +/// +/// // Mistake: floating-point values do not form a total order and using the built-in comparison +/// // operands to implement `Ord` irregardless of that reality does not change it. Use +/// // `f32::total_cmp` if you need a total order for floating-point values. +/// +/// // Reflexivity requirement of `Ord` is not given. +/// assert!(a == a); +/// assert!(b != b); +/// +/// // Antisymmetry requirement of `Ord` is not given. Only one of a < c and c < a is allowed to be +/// // true, not both or neither. +/// assert_eq!((a < b) as u8 + (b < a) as u8, 0); +/// ``` +/// +/// ``` +/// use std::cmp::Ordering; +/// +/// #[derive(Debug)] +/// struct Character { +/// health: u32, +/// experience: u32, +/// } +/// +/// impl PartialOrd for Character { +/// fn partial_cmp(&self, other: &Self) -> Option { +/// Some(self.cmp(other)) +/// } +/// } +/// +/// impl Ord for Character { +/// fn cmp(&self, other: &Self) -> std::cmp::Ordering { +/// if self.health < 50 { +/// self.health.cmp(&other.health) +/// } else { +/// self.experience.cmp(&other.experience) +/// } +/// } +/// } +/// +/// // For performance reasons implementing `PartialEq` this way is not the idiomatic way, but it +/// // ensures consistent behavior between `PartialEq`, `PartialOrd` and `Ord` in this example. +/// impl PartialEq for Character { +/// fn eq(&self, other: &Self) -> bool { +/// self.cmp(other) == Ordering::Equal +/// } +/// } +/// +/// impl Eq for Character {} +/// +/// let a = Character { +/// health: 3, +/// experience: 5, +/// }; +/// let b = Character { +/// health: 10, +/// experience: 77, +/// }; +/// let c = Character { +/// health: 143, +/// experience: 2, +/// }; +/// +/// // Mistake: The implementation of `Ord` compares different fields depending on the value of +/// // `self.health`, the resulting order is not total. +/// +/// // Transitivity requirement of `Ord` is not given. If a is smaller than b and b is smaller than +/// // c, by transitive property a must also be smaller than c. +/// assert!(a < b && b < c && c < a); +/// +/// // Antisymmetry requirement of `Ord` is not given. Only one of a < c and c < a is allowed to be +/// // true, not both or neither. +/// assert_eq!((a < c) as u8 + (c < a) as u8, 2); +/// ``` +/// +/// The documentation of [`PartialOrd`] contains further examples, for example it's wrong for +/// [`PartialOrd`] and [`PartialEq`] to disagree. +/// +/// [`cmp`]: Ord::cmp +#[doc(alias = "<")] +#[doc(alias = ">")] +#[doc(alias = "<=")] +#[doc(alias = ">=")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Ord"] +pub trait Ord: Eq + PartialOrd { + /// This method returns an [`Ordering`] between `self` and `other`. + /// + /// By convention, `self.cmp(&other)` returns the ordering matching the expression + /// `self other` if true. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(5.cmp(&10), Ordering::Less); + /// assert_eq!(10.cmp(&5), Ordering::Greater); + /// assert_eq!(5.cmp(&5), Ordering::Equal); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "ord_cmp_method"] + fn cmp(&self, other: &Self) -> Ordering; + + /// Compares and returns the maximum of two values. + /// + /// Returns the second argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1.max(2), 2); + /// assert_eq!(2.max(2), 2); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[inline] + #[must_use] + #[rustc_diagnostic_item = "cmp_ord_max"] + fn max(self, other: Self) -> Self + where + Self: Sized, + { + max_by(self, other, Ord::cmp) + } + + /// Compares and returns the minimum of two values. + /// + /// Returns the first argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1.min(2), 1); + /// assert_eq!(2.min(2), 2); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[inline] + #[must_use] + #[rustc_diagnostic_item = "cmp_ord_min"] + fn min(self, other: Self) -> Self + where + Self: Sized, + { + min_by(self, other, Ord::cmp) + } + + /// Restrict a value to a certain interval. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// # Panics + /// + /// Panics if `min > max`. + /// + /// # Examples + /// + /// ``` + /// assert_eq!((-3).clamp(-2, 1), -2); + /// assert_eq!(0.clamp(-2, 1), 0); + /// assert_eq!(2.clamp(-2, 1), 1); + /// ``` + #[must_use] + #[inline] + #[stable(feature = "clamp", since = "1.50.0")] + fn clamp(self, min: Self, max: Self) -> Self + where + Self: Sized, + { + assert!(min <= max); + if self < min { + min + } else if self > max { + max + } else { + self + } + } +} + +/// Derive macro generating an impl of the trait [`Ord`]. +/// The behavior of this macro is described in detail [here](Ord#derivable). +#[rustc_builtin_macro] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics)] +pub macro Ord($item:item) { + /* compiler built-in */ +} + +/// Trait for types that form a [partial order](https://en.wikipedia.org/wiki/Partial_order). +/// +/// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using the `<`, `<=`, `>`, and +/// `>=` operators, respectively. +/// +/// This trait should **only** contain the comparison logic for a type **if one plans on only +/// implementing `PartialOrd` but not [`Ord`]**. Otherwise the comparison logic should be in [`Ord`] +/// and this trait implemented with `Some(self.cmp(other))`. +/// +/// The methods of this trait must be consistent with each other and with those of [`PartialEq`]. +/// The following conditions must hold: +/// +/// 1. `a == b` if and only if `partial_cmp(a, b) == Some(Equal)`. +/// 2. `a < b` if and only if `partial_cmp(a, b) == Some(Less)` +/// 3. `a > b` if and only if `partial_cmp(a, b) == Some(Greater)` +/// 4. `a <= b` if and only if `a < b || a == b` +/// 5. `a >= b` if and only if `a > b || a == b` +/// 6. `a != b` if and only if `!(a == b)`. +/// +/// Conditions 2–5 above are ensured by the default implementation. Condition 6 is already ensured +/// by [`PartialEq`]. +/// +/// If [`Ord`] is also implemented for `Self` and `Rhs`, it must also be consistent with +/// `partial_cmp` (see the documentation of that trait for the exact requirements). It's easy to +/// accidentally make them disagree by deriving some of the traits and manually implementing others. +/// +/// The comparison relations must satisfy the following conditions (for all `a`, `b`, `c` of type +/// `A`, `B`, `C`): +/// +/// - **Transitivity**: if `A: PartialOrd` and `B: PartialOrd` and `A: PartialOrd`, then `a +/// < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. This must also +/// work for longer chains, such as when `A: PartialOrd`, `B: PartialOrd`, `C: +/// PartialOrd`, and `A: PartialOrd` all exist. +/// - **Duality**: if `A: PartialOrd` and `B: PartialOrd`, then `a < b` if and only if `b > +/// a`. +/// +/// Note that the `B: PartialOrd` (dual) and `A: PartialOrd` (transitive) impls are not forced +/// to exist, but these requirements apply whenever they do exist. +/// +/// Violating these requirements is a logic error. The behavior resulting from a logic error is not +/// specified, but users of the trait must ensure that such logic errors do *not* result in +/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these +/// methods. +/// +/// ## Cross-crate considerations +/// +/// Upholding the requirements stated above can become tricky when one crate implements `PartialOrd` +/// for a type of another crate (i.e., to allow comparing one of its own types with a type from the +/// standard library). The recommendation is to never implement this trait for a foreign type. In +/// other words, such a crate should do `impl PartialOrd for LocalType`, but it should +/// *not* do `impl PartialOrd for ForeignType`. +/// +/// This avoids the problem of transitive chains that criss-cross crate boundaries: for all local +/// types `T`, you may assume that no other crate will add `impl`s that allow comparing `T < U`. In +/// other words, if other crates add `impl`s that allow building longer transitive chains `U1 < ... +/// < T < V1 < ...`, then all the types that appear to the right of `T` must be types that the crate +/// defining `T` already knows about. This rules out transitive chains where downstream crates can +/// add new `impl`s that "stitch together" comparisons of foreign types in ways that violate +/// transitivity. +/// +/// Not having such foreign `impl`s also avoids forward compatibility issues where one crate adding +/// more `PartialOrd` implementations can cause build failures in downstream crates. +/// +/// ## Corollaries +/// +/// The following corollaries follow from the above requirements: +/// +/// - irreflexivity of `<` and `>`: `!(a < a)`, `!(a > a)` +/// - transitivity of `>`: if `a > b` and `b > c` then `a > c` +/// - duality of `partial_cmp`: `partial_cmp(a, b) == partial_cmp(b, a).map(Ordering::reverse)` +/// +/// ## Strict and non-strict partial orders +/// +/// The `<` and `>` operators behave according to a *strict* partial order. However, `<=` and `>=` +/// do **not** behave according to a *non-strict* partial order. That is because mathematically, a +/// non-strict partial order would require reflexivity, i.e. `a <= a` would need to be true for +/// every `a`. This isn't always the case for types that implement `PartialOrd`, for example: +/// +/// ``` +/// let a = f64::sqrt(-1.0); +/// assert_eq!(a <= a, false); +/// ``` +/// +/// ## Derivable +/// +/// This trait can be used with `#[derive]`. +/// +/// When `derive`d on structs, it will produce a +/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering based on the +/// top-to-bottom declaration order of the struct's members. +/// +/// When `derive`d on enums, variants are primarily ordered by their discriminants. Secondarily, +/// they are ordered by their fields. By default, the discriminant is smallest for variants at the +/// top, and largest for variants at the bottom. Here's an example: +/// +/// ``` +/// #[derive(PartialEq, PartialOrd)] +/// enum E { +/// Top, +/// Bottom, +/// } +/// +/// assert!(E::Top < E::Bottom); +/// ``` +/// +/// However, manually setting the discriminants can override this default behavior: +/// +/// ``` +/// #[derive(PartialEq, PartialOrd)] +/// enum E { +/// Top = 2, +/// Bottom = 1, +/// } +/// +/// assert!(E::Bottom < E::Top); +/// ``` +/// +/// ## How can I implement `PartialOrd`? +/// +/// `PartialOrd` only requires implementation of the [`partial_cmp`] method, with the others +/// generated from default implementations. +/// +/// However it remains possible to implement the others separately for types which do not have a +/// total order. For example, for floating point numbers, `NaN < 0 == false` and `NaN >= 0 == false` +/// (cf. IEEE 754-2008 section 5.11). +/// +/// `PartialOrd` requires your type to be [`PartialEq`]. +/// +/// If your type is [`Ord`], you can implement [`partial_cmp`] by using [`cmp`]: +/// +/// ``` +/// use std::cmp::Ordering; +/// +/// struct Person { +/// id: u32, +/// name: String, +/// height: u32, +/// } +/// +/// impl PartialOrd for Person { +/// fn partial_cmp(&self, other: &Self) -> Option { +/// Some(self.cmp(other)) +/// } +/// } +/// +/// impl Ord for Person { +/// fn cmp(&self, other: &Self) -> Ordering { +/// self.height.cmp(&other.height) +/// } +/// } +/// +/// impl PartialEq for Person { +/// fn eq(&self, other: &Self) -> bool { +/// self.height == other.height +/// } +/// } +/// +/// impl Eq for Person {} +/// ``` +/// +/// You may also find it useful to use [`partial_cmp`] on your type's fields. Here is an example of +/// `Person` types who have a floating-point `height` field that is the only field to be used for +/// sorting: +/// +/// ``` +/// use std::cmp::Ordering; +/// +/// struct Person { +/// id: u32, +/// name: String, +/// height: f64, +/// } +/// +/// impl PartialOrd for Person { +/// fn partial_cmp(&self, other: &Self) -> Option { +/// self.height.partial_cmp(&other.height) +/// } +/// } +/// +/// impl PartialEq for Person { +/// fn eq(&self, other: &Self) -> bool { +/// self.height == other.height +/// } +/// } +/// ``` +/// +/// ## Examples of incorrect `PartialOrd` implementations +/// +/// ``` +/// use std::cmp::Ordering; +/// +/// #[derive(PartialEq, Debug)] +/// struct Character { +/// health: u32, +/// experience: u32, +/// } +/// +/// impl PartialOrd for Character { +/// fn partial_cmp(&self, other: &Self) -> Option { +/// Some(self.health.cmp(&other.health)) +/// } +/// } +/// +/// let a = Character { +/// health: 10, +/// experience: 5, +/// }; +/// let b = Character { +/// health: 10, +/// experience: 77, +/// }; +/// +/// // Mistake: `PartialEq` and `PartialOrd` disagree with each other. +/// +/// assert_eq!(a.partial_cmp(&b).unwrap(), Ordering::Equal); // a == b according to `PartialOrd`. +/// assert_ne!(a, b); // a != b according to `PartialEq`. +/// ``` +/// +/// # Examples +/// +/// ``` +/// let x: u32 = 0; +/// let y: u32 = 1; +/// +/// assert_eq!(x < y, true); +/// assert_eq!(x.lt(&y), true); +/// ``` +/// +/// [`partial_cmp`]: PartialOrd::partial_cmp +/// [`cmp`]: Ord::cmp +#[lang = "partial_ord"] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = ">")] +#[doc(alias = "<")] +#[doc(alias = "<=")] +#[doc(alias = ">=")] +#[rustc_on_unimplemented( + message = "can't compare `{Self}` with `{Rhs}`", + label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`", + append_const_msg +)] +#[rustc_diagnostic_item = "PartialOrd"] +pub trait PartialOrd: PartialEq { + /// This method returns an ordering between `self` and `other` values if one exists. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// let result = 1.0.partial_cmp(&2.0); + /// assert_eq!(result, Some(Ordering::Less)); + /// + /// let result = 1.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Equal)); + /// + /// let result = 2.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Greater)); + /// ``` + /// + /// When comparison is impossible: + /// + /// ``` + /// let result = f64::NAN.partial_cmp(&1.0); + /// assert_eq!(result, None); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "cmp_partialord_cmp"] + fn partial_cmp(&self, other: &Rhs) -> Option; + + /// Tests less than (for `self` and `other`) and is used by the `<` operator. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1.0 < 1.0, false); + /// assert_eq!(1.0 < 2.0, true); + /// assert_eq!(2.0 < 1.0, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "cmp_partialord_lt"] + fn lt(&self, other: &Rhs) -> bool { + matches!(self.partial_cmp(other), Some(Less)) + } + + /// Tests less than or equal to (for `self` and `other`) and is used by the + /// `<=` operator. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1.0 <= 1.0, true); + /// assert_eq!(1.0 <= 2.0, true); + /// assert_eq!(2.0 <= 1.0, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "cmp_partialord_le"] + fn le(&self, other: &Rhs) -> bool { + matches!(self.partial_cmp(other), Some(Less | Equal)) + } + + /// Tests greater than (for `self` and `other`) and is used by the `>` + /// operator. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1.0 > 1.0, false); + /// assert_eq!(1.0 > 2.0, false); + /// assert_eq!(2.0 > 1.0, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "cmp_partialord_gt"] + fn gt(&self, other: &Rhs) -> bool { + matches!(self.partial_cmp(other), Some(Greater)) + } + + /// Tests greater than or equal to (for `self` and `other`) and is used by + /// the `>=` operator. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1.0 >= 1.0, true); + /// assert_eq!(1.0 >= 2.0, false); + /// assert_eq!(2.0 >= 1.0, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "cmp_partialord_ge"] + fn ge(&self, other: &Rhs) -> bool { + matches!(self.partial_cmp(other), Some(Greater | Equal)) + } +} + +/// Derive macro generating an impl of the trait [`PartialOrd`]. +/// The behavior of this macro is described in detail [here](PartialOrd#derivable). +#[rustc_builtin_macro] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics)] +pub macro PartialOrd($item:item) { + /* compiler built-in */ +} + +/// Compares and returns the minimum of two values. +/// +/// Returns the first argument if the comparison determines them to be equal. +/// +/// Internally uses an alias to [`Ord::min`]. +/// +/// # Examples +/// +/// ``` +/// use std::cmp; +/// +/// assert_eq!(cmp::min(1, 2), 1); +/// assert_eq!(cmp::min(2, 2), 2); +/// ``` +#[inline] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "cmp_min")] +pub fn min(v1: T, v2: T) -> T { + v1.min(v2) +} + +/// Returns the minimum of two values with respect to the specified comparison function. +/// +/// Returns the first argument if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// use std::cmp; +/// +/// let result = cmp::min_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())); +/// assert_eq!(result, 1); +/// +/// let result = cmp::min_by(-2, 3, |x: &i32, y: &i32| x.abs().cmp(&y.abs())); +/// assert_eq!(result, -2); +/// ``` +#[inline] +#[must_use] +#[stable(feature = "cmp_min_max_by", since = "1.53.0")] +pub fn min_by Ordering>(v1: T, v2: T, compare: F) -> T { + match compare(&v1, &v2) { + Ordering::Less | Ordering::Equal => v1, + Ordering::Greater => v2, + } +} + +/// Returns the element that gives the minimum value from the specified function. +/// +/// Returns the first argument if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// use std::cmp; +/// +/// let result = cmp::min_by_key(-2, 1, |x: &i32| x.abs()); +/// assert_eq!(result, 1); +/// +/// let result = cmp::min_by_key(-2, 2, |x: &i32| x.abs()); +/// assert_eq!(result, -2); +/// ``` +#[inline] +#[must_use] +#[stable(feature = "cmp_min_max_by", since = "1.53.0")] +pub fn min_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { + min_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) +} + +/// Compares and returns the maximum of two values. +/// +/// Returns the second argument if the comparison determines them to be equal. +/// +/// Internally uses an alias to [`Ord::max`]. +/// +/// # Examples +/// +/// ``` +/// use std::cmp; +/// +/// assert_eq!(cmp::max(1, 2), 2); +/// assert_eq!(cmp::max(2, 2), 2); +/// ``` +#[inline] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "cmp_max")] +pub fn max(v1: T, v2: T) -> T { + v1.max(v2) +} + +/// Returns the maximum of two values with respect to the specified comparison function. +/// +/// Returns the second argument if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// use std::cmp; +/// +/// let result = cmp::max_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())); +/// assert_eq!(result, -2); +/// +/// let result = cmp::max_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())) ; +/// assert_eq!(result, 2); +/// ``` +#[inline] +#[must_use] +#[stable(feature = "cmp_min_max_by", since = "1.53.0")] +pub fn max_by Ordering>(v1: T, v2: T, compare: F) -> T { + match compare(&v1, &v2) { + Ordering::Less | Ordering::Equal => v2, + Ordering::Greater => v1, + } +} + +/// Returns the element that gives the maximum value from the specified function. +/// +/// Returns the second argument if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// use std::cmp; +/// +/// let result = cmp::max_by_key(-2, 1, |x: &i32| x.abs()); +/// assert_eq!(result, -2); +/// +/// let result = cmp::max_by_key(-2, 2, |x: &i32| x.abs()); +/// assert_eq!(result, 2); +/// ``` +#[inline] +#[must_use] +#[stable(feature = "cmp_min_max_by", since = "1.53.0")] +pub fn max_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { + max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) +} + +/// Compares and sorts two values, returning minimum and maximum. +/// +/// Returns `[v1, v2]` if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_minmax)] +/// use std::cmp; +/// +/// assert_eq!(cmp::minmax(1, 2), [1, 2]); +/// assert_eq!(cmp::minmax(2, 2), [2, 2]); +/// +/// // You can destructure the result using array patterns +/// let [min, max] = cmp::minmax(42, 17); +/// assert_eq!(min, 17); +/// assert_eq!(max, 42); +/// ``` +#[inline] +#[must_use] +#[unstable(feature = "cmp_minmax", issue = "115939")] +pub fn minmax(v1: T, v2: T) -> [T; 2] +where + T: Ord, +{ + if v1 <= v2 { [v1, v2] } else { [v2, v1] } +} + +/// Returns minimum and maximum values with respect to the specified comparison function. +/// +/// Returns `[v1, v2]` if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_minmax)] +/// use std::cmp; +/// +/// assert_eq!(cmp::minmax_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), [1, -2]); +/// assert_eq!(cmp::minmax_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), [-2, 2]); +/// +/// // You can destructure the result using array patterns +/// let [min, max] = cmp::minmax_by(-42, 17, |x: &i32, y: &i32| x.abs().cmp(&y.abs())); +/// assert_eq!(min, 17); +/// assert_eq!(max, -42); +/// ``` +#[inline] +#[must_use] +#[unstable(feature = "cmp_minmax", issue = "115939")] +pub fn minmax_by(v1: T, v2: T, compare: F) -> [T; 2] +where + F: FnOnce(&T, &T) -> Ordering, +{ + if compare(&v1, &v2).is_le() { [v1, v2] } else { [v2, v1] } +} + +/// Returns minimum and maximum values with respect to the specified key function. +/// +/// Returns `[v1, v2]` if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_minmax)] +/// use std::cmp; +/// +/// assert_eq!(cmp::minmax_by_key(-2, 1, |x: &i32| x.abs()), [1, -2]); +/// assert_eq!(cmp::minmax_by_key(-2, 2, |x: &i32| x.abs()), [-2, 2]); +/// +/// // You can destructure the result using array patterns +/// let [min, max] = cmp::minmax_by_key(-42, 17, |x: &i32| x.abs()); +/// assert_eq!(min, 17); +/// assert_eq!(max, -42); +/// ``` +#[inline] +#[must_use] +#[unstable(feature = "cmp_minmax", issue = "115939")] +pub fn minmax_by_key(v1: T, v2: T, mut f: F) -> [T; 2] +where + F: FnMut(&T) -> K, + K: Ord, +{ + minmax_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) +} + +// Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types +mod impls { + use crate::cmp::Ordering::{self, Equal, Greater, Less}; + use crate::hint::unreachable_unchecked; + + macro_rules! partial_eq_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl PartialEq for $t { + #[inline] + fn eq(&self, other: &$t) -> bool { (*self) == (*other) } + #[inline] + fn ne(&self, other: &$t) -> bool { (*self) != (*other) } + } + )*) + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl PartialEq for () { + #[inline] + fn eq(&self, _other: &()) -> bool { + true + } + #[inline] + fn ne(&self, _other: &()) -> bool { + false + } + } + + partial_eq_impl! { + bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 + } + + macro_rules! eq_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Eq for $t {} + )*) + } + + eq_impl! { () bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + + macro_rules! partial_ord_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl PartialOrd for $t { + #[inline] + fn partial_cmp(&self, other: &$t) -> Option { + match (*self <= *other, *self >= *other) { + (false, false) => None, + (false, true) => Some(Greater), + (true, false) => Some(Less), + (true, true) => Some(Equal), + } + } + #[inline(always)] + fn lt(&self, other: &$t) -> bool { (*self) < (*other) } + #[inline(always)] + fn le(&self, other: &$t) -> bool { (*self) <= (*other) } + #[inline(always)] + fn ge(&self, other: &$t) -> bool { (*self) >= (*other) } + #[inline(always)] + fn gt(&self, other: &$t) -> bool { (*self) > (*other) } + } + )*) + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl PartialOrd for () { + #[inline] + fn partial_cmp(&self, _: &()) -> Option { + Some(Equal) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl PartialOrd for bool { + #[inline] + fn partial_cmp(&self, other: &bool) -> Option { + Some(self.cmp(other)) + } + } + + partial_ord_impl! { f16 f32 f64 f128 } + + macro_rules! ord_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl PartialOrd for $t { + #[inline] + fn partial_cmp(&self, other: &$t) -> Option { + Some(crate::intrinsics::three_way_compare(*self, *other)) + } + #[inline(always)] + fn lt(&self, other: &$t) -> bool { (*self) < (*other) } + #[inline(always)] + fn le(&self, other: &$t) -> bool { (*self) <= (*other) } + #[inline(always)] + fn ge(&self, other: &$t) -> bool { (*self) >= (*other) } + #[inline(always)] + fn gt(&self, other: &$t) -> bool { (*self) > (*other) } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Ord for $t { + #[inline] + fn cmp(&self, other: &$t) -> Ordering { + crate::intrinsics::three_way_compare(*self, *other) + } + } + )*) + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Ord for () { + #[inline] + fn cmp(&self, _other: &()) -> Ordering { + Equal + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Ord for bool { + #[inline] + fn cmp(&self, other: &bool) -> Ordering { + // Casting to i8's and converting the difference to an Ordering generates + // more optimal assembly. + // See for more info. + match (*self as i8) - (*other as i8) { + -1 => Less, + 0 => Equal, + 1 => Greater, + // SAFETY: bool as i8 returns 0 or 1, so the difference can't be anything else + _ => unsafe { unreachable_unchecked() }, + } + } + + #[inline] + fn min(self, other: bool) -> bool { + self & other + } + + #[inline] + fn max(self, other: bool) -> bool { + self | other + } + + #[inline] + fn clamp(self, min: bool, max: bool) -> bool { + assert!(min <= max); + self.max(min).min(max) + } + } + + ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + + #[unstable(feature = "never_type", issue = "35121")] + impl PartialEq for ! { + #[inline] + fn eq(&self, _: &!) -> bool { + *self + } + } + + #[unstable(feature = "never_type", issue = "35121")] + impl Eq for ! {} + + #[unstable(feature = "never_type", issue = "35121")] + impl PartialOrd for ! { + #[inline] + fn partial_cmp(&self, _: &!) -> Option { + *self + } + } + + #[unstable(feature = "never_type", issue = "35121")] + impl Ord for ! { + #[inline] + fn cmp(&self, _: &!) -> Ordering { + *self + } + } + + // & pointers + + #[stable(feature = "rust1", since = "1.0.0")] + impl PartialEq<&B> for &A + where + A: PartialEq, + { + #[inline] + fn eq(&self, other: &&B) -> bool { + PartialEq::eq(*self, *other) + } + #[inline] + fn ne(&self, other: &&B) -> bool { + PartialEq::ne(*self, *other) + } + } + #[stable(feature = "rust1", since = "1.0.0")] + impl PartialOrd<&B> for &A + where + A: PartialOrd, + { + #[inline] + fn partial_cmp(&self, other: &&B) -> Option { + PartialOrd::partial_cmp(*self, *other) + } + #[inline] + fn lt(&self, other: &&B) -> bool { + PartialOrd::lt(*self, *other) + } + #[inline] + fn le(&self, other: &&B) -> bool { + PartialOrd::le(*self, *other) + } + #[inline] + fn gt(&self, other: &&B) -> bool { + PartialOrd::gt(*self, *other) + } + #[inline] + fn ge(&self, other: &&B) -> bool { + PartialOrd::ge(*self, *other) + } + } + #[stable(feature = "rust1", since = "1.0.0")] + impl Ord for &A + where + A: Ord, + { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(*self, *other) + } + } + #[stable(feature = "rust1", since = "1.0.0")] + impl Eq for &A where A: Eq {} + + // &mut pointers + + #[stable(feature = "rust1", since = "1.0.0")] + impl PartialEq<&mut B> for &mut A + where + A: PartialEq, + { + #[inline] + fn eq(&self, other: &&mut B) -> bool { + PartialEq::eq(*self, *other) + } + #[inline] + fn ne(&self, other: &&mut B) -> bool { + PartialEq::ne(*self, *other) + } + } + #[stable(feature = "rust1", since = "1.0.0")] + impl PartialOrd<&mut B> for &mut A + where + A: PartialOrd, + { + #[inline] + fn partial_cmp(&self, other: &&mut B) -> Option { + PartialOrd::partial_cmp(*self, *other) + } + #[inline] + fn lt(&self, other: &&mut B) -> bool { + PartialOrd::lt(*self, *other) + } + #[inline] + fn le(&self, other: &&mut B) -> bool { + PartialOrd::le(*self, *other) + } + #[inline] + fn gt(&self, other: &&mut B) -> bool { + PartialOrd::gt(*self, *other) + } + #[inline] + fn ge(&self, other: &&mut B) -> bool { + PartialOrd::ge(*self, *other) + } + } + #[stable(feature = "rust1", since = "1.0.0")] + impl Ord for &mut A + where + A: Ord, + { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(*self, *other) + } + } + #[stable(feature = "rust1", since = "1.0.0")] + impl Eq for &mut A where A: Eq {} + + #[stable(feature = "rust1", since = "1.0.0")] + impl PartialEq<&mut B> for &A + where + A: PartialEq, + { + #[inline] + fn eq(&self, other: &&mut B) -> bool { + PartialEq::eq(*self, *other) + } + #[inline] + fn ne(&self, other: &&mut B) -> bool { + PartialEq::ne(*self, *other) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl PartialEq<&B> for &mut A + where + A: PartialEq, + { + #[inline] + fn eq(&self, other: &&B) -> bool { + PartialEq::eq(*self, *other) + } + #[inline] + fn ne(&self, other: &&B) -> bool { + PartialEq::ne(*self, *other) + } + } +} diff --git a/CoqOfRust/core/cmp/bytewise.rs b/CoqOfRust/core/cmp/bytewise.rs new file mode 100644 index 000000000..a06a5227f --- /dev/null +++ b/CoqOfRust/core/cmp/bytewise.rs @@ -0,0 +1,82 @@ +use crate::num::NonZero; + +/// Types where `==` & `!=` are equivalent to comparing their underlying bytes. +/// +/// Importantly, this means no floating-point types, as those have different +/// byte representations (like `-0` and `+0`) which compare as the same. +/// Since byte arrays are `Eq`, that implies that these types are probably also +/// `Eq`, but that's not technically required to use this trait. +/// +/// `Rhs` is *de facto* always `Self`, but the separate parameter is important +/// to avoid the `specializing impl repeats parameter` error when consuming this. +/// +/// # Safety +/// +/// - `Self` and `Rhs` have no padding. +/// - `Self` and `Rhs` have the same layout (size and alignment). +/// - Neither `Self` nor `Rhs` have provenance, so integer comparisons are correct. +/// - `>::{eq,ne}` are equivalent to comparing the bytes. +#[rustc_specialization_trait] +pub(crate) unsafe trait BytewiseEq: PartialEq + Sized {} + +macro_rules! is_bytewise_comparable { + ($($t:ty),+ $(,)?) => {$( + unsafe impl BytewiseEq for $t {} + )+}; +} + +// SAFETY: All the ordinary integer types have no padding, and are not pointers. +is_bytewise_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); + +// SAFETY: These have *niches*, but no *padding* and no *provenance*, +// so we can compare them directly. +is_bytewise_comparable!(bool, char, super::Ordering); + +// SAFETY: Similarly, the `NonZero` type has a niche, but no undef and no pointers, +// and they compare like their underlying numeric type. +is_bytewise_comparable!( + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, +); + +// SAFETY: The `NonZero` type has the "null" optimization guaranteed, and thus +// are also safe to equality-compare bitwise inside an `Option`. +// The way `PartialOrd` is defined for `Option` means that this wouldn't work +// for `<` or `>` on the signed types, but since we only do `==` it's fine. +is_bytewise_comparable!( + Option>, + Option>, + Option>, + Option>, + Option>, + Option>, + Option>, + Option>, + Option>, + Option>, + Option>, + Option>, +); + +macro_rules! is_bytewise_comparable_array_length { + ($($n:literal),+ $(,)?) => {$( + // SAFETY: Arrays have no padding between elements, so if the elements are + // `BytewiseEq`, then the whole array can be too. + unsafe impl, U> BytewiseEq<[U; $n]> for [T; $n] {} + )+}; +} + +// Frustratingly, this can't be made const-generic as it gets +// error: specializing impl repeats parameter `N` +// so just do it for a couple of plausibly-common ones. +is_bytewise_comparable_array_length!(0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64); diff --git a/CoqOfRust/core/convert/mod.rs b/CoqOfRust/core/convert/mod.rs new file mode 100644 index 000000000..432e55e8c --- /dev/null +++ b/CoqOfRust/core/convert/mod.rs @@ -0,0 +1,971 @@ +//! Traits for conversions between types. +//! +//! The traits in this module provide a way to convert from one type to another type. +//! Each trait serves a different purpose: +//! +//! - Implement the [`AsRef`] trait for cheap reference-to-reference conversions +//! - Implement the [`AsMut`] trait for cheap mutable-to-mutable conversions +//! - Implement the [`From`] trait for consuming value-to-value conversions +//! - Implement the [`Into`] trait for consuming value-to-value conversions to types +//! outside the current crate +//! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`], +//! but should be implemented when the conversion can fail. +//! +//! The traits in this module are often used as trait bounds for generic functions such that to +//! arguments of multiple types are supported. See the documentation of each trait for examples. +//! +//! As a library author, you should always prefer implementing [`From`][`From`] or +//! [`TryFrom`][`TryFrom`] rather than [`Into`][`Into`] or [`TryInto`][`TryInto`], +//! as [`From`] and [`TryFrom`] provide greater flexibility and offer +//! equivalent [`Into`] or [`TryInto`] implementations for free, thanks to a +//! blanket implementation in the standard library. When targeting a version prior to Rust 1.41, it +//! may be necessary to implement [`Into`] or [`TryInto`] directly when converting to a type +//! outside the current crate. +//! +//! # Generic Implementations +//! +//! - [`AsRef`] and [`AsMut`] auto-dereference if the inner type is a reference +//! (but not generally for all [dereferenceable types][core::ops::Deref]) +//! - [`From`]` for T` implies [`Into`]` for U` +//! - [`TryFrom`]` for T` implies [`TryInto`]` for U` +//! - [`From`] and [`Into`] are reflexive, which means that all types can +//! `into` themselves and `from` themselves +//! +//! See each trait for usage examples. + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::error::Error; +use crate::fmt; +use crate::hash::{Hash, Hasher}; + +mod num; + +#[unstable(feature = "convert_float_to_int", issue = "67057")] +pub use num::FloatToInt; + +/// The identity function. +/// +/// Two things are important to note about this function: +/// +/// - It is not always equivalent to a closure like `|x| x`, since the +/// closure may coerce `x` into a different type. +/// +/// - It moves the input `x` passed to the function. +/// +/// While it might seem strange to have a function that just returns back the +/// input, there are some interesting uses. +/// +/// # Examples +/// +/// Using `identity` to do nothing in a sequence of other, interesting, +/// functions: +/// +/// ```rust +/// use std::convert::identity; +/// +/// fn manipulation(x: u32) -> u32 { +/// // Let's pretend that adding one is an interesting function. +/// x + 1 +/// } +/// +/// let _arr = &[identity, manipulation]; +/// ``` +/// +/// Using `identity` as a "do nothing" base case in a conditional: +/// +/// ```rust +/// use std::convert::identity; +/// +/// # let condition = true; +/// # +/// # fn manipulation(x: u32) -> u32 { x + 1 } +/// # +/// let do_stuff = if condition { manipulation } else { identity }; +/// +/// // Do more interesting stuff... +/// +/// let _results = do_stuff(42); +/// ``` +/// +/// Using `identity` to keep the `Some` variants of an iterator of `Option`: +/// +/// ```rust +/// use std::convert::identity; +/// +/// let iter = [Some(1), None, Some(3)].into_iter(); +/// let filtered = iter.filter_map(identity).collect::>(); +/// assert_eq!(vec![1, 3], filtered); +/// ``` +#[stable(feature = "convert_id", since = "1.33.0")] +#[rustc_const_stable(feature = "const_identity", since = "1.33.0")] +#[inline(always)] +#[rustc_diagnostic_item = "convert_identity"] +pub const fn identity(x: T) -> T { + x +} + +/// Used to do a cheap reference-to-reference conversion. +/// +/// This trait is similar to [`AsMut`] which is used for converting between mutable references. +/// If you need to do a costly conversion it is better to implement [`From`] with type +/// `&T` or write a custom function. +/// +/// # Relation to `Borrow` +/// +/// `AsRef` has the same signature as [`Borrow`], but [`Borrow`] is different in a few aspects: +/// +/// - Unlike `AsRef`, [`Borrow`] has a blanket impl for any `T`, and can be used to accept either +/// a reference or a value. (See also note on `AsRef`'s reflexibility below.) +/// - [`Borrow`] also requires that [`Hash`], [`Eq`] and [`Ord`] for a borrowed value are +/// equivalent to those of the owned value. For this reason, if you want to +/// borrow only a single field of a struct you can implement `AsRef`, but not [`Borrow`]. +/// +/// **Note: This trait must not fail**. If the conversion can fail, use a +/// dedicated method which returns an [`Option`] or a [`Result`]. +/// +/// # Generic Implementations +/// +/// `AsRef` auto-dereferences if the inner type is a reference or a mutable reference +/// (e.g.: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`). +/// +/// Note that due to historic reasons, the above currently does not hold generally for all +/// [dereferenceable types], e.g. `foo.as_ref()` will *not* work the same as +/// `Box::new(foo).as_ref()`. Instead, many smart pointers provide an `as_ref` implementation which +/// simply returns a reference to the [pointed-to value] (but do not perform a cheap +/// reference-to-reference conversion for that value). However, [`AsRef::as_ref`] should not be +/// used for the sole purpose of dereferencing; instead ['`Deref` coercion'] can be used: +/// +/// [dereferenceable types]: core::ops::Deref +/// [pointed-to value]: core::ops::Deref::Target +/// ['`Deref` coercion']: core::ops::Deref#deref-coercion +/// +/// ``` +/// let x = Box::new(5i32); +/// // Avoid this: +/// // let y: &i32 = x.as_ref(); +/// // Better just write: +/// let y: &i32 = &x; +/// ``` +/// +/// Types which implement [`Deref`] should consider implementing `AsRef` as follows: +/// +/// [`Deref`]: core::ops::Deref +/// +/// ``` +/// # use core::ops::Deref; +/// # struct SomeType; +/// # impl Deref for SomeType { +/// # type Target = [u8]; +/// # fn deref(&self) -> &[u8] { +/// # &[] +/// # } +/// # } +/// impl AsRef for SomeType +/// where +/// T: ?Sized, +/// ::Target: AsRef, +/// { +/// fn as_ref(&self) -> &T { +/// self.deref().as_ref() +/// } +/// } +/// ``` +/// +/// # Reflexivity +/// +/// Ideally, `AsRef` would be reflexive, i.e. there would be an `impl AsRef for T` +/// with [`as_ref`] simply returning its argument unchanged. +/// Such a blanket implementation is currently *not* provided due to technical restrictions of +/// Rust's type system (it would be overlapping with another existing blanket implementation for +/// `&T where T: AsRef` which allows `AsRef` to auto-dereference, see "Generic Implementations" +/// above). +/// +/// [`as_ref`]: AsRef::as_ref +/// +/// A trivial implementation of `AsRef for T` must be added explicitly for a particular type `T` +/// where needed or desired. Note, however, that not all types from `std` contain such an +/// implementation, and those cannot be added by external code due to orphan rules. +/// +/// # Examples +/// +/// By using trait bounds we can accept arguments of different types as long as they can be +/// converted to the specified type `T`. +/// +/// For example: By creating a generic function that takes an `AsRef` we express that we +/// want to accept all references that can be converted to [`&str`] as an argument. +/// Since both [`String`] and [`&str`] implement `AsRef` we can accept both as input argument. +/// +/// [`&str`]: primitive@str +/// [`Borrow`]: crate::borrow::Borrow +/// [`Eq`]: crate::cmp::Eq +/// [`Ord`]: crate::cmp::Ord +/// [`String`]: ../../std/string/struct.String.html +/// +/// ``` +/// fn is_hello>(s: T) { +/// assert_eq!("hello", s.as_ref()); +/// } +/// +/// let s = "hello"; +/// is_hello(s); +/// +/// let s = "hello".to_string(); +/// is_hello(s); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "AsRef")] +pub trait AsRef { + /// Converts this type into a shared reference of the (usually inferred) input type. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_ref(&self) -> &T; +} + +/// Used to do a cheap mutable-to-mutable reference conversion. +/// +/// This trait is similar to [`AsRef`] but used for converting between mutable +/// references. If you need to do a costly conversion it is better to +/// implement [`From`] with type `&mut T` or write a custom function. +/// +/// **Note: This trait must not fail**. If the conversion can fail, use a +/// dedicated method which returns an [`Option`] or a [`Result`]. +/// +/// # Generic Implementations +/// +/// `AsMut` auto-dereferences if the inner type is a mutable reference +/// (e.g.: `foo.as_mut()` will work the same if `foo` has type `&mut Foo` or `&mut &mut Foo`). +/// +/// Note that due to historic reasons, the above currently does not hold generally for all +/// [mutably dereferenceable types], e.g. `foo.as_mut()` will *not* work the same as +/// `Box::new(foo).as_mut()`. Instead, many smart pointers provide an `as_mut` implementation which +/// simply returns a reference to the [pointed-to value] (but do not perform a cheap +/// reference-to-reference conversion for that value). However, [`AsMut::as_mut`] should not be +/// used for the sole purpose of mutable dereferencing; instead ['`Deref` coercion'] can be used: +/// +/// [mutably dereferenceable types]: core::ops::DerefMut +/// [pointed-to value]: core::ops::Deref::Target +/// ['`Deref` coercion']: core::ops::DerefMut#mutable-deref-coercion +/// +/// ``` +/// let mut x = Box::new(5i32); +/// // Avoid this: +/// // let y: &mut i32 = x.as_mut(); +/// // Better just write: +/// let y: &mut i32 = &mut x; +/// ``` +/// +/// Types which implement [`DerefMut`] should consider to add an implementation of `AsMut` as +/// follows: +/// +/// [`DerefMut`]: core::ops::DerefMut +/// +/// ``` +/// # use core::ops::{Deref, DerefMut}; +/// # struct SomeType; +/// # impl Deref for SomeType { +/// # type Target = [u8]; +/// # fn deref(&self) -> &[u8] { +/// # &[] +/// # } +/// # } +/// # impl DerefMut for SomeType { +/// # fn deref_mut(&mut self) -> &mut [u8] { +/// # &mut [] +/// # } +/// # } +/// impl AsMut for SomeType +/// where +/// ::Target: AsMut, +/// { +/// fn as_mut(&mut self) -> &mut T { +/// self.deref_mut().as_mut() +/// } +/// } +/// ``` +/// +/// # Reflexivity +/// +/// Ideally, `AsMut` would be reflexive, i.e. there would be an `impl AsMut for T` +/// with [`as_mut`] simply returning its argument unchanged. +/// Such a blanket implementation is currently *not* provided due to technical restrictions of +/// Rust's type system (it would be overlapping with another existing blanket implementation for +/// `&mut T where T: AsMut` which allows `AsMut` to auto-dereference, see "Generic +/// Implementations" above). +/// +/// [`as_mut`]: AsMut::as_mut +/// +/// A trivial implementation of `AsMut for T` must be added explicitly for a particular type `T` +/// where needed or desired. Note, however, that not all types from `std` contain such an +/// implementation, and those cannot be added by external code due to orphan rules. +/// +/// # Examples +/// +/// Using `AsMut` as trait bound for a generic function, we can accept all mutable references that +/// can be converted to type `&mut T`. Unlike [dereference], which has a single [target type], +/// there can be multiple implementations of `AsMut` for a type. In particular, `Vec` implements +/// both `AsMut>` and `AsMut<[T]>`. +/// +/// In the following, the example functions `caesar` and `null_terminate` provide a generic +/// interface which work with any type that can be converted by cheap mutable-to-mutable conversion +/// into a byte slice (`[u8]`) or byte vector (`Vec`), respectively. +/// +/// [dereference]: core::ops::DerefMut +/// [target type]: core::ops::Deref::Target +/// +/// ``` +/// struct Document { +/// info: String, +/// content: Vec, +/// } +/// +/// impl AsMut for Document +/// where +/// Vec: AsMut, +/// { +/// fn as_mut(&mut self) -> &mut T { +/// self.content.as_mut() +/// } +/// } +/// +/// fn caesar>(data: &mut T, key: u8) { +/// for byte in data.as_mut() { +/// *byte = byte.wrapping_add(key); +/// } +/// } +/// +/// fn null_terminate>>(data: &mut T) { +/// // Using a non-generic inner function, which contains most of the +/// // functionality, helps to minimize monomorphization overhead. +/// fn doit(data: &mut Vec) { +/// let len = data.len(); +/// if len == 0 || data[len-1] != 0 { +/// data.push(0); +/// } +/// } +/// doit(data.as_mut()); +/// } +/// +/// fn main() { +/// let mut v: Vec = vec![1, 2, 3]; +/// caesar(&mut v, 5); +/// assert_eq!(v, [6, 7, 8]); +/// null_terminate(&mut v); +/// assert_eq!(v, [6, 7, 8, 0]); +/// let mut doc = Document { +/// info: String::from("Example"), +/// content: vec![17, 19, 8], +/// }; +/// caesar(&mut doc, 1); +/// assert_eq!(doc.content, [18, 20, 9]); +/// null_terminate(&mut doc); +/// assert_eq!(doc.content, [18, 20, 9, 0]); +/// } +/// ``` +/// +/// Note, however, that APIs don't need to be generic. In many cases taking a `&mut [u8]` or +/// `&mut Vec`, for example, is the better choice (callers need to pass the correct type then). +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "AsMut")] +pub trait AsMut { + /// Converts this type into a mutable reference of the (usually inferred) input type. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_mut(&mut self) -> &mut T; +} + +/// A value-to-value conversion that consumes the input value. The +/// opposite of [`From`]. +/// +/// One should avoid implementing [`Into`] and implement [`From`] instead. +/// Implementing [`From`] automatically provides one with an implementation of [`Into`] +/// thanks to the blanket implementation in the standard library. +/// +/// Prefer using [`Into`] over [`From`] when specifying trait bounds on a generic function +/// to ensure that types that only implement [`Into`] can be used as well. +/// +/// **Note: This trait must not fail**. If the conversion can fail, use [`TryInto`]. +/// +/// # Generic Implementations +/// +/// - [`From`]` for U` implies `Into for T` +/// - [`Into`] is reflexive, which means that `Into for T` is implemented +/// +/// # Implementing [`Into`] for conversions to external types in old versions of Rust +/// +/// Prior to Rust 1.41, if the destination type was not part of the current crate +/// then you couldn't implement [`From`] directly. +/// For example, take this code: +/// +/// ``` +/// # #![allow(non_local_definitions)] +/// struct Wrapper(Vec); +/// impl From> for Vec { +/// fn from(w: Wrapper) -> Vec { +/// w.0 +/// } +/// } +/// ``` +/// This will fail to compile in older versions of the language because Rust's orphaning rules +/// used to be a little bit more strict. To bypass this, you could implement [`Into`] directly: +/// +/// ``` +/// struct Wrapper(Vec); +/// impl Into> for Wrapper { +/// fn into(self) -> Vec { +/// self.0 +/// } +/// } +/// ``` +/// +/// It is important to understand that [`Into`] does not provide a [`From`] implementation +/// (as [`From`] does with [`Into`]). Therefore, you should always try to implement [`From`] +/// and then fall back to [`Into`] if [`From`] can't be implemented. +/// +/// # Examples +/// +/// [`String`] implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>`: +/// +/// In order to express that we want a generic function to take all arguments that can be +/// converted to a specified type `T`, we can use a trait bound of [`Into`]``. +/// For example: The function `is_hello` takes all arguments that can be converted into a +/// [`Vec`]`<`[`u8`]`>`. +/// +/// ``` +/// fn is_hello>>(s: T) { +/// let bytes = b"hello".to_vec(); +/// assert_eq!(bytes, s.into()); +/// } +/// +/// let s = "hello".to_string(); +/// is_hello(s); +/// ``` +/// +/// [`String`]: ../../std/string/struct.String.html +/// [`Vec`]: ../../std/vec/struct.Vec.html +#[rustc_diagnostic_item = "Into"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Into: Sized { + /// Converts this type into the (usually inferred) input type. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn into(self) -> T; +} + +/// Used to do value-to-value conversions while consuming the input value. It is the reciprocal of +/// [`Into`]. +/// +/// One should always prefer implementing `From` over [`Into`] +/// because implementing `From` automatically provides one with an implementation of [`Into`] +/// thanks to the blanket implementation in the standard library. +/// +/// Only implement [`Into`] when targeting a version prior to Rust 1.41 and converting to a type +/// outside the current crate. +/// `From` was not able to do these types of conversions in earlier versions because of Rust's +/// orphaning rules. +/// See [`Into`] for more details. +/// +/// Prefer using [`Into`] over using `From` when specifying trait bounds on a generic function. +/// This way, types that directly implement [`Into`] can be used as arguments as well. +/// +/// The `From` trait is also very useful when performing error handling. When constructing a function +/// that is capable of failing, the return type will generally be of the form `Result`. +/// `From` simplifies error handling by allowing a function to return a single error type +/// that encapsulates multiple error types. See the "Examples" section and [the book][book] for more +/// details. +/// +/// **Note: This trait must not fail**. The `From` trait is intended for perfect conversions. +/// If the conversion can fail or is not perfect, use [`TryFrom`]. +/// +/// # Generic Implementations +/// +/// - `From for U` implies [`Into`]` for T` +/// - `From` is reflexive, which means that `From for T` is implemented +/// +/// # When to implement `From` +/// +/// While there's no technical restrictions on which conversions can be done using +/// a `From` implementation, the general expectation is that the conversions +/// should typically be restricted as follows: +/// +/// * The conversion is *infallible*: if the conversion can fail, use [`TryFrom`] +/// instead; don't provide a `From` impl that panics. +/// +/// * The conversion is *lossless*: semantically, it should not lose or discard +/// information. For example, `i32: From` exists, where the original +/// value can be recovered using `u16: TryFrom`. And `String: From<&str>` +/// exists, where you can get something equivalent to the original value via +/// `Deref`. But `From` cannot be used to convert from `u32` to `u16`, since +/// that cannot succeed in a lossless way. (There's some wiggle room here for +/// information not considered semantically relevant. For example, +/// `Box<[T]>: From>` exists even though it might not preserve capacity, +/// like how two vectors can be equal despite differing capacities.) +/// +/// * The conversion is *value-preserving*: the conceptual kind and meaning of +/// the resulting value is the same, even though the Rust type and technical +/// representation might be different. For example `-1_i8 as u8` is *lossless*, +/// since `as` casting back can recover the original value, but that conversion +/// is *not* available via `From` because `-1` and `255` are different conceptual +/// values (despite being identical bit patterns technically). But +/// `f32: From` *is* available because `1_i16` and `1.0_f32` are conceptually +/// the same real number (despite having very different bit patterns technically). +/// `String: From` is available because they're both *text*, but +/// `String: From` is *not* available, since `1` (a number) and `"1"` +/// (text) are too different. (Converting values to text is instead covered +/// by the [`Display`](crate::fmt::Display) trait.) +/// +/// * The conversion is *obvious*: it's the only reasonable conversion between +/// the two types. Otherwise it's better to have it be a named method or +/// constructor, like how [`str::as_bytes`] is a method and how integers have +/// methods like [`u32::from_ne_bytes`], [`u32::from_le_bytes`], and +/// [`u32::from_be_bytes`], none of which are `From` implementations. Whereas +/// there's only one reasonable way to wrap an [`Ipv6Addr`](crate::net::Ipv6Addr) +/// into an [`IpAddr`](crate::net::IpAddr), thus `IpAddr: From` exists. +/// +/// # Examples +/// +/// [`String`] implements `From<&str>`: +/// +/// An explicit conversion from a `&str` to a String is done as follows: +/// +/// ``` +/// let string = "hello".to_string(); +/// let other_string = String::from("hello"); +/// +/// assert_eq!(string, other_string); +/// ``` +/// +/// While performing error handling it is often useful to implement `From` for your own error type. +/// By converting underlying error types to our own custom error type that encapsulates the +/// underlying error type, we can return a single error type without losing information on the +/// underlying cause. The '?' operator automatically converts the underlying error type to our +/// custom error type with `From::from`. +/// +/// ``` +/// use std::fs; +/// use std::io; +/// use std::num; +/// +/// enum CliError { +/// IoError(io::Error), +/// ParseError(num::ParseIntError), +/// } +/// +/// impl From for CliError { +/// fn from(error: io::Error) -> Self { +/// CliError::IoError(error) +/// } +/// } +/// +/// impl From for CliError { +/// fn from(error: num::ParseIntError) -> Self { +/// CliError::ParseError(error) +/// } +/// } +/// +/// fn open_and_parse_file(file_name: &str) -> Result { +/// let mut contents = fs::read_to_string(&file_name)?; +/// let num: i32 = contents.trim().parse()?; +/// Ok(num) +/// } +/// ``` +/// +/// [`String`]: ../../std/string/struct.String.html +/// [`from`]: From::from +/// [book]: ../../book/ch09-00-error-handling.html +#[rustc_diagnostic_item = "From"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented(on( + all(_Self = "&str", T = "alloc::string::String"), + note = "to coerce a `{T}` into a `{Self}`, use `&*` as a prefix", +))] +pub trait From: Sized { + /// Converts to this type from the input type. + #[rustc_diagnostic_item = "from_fn"] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn from(value: T) -> Self; +} + +/// An attempted conversion that consumes `self`, which may or may not be +/// expensive. +/// +/// Library authors should usually not directly implement this trait, +/// but should prefer implementing the [`TryFrom`] trait, which offers +/// greater flexibility and provides an equivalent `TryInto` +/// implementation for free, thanks to a blanket implementation in the +/// standard library. For more information on this, see the +/// documentation for [`Into`]. +/// +/// # Implementing `TryInto` +/// +/// This suffers the same restrictions and reasoning as implementing +/// [`Into`], see there for details. +#[rustc_diagnostic_item = "TryInto"] +#[stable(feature = "try_from", since = "1.34.0")] +pub trait TryInto: Sized { + /// The type returned in the event of a conversion error. + #[stable(feature = "try_from", since = "1.34.0")] + type Error; + + /// Performs the conversion. + #[stable(feature = "try_from", since = "1.34.0")] + fn try_into(self) -> Result; +} + +/// Simple and safe type conversions that may fail in a controlled +/// way under some circumstances. It is the reciprocal of [`TryInto`]. +/// +/// This is useful when you are doing a type conversion that may +/// trivially succeed but may also need special handling. +/// For example, there is no way to convert an [`i64`] into an [`i32`] +/// using the [`From`] trait, because an [`i64`] may contain a value +/// that an [`i32`] cannot represent and so the conversion would lose data. +/// This might be handled by truncating the [`i64`] to an [`i32`] or by +/// simply returning [`i32::MAX`], or by some other method. The [`From`] +/// trait is intended for perfect conversions, so the `TryFrom` trait +/// informs the programmer when a type conversion could go bad and lets +/// them decide how to handle it. +/// +/// # Generic Implementations +/// +/// - `TryFrom for U` implies [`TryInto`]` for T` +/// - [`try_from`] is reflexive, which means that `TryFrom for T` +/// is implemented and cannot fail -- the associated `Error` type for +/// calling `T::try_from()` on a value of type `T` is [`Infallible`]. +/// When the [`!`] type is stabilized [`Infallible`] and [`!`] will be +/// equivalent. +/// +/// `TryFrom` can be implemented as follows: +/// +/// ``` +/// struct GreaterThanZero(i32); +/// +/// impl TryFrom for GreaterThanZero { +/// type Error = &'static str; +/// +/// fn try_from(value: i32) -> Result { +/// if value <= 0 { +/// Err("GreaterThanZero only accepts values greater than zero!") +/// } else { +/// Ok(GreaterThanZero(value)) +/// } +/// } +/// } +/// ``` +/// +/// # Examples +/// +/// As described, [`i32`] implements `TryFrom<`[`i64`]`>`: +/// +/// ``` +/// let big_number = 1_000_000_000_000i64; +/// // Silently truncates `big_number`, requires detecting +/// // and handling the truncation after the fact. +/// let smaller_number = big_number as i32; +/// assert_eq!(smaller_number, -727379968); +/// +/// // Returns an error because `big_number` is too big to +/// // fit in an `i32`. +/// let try_smaller_number = i32::try_from(big_number); +/// assert!(try_smaller_number.is_err()); +/// +/// // Returns `Ok(3)`. +/// let try_successful_smaller_number = i32::try_from(3); +/// assert!(try_successful_smaller_number.is_ok()); +/// ``` +/// +/// [`try_from`]: TryFrom::try_from +#[rustc_diagnostic_item = "TryFrom"] +#[stable(feature = "try_from", since = "1.34.0")] +pub trait TryFrom: Sized { + /// The type returned in the event of a conversion error. + #[stable(feature = "try_from", since = "1.34.0")] + type Error; + + /// Performs the conversion. + #[stable(feature = "try_from", since = "1.34.0")] + #[rustc_diagnostic_item = "try_from_fn"] + fn try_from(value: T) -> Result; +} + +//////////////////////////////////////////////////////////////////////////////// +// GENERIC IMPLS +//////////////////////////////////////////////////////////////////////////////// + +// As lifts over & +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for &T +where + T: AsRef, +{ + #[inline] + fn as_ref(&self) -> &U { + >::as_ref(*self) + } +} + +// As lifts over &mut +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for &mut T +where + T: AsRef, +{ + #[inline] + fn as_ref(&self) -> &U { + >::as_ref(*self) + } +} + +// FIXME (#45742): replace the above impls for &/&mut with the following more general one: +// // As lifts over Deref +// impl>, U: ?Sized> AsRef for D { +// fn as_ref(&self) -> &U { +// self.deref().as_ref() +// } +// } + +// AsMut lifts over &mut +#[stable(feature = "rust1", since = "1.0.0")] +impl AsMut for &mut T +where + T: AsMut, +{ + #[inline] + fn as_mut(&mut self) -> &mut U { + (*self).as_mut() + } +} + +// FIXME (#45742): replace the above impl for &mut with the following more general one: +// // AsMut lifts over DerefMut +// impl>, U: ?Sized> AsMut for D { +// fn as_mut(&mut self) -> &mut U { +// self.deref_mut().as_mut() +// } +// } + +// From implies Into +#[stable(feature = "rust1", since = "1.0.0")] +impl Into for T +where + U: From, +{ + /// Calls `U::from(self)`. + /// + /// That is, this conversion is whatever the implementation of + /// [From]<T> for U chooses to do. + #[inline] + #[track_caller] + fn into(self) -> U { + U::from(self) + } +} + +// From (and thus Into) is reflexive +#[stable(feature = "rust1", since = "1.0.0")] +impl From for T { + /// Returns the argument unchanged. + #[inline(always)] + fn from(t: T) -> T { + t + } +} + +/// **Stability note:** This impl does not yet exist, but we are +/// "reserving space" to add it in the future. See +/// [rust-lang/rust#64715][#64715] for details. +/// +/// [#64715]: https://github.com/rust-lang/rust/issues/64715 +#[stable(feature = "convert_infallible", since = "1.34.0")] +#[allow(unused_attributes)] // FIXME(#58633): do a principled fix instead. +#[rustc_reservation_impl = "permitting this impl would forbid us from adding \ + `impl From for T` later; see rust-lang/rust#64715 for details"] +impl From for T { + fn from(t: !) -> T { + t + } +} + +// TryFrom implies TryInto +#[stable(feature = "try_from", since = "1.34.0")] +impl TryInto for T +where + U: TryFrom, +{ + type Error = U::Error; + + #[inline] + fn try_into(self) -> Result { + U::try_from(self) + } +} + +// Infallible conversions are semantically equivalent to fallible conversions +// with an uninhabited error type. +#[stable(feature = "try_from", since = "1.34.0")] +impl TryFrom for T +where + U: Into, +{ + type Error = Infallible; + + #[inline] + fn try_from(value: U) -> Result { + Ok(U::into(value)) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// CONCRETE IMPLS +//////////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef<[T]> for [T] { + #[inline(always)] + fn as_ref(&self) -> &[T] { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsMut<[T]> for [T] { + #[inline(always)] + fn as_mut(&mut self) -> &mut [T] { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for str { + #[inline(always)] + fn as_ref(&self) -> &str { + self + } +} + +#[stable(feature = "as_mut_str_for_str", since = "1.51.0")] +impl AsMut for str { + #[inline(always)] + fn as_mut(&mut self) -> &mut str { + self + } +} + +//////////////////////////////////////////////////////////////////////////////// +// THE NO-ERROR ERROR TYPE +//////////////////////////////////////////////////////////////////////////////// + +/// The error type for errors that can never happen. +/// +/// Since this enum has no variant, a value of this type can never actually exist. +/// This can be useful for generic APIs that use [`Result`] and parameterize the error type, +/// to indicate that the result is always [`Ok`]. +/// +/// For example, the [`TryFrom`] trait (conversion that returns a [`Result`]) +/// has a blanket implementation for all types where a reverse [`Into`] implementation exists. +/// +/// ```ignore (illustrates std code, duplicating the impl in a doctest would be an error) +/// impl TryFrom for T where U: Into { +/// type Error = Infallible; +/// +/// fn try_from(value: U) -> Result { +/// Ok(U::into(value)) // Never returns `Err` +/// } +/// } +/// ``` +/// +/// # Future compatibility +/// +/// This enum has the same role as [the `!` “never” type][never], +/// which is unstable in this version of Rust. +/// When `!` is stabilized, we plan to make `Infallible` a type alias to it: +/// +/// ```ignore (illustrates future std change) +/// pub type Infallible = !; +/// ``` +/// +/// … and eventually deprecate `Infallible`. +/// +/// However there is one case where `!` syntax can be used +/// before `!` is stabilized as a full-fledged type: in the position of a function’s return type. +/// Specifically, it is possible to have implementations for two different function pointer types: +/// +/// ``` +/// trait MyTrait {} +/// impl MyTrait for fn() -> ! {} +/// impl MyTrait for fn() -> std::convert::Infallible {} +/// ``` +/// +/// With `Infallible` being an enum, this code is valid. +/// However when `Infallible` becomes an alias for the never type, +/// the two `impl`s will start to overlap +/// and therefore will be disallowed by the language’s trait coherence rules. +#[stable(feature = "convert_infallible", since = "1.34.0")] +#[derive(Copy)] +pub enum Infallible {} + +#[stable(feature = "convert_infallible", since = "1.34.0")] +impl Clone for Infallible { + fn clone(&self) -> Infallible { + match *self {} + } +} + +#[stable(feature = "convert_infallible", since = "1.34.0")] +impl fmt::Debug for Infallible { + fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self {} + } +} + +#[stable(feature = "convert_infallible", since = "1.34.0")] +impl fmt::Display for Infallible { + fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self {} + } +} + +#[stable(feature = "str_parse_error2", since = "1.8.0")] +impl Error for Infallible { + fn description(&self) -> &str { + match *self {} + } +} + +#[stable(feature = "convert_infallible", since = "1.34.0")] +impl PartialEq for Infallible { + fn eq(&self, _: &Infallible) -> bool { + match *self {} + } +} + +#[stable(feature = "convert_infallible", since = "1.34.0")] +impl Eq for Infallible {} + +#[stable(feature = "convert_infallible", since = "1.34.0")] +impl PartialOrd for Infallible { + fn partial_cmp(&self, _other: &Self) -> Option { + match *self {} + } +} + +#[stable(feature = "convert_infallible", since = "1.34.0")] +impl Ord for Infallible { + fn cmp(&self, _other: &Self) -> crate::cmp::Ordering { + match *self {} + } +} + +#[stable(feature = "convert_infallible", since = "1.34.0")] +impl From for Infallible { + #[inline] + fn from(x: !) -> Self { + x + } +} + +#[stable(feature = "convert_infallible_hash", since = "1.44.0")] +impl Hash for Infallible { + fn hash(&self, _: &mut H) { + match *self {} + } +} diff --git a/CoqOfRust/core/convert/num.rs b/CoqOfRust/core/convert/num.rs new file mode 100644 index 000000000..0246d0627 --- /dev/null +++ b/CoqOfRust/core/convert/num.rs @@ -0,0 +1,542 @@ +use crate::num::TryFromIntError; + +mod private { + /// This trait being unreachable from outside the crate + /// prevents other implementations of the `FloatToInt` trait, + /// which allows potentially adding more trait methods after the trait is `#[stable]`. + #[unstable(feature = "convert_float_to_int", issue = "67057")] + pub trait Sealed {} +} + +/// Supporting trait for inherent methods of `f32` and `f64` such as `to_int_unchecked`. +/// Typically doesn’t need to be used directly. +#[unstable(feature = "convert_float_to_int", issue = "67057")] +pub trait FloatToInt: private::Sealed + Sized { + #[unstable(feature = "convert_float_to_int", issue = "67057")] + #[doc(hidden)] + unsafe fn to_int_unchecked(self) -> Int; +} + +macro_rules! impl_float_to_int { + ($Float:ty => $($Int:ty),+) => { + #[unstable(feature = "convert_float_to_int", issue = "67057")] + impl private::Sealed for $Float {} + $( + #[unstable(feature = "convert_float_to_int", issue = "67057")] + impl FloatToInt<$Int> for $Float { + #[inline] + unsafe fn to_int_unchecked(self) -> $Int { + // SAFETY: the safety contract must be upheld by the caller. + unsafe { crate::intrinsics::float_to_int_unchecked(self) } + } + } + )+ + } +} + +impl_float_to_int!(f16 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); +impl_float_to_int!(f32 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); +impl_float_to_int!(f64 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); +impl_float_to_int!(f128 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); + +// Conversion traits for primitive integer and float types +// Conversions T -> T are covered by a blanket impl and therefore excluded +// Some conversions from and to usize/isize are not implemented due to portability concerns +macro_rules! impl_from { + (bool => $Int:ty $(,)?) => { + impl_from!( + bool => $Int, + #[stable(feature = "from_bool", since = "1.28.0")], + concat!( + "Converts a [`bool`] to [`", stringify!($Int), "`] losslessly.\n", + "The resulting value is `0` for `false` and `1` for `true` values.\n", + "\n", + "# Examples\n", + "\n", + "```\n", + "assert_eq!(", stringify!($Int), "::from(true), 1);\n", + "assert_eq!(", stringify!($Int), "::from(false), 0);\n", + "```\n", + ), + ); + }; + ($Small:ty => $Large:ty, #[$attr:meta] $(,)?) => { + impl_from!( + $Small => $Large, + #[$attr], + concat!("Converts [`", stringify!($Small), "`] to [`", stringify!($Large), "`] losslessly."), + ); + }; + ($Small:ty => $Large:ty, #[$attr:meta], $doc:expr $(,)?) => { + #[$attr] + impl From<$Small> for $Large { + // Rustdocs on the impl block show a "[+] show undocumented items" toggle. + // Rustdocs on functions do not. + #[doc = $doc] + #[inline(always)] + fn from(small: $Small) -> Self { + small as Self + } + } + }; +} + +// boolean -> integer +impl_from!(bool => u8); +impl_from!(bool => u16); +impl_from!(bool => u32); +impl_from!(bool => u64); +impl_from!(bool => u128); +impl_from!(bool => usize); +impl_from!(bool => i8); +impl_from!(bool => i16); +impl_from!(bool => i32); +impl_from!(bool => i64); +impl_from!(bool => i128); +impl_from!(bool => isize); + +// unsigned integer -> unsigned integer +impl_from!(u8 => u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(u8 => u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(u8 => u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(u8 => u128, #[stable(feature = "i128", since = "1.26.0")]); +impl_from!(u8 => usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(u16 => u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(u16 => u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(u16 => u128, #[stable(feature = "i128", since = "1.26.0")]); +impl_from!(u32 => u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(u32 => u128, #[stable(feature = "i128", since = "1.26.0")]); +impl_from!(u64 => u128, #[stable(feature = "i128", since = "1.26.0")]); + +// signed integer -> signed integer +impl_from!(i8 => i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(i8 => i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(i8 => i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(i8 => i128, #[stable(feature = "i128", since = "1.26.0")]); +impl_from!(i8 => isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(i16 => i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(i16 => i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(i16 => i128, #[stable(feature = "i128", since = "1.26.0")]); +impl_from!(i32 => i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(i32 => i128, #[stable(feature = "i128", since = "1.26.0")]); +impl_from!(i64 => i128, #[stable(feature = "i128", since = "1.26.0")]); + +// unsigned integer -> signed integer +impl_from!(u8 => i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(u8 => i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(u8 => i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(u8 => i128, #[stable(feature = "i128", since = "1.26.0")]); +impl_from!(u16 => i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(u16 => i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(u16 => i128, #[stable(feature = "i128", since = "1.26.0")]); +impl_from!(u32 => i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); +impl_from!(u32 => i128, #[stable(feature = "i128", since = "1.26.0")]); +impl_from!(u64 => i128, #[stable(feature = "i128", since = "1.26.0")]); + +// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX +// which imply that pointer-sized integers must be at least 16 bits: +// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4 +impl_from!(u16 => usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")]); +impl_from!(u8 => isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")]); +impl_from!(i16 => isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")]); + +// RISC-V defines the possibility of a 128-bit address space (RV128). + +// CHERI proposes 128-bit “capabilities”. Unclear if this would be relevant to usize/isize. +// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf +// https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-951.pdf + +// Note: integers can only be represented with full precision in a float if +// they fit in the significand, which is 24 bits in f32 and 53 bits in f64. +// Lossy float conversions are not implemented at this time. + +// signed integer -> float +impl_from!(i8 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(i8 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(i16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(i16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(i32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); + +// unsigned integer -> float +impl_from!(u8 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(u8 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(u16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(u16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(u32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); + +// float -> float +// FIXME(f16_f128): adding additional `From<{float}>` impls to `f32` breaks inference. See +// +impl_from!(f16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(f16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(f32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(f32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(f64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); + +macro_rules! impl_float_from_bool { + ($float:ty) => { + #[stable(feature = "float_from_bool", since = "1.68.0")] + impl From for $float { + #[doc = concat!("Converts a [`bool`] to [`", stringify!($float),"`] losslessly.")] + /// The resulting value is positive `0.0` for `false` and `1.0` for `true` values. + /// + /// # Examples + /// ``` + #[doc = concat!("let x: ", stringify!($float)," = false.into();")] + /// assert_eq!(x, 0.0); + /// assert!(x.is_sign_positive()); + /// + #[doc = concat!("let y: ", stringify!($float)," = true.into();")] + /// assert_eq!(y, 1.0); + /// ``` + #[inline] + fn from(small: bool) -> Self { + small as u8 as Self + } + } + }; +} + +// boolean -> float +impl_float_from_bool!(f32); +impl_float_from_bool!(f64); + +// no possible bounds violation +macro_rules! impl_try_from_unbounded { + ($source:ty => $($target:ty),+) => {$( + #[stable(feature = "try_from", since = "1.34.0")] + impl TryFrom<$source> for $target { + type Error = TryFromIntError; + + /// Tries to create the target number type from a source + /// number type. This returns an error if the source value + /// is outside of the range of the target type. + #[inline] + fn try_from(value: $source) -> Result { + Ok(value as Self) + } + } + )*} +} + +// only negative bounds +macro_rules! impl_try_from_lower_bounded { + ($source:ty => $($target:ty),+) => {$( + #[stable(feature = "try_from", since = "1.34.0")] + impl TryFrom<$source> for $target { + type Error = TryFromIntError; + + /// Tries to create the target number type from a source + /// number type. This returns an error if the source value + /// is outside of the range of the target type. + #[inline] + fn try_from(u: $source) -> Result { + if u >= 0 { + Ok(u as Self) + } else { + Err(TryFromIntError(())) + } + } + } + )*} +} + +// unsigned to signed (only positive bound) +macro_rules! impl_try_from_upper_bounded { + ($source:ty => $($target:ty),+) => {$( + #[stable(feature = "try_from", since = "1.34.0")] + impl TryFrom<$source> for $target { + type Error = TryFromIntError; + + /// Tries to create the target number type from a source + /// number type. This returns an error if the source value + /// is outside of the range of the target type. + #[inline] + fn try_from(u: $source) -> Result { + if u > (Self::MAX as $source) { + Err(TryFromIntError(())) + } else { + Ok(u as Self) + } + } + } + )*} +} + +// all other cases +macro_rules! impl_try_from_both_bounded { + ($source:ty => $($target:ty),+) => {$( + #[stable(feature = "try_from", since = "1.34.0")] + impl TryFrom<$source> for $target { + type Error = TryFromIntError; + + /// Tries to create the target number type from a source + /// number type. This returns an error if the source value + /// is outside of the range of the target type. + #[inline] + fn try_from(u: $source) -> Result { + let min = Self::MIN as $source; + let max = Self::MAX as $source; + if u < min || u > max { + Err(TryFromIntError(())) + } else { + Ok(u as Self) + } + } + } + )*} +} + +macro_rules! rev { + ($mac:ident, $source:ty => $($target:ty),+) => {$( + $mac!($target => $source); + )*} +} + +// unsigned integer -> unsigned integer +impl_try_from_upper_bounded!(u16 => u8); +impl_try_from_upper_bounded!(u32 => u8, u16); +impl_try_from_upper_bounded!(u64 => u8, u16, u32); +impl_try_from_upper_bounded!(u128 => u8, u16, u32, u64); + +// signed integer -> signed integer +impl_try_from_both_bounded!(i16 => i8); +impl_try_from_both_bounded!(i32 => i8, i16); +impl_try_from_both_bounded!(i64 => i8, i16, i32); +impl_try_from_both_bounded!(i128 => i8, i16, i32, i64); + +// unsigned integer -> signed integer +impl_try_from_upper_bounded!(u8 => i8); +impl_try_from_upper_bounded!(u16 => i8, i16); +impl_try_from_upper_bounded!(u32 => i8, i16, i32); +impl_try_from_upper_bounded!(u64 => i8, i16, i32, i64); +impl_try_from_upper_bounded!(u128 => i8, i16, i32, i64, i128); + +// signed integer -> unsigned integer +impl_try_from_lower_bounded!(i8 => u8, u16, u32, u64, u128); +impl_try_from_both_bounded!(i16 => u8); +impl_try_from_lower_bounded!(i16 => u16, u32, u64, u128); +impl_try_from_both_bounded!(i32 => u8, u16); +impl_try_from_lower_bounded!(i32 => u32, u64, u128); +impl_try_from_both_bounded!(i64 => u8, u16, u32); +impl_try_from_lower_bounded!(i64 => u64, u128); +impl_try_from_both_bounded!(i128 => u8, u16, u32, u64); +impl_try_from_lower_bounded!(i128 => u128); + +// usize/isize +impl_try_from_upper_bounded!(usize => isize); +impl_try_from_lower_bounded!(isize => usize); + +#[cfg(target_pointer_width = "16")] +mod ptr_try_from_impls { + use super::TryFromIntError; + + impl_try_from_upper_bounded!(usize => u8); + impl_try_from_unbounded!(usize => u16, u32, u64, u128); + impl_try_from_upper_bounded!(usize => i8, i16); + impl_try_from_unbounded!(usize => i32, i64, i128); + + impl_try_from_both_bounded!(isize => u8); + impl_try_from_lower_bounded!(isize => u16, u32, u64, u128); + impl_try_from_both_bounded!(isize => i8); + impl_try_from_unbounded!(isize => i16, i32, i64, i128); + + rev!(impl_try_from_upper_bounded, usize => u32, u64, u128); + rev!(impl_try_from_lower_bounded, usize => i8, i16); + rev!(impl_try_from_both_bounded, usize => i32, i64, i128); + + rev!(impl_try_from_upper_bounded, isize => u16, u32, u64, u128); + rev!(impl_try_from_both_bounded, isize => i32, i64, i128); +} + +#[cfg(target_pointer_width = "32")] +mod ptr_try_from_impls { + use super::TryFromIntError; + + impl_try_from_upper_bounded!(usize => u8, u16); + impl_try_from_unbounded!(usize => u32, u64, u128); + impl_try_from_upper_bounded!(usize => i8, i16, i32); + impl_try_from_unbounded!(usize => i64, i128); + + impl_try_from_both_bounded!(isize => u8, u16); + impl_try_from_lower_bounded!(isize => u32, u64, u128); + impl_try_from_both_bounded!(isize => i8, i16); + impl_try_from_unbounded!(isize => i32, i64, i128); + + rev!(impl_try_from_unbounded, usize => u32); + rev!(impl_try_from_upper_bounded, usize => u64, u128); + rev!(impl_try_from_lower_bounded, usize => i8, i16, i32); + rev!(impl_try_from_both_bounded, usize => i64, i128); + + rev!(impl_try_from_unbounded, isize => u16); + rev!(impl_try_from_upper_bounded, isize => u32, u64, u128); + rev!(impl_try_from_unbounded, isize => i32); + rev!(impl_try_from_both_bounded, isize => i64, i128); +} + +#[cfg(target_pointer_width = "64")] +mod ptr_try_from_impls { + use super::TryFromIntError; + + impl_try_from_upper_bounded!(usize => u8, u16, u32); + impl_try_from_unbounded!(usize => u64, u128); + impl_try_from_upper_bounded!(usize => i8, i16, i32, i64); + impl_try_from_unbounded!(usize => i128); + + impl_try_from_both_bounded!(isize => u8, u16, u32); + impl_try_from_lower_bounded!(isize => u64, u128); + impl_try_from_both_bounded!(isize => i8, i16, i32); + impl_try_from_unbounded!(isize => i64, i128); + + rev!(impl_try_from_unbounded, usize => u32, u64); + rev!(impl_try_from_upper_bounded, usize => u128); + rev!(impl_try_from_lower_bounded, usize => i8, i16, i32, i64); + rev!(impl_try_from_both_bounded, usize => i128); + + rev!(impl_try_from_unbounded, isize => u16, u32); + rev!(impl_try_from_upper_bounded, isize => u64, u128); + rev!(impl_try_from_unbounded, isize => i32, i64); + rev!(impl_try_from_both_bounded, isize => i128); +} + +// Conversion traits for non-zero integer types +use crate::num::NonZero; + +macro_rules! impl_nonzero_int_from_nonzero_int { + ($Small:ty => $Large:ty) => { + #[stable(feature = "nz_int_conv", since = "1.41.0")] + impl From> for NonZero<$Large> { + // Rustdocs on the impl block show a "[+] show undocumented items" toggle. + // Rustdocs on functions do not. + #[doc = concat!("Converts [NonZero]\\<[", stringify!($Small), "]> ")] + #[doc = concat!("to [NonZero]\\<[", stringify!($Large), "]> losslessly.")] + #[inline] + fn from(small: NonZero<$Small>) -> Self { + // SAFETY: input type guarantees the value is non-zero + unsafe { Self::new_unchecked(From::from(small.get())) } + } + } + }; +} + +// non-zero unsigned integer -> non-zero unsigned integer +impl_nonzero_int_from_nonzero_int!(u8 => u16); +impl_nonzero_int_from_nonzero_int!(u8 => u32); +impl_nonzero_int_from_nonzero_int!(u8 => u64); +impl_nonzero_int_from_nonzero_int!(u8 => u128); +impl_nonzero_int_from_nonzero_int!(u8 => usize); +impl_nonzero_int_from_nonzero_int!(u16 => u32); +impl_nonzero_int_from_nonzero_int!(u16 => u64); +impl_nonzero_int_from_nonzero_int!(u16 => u128); +impl_nonzero_int_from_nonzero_int!(u16 => usize); +impl_nonzero_int_from_nonzero_int!(u32 => u64); +impl_nonzero_int_from_nonzero_int!(u32 => u128); +impl_nonzero_int_from_nonzero_int!(u64 => u128); + +// non-zero signed integer -> non-zero signed integer +impl_nonzero_int_from_nonzero_int!(i8 => i16); +impl_nonzero_int_from_nonzero_int!(i8 => i32); +impl_nonzero_int_from_nonzero_int!(i8 => i64); +impl_nonzero_int_from_nonzero_int!(i8 => i128); +impl_nonzero_int_from_nonzero_int!(i8 => isize); +impl_nonzero_int_from_nonzero_int!(i16 => i32); +impl_nonzero_int_from_nonzero_int!(i16 => i64); +impl_nonzero_int_from_nonzero_int!(i16 => i128); +impl_nonzero_int_from_nonzero_int!(i16 => isize); +impl_nonzero_int_from_nonzero_int!(i32 => i64); +impl_nonzero_int_from_nonzero_int!(i32 => i128); +impl_nonzero_int_from_nonzero_int!(i64 => i128); + +// non-zero unsigned -> non-zero signed integer +impl_nonzero_int_from_nonzero_int!(u8 => i16); +impl_nonzero_int_from_nonzero_int!(u8 => i32); +impl_nonzero_int_from_nonzero_int!(u8 => i64); +impl_nonzero_int_from_nonzero_int!(u8 => i128); +impl_nonzero_int_from_nonzero_int!(u8 => isize); +impl_nonzero_int_from_nonzero_int!(u16 => i32); +impl_nonzero_int_from_nonzero_int!(u16 => i64); +impl_nonzero_int_from_nonzero_int!(u16 => i128); +impl_nonzero_int_from_nonzero_int!(u32 => i64); +impl_nonzero_int_from_nonzero_int!(u32 => i128); +impl_nonzero_int_from_nonzero_int!(u64 => i128); + +macro_rules! impl_nonzero_int_try_from_int { + ($Int:ty) => { + #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] + impl TryFrom<$Int> for NonZero<$Int> { + type Error = TryFromIntError; + + // Rustdocs on the impl block show a "[+] show undocumented items" toggle. + // Rustdocs on functions do not. + #[doc = concat!("Attempts to convert [`", stringify!($Int), "`] ")] + #[doc = concat!("to [NonZero]\\<[", stringify!($Int), "]>.")] + #[inline] + fn try_from(value: $Int) -> Result { + Self::new(value).ok_or(TryFromIntError(())) + } + } + }; +} + +// integer -> non-zero integer +impl_nonzero_int_try_from_int!(u8); +impl_nonzero_int_try_from_int!(u16); +impl_nonzero_int_try_from_int!(u32); +impl_nonzero_int_try_from_int!(u64); +impl_nonzero_int_try_from_int!(u128); +impl_nonzero_int_try_from_int!(usize); +impl_nonzero_int_try_from_int!(i8); +impl_nonzero_int_try_from_int!(i16); +impl_nonzero_int_try_from_int!(i32); +impl_nonzero_int_try_from_int!(i64); +impl_nonzero_int_try_from_int!(i128); +impl_nonzero_int_try_from_int!(isize); + +macro_rules! impl_nonzero_int_try_from_nonzero_int { + ($source:ty => $($target:ty),+) => {$( + #[stable(feature = "nzint_try_from_nzint_conv", since = "1.49.0")] + impl TryFrom> for NonZero<$target> { + type Error = TryFromIntError; + + // Rustdocs on the impl block show a "[+] show undocumented items" toggle. + // Rustdocs on functions do not. + #[doc = concat!("Attempts to convert [NonZero]\\<[", stringify!($source), "]> ")] + #[doc = concat!("to [NonZero]\\<[", stringify!($target), "]>.")] + #[inline] + fn try_from(value: NonZero<$source>) -> Result { + // SAFETY: Input is guaranteed to be non-zero. + Ok(unsafe { Self::new_unchecked(<$target>::try_from(value.get())?) }) + } + } + )*}; +} + +// unsigned non-zero integer -> unsigned non-zero integer +impl_nonzero_int_try_from_nonzero_int!(u16 => u8); +impl_nonzero_int_try_from_nonzero_int!(u32 => u8, u16, usize); +impl_nonzero_int_try_from_nonzero_int!(u64 => u8, u16, u32, usize); +impl_nonzero_int_try_from_nonzero_int!(u128 => u8, u16, u32, u64, usize); +impl_nonzero_int_try_from_nonzero_int!(usize => u8, u16, u32, u64, u128); + +// signed non-zero integer -> signed non-zero integer +impl_nonzero_int_try_from_nonzero_int!(i16 => i8); +impl_nonzero_int_try_from_nonzero_int!(i32 => i8, i16, isize); +impl_nonzero_int_try_from_nonzero_int!(i64 => i8, i16, i32, isize); +impl_nonzero_int_try_from_nonzero_int!(i128 => i8, i16, i32, i64, isize); +impl_nonzero_int_try_from_nonzero_int!(isize => i8, i16, i32, i64, i128); + +// unsigned non-zero integer -> signed non-zero integer +impl_nonzero_int_try_from_nonzero_int!(u8 => i8); +impl_nonzero_int_try_from_nonzero_int!(u16 => i8, i16, isize); +impl_nonzero_int_try_from_nonzero_int!(u32 => i8, i16, i32, isize); +impl_nonzero_int_try_from_nonzero_int!(u64 => i8, i16, i32, i64, isize); +impl_nonzero_int_try_from_nonzero_int!(u128 => i8, i16, i32, i64, i128, isize); +impl_nonzero_int_try_from_nonzero_int!(usize => i8, i16, i32, i64, i128, isize); + +// signed non-zero integer -> unsigned non-zero integer +impl_nonzero_int_try_from_nonzero_int!(i8 => u8, u16, u32, u64, u128, usize); +impl_nonzero_int_try_from_nonzero_int!(i16 => u8, u16, u32, u64, u128, usize); +impl_nonzero_int_try_from_nonzero_int!(i32 => u8, u16, u32, u64, u128, usize); +impl_nonzero_int_try_from_nonzero_int!(i64 => u8, u16, u32, u64, u128, usize); +impl_nonzero_int_try_from_nonzero_int!(i128 => u8, u16, u32, u64, u128, usize); +impl_nonzero_int_try_from_nonzero_int!(isize => u8, u16, u32, u64, u128, usize); diff --git a/CoqOfRust/core/default.rs b/CoqOfRust/core/default.rs new file mode 100644 index 000000000..4c30290ff --- /dev/null +++ b/CoqOfRust/core/default.rs @@ -0,0 +1,185 @@ +//! The `Default` trait for types with a default value. + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::ascii::Char as AsciiChar; + +/// A trait for giving a type a useful default value. +/// +/// Sometimes, you want to fall back to some kind of default value, and +/// don't particularly care what it is. This comes up often with `struct`s +/// that define a set of options: +/// +/// ``` +/// # #[allow(dead_code)] +/// struct SomeOptions { +/// foo: i32, +/// bar: f32, +/// } +/// ``` +/// +/// How can we define some default values? You can use `Default`: +/// +/// ``` +/// # #[allow(dead_code)] +/// #[derive(Default)] +/// struct SomeOptions { +/// foo: i32, +/// bar: f32, +/// } +/// +/// fn main() { +/// let options: SomeOptions = Default::default(); +/// } +/// ``` +/// +/// Now, you get all of the default values. Rust implements `Default` for various primitives types. +/// +/// If you want to override a particular option, but still retain the other defaults: +/// +/// ``` +/// # #[allow(dead_code)] +/// # #[derive(Default)] +/// # struct SomeOptions { +/// # foo: i32, +/// # bar: f32, +/// # } +/// fn main() { +/// let options = SomeOptions { foo: 42, ..Default::default() }; +/// } +/// ``` +/// +/// ## Derivable +/// +/// This trait can be used with `#[derive]` if all of the type's fields implement +/// `Default`. When `derive`d, it will use the default value for each field's type. +/// +/// ### `enum`s +/// +/// When using `#[derive(Default)]` on an `enum`, you need to choose which unit variant will be +/// default. You do this by placing the `#[default]` attribute on the variant. +/// +/// ``` +/// #[derive(Default)] +/// enum Kind { +/// #[default] +/// A, +/// B, +/// C, +/// } +/// ``` +/// +/// You cannot use the `#[default]` attribute on non-unit or non-exhaustive variants. +/// +/// The `#[default]` attribute was stabilized in Rust 1.62.0. +/// +/// ## How can I implement `Default`? +/// +/// Provide an implementation for the `default()` method that returns the value of +/// your type that should be the default: +/// +/// ``` +/// # #![allow(dead_code)] +/// enum Kind { +/// A, +/// B, +/// C, +/// } +/// +/// impl Default for Kind { +/// fn default() -> Self { Kind::A } +/// } +/// ``` +/// +/// # Examples +/// +/// ``` +/// # #[allow(dead_code)] +/// #[derive(Default)] +/// struct SomeOptions { +/// foo: i32, +/// bar: f32, +/// } +/// ``` +#[cfg_attr(not(test), rustc_diagnostic_item = "Default")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_trivial_field_reads] +pub trait Default: Sized { + /// Returns the "default value" for a type. + /// + /// Default values are often some kind of initial value, identity value, or anything else that + /// may make sense as a default. + /// + /// # Examples + /// + /// Using built-in default values: + /// + /// ``` + /// let i: i8 = Default::default(); + /// let (x, y): (Option, f64) = Default::default(); + /// let (a, b, (c, d)): (i32, u32, (bool, bool)) = Default::default(); + /// ``` + /// + /// Making your own: + /// + /// ``` + /// # #[allow(dead_code)] + /// enum Kind { + /// A, + /// B, + /// C, + /// } + /// + /// impl Default for Kind { + /// fn default() -> Self { Kind::A } + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "default_fn"] + fn default() -> Self; +} + +/// Derive macro generating an impl of the trait `Default`. +#[rustc_builtin_macro(Default, attributes(default))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics)] +pub macro Default($item:item) { + /* compiler built-in */ +} + +macro_rules! default_impl { + ($t:ty, $v:expr, $doc:tt) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl Default for $t { + #[inline(always)] + #[doc = $doc] + fn default() -> $t { + $v + } + } + }; +} + +default_impl! { (), (), "Returns the default value of `()`" } +default_impl! { bool, false, "Returns the default value of `false`" } +default_impl! { char, '\x00', "Returns the default value of `\\x00`" } +default_impl! { AsciiChar, AsciiChar::Null, "Returns the default value of `Null`" } + +default_impl! { usize, 0, "Returns the default value of `0`" } +default_impl! { u8, 0, "Returns the default value of `0`" } +default_impl! { u16, 0, "Returns the default value of `0`" } +default_impl! { u32, 0, "Returns the default value of `0`" } +default_impl! { u64, 0, "Returns the default value of `0`" } +default_impl! { u128, 0, "Returns the default value of `0`" } + +default_impl! { isize, 0, "Returns the default value of `0`" } +default_impl! { i8, 0, "Returns the default value of `0`" } +default_impl! { i16, 0, "Returns the default value of `0`" } +default_impl! { i32, 0, "Returns the default value of `0`" } +default_impl! { i64, 0, "Returns the default value of `0`" } +default_impl! { i128, 0, "Returns the default value of `0`" } + +default_impl! { f16, 0.0f16, "Returns the default value of `0.0`" } +default_impl! { f32, 0.0f32, "Returns the default value of `0.0`" } +default_impl! { f64, 0.0f64, "Returns the default value of `0.0`" } +default_impl! { f128, 0.0f128, "Returns the default value of `0.0`" } diff --git a/CoqOfRust/core/error.rs b/CoqOfRust/core/error.rs new file mode 100644 index 000000000..95a39cc3a --- /dev/null +++ b/CoqOfRust/core/error.rs @@ -0,0 +1,1079 @@ +#![doc = include_str!("error.md")] +#![stable(feature = "error_in_core", since = "1.81.0")] + +use crate::any::TypeId; +use crate::fmt::{Debug, Display, Formatter, Result}; + +/// `Error` is a trait representing the basic expectations for error values, +/// i.e., values of type `E` in [`Result`]. +/// +/// Errors must describe themselves through the [`Display`] and [`Debug`] +/// traits. Error messages are typically concise lowercase sentences without +/// trailing punctuation: +/// +/// ``` +/// let err = "NaN".parse::().unwrap_err(); +/// assert_eq!(err.to_string(), "invalid digit found in string"); +/// ``` +/// +/// Errors may provide cause information. [`Error::source()`] is generally +/// used when errors cross "abstraction boundaries". If one module must report +/// an error that is caused by an error from a lower-level module, it can allow +/// accessing that error via [`Error::source()`]. This makes it possible for the +/// high-level module to provide its own errors while also revealing some of the +/// implementation for debugging. +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Error")] +#[rustc_has_incoherent_inherent_impls] +#[allow(multiple_supertrait_upcastable)] +pub trait Error: Debug + Display { + /// Returns the lower-level source of this error, if any. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// + /// #[derive(Debug)] + /// struct SuperError { + /// source: SuperErrorSideKick, + /// } + /// + /// impl fmt::Display for SuperError { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "SuperError is here!") + /// } + /// } + /// + /// impl Error for SuperError { + /// fn source(&self) -> Option<&(dyn Error + 'static)> { + /// Some(&self.source) + /// } + /// } + /// + /// #[derive(Debug)] + /// struct SuperErrorSideKick; + /// + /// impl fmt::Display for SuperErrorSideKick { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "SuperErrorSideKick is here!") + /// } + /// } + /// + /// impl Error for SuperErrorSideKick {} + /// + /// fn get_super_error() -> Result<(), SuperError> { + /// Err(SuperError { source: SuperErrorSideKick }) + /// } + /// + /// fn main() { + /// match get_super_error() { + /// Err(e) => { + /// println!("Error: {e}"); + /// println!("Caused by: {}", e.source().unwrap()); + /// } + /// _ => println!("No error"), + /// } + /// } + /// ``` + #[stable(feature = "error_source", since = "1.30.0")] + fn source(&self) -> Option<&(dyn Error + 'static)> { + None + } + + /// Gets the `TypeId` of `self`. + #[doc(hidden)] + #[unstable( + feature = "error_type_id", + reason = "this is memory-unsafe to override in user code", + issue = "60784" + )] + fn type_id(&self, _: private::Internal) -> TypeId + where + Self: 'static, + { + TypeId::of::() + } + + /// ``` + /// if let Err(e) = "xc".parse::() { + /// // Print `e` itself, no need for description(). + /// eprintln!("Error: {e}"); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.42.0", note = "use the Display impl or to_string()")] + fn description(&self) -> &str { + "description() is deprecated; use Display" + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated( + since = "1.33.0", + note = "replaced by Error::source, which can support downcasting" + )] + #[allow(missing_docs)] + fn cause(&self) -> Option<&dyn Error> { + self.source() + } + + /// Provides type-based access to context intended for error reports. + /// + /// Used in conjunction with [`Request::provide_value`] and [`Request::provide_ref`] to extract + /// references to member variables from `dyn Error` trait objects. + /// + /// # Example + /// + /// ```rust + /// #![feature(error_generic_member_access)] + /// use core::fmt; + /// use core::error::{request_ref, Request}; + /// + /// #[derive(Debug)] + /// enum MyLittleTeaPot { + /// Empty, + /// } + /// + /// #[derive(Debug)] + /// struct MyBacktrace { + /// // ... + /// } + /// + /// impl MyBacktrace { + /// fn new() -> MyBacktrace { + /// // ... + /// # MyBacktrace {} + /// } + /// } + /// + /// #[derive(Debug)] + /// struct Error { + /// backtrace: MyBacktrace, + /// } + /// + /// impl fmt::Display for Error { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "Example Error") + /// } + /// } + /// + /// impl std::error::Error for Error { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// request + /// .provide_ref::(&self.backtrace); + /// } + /// } + /// + /// fn main() { + /// let backtrace = MyBacktrace::new(); + /// let error = Error { backtrace }; + /// let dyn_error = &error as &dyn std::error::Error; + /// let backtrace_ref = request_ref::(dyn_error).unwrap(); + /// + /// assert!(core::ptr::eq(&error.backtrace, backtrace_ref)); + /// assert!(request_ref::(dyn_error).is_none()); + /// } + /// ``` + #[unstable(feature = "error_generic_member_access", issue = "99301")] + #[allow(unused_variables)] + fn provide<'a>(&'a self, request: &mut Request<'a>) {} +} + +mod private { + // This is a hack to prevent `type_id` from being overridden by `Error` + // implementations, since that can enable unsound downcasting. + #[unstable(feature = "error_type_id", issue = "60784")] + #[derive(Debug)] + pub struct Internal; +} + +#[unstable(feature = "never_type", issue = "35121")] +impl Error for ! {} + +// Copied from `any.rs`. +impl dyn Error + 'static { + /// Returns `true` if the inner type is the same as `T`. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn is(&self) -> bool { + // Get `TypeId` of the type this function is instantiated with. + let t = TypeId::of::(); + + // Get `TypeId` of the type in the trait object (`self`). + let concrete = self.type_id(private::Internal); + + // Compare both `TypeId`s on equality. + t == concrete + } + + /// Returns some reference to the inner value if it is of type `T`, or + /// `None` if it isn't. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + if self.is::() { + // SAFETY: `is` ensures this type cast is correct + unsafe { Some(&*(self as *const dyn Error as *const T)) } + } else { + None + } + } + + /// Returns some mutable reference to the inner value if it is of type `T`, or + /// `None` if it isn't. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + if self.is::() { + // SAFETY: `is` ensures this type cast is correct + unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) } + } else { + None + } + } +} + +impl dyn Error + 'static + Send { + /// Forwards to the method defined on the type `dyn Error`. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn is(&self) -> bool { + ::is::(self) + } + + /// Forwards to the method defined on the type `dyn Error`. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + ::downcast_ref::(self) + } + + /// Forwards to the method defined on the type `dyn Error`. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + ::downcast_mut::(self) + } +} + +impl dyn Error + 'static + Send + Sync { + /// Forwards to the method defined on the type `dyn Error`. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn is(&self) -> bool { + ::is::(self) + } + + /// Forwards to the method defined on the type `dyn Error`. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + ::downcast_ref::(self) + } + + /// Forwards to the method defined on the type `dyn Error`. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + ::downcast_mut::(self) + } +} + +impl dyn Error { + /// Returns an iterator starting with the current error and continuing with + /// recursively calling [`Error::source`]. + /// + /// If you want to omit the current error and only use its sources, + /// use `skip(1)`. + /// + /// # Examples + /// + /// ``` + /// #![feature(error_iter)] + /// use std::error::Error; + /// use std::fmt; + /// + /// #[derive(Debug)] + /// struct A; + /// + /// #[derive(Debug)] + /// struct B(Option>); + /// + /// impl fmt::Display for A { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "A") + /// } + /// } + /// + /// impl fmt::Display for B { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "B") + /// } + /// } + /// + /// impl Error for A {} + /// + /// impl Error for B { + /// fn source(&self) -> Option<&(dyn Error + 'static)> { + /// self.0.as_ref().map(|e| e.as_ref()) + /// } + /// } + /// + /// let b = B(Some(Box::new(A))); + /// + /// // let err : Box = b.into(); // or + /// let err = &b as &(dyn Error); + /// + /// let mut iter = err.sources(); + /// + /// assert_eq!("B".to_string(), iter.next().unwrap().to_string()); + /// assert_eq!("A".to_string(), iter.next().unwrap().to_string()); + /// assert!(iter.next().is_none()); + /// assert!(iter.next().is_none()); + /// ``` + #[unstable(feature = "error_iter", issue = "58520")] + #[inline] + pub fn sources(&self) -> Source<'_> { + // You may think this method would be better in the `Error` trait, and you'd be right. + // Unfortunately that doesn't work, not because of the dyn-incompatibility rules but + // because we save a reference to `self` in `Source`s below as a trait object. + // If this method was declared in `Error`, then `self` would have the type `&T` where + // `T` is some concrete type which implements `Error`. We would need to coerce `self` + // to have type `&dyn Error`, but that requires that `Self` has a known size + // (i.e., `Self: Sized`). We can't put that bound on `Error` since that would forbid + // `Error` trait objects, and we can't put that bound on the method because that means + // the method can't be called on trait objects (we'd also need the `'static` bound, + // but that isn't allowed because methods with bounds on `Self` other than `Sized` are + // dyn-incompatible). Requiring an `Unsize` bound is not backwards compatible. + + Source { current: Some(self) } + } +} + +/// Requests a value of type `T` from the given `impl Error`. +/// +/// # Examples +/// +/// Get a string value from an error. +/// +/// ```rust +/// #![feature(error_generic_member_access)] +/// use std::error::Error; +/// use core::error::request_value; +/// +/// fn get_string(err: &impl Error) -> String { +/// request_value::(err).unwrap() +/// } +/// ``` +#[unstable(feature = "error_generic_member_access", issue = "99301")] +pub fn request_value<'a, T>(err: &'a (impl Error + ?Sized)) -> Option +where + T: 'static, +{ + request_by_type_tag::<'a, tags::Value>(err) +} + +/// Requests a reference of type `T` from the given `impl Error`. +/// +/// # Examples +/// +/// Get a string reference from an error. +/// +/// ```rust +/// #![feature(error_generic_member_access)] +/// use core::error::Error; +/// use core::error::request_ref; +/// +/// fn get_str(err: &impl Error) -> &str { +/// request_ref::(err).unwrap() +/// } +/// ``` +#[unstable(feature = "error_generic_member_access", issue = "99301")] +pub fn request_ref<'a, T>(err: &'a (impl Error + ?Sized)) -> Option<&'a T> +where + T: 'static + ?Sized, +{ + request_by_type_tag::<'a, tags::Ref>>(err) +} + +/// Request a specific value by tag from the `Error`. +fn request_by_type_tag<'a, I>(err: &'a (impl Error + ?Sized)) -> Option +where + I: tags::Type<'a>, +{ + let mut tagged = Tagged { tag_id: TypeId::of::(), value: TaggedOption::<'a, I>(None) }; + err.provide(tagged.as_request()); + tagged.value.0 +} + +/////////////////////////////////////////////////////////////////////////////// +// Request and its methods +/////////////////////////////////////////////////////////////////////////////// + +/// `Request` supports generic, type-driven access to data. Its use is currently restricted to the +/// standard library in cases where trait authors wish to allow trait implementors to share generic +/// information across trait boundaries. The motivating and prototypical use case is +/// `core::error::Error` which would otherwise require a method per concrete type (eg. +/// `std::backtrace::Backtrace` instance that implementors want to expose to users). +/// +/// # Data flow +/// +/// To describe the intended data flow for Request objects, let's consider two conceptual users +/// separated by API boundaries: +/// +/// * Consumer - the consumer requests objects using a Request instance; eg a crate that offers +/// fancy `Error`/`Result` reporting to users wants to request a Backtrace from a given `dyn Error`. +/// +/// * Producer - the producer provides objects when requested via Request; eg. a library with an +/// an `Error` implementation that automatically captures backtraces at the time instances are +/// created. +/// +/// The consumer only needs to know where to submit their request and are expected to handle the +/// request not being fulfilled by the use of `Option` in the responses offered by the producer. +/// +/// * A Producer initializes the value of one of its fields of a specific type. (or is otherwise +/// prepared to generate a value requested). eg, `backtrace::Backtrace` or +/// `std::backtrace::Backtrace` +/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace`). In the +/// case of a `dyn Error` trait object (the Producer), there are functions called `request_ref` and +/// `request_value` to simplify obtaining an `Option` for a given type. +/// * The Producer, when requested, populates the given Request object which is given as a mutable +/// reference. +/// * The Consumer extracts a value or reference to the requested type from the `Request` object +/// wrapped in an `Option`; in the case of `dyn Error` the aforementioned `request_ref` and ` +/// request_value` methods mean that `dyn Error` users don't have to deal with the `Request` type at +/// all (but `Error` implementors do). The `None` case of the `Option` suggests only that the +/// Producer cannot currently offer an instance of the requested type, not it can't or never will. +/// +/// # Examples +/// +/// The best way to demonstrate this is using an example implementation of `Error`'s `provide` trait +/// method: +/// +/// ``` +/// #![feature(error_generic_member_access)] +/// use core::fmt; +/// use core::error::Request; +/// use core::error::request_ref; +/// +/// #[derive(Debug)] +/// enum MyLittleTeaPot { +/// Empty, +/// } +/// +/// #[derive(Debug)] +/// struct MyBacktrace { +/// // ... +/// } +/// +/// impl MyBacktrace { +/// fn new() -> MyBacktrace { +/// // ... +/// # MyBacktrace {} +/// } +/// } +/// +/// #[derive(Debug)] +/// struct Error { +/// backtrace: MyBacktrace, +/// } +/// +/// impl fmt::Display for Error { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// write!(f, "Example Error") +/// } +/// } +/// +/// impl std::error::Error for Error { +/// fn provide<'a>(&'a self, request: &mut Request<'a>) { +/// request +/// .provide_ref::(&self.backtrace); +/// } +/// } +/// +/// fn main() { +/// let backtrace = MyBacktrace::new(); +/// let error = Error { backtrace }; +/// let dyn_error = &error as &dyn std::error::Error; +/// let backtrace_ref = request_ref::(dyn_error).unwrap(); +/// +/// assert!(core::ptr::eq(&error.backtrace, backtrace_ref)); +/// assert!(request_ref::(dyn_error).is_none()); +/// } +/// ``` +/// +#[unstable(feature = "error_generic_member_access", issue = "99301")] +#[repr(transparent)] +pub struct Request<'a>(Tagged + 'a>); + +impl<'a> Request<'a> { + /// Provides a value or other type with only static lifetimes. + /// + /// # Examples + /// + /// Provides an `u8`. + /// + /// ```rust + /// #![feature(error_generic_member_access)] + /// + /// use core::error::Request; + /// + /// #[derive(Debug)] + /// struct SomeConcreteType { field: u8 } + /// + /// impl std::fmt::Display for SomeConcreteType { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "{} failed", self.field) + /// } + /// } + /// + /// impl std::error::Error for SomeConcreteType { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// request.provide_value::(self.field); + /// } + /// } + /// ``` + #[unstable(feature = "error_generic_member_access", issue = "99301")] + pub fn provide_value(&mut self, value: T) -> &mut Self + where + T: 'static, + { + self.provide::>(value) + } + + /// Provides a value or other type with only static lifetimes computed using a closure. + /// + /// # Examples + /// + /// Provides a `String` by cloning. + /// + /// ```rust + /// #![feature(error_generic_member_access)] + /// + /// use core::error::Request; + /// + /// #[derive(Debug)] + /// struct SomeConcreteType { field: String } + /// + /// impl std::fmt::Display for SomeConcreteType { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "{} failed", self.field) + /// } + /// } + /// + /// impl std::error::Error for SomeConcreteType { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// request.provide_value_with::(|| self.field.clone()); + /// } + /// } + /// ``` + #[unstable(feature = "error_generic_member_access", issue = "99301")] + pub fn provide_value_with(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self + where + T: 'static, + { + self.provide_with::>(fulfil) + } + + /// Provides a reference. The referee type must be bounded by `'static`, + /// but may be unsized. + /// + /// # Examples + /// + /// Provides a reference to a field as a `&str`. + /// + /// ```rust + /// #![feature(error_generic_member_access)] + /// + /// use core::error::Request; + /// + /// #[derive(Debug)] + /// struct SomeConcreteType { field: String } + /// + /// impl std::fmt::Display for SomeConcreteType { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "{} failed", self.field) + /// } + /// } + /// + /// impl std::error::Error for SomeConcreteType { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// request.provide_ref::(&self.field); + /// } + /// } + /// ``` + #[unstable(feature = "error_generic_member_access", issue = "99301")] + pub fn provide_ref(&mut self, value: &'a T) -> &mut Self { + self.provide::>>(value) + } + + /// Provides a reference computed using a closure. The referee type + /// must be bounded by `'static`, but may be unsized. + /// + /// # Examples + /// + /// Provides a reference to a field as a `&str`. + /// + /// ```rust + /// #![feature(error_generic_member_access)] + /// + /// use core::error::Request; + /// + /// #[derive(Debug)] + /// struct SomeConcreteType { business: String, party: String } + /// fn today_is_a_weekday() -> bool { true } + /// + /// impl std::fmt::Display for SomeConcreteType { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "{} failed", self.business) + /// } + /// } + /// + /// impl std::error::Error for SomeConcreteType { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// request.provide_ref_with::(|| { + /// if today_is_a_weekday() { + /// &self.business + /// } else { + /// &self.party + /// } + /// }); + /// } + /// } + /// ``` + #[unstable(feature = "error_generic_member_access", issue = "99301")] + pub fn provide_ref_with( + &mut self, + fulfil: impl FnOnce() -> &'a T, + ) -> &mut Self { + self.provide_with::>>(fulfil) + } + + /// Provides a value with the given `Type` tag. + fn provide(&mut self, value: I::Reified) -> &mut Self + where + I: tags::Type<'a>, + { + if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::() { + res.0 = Some(value); + } + self + } + + /// Provides a value with the given `Type` tag, using a closure to prevent unnecessary work. + fn provide_with(&mut self, fulfil: impl FnOnce() -> I::Reified) -> &mut Self + where + I: tags::Type<'a>, + { + if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::() { + res.0 = Some(fulfil()); + } + self + } + + /// Checks if the `Request` would be satisfied if provided with a + /// value of the specified type. If the type does not match or has + /// already been provided, returns false. + /// + /// # Examples + /// + /// Checks if a `u8` still needs to be provided and then provides + /// it. + /// + /// ```rust + /// #![feature(error_generic_member_access)] + /// + /// use core::error::Request; + /// use core::error::request_value; + /// + /// #[derive(Debug)] + /// struct Parent(Option); + /// + /// impl std::fmt::Display for Parent { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "a parent failed") + /// } + /// } + /// + /// impl std::error::Error for Parent { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// if let Some(v) = self.0 { + /// request.provide_value::(v); + /// } + /// } + /// } + /// + /// #[derive(Debug)] + /// struct Child { + /// parent: Parent, + /// } + /// + /// impl Child { + /// // Pretend that this takes a lot of resources to evaluate. + /// fn an_expensive_computation(&self) -> Option { + /// Some(99) + /// } + /// } + /// + /// impl std::fmt::Display for Child { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "child failed: \n because of parent: {}", self.parent) + /// } + /// } + /// + /// impl std::error::Error for Child { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// // In general, we don't know if this call will provide + /// // an `u8` value or not... + /// self.parent.provide(request); + /// + /// // ...so we check to see if the `u8` is needed before + /// // we run our expensive computation. + /// if request.would_be_satisfied_by_value_of::() { + /// if let Some(v) = self.an_expensive_computation() { + /// request.provide_value::(v); + /// } + /// } + /// + /// // The request will be satisfied now, regardless of if + /// // the parent provided the value or we did. + /// assert!(!request.would_be_satisfied_by_value_of::()); + /// } + /// } + /// + /// let parent = Parent(Some(42)); + /// let child = Child { parent }; + /// assert_eq!(Some(42), request_value::(&child)); + /// + /// let parent = Parent(None); + /// let child = Child { parent }; + /// assert_eq!(Some(99), request_value::(&child)); + /// + /// ``` + #[unstable(feature = "error_generic_member_access", issue = "99301")] + pub fn would_be_satisfied_by_value_of(&self) -> bool + where + T: 'static, + { + self.would_be_satisfied_by::>() + } + + /// Checks if the `Request` would be satisfied if provided with a + /// reference to a value of the specified type. + /// + /// If the type does not match or has already been provided, returns false. + /// + /// # Examples + /// + /// Checks if a `&str` still needs to be provided and then provides + /// it. + /// + /// ```rust + /// #![feature(error_generic_member_access)] + /// + /// use core::error::Request; + /// use core::error::request_ref; + /// + /// #[derive(Debug)] + /// struct Parent(Option); + /// + /// impl std::fmt::Display for Parent { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "a parent failed") + /// } + /// } + /// + /// impl std::error::Error for Parent { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// if let Some(v) = &self.0 { + /// request.provide_ref::(v); + /// } + /// } + /// } + /// + /// #[derive(Debug)] + /// struct Child { + /// parent: Parent, + /// name: String, + /// } + /// + /// impl Child { + /// // Pretend that this takes a lot of resources to evaluate. + /// fn an_expensive_computation(&self) -> Option<&str> { + /// Some(&self.name) + /// } + /// } + /// + /// impl std::fmt::Display for Child { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "{} failed: \n {}", self.name, self.parent) + /// } + /// } + /// + /// impl std::error::Error for Child { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// // In general, we don't know if this call will provide + /// // a `str` reference or not... + /// self.parent.provide(request); + /// + /// // ...so we check to see if the `&str` is needed before + /// // we run our expensive computation. + /// if request.would_be_satisfied_by_ref_of::() { + /// if let Some(v) = self.an_expensive_computation() { + /// request.provide_ref::(v); + /// } + /// } + /// + /// // The request will be satisfied now, regardless of if + /// // the parent provided the reference or we did. + /// assert!(!request.would_be_satisfied_by_ref_of::()); + /// } + /// } + /// + /// let parent = Parent(Some("parent".into())); + /// let child = Child { parent, name: "child".into() }; + /// assert_eq!(Some("parent"), request_ref::(&child)); + /// + /// let parent = Parent(None); + /// let child = Child { parent, name: "child".into() }; + /// assert_eq!(Some("child"), request_ref::(&child)); + /// ``` + #[unstable(feature = "error_generic_member_access", issue = "99301")] + pub fn would_be_satisfied_by_ref_of(&self) -> bool + where + T: ?Sized + 'static, + { + self.would_be_satisfied_by::>>() + } + + fn would_be_satisfied_by(&self) -> bool + where + I: tags::Type<'a>, + { + matches!(self.0.downcast::(), Some(TaggedOption(None))) + } +} + +#[unstable(feature = "error_generic_member_access", issue = "99301")] +impl<'a> Debug for Request<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.debug_struct("Request").finish_non_exhaustive() + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Type tags +/////////////////////////////////////////////////////////////////////////////// + +pub(crate) mod tags { + //! Type tags are used to identify a type using a separate value. This module includes type tags + //! for some very common types. + //! + //! Currently type tags are not exposed to the user. But in the future, if you want to use the + //! Request API with more complex types (typically those including lifetime parameters), you + //! will need to write your own tags. + + use crate::marker::PhantomData; + + /// This trait is implemented by specific tag types in order to allow + /// describing a type which can be requested for a given lifetime `'a`. + /// + /// A few example implementations for type-driven tags can be found in this + /// module, although crates may also implement their own tags for more + /// complex types with internal lifetimes. + pub(crate) trait Type<'a>: Sized + 'static { + /// The type of values which may be tagged by this tag for the given + /// lifetime. + type Reified: 'a; + } + + /// Similar to the [`Type`] trait, but represents a type which may be unsized (i.e., has a + /// `?Sized` bound). E.g., `str`. + pub(crate) trait MaybeSizedType<'a>: Sized + 'static { + type Reified: 'a + ?Sized; + } + + impl<'a, T: Type<'a>> MaybeSizedType<'a> for T { + type Reified = T::Reified; + } + + /// Type-based tag for types bounded by `'static`, i.e., with no borrowed elements. + #[derive(Debug)] + pub(crate) struct Value(PhantomData); + + impl<'a, T: 'static> Type<'a> for Value { + type Reified = T; + } + + /// Type-based tag similar to [`Value`] but which may be unsized (i.e., has a `?Sized` bound). + #[derive(Debug)] + pub(crate) struct MaybeSizedValue(PhantomData); + + impl<'a, T: ?Sized + 'static> MaybeSizedType<'a> for MaybeSizedValue { + type Reified = T; + } + + /// Type-based tag for reference types (`&'a T`, where T is represented by + /// `>::Reified`. + #[derive(Debug)] + pub(crate) struct Ref(PhantomData); + + impl<'a, I: MaybeSizedType<'a>> Type<'a> for Ref { + type Reified = &'a I::Reified; + } +} + +/// An `Option` with a type tag `I`. +/// +/// Since this struct implements `Erased`, the type can be erased to make a dynamically typed +/// option. The type can be checked dynamically using `Tagged::tag_id` and since this is statically +/// checked for the concrete type, there is some degree of type safety. +#[repr(transparent)] +pub(crate) struct TaggedOption<'a, I: tags::Type<'a>>(pub Option); + +impl<'a, I: tags::Type<'a>> Tagged> { + pub(crate) fn as_request(&mut self) -> &mut Request<'a> { + let erased = self as &mut Tagged + 'a>; + // SAFETY: transmuting `&mut Tagged + 'a>` to `&mut Request<'a>` is safe since + // `Request` is repr(transparent). + unsafe { &mut *(erased as *mut Tagged> as *mut Request<'a>) } + } +} + +/// Represents a type-erased but identifiable object. +/// +/// This trait is exclusively implemented by the `TaggedOption` type. +unsafe trait Erased<'a>: 'a {} + +unsafe impl<'a, I: tags::Type<'a>> Erased<'a> for TaggedOption<'a, I> {} + +struct Tagged { + tag_id: TypeId, + value: E, +} + +impl<'a> Tagged + 'a> { + /// Returns some reference to the dynamic value if it is tagged with `I`, + /// or `None` otherwise. + #[inline] + fn downcast(&self) -> Option<&TaggedOption<'a, I>> + where + I: tags::Type<'a>, + { + if self.tag_id == TypeId::of::() { + // SAFETY: Just checked whether we're pointing to an I. + Some(&unsafe { &*(self as *const Self).cast::>>() }.value) + } else { + None + } + } + + /// Returns some mutable reference to the dynamic value if it is tagged with `I`, + /// or `None` otherwise. + #[inline] + fn downcast_mut(&mut self) -> Option<&mut TaggedOption<'a, I>> + where + I: tags::Type<'a>, + { + if self.tag_id == TypeId::of::() { + Some( + // SAFETY: Just checked whether we're pointing to an I. + &mut unsafe { &mut *(self as *mut Self).cast::>>() } + .value, + ) + } else { + None + } + } +} + +/// An iterator over an [`Error`] and its sources. +/// +/// If you want to omit the initial error and only process +/// its sources, use `skip(1)`. +#[unstable(feature = "error_iter", issue = "58520")] +#[derive(Clone, Debug)] +pub struct Source<'a> { + current: Option<&'a (dyn Error + 'static)>, +} + +#[unstable(feature = "error_iter", issue = "58520")] +impl<'a> Iterator for Source<'a> { + type Item = &'a (dyn Error + 'static); + + fn next(&mut self) -> Option { + let current = self.current; + self.current = self.current.and_then(Error::source); + current + } + + fn size_hint(&self) -> (usize, Option) { + if self.current.is_some() { (1, None) } else { (0, Some(0)) } + } +} + +#[unstable(feature = "error_iter", issue = "58520")] +impl<'a> crate::iter::FusedIterator for Source<'a> {} + +#[stable(feature = "error_by_ref", since = "1.51.0")] +impl<'a, T: Error + ?Sized> Error for &'a T { + #[allow(deprecated, deprecated_in_future)] + fn description(&self) -> &str { + Error::description(&**self) + } + + #[allow(deprecated)] + fn cause(&self) -> Option<&dyn Error> { + Error::cause(&**self) + } + + fn source(&self) -> Option<&(dyn Error + 'static)> { + Error::source(&**self) + } + + fn provide<'b>(&'b self, request: &mut Request<'b>) { + Error::provide(&**self, request); + } +} + +#[stable(feature = "fmt_error", since = "1.11.0")] +impl Error for crate::fmt::Error { + #[allow(deprecated)] + fn description(&self) -> &str { + "an error occurred when formatting an argument" + } +} + +#[stable(feature = "try_borrow", since = "1.13.0")] +impl Error for crate::cell::BorrowError { + #[allow(deprecated)] + fn description(&self) -> &str { + "already mutably borrowed" + } +} + +#[stable(feature = "try_borrow", since = "1.13.0")] +impl Error for crate::cell::BorrowMutError { + #[allow(deprecated)] + fn description(&self) -> &str { + "already borrowed" + } +} + +#[stable(feature = "try_from", since = "1.34.0")] +impl Error for crate::char::CharTryFromError { + #[allow(deprecated)] + fn description(&self) -> &str { + "converted integer out of range for `char`" + } +} + +#[stable(feature = "duration_checked_float", since = "1.66.0")] +impl Error for crate::time::TryFromFloatSecsError {} + +#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] +impl Error for crate::ffi::FromBytesUntilNulError {} + +#[unstable(feature = "get_many_mut", issue = "104642")] +impl Error for crate::slice::GetManyMutError {} diff --git a/CoqOfRust/core/escape.rs b/CoqOfRust/core/escape.rs new file mode 100644 index 000000000..0685f525d --- /dev/null +++ b/CoqOfRust/core/escape.rs @@ -0,0 +1,225 @@ +//! Helper code for character escaping. + +use crate::ascii; +use crate::num::NonZero; +use crate::ops::Range; + +const HEX_DIGITS: [ascii::Char; 16] = *b"0123456789abcdef".as_ascii().unwrap(); + +#[inline] +const fn backslash(a: ascii::Char) -> ([ascii::Char; N], Range) { + const { assert!(N >= 2) }; + + let mut output = [ascii::Char::Null; N]; + + output[0] = ascii::Char::ReverseSolidus; + output[1] = a; + + (output, 0..2) +} + +#[inline] +const fn hex_escape(byte: u8) -> ([ascii::Char; N], Range) { + const { assert!(N >= 4) }; + + let mut output = [ascii::Char::Null; N]; + + let hi = HEX_DIGITS[(byte >> 4) as usize]; + let lo = HEX_DIGITS[(byte & 0xf) as usize]; + + output[0] = ascii::Char::ReverseSolidus; + output[1] = ascii::Char::SmallX; + output[2] = hi; + output[3] = lo; + + (output, 0..4) +} + +#[inline] +const fn verbatim(a: ascii::Char) -> ([ascii::Char; N], Range) { + const { assert!(N >= 1) }; + + let mut output = [ascii::Char::Null; N]; + + output[0] = a; + + (output, 0..1) +} + +/// Escapes an ASCII character. +/// +/// Returns a buffer and the length of the escaped representation. +const fn escape_ascii(byte: u8) -> ([ascii::Char; N], Range) { + const { assert!(N >= 4) }; + + #[cfg(feature = "optimize_for_size")] + { + match byte { + b'\t' => backslash(ascii::Char::SmallT), + b'\r' => backslash(ascii::Char::SmallR), + b'\n' => backslash(ascii::Char::SmallN), + b'\\' => backslash(ascii::Char::ReverseSolidus), + b'\'' => backslash(ascii::Char::Apostrophe), + b'"' => backslash(ascii::Char::QuotationMark), + 0x00..=0x1F | 0x7F => hex_escape(byte), + _ => match ascii::Char::from_u8(byte) { + Some(a) => verbatim(a), + None => hex_escape(byte), + }, + } + } + + #[cfg(not(feature = "optimize_for_size"))] + { + /// Lookup table helps us determine how to display character. + /// + /// Since ASCII characters will always be 7 bits, we can exploit this to store the 8th bit to + /// indicate whether the result is escaped or unescaped. + /// + /// We additionally use 0x80 (escaped NUL character) to indicate hex-escaped bytes, since + /// escaped NUL will not occur. + const LOOKUP: [u8; 256] = { + let mut arr = [0; 256]; + let mut idx = 0; + while idx <= 255 { + arr[idx] = match idx as u8 { + // use 8th bit to indicate escaped + b'\t' => 0x80 | b't', + b'\r' => 0x80 | b'r', + b'\n' => 0x80 | b'n', + b'\\' => 0x80 | b'\\', + b'\'' => 0x80 | b'\'', + b'"' => 0x80 | b'"', + + // use NUL to indicate hex-escaped + 0x00..=0x1F | 0x7F..=0xFF => 0x80 | b'\0', + + idx => idx, + }; + idx += 1; + } + arr + }; + + let lookup = LOOKUP[byte as usize]; + + // 8th bit indicates escape + let lookup_escaped = lookup & 0x80 != 0; + + // SAFETY: We explicitly mask out the eighth bit to get a 7-bit ASCII character. + let lookup_ascii = unsafe { ascii::Char::from_u8_unchecked(lookup & 0x7F) }; + + if lookup_escaped { + // NUL indicates hex-escaped + if matches!(lookup_ascii, ascii::Char::Null) { + hex_escape(byte) + } else { + backslash(lookup_ascii) + } + } else { + verbatim(lookup_ascii) + } + } +} + +/// Escapes a character `\u{NNNN}` representation. +/// +/// Returns a buffer and the length of the escaped representation. +const fn escape_unicode(c: char) -> ([ascii::Char; N], Range) { + const { assert!(N >= 10 && N < u8::MAX as usize) }; + + let c = c as u32; + + // OR-ing `1` ensures that for `c == 0` the code computes that + // one digit should be printed. + let start = (c | 1).leading_zeros() as usize / 4 - 2; + + let mut output = [ascii::Char::Null; N]; + output[3] = HEX_DIGITS[((c >> 20) & 15) as usize]; + output[4] = HEX_DIGITS[((c >> 16) & 15) as usize]; + output[5] = HEX_DIGITS[((c >> 12) & 15) as usize]; + output[6] = HEX_DIGITS[((c >> 8) & 15) as usize]; + output[7] = HEX_DIGITS[((c >> 4) & 15) as usize]; + output[8] = HEX_DIGITS[((c >> 0) & 15) as usize]; + output[9] = ascii::Char::RightCurlyBracket; + output[start + 0] = ascii::Char::ReverseSolidus; + output[start + 1] = ascii::Char::SmallU; + output[start + 2] = ascii::Char::LeftCurlyBracket; + + (output, (start as u8)..(N as u8)) +} + +/// An iterator over an fixed-size array. +/// +/// This is essentially equivalent to array’s IntoIter except that indexes are +/// limited to u8 to reduce size of the structure. +#[derive(Clone, Debug)] +pub(crate) struct EscapeIterInner { + // The element type ensures this is always ASCII, and thus also valid UTF-8. + data: [ascii::Char; N], + + // Invariant: `alive.start <= alive.end <= N` + alive: Range, +} + +impl EscapeIterInner { + pub const fn backslash(c: ascii::Char) -> Self { + let (data, range) = backslash(c); + Self { data, alive: range } + } + + pub const fn ascii(c: u8) -> Self { + let (data, range) = escape_ascii(c); + Self { data, alive: range } + } + + pub const fn unicode(c: char) -> Self { + let (data, range) = escape_unicode(c); + Self { data, alive: range } + } + + #[inline] + pub const fn empty() -> Self { + Self { data: [ascii::Char::Null; N], alive: 0..0 } + } + + #[inline] + pub fn as_ascii(&self) -> &[ascii::Char] { + // SAFETY: `self.alive` is guaranteed to be a valid range for indexing `self.data`. + unsafe { + self.data.get_unchecked(usize::from(self.alive.start)..usize::from(self.alive.end)) + } + } + + #[inline] + pub fn as_str(&self) -> &str { + self.as_ascii().as_str() + } + + #[inline] + pub fn len(&self) -> usize { + usize::from(self.alive.end - self.alive.start) + } + + pub fn next(&mut self) -> Option { + let i = self.alive.next()?; + + // SAFETY: `i` is guaranteed to be a valid index for `self.data`. + unsafe { Some(self.data.get_unchecked(usize::from(i)).to_u8()) } + } + + pub fn next_back(&mut self) -> Option { + let i = self.alive.next_back()?; + + // SAFETY: `i` is guaranteed to be a valid index for `self.data`. + unsafe { Some(self.data.get_unchecked(usize::from(i)).to_u8()) } + } + + pub fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.alive.advance_by(n) + } + + pub fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.alive.advance_back_by(n) + } +} diff --git a/CoqOfRust/core/ffi/c_str.rs b/CoqOfRust/core/ffi/c_str.rs new file mode 100644 index 000000000..8831443a1 --- /dev/null +++ b/CoqOfRust/core/ffi/c_str.rs @@ -0,0 +1,829 @@ +//! [`CStr`] and its related types. + +use crate::cmp::Ordering; +use crate::error::Error; +use crate::ffi::c_char; +use crate::intrinsics::const_eval_select; +use crate::iter::FusedIterator; +use crate::marker::PhantomData; +use crate::ptr::NonNull; +use crate::slice::memchr; +use crate::{fmt, ops, slice, str}; + +// FIXME: because this is doc(inline)d, we *have* to use intra-doc links because the actual link +// depends on where the item is being documented. however, since this is libcore, we can't +// actually reference libstd or liballoc in intra-doc links. so, the best we can do is remove the +// links to `CString` and `String` for now until a solution is developed + +/// Representation of a borrowed C string. +/// +/// This type represents a borrowed reference to a nul-terminated +/// array of bytes. It can be constructed safely from a &[[u8]] +/// slice, or unsafely from a raw `*const c_char`. It can be expressed as a +/// literal in the form `c"Hello world"`. +/// +/// The `CStr` can then be converted to a Rust &[str] by performing +/// UTF-8 validation, or into an owned `CString`. +/// +/// `&CStr` is to `CString` as &[str] is to `String`: the former +/// in each pair are borrowed references; the latter are owned +/// strings. +/// +/// Note that this structure does **not** have a guaranteed layout (the `repr(transparent)` +/// notwithstanding) and should not be placed in the signatures of FFI functions. +/// Instead, safe wrappers of FFI functions may leverage [`CStr::as_ptr`] and the unsafe +/// [`CStr::from_ptr`] constructor to provide a safe interface to other consumers. +/// +/// # Examples +/// +/// Inspecting a foreign C string: +/// +/// ``` +/// use std::ffi::CStr; +/// use std::os::raw::c_char; +/// +/// # /* Extern functions are awkward in doc comments - fake it instead +/// extern "C" { fn my_string() -> *const c_char; } +/// # */ unsafe extern "C" fn my_string() -> *const c_char { c"hello".as_ptr() } +/// +/// unsafe { +/// let slice = CStr::from_ptr(my_string()); +/// println!("string buffer size without nul terminator: {}", slice.to_bytes().len()); +/// } +/// ``` +/// +/// Passing a Rust-originating C string: +/// +/// ``` +/// use std::ffi::{CString, CStr}; +/// use std::os::raw::c_char; +/// +/// fn work(data: &CStr) { +/// # /* Extern functions are awkward in doc comments - fake it instead +/// extern "C" { fn work_with(data: *const c_char); } +/// # */ unsafe extern "C" fn work_with(s: *const c_char) {} +/// +/// unsafe { work_with(data.as_ptr()) } +/// } +/// +/// let s = CString::new("data data data data").expect("CString::new failed"); +/// work(&s); +/// ``` +/// +/// Converting a foreign C string into a Rust `String`: +/// +/// ``` +/// use std::ffi::CStr; +/// use std::os::raw::c_char; +/// +/// # /* Extern functions are awkward in doc comments - fake it instead +/// extern "C" { fn my_string() -> *const c_char; } +/// # */ unsafe extern "C" fn my_string() -> *const c_char { c"hello".as_ptr() } +/// +/// fn my_string_safe() -> String { +/// let cstr = unsafe { CStr::from_ptr(my_string()) }; +/// // Get copy-on-write Cow<'_, str>, then guarantee a freshly-owned String allocation +/// String::from_utf8_lossy(cstr.to_bytes()).to_string() +/// } +/// +/// println!("string: {}", my_string_safe()); +/// ``` +/// +/// [str]: prim@str "str" +#[derive(PartialEq, Eq, Hash)] +#[stable(feature = "core_c_str", since = "1.64.0")] +#[rustc_diagnostic_item = "cstr_type"] +#[rustc_has_incoherent_inherent_impls] +#[lang = "CStr"] +// `fn from` in `impl From<&CStr> for Box` current implementation relies +// on `CStr` being layout-compatible with `[u8]`. +// However, `CStr` layout is considered an implementation detail and must not be relied upon. We +// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under +// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy. +#[repr(transparent)] +pub struct CStr { + // FIXME: this should not be represented with a DST slice but rather with + // just a raw `c_char` along with some form of marker to make + // this an unsized type. Essentially `sizeof(&CStr)` should be the + // same as `sizeof(&c_char)` but `CStr` should be an unsized type. + inner: [c_char], +} + +/// An error indicating that a nul byte was not in the expected position. +/// +/// The slice used to create a [`CStr`] must have one and only one nul byte, +/// positioned at the end. +/// +/// This error is created by the [`CStr::from_bytes_with_nul`] method. +/// See its documentation for more. +/// +/// # Examples +/// +/// ``` +/// use std::ffi::{CStr, FromBytesWithNulError}; +/// +/// let _: FromBytesWithNulError = CStr::from_bytes_with_nul(b"f\0oo").unwrap_err(); +/// ``` +#[derive(Clone, PartialEq, Eq, Debug)] +#[stable(feature = "core_c_str", since = "1.64.0")] +pub struct FromBytesWithNulError { + kind: FromBytesWithNulErrorKind, +} + +#[derive(Clone, PartialEq, Eq, Debug)] +enum FromBytesWithNulErrorKind { + InteriorNul(usize), + NotNulTerminated, +} + +// FIXME: const stability attributes should not be required here, I think +impl FromBytesWithNulError { + const fn interior_nul(pos: usize) -> FromBytesWithNulError { + FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) } + } + const fn not_nul_terminated() -> FromBytesWithNulError { + FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated } + } +} + +#[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")] +impl Error for FromBytesWithNulError { + #[allow(deprecated)] + fn description(&self) -> &str { + match self.kind { + FromBytesWithNulErrorKind::InteriorNul(..) => { + "data provided contains an interior nul byte" + } + FromBytesWithNulErrorKind::NotNulTerminated => "data provided is not nul terminated", + } + } +} + +/// An error indicating that no nul byte was present. +/// +/// A slice used to create a [`CStr`] must contain a nul byte somewhere +/// within the slice. +/// +/// This error is created by the [`CStr::from_bytes_until_nul`] method. +/// +#[derive(Clone, PartialEq, Eq, Debug)] +#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] +pub struct FromBytesUntilNulError(()); + +#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] +impl fmt::Display for FromBytesUntilNulError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "data provided does not contain a nul") + } +} + +#[stable(feature = "cstr_debug", since = "1.3.0")] +impl fmt::Debug for CStr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "\"{}\"", self.to_bytes().escape_ascii()) + } +} + +#[stable(feature = "cstr_default", since = "1.10.0")] +impl Default for &CStr { + #[inline] + fn default() -> Self { + const SLICE: &[c_char] = &[0]; + // SAFETY: `SLICE` is indeed pointing to a valid nul-terminated string. + unsafe { CStr::from_ptr(SLICE.as_ptr()) } + } +} + +#[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")] +impl fmt::Display for FromBytesWithNulError { + #[allow(deprecated, deprecated_in_future)] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.description())?; + if let FromBytesWithNulErrorKind::InteriorNul(pos) = self.kind { + write!(f, " at byte pos {pos}")?; + } + Ok(()) + } +} + +impl CStr { + /// Wraps a raw C string with a safe C string wrapper. + /// + /// This function will wrap the provided `ptr` with a `CStr` wrapper, which + /// allows inspection and interoperation of non-owned C strings. The total + /// size of the terminated buffer must be smaller than [`isize::MAX`] **bytes** + /// in memory (a restriction from [`slice::from_raw_parts`]). + /// + /// # Safety + /// + /// * The memory pointed to by `ptr` must contain a valid nul terminator at the + /// end of the string. + /// + /// * `ptr` must be [valid] for reads of bytes up to and including the nul terminator. + /// This means in particular: + /// + /// * The entire memory range of this `CStr` must be contained within a single allocated object! + /// * `ptr` must be non-null even for a zero-length cstr. + /// + /// * The memory referenced by the returned `CStr` must not be mutated for + /// the duration of lifetime `'a`. + /// + /// * The nul terminator must be within `isize::MAX` from `ptr` + /// + /// > **Note**: This operation is intended to be a 0-cost cast but it is + /// > currently implemented with an up-front calculation of the length of + /// > the string. This is not guaranteed to always be the case. + /// + /// # Caveat + /// + /// The lifetime for the returned slice is inferred from its usage. To prevent accidental misuse, + /// it's suggested to tie the lifetime to whichever source lifetime is safe in the context, + /// such as by providing a helper function taking the lifetime of a host value for the slice, + /// or by explicit annotation. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::{c_char, CStr}; + /// + /// fn my_string() -> *const c_char { + /// c"hello".as_ptr() + /// } + /// + /// unsafe { + /// let slice = CStr::from_ptr(my_string()); + /// assert_eq!(slice.to_str().unwrap(), "hello"); + /// } + /// ``` + /// + /// ``` + /// use std::ffi::{c_char, CStr}; + /// + /// const HELLO_PTR: *const c_char = { + /// const BYTES: &[u8] = b"Hello, world!\0"; + /// BYTES.as_ptr().cast() + /// }; + /// const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) }; + /// + /// assert_eq!(c"Hello, world!", HELLO); + /// ``` + /// + /// [valid]: core::ptr#safety + #[inline] // inline is necessary for codegen to see strlen. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")] + pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { + // SAFETY: The caller has provided a pointer that points to a valid C + // string with a NUL terminator less than `isize::MAX` from `ptr`. + let len = unsafe { strlen(ptr) }; + + // SAFETY: The caller has provided a valid pointer with length less than + // `isize::MAX`, so `from_raw_parts` is safe. The content remains valid + // and doesn't change for the lifetime of the returned `CStr`. This + // means the call to `from_bytes_with_nul_unchecked` is correct. + // + // The cast from c_char to u8 is ok because a c_char is always one byte. + unsafe { Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr.cast(), len + 1)) } + } + + /// Creates a C string wrapper from a byte slice with any number of nuls. + /// + /// This method will create a `CStr` from any byte slice that contains at + /// least one nul byte. Unlike with [`CStr::from_bytes_with_nul`], the caller + /// does not need to know where the nul byte is located. + /// + /// If the first byte is a nul character, this method will return an + /// empty `CStr`. If multiple nul characters are present, the `CStr` will + /// end at the first one. + /// + /// If the slice only has a single nul byte at the end, this method is + /// equivalent to [`CStr::from_bytes_with_nul`]. + /// + /// # Examples + /// ``` + /// use std::ffi::CStr; + /// + /// let mut buffer = [0u8; 16]; + /// unsafe { + /// // Here we might call an unsafe C function that writes a string + /// // into the buffer. + /// let buf_ptr = buffer.as_mut_ptr(); + /// buf_ptr.write_bytes(b'A', 8); + /// } + /// // Attempt to extract a C nul-terminated string from the buffer. + /// let c_str = CStr::from_bytes_until_nul(&buffer[..]).unwrap(); + /// assert_eq!(c_str.to_str().unwrap(), "AAAAAAAA"); + /// ``` + /// + #[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] + #[rustc_const_stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] + pub const fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError> { + let nul_pos = memchr::memchr(0, bytes); + match nul_pos { + Some(nul_pos) => { + // FIXME(const-hack) replace with range index + // SAFETY: nul_pos + 1 <= bytes.len() + let subslice = unsafe { crate::slice::from_raw_parts(bytes.as_ptr(), nul_pos + 1) }; + // SAFETY: We know there is a nul byte at nul_pos, so this slice + // (ending at the nul byte) is a well-formed C string. + Ok(unsafe { CStr::from_bytes_with_nul_unchecked(subslice) }) + } + None => Err(FromBytesUntilNulError(())), + } + } + + /// Creates a C string wrapper from a byte slice with exactly one nul + /// terminator. + /// + /// This function will cast the provided `bytes` to a `CStr` + /// wrapper after ensuring that the byte slice is nul-terminated + /// and does not contain any interior nul bytes. + /// + /// If the nul byte may not be at the end, + /// [`CStr::from_bytes_until_nul`] can be used instead. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CStr; + /// + /// let cstr = CStr::from_bytes_with_nul(b"hello\0"); + /// assert!(cstr.is_ok()); + /// ``` + /// + /// Creating a `CStr` without a trailing nul terminator is an error: + /// + /// ``` + /// use std::ffi::CStr; + /// + /// let cstr = CStr::from_bytes_with_nul(b"hello"); + /// assert!(cstr.is_err()); + /// ``` + /// + /// Creating a `CStr` with an interior nul byte is an error: + /// + /// ``` + /// use std::ffi::CStr; + /// + /// let cstr = CStr::from_bytes_with_nul(b"he\0llo\0"); + /// assert!(cstr.is_err()); + /// ``` + #[stable(feature = "cstr_from_bytes", since = "1.10.0")] + #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")] + pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> { + let nul_pos = memchr::memchr(0, bytes); + match nul_pos { + Some(nul_pos) if nul_pos + 1 == bytes.len() => { + // SAFETY: We know there is only one nul byte, at the end + // of the byte slice. + Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) }) + } + Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)), + None => Err(FromBytesWithNulError::not_nul_terminated()), + } + } + + /// Unsafely creates a C string wrapper from a byte slice. + /// + /// This function will cast the provided `bytes` to a `CStr` wrapper without + /// performing any sanity checks. + /// + /// # Safety + /// The provided slice **must** be nul-terminated and not contain any interior + /// nul bytes. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::{CStr, CString}; + /// + /// unsafe { + /// let cstring = CString::new("hello").expect("CString::new failed"); + /// let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul()); + /// assert_eq!(cstr, &*cstring); + /// } + /// ``` + #[inline] + #[must_use] + #[stable(feature = "cstr_from_bytes", since = "1.10.0")] + #[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")] + #[rustc_allow_const_fn_unstable(const_eval_select)] + pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { + const_eval_select!( + @capture { bytes: &[u8] } -> &CStr: + if const { + // Saturating so that an empty slice panics in the assert with a good + // message, not here due to underflow. + let mut i = bytes.len().saturating_sub(1); + assert!(!bytes.is_empty() && bytes[i] == 0, "input was not nul-terminated"); + + // Ending nul byte exists, skip to the rest. + while i != 0 { + i -= 1; + let byte = bytes[i]; + assert!(byte != 0, "input contained interior nul"); + } + + // SAFETY: See runtime cast comment below. + unsafe { &*(bytes as *const [u8] as *const CStr) } + } else { + // Chance at catching some UB at runtime with debug builds. + debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0); + + // SAFETY: Casting to CStr is safe because its internal representation + // is a [u8] too (safe only inside std). + // Dereferencing the obtained pointer is safe because it comes from a + // reference. Making a reference is then safe because its lifetime + // is bound by the lifetime of the given `bytes`. + unsafe { &*(bytes as *const [u8] as *const CStr) } + } + ) + } + + /// Returns the inner pointer to this C string. + /// + /// The returned pointer will be valid for as long as `self` is, and points + /// to a contiguous region of memory terminated with a 0 byte to represent + /// the end of the string. + /// + /// The type of the returned pointer is + /// [`*const c_char`][crate::ffi::c_char], and whether it's + /// an alias for `*const i8` or `*const u8` is platform-specific. + /// + /// **WARNING** + /// + /// The returned pointer is read-only; writing to it (including passing it + /// to C code that writes to it) causes undefined behavior. + /// + /// It is your responsibility to make sure that the underlying memory is not + /// freed too early. For example, the following code will cause undefined + /// behavior when `ptr` is used inside the `unsafe` block: + /// + /// ```no_run + /// # #![allow(unused_must_use)] + /// # #![expect(dangling_pointers_from_temporaries)] + /// use std::ffi::CString; + /// + /// // Do not do this: + /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr(); + /// unsafe { + /// // `ptr` is dangling + /// *ptr; + /// } + /// ``` + /// + /// This happens because the pointer returned by `as_ptr` does not carry any + /// lifetime information and the `CString` is deallocated immediately after + /// the `CString::new("Hello").expect("CString::new failed").as_ptr()` + /// expression is evaluated. + /// To fix the problem, bind the `CString` to a local variable: + /// + /// ```no_run + /// # #![allow(unused_must_use)] + /// use std::ffi::CString; + /// + /// let hello = CString::new("Hello").expect("CString::new failed"); + /// let ptr = hello.as_ptr(); + /// unsafe { + /// // `ptr` is valid because `hello` is in scope + /// *ptr; + /// } + /// ``` + /// + /// This way, the lifetime of the `CString` in `hello` encompasses + /// the lifetime of `ptr` and the `unsafe` block. + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")] + #[rustc_as_ptr] + #[rustc_never_returns_null_ptr] + pub const fn as_ptr(&self) -> *const c_char { + self.inner.as_ptr() + } + + /// We could eventually expose this publicly, if we wanted. + #[inline] + #[must_use] + const fn as_non_null_ptr(&self) -> NonNull { + // FIXME(const_trait_impl) replace with `NonNull::from` + // SAFETY: a reference is never null + unsafe { NonNull::new_unchecked(&self.inner as *const [c_char] as *mut [c_char]) } + .as_non_null_ptr() + } + + /// Returns the length of `self`. Like C's `strlen`, this does not include the nul terminator. + /// + /// > **Note**: This method is currently implemented as a constant-time + /// > cast, but it is planned to alter its definition in the future to + /// > perform the length calculation whenever this method is called. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CStr; + /// + /// let cstr = CStr::from_bytes_with_nul(b"foo\0").unwrap(); + /// assert_eq!(cstr.count_bytes(), 3); + /// + /// let cstr = CStr::from_bytes_with_nul(b"\0").unwrap(); + /// assert_eq!(cstr.count_bytes(), 0); + /// ``` + #[inline] + #[must_use] + #[doc(alias("len", "strlen"))] + #[stable(feature = "cstr_count_bytes", since = "1.79.0")] + #[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")] + pub const fn count_bytes(&self) -> usize { + self.inner.len() - 1 + } + + /// Returns `true` if `self.to_bytes()` has a length of 0. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CStr; + /// # use std::ffi::FromBytesWithNulError; + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Result<(), FromBytesWithNulError> { + /// let cstr = CStr::from_bytes_with_nul(b"foo\0")?; + /// assert!(!cstr.is_empty()); + /// + /// let empty_cstr = CStr::from_bytes_with_nul(b"\0")?; + /// assert!(empty_cstr.is_empty()); + /// assert!(c"".is_empty()); + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "cstr_is_empty", since = "1.71.0")] + #[rustc_const_stable(feature = "cstr_is_empty", since = "1.71.0")] + pub const fn is_empty(&self) -> bool { + // SAFETY: We know there is at least one byte; for empty strings it + // is the NUL terminator. + // FIXME(const-hack): use get_unchecked + unsafe { *self.inner.as_ptr() == 0 } + } + + /// Converts this C string to a byte slice. + /// + /// The returned slice will **not** contain the trailing nul terminator that this C + /// string has. + /// + /// > **Note**: This method is currently implemented as a constant-time + /// > cast, but it is planned to alter its definition in the future to + /// > perform the length calculation whenever this method is called. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CStr; + /// + /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + /// assert_eq!(cstr.to_bytes(), b"foo"); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")] + pub const fn to_bytes(&self) -> &[u8] { + let bytes = self.to_bytes_with_nul(); + // FIXME(const-hack) replace with range index + // SAFETY: to_bytes_with_nul returns slice with length at least 1 + unsafe { slice::from_raw_parts(bytes.as_ptr(), bytes.len() - 1) } + } + + /// Converts this C string to a byte slice containing the trailing 0 byte. + /// + /// This function is the equivalent of [`CStr::to_bytes`] except that it + /// will retain the trailing nul terminator instead of chopping it off. + /// + /// > **Note**: This method is currently implemented as a 0-cost cast, but + /// > it is planned to alter its definition in the future to perform the + /// > length calculation whenever this method is called. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CStr; + /// + /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + /// assert_eq!(cstr.to_bytes_with_nul(), b"foo\0"); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")] + pub const fn to_bytes_with_nul(&self) -> &[u8] { + // SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s + // is safe on all supported targets. + unsafe { &*((&raw const self.inner) as *const [u8]) } + } + + /// Iterates over the bytes in this C string. + /// + /// The returned iterator will **not** contain the trailing nul terminator + /// that this C string has. + /// + /// # Examples + /// + /// ``` + /// #![feature(cstr_bytes)] + /// use std::ffi::CStr; + /// + /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + /// assert!(cstr.bytes().eq(*b"foo")); + /// ``` + #[inline] + #[unstable(feature = "cstr_bytes", issue = "112115")] + pub fn bytes(&self) -> Bytes<'_> { + Bytes::new(self) + } + + /// Yields a &[str] slice if the `CStr` contains valid UTF-8. + /// + /// If the contents of the `CStr` are valid UTF-8 data, this + /// function will return the corresponding &[str] slice. Otherwise, + /// it will return an error with details of where UTF-8 validation failed. + /// + /// [str]: prim@str "str" + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CStr; + /// + /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + /// assert_eq!(cstr.to_str(), Ok("foo")); + /// ``` + #[stable(feature = "cstr_to_str", since = "1.4.0")] + #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")] + pub const fn to_str(&self) -> Result<&str, str::Utf8Error> { + // N.B., when `CStr` is changed to perform the length check in `.to_bytes()` + // instead of in `from_ptr()`, it may be worth considering if this should + // be rewritten to do the UTF-8 check inline with the length calculation + // instead of doing it afterwards. + str::from_utf8(self.to_bytes()) + } +} + +// `.to_bytes()` representations are compared instead of the inner `[c_char]`s, +// because `c_char` is `i8` (not `u8`) on some platforms. +// That is why this is implemented manually and not derived. +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for CStr { + #[inline] + fn partial_cmp(&self, other: &CStr) -> Option { + self.to_bytes().partial_cmp(&other.to_bytes()) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for CStr { + #[inline] + fn cmp(&self, other: &CStr) -> Ordering { + self.to_bytes().cmp(&other.to_bytes()) + } +} + +#[stable(feature = "cstr_range_from", since = "1.47.0")] +impl ops::Index> for CStr { + type Output = CStr; + + #[inline] + fn index(&self, index: ops::RangeFrom) -> &CStr { + let bytes = self.to_bytes_with_nul(); + // we need to manually check the starting index to account for the null + // byte, since otherwise we could get an empty string that doesn't end + // in a null. + if index.start < bytes.len() { + // SAFETY: Non-empty tail of a valid `CStr` is still a valid `CStr`. + unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) } + } else { + panic!( + "index out of bounds: the len is {} but the index is {}", + bytes.len(), + index.start + ); + } + } +} + +#[stable(feature = "cstring_asref", since = "1.7.0")] +impl AsRef for CStr { + #[inline] + fn as_ref(&self) -> &CStr { + self + } +} + +/// Calculate the length of a nul-terminated string. Defers to C's `strlen` when possible. +/// +/// # Safety +/// +/// The pointer must point to a valid buffer that contains a NUL terminator. The NUL must be +/// located within `isize::MAX` from `ptr`. +#[inline] +#[unstable(feature = "cstr_internals", issue = "none")] +#[rustc_allow_const_fn_unstable(const_eval_select)] +const unsafe fn strlen(ptr: *const c_char) -> usize { + const_eval_select!( + @capture { s: *const c_char = ptr } -> usize: + if const { + let mut len = 0; + + // SAFETY: Outer caller has provided a pointer to a valid C string. + while unsafe { *s.add(len) } != 0 { + len += 1; + } + + len + } else { + extern "C" { + /// Provided by libc or compiler_builtins. + fn strlen(s: *const c_char) -> usize; + } + + // SAFETY: Outer caller has provided a pointer to a valid C string. + unsafe { strlen(s) } + } + ) +} + +/// An iterator over the bytes of a [`CStr`], without the nul terminator. +/// +/// This struct is created by the [`bytes`] method on [`CStr`]. +/// See its documentation for more. +/// +/// [`bytes`]: CStr::bytes +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[unstable(feature = "cstr_bytes", issue = "112115")] +#[derive(Clone, Debug)] +pub struct Bytes<'a> { + // since we know the string is nul-terminated, we only need one pointer + ptr: NonNull, + phantom: PhantomData<&'a [c_char]>, +} + +#[unstable(feature = "cstr_bytes", issue = "112115")] +unsafe impl Send for Bytes<'_> {} + +#[unstable(feature = "cstr_bytes", issue = "112115")] +unsafe impl Sync for Bytes<'_> {} + +impl<'a> Bytes<'a> { + #[inline] + fn new(s: &'a CStr) -> Self { + Self { ptr: s.as_non_null_ptr().cast(), phantom: PhantomData } + } + + #[inline] + fn is_empty(&self) -> bool { + // SAFETY: We uphold that the pointer is always valid to dereference + // by starting with a valid C string and then never incrementing beyond + // the nul terminator. + unsafe { self.ptr.read() == 0 } + } +} + +#[unstable(feature = "cstr_bytes", issue = "112115")] +impl Iterator for Bytes<'_> { + type Item = u8; + + #[inline] + fn next(&mut self) -> Option { + // SAFETY: We only choose a pointer from a valid C string, which must + // be non-null and contain at least one value. Since we always stop at + // the nul terminator, which is guaranteed to exist, we can assume that + // the pointer is non-null and valid. This lets us safely dereference + // it and assume that adding 1 will create a new, non-null, valid + // pointer. + unsafe { + let ret = self.ptr.read(); + if ret == 0 { + None + } else { + self.ptr = self.ptr.add(1); + Some(ret) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.is_empty() { (0, Some(0)) } else { (1, None) } + } + + #[inline] + fn count(self) -> usize { + // SAFETY: We always hold a valid pointer to a C string + unsafe { strlen(self.ptr.as_ptr().cast()) } + } +} + +#[unstable(feature = "cstr_bytes", issue = "112115")] +impl FusedIterator for Bytes<'_> {} diff --git a/CoqOfRust/core/ffi/mod.rs b/CoqOfRust/core/ffi/mod.rs new file mode 100644 index 000000000..dc107c5d2 --- /dev/null +++ b/CoqOfRust/core/ffi/mod.rs @@ -0,0 +1,225 @@ +//! Platform-specific types, as defined by C. +//! +//! Code that interacts via FFI will almost certainly be using the +//! base types provided by C, which aren't nearly as nicely defined +//! as Rust's primitive types. This module provides types which will +//! match those defined by C, so that code that interacts with C will +//! refer to the correct types. + +#![stable(feature = "core_ffi", since = "1.30.0")] +#![allow(non_camel_case_types)] + +#[doc(inline)] +#[stable(feature = "core_c_str", since = "1.64.0")] +pub use self::c_str::CStr; +#[doc(no_inline)] +#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] +pub use self::c_str::FromBytesUntilNulError; +#[doc(no_inline)] +#[stable(feature = "core_c_str", since = "1.64.0")] +pub use self::c_str::FromBytesWithNulError; +use crate::fmt; + +#[unstable(feature = "c_str_module", issue = "112134")] +pub mod c_str; + +#[unstable( + feature = "c_variadic", + issue = "44930", + reason = "the `c_variadic` feature has not been properly tested on all supported platforms" +)] +pub use self::va_list::{VaList, VaListImpl}; + +#[unstable( + feature = "c_variadic", + issue = "44930", + reason = "the `c_variadic` feature has not been properly tested on all supported platforms" +)] +pub mod va_list; + +macro_rules! type_alias { + { + $Docfile:tt, $Alias:ident = $Real:ty; + $( $Cfg:tt )* + } => { + #[doc = include_str!($Docfile)] + $( $Cfg )* + #[stable(feature = "core_ffi_c", since = "1.64.0")] + pub type $Alias = $Real; + } +} + +type_alias! { "c_char.md", c_char = c_char_definition::c_char; #[doc(cfg(all()))] } + +type_alias! { "c_schar.md", c_schar = i8; } +type_alias! { "c_uchar.md", c_uchar = u8; } +type_alias! { "c_short.md", c_short = i16; } +type_alias! { "c_ushort.md", c_ushort = u16; } + +type_alias! { "c_int.md", c_int = c_int_definition::c_int; #[doc(cfg(all()))] } +type_alias! { "c_uint.md", c_uint = c_int_definition::c_uint; #[doc(cfg(all()))] } + +type_alias! { "c_long.md", c_long = c_long_definition::c_long; #[doc(cfg(all()))] } +type_alias! { "c_ulong.md", c_ulong = c_long_definition::c_ulong; #[doc(cfg(all()))] } + +type_alias! { "c_longlong.md", c_longlong = i64; } +type_alias! { "c_ulonglong.md", c_ulonglong = u64; } + +type_alias! { "c_float.md", c_float = f32; } +type_alias! { "c_double.md", c_double = f64; } + +/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++). +/// +/// This type is currently always [`usize`], however in the future there may be +/// platforms where this is not the case. +#[unstable(feature = "c_size_t", issue = "88345")] +pub type c_size_t = usize; + +/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++). +/// +/// This type is currently always [`isize`], however in the future there may be +/// platforms where this is not the case. +#[unstable(feature = "c_size_t", issue = "88345")] +pub type c_ptrdiff_t = isize; + +/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type. +/// +/// This type is currently always [`isize`], however in the future there may be +/// platforms where this is not the case. +#[unstable(feature = "c_size_t", issue = "88345")] +pub type c_ssize_t = isize; + +mod c_char_definition { + cfg_if! { + // These are the targets on which c_char is unsigned. + if #[cfg(any( + all( + target_os = "linux", + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "hexagon", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "s390x", + target_arch = "riscv64", + target_arch = "riscv32", + target_arch = "csky" + ) + ), + all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")), + all(target_os = "l4re", target_arch = "x86_64"), + all( + any(target_os = "freebsd", target_os = "openbsd", target_os = "rtems"), + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "riscv64" + ) + ), + all( + target_os = "netbsd", + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "riscv64" + ) + ), + all( + target_os = "vxworks", + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc64", + target_arch = "powerpc" + ) + ), + all( + target_os = "fuchsia", + any(target_arch = "aarch64", target_arch = "riscv64") + ), + all(target_os = "nto", target_arch = "aarch64"), + target_os = "horizon", + target_os = "aix", + ))] { + pub type c_char = u8; + } else { + // On every other target, c_char is signed. + pub type c_char = i8; + } + } +} + +mod c_int_definition { + cfg_if! { + if #[cfg(any(target_arch = "avr", target_arch = "msp430"))] { + pub type c_int = i16; + pub type c_uint = u16; + } else { + pub type c_int = i32; + pub type c_uint = u32; + } + } +} + +mod c_long_definition { + cfg_if! { + if #[cfg(all(target_pointer_width = "64", not(windows)))] { + pub type c_long = i64; + pub type c_ulong = u64; + } else { + // The minimal size of `long` in the C standard is 32 bits + pub type c_long = i32; + pub type c_ulong = u32; + } + } +} + +// N.B., for LLVM to recognize the void pointer type and by extension +// functions like malloc(), we need to have it represented as i8* in +// LLVM bitcode. The enum used here ensures this and prevents misuse +// of the "raw" type by only having private variants. We need two +// variants, because the compiler complains about the repr attribute +// otherwise and we need at least one variant as otherwise the enum +// would be uninhabited and at least dereferencing such pointers would +// be UB. +#[doc = include_str!("c_void.md")] +#[lang = "c_void"] +#[cfg_attr(not(doc), repr(u8))] // An implementation detail we don't want to show up in rustdoc +#[stable(feature = "core_c_void", since = "1.30.0")] +pub enum c_void { + #[unstable( + feature = "c_void_variant", + reason = "temporary implementation detail", + issue = "none" + )] + #[doc(hidden)] + __variant1, + #[unstable( + feature = "c_void_variant", + reason = "temporary implementation detail", + issue = "none" + )] + #[doc(hidden)] + __variant2, +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for c_void { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("c_void").finish() + } +} + +// Link the MSVC default lib +#[cfg(all(windows, target_env = "msvc"))] +#[link( + name = "/defaultlib:msvcrt", + modifiers = "+verbatim", + cfg(not(target_feature = "crt-static")) +)] +#[link(name = "/defaultlib:libcmt", modifiers = "+verbatim", cfg(target_feature = "crt-static"))] +extern "C" {} diff --git a/CoqOfRust/core/ffi/va_list.rs b/CoqOfRust/core/ffi/va_list.rs new file mode 100644 index 000000000..f67c592d8 --- /dev/null +++ b/CoqOfRust/core/ffi/va_list.rs @@ -0,0 +1,319 @@ +//! C's "variable arguments" +//! +//! Better known as "varargs". + +use crate::ffi::c_void; +#[allow(unused_imports)] +use crate::fmt; +use crate::marker::PhantomData; +use crate::ops::{Deref, DerefMut}; + +/// Basic implementation of a `va_list`. +// The name is WIP, using `VaListImpl` for now. +#[cfg(any( + all( + not(target_arch = "aarch64"), + not(target_arch = "powerpc"), + not(target_arch = "s390x"), + not(target_arch = "xtensa"), + not(target_arch = "x86_64") + ), + all(target_arch = "aarch64", target_vendor = "apple"), + target_family = "wasm", + target_os = "uefi", + windows, +))] +#[repr(transparent)] +#[lang = "va_list"] +pub struct VaListImpl<'f> { + ptr: *mut c_void, + + // Invariant over `'f`, so each `VaListImpl<'f>` object is tied to + // the region of the function it's defined in + _marker: PhantomData<&'f mut &'f c_void>, +} + +#[cfg(any( + all( + not(target_arch = "aarch64"), + not(target_arch = "powerpc"), + not(target_arch = "s390x"), + not(target_arch = "xtensa"), + not(target_arch = "x86_64") + ), + all(target_arch = "aarch64", target_vendor = "apple"), + target_family = "wasm", + target_os = "uefi", + windows, +))] +impl<'f> fmt::Debug for VaListImpl<'f> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "va_list* {:p}", self.ptr) + } +} + +/// AArch64 ABI implementation of a `va_list`. See the +/// [AArch64 Procedure Call Standard] for more details. +/// +/// [AArch64 Procedure Call Standard]: +/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf +#[cfg(all( + target_arch = "aarch64", + not(target_vendor = "apple"), + not(target_os = "uefi"), + not(windows), +))] +#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 +#[derive(Debug)] +#[lang = "va_list"] +pub struct VaListImpl<'f> { + stack: *mut c_void, + gr_top: *mut c_void, + vr_top: *mut c_void, + gr_offs: i32, + vr_offs: i32, + _marker: PhantomData<&'f mut &'f c_void>, +} + +/// PowerPC ABI implementation of a `va_list`. +#[cfg(all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)))] +#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 +#[derive(Debug)] +#[lang = "va_list"] +pub struct VaListImpl<'f> { + gpr: u8, + fpr: u8, + reserved: u16, + overflow_arg_area: *mut c_void, + reg_save_area: *mut c_void, + _marker: PhantomData<&'f mut &'f c_void>, +} + +/// s390x ABI implementation of a `va_list`. +#[cfg(target_arch = "s390x")] +#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 +#[derive(Debug)] +#[lang = "va_list"] +pub struct VaListImpl<'f> { + gpr: i64, + fpr: i64, + overflow_arg_area: *mut c_void, + reg_save_area: *mut c_void, + _marker: PhantomData<&'f mut &'f c_void>, +} + +/// x86_64 ABI implementation of a `va_list`. +#[cfg(all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)))] +#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 +#[derive(Debug)] +#[lang = "va_list"] +pub struct VaListImpl<'f> { + gp_offset: i32, + fp_offset: i32, + overflow_arg_area: *mut c_void, + reg_save_area: *mut c_void, + _marker: PhantomData<&'f mut &'f c_void>, +} + +/// Xtensa ABI implementation of a `va_list`. +#[cfg(target_arch = "xtensa")] +#[repr(C)] +#[derive(Debug)] +#[lang = "va_list"] +pub struct VaListImpl<'f> { + stk: *mut i32, + reg: *mut i32, + ndx: i32, + _marker: PhantomData<&'f mut &'f c_void>, +} + +/// A wrapper for a `va_list` +#[repr(transparent)] +#[derive(Debug)] +pub struct VaList<'a, 'f: 'a> { + #[cfg(any( + all( + not(target_arch = "aarch64"), + not(target_arch = "powerpc"), + not(target_arch = "s390x"), + not(target_arch = "x86_64") + ), + target_arch = "xtensa", + all(target_arch = "aarch64", target_vendor = "apple"), + target_family = "wasm", + target_os = "uefi", + windows, + ))] + inner: VaListImpl<'f>, + + #[cfg(all( + any( + target_arch = "aarch64", + target_arch = "powerpc", + target_arch = "s390x", + target_arch = "x86_64" + ), + not(target_arch = "xtensa"), + any(not(target_arch = "aarch64"), not(target_vendor = "apple")), + not(target_family = "wasm"), + not(target_os = "uefi"), + not(windows), + ))] + inner: &'a mut VaListImpl<'f>, + + _marker: PhantomData<&'a mut VaListImpl<'f>>, +} + +#[cfg(any( + all( + not(target_arch = "aarch64"), + not(target_arch = "powerpc"), + not(target_arch = "s390x"), + not(target_arch = "x86_64") + ), + target_arch = "xtensa", + all(target_arch = "aarch64", target_vendor = "apple"), + target_family = "wasm", + target_os = "uefi", + windows, +))] +impl<'f> VaListImpl<'f> { + /// Converts a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`. + #[inline] + pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { + VaList { inner: VaListImpl { ..*self }, _marker: PhantomData } + } +} + +#[cfg(all( + any( + target_arch = "aarch64", + target_arch = "powerpc", + target_arch = "s390x", + target_arch = "xtensa", + target_arch = "x86_64" + ), + not(target_arch = "xtensa"), + any(not(target_arch = "aarch64"), not(target_vendor = "apple")), + not(target_family = "wasm"), + not(target_os = "uefi"), + not(windows), +))] +impl<'f> VaListImpl<'f> { + /// Converts a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`. + #[inline] + pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { + VaList { inner: self, _marker: PhantomData } + } +} + +impl<'a, 'f: 'a> Deref for VaList<'a, 'f> { + type Target = VaListImpl<'f>; + + #[inline] + fn deref(&self) -> &VaListImpl<'f> { + &self.inner + } +} + +impl<'a, 'f: 'a> DerefMut for VaList<'a, 'f> { + #[inline] + fn deref_mut(&mut self) -> &mut VaListImpl<'f> { + &mut self.inner + } +} + +// The VaArgSafe trait needs to be used in public interfaces, however, the trait +// itself must not be allowed to be used outside this module. Allowing users to +// implement the trait for a new type (thereby allowing the va_arg intrinsic to +// be used on a new type) is likely to cause undefined behavior. +// +// FIXME(dlrobertson): In order to use the VaArgSafe trait in a public interface +// but also ensure it cannot be used elsewhere, the trait needs to be public +// within a private module. Once RFC 2145 has been implemented look into +// improving this. +mod sealed_trait { + /// Trait which permits the allowed types to be used with [super::VaListImpl::arg]. + pub unsafe trait VaArgSafe {} +} + +macro_rules! impl_va_arg_safe { + ($($t:ty),+) => { + $( + unsafe impl sealed_trait::VaArgSafe for $t {} + )+ + } +} + +impl_va_arg_safe! {i8, i16, i32, i64, usize} +impl_va_arg_safe! {u8, u16, u32, u64, isize} +impl_va_arg_safe! {f64} + +unsafe impl sealed_trait::VaArgSafe for *mut T {} +unsafe impl sealed_trait::VaArgSafe for *const T {} + +impl<'f> VaListImpl<'f> { + /// Advance to the next arg. + #[inline] + pub unsafe fn arg(&mut self) -> T { + // SAFETY: the caller must uphold the safety contract for `va_arg`. + unsafe { va_arg(self) } + } + + /// Copies the `va_list` at the current location. + pub unsafe fn with_copy(&self, f: F) -> R + where + F: for<'copy> FnOnce(VaList<'copy, 'f>) -> R, + { + let mut ap = self.clone(); + let ret = f(ap.as_va_list()); + // SAFETY: the caller must uphold the safety contract for `va_end`. + unsafe { + va_end(&mut ap); + } + ret + } +} + +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() + } + } +} + +impl<'f> Drop for VaListImpl<'f> { + fn drop(&mut self) { + // FIXME: this should call `va_end`, but there's no clean way to + // guarantee that `drop` always gets inlined into its caller, + // so the `va_end` would get directly called from the same function as + // the corresponding `va_copy`. `man va_end` states that C requires this, + // and LLVM basically follows the C semantics, so we need to make sure + // that `va_end` is always called from the same function as `va_copy`. + // For more details, see https://github.com/rust-lang/rust/pull/59625 + // and https://llvm.org/docs/LangRef.html#llvm-va-end-intrinsic. + // + // This works for now, since `va_end` is a no-op on all current LLVM targets. + } +} + +extern "rust-intrinsic" { + /// Destroy the arglist `ap` after initialization with `va_start` or + /// `va_copy`. + #[rustc_nounwind] + fn va_end(ap: &mut VaListImpl<'_>); + + /// Copies the current location of arglist `src` to the arglist `dst`. + #[rustc_nounwind] + fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>); + + /// Loads an argument of type `T` from the `va_list` `ap` and increment the + /// argument `ap` points to. + #[rustc_nounwind] + fn va_arg(ap: &mut VaListImpl<'_>) -> T; +} diff --git a/CoqOfRust/core/fmt/builders.rs b/CoqOfRust/core/fmt/builders.rs new file mode 100644 index 000000000..1862be0e8 --- /dev/null +++ b/CoqOfRust/core/fmt/builders.rs @@ -0,0 +1,1261 @@ +#![allow(unused_imports)] + +use crate::fmt::{self, Debug, Formatter}; + +struct PadAdapter<'buf, 'state> { + buf: &'buf mut (dyn fmt::Write + 'buf), + state: &'state mut PadAdapterState, +} + +struct PadAdapterState { + on_newline: bool, +} + +impl Default for PadAdapterState { + fn default() -> Self { + PadAdapterState { on_newline: true } + } +} + +impl<'buf, 'state> PadAdapter<'buf, 'state> { + fn wrap<'slot, 'fmt: 'buf + 'slot>( + fmt: &'fmt mut fmt::Formatter<'_>, + slot: &'slot mut Option, + state: &'state mut PadAdapterState, + ) -> fmt::Formatter<'slot> { + fmt.wrap_buf(move |buf| slot.insert(PadAdapter { buf, state })) + } +} + +impl fmt::Write for PadAdapter<'_, '_> { + fn write_str(&mut self, s: &str) -> fmt::Result { + for s in s.split_inclusive('\n') { + if self.state.on_newline { + self.buf.write_str(" ")?; + } + + self.state.on_newline = s.ends_with('\n'); + self.buf.write_str(s)?; + } + + Ok(()) + } + + fn write_char(&mut self, c: char) -> fmt::Result { + if self.state.on_newline { + self.buf.write_str(" ")?; + } + self.state.on_newline = c == '\n'; + self.buf.write_char(c) + } +} + +/// A struct to help with [`fmt::Debug`](Debug) implementations. +/// +/// This is useful when you wish to output a formatted struct as a part of your +/// [`Debug::fmt`] implementation. +/// +/// This can be constructed by the [`Formatter::debug_struct`] method. +/// +/// # Examples +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo { +/// bar: i32, +/// baz: String, +/// } +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { +/// fmt.debug_struct("Foo") +/// .field("bar", &self.bar) +/// .field("baz", &self.baz) +/// .finish() +/// } +/// } +/// +/// assert_eq!( +/// format!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }), +/// r#"Foo { bar: 10, baz: "Hello World" }"#, +/// ); +/// ``` +#[must_use = "must eventually call `finish()` on Debug builders"] +#[allow(missing_debug_implementations)] +#[stable(feature = "debug_builders", since = "1.2.0")] +#[rustc_diagnostic_item = "DebugStruct"] +pub struct DebugStruct<'a, 'b: 'a> { + fmt: &'a mut fmt::Formatter<'b>, + result: fmt::Result, + has_fields: bool, +} + +pub(super) fn debug_struct_new<'a, 'b>( + fmt: &'a mut fmt::Formatter<'b>, + name: &str, +) -> DebugStruct<'a, 'b> { + let result = fmt.write_str(name); + DebugStruct { fmt, result, has_fields: false } +} + +impl<'a, 'b: 'a> DebugStruct<'a, 'b> { + /// Adds a new field to the generated struct output. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Bar { + /// bar: i32, + /// another: String, + /// } + /// + /// impl fmt::Debug for Bar { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_struct("Bar") + /// .field("bar", &self.bar) // We add `bar` field. + /// .field("another", &self.another) // We add `another` field. + /// // We even add a field which doesn't exist (because why not?). + /// .field("nonexistent_field", &1) + /// .finish() // We're good to go! + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Bar { bar: 10, another: "Hello World".to_string() }), + /// r#"Bar { bar: 10, another: "Hello World", nonexistent_field: 1 }"#, + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut Self { + self.field_with(name, |f| value.fmt(f)) + } + + /// Adds a new field to the generated struct output. + /// + /// This method is equivalent to [`DebugStruct::field`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn field_with(&mut self, name: &str, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.result = self.result.and_then(|_| { + if self.is_pretty() { + if !self.has_fields { + self.fmt.write_str(" {\n")?; + } + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); + writer.write_str(name)?; + writer.write_str(": ")?; + value_fmt(&mut writer)?; + writer.write_str(",\n") + } else { + let prefix = if self.has_fields { ", " } else { " { " }; + self.fmt.write_str(prefix)?; + self.fmt.write_str(name)?; + self.fmt.write_str(": ")?; + value_fmt(self.fmt) + } + }); + + self.has_fields = true; + self + } + + /// Marks the struct as non-exhaustive, indicating to the reader that there are some other + /// fields that are not shown in the debug representation. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Bar { + /// bar: i32, + /// hidden: f32, + /// } + /// + /// impl fmt::Debug for Bar { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_struct("Bar") + /// .field("bar", &self.bar) + /// .finish_non_exhaustive() // Show that some other field(s) exist. + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Bar { bar: 10, hidden: 1.0 }), + /// "Bar { bar: 10, .. }", + /// ); + /// ``` + #[stable(feature = "debug_non_exhaustive", since = "1.53.0")] + pub fn finish_non_exhaustive(&mut self) -> fmt::Result { + self.result = self.result.and_then(|_| { + if self.has_fields { + if self.is_pretty() { + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + self.fmt.write_str("}") + } else { + self.fmt.write_str(", .. }") + } + } else { + self.fmt.write_str(" { .. }") + } + }); + self.result + } + + /// Finishes output and returns any error encountered. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Bar { + /// bar: i32, + /// baz: String, + /// } + /// + /// impl fmt::Debug for Bar { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_struct("Bar") + /// .field("bar", &self.bar) + /// .field("baz", &self.baz) + /// .finish() // You need to call it to "finish" the + /// // struct formatting. + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Bar { bar: 10, baz: "Hello World".to_string() }), + /// r#"Bar { bar: 10, baz: "Hello World" }"#, + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn finish(&mut self) -> fmt::Result { + if self.has_fields { + self.result = self.result.and_then(|_| { + if self.is_pretty() { self.fmt.write_str("}") } else { self.fmt.write_str(" }") } + }); + } + self.result + } + + fn is_pretty(&self) -> bool { + self.fmt.alternate() + } +} + +/// A struct to help with [`fmt::Debug`](Debug) implementations. +/// +/// This is useful when you wish to output a formatted tuple as a part of your +/// [`Debug::fmt`] implementation. +/// +/// This can be constructed by the [`Formatter::debug_tuple`] method. +/// +/// # Examples +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(i32, String); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { +/// fmt.debug_tuple("Foo") +/// .field(&self.0) +/// .field(&self.1) +/// .finish() +/// } +/// } +/// +/// assert_eq!( +/// format!("{:?}", Foo(10, "Hello World".to_string())), +/// r#"Foo(10, "Hello World")"#, +/// ); +/// ``` +#[must_use = "must eventually call `finish()` on Debug builders"] +#[allow(missing_debug_implementations)] +#[stable(feature = "debug_builders", since = "1.2.0")] +pub struct DebugTuple<'a, 'b: 'a> { + fmt: &'a mut fmt::Formatter<'b>, + result: fmt::Result, + fields: usize, + empty_name: bool, +} + +pub(super) fn debug_tuple_new<'a, 'b>( + fmt: &'a mut fmt::Formatter<'b>, + name: &str, +) -> DebugTuple<'a, 'b> { + let result = fmt.write_str(name); + DebugTuple { fmt, result, fields: 0, empty_name: name.is_empty() } +} + +impl<'a, 'b: 'a> DebugTuple<'a, 'b> { + /// Adds a new field to the generated tuple struct output. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32, String); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_tuple("Foo") + /// .field(&self.0) // We add the first field. + /// .field(&self.1) // We add the second field. + /// .finish() // We're good to go! + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(10, "Hello World".to_string())), + /// r#"Foo(10, "Hello World")"#, + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut Self { + self.field_with(|f| value.fmt(f)) + } + + /// Adds a new field to the generated tuple struct output. + /// + /// This method is equivalent to [`DebugTuple::field`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn field_with(&mut self, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.result = self.result.and_then(|_| { + if self.is_pretty() { + if self.fields == 0 { + self.fmt.write_str("(\n")?; + } + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); + value_fmt(&mut writer)?; + writer.write_str(",\n") + } else { + let prefix = if self.fields == 0 { "(" } else { ", " }; + self.fmt.write_str(prefix)?; + value_fmt(self.fmt) + } + }); + + self.fields += 1; + self + } + + /// Marks the tuple struct as non-exhaustive, indicating to the reader that there are some + /// other fields that are not shown in the debug representation. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32, String); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_tuple("Foo") + /// .field(&self.0) + /// .finish_non_exhaustive() // Show that some other field(s) exist. + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(10, "secret!".to_owned())), + /// "Foo(10, ..)", + /// ); + /// ``` + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] + pub fn finish_non_exhaustive(&mut self) -> fmt::Result { + self.result = self.result.and_then(|_| { + if self.fields > 0 { + if self.is_pretty() { + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + self.fmt.write_str(")") + } else { + self.fmt.write_str(", ..)") + } + } else { + self.fmt.write_str("(..)") + } + }); + self.result + } + + /// Finishes output and returns any error encountered. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32, String); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_tuple("Foo") + /// .field(&self.0) + /// .field(&self.1) + /// .finish() // You need to call it to "finish" the + /// // tuple formatting. + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(10, "Hello World".to_string())), + /// r#"Foo(10, "Hello World")"#, + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn finish(&mut self) -> fmt::Result { + if self.fields > 0 { + self.result = self.result.and_then(|_| { + if self.fields == 1 && self.empty_name && !self.is_pretty() { + self.fmt.write_str(",")?; + } + self.fmt.write_str(")") + }); + } + self.result + } + + fn is_pretty(&self) -> bool { + self.fmt.alternate() + } +} + +/// A helper used to print list-like items with no special formatting. +struct DebugInner<'a, 'b: 'a> { + fmt: &'a mut fmt::Formatter<'b>, + result: fmt::Result, + has_fields: bool, +} + +impl<'a, 'b: 'a> DebugInner<'a, 'b> { + fn entry_with(&mut self, entry_fmt: F) + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.result = self.result.and_then(|_| { + if self.is_pretty() { + if !self.has_fields { + self.fmt.write_str("\n")?; + } + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); + entry_fmt(&mut writer)?; + writer.write_str(",\n") + } else { + if self.has_fields { + self.fmt.write_str(", ")? + } + entry_fmt(self.fmt) + } + }); + + self.has_fields = true; + } + + fn is_pretty(&self) -> bool { + self.fmt.alternate() + } +} + +/// A struct to help with [`fmt::Debug`](Debug) implementations. +/// +/// This is useful when you wish to output a formatted set of items as a part +/// of your [`Debug::fmt`] implementation. +/// +/// This can be constructed by the [`Formatter::debug_set`] method. +/// +/// # Examples +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(Vec); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { +/// fmt.debug_set().entries(self.0.iter()).finish() +/// } +/// } +/// +/// assert_eq!( +/// format!("{:?}", Foo(vec![10, 11])), +/// "{10, 11}", +/// ); +/// ``` +#[must_use = "must eventually call `finish()` on Debug builders"] +#[allow(missing_debug_implementations)] +#[stable(feature = "debug_builders", since = "1.2.0")] +pub struct DebugSet<'a, 'b: 'a> { + inner: DebugInner<'a, 'b>, +} + +pub(super) fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> { + let result = fmt.write_str("{"); + DebugSet { inner: DebugInner { fmt, result, has_fields: false } } +} + +impl<'a, 'b: 'a> DebugSet<'a, 'b> { + /// Adds a new entry to the set output. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(Vec, Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_set() + /// .entry(&self.0) // Adds the first "entry". + /// .entry(&self.1) // Adds the second "entry". + /// .finish() + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![10, 11], vec![12, 13])), + /// "{[10, 11], [12, 13]}", + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self { + self.inner.entry_with(|f| entry.fmt(f)); + self + } + + /// Adds a new entry to the set output. + /// + /// This method is equivalent to [`DebugSet::entry`], but formats the + /// entry using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.inner.entry_with(entry_fmt); + self + } + + /// Adds the contents of an iterator of entries to the set output. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(Vec, Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_set() + /// .entries(self.0.iter()) // Adds the first "entry". + /// .entries(self.1.iter()) // Adds the second "entry". + /// .finish() + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![10, 11], vec![12, 13])), + /// "{10, 11, 12, 13}", + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn entries(&mut self, entries: I) -> &mut Self + where + D: fmt::Debug, + I: IntoIterator, + { + for entry in entries { + self.entry(&entry); + } + self + } + + /// Marks the set as non-exhaustive, indicating to the reader that there are some other + /// elements that are not shown in the debug representation. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// // Print at most two elements, abbreviate the rest + /// let mut f = fmt.debug_set(); + /// let mut f = f.entries(self.0.iter().take(2)); + /// if self.0.len() > 2 { + /// f.finish_non_exhaustive() + /// } else { + /// f.finish() + /// } + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![1, 2, 3, 4])), + /// "{1, 2, ..}", + /// ); + /// ``` + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] + pub fn finish_non_exhaustive(&mut self) -> fmt::Result { + self.inner.result = self.inner.result.and_then(|_| { + if self.inner.has_fields { + if self.inner.is_pretty() { + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.inner.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + self.inner.fmt.write_str("}") + } else { + self.inner.fmt.write_str(", ..}") + } + } else { + self.inner.fmt.write_str("..}") + } + }); + self.inner.result + } + + /// Finishes output and returns any error encountered. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_set() + /// .entries(self.0.iter()) + /// .finish() // Ends the set formatting. + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![10, 11])), + /// "{10, 11}", + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn finish(&mut self) -> fmt::Result { + self.inner.result = self.inner.result.and_then(|_| self.inner.fmt.write_str("}")); + self.inner.result + } +} + +/// A struct to help with [`fmt::Debug`](Debug) implementations. +/// +/// This is useful when you wish to output a formatted list of items as a part +/// of your [`Debug::fmt`] implementation. +/// +/// This can be constructed by the [`Formatter::debug_list`] method. +/// +/// # Examples +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(Vec); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { +/// fmt.debug_list().entries(self.0.iter()).finish() +/// } +/// } +/// +/// assert_eq!( +/// format!("{:?}", Foo(vec![10, 11])), +/// "[10, 11]", +/// ); +/// ``` +#[must_use = "must eventually call `finish()` on Debug builders"] +#[allow(missing_debug_implementations)] +#[stable(feature = "debug_builders", since = "1.2.0")] +pub struct DebugList<'a, 'b: 'a> { + inner: DebugInner<'a, 'b>, +} + +pub(super) fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> { + let result = fmt.write_str("["); + DebugList { inner: DebugInner { fmt, result, has_fields: false } } +} + +impl<'a, 'b: 'a> DebugList<'a, 'b> { + /// Adds a new entry to the list output. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(Vec, Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_list() + /// .entry(&self.0) // We add the first "entry". + /// .entry(&self.1) // We add the second "entry". + /// .finish() + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![10, 11], vec![12, 13])), + /// "[[10, 11], [12, 13]]", + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self { + self.inner.entry_with(|f| entry.fmt(f)); + self + } + + /// Adds a new entry to the list output. + /// + /// This method is equivalent to [`DebugList::entry`], but formats the + /// entry using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.inner.entry_with(entry_fmt); + self + } + + /// Adds the contents of an iterator of entries to the list output. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(Vec, Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_list() + /// .entries(self.0.iter()) + /// .entries(self.1.iter()) + /// .finish() + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![10, 11], vec![12, 13])), + /// "[10, 11, 12, 13]", + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn entries(&mut self, entries: I) -> &mut Self + where + D: fmt::Debug, + I: IntoIterator, + { + for entry in entries { + self.entry(&entry); + } + self + } + + /// Marks the list as non-exhaustive, indicating to the reader that there are some other + /// elements that are not shown in the debug representation. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// // Print at most two elements, abbreviate the rest + /// let mut f = fmt.debug_list(); + /// let mut f = f.entries(self.0.iter().take(2)); + /// if self.0.len() > 2 { + /// f.finish_non_exhaustive() + /// } else { + /// f.finish() + /// } + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![1, 2, 3, 4])), + /// "[1, 2, ..]", + /// ); + /// ``` + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] + pub fn finish_non_exhaustive(&mut self) -> fmt::Result { + self.inner.result.and_then(|_| { + if self.inner.has_fields { + if self.inner.is_pretty() { + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.inner.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + self.inner.fmt.write_str("]") + } else { + self.inner.fmt.write_str(", ..]") + } + } else { + self.inner.fmt.write_str("..]") + } + }) + } + + /// Finishes output and returns any error encountered. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_list() + /// .entries(self.0.iter()) + /// .finish() // Ends the list formatting. + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![10, 11])), + /// "[10, 11]", + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn finish(&mut self) -> fmt::Result { + self.inner.result = self.inner.result.and_then(|_| self.inner.fmt.write_str("]")); + self.inner.result + } +} + +/// A struct to help with [`fmt::Debug`](Debug) implementations. +/// +/// This is useful when you wish to output a formatted map as a part of your +/// [`Debug::fmt`] implementation. +/// +/// This can be constructed by the [`Formatter::debug_map`] method. +/// +/// # Examples +/// +/// ``` +/// use std::fmt; +/// +/// struct Foo(Vec<(String, i32)>); +/// +/// impl fmt::Debug for Foo { +/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { +/// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish() +/// } +/// } +/// +/// assert_eq!( +/// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), +/// r#"{"A": 10, "B": 11}"#, +/// ); +/// ``` +#[must_use = "must eventually call `finish()` on Debug builders"] +#[allow(missing_debug_implementations)] +#[stable(feature = "debug_builders", since = "1.2.0")] +pub struct DebugMap<'a, 'b: 'a> { + fmt: &'a mut fmt::Formatter<'b>, + result: fmt::Result, + has_fields: bool, + has_key: bool, + // The state of newlines is tracked between keys and values + state: PadAdapterState, +} + +pub(super) fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> { + let result = fmt.write_str("{"); + DebugMap { fmt, result, has_fields: false, has_key: false, state: Default::default() } +} + +impl<'a, 'b: 'a> DebugMap<'a, 'b> { + /// Adds a new entry to the map output. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(Vec<(String, i32)>); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_map() + /// .entry(&"whole", &self.0) // We add the "whole" entry. + /// .finish() + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), + /// r#"{"whole": [("A", 10), ("B", 11)]}"#, + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn entry(&mut self, key: &dyn fmt::Debug, value: &dyn fmt::Debug) -> &mut Self { + self.key(key).value(value) + } + + /// Adds the key part of a new entry to the map output. + /// + /// This method, together with `value`, is an alternative to `entry` that + /// can be used when the complete entry isn't known upfront. Prefer the `entry` + /// method when it's possible to use. + /// + /// # Panics + /// + /// `key` must be called before `value` and each call to `key` must be followed + /// by a corresponding call to `value`. Otherwise this method will panic. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(Vec<(String, i32)>); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_map() + /// .key(&"whole").value(&self.0) // We add the "whole" entry. + /// .finish() + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), + /// r#"{"whole": [("A", 10), ("B", 11)]}"#, + /// ); + /// ``` + #[stable(feature = "debug_map_key_value", since = "1.42.0")] + pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut Self { + self.key_with(|f| key.fmt(f)) + } + + /// Adds the key part of a new entry to the map output. + /// + /// This method is equivalent to [`DebugMap::key`], but formats the + /// key using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn key_with(&mut self, key_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.result = self.result.and_then(|_| { + assert!( + !self.has_key, + "attempted to begin a new map entry \ + without completing the previous one" + ); + + if self.is_pretty() { + if !self.has_fields { + self.fmt.write_str("\n")?; + } + let mut slot = None; + self.state = Default::default(); + let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state); + key_fmt(&mut writer)?; + writer.write_str(": ")?; + } else { + if self.has_fields { + self.fmt.write_str(", ")? + } + key_fmt(self.fmt)?; + self.fmt.write_str(": ")?; + } + + self.has_key = true; + Ok(()) + }); + + self + } + + /// Adds the value part of a new entry to the map output. + /// + /// This method, together with `key`, is an alternative to `entry` that + /// can be used when the complete entry isn't known upfront. Prefer the `entry` + /// method when it's possible to use. + /// + /// # Panics + /// + /// `key` must be called before `value` and each call to `key` must be followed + /// by a corresponding call to `value`. Otherwise this method will panic. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(Vec<(String, i32)>); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_map() + /// .key(&"whole").value(&self.0) // We add the "whole" entry. + /// .finish() + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), + /// r#"{"whole": [("A", 10), ("B", 11)]}"#, + /// ); + /// ``` + #[stable(feature = "debug_map_key_value", since = "1.42.0")] + pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut Self { + self.value_with(|f| value.fmt(f)) + } + + /// Adds the value part of a new entry to the map output. + /// + /// This method is equivalent to [`DebugMap::value`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn value_with(&mut self, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.result = self.result.and_then(|_| { + assert!(self.has_key, "attempted to format a map value before its key"); + + if self.is_pretty() { + let mut slot = None; + let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state); + value_fmt(&mut writer)?; + writer.write_str(",\n")?; + } else { + value_fmt(self.fmt)?; + } + + self.has_key = false; + Ok(()) + }); + + self.has_fields = true; + self + } + + /// Adds the contents of an iterator of entries to the map output. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(Vec<(String, i32)>); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_map() + /// // We map our vec so each entries' first field will become + /// // the "key". + /// .entries(self.0.iter().map(|&(ref k, ref v)| (k, v))) + /// .finish() + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), + /// r#"{"A": 10, "B": 11}"#, + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn entries(&mut self, entries: I) -> &mut Self + where + K: fmt::Debug, + V: fmt::Debug, + I: IntoIterator, + { + for (k, v) in entries { + self.entry(&k, &v); + } + self + } + + /// Marks the map as non-exhaustive, indicating to the reader that there are some other + /// entries that are not shown in the debug representation. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(Vec<(String, i32)>); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// // Print at most two elements, abbreviate the rest + /// let mut f = fmt.debug_map(); + /// let mut f = f.entries(self.0.iter().take(2).map(|&(ref k, ref v)| (k, v))); + /// if self.0.len() > 2 { + /// f.finish_non_exhaustive() + /// } else { + /// f.finish() + /// } + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![ + /// ("A".to_string(), 10), + /// ("B".to_string(), 11), + /// ("C".to_string(), 12), + /// ])), + /// r#"{"A": 10, "B": 11, ..}"#, + /// ); + /// ``` + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] + pub fn finish_non_exhaustive(&mut self) -> fmt::Result { + self.result = self.result.and_then(|_| { + assert!(!self.has_key, "attempted to finish a map with a partial entry"); + + if self.has_fields { + if self.is_pretty() { + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + self.fmt.write_str("}") + } else { + self.fmt.write_str(", ..}") + } + } else { + self.fmt.write_str("..}") + } + }); + self.result + } + + /// Finishes output and returns any error encountered. + /// + /// # Panics + /// + /// `key` must be called before `value` and each call to `key` must be followed + /// by a corresponding call to `value`. Otherwise this method will panic. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(Vec<(String, i32)>); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_map() + /// .entries(self.0.iter().map(|&(ref k, ref v)| (k, v))) + /// .finish() // Ends the map formatting. + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), + /// r#"{"A": 10, "B": 11}"#, + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn finish(&mut self) -> fmt::Result { + self.result = self.result.and_then(|_| { + assert!(!self.has_key, "attempted to finish a map with a partial entry"); + + self.fmt.write_str("}") + }); + self.result + } + + fn is_pretty(&self) -> bool { + self.fmt.alternate() + } +} + +/// Creates a type whose [`fmt::Debug`] and [`fmt::Display`] impls are provided with the function +/// `f`. +/// +/// # Examples +/// +/// ``` +/// #![feature(debug_closure_helpers)] +/// use std::fmt; +/// +/// let value = 'a'; +/// assert_eq!(format!("{}", value), "a"); +/// assert_eq!(format!("{:?}", value), "'a'"); +/// +/// let wrapped = fmt::from_fn(|f| write!(f, "{value:?}")); +/// assert_eq!(format!("{}", wrapped), "'a'"); +/// assert_eq!(format!("{:?}", wrapped), "'a'"); +/// ``` +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +pub fn from_fn) -> fmt::Result>(f: F) -> FromFn { + FromFn(f) +} + +/// Implements [`fmt::Debug`] and [`fmt::Display`] using a function. +/// +/// Created with [`from_fn`]. +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +pub struct FromFn(F) +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result; + +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +impl fmt::Debug for FromFn +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0)(f) + } +} + +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +impl fmt::Display for FromFn +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0)(f) + } +} diff --git a/CoqOfRust/core/fmt/float.rs b/CoqOfRust/core/fmt/float.rs new file mode 100644 index 000000000..04230b161 --- /dev/null +++ b/CoqOfRust/core/fmt/float.rs @@ -0,0 +1,248 @@ +use crate::fmt::{Debug, Display, Formatter, LowerExp, Result, UpperExp}; +use crate::mem::MaybeUninit; +use crate::num::{flt2dec, fmt as numfmt}; + +#[doc(hidden)] +trait GeneralFormat: PartialOrd { + /// Determines if a value should use exponential based on its magnitude, given the precondition + /// that it will not be rounded any further before it is displayed. + fn already_rounded_value_should_use_exponential(&self) -> bool; +} + +macro_rules! impl_general_format { + ($($t:ident)*) => { + $(impl GeneralFormat for $t { + fn already_rounded_value_should_use_exponential(&self) -> bool { + let abs = $t::abs(*self); + (abs != 0.0 && abs < 1e-4) || abs >= 1e+16 + } + })* + } +} + +impl_general_format! { f32 f64 } + +// Don't inline this so callers don't use the stack space this function +// requires unless they have to. +#[inline(never)] +fn float_to_decimal_common_exact( + fmt: &mut Formatter<'_>, + num: &T, + sign: flt2dec::Sign, + precision: usize, +) -> Result +where + T: flt2dec::DecodableFloat, +{ + let mut buf: [MaybeUninit; 1024] = [MaybeUninit::uninit(); 1024]; // enough for f32 and f64 + let mut parts: [MaybeUninit>; 4] = [MaybeUninit::uninit(); 4]; + let formatted = flt2dec::to_exact_fixed_str( + flt2dec::strategy::grisu::format_exact, + *num, + sign, + precision, + &mut buf, + &mut parts, + ); + // SAFETY: `to_exact_fixed_str` and `format_exact` produce only ASCII characters. + unsafe { fmt.pad_formatted_parts(&formatted) } +} + +// Don't inline this so callers that call both this and the above won't wind +// up using the combined stack space of both functions in some cases. +#[inline(never)] +fn float_to_decimal_common_shortest( + fmt: &mut Formatter<'_>, + num: &T, + sign: flt2dec::Sign, + precision: usize, +) -> Result +where + T: flt2dec::DecodableFloat, +{ + // enough for f32 and f64 + let mut buf: [MaybeUninit; flt2dec::MAX_SIG_DIGITS] = + [MaybeUninit::uninit(); flt2dec::MAX_SIG_DIGITS]; + let mut parts: [MaybeUninit>; 4] = [MaybeUninit::uninit(); 4]; + let formatted = flt2dec::to_shortest_str( + flt2dec::strategy::grisu::format_shortest, + *num, + sign, + precision, + &mut buf, + &mut parts, + ); + // SAFETY: `to_shortest_str` and `format_shortest` produce only ASCII characters. + unsafe { fmt.pad_formatted_parts(&formatted) } +} + +fn float_to_decimal_display(fmt: &mut Formatter<'_>, num: &T) -> Result +where + T: flt2dec::DecodableFloat, +{ + let force_sign = fmt.sign_plus(); + let sign = match force_sign { + false => flt2dec::Sign::Minus, + true => flt2dec::Sign::MinusPlus, + }; + + if let Some(precision) = fmt.precision { + float_to_decimal_common_exact(fmt, num, sign, precision) + } else { + let min_precision = 0; + float_to_decimal_common_shortest(fmt, num, sign, min_precision) + } +} + +// Don't inline this so callers don't use the stack space this function +// requires unless they have to. +#[inline(never)] +fn float_to_exponential_common_exact( + fmt: &mut Formatter<'_>, + num: &T, + sign: flt2dec::Sign, + precision: usize, + upper: bool, +) -> Result +where + T: flt2dec::DecodableFloat, +{ + let mut buf: [MaybeUninit; 1024] = [MaybeUninit::uninit(); 1024]; // enough for f32 and f64 + let mut parts: [MaybeUninit>; 6] = [MaybeUninit::uninit(); 6]; + let formatted = flt2dec::to_exact_exp_str( + flt2dec::strategy::grisu::format_exact, + *num, + sign, + precision, + upper, + &mut buf, + &mut parts, + ); + // SAFETY: `to_exact_exp_str` and `format_exact` produce only ASCII characters. + unsafe { fmt.pad_formatted_parts(&formatted) } +} + +// Don't inline this so callers that call both this and the above won't wind +// up using the combined stack space of both functions in some cases. +#[inline(never)] +fn float_to_exponential_common_shortest( + fmt: &mut Formatter<'_>, + num: &T, + sign: flt2dec::Sign, + upper: bool, +) -> Result +where + T: flt2dec::DecodableFloat, +{ + // enough for f32 and f64 + let mut buf: [MaybeUninit; flt2dec::MAX_SIG_DIGITS] = + [MaybeUninit::uninit(); flt2dec::MAX_SIG_DIGITS]; + let mut parts: [MaybeUninit>; 6] = [MaybeUninit::uninit(); 6]; + let formatted = flt2dec::to_shortest_exp_str( + flt2dec::strategy::grisu::format_shortest, + *num, + sign, + (0, 0), + upper, + &mut buf, + &mut parts, + ); + // SAFETY: `to_shortest_exp_str` and `format_shortest` produce only ASCII characters. + unsafe { fmt.pad_formatted_parts(&formatted) } +} + +// Common code of floating point LowerExp and UpperExp. +fn float_to_exponential_common(fmt: &mut Formatter<'_>, num: &T, upper: bool) -> Result +where + T: flt2dec::DecodableFloat, +{ + let force_sign = fmt.sign_plus(); + let sign = match force_sign { + false => flt2dec::Sign::Minus, + true => flt2dec::Sign::MinusPlus, + }; + + if let Some(precision) = fmt.precision { + // 1 integral digit + `precision` fractional digits = `precision + 1` total digits + float_to_exponential_common_exact(fmt, num, sign, precision + 1, upper) + } else { + float_to_exponential_common_shortest(fmt, num, sign, upper) + } +} + +fn float_to_general_debug(fmt: &mut Formatter<'_>, num: &T) -> Result +where + T: flt2dec::DecodableFloat + GeneralFormat, +{ + let force_sign = fmt.sign_plus(); + let sign = match force_sign { + false => flt2dec::Sign::Minus, + true => flt2dec::Sign::MinusPlus, + }; + + if let Some(precision) = fmt.precision { + // this behavior of {:.PREC?} predates exponential formatting for {:?} + float_to_decimal_common_exact(fmt, num, sign, precision) + } else { + // since there is no precision, there will be no rounding + if num.already_rounded_value_should_use_exponential() { + let upper = false; + float_to_exponential_common_shortest(fmt, num, sign, upper) + } else { + let min_precision = 1; + float_to_decimal_common_shortest(fmt, num, sign, min_precision) + } + } +} + +macro_rules! floating { + ($($ty:ident)*) => { + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl Debug for $ty { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { + float_to_general_debug(fmt, self) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Display for $ty { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { + float_to_decimal_display(fmt, self) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl LowerExp for $ty { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { + float_to_exponential_common(fmt, self, false) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl UpperExp for $ty { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { + float_to_exponential_common(fmt, self, true) + } + } + )* + }; +} + +floating! { f32 f64 } + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for f16 { + #[inline] + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{:#06x}", self.to_bits()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for f128 { + #[inline] + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{:#034x}", self.to_bits()) + } +} diff --git a/CoqOfRust/core/fmt/mod.rs b/CoqOfRust/core/fmt/mod.rs new file mode 100644 index 000000000..7fc9dd21f --- /dev/null +++ b/CoqOfRust/core/fmt/mod.rs @@ -0,0 +1,2707 @@ +//! Utilities for formatting and printing strings. + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::cell::{Cell, Ref, RefCell, RefMut, SyncUnsafeCell, UnsafeCell}; +use crate::char::EscapeDebugExtArgs; +use crate::marker::PhantomData; +use crate::num::fmt as numfmt; +use crate::ops::Deref; +use crate::{iter, mem, result, str}; + +mod builders; +#[cfg(not(no_fp_fmt_parse))] +mod float; +#[cfg(no_fp_fmt_parse)] +mod nofloat; +mod num; +mod rt; + +#[stable(feature = "fmt_flags_align", since = "1.28.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Alignment")] +/// Possible alignments returned by `Formatter::align` +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Alignment { + #[stable(feature = "fmt_flags_align", since = "1.28.0")] + /// Indication that contents should be left-aligned. + Left, + #[stable(feature = "fmt_flags_align", since = "1.28.0")] + /// Indication that contents should be right-aligned. + Right, + #[stable(feature = "fmt_flags_align", since = "1.28.0")] + /// Indication that contents should be center-aligned. + Center, +} + +#[stable(feature = "debug_builders", since = "1.2.0")] +pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +pub use self::builders::{FromFn, from_fn}; + +/// The type returned by formatter methods. +/// +/// # Examples +/// +/// ``` +/// use std::fmt; +/// +/// #[derive(Debug)] +/// struct Triangle { +/// a: f32, +/// b: f32, +/// c: f32 +/// } +/// +/// impl fmt::Display for Triangle { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// write!(f, "({}, {}, {})", self.a, self.b, self.c) +/// } +/// } +/// +/// let pythagorean_triple = Triangle { a: 3.0, b: 4.0, c: 5.0 }; +/// +/// assert_eq!(format!("{pythagorean_triple}"), "(3, 4, 5)"); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub type Result = result::Result<(), Error>; + +/// The error type which is returned from formatting a message into a stream. +/// +/// This type does not support transmission of an error other than that an error +/// occurred. This is because, despite the existence of this error, +/// string formatting is considered an infallible operation. +/// `fmt()` implementors should not return this `Error` unless they received it from their +/// [`Formatter`]. The only time your code should create a new instance of this +/// error is when implementing `fmt::Write`, in order to cancel the formatting operation when +/// writing to the underlying stream fails. +/// +/// Any extra information must be arranged to be transmitted through some other means, +/// such as storing it in a field to be consulted after the formatting operation has been +/// cancelled. (For example, this is how [`std::io::Write::write_fmt()`] propagates IO errors +/// during writing.) +/// +/// This type, `fmt::Error`, should not be +/// confused with [`std::io::Error`] or [`std::error::Error`], which you may also +/// have in scope. +/// +/// [`std::io::Error`]: ../../std/io/struct.Error.html +/// [`std::io::Write::write_fmt()`]: ../../std/io/trait.Write.html#method.write_fmt +/// [`std::error::Error`]: ../../std/error/trait.Error.html +/// +/// # Examples +/// +/// ```rust +/// use std::fmt::{self, write}; +/// +/// let mut output = String::new(); +/// if let Err(fmt::Error) = write(&mut output, format_args!("Hello {}!", "world")) { +/// panic!("An error occurred"); +/// } +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Error; + +/// A trait for writing or formatting into Unicode-accepting buffers or streams. +/// +/// This trait only accepts UTF-8–encoded data and is not [flushable]. If you only +/// want to accept Unicode and you don't need flushing, you should implement this trait; +/// otherwise you should implement [`std::io::Write`]. +/// +/// [`std::io::Write`]: ../../std/io/trait.Write.html +/// [flushable]: ../../std/io/trait.Write.html#tymethod.flush +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Write { + /// Writes a string slice into this writer, returning whether the write + /// succeeded. + /// + /// This method can only succeed if the entire string slice was successfully + /// written, and this method will not return until all data has been + /// written or an error occurs. + /// + /// # Errors + /// + /// This function will return an instance of [`std::fmt::Error`][Error] on error. + /// + /// The purpose of that error is to abort the formatting operation when the underlying + /// destination encounters some error preventing it from accepting more text; + /// in particular, it does not communicate any information about *what* error occurred. + /// It should generally be propagated rather than handled, at least when implementing + /// formatting traits. + /// + /// # Examples + /// + /// ``` + /// use std::fmt::{Error, Write}; + /// + /// fn writer(f: &mut W, s: &str) -> Result<(), Error> { + /// f.write_str(s) + /// } + /// + /// let mut buf = String::new(); + /// writer(&mut buf, "hola").unwrap(); + /// assert_eq!(&buf, "hola"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn write_str(&mut self, s: &str) -> Result; + + /// Writes a [`char`] into this writer, returning whether the write succeeded. + /// + /// A single [`char`] may be encoded as more than one byte. + /// This method can only succeed if the entire byte sequence was successfully + /// written, and this method will not return until all data has been + /// written or an error occurs. + /// + /// # Errors + /// + /// This function will return an instance of [`Error`] on error. + /// + /// # Examples + /// + /// ``` + /// use std::fmt::{Error, Write}; + /// + /// fn writer(f: &mut W, c: char) -> Result<(), Error> { + /// f.write_char(c) + /// } + /// + /// let mut buf = String::new(); + /// writer(&mut buf, 'a').unwrap(); + /// writer(&mut buf, 'b').unwrap(); + /// assert_eq!(&buf, "ab"); + /// ``` + #[stable(feature = "fmt_write_char", since = "1.1.0")] + fn write_char(&mut self, c: char) -> Result { + self.write_str(c.encode_utf8(&mut [0; 4])) + } + + /// Glue for usage of the [`write!`] macro with implementors of this trait. + /// + /// This method should generally not be invoked manually, but rather through + /// the [`write!`] macro itself. + /// + /// # Errors + /// + /// This function will return an instance of [`Error`] on error. Please see + /// [write_str](Write::write_str) for details. + /// + /// # Examples + /// + /// ``` + /// use std::fmt::{Error, Write}; + /// + /// fn writer(f: &mut W, s: &str) -> Result<(), Error> { + /// f.write_fmt(format_args!("{s}")) + /// } + /// + /// let mut buf = String::new(); + /// writer(&mut buf, "world").unwrap(); + /// assert_eq!(&buf, "world"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn write_fmt(&mut self, args: Arguments<'_>) -> Result { + // We use a specialization for `Sized` types to avoid an indirection + // through `&mut self` + trait SpecWriteFmt { + fn spec_write_fmt(self, args: Arguments<'_>) -> Result; + } + + impl SpecWriteFmt for &mut W { + #[inline] + default fn spec_write_fmt(mut self, args: Arguments<'_>) -> Result { + if let Some(s) = args.as_statically_known_str() { + self.write_str(s) + } else { + write(&mut self, args) + } + } + } + + impl SpecWriteFmt for &mut W { + #[inline] + fn spec_write_fmt(self, args: Arguments<'_>) -> Result { + if let Some(s) = args.as_statically_known_str() { + self.write_str(s) + } else { + write(self, args) + } + } + } + + self.spec_write_fmt(args) + } +} + +#[stable(feature = "fmt_write_blanket_impl", since = "1.4.0")] +impl Write for &mut W { + fn write_str(&mut self, s: &str) -> Result { + (**self).write_str(s) + } + + fn write_char(&mut self, c: char) -> Result { + (**self).write_char(c) + } + + fn write_fmt(&mut self, args: Arguments<'_>) -> Result { + (**self).write_fmt(args) + } +} + +/// Configuration for formatting. +/// +/// A `Formatter` represents various options related to formatting. Users do not +/// construct `Formatter`s directly; a mutable reference to one is passed to +/// the `fmt` method of all formatting traits, like [`Debug`] and [`Display`]. +/// +/// To interact with a `Formatter`, you'll call various methods to change the +/// various options related to formatting. For examples, please see the +/// documentation of the methods defined on `Formatter` below. +#[allow(missing_debug_implementations)] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Formatter"] +pub struct Formatter<'a> { + flags: u32, + fill: char, + align: rt::Alignment, + width: Option, + precision: Option, + + buf: &'a mut (dyn Write + 'a), +} + +impl<'a> Formatter<'a> { + /// Creates a new formatter with default settings. + /// + /// This can be used as a micro-optimization in cases where a full `Arguments` + /// structure (as created by `format_args!`) is not necessary; `Arguments` + /// is a little more expensive to use in simple formatting scenarios. + /// + /// Currently not intended for use outside of the standard library. + #[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")] + #[doc(hidden)] + pub fn new(buf: &'a mut (dyn Write + 'a)) -> Formatter<'a> { + Formatter { + flags: 0, + fill: ' ', + align: rt::Alignment::Unknown, + width: None, + precision: None, + buf, + } + } +} + +/// This structure represents a safely precompiled version of a format string +/// and its arguments. This cannot be generated at runtime because it cannot +/// safely be done, so no constructors are given and the fields are private +/// to prevent modification. +/// +/// The [`format_args!`] macro will safely create an instance of this structure. +/// The macro validates the format string at compile-time so usage of the +/// [`write()`] and [`format()`] functions can be safely performed. +/// +/// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug` +/// and `Display` contexts as seen below. The example also shows that `Debug` +/// and `Display` format to the same thing: the interpolated format string +/// in `format_args!`. +/// +/// ```rust +/// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); +/// let display = format!("{}", format_args!("{} foo {:?}", 1, 2)); +/// assert_eq!("1 foo 2", display); +/// assert_eq!(display, debug); +/// ``` +/// +/// [`format()`]: ../../std/fmt/fn.format.html +#[lang = "format_arguments"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Copy, Clone)] +pub struct Arguments<'a> { + // Format string pieces to print. + pieces: &'a [&'static str], + + // Placeholder specs, or `None` if all specs are default (as in "{}{}"). + fmt: Option<&'a [rt::Placeholder]>, + + // Dynamic arguments for interpolation, to be interleaved with string + // pieces. (Every argument is preceded by a string piece.) + args: &'a [rt::Argument<'a>], +} + +/// Used by the format_args!() macro to create a fmt::Arguments object. +#[doc(hidden)] +#[unstable(feature = "fmt_internals", issue = "none")] +impl<'a> Arguments<'a> { + #[inline] + pub const fn new_const(pieces: &'a [&'static str; N]) -> Self { + const { assert!(N <= 1) }; + Arguments { pieces, fmt: None, args: &[] } + } + + /// When using the format_args!() macro, this function is used to generate the + /// Arguments structure. + #[inline] + pub fn new_v1( + pieces: &'a [&'static str; P], + args: &'a [rt::Argument<'a>; A], + ) -> Arguments<'a> { + const { assert!(P >= A && P <= A + 1, "invalid args") } + Arguments { pieces, fmt: None, args } + } + + /// Specifies nonstandard formatting parameters. + /// + /// An `rt::UnsafeArg` is required because the following invariants must be held + /// in order for this function to be safe: + /// 1. The `pieces` slice must be at least as long as `fmt`. + /// 2. Every `rt::Placeholder::position` value within `fmt` must be a valid index of `args`. + /// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`. + #[inline] + pub fn new_v1_formatted( + pieces: &'a [&'static str], + args: &'a [rt::Argument<'a>], + fmt: &'a [rt::Placeholder], + _unsafe_arg: rt::UnsafeArg, + ) -> Arguments<'a> { + Arguments { pieces, fmt: Some(fmt), args } + } + + /// Estimates the length of the formatted text. + /// + /// This is intended to be used for setting initial `String` capacity + /// when using `format!`. Note: this is neither the lower nor upper bound. + #[inline] + pub fn estimated_capacity(&self) -> usize { + let pieces_length: usize = self.pieces.iter().map(|x| x.len()).sum(); + + if self.args.is_empty() { + pieces_length + } else if !self.pieces.is_empty() && self.pieces[0].is_empty() && pieces_length < 16 { + // If the format string starts with an argument, + // don't preallocate anything, unless length + // of pieces is significant. + 0 + } else { + // There are some arguments, so any additional push + // will reallocate the string. To avoid that, + // we're "pre-doubling" the capacity here. + pieces_length.checked_mul(2).unwrap_or(0) + } + } +} + +impl<'a> Arguments<'a> { + /// Gets the formatted string, if it has no arguments to be formatted at runtime. + /// + /// This can be used to avoid allocations in some cases. + /// + /// # Guarantees + /// + /// For `format_args!("just a literal")`, this function is guaranteed to + /// return `Some("just a literal")`. + /// + /// For most cases with placeholders, this function will return `None`. + /// + /// However, the compiler may perform optimizations that can cause this + /// function to return `Some(_)` even if the format string contains + /// placeholders. For example, `format_args!("Hello, {}!", "world")` may be + /// optimized to `format_args!("Hello, world!")`, such that `as_str()` + /// returns `Some("Hello, world!")`. + /// + /// The behavior for anything but the trivial case (without placeholders) + /// is not guaranteed, and should not be relied upon for anything other + /// than optimization. + /// + /// # Examples + /// + /// ```rust + /// use std::fmt::Arguments; + /// + /// fn write_str(_: &str) { /* ... */ } + /// + /// fn write_fmt(args: &Arguments<'_>) { + /// if let Some(s) = args.as_str() { + /// write_str(s) + /// } else { + /// write_str(&args.to_string()); + /// } + /// } + /// ``` + /// + /// ```rust + /// assert_eq!(format_args!("hello").as_str(), Some("hello")); + /// assert_eq!(format_args!("").as_str(), Some("")); + /// assert_eq!(format_args!("{:?}", std::env::current_dir()).as_str(), None); + /// ``` + #[stable(feature = "fmt_as_str", since = "1.52.0")] + #[rustc_const_stable(feature = "const_arguments_as_str", since = "1.84.0")] + #[must_use] + #[inline] + pub const fn as_str(&self) -> Option<&'static str> { + match (self.pieces, self.args) { + ([], []) => Some(""), + ([s], []) => Some(s), + _ => None, + } + } + + /// Same as [`Arguments::as_str`], but will only return `Some(s)` if it can be determined at compile time. + #[must_use] + #[inline] + fn as_statically_known_str(&self) -> Option<&'static str> { + let s = self.as_str(); + if core::intrinsics::is_val_statically_known(s.is_some()) { s } else { None } + } +} + +// Manually implementing these results in better error messages. +#[stable(feature = "rust1", since = "1.0.0")] +impl !Send for Arguments<'_> {} +#[stable(feature = "rust1", since = "1.0.0")] +impl !Sync for Arguments<'_> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for Arguments<'_> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { + Display::fmt(self, fmt) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Display for Arguments<'_> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { + write(fmt.buf, *self) + } +} + +/// `?` formatting. +/// +/// `Debug` should format the output in a programmer-facing, debugging context. +/// +/// Generally speaking, you should just `derive` a `Debug` implementation. +/// +/// When used with the alternate format specifier `#?`, the output is pretty-printed. +/// +/// For more information on formatters, see [the module-level documentation][module]. +/// +/// [module]: ../../std/fmt/index.html +/// +/// This trait can be used with `#[derive]` if all fields implement `Debug`. When +/// `derive`d for structs, it will use the name of the `struct`, then `{`, then a +/// comma-separated list of each field's name and `Debug` value, then `}`. For +/// `enum`s, it will use the name of the variant and, if applicable, `(`, then the +/// `Debug` values of the fields, then `)`. +/// +/// # Stability +/// +/// Derived `Debug` formats are not stable, and so may change with future Rust +/// versions. Additionally, `Debug` implementations of types provided by the +/// standard library (`std`, `core`, `alloc`, etc.) are not stable, and +/// may also change with future Rust versions. +/// +/// # Examples +/// +/// Deriving an implementation: +/// +/// ``` +/// #[derive(Debug)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// let origin = Point { x: 0, y: 0 }; +/// +/// assert_eq!( +/// format!("The origin is: {origin:?}"), +/// "The origin is: Point { x: 0, y: 0 }", +/// ); +/// ``` +/// +/// Manually implementing: +/// +/// ``` +/// use std::fmt; +/// +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl fmt::Debug for Point { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// f.debug_struct("Point") +/// .field("x", &self.x) +/// .field("y", &self.y) +/// .finish() +/// } +/// } +/// +/// let origin = Point { x: 0, y: 0 }; +/// +/// assert_eq!( +/// format!("The origin is: {origin:?}"), +/// "The origin is: Point { x: 0, y: 0 }", +/// ); +/// ``` +/// +/// There are a number of helper methods on the [`Formatter`] struct to help you with manual +/// implementations, such as [`debug_struct`]. +/// +/// [`debug_struct`]: Formatter::debug_struct +/// +/// Types that do not wish to use the standard suite of debug representations +/// provided by the `Formatter` trait (`debug_struct`, `debug_tuple`, +/// `debug_list`, `debug_set`, `debug_map`) can do something totally custom by +/// manually writing an arbitrary representation to the `Formatter`. +/// +/// ``` +/// # use std::fmt; +/// # struct Point { +/// # x: i32, +/// # y: i32, +/// # } +/// # +/// impl fmt::Debug for Point { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// write!(f, "Point [{} {}]", self.x, self.y) +/// } +/// } +/// ``` +/// +/// `Debug` implementations using either `derive` or the debug builder API +/// on [`Formatter`] support pretty-printing using the alternate flag: `{:#?}`. +/// +/// Pretty-printing with `#?`: +/// +/// ``` +/// #[derive(Debug)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// let origin = Point { x: 0, y: 0 }; +/// +/// let expected = "The origin is: Point { +/// x: 0, +/// y: 0, +/// }"; +/// assert_eq!(format!("The origin is: {origin:#?}"), expected); +/// ``` + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + on( + crate_local, + label = "`{Self}` cannot be formatted using `{{:?}}`", + note = "add `#[derive(Debug)]` to `{Self}` or manually `impl {Debug} for {Self}`" + ), + message = "`{Self}` doesn't implement `{Debug}`", + label = "`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`" +)] +#[doc(alias = "{:?}")] +#[rustc_diagnostic_item = "Debug"] +#[rustc_trivial_field_reads] +pub trait Debug { + #[doc = include_str!("fmt_trait_method_doc.md")] + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Position { + /// longitude: f32, + /// latitude: f32, + /// } + /// + /// impl fmt::Debug for Position { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// f.debug_tuple("") + /// .field(&self.longitude) + /// .field(&self.latitude) + /// .finish() + /// } + /// } + /// + /// let position = Position { longitude: 1.987, latitude: 2.983 }; + /// assert_eq!(format!("{position:?}"), "(1.987, 2.983)"); + /// + /// assert_eq!(format!("{position:#?}"), "( + /// 1.987, + /// 2.983, + /// )"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn fmt(&self, f: &mut Formatter<'_>) -> Result; +} + +// Separate module to reexport the macro `Debug` from prelude without the trait `Debug`. +pub(crate) mod macros { + /// Derive macro generating an impl of the trait `Debug`. + #[rustc_builtin_macro] + #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] + #[allow_internal_unstable(core_intrinsics, fmt_helpers_for_derive)] + pub macro Debug($item:item) { + /* compiler built-in */ + } +} +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(inline)] +pub use macros::Debug; + +/// Format trait for an empty format, `{}`. +/// +/// Implementing this trait for a type will automatically implement the +/// [`ToString`][tostring] trait for the type, allowing the usage +/// of the [`.to_string()`][tostring_function] method. Prefer implementing +/// the `Display` trait for a type, rather than [`ToString`][tostring]. +/// +/// `Display` is similar to [`Debug`], but `Display` is for user-facing +/// output, and so cannot be derived. +/// +/// For more information on formatters, see [the module-level documentation][module]. +/// +/// [module]: ../../std/fmt/index.html +/// [tostring]: ../../std/string/trait.ToString.html +/// [tostring_function]: ../../std/string/trait.ToString.html#tymethod.to_string +/// +/// # Internationalization +/// +/// Because a type can only have one `Display` implementation, it is often preferable +/// to only implement `Display` when there is a single most "obvious" way that +/// values can be formatted as text. This could mean formatting according to the +/// "invariant" culture and "undefined" locale, or it could mean that the type +/// display is designed for a specific culture/locale, such as developer logs. +/// +/// If not all values have a justifiably canonical textual format or if you want +/// to support alternative formats not covered by the standard set of possible +/// [formatting traits], the most flexible approach is display adapters: methods +/// like [`str::escape_default`] or [`Path::display`] which create a wrapper +/// implementing `Display` to output the specific display format. +/// +/// [formatting traits]: ../../std/fmt/index.html#formatting-traits +/// [`Path::display`]: ../../std/path/struct.Path.html#method.display +/// +/// # Examples +/// +/// Implementing `Display` on a type: +/// +/// ``` +/// use std::fmt; +/// +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl fmt::Display for Point { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// write!(f, "({}, {})", self.x, self.y) +/// } +/// } +/// +/// let origin = Point { x: 0, y: 0 }; +/// +/// assert_eq!(format!("The origin is: {origin}"), "The origin is: (0, 0)"); +/// ``` +#[rustc_on_unimplemented( + on( + any(_Self = "std::path::Path", _Self = "std::path::PathBuf"), + label = "`{Self}` cannot be formatted with the default formatter; call `.display()` on it", + note = "call `.display()` or `.to_string_lossy()` to safely print paths, \ + as they may contain non-Unicode data" + ), + message = "`{Self}` doesn't implement `{Display}`", + label = "`{Self}` cannot be formatted with the default formatter", + note = "in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead" +)] +#[doc(alias = "{}")] +#[rustc_diagnostic_item = "Display"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Display { + #[doc = include_str!("fmt_trait_method_doc.md")] + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Position { + /// longitude: f32, + /// latitude: f32, + /// } + /// + /// impl fmt::Display for Position { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "({}, {})", self.longitude, self.latitude) + /// } + /// } + /// + /// assert_eq!( + /// "(1.987, 2.983)", + /// format!("{}", Position { longitude: 1.987, latitude: 2.983, }), + /// ); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn fmt(&self, f: &mut Formatter<'_>) -> Result; +} + +/// `o` formatting. +/// +/// The `Octal` trait should format its output as a number in base-8. +/// +/// For primitive signed integers (`i8` to `i128`, and `isize`), +/// negative values are formatted as the two’s complement representation. +/// +/// The alternate flag, `#`, adds a `0o` in front of the output. +/// +/// For more information on formatters, see [the module-level documentation][module]. +/// +/// [module]: ../../std/fmt/index.html +/// +/// # Examples +/// +/// Basic usage with `i32`: +/// +/// ``` +/// let x = 42; // 42 is '52' in octal +/// +/// assert_eq!(format!("{x:o}"), "52"); +/// assert_eq!(format!("{x:#o}"), "0o52"); +/// +/// assert_eq!(format!("{:o}", -16), "37777777760"); +/// ``` +/// +/// Implementing `Octal` on a type: +/// +/// ``` +/// use std::fmt; +/// +/// struct Length(i32); +/// +/// impl fmt::Octal for Length { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// let val = self.0; +/// +/// fmt::Octal::fmt(&val, f) // delegate to i32's implementation +/// } +/// } +/// +/// let l = Length(9); +/// +/// assert_eq!(format!("l as octal is: {l:o}"), "l as octal is: 11"); +/// +/// assert_eq!(format!("l as octal is: {l:#06o}"), "l as octal is: 0o0011"); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Octal { + #[doc = include_str!("fmt_trait_method_doc.md")] + #[stable(feature = "rust1", since = "1.0.0")] + fn fmt(&self, f: &mut Formatter<'_>) -> Result; +} + +/// `b` formatting. +/// +/// The `Binary` trait should format its output as a number in binary. +/// +/// For primitive signed integers ([`i8`] to [`i128`], and [`isize`]), +/// negative values are formatted as the two’s complement representation. +/// +/// The alternate flag, `#`, adds a `0b` in front of the output. +/// +/// For more information on formatters, see [the module-level documentation][module]. +/// +/// [module]: ../../std/fmt/index.html +/// +/// # Examples +/// +/// Basic usage with [`i32`]: +/// +/// ``` +/// let x = 42; // 42 is '101010' in binary +/// +/// assert_eq!(format!("{x:b}"), "101010"); +/// assert_eq!(format!("{x:#b}"), "0b101010"); +/// +/// assert_eq!(format!("{:b}", -16), "11111111111111111111111111110000"); +/// ``` +/// +/// Implementing `Binary` on a type: +/// +/// ``` +/// use std::fmt; +/// +/// struct Length(i32); +/// +/// impl fmt::Binary for Length { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// let val = self.0; +/// +/// fmt::Binary::fmt(&val, f) // delegate to i32's implementation +/// } +/// } +/// +/// let l = Length(107); +/// +/// assert_eq!(format!("l as binary is: {l:b}"), "l as binary is: 1101011"); +/// +/// assert_eq!( +/// // Note that the `0b` prefix added by `#` is included in the total width, so we +/// // need to add two to correctly display all 32 bits. +/// format!("l as binary is: {l:#034b}"), +/// "l as binary is: 0b00000000000000000000000001101011" +/// ); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Binary { + #[doc = include_str!("fmt_trait_method_doc.md")] + #[stable(feature = "rust1", since = "1.0.0")] + fn fmt(&self, f: &mut Formatter<'_>) -> Result; +} + +/// `x` formatting. +/// +/// The `LowerHex` trait should format its output as a number in hexadecimal, with `a` through `f` +/// in lower case. +/// +/// For primitive signed integers (`i8` to `i128`, and `isize`), +/// negative values are formatted as the two’s complement representation. +/// +/// The alternate flag, `#`, adds a `0x` in front of the output. +/// +/// For more information on formatters, see [the module-level documentation][module]. +/// +/// [module]: ../../std/fmt/index.html +/// +/// # Examples +/// +/// Basic usage with `i32`: +/// +/// ``` +/// let y = 42; // 42 is '2a' in hex +/// +/// assert_eq!(format!("{y:x}"), "2a"); +/// assert_eq!(format!("{y:#x}"), "0x2a"); +/// +/// assert_eq!(format!("{:x}", -16), "fffffff0"); +/// ``` +/// +/// Implementing `LowerHex` on a type: +/// +/// ``` +/// use std::fmt; +/// +/// struct Length(i32); +/// +/// impl fmt::LowerHex for Length { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// let val = self.0; +/// +/// fmt::LowerHex::fmt(&val, f) // delegate to i32's implementation +/// } +/// } +/// +/// let l = Length(9); +/// +/// assert_eq!(format!("l as hex is: {l:x}"), "l as hex is: 9"); +/// +/// assert_eq!(format!("l as hex is: {l:#010x}"), "l as hex is: 0x00000009"); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub trait LowerHex { + #[doc = include_str!("fmt_trait_method_doc.md")] + #[stable(feature = "rust1", since = "1.0.0")] + fn fmt(&self, f: &mut Formatter<'_>) -> Result; +} + +/// `X` formatting. +/// +/// The `UpperHex` trait should format its output as a number in hexadecimal, with `A` through `F` +/// in upper case. +/// +/// For primitive signed integers (`i8` to `i128`, and `isize`), +/// negative values are formatted as the two’s complement representation. +/// +/// The alternate flag, `#`, adds a `0x` in front of the output. +/// +/// For more information on formatters, see [the module-level documentation][module]. +/// +/// [module]: ../../std/fmt/index.html +/// +/// # Examples +/// +/// Basic usage with `i32`: +/// +/// ``` +/// let y = 42; // 42 is '2A' in hex +/// +/// assert_eq!(format!("{y:X}"), "2A"); +/// assert_eq!(format!("{y:#X}"), "0x2A"); +/// +/// assert_eq!(format!("{:X}", -16), "FFFFFFF0"); +/// ``` +/// +/// Implementing `UpperHex` on a type: +/// +/// ``` +/// use std::fmt; +/// +/// struct Length(i32); +/// +/// impl fmt::UpperHex for Length { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// let val = self.0; +/// +/// fmt::UpperHex::fmt(&val, f) // delegate to i32's implementation +/// } +/// } +/// +/// let l = Length(i32::MAX); +/// +/// assert_eq!(format!("l as hex is: {l:X}"), "l as hex is: 7FFFFFFF"); +/// +/// assert_eq!(format!("l as hex is: {l:#010X}"), "l as hex is: 0x7FFFFFFF"); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub trait UpperHex { + #[doc = include_str!("fmt_trait_method_doc.md")] + #[stable(feature = "rust1", since = "1.0.0")] + fn fmt(&self, f: &mut Formatter<'_>) -> Result; +} + +/// `p` formatting. +/// +/// The `Pointer` trait should format its output as a memory location. This is commonly presented +/// as hexadecimal. For more information on formatters, see [the module-level documentation][module]. +/// +/// Printing of pointers is not a reliable way to discover how Rust programs are implemented. +/// The act of reading an address changes the program itself, and may change how the data is represented +/// in memory, and may affect which optimizations are applied to the code. +/// +/// The printed pointer values are not guaranteed to be stable nor unique identifiers of objects. +/// Rust allows moving values to different memory locations, and may reuse the same memory locations +/// for different purposes. +/// +/// There is no guarantee that the printed value can be converted back to a pointer. +/// +/// [module]: ../../std/fmt/index.html +/// +/// # Examples +/// +/// Basic usage with `&i32`: +/// +/// ``` +/// let x = &42; +/// +/// let address = format!("{x:p}"); // this produces something like '0x7f06092ac6d0' +/// ``` +/// +/// Implementing `Pointer` on a type: +/// +/// ``` +/// use std::fmt; +/// +/// struct Length(i32); +/// +/// impl fmt::Pointer for Length { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// // use `as` to convert to a `*const T`, which implements Pointer, which we can use +/// +/// let ptr = self as *const Self; +/// fmt::Pointer::fmt(&ptr, f) +/// } +/// } +/// +/// let l = Length(42); +/// +/// println!("l is in memory here: {l:p}"); +/// +/// let l_ptr = format!("{l:018p}"); +/// assert_eq!(l_ptr.len(), 18); +/// assert_eq!(&l_ptr[..2], "0x"); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Pointer"] +pub trait Pointer { + #[doc = include_str!("fmt_trait_method_doc.md")] + #[stable(feature = "rust1", since = "1.0.0")] + fn fmt(&self, f: &mut Formatter<'_>) -> Result; +} + +/// `e` formatting. +/// +/// The `LowerExp` trait should format its output in scientific notation with a lower-case `e`. +/// +/// For more information on formatters, see [the module-level documentation][module]. +/// +/// [module]: ../../std/fmt/index.html +/// +/// # Examples +/// +/// Basic usage with `f64`: +/// +/// ``` +/// let x = 42.0; // 42.0 is '4.2e1' in scientific notation +/// +/// assert_eq!(format!("{x:e}"), "4.2e1"); +/// ``` +/// +/// Implementing `LowerExp` on a type: +/// +/// ``` +/// use std::fmt; +/// +/// struct Length(i32); +/// +/// impl fmt::LowerExp for Length { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// let val = f64::from(self.0); +/// fmt::LowerExp::fmt(&val, f) // delegate to f64's implementation +/// } +/// } +/// +/// let l = Length(100); +/// +/// assert_eq!( +/// format!("l in scientific notation is: {l:e}"), +/// "l in scientific notation is: 1e2" +/// ); +/// +/// assert_eq!( +/// format!("l in scientific notation is: {l:05e}"), +/// "l in scientific notation is: 001e2" +/// ); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub trait LowerExp { + #[doc = include_str!("fmt_trait_method_doc.md")] + #[stable(feature = "rust1", since = "1.0.0")] + fn fmt(&self, f: &mut Formatter<'_>) -> Result; +} + +/// `E` formatting. +/// +/// The `UpperExp` trait should format its output in scientific notation with an upper-case `E`. +/// +/// For more information on formatters, see [the module-level documentation][module]. +/// +/// [module]: ../../std/fmt/index.html +/// +/// # Examples +/// +/// Basic usage with `f64`: +/// +/// ``` +/// let x = 42.0; // 42.0 is '4.2E1' in scientific notation +/// +/// assert_eq!(format!("{x:E}"), "4.2E1"); +/// ``` +/// +/// Implementing `UpperExp` on a type: +/// +/// ``` +/// use std::fmt; +/// +/// struct Length(i32); +/// +/// impl fmt::UpperExp for Length { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// let val = f64::from(self.0); +/// fmt::UpperExp::fmt(&val, f) // delegate to f64's implementation +/// } +/// } +/// +/// let l = Length(100); +/// +/// assert_eq!( +/// format!("l in scientific notation is: {l:E}"), +/// "l in scientific notation is: 1E2" +/// ); +/// +/// assert_eq!( +/// format!("l in scientific notation is: {l:05E}"), +/// "l in scientific notation is: 001E2" +/// ); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub trait UpperExp { + #[doc = include_str!("fmt_trait_method_doc.md")] + #[stable(feature = "rust1", since = "1.0.0")] + fn fmt(&self, f: &mut Formatter<'_>) -> Result; +} + +/// Takes an output stream and an `Arguments` struct that can be precompiled with +/// the `format_args!` macro. +/// +/// The arguments will be formatted according to the specified format string +/// into the output stream provided. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::fmt; +/// +/// let mut output = String::new(); +/// fmt::write(&mut output, format_args!("Hello {}!", "world")) +/// .expect("Error occurred while trying to write in String"); +/// assert_eq!(output, "Hello world!"); +/// ``` +/// +/// Please note that using [`write!`] might be preferable. Example: +/// +/// ``` +/// use std::fmt::Write; +/// +/// let mut output = String::new(); +/// write!(&mut output, "Hello {}!", "world") +/// .expect("Error occurred while trying to write in String"); +/// assert_eq!(output, "Hello world!"); +/// ``` +/// +/// [`write!`]: crate::write! +#[stable(feature = "rust1", since = "1.0.0")] +pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { + let mut formatter = Formatter::new(output); + let mut idx = 0; + + match args.fmt { + None => { + // We can use default formatting parameters for all arguments. + for (i, arg) in args.args.iter().enumerate() { + // SAFETY: args.args and args.pieces come from the same Arguments, + // which guarantees the indexes are always within bounds. + let piece = unsafe { args.pieces.get_unchecked(i) }; + if !piece.is_empty() { + formatter.buf.write_str(*piece)?; + } + + // SAFETY: There are no formatting parameters and hence no + // count arguments. + unsafe { + arg.fmt(&mut formatter)?; + } + idx += 1; + } + } + Some(fmt) => { + // Every spec has a corresponding argument that is preceded by + // a string piece. + for (i, arg) in fmt.iter().enumerate() { + // SAFETY: fmt and args.pieces come from the same Arguments, + // which guarantees the indexes are always within bounds. + let piece = unsafe { args.pieces.get_unchecked(i) }; + if !piece.is_empty() { + formatter.buf.write_str(*piece)?; + } + // SAFETY: arg and args.args come from the same Arguments, + // which guarantees the indexes are always within bounds. + unsafe { run(&mut formatter, arg, args.args) }?; + idx += 1; + } + } + } + + // There can be only one trailing string piece left. + if let Some(piece) = args.pieces.get(idx) { + formatter.buf.write_str(*piece)?; + } + + Ok(()) +} + +unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argument<'_>]) -> Result { + fmt.fill = arg.fill; + fmt.align = arg.align; + fmt.flags = arg.flags; + // SAFETY: arg and args come from the same Arguments, + // which guarantees the indexes are always within bounds. + unsafe { + fmt.width = getcount(args, &arg.width); + fmt.precision = getcount(args, &arg.precision); + } + + // Extract the correct argument + debug_assert!(arg.position < args.len()); + // SAFETY: arg and args come from the same Arguments, + // which guarantees its index is always within bounds. + let value = unsafe { args.get_unchecked(arg.position) }; + + // Then actually do some printing + // SAFETY: this is a placeholder argument. + unsafe { value.fmt(fmt) } +} + +unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option { + match *cnt { + rt::Count::Is(n) => Some(n), + rt::Count::Implied => None, + rt::Count::Param(i) => { + debug_assert!(i < args.len()); + // SAFETY: cnt and args come from the same Arguments, + // which guarantees this index is always within bounds. + unsafe { args.get_unchecked(i).as_usize() } + } + } +} + +/// Padding after the end of something. Returned by `Formatter::padding`. +#[must_use = "don't forget to write the post padding"] +pub(crate) struct PostPadding { + fill: char, + padding: usize, +} + +impl PostPadding { + fn new(fill: char, padding: usize) -> PostPadding { + PostPadding { fill, padding } + } + + /// Writes this post padding. + pub(crate) fn write(self, f: &mut Formatter<'_>) -> Result { + for _ in 0..self.padding { + f.buf.write_char(self.fill)?; + } + Ok(()) + } +} + +impl<'a> Formatter<'a> { + fn wrap_buf<'b, 'c, F>(&'b mut self, wrap: F) -> Formatter<'c> + where + 'b: 'c, + F: FnOnce(&'b mut (dyn Write + 'b)) -> &'c mut (dyn Write + 'c), + { + Formatter { + // We want to change this + buf: wrap(self.buf), + + // And preserve these + flags: self.flags, + fill: self.fill, + align: self.align, + width: self.width, + precision: self.precision, + } + } + + // Helper methods used for padding and processing formatting arguments that + // all formatting traits can use. + + /// Performs the correct padding for an integer which has already been + /// emitted into a str. The str should *not* contain the sign for the + /// integer, that will be added by this method. + /// + /// # Arguments + /// + /// * is_nonnegative - whether the original integer was either positive or zero. + /// * prefix - if the '#' character (Alternate) is provided, this + /// is the prefix to put in front of the number. + /// * buf - the byte array that the number has been formatted into + /// + /// This function will correctly account for the flags provided as well as + /// the minimum width. It will not take precision into account. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo { nb: i32 } + /// + /// impl Foo { + /// fn new(nb: i32) -> Foo { + /// Foo { + /// nb, + /// } + /// } + /// } + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + /// // We need to remove "-" from the number output. + /// let tmp = self.nb.abs().to_string(); + /// + /// formatter.pad_integral(self.nb >= 0, "Foo ", &tmp) + /// } + /// } + /// + /// assert_eq!(format!("{}", Foo::new(2)), "2"); + /// assert_eq!(format!("{}", Foo::new(-1)), "-1"); + /// assert_eq!(format!("{}", Foo::new(0)), "0"); + /// assert_eq!(format!("{:#}", Foo::new(-1)), "-Foo 1"); + /// assert_eq!(format!("{:0>#8}", Foo::new(-1)), "00-Foo 1"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pad_integral(&mut self, is_nonnegative: bool, prefix: &str, buf: &str) -> Result { + let mut width = buf.len(); + + let mut sign = None; + if !is_nonnegative { + sign = Some('-'); + width += 1; + } else if self.sign_plus() { + sign = Some('+'); + width += 1; + } + + let prefix = if self.alternate() { + width += prefix.chars().count(); + Some(prefix) + } else { + None + }; + + // Writes the sign if it exists, and then the prefix if it was requested + #[inline(never)] + fn write_prefix(f: &mut Formatter<'_>, sign: Option, prefix: Option<&str>) -> Result { + if let Some(c) = sign { + f.buf.write_char(c)?; + } + if let Some(prefix) = prefix { f.buf.write_str(prefix) } else { Ok(()) } + } + + // The `width` field is more of a `min-width` parameter at this point. + match self.width { + // If there's no minimum length requirements then we can just + // write the bytes. + None => { + write_prefix(self, sign, prefix)?; + self.buf.write_str(buf) + } + // Check if we're over the minimum width, if so then we can also + // just write the bytes. + Some(min) if width >= min => { + write_prefix(self, sign, prefix)?; + self.buf.write_str(buf) + } + // The sign and prefix goes before the padding if the fill character + // is zero + Some(min) if self.sign_aware_zero_pad() => { + let old_fill = crate::mem::replace(&mut self.fill, '0'); + let old_align = crate::mem::replace(&mut self.align, rt::Alignment::Right); + write_prefix(self, sign, prefix)?; + let post_padding = self.padding(min - width, Alignment::Right)?; + self.buf.write_str(buf)?; + post_padding.write(self)?; + self.fill = old_fill; + self.align = old_align; + Ok(()) + } + // Otherwise, the sign and prefix goes after the padding + Some(min) => { + let post_padding = self.padding(min - width, Alignment::Right)?; + write_prefix(self, sign, prefix)?; + self.buf.write_str(buf)?; + post_padding.write(self) + } + } + } + + /// Takes a string slice and emits it to the internal buffer after applying + /// the relevant formatting flags specified. + /// + /// The flags recognized for generic strings are: + /// + /// * width - the minimum width of what to emit + /// * fill/align - what to emit and where to emit it if the string + /// provided needs to be padded + /// * precision - the maximum length to emit, the string is truncated if it + /// is longer than this length + /// + /// Notably this function ignores the `flag` parameters. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo; + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + /// formatter.pad("Foo") + /// } + /// } + /// + /// assert_eq!(format!("{Foo:<4}"), "Foo "); + /// assert_eq!(format!("{Foo:0>4}"), "0Foo"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pad(&mut self, s: &str) -> Result { + // Make sure there's a fast path up front + if self.width.is_none() && self.precision.is_none() { + return self.buf.write_str(s); + } + // The `precision` field can be interpreted as a `max-width` for the + // string being formatted. + let s = if let Some(max) = self.precision { + // If our string is longer that the precision, then we must have + // truncation. However other flags like `fill`, `width` and `align` + // must act as always. + if let Some((i, _)) = s.char_indices().nth(max) { + // LLVM here can't prove that `..i` won't panic `&s[..i]`, but + // we know that it can't panic. Use `get` + `unwrap_or` to avoid + // `unsafe` and otherwise don't emit any panic-related code + // here. + s.get(..i).unwrap_or(s) + } else { + &s + } + } else { + &s + }; + // The `width` field is more of a `min-width` parameter at this point. + match self.width { + // If we're under the maximum length, and there's no minimum length + // requirements, then we can just emit the string + None => self.buf.write_str(s), + Some(width) => { + let chars_count = s.chars().count(); + // If we're under the maximum width, check if we're over the minimum + // width, if so it's as easy as just emitting the string. + if chars_count >= width { + self.buf.write_str(s) + } + // If we're under both the maximum and the minimum width, then fill + // up the minimum width with the specified string + some alignment. + else { + let align = Alignment::Left; + let post_padding = self.padding(width - chars_count, align)?; + self.buf.write_str(s)?; + post_padding.write(self) + } + } + } + } + + /// Writes the pre-padding and returns the unwritten post-padding. + /// + /// Callers are responsible for ensuring post-padding is written after the + /// thing that is being padded. + pub(crate) fn padding( + &mut self, + padding: usize, + default: Alignment, + ) -> result::Result { + let align = match self.align { + rt::Alignment::Unknown => default, + rt::Alignment::Left => Alignment::Left, + rt::Alignment::Right => Alignment::Right, + rt::Alignment::Center => Alignment::Center, + }; + + let (pre_pad, post_pad) = match align { + Alignment::Left => (0, padding), + Alignment::Right => (padding, 0), + Alignment::Center => (padding / 2, (padding + 1) / 2), + }; + + for _ in 0..pre_pad { + self.buf.write_char(self.fill)?; + } + + Ok(PostPadding::new(self.fill, post_pad)) + } + + /// Takes the formatted parts and applies the padding. + /// + /// Assumes that the caller already has rendered the parts with required precision, + /// so that `self.precision` can be ignored. + /// + /// # Safety + /// + /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8. + unsafe fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result { + if let Some(mut width) = self.width { + // for the sign-aware zero padding, we render the sign first and + // behave as if we had no sign from the beginning. + let mut formatted = formatted.clone(); + let old_fill = self.fill; + let old_align = self.align; + if self.sign_aware_zero_pad() { + // a sign always goes first + let sign = formatted.sign; + self.buf.write_str(sign)?; + + // remove the sign from the formatted parts + formatted.sign = ""; + width = width.saturating_sub(sign.len()); + self.fill = '0'; + self.align = rt::Alignment::Right; + } + + // remaining parts go through the ordinary padding process. + let len = formatted.len(); + let ret = if width <= len { + // no padding + // SAFETY: Per the precondition. + unsafe { self.write_formatted_parts(&formatted) } + } else { + let post_padding = self.padding(width - len, Alignment::Right)?; + // SAFETY: Per the precondition. + unsafe { + self.write_formatted_parts(&formatted)?; + } + post_padding.write(self) + }; + self.fill = old_fill; + self.align = old_align; + ret + } else { + // this is the common case and we take a shortcut + // SAFETY: Per the precondition. + unsafe { self.write_formatted_parts(formatted) } + } + } + + /// # Safety + /// + /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8. + unsafe fn write_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result { + unsafe fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result { + // SAFETY: This is used for `numfmt::Part::Num` and `numfmt::Part::Copy`. + // It's safe to use for `numfmt::Part::Num` since every char `c` is between + // `b'0'` and `b'9'`, which means `s` is valid UTF-8. It's safe to use for + // `numfmt::Part::Copy` due to this function's precondition. + buf.write_str(unsafe { str::from_utf8_unchecked(s) }) + } + + if !formatted.sign.is_empty() { + self.buf.write_str(formatted.sign)?; + } + for part in formatted.parts { + match *part { + numfmt::Part::Zero(mut nzeroes) => { + const ZEROES: &str = // 64 zeroes + "0000000000000000000000000000000000000000000000000000000000000000"; + while nzeroes > ZEROES.len() { + self.buf.write_str(ZEROES)?; + nzeroes -= ZEROES.len(); + } + if nzeroes > 0 { + self.buf.write_str(&ZEROES[..nzeroes])?; + } + } + numfmt::Part::Num(mut v) => { + let mut s = [0; 5]; + let len = part.len(); + for c in s[..len].iter_mut().rev() { + *c = b'0' + (v % 10) as u8; + v /= 10; + } + // SAFETY: Per the precondition. + unsafe { + write_bytes(self.buf, &s[..len])?; + } + } + // SAFETY: Per the precondition. + numfmt::Part::Copy(buf) => unsafe { + write_bytes(self.buf, buf)?; + }, + } + } + Ok(()) + } + + /// Writes some data to the underlying buffer contained within this + /// formatter. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo; + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + /// formatter.write_str("Foo") + /// // This is equivalent to: + /// // write!(formatter, "Foo") + /// } + /// } + /// + /// assert_eq!(format!("{Foo}"), "Foo"); + /// assert_eq!(format!("{Foo:0>8}"), "Foo"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn write_str(&mut self, data: &str) -> Result { + self.buf.write_str(data) + } + + /// Glue for usage of the [`write!`] macro with implementors of this trait. + /// + /// This method should generally not be invoked manually, but rather through + /// the [`write!`] macro itself. + /// + /// Writes some formatted information into this instance. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32); + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + /// formatter.write_fmt(format_args!("Foo {}", self.0)) + /// } + /// } + /// + /// assert_eq!(format!("{}", Foo(-1)), "Foo -1"); + /// assert_eq!(format!("{:0>8}", Foo(2)), "Foo 2"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result { + if let Some(s) = fmt.as_statically_known_str() { + self.buf.write_str(s) + } else { + write(self.buf, fmt) + } + } + + /// Returns flags for formatting. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated( + since = "1.24.0", + note = "use the `sign_plus`, `sign_minus`, `alternate`, \ + or `sign_aware_zero_pad` methods instead" + )] + pub fn flags(&self) -> u32 { + self.flags + } + + /// Returns the character used as 'fill' whenever there is alignment. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo; + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + /// let c = formatter.fill(); + /// if let Some(width) = formatter.width() { + /// for _ in 0..width { + /// write!(formatter, "{c}")?; + /// } + /// Ok(()) + /// } else { + /// write!(formatter, "{c}") + /// } + /// } + /// } + /// + /// // We set alignment to the right with ">". + /// assert_eq!(format!("{Foo:G>3}"), "GGG"); + /// assert_eq!(format!("{Foo:t>6}"), "tttttt"); + /// ``` + #[must_use] + #[stable(feature = "fmt_flags", since = "1.5.0")] + pub fn fill(&self) -> char { + self.fill + } + + /// Returns a flag indicating what form of alignment was requested. + /// + /// # Examples + /// + /// ``` + /// use std::fmt::{self, Alignment}; + /// + /// struct Foo; + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + /// let s = if let Some(s) = formatter.align() { + /// match s { + /// Alignment::Left => "left", + /// Alignment::Right => "right", + /// Alignment::Center => "center", + /// } + /// } else { + /// "into the void" + /// }; + /// write!(formatter, "{s}") + /// } + /// } + /// + /// assert_eq!(format!("{Foo:<}"), "left"); + /// assert_eq!(format!("{Foo:>}"), "right"); + /// assert_eq!(format!("{Foo:^}"), "center"); + /// assert_eq!(format!("{Foo}"), "into the void"); + /// ``` + #[must_use] + #[stable(feature = "fmt_flags_align", since = "1.28.0")] + pub fn align(&self) -> Option { + match self.align { + rt::Alignment::Left => Some(Alignment::Left), + rt::Alignment::Right => Some(Alignment::Right), + rt::Alignment::Center => Some(Alignment::Center), + rt::Alignment::Unknown => None, + } + } + + /// Returns the optionally specified integer width that the output should be. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32); + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + /// if let Some(width) = formatter.width() { + /// // If we received a width, we use it + /// write!(formatter, "{:width$}", format!("Foo({})", self.0), width = width) + /// } else { + /// // Otherwise we do nothing special + /// write!(formatter, "Foo({})", self.0) + /// } + /// } + /// } + /// + /// assert_eq!(format!("{:10}", Foo(23)), "Foo(23) "); + /// assert_eq!(format!("{}", Foo(23)), "Foo(23)"); + /// ``` + #[must_use] + #[stable(feature = "fmt_flags", since = "1.5.0")] + pub fn width(&self) -> Option { + self.width + } + + /// Returns the optionally specified precision for numeric types. + /// Alternatively, the maximum width for string types. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(f32); + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + /// if let Some(precision) = formatter.precision() { + /// // If we received a precision, we use it. + /// write!(formatter, "Foo({1:.*})", precision, self.0) + /// } else { + /// // Otherwise we default to 2. + /// write!(formatter, "Foo({:.2})", self.0) + /// } + /// } + /// } + /// + /// assert_eq!(format!("{:.4}", Foo(23.2)), "Foo(23.2000)"); + /// assert_eq!(format!("{}", Foo(23.2)), "Foo(23.20)"); + /// ``` + #[must_use] + #[stable(feature = "fmt_flags", since = "1.5.0")] + pub fn precision(&self) -> Option { + self.precision + } + + /// Determines if the `+` flag was specified. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32); + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + /// if formatter.sign_plus() { + /// write!(formatter, + /// "Foo({}{})", + /// if self.0 < 0 { '-' } else { '+' }, + /// self.0.abs()) + /// } else { + /// write!(formatter, "Foo({})", self.0) + /// } + /// } + /// } + /// + /// assert_eq!(format!("{:+}", Foo(23)), "Foo(+23)"); + /// assert_eq!(format!("{:+}", Foo(-23)), "Foo(-23)"); + /// assert_eq!(format!("{}", Foo(23)), "Foo(23)"); + /// ``` + #[must_use] + #[stable(feature = "fmt_flags", since = "1.5.0")] + pub fn sign_plus(&self) -> bool { + self.flags & (1 << rt::Flag::SignPlus as u32) != 0 + } + + /// Determines if the `-` flag was specified. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32); + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + /// if formatter.sign_minus() { + /// // You want a minus sign? Have one! + /// write!(formatter, "-Foo({})", self.0) + /// } else { + /// write!(formatter, "Foo({})", self.0) + /// } + /// } + /// } + /// + /// assert_eq!(format!("{:-}", Foo(23)), "-Foo(23)"); + /// assert_eq!(format!("{}", Foo(23)), "Foo(23)"); + /// ``` + #[must_use] + #[stable(feature = "fmt_flags", since = "1.5.0")] + pub fn sign_minus(&self) -> bool { + self.flags & (1 << rt::Flag::SignMinus as u32) != 0 + } + + /// Determines if the `#` flag was specified. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32); + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + /// if formatter.alternate() { + /// write!(formatter, "Foo({})", self.0) + /// } else { + /// write!(formatter, "{}", self.0) + /// } + /// } + /// } + /// + /// assert_eq!(format!("{:#}", Foo(23)), "Foo(23)"); + /// assert_eq!(format!("{}", Foo(23)), "23"); + /// ``` + #[must_use] + #[stable(feature = "fmt_flags", since = "1.5.0")] + pub fn alternate(&self) -> bool { + self.flags & (1 << rt::Flag::Alternate as u32) != 0 + } + + /// Determines if the `0` flag was specified. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32); + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + /// assert!(formatter.sign_aware_zero_pad()); + /// assert_eq!(formatter.width(), Some(4)); + /// // We ignore the formatter's options. + /// write!(formatter, "{}", self.0) + /// } + /// } + /// + /// assert_eq!(format!("{:04}", Foo(23)), "23"); + /// ``` + #[must_use] + #[stable(feature = "fmt_flags", since = "1.5.0")] + pub fn sign_aware_zero_pad(&self) -> bool { + self.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0 + } + + // FIXME: Decide what public API we want for these two flags. + // https://github.com/rust-lang/rust/issues/48584 + fn debug_lower_hex(&self) -> bool { + self.flags & (1 << rt::Flag::DebugLowerHex as u32) != 0 + } + + fn debug_upper_hex(&self) -> bool { + self.flags & (1 << rt::Flag::DebugUpperHex as u32) != 0 + } + + /// Creates a [`DebugStruct`] builder designed to assist with creation of + /// [`fmt::Debug`] implementations for structs. + /// + /// [`fmt::Debug`]: self::Debug + /// + /// # Examples + /// + /// ```rust + /// use std::fmt; + /// use std::net::Ipv4Addr; + /// + /// struct Foo { + /// bar: i32, + /// baz: String, + /// addr: Ipv4Addr, + /// } + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_struct("Foo") + /// .field("bar", &self.bar) + /// .field("baz", &self.baz) + /// .field("addr", &format_args!("{}", self.addr)) + /// .finish() + /// } + /// } + /// + /// assert_eq!( + /// "Foo { bar: 10, baz: \"Hello World\", addr: 127.0.0.1 }", + /// format!("{:?}", Foo { + /// bar: 10, + /// baz: "Hello World".to_string(), + /// addr: Ipv4Addr::new(127, 0, 0, 1), + /// }) + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> { + builders::debug_struct_new(self, name) + } + + /// Shrinks `derive(Debug)` code, for faster compilation and smaller + /// binaries. `debug_struct_fields_finish` is more general, but this is + /// faster for 1 field. + #[doc(hidden)] + #[unstable(feature = "fmt_helpers_for_derive", issue = "none")] + pub fn debug_struct_field1_finish<'b>( + &'b mut self, + name: &str, + name1: &str, + value1: &dyn Debug, + ) -> Result { + let mut builder = builders::debug_struct_new(self, name); + builder.field(name1, value1); + builder.finish() + } + + /// Shrinks `derive(Debug)` code, for faster compilation and smaller + /// binaries. `debug_struct_fields_finish` is more general, but this is + /// faster for 2 fields. + #[doc(hidden)] + #[unstable(feature = "fmt_helpers_for_derive", issue = "none")] + pub fn debug_struct_field2_finish<'b>( + &'b mut self, + name: &str, + name1: &str, + value1: &dyn Debug, + name2: &str, + value2: &dyn Debug, + ) -> Result { + let mut builder = builders::debug_struct_new(self, name); + builder.field(name1, value1); + builder.field(name2, value2); + builder.finish() + } + + /// Shrinks `derive(Debug)` code, for faster compilation and smaller + /// binaries. `debug_struct_fields_finish` is more general, but this is + /// faster for 3 fields. + #[doc(hidden)] + #[unstable(feature = "fmt_helpers_for_derive", issue = "none")] + pub fn debug_struct_field3_finish<'b>( + &'b mut self, + name: &str, + name1: &str, + value1: &dyn Debug, + name2: &str, + value2: &dyn Debug, + name3: &str, + value3: &dyn Debug, + ) -> Result { + let mut builder = builders::debug_struct_new(self, name); + builder.field(name1, value1); + builder.field(name2, value2); + builder.field(name3, value3); + builder.finish() + } + + /// Shrinks `derive(Debug)` code, for faster compilation and smaller + /// binaries. `debug_struct_fields_finish` is more general, but this is + /// faster for 4 fields. + #[doc(hidden)] + #[unstable(feature = "fmt_helpers_for_derive", issue = "none")] + pub fn debug_struct_field4_finish<'b>( + &'b mut self, + name: &str, + name1: &str, + value1: &dyn Debug, + name2: &str, + value2: &dyn Debug, + name3: &str, + value3: &dyn Debug, + name4: &str, + value4: &dyn Debug, + ) -> Result { + let mut builder = builders::debug_struct_new(self, name); + builder.field(name1, value1); + builder.field(name2, value2); + builder.field(name3, value3); + builder.field(name4, value4); + builder.finish() + } + + /// Shrinks `derive(Debug)` code, for faster compilation and smaller + /// binaries. `debug_struct_fields_finish` is more general, but this is + /// faster for 5 fields. + #[doc(hidden)] + #[unstable(feature = "fmt_helpers_for_derive", issue = "none")] + pub fn debug_struct_field5_finish<'b>( + &'b mut self, + name: &str, + name1: &str, + value1: &dyn Debug, + name2: &str, + value2: &dyn Debug, + name3: &str, + value3: &dyn Debug, + name4: &str, + value4: &dyn Debug, + name5: &str, + value5: &dyn Debug, + ) -> Result { + let mut builder = builders::debug_struct_new(self, name); + builder.field(name1, value1); + builder.field(name2, value2); + builder.field(name3, value3); + builder.field(name4, value4); + builder.field(name5, value5); + builder.finish() + } + + /// Shrinks `derive(Debug)` code, for faster compilation and smaller binaries. + /// For the cases not covered by `debug_struct_field[12345]_finish`. + #[doc(hidden)] + #[unstable(feature = "fmt_helpers_for_derive", issue = "none")] + pub fn debug_struct_fields_finish<'b>( + &'b mut self, + name: &str, + names: &[&str], + values: &[&dyn Debug], + ) -> Result { + assert_eq!(names.len(), values.len()); + let mut builder = builders::debug_struct_new(self, name); + for (name, value) in iter::zip(names, values) { + builder.field(name, value); + } + builder.finish() + } + + /// Creates a `DebugTuple` builder designed to assist with creation of + /// `fmt::Debug` implementations for tuple structs. + /// + /// # Examples + /// + /// ```rust + /// use std::fmt; + /// use std::marker::PhantomData; + /// + /// struct Foo(i32, String, PhantomData); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_tuple("Foo") + /// .field(&self.0) + /// .field(&self.1) + /// .field(&format_args!("_")) + /// .finish() + /// } + /// } + /// + /// assert_eq!( + /// "Foo(10, \"Hello\", _)", + /// format!("{:?}", Foo(10, "Hello".to_string(), PhantomData::)) + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> { + builders::debug_tuple_new(self, name) + } + + /// Shrinks `derive(Debug)` code, for faster compilation and smaller + /// binaries. `debug_tuple_fields_finish` is more general, but this is faster + /// for 1 field. + #[doc(hidden)] + #[unstable(feature = "fmt_helpers_for_derive", issue = "none")] + pub fn debug_tuple_field1_finish<'b>(&'b mut self, name: &str, value1: &dyn Debug) -> Result { + let mut builder = builders::debug_tuple_new(self, name); + builder.field(value1); + builder.finish() + } + + /// Shrinks `derive(Debug)` code, for faster compilation and smaller + /// binaries. `debug_tuple_fields_finish` is more general, but this is faster + /// for 2 fields. + #[doc(hidden)] + #[unstable(feature = "fmt_helpers_for_derive", issue = "none")] + pub fn debug_tuple_field2_finish<'b>( + &'b mut self, + name: &str, + value1: &dyn Debug, + value2: &dyn Debug, + ) -> Result { + let mut builder = builders::debug_tuple_new(self, name); + builder.field(value1); + builder.field(value2); + builder.finish() + } + + /// Shrinks `derive(Debug)` code, for faster compilation and smaller + /// binaries. `debug_tuple_fields_finish` is more general, but this is faster + /// for 3 fields. + #[doc(hidden)] + #[unstable(feature = "fmt_helpers_for_derive", issue = "none")] + pub fn debug_tuple_field3_finish<'b>( + &'b mut self, + name: &str, + value1: &dyn Debug, + value2: &dyn Debug, + value3: &dyn Debug, + ) -> Result { + let mut builder = builders::debug_tuple_new(self, name); + builder.field(value1); + builder.field(value2); + builder.field(value3); + builder.finish() + } + + /// Shrinks `derive(Debug)` code, for faster compilation and smaller + /// binaries. `debug_tuple_fields_finish` is more general, but this is faster + /// for 4 fields. + #[doc(hidden)] + #[unstable(feature = "fmt_helpers_for_derive", issue = "none")] + pub fn debug_tuple_field4_finish<'b>( + &'b mut self, + name: &str, + value1: &dyn Debug, + value2: &dyn Debug, + value3: &dyn Debug, + value4: &dyn Debug, + ) -> Result { + let mut builder = builders::debug_tuple_new(self, name); + builder.field(value1); + builder.field(value2); + builder.field(value3); + builder.field(value4); + builder.finish() + } + + /// Shrinks `derive(Debug)` code, for faster compilation and smaller + /// binaries. `debug_tuple_fields_finish` is more general, but this is faster + /// for 5 fields. + #[doc(hidden)] + #[unstable(feature = "fmt_helpers_for_derive", issue = "none")] + pub fn debug_tuple_field5_finish<'b>( + &'b mut self, + name: &str, + value1: &dyn Debug, + value2: &dyn Debug, + value3: &dyn Debug, + value4: &dyn Debug, + value5: &dyn Debug, + ) -> Result { + let mut builder = builders::debug_tuple_new(self, name); + builder.field(value1); + builder.field(value2); + builder.field(value3); + builder.field(value4); + builder.field(value5); + builder.finish() + } + + /// Shrinks `derive(Debug)` code, for faster compilation and smaller + /// binaries. For the cases not covered by `debug_tuple_field[12345]_finish`. + #[doc(hidden)] + #[unstable(feature = "fmt_helpers_for_derive", issue = "none")] + pub fn debug_tuple_fields_finish<'b>( + &'b mut self, + name: &str, + values: &[&dyn Debug], + ) -> Result { + let mut builder = builders::debug_tuple_new(self, name); + for value in values { + builder.field(value); + } + builder.finish() + } + + /// Creates a `DebugList` builder designed to assist with creation of + /// `fmt::Debug` implementations for list-like structures. + /// + /// # Examples + /// + /// ```rust + /// use std::fmt; + /// + /// struct Foo(Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_list().entries(self.0.iter()).finish() + /// } + /// } + /// + /// assert_eq!(format!("{:?}", Foo(vec![10, 11])), "[10, 11]"); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn debug_list<'b>(&'b mut self) -> DebugList<'b, 'a> { + builders::debug_list_new(self) + } + + /// Creates a `DebugSet` builder designed to assist with creation of + /// `fmt::Debug` implementations for set-like structures. + /// + /// # Examples + /// + /// ```rust + /// use std::fmt; + /// + /// struct Foo(Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_set().entries(self.0.iter()).finish() + /// } + /// } + /// + /// assert_eq!(format!("{:?}", Foo(vec![10, 11])), "{10, 11}"); + /// ``` + /// + /// [`format_args!`]: crate::format_args + /// + /// In this more complex example, we use [`format_args!`] and `.debug_set()` + /// to build a list of match arms: + /// + /// ```rust + /// use std::fmt; + /// + /// struct Arm<'a, L, R>(&'a (L, R)); + /// struct Table<'a, K, V>(&'a [(K, V)], V); + /// + /// impl<'a, L, R> fmt::Debug for Arm<'a, L, R> + /// where + /// L: 'a + fmt::Debug, R: 'a + fmt::Debug + /// { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// L::fmt(&(self.0).0, fmt)?; + /// fmt.write_str(" => ")?; + /// R::fmt(&(self.0).1, fmt) + /// } + /// } + /// + /// impl<'a, K, V> fmt::Debug for Table<'a, K, V> + /// where + /// K: 'a + fmt::Debug, V: 'a + fmt::Debug + /// { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_set() + /// .entries(self.0.iter().map(Arm)) + /// .entry(&Arm(&(format_args!("_"), &self.1))) + /// .finish() + /// } + /// } + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn debug_set<'b>(&'b mut self) -> DebugSet<'b, 'a> { + builders::debug_set_new(self) + } + + /// Creates a `DebugMap` builder designed to assist with creation of + /// `fmt::Debug` implementations for map-like structures. + /// + /// # Examples + /// + /// ```rust + /// use std::fmt; + /// + /// struct Foo(Vec<(String, i32)>); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish() + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), + /// r#"{"A": 10, "B": 11}"# + /// ); + /// ``` + #[stable(feature = "debug_builders", since = "1.2.0")] + pub fn debug_map<'b>(&'b mut self) -> DebugMap<'b, 'a> { + builders::debug_map_new(self) + } +} + +#[stable(since = "1.2.0", feature = "formatter_write")] +impl Write for Formatter<'_> { + fn write_str(&mut self, s: &str) -> Result { + self.buf.write_str(s) + } + + fn write_char(&mut self, c: char) -> Result { + self.buf.write_char(c) + } + + #[inline] + fn write_fmt(&mut self, args: Arguments<'_>) -> Result { + if let Some(s) = args.as_statically_known_str() { + self.buf.write_str(s) + } else { + write(self.buf, args) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Display for Error { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + Display::fmt("an error occurred when formatting an argument", f) + } +} + +// Implementations of the core formatting traits + +macro_rules! fmt_refs { + ($($tr:ident),*) => { + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl $tr for &T { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) } + } + #[stable(feature = "rust1", since = "1.0.0")] + impl $tr for &mut T { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) } + } + )* + } +} + +fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp } + +#[unstable(feature = "never_type", issue = "35121")] +impl Debug for ! { + #[inline] + fn fmt(&self, _: &mut Formatter<'_>) -> Result { + *self + } +} + +#[unstable(feature = "never_type", issue = "35121")] +impl Display for ! { + #[inline] + fn fmt(&self, _: &mut Formatter<'_>) -> Result { + *self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for bool { + #[inline] + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + Display::fmt(self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Display for bool { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + Display::fmt(if *self { "true" } else { "false" }, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for str { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.write_char('"')?; + + // substring we know is printable + let mut printable_range = 0..0; + + fn needs_escape(b: u8) -> bool { + b > 0x7E || b < 0x20 || b == b'\\' || b == b'"' + } + + // the loop here first skips over runs of printable ASCII as a fast path. + // other chars (unicode, or ASCII that needs escaping) are then handled per-`char`. + let mut rest = self; + while rest.len() > 0 { + let Some(non_printable_start) = rest.as_bytes().iter().position(|&b| needs_escape(b)) + else { + printable_range.end += rest.len(); + break; + }; + + printable_range.end += non_printable_start; + // SAFETY: the position was derived from an iterator, so is known to be within bounds, and at a char boundary + rest = unsafe { rest.get_unchecked(non_printable_start..) }; + + let mut chars = rest.chars(); + if let Some(c) = chars.next() { + let esc = c.escape_debug_ext(EscapeDebugExtArgs { + escape_grapheme_extended: true, + escape_single_quote: false, + escape_double_quote: true, + }); + if esc.len() != 1 { + f.write_str(&self[printable_range.clone()])?; + Display::fmt(&esc, f)?; + printable_range.start = printable_range.end + c.len_utf8(); + } + printable_range.end += c.len_utf8(); + } + rest = chars.as_str(); + } + + f.write_str(&self[printable_range])?; + + f.write_char('"') + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Display for str { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.pad(self) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for char { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.write_char('\'')?; + let esc = self.escape_debug_ext(EscapeDebugExtArgs { + escape_grapheme_extended: true, + escape_single_quote: true, + escape_double_quote: false, + }); + Display::fmt(&esc, f)?; + f.write_char('\'') + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Display for char { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + if f.width.is_none() && f.precision.is_none() { + f.write_char(*self) + } else { + f.pad(self.encode_utf8(&mut [0; 4])) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Pointer for *const T { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + pointer_fmt_inner(self.expose_provenance(), f) + } +} + +/// Since the formatting will be identical for all pointer types, uses a +/// non-monomorphized implementation for the actual formatting to reduce the +/// amount of codegen work needed. +/// +/// This uses `ptr_addr: usize` and not `ptr: *const ()` to be able to use this for +/// `fn(...) -> ...` without using [problematic] "Oxford Casts". +/// +/// [problematic]: https://github.com/rust-lang/rust/issues/95489 +pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Result { + let old_width = f.width; + let old_flags = f.flags; + + // The alternate flag is already treated by LowerHex as being special- + // it denotes whether to prefix with 0x. We use it to work out whether + // or not to zero extend, and then unconditionally set it to get the + // prefix. + if f.alternate() { + f.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32); + + if f.width.is_none() { + f.width = Some((usize::BITS / 4) as usize + 2); + } + } + f.flags |= 1 << (rt::Flag::Alternate as u32); + + let ret = LowerHex::fmt(&ptr_addr, f); + + f.width = old_width; + f.flags = old_flags; + + ret +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Pointer for *mut T { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + Pointer::fmt(&(*self as *const T), f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Pointer for &T { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + Pointer::fmt(&(*self as *const T), f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Pointer for &mut T { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + Pointer::fmt(&(&**self as *const T), f) + } +} + +// Implementation of Display/Debug for various core types + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for *const T { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + Pointer::fmt(self, f) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for *mut T { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + Pointer::fmt(self, f) + } +} + +macro_rules! peel { + ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* }) +} + +macro_rules! tuple { + () => (); + ( $($name:ident,)+ ) => ( + maybe_tuple_doc! { + $($name)+ @ + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($name:Debug),+> Debug for ($($name,)+) where last_type!($($name,)+): ?Sized { + #[allow(non_snake_case, unused_assignments)] + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + let mut builder = f.debug_tuple(""); + let ($(ref $name,)+) = *self; + $( + builder.field(&$name); + )+ + + builder.finish() + } + } + } + peel! { $($name,)+ } + ) +} + +macro_rules! maybe_tuple_doc { + ($a:ident @ #[$meta:meta] $item:item) => { + #[doc(fake_variadic)] + #[doc = "This trait is implemented for tuples up to twelve items long."] + #[$meta] + $item + }; + ($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => { + #[doc(hidden)] + #[$meta] + $item + }; +} + +macro_rules! last_type { + ($a:ident,) => { $a }; + ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; +} + +tuple! { E, D, C, B, A, Z, Y, X, W, V, U, T, } + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for [T] { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.debug_list().entries(self.iter()).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for () { + #[inline] + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.pad("()") + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for PhantomData { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "PhantomData<{}>", crate::any::type_name::()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for Cell { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.debug_struct("Cell").field("value", &self.get()).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for RefCell { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + let mut d = f.debug_struct("RefCell"); + match self.try_borrow() { + Ok(borrow) => d.field("value", &borrow), + Err(_) => d.field("value", &format_args!("")), + }; + d.finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for Ref<'_, T> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for RefMut<'_, T> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + Debug::fmt(&*(self.deref()), f) + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl Debug for UnsafeCell { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.debug_struct("UnsafeCell").finish_non_exhaustive() + } +} + +#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +impl Debug for SyncUnsafeCell { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.debug_struct("SyncUnsafeCell").finish_non_exhaustive() + } +} + +// If you expected tests to be here, look instead at the core/tests/fmt.rs file, +// it's a lot easier than creating all of the rt::Piece structures here. +// There are also tests in the alloc crate, for those that need allocations. diff --git a/CoqOfRust/core/fmt/nofloat.rs b/CoqOfRust/core/fmt/nofloat.rs new file mode 100644 index 000000000..29aaee75d --- /dev/null +++ b/CoqOfRust/core/fmt/nofloat.rs @@ -0,0 +1,17 @@ +use crate::fmt::{Debug, Formatter, Result}; + +macro_rules! floating { + ($($ty:ident)*) => { + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl Debug for $ty { + #[inline] + fn fmt(&self, _fmt: &mut Formatter<'_>) -> Result { + panic!("floating point fmt support is turned off"); + } + } + )* + }; +} + +floating! { f16 f32 f64 f128 } diff --git a/CoqOfRust/core/fmt/num.rs b/CoqOfRust/core/fmt/num.rs new file mode 100644 index 000000000..683e45b35 --- /dev/null +++ b/CoqOfRust/core/fmt/num.rs @@ -0,0 +1,753 @@ +//! Integer and floating-point number formatting + +use crate::mem::MaybeUninit; +use crate::num::fmt as numfmt; +use crate::ops::{Div, Rem, Sub}; +use crate::{fmt, ptr, slice, str}; + +#[doc(hidden)] +trait DisplayInt: + PartialEq + PartialOrd + Div + Rem + Sub + Copy +{ + fn zero() -> Self; + fn from_u8(u: u8) -> Self; + fn to_u8(&self) -> u8; + #[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))] + fn to_u32(&self) -> u32; + fn to_u64(&self) -> u64; + fn to_u128(&self) -> u128; +} + +macro_rules! impl_int { + ($($t:ident)*) => ( + $(impl DisplayInt for $t { + fn zero() -> Self { 0 } + fn from_u8(u: u8) -> Self { u as Self } + fn to_u8(&self) -> u8 { *self as u8 } + #[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))] + fn to_u32(&self) -> u32 { *self as u32 } + fn to_u64(&self) -> u64 { *self as u64 } + fn to_u128(&self) -> u128 { *self as u128 } + })* + ) +} + +impl_int! { + i8 i16 i32 i64 i128 isize + u8 u16 u32 u64 u128 usize +} + +/// A type that represents a specific radix +/// +/// # Safety +/// +/// `digit` must return an ASCII character. +#[doc(hidden)] +unsafe trait GenericRadix: Sized { + /// The number of digits. + const BASE: u8; + + /// A radix-specific prefix string. + const PREFIX: &'static str; + + /// Converts an integer to corresponding radix digit. + fn digit(x: u8) -> u8; + + /// Format an integer using the radix using a formatter. + fn fmt_int(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // The radix can be as low as 2, so we need a buffer of at least 128 + // characters for a base 2 number. + let zero = T::zero(); + let is_nonnegative = x >= zero; + let mut buf = [MaybeUninit::::uninit(); 128]; + let mut curr = buf.len(); + let base = T::from_u8(Self::BASE); + if is_nonnegative { + // Accumulate each digit of the number from the least significant + // to the most significant figure. + loop { + let n = x % base; // Get the current place value. + x = x / base; // Deaccumulate the number. + curr -= 1; + buf[curr].write(Self::digit(n.to_u8())); // Store the digit in the buffer. + if x == zero { + // No more digits left to accumulate. + break; + }; + } + } else { + // Do the same as above, but accounting for two's complement. + loop { + let n = zero - (x % base); // Get the current place value. + x = x / base; // Deaccumulate the number. + curr -= 1; + buf[curr].write(Self::digit(n.to_u8())); // Store the digit in the buffer. + if x == zero { + // No more digits left to accumulate. + break; + }; + } + } + // SAFETY: `curr` is initialized to `buf.len()` and is only decremented, so it can't overflow. It is + // decremented exactly once for each digit. Since u128 is the widest fixed width integer format supported, + // the maximum number of digits (bits) is 128 for base-2, so `curr` won't underflow as well. + let buf = unsafe { buf.get_unchecked(curr..) }; + // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be + // valid UTF-8 + let buf = unsafe { + str::from_utf8_unchecked(slice::from_raw_parts( + MaybeUninit::slice_as_ptr(buf), + buf.len(), + )) + }; + f.pad_integral(is_nonnegative, Self::PREFIX, buf) + } +} + +/// A binary (base 2) radix +#[derive(Clone, PartialEq)] +struct Binary; + +/// An octal (base 8) radix +#[derive(Clone, PartialEq)] +struct Octal; + +/// A hexadecimal (base 16) radix, formatted with lower-case characters +#[derive(Clone, PartialEq)] +struct LowerHex; + +/// A hexadecimal (base 16) radix, formatted with upper-case characters +#[derive(Clone, PartialEq)] +struct UpperHex; + +macro_rules! radix { + ($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => { + unsafe impl GenericRadix for $T { + const BASE: u8 = $base; + const PREFIX: &'static str = $prefix; + fn digit(x: u8) -> u8 { + match x { + $($x => $conv,)+ + x => panic!("number not in the range 0..={}: {}", Self::BASE - 1, x), + } + } + } + } +} + +radix! { Binary, 2, "0b", x @ 0 ..= 1 => b'0' + x } +radix! { Octal, 8, "0o", x @ 0 ..= 7 => b'0' + x } +radix! { LowerHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'a' + (x - 10) } +radix! { UpperHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'A' + (x - 10) } + +macro_rules! int_base { + (fmt::$Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::$Trait for $T { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + $Radix.fmt_int(*self as $U, f) + } + } + }; +} + +macro_rules! integer { + ($Int:ident, $Uint:ident) => { + int_base! { fmt::Binary for $Int as $Uint -> Binary } + int_base! { fmt::Octal for $Int as $Uint -> Octal } + int_base! { fmt::LowerHex for $Int as $Uint -> LowerHex } + int_base! { fmt::UpperHex for $Int as $Uint -> UpperHex } + + int_base! { fmt::Binary for $Uint as $Uint -> Binary } + int_base! { fmt::Octal for $Uint as $Uint -> Octal } + int_base! { fmt::LowerHex for $Uint as $Uint -> LowerHex } + int_base! { fmt::UpperHex for $Uint as $Uint -> UpperHex } + }; +} +integer! { isize, usize } +integer! { i8, u8 } +integer! { i16, u16 } +integer! { i32, u32 } +integer! { i64, u64 } +integer! { i128, u128 } + +macro_rules! impl_Debug { + ($($T:ident)*) => { + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::Debug for $T { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if f.debug_lower_hex() { + fmt::LowerHex::fmt(self, f) + } else if f.debug_upper_hex() { + fmt::UpperHex::fmt(self, f) + } else { + fmt::Display::fmt(self, f) + } + } + } + )* + }; +} + +// 2 digit decimal look up table +static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\ + 2021222324252627282930313233343536373839\ + 4041424344454647484950515253545556575859\ + 6061626364656667686970717273747576777879\ + 8081828384858687888990919293949596979899"; + +macro_rules! impl_Display { + ($($signed:ident, $unsigned:ident,)* ; as $u:ident via $conv_fn:ident named $gen_name:ident) => { + + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::Display for $unsigned { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + #[cfg(not(feature = "optimize_for_size"))] + { + self._fmt(true, f) + } + #[cfg(feature = "optimize_for_size")] + { + $gen_name(self.$conv_fn(), true, f) + } + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::Display for $signed { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + #[cfg(not(feature = "optimize_for_size"))] + { + return self.unsigned_abs()._fmt(*self >= 0, f); + } + #[cfg(feature = "optimize_for_size")] + { + return $gen_name(self.unsigned_abs().$conv_fn(), *self >= 0, f); + } + } + } + + #[cfg(not(feature = "optimize_for_size"))] + impl $unsigned { + fn _fmt(mut self, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { + const SIZE: usize = $unsigned::MAX.ilog(10) as usize + 1; + let mut buf = [MaybeUninit::::uninit(); SIZE]; + let mut curr = SIZE; + let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); + let lut_ptr = DEC_DIGITS_LUT.as_ptr(); + + // SAFETY: Since `d1` and `d2` are always less than or equal to `198`, we + // can copy from `lut_ptr[d1..d1 + 1]` and `lut_ptr[d2..d2 + 1]`. To show + // that it's OK to copy into `buf_ptr`, notice that at the beginning + // `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at + // each step this is kept the same as `n` is divided. Since `n` is always + // non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]` + // is safe to access. + unsafe { + // need at least 16 bits for the 4-characters-at-a-time to work. + #[allow(overflowing_literals)] + #[allow(unused_comparisons)] + // This block will be removed for smaller types at compile time and in the worst + // case, it will prevent to have the `10000` literal to overflow for `i8` and `u8`. + if core::mem::size_of::<$unsigned>() >= 2 { + // eagerly decode 4 characters at a time + while self >= 10000 { + let rem = (self % 10000) as usize; + self /= 10000; + + let d1 = (rem / 100) << 1; + let d2 = (rem % 100) << 1; + curr -= 4; + + // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since + // otherwise `curr < 0`. But then `n` was originally at least `10000^10` + // which is `10^40 > 2^128 > n`. + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(curr + 2), 2); + } + } + + // if we reach here numbers are <= 9999, so at most 4 chars long + let mut n = self as usize; // possibly reduce 64bit math + + // decode 2 more chars, if > 2 chars + if n >= 100 { + let d1 = (n % 100) << 1; + n /= 100; + curr -= 2; + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2); + } + + // if we reach here numbers are <= 100, so at most 2 chars long + // The biggest it can be is 99, and 99 << 1 == 198, so a `u8` is enough. + // decode last 1 or 2 chars + if n < 10 { + curr -= 1; + *buf_ptr.add(curr) = (n as u8) + b'0'; + } else { + let d1 = n << 1; + curr -= 2; + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2); + } + } + + // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid + // UTF-8 since `DEC_DIGITS_LUT` is + let buf_slice = unsafe { + str::from_utf8_unchecked( + slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr)) + }; + f.pad_integral(is_nonnegative, "", buf_slice) + } + })* + + #[cfg(feature = "optimize_for_size")] + fn $gen_name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { + const SIZE: usize = $u::MAX.ilog(10) as usize + 1; + let mut buf = [MaybeUninit::::uninit(); SIZE]; + let mut curr = buf.len(); + let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); + + // SAFETY: To show that it's OK to copy into `buf_ptr`, notice that at the beginning + // `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at + // each step this is kept the same as `n` is divided. Since `n` is always + // non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]` + // is safe to access. + unsafe { + loop { + curr -= 1; + buf_ptr.add(curr).write((n % 10) as u8 + b'0'); + n /= 10; + + if n == 0 { + break; + } + } + } + + // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid UTF-8 + let buf_slice = unsafe { + str::from_utf8_unchecked( + slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr)) + }; + f.pad_integral(is_nonnegative, "", buf_slice) + } + }; +} + +macro_rules! impl_Exp { + ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => { + fn $name( + mut n: $u, + is_nonnegative: bool, + upper: bool, + f: &mut fmt::Formatter<'_> + ) -> fmt::Result { + let (mut n, mut exponent, trailing_zeros, added_precision) = { + let mut exponent = 0; + // count and remove trailing decimal zeroes + while n % 10 == 0 && n >= 10 { + n /= 10; + exponent += 1; + } + let (added_precision, subtracted_precision) = match f.precision() { + Some(fmt_prec) => { + // number of decimal digits minus 1 + let mut tmp = n; + let mut prec = 0; + while tmp >= 10 { + tmp /= 10; + prec += 1; + } + (fmt_prec.saturating_sub(prec), prec.saturating_sub(fmt_prec)) + } + None => (0, 0) + }; + for _ in 1..subtracted_precision { + n /= 10; + exponent += 1; + } + if subtracted_precision != 0 { + let rem = n % 10; + n /= 10; + exponent += 1; + // round up last digit, round to even on a tie + if rem > 5 || (rem == 5 && (n % 2 != 0 || subtracted_precision > 1 )) { + n += 1; + // if the digit is rounded to the next power + // instead adjust the exponent + if n.ilog10() > (n - 1).ilog10() { + n /= 10; + exponent += 1; + } + } + } + (n, exponent, exponent, added_precision) + }; + + // Since `curr` always decreases by the number of digits copied, this means + // that `curr >= 0`. + let mut buf = [MaybeUninit::::uninit(); 40]; + let mut curr = buf.len(); //index for buf + let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); + let lut_ptr = DEC_DIGITS_LUT.as_ptr(); + + // decode 2 chars at a time + while n >= 100 { + let d1 = ((n % 100) as usize) << 1; + curr -= 2; + // SAFETY: `d1 <= 198`, so we can copy from `lut_ptr[d1..d1 + 2]` since + // `DEC_DIGITS_LUT` has a length of 200. + unsafe { + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2); + } + n /= 100; + exponent += 2; + } + // n is <= 99, so at most 2 chars long + let mut n = n as isize; // possibly reduce 64bit math + // decode second-to-last character + if n >= 10 { + curr -= 1; + // SAFETY: Safe since `40 > curr >= 0` (see comment) + unsafe { + *buf_ptr.add(curr) = (n as u8 % 10_u8) + b'0'; + } + n /= 10; + exponent += 1; + } + // add decimal point iff >1 mantissa digit will be printed + if exponent != trailing_zeros || added_precision != 0 { + curr -= 1; + // SAFETY: Safe since `40 > curr >= 0` + unsafe { + *buf_ptr.add(curr) = b'.'; + } + } + + // SAFETY: Safe since `40 > curr >= 0` + let buf_slice = unsafe { + // decode last character + curr -= 1; + *buf_ptr.add(curr) = (n as u8) + b'0'; + + let len = buf.len() - curr as usize; + slice::from_raw_parts(buf_ptr.add(curr), len) + }; + + // stores 'e' (or 'E') and the up to 2-digit exponent + let mut exp_buf = [MaybeUninit::::uninit(); 3]; + let exp_ptr = MaybeUninit::slice_as_mut_ptr(&mut exp_buf); + // SAFETY: In either case, `exp_buf` is written within bounds and `exp_ptr[..len]` + // is contained within `exp_buf` since `len <= 3`. + let exp_slice = unsafe { + *exp_ptr.add(0) = if upper { b'E' } else { b'e' }; + let len = if exponent < 10 { + *exp_ptr.add(1) = (exponent as u8) + b'0'; + 2 + } else { + let off = exponent << 1; + ptr::copy_nonoverlapping(lut_ptr.add(off), exp_ptr.add(1), 2); + 3 + }; + slice::from_raw_parts(exp_ptr, len) + }; + + let parts = &[ + numfmt::Part::Copy(buf_slice), + numfmt::Part::Zero(added_precision), + numfmt::Part::Copy(exp_slice), + ]; + let sign = if !is_nonnegative { + "-" + } else if f.sign_plus() { + "+" + } else { + "" + }; + let formatted = numfmt::Formatted { sign, parts }; + // SAFETY: `buf_slice` and `exp_slice` contain only ASCII characters. + unsafe { f.pad_formatted_parts(&formatted) } + } + + $( + #[stable(feature = "integer_exp_format", since = "1.42.0")] + impl fmt::LowerExp for $t { + #[allow(unused_comparisons)] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let is_nonnegative = *self >= 0; + let n = if is_nonnegative { + self.$conv_fn() + } else { + // convert the negative num to positive by summing 1 to its 2s complement + (!self.$conv_fn()).wrapping_add(1) + }; + $name(n, is_nonnegative, false, f) + } + })* + $( + #[stable(feature = "integer_exp_format", since = "1.42.0")] + impl fmt::UpperExp for $t { + #[allow(unused_comparisons)] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let is_nonnegative = *self >= 0; + let n = if is_nonnegative { + self.$conv_fn() + } else { + // convert the negative num to positive by summing 1 to its 2s complement + (!self.$conv_fn()).wrapping_add(1) + }; + $name(n, is_nonnegative, true, f) + } + })* + }; +} + +impl_Debug! { + i8 i16 i32 i64 i128 isize + u8 u16 u32 u64 u128 usize +} + +// Include wasm32 in here since it doesn't reflect the native pointer size, and +// often cares strongly about getting a smaller code size. +#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))] +mod imp { + use super::*; + impl_Display!( + i8, u8, + i16, u16, + i32, u32, + i64, u64, + isize, usize, + ; as u64 via to_u64 named fmt_u64 + ); + impl_Exp!( + i8, u8, i16, u16, i32, u32, i64, u64, usize, isize + as u64 via to_u64 named exp_u64 + ); +} + +#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))] +mod imp { + use super::*; + impl_Display!( + i8, u8, + i16, u16, + i32, u32, + isize, usize, + ; as u32 via to_u32 named fmt_u32); + impl_Display!( + i64, u64, + ; as u64 via to_u64 named fmt_u64); + + impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32); + impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64); +} +impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128); + +/// Helper function for writing a u64 into `buf` going from last to first, with `curr`. +fn parse_u64_into(mut n: u64, buf: &mut [MaybeUninit; N], curr: &mut usize) { + let buf_ptr = MaybeUninit::slice_as_mut_ptr(buf); + let lut_ptr = DEC_DIGITS_LUT.as_ptr(); + assert!(*curr > 19); + + // SAFETY: + // Writes at most 19 characters into the buffer. Guaranteed that any ptr into LUT is at most + // 198, so will never OOB. There is a check above that there are at least 19 characters + // remaining. + unsafe { + if n >= 1e16 as u64 { + let to_parse = n % 1e16 as u64; + n /= 1e16 as u64; + + // Some of these are nops but it looks more elegant this way. + let d1 = ((to_parse / 1e14 as u64) % 100) << 1; + let d2 = ((to_parse / 1e12 as u64) % 100) << 1; + let d3 = ((to_parse / 1e10 as u64) % 100) << 1; + let d4 = ((to_parse / 1e8 as u64) % 100) << 1; + let d5 = ((to_parse / 1e6 as u64) % 100) << 1; + let d6 = ((to_parse / 1e4 as u64) % 100) << 1; + let d7 = ((to_parse / 1e2 as u64) % 100) << 1; + let d8 = ((to_parse / 1e0 as u64) % 100) << 1; + + *curr -= 16; + + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d3 as usize), buf_ptr.add(*curr + 4), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d4 as usize), buf_ptr.add(*curr + 6), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d5 as usize), buf_ptr.add(*curr + 8), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d6 as usize), buf_ptr.add(*curr + 10), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d7 as usize), buf_ptr.add(*curr + 12), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d8 as usize), buf_ptr.add(*curr + 14), 2); + } + if n >= 1e8 as u64 { + let to_parse = n % 1e8 as u64; + n /= 1e8 as u64; + + // Some of these are nops but it looks more elegant this way. + let d1 = ((to_parse / 1e6 as u64) % 100) << 1; + let d2 = ((to_parse / 1e4 as u64) % 100) << 1; + let d3 = ((to_parse / 1e2 as u64) % 100) << 1; + let d4 = ((to_parse / 1e0 as u64) % 100) << 1; + *curr -= 8; + + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d3 as usize), buf_ptr.add(*curr + 4), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d4 as usize), buf_ptr.add(*curr + 6), 2); + } + // `n` < 1e8 < (1 << 32) + let mut n = n as u32; + if n >= 1e4 as u32 { + let to_parse = n % 1e4 as u32; + n /= 1e4 as u32; + + let d1 = (to_parse / 100) << 1; + let d2 = (to_parse % 100) << 1; + *curr -= 4; + + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2); + } + + // `n` < 1e4 < (1 << 16) + let mut n = n as u16; + if n >= 100 { + let d1 = (n % 100) << 1; + n /= 100; + *curr -= 2; + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr), 2); + } + + // decode last 1 or 2 chars + if n < 10 { + *curr -= 1; + *buf_ptr.add(*curr) = (n as u8) + b'0'; + } else { + let d1 = n << 1; + *curr -= 2; + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr), 2); + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for u128 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt_u128(*self, true, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for i128 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let is_nonnegative = *self >= 0; + let n = if is_nonnegative { + self.to_u128() + } else { + // convert the negative num to positive by summing 1 to its 2s complement + (!self.to_u128()).wrapping_add(1) + }; + fmt_u128(n, is_nonnegative, f) + } +} + +/// Specialized optimization for u128. Instead of taking two items at a time, it splits +/// into at most 2 u64s, and then chunks by 10e16, 10e8, 10e4, 10e2, and then 10e1. +/// It also has to handle 1 last item, as 10^40 > 2^128 > 10^39, whereas +/// 10^20 > 2^64 > 10^19. +fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // 2^128 is about 3*10^38, so 39 gives an extra byte of space + let mut buf = [MaybeUninit::::uninit(); 39]; + let mut curr = buf.len(); + + let (n, rem) = udiv_1e19(n); + parse_u64_into(rem, &mut buf, &mut curr); + + if n != 0 { + // 0 pad up to point + let target = buf.len() - 19; + // SAFETY: Guaranteed that we wrote at most 19 bytes, and there must be space + // remaining since it has length 39 + unsafe { + ptr::write_bytes( + MaybeUninit::slice_as_mut_ptr(&mut buf).add(target), + b'0', + curr - target, + ); + } + curr = target; + + let (n, rem) = udiv_1e19(n); + parse_u64_into(rem, &mut buf, &mut curr); + // Should this following branch be annotated with unlikely? + if n != 0 { + let target = buf.len() - 38; + // The raw `buf_ptr` pointer is only valid until `buf` is used the next time, + // buf `buf` is not used in this scope so we are good. + let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); + // SAFETY: At this point we wrote at most 38 bytes, pad up to that point, + // There can only be at most 1 digit remaining. + unsafe { + ptr::write_bytes(buf_ptr.add(target), b'0', curr - target); + curr = target - 1; + *buf_ptr.add(curr) = (n as u8) + b'0'; + } + } + } + + // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid + // UTF-8 since `DEC_DIGITS_LUT` is + let buf_slice = unsafe { + str::from_utf8_unchecked(slice::from_raw_parts( + MaybeUninit::slice_as_mut_ptr(&mut buf).add(curr), + buf.len() - curr, + )) + }; + f.pad_integral(is_nonnegative, "", buf_slice) +} + +/// Partition of `n` into n > 1e19 and rem <= 1e19 +/// +/// Integer division algorithm is based on the following paper: +/// +/// T. Granlund and P. Montgomery, “Division by Invariant Integers Using Multiplication” +/// in Proc. of the SIGPLAN94 Conference on Programming Language Design and +/// Implementation, 1994, pp. 61–72 +/// +fn udiv_1e19(n: u128) -> (u128, u64) { + const DIV: u64 = 1e19 as u64; + const FACTOR: u128 = 156927543384667019095894735580191660403; + + let quot = if n < 1 << 83 { + ((n >> 19) as u64 / (DIV >> 19)) as u128 + } else { + u128_mulhi(n, FACTOR) >> 62 + }; + + let rem = (n - quot * DIV as u128) as u64; + (quot, rem) +} + +/// Multiply unsigned 128 bit integers, return upper 128 bits of the result +#[inline] +fn u128_mulhi(x: u128, y: u128) -> u128 { + let x_lo = x as u64; + let x_hi = (x >> 64) as u64; + let y_lo = y as u64; + let y_hi = (y >> 64) as u64; + + // handle possibility of overflow + let carry = (x_lo as u128 * y_lo as u128) >> 64; + let m = x_lo as u128 * y_hi as u128 + carry; + let high1 = m >> 64; + + let m_lo = m as u64; + let high2 = (x_hi as u128 * y_lo as u128 + m_lo as u128) >> 64; + + x_hi as u128 * y_hi as u128 + high1 + high2 +} diff --git a/CoqOfRust/core/fmt/rt.rs b/CoqOfRust/core/fmt/rt.rs new file mode 100644 index 000000000..af6f0da88 --- /dev/null +++ b/CoqOfRust/core/fmt/rt.rs @@ -0,0 +1,222 @@ +#![allow(missing_debug_implementations)] +#![unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] + +//! These are the lang items used by format_args!(). + +use super::*; +use crate::hint::unreachable_unchecked; +use crate::ptr::NonNull; + +#[lang = "format_placeholder"] +#[derive(Copy, Clone)] +pub struct Placeholder { + pub position: usize, + pub fill: char, + pub align: Alignment, + pub flags: u32, + pub precision: Count, + pub width: Count, +} + +impl Placeholder { + #[inline(always)] + pub const fn new( + position: usize, + fill: char, + align: Alignment, + flags: u32, + precision: Count, + width: Count, + ) -> Self { + Self { position, fill, align, flags, precision, width } + } +} + +#[lang = "format_alignment"] +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum Alignment { + Left, + Right, + Center, + Unknown, +} + +/// Used by [width](https://doc.rust-lang.org/std/fmt/#width) +/// and [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers. +#[lang = "format_count"] +#[derive(Copy, Clone)] +pub enum Count { + /// Specified with a literal number, stores the value + Is(usize), + /// Specified using `$` and `*` syntaxes, stores the index into `args` + Param(usize), + /// Not specified + Implied, +} + +// This needs to match the order of flags in compiler/rustc_ast_lowering/src/format.rs. +#[derive(Copy, Clone)] +pub(super) enum Flag { + SignPlus, + SignMinus, + Alternate, + SignAwareZeroPad, + DebugLowerHex, + DebugUpperHex, +} + +#[derive(Copy, Clone)] +enum ArgumentType<'a> { + Placeholder { + // INVARIANT: `formatter` has type `fn(&T, _) -> _` for some `T`, and `value` + // was derived from a `&'a T`. + value: NonNull<()>, + formatter: unsafe fn(NonNull<()>, &mut Formatter<'_>) -> Result, + _lifetime: PhantomData<&'a ()>, + }, + Count(usize), +} + +/// This struct represents a generic "argument" which is taken by format_args!(). +/// +/// This can be either a placeholder argument or a count argument. +/// * A placeholder argument contains a function to format the given value. At +/// compile time it is ensured that the function and the value have the correct +/// types, and then this struct is used to canonicalize arguments to one type. +/// Placeholder arguments are essentially an optimized partially applied formatting +/// function, equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`. +/// * A count argument contains a count for dynamic formatting parameters like +/// precision and width. +#[lang = "format_argument"] +#[derive(Copy, Clone)] +pub struct Argument<'a> { + ty: ArgumentType<'a>, +} + +#[rustc_diagnostic_item = "ArgumentMethods"] +impl Argument<'_> { + #[inline(always)] + fn new<'a, T>(x: &'a T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'a> { + Argument { + // INVARIANT: this creates an `ArgumentType<'a>` from a `&'a T` and + // a `fn(&T, ...)`, so the invariant is maintained. + ty: ArgumentType::Placeholder { + value: NonNull::from(x).cast(), + // SAFETY: function pointers always have the same layout. + formatter: unsafe { mem::transmute(f) }, + _lifetime: PhantomData, + }, + } + } + + #[inline(always)] + pub fn new_display(x: &T) -> Argument<'_> { + Self::new(x, Display::fmt) + } + #[inline(always)] + pub fn new_debug(x: &T) -> Argument<'_> { + Self::new(x, Debug::fmt) + } + #[inline(always)] + pub fn new_debug_noop(x: &T) -> Argument<'_> { + Self::new(x, |_, _| Ok(())) + } + #[inline(always)] + pub fn new_octal(x: &T) -> Argument<'_> { + Self::new(x, Octal::fmt) + } + #[inline(always)] + pub fn new_lower_hex(x: &T) -> Argument<'_> { + Self::new(x, LowerHex::fmt) + } + #[inline(always)] + pub fn new_upper_hex(x: &T) -> Argument<'_> { + Self::new(x, UpperHex::fmt) + } + #[inline(always)] + pub fn new_pointer(x: &T) -> Argument<'_> { + Self::new(x, Pointer::fmt) + } + #[inline(always)] + pub fn new_binary(x: &T) -> Argument<'_> { + Self::new(x, Binary::fmt) + } + #[inline(always)] + pub fn new_lower_exp(x: &T) -> Argument<'_> { + Self::new(x, LowerExp::fmt) + } + #[inline(always)] + pub fn new_upper_exp(x: &T) -> Argument<'_> { + Self::new(x, UpperExp::fmt) + } + #[inline(always)] + pub fn from_usize(x: &usize) -> Argument<'_> { + Argument { ty: ArgumentType::Count(*x) } + } + + /// Format this placeholder argument. + /// + /// # Safety + /// + /// This argument must actually be a placeholder argument. + /// + // FIXME: Transmuting formatter in new and indirectly branching to/calling + // it here is an explicit CFI violation. + #[allow(inline_no_sanitize)] + #[no_sanitize(cfi, kcfi)] + #[inline(always)] + pub(super) unsafe fn fmt(&self, f: &mut Formatter<'_>) -> Result { + match self.ty { + // SAFETY: + // Because of the invariant that if `formatter` had the type + // `fn(&T, _) -> _` then `value` has type `&'b T` where `'b` is + // the lifetime of the `ArgumentType`, and because references + // and `NonNull` are ABI-compatible, this is completely equivalent + // to calling the original function passed to `new` with the + // original reference, which is sound. + ArgumentType::Placeholder { formatter, value, .. } => unsafe { formatter(value, f) }, + // SAFETY: the caller promised this. + ArgumentType::Count(_) => unsafe { unreachable_unchecked() }, + } + } + + #[inline(always)] + pub(super) fn as_usize(&self) -> Option { + match self.ty { + ArgumentType::Count(count) => Some(count), + ArgumentType::Placeholder { .. } => None, + } + } + + /// Used by `format_args` when all arguments are gone after inlining, + /// when using `&[]` would incorrectly allow for a bigger lifetime. + /// + /// This fails without format argument inlining, and that shouldn't be different + /// when the argument is inlined: + /// + /// ```compile_fail,E0716 + /// let f = format_args!("{}", "a"); + /// println!("{f}"); + /// ``` + #[inline(always)] + pub fn none() -> [Self; 0] { + [] + } +} + +/// This struct represents the unsafety of constructing an `Arguments`. +/// It exists, rather than an unsafe function, in order to simplify the expansion +/// of `format_args!(..)` and reduce the scope of the `unsafe` block. +#[lang = "format_unsafe_arg"] +pub struct UnsafeArg { + _private: (), +} + +impl UnsafeArg { + /// See documentation where `UnsafeArg` is required to know when it is safe to + /// create and use `UnsafeArg`. + #[inline(always)] + pub unsafe fn new() -> Self { + Self { _private: () } + } +} diff --git a/CoqOfRust/core/future/async_drop.rs b/CoqOfRust/core/future/async_drop.rs new file mode 100644 index 000000000..7de5fe67c --- /dev/null +++ b/CoqOfRust/core/future/async_drop.rs @@ -0,0 +1,283 @@ +#![unstable(feature = "async_drop", issue = "126482")] + +use crate::fmt; +use crate::future::{Future, IntoFuture}; +use crate::intrinsics::discriminant_value; +use crate::marker::{DiscriminantKind, PhantomPinned}; +use crate::mem::MaybeUninit; +use crate::pin::Pin; +use crate::task::{Context, Poll, ready}; + +/// Asynchronously drops a value by running `AsyncDrop::async_drop` +/// on a value and its fields recursively. +#[unstable(feature = "async_drop", issue = "126482")] +pub fn async_drop(value: T) -> AsyncDropOwning { + AsyncDropOwning { value: MaybeUninit::new(value), dtor: None, _pinned: PhantomPinned } +} + +/// A future returned by the [`async_drop`]. +#[unstable(feature = "async_drop", issue = "126482")] +pub struct AsyncDropOwning { + value: MaybeUninit, + dtor: Option>, + _pinned: PhantomPinned, +} + +#[unstable(feature = "async_drop", issue = "126482")] +impl fmt::Debug for AsyncDropOwning { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsyncDropOwning").finish_non_exhaustive() + } +} + +#[unstable(feature = "async_drop", issue = "126482")] +impl Future for AsyncDropOwning { + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // SAFETY: Self is pinned thus it is ok to store references to self + unsafe { + let this = self.get_unchecked_mut(); + let dtor = Pin::new_unchecked( + this.dtor.get_or_insert_with(|| async_drop_in_place(this.value.as_mut_ptr())), + ); + // AsyncDestuctors are idempotent so Self gets idempotency as well + dtor.poll(cx) + } + } +} + +#[lang = "async_drop_in_place"] +#[allow(unconditional_recursion)] +// FIXME: Consider if `#[rustc_diagnostic_item = "ptr_drop_in_place"]` is needed? +unsafe fn async_drop_in_place_raw( + to_drop: *mut T, +) -> ::AsyncDestructor { + // Code here does not matter - this is replaced by the + // real async drop glue constructor by the compiler. + + // SAFETY: see comment above + unsafe { async_drop_in_place_raw(to_drop) } +} + +/// Creates the asynchronous destructor of the pointed-to value. +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `to_drop` must be [valid](crate::ptr#safety) for both reads and writes. +/// +/// * `to_drop` must be properly aligned, even if `T` has size 0. +/// +/// * `to_drop` must be nonnull, even if `T` has size 0. +/// +/// * The value `to_drop` points to must be valid for async dropping, +/// which may mean it must uphold additional invariants. These +/// invariants depend on the type of the value being dropped. For +/// instance, when dropping a Box, the box's pointer to the heap must +/// be valid. +/// +/// * While `async_drop_in_place` is executing or the returned async +/// destructor is alive, the only way to access parts of `to_drop` +/// is through the `self: Pin<&mut Self>` references supplied to +/// the `AsyncDrop::async_drop` methods that `async_drop_in_place` +/// or `AsyncDropInPlace::poll` invokes. This usually means the +/// returned future stores the `to_drop` pointer and user is required +/// to guarantee that dropped value doesn't move. +/// +#[unstable(feature = "async_drop", issue = "126482")] +pub unsafe fn async_drop_in_place(to_drop: *mut T) -> AsyncDropInPlace { + // SAFETY: `async_drop_in_place_raw` has the same safety requirements + unsafe { AsyncDropInPlace(async_drop_in_place_raw(to_drop)) } +} + +/// A future returned by the [`async_drop_in_place`]. +#[unstable(feature = "async_drop", issue = "126482")] +pub struct AsyncDropInPlace(::AsyncDestructor); + +#[unstable(feature = "async_drop", issue = "126482")] +impl fmt::Debug for AsyncDropInPlace { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AsyncDropInPlace").finish_non_exhaustive() + } +} + +#[unstable(feature = "async_drop", issue = "126482")] +impl Future for AsyncDropInPlace { + type Output = (); + + #[inline(always)] + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // SAFETY: This code simply forwards poll call to the inner future + unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) }.poll(cx) + } +} + +// FIXME(zetanumbers): Add same restrictions on AsyncDrop impls as +// with Drop impls +/// Custom code within the asynchronous destructor. +#[unstable(feature = "async_drop", issue = "126482")] +#[lang = "async_drop"] +pub trait AsyncDrop { + /// A future returned by the [`AsyncDrop::async_drop`] to be part + /// of the async destructor. + #[unstable(feature = "async_drop", issue = "126482")] + type Dropper<'a>: Future + where + Self: 'a; + + /// Constructs the asynchronous destructor for this type. + #[unstable(feature = "async_drop", issue = "126482")] + fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_>; +} + +#[lang = "async_destruct"] +#[rustc_deny_explicit_impl(implement_via_object = false)] +trait AsyncDestruct { + type AsyncDestructor: Future; +} + +/// Basically calls `AsyncDrop::async_drop` with pointer. Used to simplify +/// generation of the code for `async_drop_in_place_raw` +#[lang = "surface_async_drop_in_place"] +async unsafe fn surface_async_drop_in_place(ptr: *mut T) { + // SAFETY: We call this from async drop `async_drop_in_place_raw` + // which has the same safety requirements + unsafe { ::async_drop(Pin::new_unchecked(&mut *ptr)).await } +} + +/// Basically calls `Drop::drop` with pointer. Used to simplify generation +/// of the code for `async_drop_in_place_raw` +#[allow(drop_bounds)] +#[lang = "async_drop_surface_drop_in_place"] +async unsafe fn surface_drop_in_place(ptr: *mut T) { + // SAFETY: We call this from async drop `async_drop_in_place_raw` + // which has the same safety requirements + unsafe { crate::ops::fallback_surface_drop(&mut *ptr) } +} + +/// Wraps a future to continue outputting `Poll::Ready(())` once after +/// wrapped future completes by returning `Poll::Ready(())` on poll. This +/// is useful for constructing async destructors to guarantee this +/// "fuse" property +// +// FIXME: Consider optimizing combinators to not have to use fuse in majority +// of cases, perhaps by adding `#[(rustc_)idempotent(_future)]` attribute for +// async functions and blocks with the unit return type. However current layout +// optimizations currently encode `None` case into the async block's discriminant. +struct Fuse { + inner: Option, +} + +#[lang = "async_drop_fuse"] +fn fuse(inner: T) -> Fuse { + Fuse { inner: Some(inner) } +} + +impl Future for Fuse +where + T: Future, +{ + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // SAFETY: pin projection into `self.inner` + unsafe { + let this = self.get_unchecked_mut(); + if let Some(inner) = &mut this.inner { + ready!(Pin::new_unchecked(inner).poll(cx)); + this.inner = None; + } + } + Poll::Ready(()) + } +} + +/// Async destructor for arrays and slices. +#[lang = "async_drop_slice"] +async unsafe fn slice(s: *mut [T]) { + let len = s.len(); + let ptr = s.as_mut_ptr(); + for i in 0..len { + // SAFETY: we iterate over elements of `s` slice + unsafe { async_drop_in_place_raw(ptr.add(i)).await } + } +} + +/// Constructs a chain of two futures, which awaits them sequentially as +/// a future. +#[lang = "async_drop_chain"] +async fn chain(first: F, last: G) +where + F: IntoFuture, + G: IntoFuture, +{ + first.await; + last.await; +} + +/// Basically a lazy version of `async_drop_in_place`. Returns a future +/// that would call `AsyncDrop::async_drop` on a first poll. +/// +/// # Safety +/// +/// Same as `async_drop_in_place` except is lazy to avoid creating +/// multiple mutable references. +#[lang = "async_drop_defer"] +async unsafe fn defer(to_drop: *mut T) { + // SAFETY: same safety requirements as `async_drop_in_place` + unsafe { async_drop_in_place(to_drop) }.await +} + +/// If `T`'s discriminant is equal to the stored one then awaits `M` +/// otherwise awaits the `O`. +/// +/// # Safety +/// +/// Users should carefully manage the returned future, since it would +/// try creating an immutable reference from `this` and get pointee's +/// discriminant. +// FIXME(zetanumbers): Send and Sync impls +#[lang = "async_drop_either"] +async unsafe fn either, M: IntoFuture, T>( + other: O, + matched: M, + this: *mut T, + discr: ::Discriminant, +) { + // SAFETY: Guaranteed by the safety section of this funtion's documentation + if unsafe { discriminant_value(&*this) } == discr { + drop(other); + matched.await + } else { + drop(matched); + other.await + } +} + +#[lang = "async_drop_deferred_drop_in_place"] +async unsafe fn deferred_drop_in_place(to_drop: *mut T) { + // SAFETY: same safety requirements as with drop_in_place (implied by + // function's name) + unsafe { crate::ptr::drop_in_place(to_drop) } +} + +/// Used for noop async destructors. We don't use [`core::future::Ready`] +/// because it panics after its second poll, which could be potentially +/// bad if that would happen during the cleanup. +#[derive(Clone, Copy)] +struct Noop; + +#[lang = "async_drop_noop"] +fn noop() -> Noop { + Noop +} + +impl Future for Noop { + type Output = (); + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + Poll::Ready(()) + } +} diff --git a/CoqOfRust/core/future/future.rs b/CoqOfRust/core/future/future.rs new file mode 100644 index 000000000..cfbd88bbe --- /dev/null +++ b/CoqOfRust/core/future/future.rs @@ -0,0 +1,126 @@ +#![stable(feature = "futures_api", since = "1.36.0")] + +use crate::ops; +use crate::pin::Pin; +use crate::task::{Context, Poll}; + +/// A future represents an asynchronous computation obtained by use of [`async`]. +/// +/// A future is a value that might not have finished computing yet. This kind of +/// "asynchronous value" makes it possible for a thread to continue doing useful +/// work while it waits for the value to become available. +/// +/// # The `poll` method +/// +/// The core method of future, `poll`, *attempts* to resolve the future into a +/// final value. This method does not block if the value is not ready. Instead, +/// the current task is scheduled to be woken up when it's possible to make +/// further progress by `poll`ing again. The `context` passed to the `poll` +/// method can provide a [`Waker`], which is a handle for waking up the current +/// task. +/// +/// When using a future, you generally won't call `poll` directly, but instead +/// `.await` the value. +/// +/// [`async`]: ../../std/keyword.async.html +/// [`Waker`]: crate::task::Waker +#[doc(notable_trait)] +#[doc(search_unbox)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +#[stable(feature = "futures_api", since = "1.36.0")] +#[lang = "future_trait"] +#[diagnostic::on_unimplemented( + label = "`{Self}` is not a future", + message = "`{Self}` is not a future" +)] +pub trait Future { + /// The type of value produced on completion. + #[stable(feature = "futures_api", since = "1.36.0")] + #[lang = "future_output"] + type Output; + + /// Attempts to resolve the future to a final value, registering + /// the current task for wakeup if the value is not yet available. + /// + /// # Return value + /// + /// This function returns: + /// + /// - [`Poll::Pending`] if the future is not ready yet + /// - [`Poll::Ready(val)`] with the result `val` of this future if it + /// finished successfully. + /// + /// Once a future has finished, clients should not `poll` it again. + /// + /// When a future is not ready yet, `poll` returns `Poll::Pending` and + /// stores a clone of the [`Waker`] copied from the current [`Context`]. + /// This [`Waker`] is then woken once the future can make progress. + /// For example, a future waiting for a socket to become + /// readable would call `.clone()` on the [`Waker`] and store it. + /// When a signal arrives elsewhere indicating that the socket is readable, + /// [`Waker::wake`] is called and the socket future's task is awoken. + /// Once a task has been woken up, it should attempt to `poll` the future + /// again, which may or may not produce a final value. + /// + /// Note that on multiple calls to `poll`, only the [`Waker`] from the + /// [`Context`] passed to the most recent call should be scheduled to + /// receive a wakeup. + /// + /// # Runtime characteristics + /// + /// Futures alone are *inert*; they must be *actively* `poll`ed to make + /// progress, meaning that each time the current task is woken up, it should + /// actively re-`poll` pending futures that it still has an interest in. + /// + /// The `poll` function is not called repeatedly in a tight loop -- instead, + /// it should only be called when the future indicates that it is ready to + /// make progress (by calling `wake()`). If you're familiar with the + /// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures + /// typically do *not* suffer the same problems of "all wakeups must poll + /// all events"; they are more like `epoll(4)`. + /// + /// An implementation of `poll` should strive to return quickly, and should + /// not block. Returning quickly prevents unnecessarily clogging up + /// threads or event loops. If it is known ahead of time that a call to + /// `poll` may end up taking a while, the work should be offloaded to a + /// thread pool (or something similar) to ensure that `poll` can return + /// quickly. + /// + /// # Panics + /// + /// Once a future has completed (returned `Ready` from `poll`), calling its + /// `poll` method again may panic, block forever, or cause other kinds of + /// problems; the `Future` trait places no requirements on the effects of + /// such a call. However, as the `poll` method is not marked `unsafe`, + /// Rust's usual rules apply: calls must never cause undefined behavior + /// (memory corruption, incorrect use of `unsafe` functions, or the like), + /// regardless of the future's state. + /// + /// [`Poll::Ready(val)`]: Poll::Ready + /// [`Waker`]: crate::task::Waker + /// [`Waker::wake`]: crate::task::Waker::wake + #[lang = "poll"] + #[stable(feature = "futures_api", since = "1.36.0")] + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; +} + +#[stable(feature = "futures_api", since = "1.36.0")] +impl Future for &mut F { + type Output = F::Output; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + F::poll(Pin::new(&mut **self), cx) + } +} + +#[stable(feature = "futures_api", since = "1.36.0")] +impl

Future for Pin

+where + P: ops::DerefMut, +{ + type Output = <

::Target as Future>::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + ::poll(self.as_deref_mut(), cx) + } +} diff --git a/CoqOfRust/core/future/into_future.rs b/CoqOfRust/core/future/into_future.rs new file mode 100644 index 000000000..aa546b940 --- /dev/null +++ b/CoqOfRust/core/future/into_future.rs @@ -0,0 +1,145 @@ +use crate::future::Future; + +/// Conversion into a `Future`. +/// +/// By implementing `IntoFuture` for a type, you define how it will be +/// converted to a future. +/// +/// # `.await` desugaring +/// +/// The `.await` keyword desugars into a call to `IntoFuture::into_future` +/// first before polling the future to completion. `IntoFuture` is implemented +/// for all `T: Future` which means the `into_future` method will be available +/// on all futures. +/// +/// ```no_run +/// use std::future::IntoFuture; +/// +/// # async fn foo() { +/// let v = async { "meow" }; +/// let mut fut = v.into_future(); +/// assert_eq!("meow", fut.await); +/// # } +/// ``` +/// +/// # Async builders +/// +/// When implementing futures manually there will often be a choice between +/// implementing `Future` or `IntoFuture` for a type. Implementing `Future` is a +/// good choice in most cases. But implementing `IntoFuture` is most useful when +/// implementing "async builder" types, which allow their values to be modified +/// multiple times before being `.await`ed. +/// +/// ```rust +/// use std::future::{ready, Ready, IntoFuture}; +/// +/// /// Eventually multiply two numbers +/// pub struct Multiply { +/// num: u16, +/// factor: u16, +/// } +/// +/// impl Multiply { +/// /// Constructs a new instance of `Multiply`. +/// pub fn new(num: u16, factor: u16) -> Self { +/// Self { num, factor } +/// } +/// +/// /// Set the number to multiply by the factor. +/// pub fn number(mut self, num: u16) -> Self { +/// self.num = num; +/// self +/// } +/// +/// /// Set the factor to multiply the number with. +/// pub fn factor(mut self, factor: u16) -> Self { +/// self.factor = factor; +/// self +/// } +/// } +/// +/// impl IntoFuture for Multiply { +/// type Output = u16; +/// type IntoFuture = Ready; +/// +/// fn into_future(self) -> Self::IntoFuture { +/// ready(self.num * self.factor) +/// } +/// } +/// +/// // NOTE: Rust does not yet have an `async fn main` function, that functionality +/// // currently only exists in the ecosystem. +/// async fn run() { +/// let num = Multiply::new(0, 0) // initialize the builder to number: 0, factor: 0 +/// .number(2) // change the number to 2 +/// .factor(2) // change the factor to 2 +/// .await; // convert to future and .await +/// +/// assert_eq!(num, 4); +/// } +/// ``` +/// +/// # Usage in trait bounds +/// +/// Using `IntoFuture` in trait bounds allows a function to be generic over both +/// `Future` and `IntoFuture`. This is convenient for users of the function, so +/// when they are using it they don't have to make an extra call to +/// `IntoFuture::into_future` to obtain an instance of `Future`: +/// +/// ```rust +/// use std::future::IntoFuture; +/// +/// /// Converts the output of a future to a string. +/// async fn fut_to_string(fut: Fut) -> String +/// where +/// Fut: IntoFuture, +/// Fut::Output: std::fmt::Debug, +/// { +/// format!("{:?}", fut.await) +/// } +/// ``` +#[stable(feature = "into_future", since = "1.64.0")] +#[rustc_diagnostic_item = "IntoFuture"] +#[diagnostic::on_unimplemented( + label = "`{Self}` is not a future", + message = "`{Self}` is not a future", + note = "{Self} must be a future or must implement `IntoFuture` to be awaited" +)] +pub trait IntoFuture { + /// The output that the future will produce on completion. + #[stable(feature = "into_future", since = "1.64.0")] + type Output; + + /// Which kind of future are we turning this into? + #[stable(feature = "into_future", since = "1.64.0")] + type IntoFuture: Future; + + /// Creates a future from a value. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ```no_run + /// use std::future::IntoFuture; + /// + /// # async fn foo() { + /// let v = async { "meow" }; + /// let mut fut = v.into_future(); + /// assert_eq!("meow", fut.await); + /// # } + /// ``` + #[stable(feature = "into_future", since = "1.64.0")] + #[lang = "into_future"] + fn into_future(self) -> Self::IntoFuture; +} + +#[stable(feature = "into_future", since = "1.64.0")] +impl IntoFuture for F { + type Output = F::Output; + type IntoFuture = F; + + fn into_future(self) -> Self::IntoFuture { + self + } +} diff --git a/CoqOfRust/core/future/join.rs b/CoqOfRust/core/future/join.rs new file mode 100644 index 000000000..18bc8d965 --- /dev/null +++ b/CoqOfRust/core/future/join.rs @@ -0,0 +1,193 @@ +#![allow(unused_imports, unused_macros)] // items are used by the macro + +use crate::cell::UnsafeCell; +use crate::future::{Future, poll_fn}; +use crate::mem; +use crate::pin::Pin; +use crate::task::{Context, Poll, ready}; + +/// Polls multiple futures simultaneously, returning a tuple +/// of all results once complete. +/// +/// While `join!(a, b).await` is similar to `(a.await, b.await)`, +/// `join!` polls both futures concurrently and is therefore more efficient. +/// +/// # Examples +/// +/// ``` +/// #![feature(future_join)] +/// +/// use std::future::join; +/// +/// async fn one() -> usize { 1 } +/// async fn two() -> usize { 2 } +/// +/// # let _ = async { +/// let x = join!(one(), two()).await; +/// assert_eq!(x, (1, 2)); +/// # }; +/// ``` +/// +/// `join!` is variadic, so you can pass any number of futures: +/// +/// ``` +/// #![feature(future_join)] +/// +/// use std::future::join; +/// +/// async fn one() -> usize { 1 } +/// async fn two() -> usize { 2 } +/// async fn three() -> usize { 3 } +/// +/// # let _ = async { +/// let x = join!(one(), two(), three()).await; +/// assert_eq!(x, (1, 2, 3)); +/// # }; +/// ``` +#[unstable(feature = "future_join", issue = "91642")] +pub macro join( $($fut:expr),+ $(,)? ) { + // Funnel through an internal macro not to leak implementation details. + join_internal! { + current_position: [] + futures_and_positions: [] + munching: [ $($fut)+ ] + } +} + +// FIXME(danielhenrymantilla): a private macro should need no stability guarantee. +#[unstable(feature = "future_join", issue = "91642")] +/// To be able to *name* the i-th future in the tuple (say we want the .4-th), +/// the following trick will be used: `let (_, _, _, _, it, ..) = tuple;` +/// In order to do that, we need to generate a `i`-long repetition of `_`, +/// for each i-th fut. Hence the recursive muncher approach. +macro join_internal { + // Recursion step: map each future with its "position" (underscore count). + ( + // Accumulate a token for each future that has been expanded: "_ _ _". + current_position: [ + $($underscores:tt)* + ] + // Accumulate Futures and their positions in the tuple: `_0th () _1st ( _ ) …`. + futures_and_positions: [ + $($acc:tt)* + ] + // Munch one future. + munching: [ + $current:tt + $($rest:tt)* + ] + ) => ( + join_internal! { + current_position: [ + $($underscores)* + _ + ] + futures_and_positions: [ + $($acc)* + $current ( $($underscores)* ) + ] + munching: [ + $($rest)* + ] + } + ), + + // End of recursion: generate the output future. + ( + current_position: $_:tt + futures_and_positions: [ + $( + $fut_expr:tt ( $($pos:tt)* ) + )* + ] + // Nothing left to munch. + munching: [] + ) => ( + match ( $( MaybeDone::Future($fut_expr), )* ) { futures => async { + let mut futures = futures; + // SAFETY: this is `pin_mut!`. + let mut futures = unsafe { Pin::new_unchecked(&mut futures) }; + poll_fn(move |cx| { + let mut done = true; + // For each `fut`, pin-project to it, and poll it. + $( + // SAFETY: pinning projection + let fut = unsafe { + futures.as_mut().map_unchecked_mut(|it| { + let ( $($pos,)* fut, .. ) = it; + fut + }) + }; + // Despite how tempting it may be to `let () = ready!(fut.poll(cx));` + // doing so would defeat the point of `join!`: to start polling eagerly all + // of the futures, to allow parallelizing the waits. + done &= fut.poll(cx).is_ready(); + )* + if !done { + return Poll::Pending; + } + // All ready; time to extract all the outputs. + + // SAFETY: `.take_output()` does not break the `Pin` invariants for that `fut`. + let futures = unsafe { + futures.as_mut().get_unchecked_mut() + }; + Poll::Ready( + ($( + { + let ( $($pos,)* fut, .. ) = &mut *futures; + fut.take_output().unwrap() + } + ),*) // <- no trailing comma since we don't want 1-tuples. + ) + }).await + }} + ), +} + +/// Future used by `join!` that stores it's output to +/// be later taken and doesn't panic when polled after ready. +/// +/// This type is public in a private module for use by the macro. +#[allow(missing_debug_implementations)] +#[unstable(feature = "future_join", issue = "91642")] +pub enum MaybeDone { + Future(F), + Done(F::Output), + Taken, +} + +#[unstable(feature = "future_join", issue = "91642")] +impl MaybeDone { + pub fn take_output(&mut self) -> Option { + match *self { + MaybeDone::Done(_) => match mem::replace(self, Self::Taken) { + MaybeDone::Done(val) => Some(val), + _ => unreachable!(), + }, + _ => None, + } + } +} + +#[unstable(feature = "future_join", issue = "91642")] +impl Future for MaybeDone { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // SAFETY: pinning in structural for `f` + unsafe { + // Do not mix match ergonomics with unsafe. + match *self.as_mut().get_unchecked_mut() { + MaybeDone::Future(ref mut f) => { + let val = ready!(Pin::new_unchecked(f).poll(cx)); + self.set(Self::Done(val)); + } + MaybeDone::Done(_) => {} + MaybeDone::Taken => unreachable!(), + } + } + + Poll::Ready(()) + } +} diff --git a/CoqOfRust/core/future/mod.rs b/CoqOfRust/core/future/mod.rs new file mode 100644 index 000000000..e5a368796 --- /dev/null +++ b/CoqOfRust/core/future/mod.rs @@ -0,0 +1,68 @@ +#![stable(feature = "futures_api", since = "1.36.0")] + +//! Asynchronous basic functionality. +//! +//! Please see the fundamental [`async`] and [`await`] keywords and the [async book] +//! for more information on asynchronous programming in Rust. +//! +//! [`async`]: ../../std/keyword.async.html +//! [`await`]: ../../std/keyword.await.html +//! [async book]: https://rust-lang.github.io/async-book/ + +use crate::ptr::NonNull; +use crate::task::Context; + +mod async_drop; +mod future; +mod into_future; +mod join; +mod pending; +mod poll_fn; +mod ready; + +#[unstable(feature = "async_drop", issue = "126482")] +pub use async_drop::{AsyncDrop, AsyncDropInPlace, async_drop, async_drop_in_place}; +#[stable(feature = "into_future", since = "1.64.0")] +pub use into_future::IntoFuture; +#[stable(feature = "future_readiness_fns", since = "1.48.0")] +pub use pending::{Pending, pending}; +#[stable(feature = "future_poll_fn", since = "1.64.0")] +pub use poll_fn::{PollFn, poll_fn}; +#[stable(feature = "future_readiness_fns", since = "1.48.0")] +pub use ready::{Ready, ready}; + +#[stable(feature = "futures_api", since = "1.36.0")] +pub use self::future::Future; +#[unstable(feature = "future_join", issue = "91642")] +pub use self::join::join; + +/// This type is needed because: +/// +/// a) Coroutines cannot implement `for<'a, 'b> Coroutine<&'a mut Context<'b>>`, so we need to pass +/// a raw pointer (see ). +/// b) Raw pointers and `NonNull` aren't `Send` or `Sync`, so that would make every single future +/// non-Send/Sync as well, and we don't want that. +/// +/// It also simplifies the HIR lowering of `.await`. +#[lang = "ResumeTy"] +#[doc(hidden)] +#[unstable(feature = "gen_future", issue = "50547")] +#[derive(Debug, Copy, Clone)] +pub struct ResumeTy(NonNull>); + +#[unstable(feature = "gen_future", issue = "50547")] +unsafe impl Send for ResumeTy {} + +#[unstable(feature = "gen_future", issue = "50547")] +unsafe impl Sync for ResumeTy {} + +#[lang = "get_context"] +#[doc(hidden)] +#[unstable(feature = "gen_future", issue = "50547")] +#[must_use] +#[inline] +pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> { + // SAFETY: the caller must guarantee that `cx.0` is a valid pointer + // that fulfills all the requirements for a mutable reference. + unsafe { &mut *cx.0.as_ptr().cast() } +} diff --git a/CoqOfRust/core/future/pending.rs b/CoqOfRust/core/future/pending.rs new file mode 100644 index 000000000..2877e66ec --- /dev/null +++ b/CoqOfRust/core/future/pending.rs @@ -0,0 +1,58 @@ +use crate::fmt::{self, Debug}; +use crate::future::Future; +use crate::marker; +use crate::pin::Pin; +use crate::task::{Context, Poll}; + +/// Creates a future which never resolves, representing a computation that never +/// finishes. +/// +/// This `struct` is created by [`pending()`]. See its +/// documentation for more. +#[stable(feature = "future_readiness_fns", since = "1.48.0")] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Pending { + _data: marker::PhantomData T>, +} + +/// Creates a future which never resolves, representing a computation that never +/// finishes. +/// +/// # Examples +/// +/// ```no_run +/// use std::future; +/// +/// # async fn run() { +/// let future = future::pending(); +/// let () = future.await; +/// unreachable!(); +/// # } +/// ``` +#[stable(feature = "future_readiness_fns", since = "1.48.0")] +pub fn pending() -> Pending { + Pending { _data: marker::PhantomData } +} + +#[stable(feature = "future_readiness_fns", since = "1.48.0")] +impl Future for Pending { + type Output = T; + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + Poll::Pending + } +} + +#[stable(feature = "future_readiness_fns", since = "1.48.0")] +impl Debug for Pending { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Pending").finish() + } +} + +#[stable(feature = "future_readiness_fns", since = "1.48.0")] +impl Clone for Pending { + fn clone(&self) -> Self { + pending() + } +} diff --git a/CoqOfRust/core/future/poll_fn.rs b/CoqOfRust/core/future/poll_fn.rs new file mode 100644 index 000000000..d27a9dfc1 --- /dev/null +++ b/CoqOfRust/core/future/poll_fn.rs @@ -0,0 +1,153 @@ +use crate::fmt; +use crate::future::Future; +use crate::pin::Pin; +use crate::task::{Context, Poll}; + +/// Creates a future that wraps a function returning [`Poll`]. +/// +/// Polling the future delegates to the wrapped function. If the returned future is pinned, then the +/// captured environment of the wrapped function is also pinned in-place, so as long as the closure +/// does not move out of its captures it can soundly create pinned references to them. +/// +/// # Examples +/// +/// ``` +/// # async fn run() { +/// use core::future::poll_fn; +/// use std::task::{Context, Poll}; +/// +/// fn read_line(_cx: &mut Context<'_>) -> Poll { +/// Poll::Ready("Hello, World!".into()) +/// } +/// +/// let read_future = poll_fn(read_line); +/// assert_eq!(read_future.await, "Hello, World!".to_owned()); +/// # } +/// ``` +/// +/// ## Capturing a pinned state +/// +/// Example of a closure wrapping inner futures: +/// +/// ``` +/// # async fn run() { +/// use core::future::{self, Future}; +/// use core::task::Poll; +/// +/// /// Resolves to the first future that completes. In the event of a tie, `a` wins. +/// fn naive_select( +/// a: impl Future, +/// b: impl Future, +/// ) -> impl Future +/// { +/// let (mut a, mut b) = (Box::pin(a), Box::pin(b)); +/// future::poll_fn(move |cx| { +/// if let Poll::Ready(r) = a.as_mut().poll(cx) { +/// Poll::Ready(r) +/// } else if let Poll::Ready(r) = b.as_mut().poll(cx) { +/// Poll::Ready(r) +/// } else { +/// Poll::Pending +/// } +/// }) +/// } +/// +/// let a = async { 42 }; +/// let b = future::pending(); +/// let v = naive_select(a, b).await; +/// assert_eq!(v, 42); +/// +/// let a = future::pending(); +/// let b = async { 27 }; +/// let v = naive_select(a, b).await; +/// assert_eq!(v, 27); +/// +/// let a = async { 42 }; +/// let b = async { 27 }; +/// let v = naive_select(a, b).await; +/// assert_eq!(v, 42); // biased towards `a` in case of tie! +/// # } +/// ``` +/// +/// This time without [`Box::pin`]ning: +/// +/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin +/// +/// ``` +/// # async fn run() { +/// use core::future::{self, Future}; +/// use core::pin::pin; +/// use core::task::Poll; +/// +/// /// Resolves to the first future that completes. In the event of a tie, `a` wins. +/// fn naive_select( +/// a: impl Future, +/// b: impl Future, +/// ) -> impl Future +/// { +/// async { +/// let (mut a, mut b) = (pin!(a), pin!(b)); +/// future::poll_fn(move |cx| { +/// if let Poll::Ready(r) = a.as_mut().poll(cx) { +/// Poll::Ready(r) +/// } else if let Poll::Ready(r) = b.as_mut().poll(cx) { +/// Poll::Ready(r) +/// } else { +/// Poll::Pending +/// } +/// }).await +/// } +/// } +/// +/// let a = async { 42 }; +/// let b = future::pending(); +/// let v = naive_select(a, b).await; +/// assert_eq!(v, 42); +/// # } +/// ``` +/// +/// - Notice how, by virtue of being in an `async` context, we have been able to make the [`pin!`] +/// macro work, thereby avoiding any need for the `unsafe` +/// [Pin::new_unchecked](&mut fut) constructor. +/// +/// [`pin!`]: crate::pin::pin! +#[stable(feature = "future_poll_fn", since = "1.64.0")] +pub fn poll_fn(f: F) -> PollFn +where + F: FnMut(&mut Context<'_>) -> Poll, +{ + PollFn { f } +} + +/// A Future that wraps a function returning [`Poll`]. +/// +/// This `struct` is created by [`poll_fn()`]. See its +/// documentation for more. +#[must_use = "futures do nothing unless you `.await` or poll them"] +#[stable(feature = "future_poll_fn", since = "1.64.0")] +pub struct PollFn { + f: F, +} + +#[stable(feature = "future_poll_fn", since = "1.64.0")] +impl Unpin for PollFn {} + +#[stable(feature = "future_poll_fn", since = "1.64.0")] +impl fmt::Debug for PollFn { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("PollFn").finish() + } +} + +#[stable(feature = "future_poll_fn", since = "1.64.0")] +impl Future for PollFn +where + F: FnMut(&mut Context<'_>) -> Poll, +{ + type Output = T; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // SAFETY: We are not moving out of the pinned field. + (unsafe { &mut self.get_unchecked_mut().f })(cx) + } +} diff --git a/CoqOfRust/core/future/ready.rs b/CoqOfRust/core/future/ready.rs new file mode 100644 index 000000000..b562ad4d8 --- /dev/null +++ b/CoqOfRust/core/future/ready.rs @@ -0,0 +1,69 @@ +use crate::future::Future; +use crate::pin::Pin; +use crate::task::{Context, Poll}; + +/// A future that is immediately ready with a value. +/// +/// This `struct` is created by [`ready()`]. See its +/// documentation for more. +#[stable(feature = "future_readiness_fns", since = "1.48.0")] +#[derive(Debug, Clone)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Ready(Option); + +#[stable(feature = "future_readiness_fns", since = "1.48.0")] +impl Unpin for Ready {} + +#[stable(feature = "future_readiness_fns", since = "1.48.0")] +impl Future for Ready { + type Output = T; + + #[inline] + fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Ready(self.0.take().expect("`Ready` polled after completion")) + } +} + +impl Ready { + /// Consumes the `Ready`, returning the wrapped value. + /// + /// # Panics + /// + /// Will panic if this [`Ready`] was already polled to completion. + /// + /// # Examples + /// + /// ``` + /// use std::future; + /// + /// let a = future::ready(1); + /// assert_eq!(a.into_inner(), 1); + /// ``` + #[stable(feature = "ready_into_inner", since = "1.82.0")] + #[must_use] + #[inline] + pub fn into_inner(self) -> T { + self.0.expect("Called `into_inner()` on `Ready` after completion") + } +} + +/// Creates a future that is immediately ready with a value. +/// +/// Futures created through this function are functionally similar to those +/// created through `async {}`. The main difference is that futures created +/// through this function are named and implement `Unpin`. +/// +/// # Examples +/// +/// ``` +/// use std::future; +/// +/// # async fn run() { +/// let a = future::ready(1); +/// assert_eq!(a.await, 1); +/// # } +/// ``` +#[stable(feature = "future_readiness_fns", since = "1.48.0")] +pub fn ready(t: T) -> Ready { + Ready(Some(t)) +} diff --git a/CoqOfRust/core/hash/mod.rs b/CoqOfRust/core/hash/mod.rs new file mode 100644 index 000000000..84bbf985e --- /dev/null +++ b/CoqOfRust/core/hash/mod.rs @@ -0,0 +1,981 @@ +//! Generic hashing support. +//! +//! This module provides a generic way to compute the [hash] of a value. +//! Hashes are most commonly used with [`HashMap`] and [`HashSet`]. +//! +//! [hash]: https://en.wikipedia.org/wiki/Hash_function +//! [`HashMap`]: ../../std/collections/struct.HashMap.html +//! [`HashSet`]: ../../std/collections/struct.HashSet.html +//! +//! The simplest way to make a type hashable is to use `#[derive(Hash)]`: +//! +//! # Examples +//! +//! ```rust +//! use std::hash::{DefaultHasher, Hash, Hasher}; +//! +//! #[derive(Hash)] +//! struct Person { +//! id: u32, +//! name: String, +//! phone: u64, +//! } +//! +//! let person1 = Person { +//! id: 5, +//! name: "Janet".to_string(), +//! phone: 555_666_7777, +//! }; +//! let person2 = Person { +//! id: 5, +//! name: "Bob".to_string(), +//! phone: 555_666_7777, +//! }; +//! +//! assert!(calculate_hash(&person1) != calculate_hash(&person2)); +//! +//! fn calculate_hash(t: &T) -> u64 { +//! let mut s = DefaultHasher::new(); +//! t.hash(&mut s); +//! s.finish() +//! } +//! ``` +//! +//! If you need more control over how a value is hashed, you need to implement +//! the [`Hash`] trait: +//! +//! ```rust +//! use std::hash::{DefaultHasher, Hash, Hasher}; +//! +//! struct Person { +//! id: u32, +//! # #[allow(dead_code)] +//! name: String, +//! phone: u64, +//! } +//! +//! impl Hash for Person { +//! fn hash(&self, state: &mut H) { +//! self.id.hash(state); +//! self.phone.hash(state); +//! } +//! } +//! +//! let person1 = Person { +//! id: 5, +//! name: "Janet".to_string(), +//! phone: 555_666_7777, +//! }; +//! let person2 = Person { +//! id: 5, +//! name: "Bob".to_string(), +//! phone: 555_666_7777, +//! }; +//! +//! assert_eq!(calculate_hash(&person1), calculate_hash(&person2)); +//! +//! fn calculate_hash(t: &T) -> u64 { +//! let mut s = DefaultHasher::new(); +//! t.hash(&mut s); +//! s.finish() +//! } +//! ``` + +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] +pub use self::sip::SipHasher; +#[unstable(feature = "hashmap_internals", issue = "none")] +#[allow(deprecated)] +#[doc(hidden)] +pub use self::sip::SipHasher13; +use crate::{fmt, marker}; + +mod sip; + +/// A hashable type. +/// +/// Types implementing `Hash` are able to be [`hash`]ed with an instance of +/// [`Hasher`]. +/// +/// ## Implementing `Hash` +/// +/// You can derive `Hash` with `#[derive(Hash)]` if all fields implement `Hash`. +/// The resulting hash will be the combination of the values from calling +/// [`hash`] on each field. +/// +/// ``` +/// #[derive(Hash)] +/// struct Rustacean { +/// name: String, +/// country: String, +/// } +/// ``` +/// +/// If you need more control over how a value is hashed, you can of course +/// implement the `Hash` trait yourself: +/// +/// ``` +/// use std::hash::{Hash, Hasher}; +/// +/// struct Person { +/// id: u32, +/// name: String, +/// phone: u64, +/// } +/// +/// impl Hash for Person { +/// fn hash(&self, state: &mut H) { +/// self.id.hash(state); +/// self.phone.hash(state); +/// } +/// } +/// ``` +/// +/// ## `Hash` and `Eq` +/// +/// When implementing both `Hash` and [`Eq`], it is important that the following +/// property holds: +/// +/// ```text +/// k1 == k2 -> hash(k1) == hash(k2) +/// ``` +/// +/// In other words, if two keys are equal, their hashes must also be equal. +/// [`HashMap`] and [`HashSet`] both rely on this behavior. +/// +/// Thankfully, you won't need to worry about upholding this property when +/// deriving both [`Eq`] and `Hash` with `#[derive(PartialEq, Eq, Hash)]`. +/// +/// Violating this property is a logic error. The behavior resulting from a logic error is not +/// specified, but users of the trait must ensure that such logic errors do *not* result in +/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these +/// methods. +/// +/// ## Prefix collisions +/// +/// Implementations of `hash` should ensure that the data they +/// pass to the `Hasher` are prefix-free. That is, +/// values which are not equal should cause two different sequences of values to be written, +/// and neither of the two sequences should be a prefix of the other. +/// +/// For example, the standard implementation of [`Hash` for `&str`][impl] passes an extra +/// `0xFF` byte to the `Hasher` so that the values `("ab", "c")` and `("a", +/// "bc")` hash differently. +/// +/// ## Portability +/// +/// Due to differences in endianness and type sizes, data fed by `Hash` to a `Hasher` +/// should not be considered portable across platforms. Additionally the data passed by most +/// standard library types should not be considered stable between compiler versions. +/// +/// This means tests shouldn't probe hard-coded hash values or data fed to a `Hasher` and +/// instead should check consistency with `Eq`. +/// +/// Serialization formats intended to be portable between platforms or compiler versions should +/// either avoid encoding hashes or only rely on `Hash` and `Hasher` implementations that +/// provide additional guarantees. +/// +/// [`HashMap`]: ../../std/collections/struct.HashMap.html +/// [`HashSet`]: ../../std/collections/struct.HashSet.html +/// [`hash`]: Hash::hash +/// [impl]: ../../std/primitive.str.html#impl-Hash-for-str +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Hash"] +pub trait Hash { + /// Feeds this value into the given [`Hasher`]. + /// + /// # Examples + /// + /// ``` + /// use std::hash::{DefaultHasher, Hash, Hasher}; + /// + /// let mut hasher = DefaultHasher::new(); + /// 7920.hash(&mut hasher); + /// println!("Hash is {:x}!", hasher.finish()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn hash(&self, state: &mut H); + + /// Feeds a slice of this type into the given [`Hasher`]. + /// + /// This method is meant as a convenience, but its implementation is + /// also explicitly left unspecified. It isn't guaranteed to be + /// equivalent to repeated calls of [`hash`] and implementations of + /// [`Hash`] should keep that in mind and call [`hash`] themselves + /// if the slice isn't treated as a whole unit in the [`PartialEq`] + /// implementation. + /// + /// For example, a [`VecDeque`] implementation might naïvely call + /// [`as_slices`] and then [`hash_slice`] on each slice, but this + /// is wrong since the two slices can change with a call to + /// [`make_contiguous`] without affecting the [`PartialEq`] + /// result. Since these slices aren't treated as singular + /// units, and instead part of a larger deque, this method cannot + /// be used. + /// + /// # Examples + /// + /// ``` + /// use std::hash::{DefaultHasher, Hash, Hasher}; + /// + /// let mut hasher = DefaultHasher::new(); + /// let numbers = [6, 28, 496, 8128]; + /// Hash::hash_slice(&numbers, &mut hasher); + /// println!("Hash is {:x}!", hasher.finish()); + /// ``` + /// + /// [`VecDeque`]: ../../std/collections/struct.VecDeque.html + /// [`as_slices`]: ../../std/collections/struct.VecDeque.html#method.as_slices + /// [`make_contiguous`]: ../../std/collections/struct.VecDeque.html#method.make_contiguous + /// [`hash`]: Hash::hash + /// [`hash_slice`]: Hash::hash_slice + #[stable(feature = "hash_slice", since = "1.3.0")] + fn hash_slice(data: &[Self], state: &mut H) + where + Self: Sized, + { + for piece in data { + piece.hash(state) + } + } +} + +// Separate module to reexport the macro `Hash` from prelude without the trait `Hash`. +pub(crate) mod macros { + /// Derive macro generating an impl of the trait `Hash`. + #[rustc_builtin_macro] + #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] + #[allow_internal_unstable(core_intrinsics)] + pub macro Hash($item:item) { + /* compiler built-in */ + } +} +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(inline)] +pub use macros::Hash; + +/// A trait for hashing an arbitrary stream of bytes. +/// +/// Instances of `Hasher` usually represent state that is changed while hashing +/// data. +/// +/// `Hasher` provides a fairly basic interface for retrieving the generated hash +/// (with [`finish`]), and writing integers as well as slices of bytes into an +/// instance (with [`write`] and [`write_u8`] etc.). Most of the time, `Hasher` +/// instances are used in conjunction with the [`Hash`] trait. +/// +/// This trait provides no guarantees about how the various `write_*` methods are +/// defined and implementations of [`Hash`] should not assume that they work one +/// way or another. You cannot assume, for example, that a [`write_u32`] call is +/// equivalent to four calls of [`write_u8`]. Nor can you assume that adjacent +/// `write` calls are merged, so it's possible, for example, that +/// ``` +/// # fn foo(hasher: &mut impl std::hash::Hasher) { +/// hasher.write(&[1, 2]); +/// hasher.write(&[3, 4, 5, 6]); +/// # } +/// ``` +/// and +/// ``` +/// # fn foo(hasher: &mut impl std::hash::Hasher) { +/// hasher.write(&[1, 2, 3, 4]); +/// hasher.write(&[5, 6]); +/// # } +/// ``` +/// end up producing different hashes. +/// +/// Thus to produce the same hash value, [`Hash`] implementations must ensure +/// for equivalent items that exactly the same sequence of calls is made -- the +/// same methods with the same parameters in the same order. +/// +/// # Examples +/// +/// ``` +/// use std::hash::{DefaultHasher, Hasher}; +/// +/// let mut hasher = DefaultHasher::new(); +/// +/// hasher.write_u32(1989); +/// hasher.write_u8(11); +/// hasher.write_u8(9); +/// hasher.write(b"Huh?"); +/// +/// println!("Hash is {:x}!", hasher.finish()); +/// ``` +/// +/// [`finish`]: Hasher::finish +/// [`write`]: Hasher::write +/// [`write_u8`]: Hasher::write_u8 +/// [`write_u32`]: Hasher::write_u32 +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Hasher { + /// Returns the hash value for the values written so far. + /// + /// Despite its name, the method does not reset the hasher’s internal + /// state. Additional [`write`]s will continue from the current value. + /// If you need to start a fresh hash value, you will have to create + /// a new hasher. + /// + /// # Examples + /// + /// ``` + /// use std::hash::{DefaultHasher, Hasher}; + /// + /// let mut hasher = DefaultHasher::new(); + /// hasher.write(b"Cool!"); + /// + /// println!("Hash is {:x}!", hasher.finish()); + /// ``` + /// + /// [`write`]: Hasher::write + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + fn finish(&self) -> u64; + + /// Writes some data into this `Hasher`. + /// + /// # Examples + /// + /// ``` + /// use std::hash::{DefaultHasher, Hasher}; + /// + /// let mut hasher = DefaultHasher::new(); + /// let data = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]; + /// + /// hasher.write(&data); + /// + /// println!("Hash is {:x}!", hasher.finish()); + /// ``` + /// + /// # Note to Implementers + /// + /// You generally should not do length-prefixing as part of implementing + /// this method. It's up to the [`Hash`] implementation to call + /// [`Hasher::write_length_prefix`] before sequences that need it. + #[stable(feature = "rust1", since = "1.0.0")] + fn write(&mut self, bytes: &[u8]); + + /// Writes a single `u8` into this hasher. + #[inline] + #[stable(feature = "hasher_write", since = "1.3.0")] + fn write_u8(&mut self, i: u8) { + self.write(&[i]) + } + /// Writes a single `u16` into this hasher. + #[inline] + #[stable(feature = "hasher_write", since = "1.3.0")] + fn write_u16(&mut self, i: u16) { + self.write(&i.to_ne_bytes()) + } + /// Writes a single `u32` into this hasher. + #[inline] + #[stable(feature = "hasher_write", since = "1.3.0")] + fn write_u32(&mut self, i: u32) { + self.write(&i.to_ne_bytes()) + } + /// Writes a single `u64` into this hasher. + #[inline] + #[stable(feature = "hasher_write", since = "1.3.0")] + fn write_u64(&mut self, i: u64) { + self.write(&i.to_ne_bytes()) + } + /// Writes a single `u128` into this hasher. + #[inline] + #[stable(feature = "i128", since = "1.26.0")] + fn write_u128(&mut self, i: u128) { + self.write(&i.to_ne_bytes()) + } + /// Writes a single `usize` into this hasher. + #[inline] + #[stable(feature = "hasher_write", since = "1.3.0")] + fn write_usize(&mut self, i: usize) { + self.write(&i.to_ne_bytes()) + } + + /// Writes a single `i8` into this hasher. + #[inline] + #[stable(feature = "hasher_write", since = "1.3.0")] + fn write_i8(&mut self, i: i8) { + self.write_u8(i as u8) + } + /// Writes a single `i16` into this hasher. + #[inline] + #[stable(feature = "hasher_write", since = "1.3.0")] + fn write_i16(&mut self, i: i16) { + self.write_u16(i as u16) + } + /// Writes a single `i32` into this hasher. + #[inline] + #[stable(feature = "hasher_write", since = "1.3.0")] + fn write_i32(&mut self, i: i32) { + self.write_u32(i as u32) + } + /// Writes a single `i64` into this hasher. + #[inline] + #[stable(feature = "hasher_write", since = "1.3.0")] + fn write_i64(&mut self, i: i64) { + self.write_u64(i as u64) + } + /// Writes a single `i128` into this hasher. + #[inline] + #[stable(feature = "i128", since = "1.26.0")] + fn write_i128(&mut self, i: i128) { + self.write_u128(i as u128) + } + /// Writes a single `isize` into this hasher. + #[inline] + #[stable(feature = "hasher_write", since = "1.3.0")] + fn write_isize(&mut self, i: isize) { + self.write_usize(i as usize) + } + + /// Writes a length prefix into this hasher, as part of being prefix-free. + /// + /// If you're implementing [`Hash`] for a custom collection, call this before + /// writing its contents to this `Hasher`. That way + /// `(collection![1, 2, 3], collection![4, 5])` and + /// `(collection![1, 2], collection![3, 4, 5])` will provide different + /// sequences of values to the `Hasher` + /// + /// The `impl Hash for [T]` includes a call to this method, so if you're + /// hashing a slice (or array or vector) via its `Hash::hash` method, + /// you should **not** call this yourself. + /// + /// This method is only for providing domain separation. If you want to + /// hash a `usize` that represents part of the *data*, then it's important + /// that you pass it to [`Hasher::write_usize`] instead of to this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(hasher_prefixfree_extras)] + /// # // Stubs to make the `impl` below pass the compiler + /// # #![allow(non_local_definitions)] + /// # struct MyCollection(Option); + /// # impl MyCollection { + /// # fn len(&self) -> usize { todo!() } + /// # } + /// # impl<'a, T> IntoIterator for &'a MyCollection { + /// # type Item = T; + /// # type IntoIter = std::iter::Empty; + /// # fn into_iter(self) -> Self::IntoIter { todo!() } + /// # } + /// + /// use std::hash::{Hash, Hasher}; + /// impl Hash for MyCollection { + /// fn hash(&self, state: &mut H) { + /// state.write_length_prefix(self.len()); + /// for elt in self { + /// elt.hash(state); + /// } + /// } + /// } + /// ``` + /// + /// # Note to Implementers + /// + /// If you've decided that your `Hasher` is willing to be susceptible to + /// Hash-DoS attacks, then you might consider skipping hashing some or all + /// of the `len` provided in the name of increased performance. + #[inline] + #[unstable(feature = "hasher_prefixfree_extras", issue = "96762")] + fn write_length_prefix(&mut self, len: usize) { + self.write_usize(len); + } + + /// Writes a single `str` into this hasher. + /// + /// If you're implementing [`Hash`], you generally do not need to call this, + /// as the `impl Hash for str` does, so you should prefer that instead. + /// + /// This includes the domain separator for prefix-freedom, so you should + /// **not** call `Self::write_length_prefix` before calling this. + /// + /// # Note to Implementers + /// + /// There are at least two reasonable default ways to implement this. + /// Which one will be the default is not yet decided, so for now + /// you probably want to override it specifically. + /// + /// ## The general answer + /// + /// It's always correct to implement this with a length prefix: + /// + /// ``` + /// # #![feature(hasher_prefixfree_extras)] + /// # struct Foo; + /// # impl std::hash::Hasher for Foo { + /// # fn finish(&self) -> u64 { unimplemented!() } + /// # fn write(&mut self, _bytes: &[u8]) { unimplemented!() } + /// fn write_str(&mut self, s: &str) { + /// self.write_length_prefix(s.len()); + /// self.write(s.as_bytes()); + /// } + /// # } + /// ``` + /// + /// And, if your `Hasher` works in `usize` chunks, this is likely a very + /// efficient way to do it, as anything more complicated may well end up + /// slower than just running the round with the length. + /// + /// ## If your `Hasher` works byte-wise + /// + /// One nice thing about `str` being UTF-8 is that the `b'\xFF'` byte + /// never happens. That means that you can append that to the byte stream + /// being hashed and maintain prefix-freedom: + /// + /// ``` + /// # #![feature(hasher_prefixfree_extras)] + /// # struct Foo; + /// # impl std::hash::Hasher for Foo { + /// # fn finish(&self) -> u64 { unimplemented!() } + /// # fn write(&mut self, _bytes: &[u8]) { unimplemented!() } + /// fn write_str(&mut self, s: &str) { + /// self.write(s.as_bytes()); + /// self.write_u8(0xff); + /// } + /// # } + /// ``` + /// + /// This does require that your implementation not add extra padding, and + /// thus generally requires that you maintain a buffer, running a round + /// only once that buffer is full (or `finish` is called). + /// + /// That's because if `write` pads data out to a fixed chunk size, it's + /// likely that it does it in such a way that `"a"` and `"a\x00"` would + /// end up hashing the same sequence of things, introducing conflicts. + #[inline] + #[unstable(feature = "hasher_prefixfree_extras", issue = "96762")] + fn write_str(&mut self, s: &str) { + self.write(s.as_bytes()); + self.write_u8(0xff); + } +} + +#[stable(feature = "indirect_hasher_impl", since = "1.22.0")] +impl Hasher for &mut H { + fn finish(&self) -> u64 { + (**self).finish() + } + fn write(&mut self, bytes: &[u8]) { + (**self).write(bytes) + } + fn write_u8(&mut self, i: u8) { + (**self).write_u8(i) + } + fn write_u16(&mut self, i: u16) { + (**self).write_u16(i) + } + fn write_u32(&mut self, i: u32) { + (**self).write_u32(i) + } + fn write_u64(&mut self, i: u64) { + (**self).write_u64(i) + } + fn write_u128(&mut self, i: u128) { + (**self).write_u128(i) + } + fn write_usize(&mut self, i: usize) { + (**self).write_usize(i) + } + fn write_i8(&mut self, i: i8) { + (**self).write_i8(i) + } + fn write_i16(&mut self, i: i16) { + (**self).write_i16(i) + } + fn write_i32(&mut self, i: i32) { + (**self).write_i32(i) + } + fn write_i64(&mut self, i: i64) { + (**self).write_i64(i) + } + fn write_i128(&mut self, i: i128) { + (**self).write_i128(i) + } + fn write_isize(&mut self, i: isize) { + (**self).write_isize(i) + } + fn write_length_prefix(&mut self, len: usize) { + (**self).write_length_prefix(len) + } + fn write_str(&mut self, s: &str) { + (**self).write_str(s) + } +} + +/// A trait for creating instances of [`Hasher`]. +/// +/// A `BuildHasher` is typically used (e.g., by [`HashMap`]) to create +/// [`Hasher`]s for each key such that they are hashed independently of one +/// another, since [`Hasher`]s contain state. +/// +/// For each instance of `BuildHasher`, the [`Hasher`]s created by +/// [`build_hasher`] should be identical. That is, if the same stream of bytes +/// is fed into each hasher, the same output will also be generated. +/// +/// # Examples +/// +/// ``` +/// use std::hash::{BuildHasher, Hasher, RandomState}; +/// +/// let s = RandomState::new(); +/// let mut hasher_1 = s.build_hasher(); +/// let mut hasher_2 = s.build_hasher(); +/// +/// hasher_1.write_u32(8128); +/// hasher_2.write_u32(8128); +/// +/// assert_eq!(hasher_1.finish(), hasher_2.finish()); +/// ``` +/// +/// [`build_hasher`]: BuildHasher::build_hasher +/// [`HashMap`]: ../../std/collections/struct.HashMap.html +#[stable(since = "1.7.0", feature = "build_hasher")] +pub trait BuildHasher { + /// Type of the hasher that will be created. + #[stable(since = "1.7.0", feature = "build_hasher")] + type Hasher: Hasher; + + /// Creates a new hasher. + /// + /// Each call to `build_hasher` on the same instance should produce identical + /// [`Hasher`]s. + /// + /// # Examples + /// + /// ``` + /// use std::hash::{BuildHasher, RandomState}; + /// + /// let s = RandomState::new(); + /// let new_s = s.build_hasher(); + /// ``` + #[stable(since = "1.7.0", feature = "build_hasher")] + fn build_hasher(&self) -> Self::Hasher; + + /// Calculates the hash of a single value. + /// + /// This is intended as a convenience for code which *consumes* hashes, such + /// as the implementation of a hash table or in unit tests that check + /// whether a custom [`Hash`] implementation behaves as expected. + /// + /// This must not be used in any code which *creates* hashes, such as in an + /// implementation of [`Hash`]. The way to create a combined hash of + /// multiple values is to call [`Hash::hash`] multiple times using the same + /// [`Hasher`], not to call this method repeatedly and combine the results. + /// + /// # Example + /// + /// ``` + /// use std::cmp::{max, min}; + /// use std::hash::{BuildHasher, Hash, Hasher}; + /// struct OrderAmbivalentPair(T, T); + /// impl Hash for OrderAmbivalentPair { + /// fn hash(&self, hasher: &mut H) { + /// min(&self.0, &self.1).hash(hasher); + /// max(&self.0, &self.1).hash(hasher); + /// } + /// } + /// + /// // Then later, in a `#[test]` for the type... + /// let bh = std::hash::RandomState::new(); + /// assert_eq!( + /// bh.hash_one(OrderAmbivalentPair(1, 2)), + /// bh.hash_one(OrderAmbivalentPair(2, 1)) + /// ); + /// assert_eq!( + /// bh.hash_one(OrderAmbivalentPair(10, 2)), + /// bh.hash_one(&OrderAmbivalentPair(2, 10)) + /// ); + /// ``` + #[stable(feature = "build_hasher_simple_hash_one", since = "1.71.0")] + fn hash_one(&self, x: T) -> u64 + where + Self: Sized, + Self::Hasher: Hasher, + { + let mut hasher = self.build_hasher(); + x.hash(&mut hasher); + hasher.finish() + } +} + +/// Used to create a default [`BuildHasher`] instance for types that implement +/// [`Hasher`] and [`Default`]. +/// +/// `BuildHasherDefault` can be used when a type `H` implements [`Hasher`] and +/// [`Default`], and you need a corresponding [`BuildHasher`] instance, but none is +/// defined. +/// +/// Any `BuildHasherDefault` is [zero-sized]. It can be created with +/// [`default`][method.default]. When using `BuildHasherDefault` with [`HashMap`] or +/// [`HashSet`], this doesn't need to be done, since they implement appropriate +/// [`Default`] instances themselves. +/// +/// # Examples +/// +/// Using `BuildHasherDefault` to specify a custom [`BuildHasher`] for +/// [`HashMap`]: +/// +/// ``` +/// use std::collections::HashMap; +/// use std::hash::{BuildHasherDefault, Hasher}; +/// +/// #[derive(Default)] +/// struct MyHasher; +/// +/// impl Hasher for MyHasher { +/// fn write(&mut self, bytes: &[u8]) { +/// // Your hashing algorithm goes here! +/// unimplemented!() +/// } +/// +/// fn finish(&self) -> u64 { +/// // Your hashing algorithm goes here! +/// unimplemented!() +/// } +/// } +/// +/// type MyBuildHasher = BuildHasherDefault; +/// +/// let hash_map = HashMap::::default(); +/// ``` +/// +/// [method.default]: BuildHasherDefault::default +/// [`HashMap`]: ../../std/collections/struct.HashMap.html +/// [`HashSet`]: ../../std/collections/struct.HashSet.html +/// [zero-sized]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts +#[stable(since = "1.7.0", feature = "build_hasher")] +pub struct BuildHasherDefault(marker::PhantomData H>); + +impl BuildHasherDefault { + /// Creates a new BuildHasherDefault for Hasher `H`. + #[stable(feature = "build_hasher_default_const_new", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable( + feature = "build_hasher_default_const_new", + since = "CURRENT_RUSTC_VERSION" + )] + pub const fn new() -> Self { + BuildHasherDefault(marker::PhantomData) + } +} + +#[stable(since = "1.9.0", feature = "core_impl_debug")] +impl fmt::Debug for BuildHasherDefault { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BuildHasherDefault").finish() + } +} + +#[stable(since = "1.7.0", feature = "build_hasher")] +impl BuildHasher for BuildHasherDefault { + type Hasher = H; + + fn build_hasher(&self) -> H { + H::default() + } +} + +#[stable(since = "1.7.0", feature = "build_hasher")] +impl Clone for BuildHasherDefault { + fn clone(&self) -> BuildHasherDefault { + BuildHasherDefault(marker::PhantomData) + } +} + +#[stable(since = "1.7.0", feature = "build_hasher")] +impl Default for BuildHasherDefault { + fn default() -> BuildHasherDefault { + Self::new() + } +} + +#[stable(since = "1.29.0", feature = "build_hasher_eq")] +impl PartialEq for BuildHasherDefault { + fn eq(&self, _other: &BuildHasherDefault) -> bool { + true + } +} + +#[stable(since = "1.29.0", feature = "build_hasher_eq")] +impl Eq for BuildHasherDefault {} + +mod impls { + use super::*; + use crate::{mem, slice}; + + macro_rules! impl_write { + ($(($ty:ident, $meth:ident),)*) => {$( + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for $ty { + #[inline] + fn hash(&self, state: &mut H) { + state.$meth(*self) + } + + #[inline] + fn hash_slice(data: &[$ty], state: &mut H) { + let newlen = mem::size_of_val(data); + let ptr = data.as_ptr() as *const u8; + // SAFETY: `ptr` is valid and aligned, as this macro is only used + // for numeric primitives which have no padding. The new slice only + // spans across `data` and is never mutated, and its total size is the + // same as the original `data` so it can't be over `isize::MAX`. + state.write(unsafe { slice::from_raw_parts(ptr, newlen) }) + } + } + )*} + } + + impl_write! { + (u8, write_u8), + (u16, write_u16), + (u32, write_u32), + (u64, write_u64), + (usize, write_usize), + (i8, write_i8), + (i16, write_i16), + (i32, write_i32), + (i64, write_i64), + (isize, write_isize), + (u128, write_u128), + (i128, write_i128), + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for bool { + #[inline] + fn hash(&self, state: &mut H) { + state.write_u8(*self as u8) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for char { + #[inline] + fn hash(&self, state: &mut H) { + state.write_u32(*self as u32) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for str { + #[inline] + fn hash(&self, state: &mut H) { + state.write_str(self); + } + } + + #[stable(feature = "never_hash", since = "1.29.0")] + impl Hash for ! { + #[inline] + fn hash(&self, _: &mut H) { + *self + } + } + + macro_rules! impl_hash_tuple { + () => ( + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for () { + #[inline] + fn hash(&self, _state: &mut H) {} + } + ); + + ( $($name:ident)+) => ( + maybe_tuple_doc! { + $($name)+ @ + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($name: Hash),+> Hash for ($($name,)+) where last_type!($($name,)+): ?Sized { + #[allow(non_snake_case)] + #[inline] + fn hash(&self, state: &mut S) { + let ($(ref $name,)+) = *self; + $($name.hash(state);)+ + } + } + } + ); + } + + macro_rules! maybe_tuple_doc { + ($a:ident @ #[$meta:meta] $item:item) => { + #[doc(fake_variadic)] + #[doc = "This trait is implemented for tuples up to twelve items long."] + #[$meta] + $item + }; + ($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => { + #[doc(hidden)] + #[$meta] + $item + }; + } + + macro_rules! last_type { + ($a:ident,) => { $a }; + ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; + } + + impl_hash_tuple! {} + impl_hash_tuple! { T } + impl_hash_tuple! { T B } + impl_hash_tuple! { T B C } + impl_hash_tuple! { T B C D } + impl_hash_tuple! { T B C D E } + impl_hash_tuple! { T B C D E F } + impl_hash_tuple! { T B C D E F G } + impl_hash_tuple! { T B C D E F G H } + impl_hash_tuple! { T B C D E F G H I } + impl_hash_tuple! { T B C D E F G H I J } + impl_hash_tuple! { T B C D E F G H I J K } + impl_hash_tuple! { T B C D E F G H I J K L } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for [T] { + #[inline] + fn hash(&self, state: &mut H) { + state.write_length_prefix(self.len()); + Hash::hash_slice(self, state) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for &T { + #[inline] + fn hash(&self, state: &mut H) { + (**self).hash(state); + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for &mut T { + #[inline] + fn hash(&self, state: &mut H) { + (**self).hash(state); + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for *const T { + #[inline] + fn hash(&self, state: &mut H) { + let (address, metadata) = self.to_raw_parts(); + state.write_usize(address.addr()); + metadata.hash(state); + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for *mut T { + #[inline] + fn hash(&self, state: &mut H) { + let (address, metadata) = self.to_raw_parts(); + state.write_usize(address.addr()); + metadata.hash(state); + } + } +} diff --git a/CoqOfRust/core/hash/sip.rs b/CoqOfRust/core/hash/sip.rs new file mode 100644 index 000000000..6ea3241c5 --- /dev/null +++ b/CoqOfRust/core/hash/sip.rs @@ -0,0 +1,389 @@ +//! An implementation of SipHash. + +#![allow(deprecated)] // the types in this module are deprecated + +use crate::marker::PhantomData; +use crate::{cmp, mem, ptr}; + +/// An implementation of SipHash 1-3. +/// +/// This is currently the default hashing function used by standard library +/// (e.g., `collections::HashMap` uses it by default). +/// +/// See: +#[unstable(feature = "hashmap_internals", issue = "none")] +#[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] +#[derive(Debug, Clone, Default)] +#[doc(hidden)] +pub struct SipHasher13 { + hasher: Hasher, +} + +/// An implementation of SipHash 2-4. +/// +/// See: +#[unstable(feature = "hashmap_internals", issue = "none")] +#[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] +#[derive(Debug, Clone, Default)] +struct SipHasher24 { + hasher: Hasher, +} + +/// An implementation of SipHash 2-4. +/// +/// See: +/// +/// SipHash is a general-purpose hashing function: it runs at a good +/// speed (competitive with Spooky and City) and permits strong _keyed_ +/// hashing. This lets you key your hash tables from a strong RNG, such as +/// [`rand::os::OsRng`](https://docs.rs/rand/latest/rand/rngs/struct.OsRng.html). +/// +/// Although the SipHash algorithm is considered to be generally strong, +/// it is not intended for cryptographic purposes. As such, all +/// cryptographic uses of this implementation are _strongly discouraged_. +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] +#[derive(Debug, Clone, Default)] +pub struct SipHasher(SipHasher24); + +#[derive(Debug)] +struct Hasher { + k0: u64, + k1: u64, + length: usize, // how many bytes we've processed + state: State, // hash State + tail: u64, // unprocessed bytes le + ntail: usize, // how many bytes in tail are valid + _marker: PhantomData, +} + +#[derive(Debug, Clone, Copy)] +#[repr(C)] +struct State { + // v0, v2 and v1, v3 show up in pairs in the algorithm, + // and simd implementations of SipHash will use vectors + // of v02 and v13. By placing them in this order in the struct, + // the compiler can pick up on just a few simd optimizations by itself. + v0: u64, + v2: u64, + v1: u64, + v3: u64, +} + +macro_rules! compress { + ($state:expr) => {{ compress!($state.v0, $state.v1, $state.v2, $state.v3) }}; + ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => {{ + $v0 = $v0.wrapping_add($v1); + $v2 = $v2.wrapping_add($v3); + $v1 = $v1.rotate_left(13); + $v1 ^= $v0; + $v3 = $v3.rotate_left(16); + $v3 ^= $v2; + $v0 = $v0.rotate_left(32); + + $v2 = $v2.wrapping_add($v1); + $v0 = $v0.wrapping_add($v3); + $v1 = $v1.rotate_left(17); + $v1 ^= $v2; + $v3 = $v3.rotate_left(21); + $v3 ^= $v0; + $v2 = $v2.rotate_left(32); + }}; +} + +/// Loads an integer of the desired type from a byte stream, in LE order. Uses +/// `copy_nonoverlapping` to let the compiler generate the most efficient way +/// to load it from a possibly unaligned address. +/// +/// Safety: this performs unchecked indexing of `$buf` at +/// `$i..$i+size_of::<$int_ty>()`, so that must be in-bounds. +macro_rules! load_int_le { + ($buf:expr, $i:expr, $int_ty:ident) => {{ + debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len()); + let mut data = 0 as $int_ty; + ptr::copy_nonoverlapping( + $buf.as_ptr().add($i), + &mut data as *mut _ as *mut u8, + mem::size_of::<$int_ty>(), + ); + data.to_le() + }}; +} + +/// Loads a u64 using up to 7 bytes of a byte slice. It looks clumsy but the +/// `copy_nonoverlapping` calls that occur (via `load_int_le!`) all have fixed +/// sizes and avoid calling `memcpy`, which is good for speed. +/// +/// Safety: this performs unchecked indexing of `buf` at `start..start+len`, so +/// that must be in-bounds. +#[inline] +unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { + debug_assert!(len < 8); + let mut i = 0; // current byte index (from LSB) in the output u64 + let mut out = 0; + if i + 3 < len { + // SAFETY: `i` cannot be greater than `len`, and the caller must guarantee + // that the index start..start+len is in bounds. + out = unsafe { load_int_le!(buf, start + i, u32) } as u64; + i += 4; + } + if i + 1 < len { + // SAFETY: same as above. + out |= (unsafe { load_int_le!(buf, start + i, u16) } as u64) << (i * 8); + i += 2 + } + if i < len { + // SAFETY: same as above. + out |= (unsafe { *buf.get_unchecked(start + i) } as u64) << (i * 8); + i += 1; + } + //FIXME(fee1-dead): use debug_assert_eq + debug_assert!(i == len); + out +} + +impl SipHasher { + /// Creates a new `SipHasher` with the two initial keys set to 0. + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] + #[must_use] + pub fn new() -> SipHasher { + SipHasher::new_with_keys(0, 0) + } + + /// Creates a `SipHasher` that is keyed off the provided keys. + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] + #[must_use] + pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher { + SipHasher(SipHasher24 { hasher: Hasher::new_with_keys(key0, key1) }) + } +} + +impl SipHasher13 { + /// Creates a new `SipHasher13` with the two initial keys set to 0. + #[inline] + #[unstable(feature = "hashmap_internals", issue = "none")] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] + pub fn new() -> SipHasher13 { + SipHasher13::new_with_keys(0, 0) + } + + /// Creates a `SipHasher13` that is keyed off the provided keys. + #[inline] + #[unstable(feature = "hashmap_internals", issue = "none")] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] + pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { + SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) } + } +} + +impl Hasher { + #[inline] + const fn new_with_keys(key0: u64, key1: u64) -> Hasher { + let mut state = Hasher { + k0: key0, + k1: key1, + length: 0, + state: State { v0: 0, v1: 0, v2: 0, v3: 0 }, + tail: 0, + ntail: 0, + _marker: PhantomData, + }; + state.reset(); + state + } + + #[inline] + const fn reset(&mut self) { + self.length = 0; + self.state.v0 = self.k0 ^ 0x736f6d6570736575; + self.state.v1 = self.k1 ^ 0x646f72616e646f6d; + self.state.v2 = self.k0 ^ 0x6c7967656e657261; + self.state.v3 = self.k1 ^ 0x7465646279746573; + self.ntail = 0; + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl super::Hasher for SipHasher { + #[inline] + fn write(&mut self, msg: &[u8]) { + self.0.hasher.write(msg) + } + + #[inline] + fn write_str(&mut self, s: &str) { + self.0.hasher.write_str(s); + } + + #[inline] + fn finish(&self) -> u64 { + self.0.hasher.finish() + } +} + +#[unstable(feature = "hashmap_internals", issue = "none")] +impl super::Hasher for SipHasher13 { + #[inline] + fn write(&mut self, msg: &[u8]) { + self.hasher.write(msg) + } + + #[inline] + fn write_str(&mut self, s: &str) { + self.hasher.write_str(s); + } + + #[inline] + fn finish(&self) -> u64 { + self.hasher.finish() + } +} + +impl super::Hasher for Hasher { + // Note: no integer hashing methods (`write_u*`, `write_i*`) are defined + // for this type. We could add them, copy the `short_write` implementation + // in librustc_data_structures/sip128.rs, and add `write_u*`/`write_i*` + // methods to `SipHasher`, `SipHasher13`, and `DefaultHasher`. This would + // greatly speed up integer hashing by those hashers, at the cost of + // slightly slowing down compile speeds on some benchmarks. See #69152 for + // details. + #[inline] + fn write(&mut self, msg: &[u8]) { + let length = msg.len(); + self.length += length; + + let mut needed = 0; + + if self.ntail != 0 { + needed = 8 - self.ntail; + // SAFETY: `cmp::min(length, needed)` is guaranteed to not be over `length` + self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << (8 * self.ntail); + if length < needed { + self.ntail += length; + return; + } else { + self.state.v3 ^= self.tail; + S::c_rounds(&mut self.state); + self.state.v0 ^= self.tail; + self.ntail = 0; + } + } + + // Buffered tail is now flushed, process new input. + let len = length - needed; + let left = len & 0x7; // len % 8 + + let mut i = needed; + while i < len - left { + // SAFETY: because `len - left` is the biggest multiple of 8 under + // `len`, and because `i` starts at `needed` where `len` is `length - needed`, + // `i + 8` is guaranteed to be less than or equal to `length`. + let mi = unsafe { load_int_le!(msg, i, u64) }; + + self.state.v3 ^= mi; + S::c_rounds(&mut self.state); + self.state.v0 ^= mi; + + i += 8; + } + + // SAFETY: `i` is now `needed + len.div_euclid(8) * 8`, + // so `i + left` = `needed + len` = `length`, which is by + // definition equal to `msg.len()`. + self.tail = unsafe { u8to64_le(msg, i, left) }; + self.ntail = left; + } + + #[inline] + fn write_str(&mut self, s: &str) { + // This hasher works byte-wise, and `0xFF` cannot show up in a `str`, + // so just hashing the one extra byte is enough to be prefix-free. + self.write(s.as_bytes()); + self.write_u8(0xFF); + } + + #[inline] + fn finish(&self) -> u64 { + let mut state = self.state; + + let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail; + + state.v3 ^= b; + S::c_rounds(&mut state); + state.v0 ^= b; + + state.v2 ^= 0xff; + S::d_rounds(&mut state); + + state.v0 ^ state.v1 ^ state.v2 ^ state.v3 + } +} + +impl Clone for Hasher { + #[inline] + fn clone(&self) -> Hasher { + Hasher { + k0: self.k0, + k1: self.k1, + length: self.length, + state: self.state, + tail: self.tail, + ntail: self.ntail, + _marker: self._marker, + } + } +} + +impl Default for Hasher { + /// Creates a `Hasher` with the two initial keys set to 0. + #[inline] + fn default() -> Hasher { + Hasher::new_with_keys(0, 0) + } +} + +#[doc(hidden)] +trait Sip { + fn c_rounds(_: &mut State); + fn d_rounds(_: &mut State); +} + +#[derive(Debug, Clone, Default)] +struct Sip13Rounds; + +impl Sip for Sip13Rounds { + #[inline] + fn c_rounds(state: &mut State) { + compress!(state); + } + + #[inline] + fn d_rounds(state: &mut State) { + compress!(state); + compress!(state); + compress!(state); + } +} + +#[derive(Debug, Clone, Default)] +struct Sip24Rounds; + +impl Sip for Sip24Rounds { + #[inline] + fn c_rounds(state: &mut State) { + compress!(state); + compress!(state); + } + + #[inline] + fn d_rounds(state: &mut State) { + compress!(state); + compress!(state); + compress!(state); + compress!(state); + } +} diff --git a/CoqOfRust/core/hint.rs b/CoqOfRust/core/hint.rs new file mode 100644 index 000000000..c59e4414d --- /dev/null +++ b/CoqOfRust/core/hint.rs @@ -0,0 +1,513 @@ +#![stable(feature = "core_hint", since = "1.27.0")] + +//! Hints to compiler that affects how code should be emitted or optimized. +//! +//! Hints may be compile time or runtime. + +use crate::{intrinsics, ub_checks}; + +/// Informs the compiler that the site which is calling this function is not +/// reachable, possibly enabling further optimizations. +/// +/// # Safety +/// +/// Reaching this function is *Undefined Behavior*. +/// +/// As the compiler assumes that all forms of Undefined Behavior can never +/// happen, it will eliminate all branches in the surrounding code that it can +/// determine will invariably lead to a call to `unreachable_unchecked()`. +/// +/// If the assumptions embedded in using this function turn out to be wrong - +/// that is, if the site which is calling `unreachable_unchecked()` is actually +/// reachable at runtime - the compiler may have generated nonsensical machine +/// instructions for this situation, including in seemingly unrelated code, +/// causing difficult-to-debug problems. +/// +/// Use this function sparingly. Consider using the [`unreachable!`] macro, +/// which may prevent some optimizations but will safely panic in case it is +/// actually reached at runtime. Benchmark your code to find out if using +/// `unreachable_unchecked()` comes with a performance benefit. +/// +/// # Examples +/// +/// `unreachable_unchecked()` can be used in situations where the compiler +/// can't prove invariants that were previously established. Such situations +/// have a higher chance of occurring if those invariants are upheld by +/// external code that the compiler can't analyze. +/// ``` +/// fn prepare_inputs(divisors: &mut Vec) { +/// // Note to future-self when making changes: The invariant established +/// // here is NOT checked in `do_computation()`; if this changes, you HAVE +/// // to change `do_computation()`. +/// divisors.retain(|divisor| *divisor != 0) +/// } +/// +/// /// # Safety +/// /// All elements of `divisor` must be non-zero. +/// unsafe fn do_computation(i: u32, divisors: &[u32]) -> u32 { +/// divisors.iter().fold(i, |acc, divisor| { +/// // Convince the compiler that a division by zero can't happen here +/// // and a check is not needed below. +/// if *divisor == 0 { +/// // Safety: `divisor` can't be zero because of `prepare_inputs`, +/// // but the compiler does not know about this. We *promise* +/// // that we always call `prepare_inputs`. +/// std::hint::unreachable_unchecked() +/// } +/// // The compiler would normally introduce a check here that prevents +/// // a division by zero. However, if `divisor` was zero, the branch +/// // above would reach what we explicitly marked as unreachable. +/// // The compiler concludes that `divisor` can't be zero at this point +/// // and removes the - now proven useless - check. +/// acc / divisor +/// }) +/// } +/// +/// let mut divisors = vec![2, 0, 4]; +/// prepare_inputs(&mut divisors); +/// let result = unsafe { +/// // Safety: prepare_inputs() guarantees that divisors is non-zero +/// do_computation(100, &divisors) +/// }; +/// assert_eq!(result, 12); +/// +/// ``` +/// +/// While using `unreachable_unchecked()` is perfectly sound in the following +/// example, as the compiler is able to prove that a division by zero is not +/// possible, benchmarking reveals that `unreachable_unchecked()` provides +/// no benefit over using [`unreachable!`], while the latter does not introduce +/// the possibility of Undefined Behavior. +/// +/// ``` +/// fn div_1(a: u32, b: u32) -> u32 { +/// use std::hint::unreachable_unchecked; +/// +/// // `b.saturating_add(1)` is always positive (not zero), +/// // hence `checked_div` will never return `None`. +/// // Therefore, the else branch is unreachable. +/// a.checked_div(b.saturating_add(1)) +/// .unwrap_or_else(|| unsafe { unreachable_unchecked() }) +/// } +/// +/// assert_eq!(div_1(7, 0), 7); +/// assert_eq!(div_1(9, 1), 4); +/// assert_eq!(div_1(11, u32::MAX), 0); +/// ``` +#[inline] +#[stable(feature = "unreachable", since = "1.27.0")] +#[rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub const unsafe fn unreachable_unchecked() -> ! { + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "hint::unreachable_unchecked must never be reached", + () => false + ); + // SAFETY: the safety contract for `intrinsics::unreachable` must + // be upheld by the caller. + unsafe { intrinsics::unreachable() } +} + +/// Makes a *soundness* promise to the compiler that `cond` holds. +/// +/// This may allow the optimizer to simplify things, but it might also make the generated code +/// slower. Either way, calling it will most likely make compilation take longer. +/// +/// You may know this from other places as +/// [`llvm.assume`](https://llvm.org/docs/LangRef.html#llvm-assume-intrinsic) or, in C, +/// [`__builtin_assume`](https://clang.llvm.org/docs/LanguageExtensions.html#builtin-assume). +/// +/// This promotes a correctness requirement to a soundness requirement. Don't do that without +/// very good reason. +/// +/// # Usage +/// +/// This is a situational tool for micro-optimization, and is allowed to do nothing. Any use +/// should come with a repeatable benchmark to show the value, with the expectation to drop it +/// later should the optimizer get smarter and no longer need it. +/// +/// The more complicated the condition, the less likely this is to be useful. For example, +/// `assert_unchecked(foo.is_sorted())` is a complex enough value that the compiler is unlikely +/// to be able to take advantage of it. +/// +/// There's also no need to `assert_unchecked` basic properties of things. For example, the +/// compiler already knows the range of `count_ones`, so there is no benefit to +/// `let n = u32::count_ones(x); assert_unchecked(n <= u32::BITS);`. +/// +/// `assert_unchecked` is logically equivalent to `if !cond { unreachable_unchecked(); }`. If +/// ever you are tempted to write `assert_unchecked(false)`, you should instead use +/// [`unreachable_unchecked()`] directly. +/// +/// # Safety +/// +/// `cond` must be `true`. It is immediate UB to call this with `false`. +/// +/// # Example +/// +/// ``` +/// use core::hint; +/// +/// /// # Safety +/// /// +/// /// `p` must be nonnull and valid +/// pub unsafe fn next_value(p: *const i32) -> i32 { +/// // SAFETY: caller invariants guarantee that `p` is not null +/// unsafe { hint::assert_unchecked(!p.is_null()) } +/// +/// if p.is_null() { +/// return -1; +/// } else { +/// // SAFETY: caller invariants guarantee that `p` is valid +/// unsafe { *p + 1 } +/// } +/// } +/// ``` +/// +/// Without the `assert_unchecked`, the above function produces the following with optimizations +/// enabled: +/// +/// ```asm +/// next_value: +/// test rdi, rdi +/// je .LBB0_1 +/// mov eax, dword ptr [rdi] +/// inc eax +/// ret +/// .LBB0_1: +/// mov eax, -1 +/// ret +/// ``` +/// +/// Adding the assertion allows the optimizer to remove the extra check: +/// +/// ```asm +/// next_value: +/// mov eax, dword ptr [rdi] +/// inc eax +/// ret +/// ``` +/// +/// This example is quite unlike anything that would be used in the real world: it is redundant +/// to put an assertion right next to code that checks the same thing, and dereferencing a +/// pointer already has the builtin assumption that it is nonnull. However, it illustrates the +/// kind of changes the optimizer can make even when the behavior is less obviously related. +#[track_caller] +#[inline(always)] +#[doc(alias = "assume")] +#[stable(feature = "hint_assert_unchecked", since = "1.81.0")] +#[rustc_const_stable(feature = "hint_assert_unchecked", since = "1.81.0")] +pub const unsafe fn assert_unchecked(cond: bool) { + // SAFETY: The caller promised `cond` is true. + unsafe { + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "hint::assert_unchecked must never be called when the condition is false", + (cond: bool = cond) => cond, + ); + crate::intrinsics::assume(cond); + } +} + +/// Emits a machine instruction to signal the processor that it is running in +/// a busy-wait spin-loop ("spin lock"). +/// +/// Upon receiving the spin-loop signal the processor can optimize its behavior by, +/// for example, saving power or switching hyper-threads. +/// +/// This function is different from [`thread::yield_now`] which directly +/// yields to the system's scheduler, whereas `spin_loop` does not interact +/// with the operating system. +/// +/// A common use case for `spin_loop` is implementing bounded optimistic +/// spinning in a CAS loop in synchronization primitives. To avoid problems +/// like priority inversion, it is strongly recommended that the spin loop is +/// terminated after a finite amount of iterations and an appropriate blocking +/// syscall is made. +/// +/// **Note**: On platforms that do not support receiving spin-loop hints this +/// function does not do anything at all. +/// +/// # Examples +/// +/// ``` +/// use std::sync::atomic::{AtomicBool, Ordering}; +/// use std::sync::Arc; +/// use std::{hint, thread}; +/// +/// // A shared atomic value that threads will use to coordinate +/// let live = Arc::new(AtomicBool::new(false)); +/// +/// // In a background thread we'll eventually set the value +/// let bg_work = { +/// let live = live.clone(); +/// thread::spawn(move || { +/// // Do some work, then make the value live +/// do_some_work(); +/// live.store(true, Ordering::Release); +/// }) +/// }; +/// +/// // Back on our current thread, we wait for the value to be set +/// while !live.load(Ordering::Acquire) { +/// // The spin loop is a hint to the CPU that we're waiting, but probably +/// // not for very long +/// hint::spin_loop(); +/// } +/// +/// // The value is now set +/// # fn do_some_work() {} +/// do_some_work(); +/// bg_work.join()?; +/// # Ok::<(), Box>(()) +/// ``` +/// +/// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html +#[inline(always)] +#[stable(feature = "renamed_spin_loop", since = "1.49.0")] +pub fn spin_loop() { + #[cfg(target_arch = "x86")] + { + // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets. + unsafe { crate::arch::x86::_mm_pause() }; + } + + #[cfg(target_arch = "x86_64")] + { + // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets. + unsafe { crate::arch::x86_64::_mm_pause() }; + } + + #[cfg(target_arch = "riscv32")] + { + crate::arch::riscv32::pause(); + } + + #[cfg(target_arch = "riscv64")] + { + crate::arch::riscv64::pause(); + } + + #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] + { + // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets. + unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) }; + } + + #[cfg(all(target_arch = "arm", target_feature = "v6"))] + { + // SAFETY: the `cfg` attr ensures that we only execute this on arm targets + // with support for the v6 feature. + unsafe { crate::arch::arm::__yield() }; + } +} + +/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what +/// `black_box` could do. +/// +/// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can +/// use `dummy` in any possible valid way that Rust code is allowed to without introducing undefined +/// behavior in the calling code. This property makes `black_box` useful for writing code in which +/// certain optimizations are not desired, such as benchmarks. +/// +/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The +/// extent to which it can block optimisations may vary depending upon the platform and code-gen +/// backend used. Programs cannot rely on `black_box` for *correctness*, beyond it behaving as the +/// identity function. As such, it **must not be relied upon to control critical program behavior.** +/// This also means that this function does not offer any guarantees for cryptographic or security +/// purposes. +/// +/// [`std::convert::identity`]: crate::convert::identity +/// +/// # When is this useful? +/// +/// While not suitable in those mission-critical cases, `black_box`'s functionality can generally be +/// relied upon for benchmarking, and should be used there. It will try to ensure that the +/// compiler doesn't optimize away part of the intended test code based on context. For +/// example: +/// +/// ``` +/// fn contains(haystack: &[&str], needle: &str) -> bool { +/// haystack.iter().any(|x| x == &needle) +/// } +/// +/// pub fn benchmark() { +/// let haystack = vec!["abc", "def", "ghi", "jkl", "mno"]; +/// let needle = "ghi"; +/// for _ in 0..10 { +/// contains(&haystack, needle); +/// } +/// } +/// ``` +/// +/// The compiler could theoretically make optimizations like the following: +/// +/// - The `needle` and `haystack` do not change, move the call to `contains` outside the loop and +/// delete the loop +/// - Inline `contains` +/// - `needle` and `haystack` have values known at compile time, `contains` is always true. Remove +/// the call and replace with `true` +/// - Nothing is done with the result of `contains`: delete this function call entirely +/// - `benchmark` now has no purpose: delete this function +/// +/// It is not likely that all of the above happens, but the compiler is definitely able to make some +/// optimizations that could result in a very inaccurate benchmark. This is where `black_box` comes +/// in: +/// +/// ``` +/// use std::hint::black_box; +/// +/// // Same `contains` function +/// fn contains(haystack: &[&str], needle: &str) -> bool { +/// haystack.iter().any(|x| x == &needle) +/// } +/// +/// pub fn benchmark() { +/// let haystack = vec!["abc", "def", "ghi", "jkl", "mno"]; +/// let needle = "ghi"; +/// for _ in 0..10 { +/// // Adjust our benchmark loop contents +/// black_box(contains(black_box(&haystack), black_box(needle))); +/// } +/// } +/// ``` +/// +/// This essentially tells the compiler to block optimizations across any calls to `black_box`. So, +/// it now: +/// +/// - Treats both arguments to `contains` as unpredictable: the body of `contains` can no longer be +/// optimized based on argument values +/// - Treats the call to `contains` and its result as volatile: the body of `benchmark` cannot +/// optimize this away +/// +/// This makes our benchmark much more realistic to how the function would actually be used, where +/// arguments are usually not known at compile time and the result is used in some way. +#[inline] +#[stable(feature = "bench_black_box", since = "1.66.0")] +#[rustc_const_unstable(feature = "const_black_box", issue = "none")] +pub const fn black_box(dummy: T) -> T { + crate::intrinsics::black_box(dummy) +} + +/// An identity function that causes an `unused_must_use` warning to be +/// triggered if the given value is not used (returned, stored in a variable, +/// etc) by the caller. +/// +/// This is primarily intended for use in macro-generated code, in which a +/// [`#[must_use]` attribute][must_use] either on a type or a function would not +/// be convenient. +/// +/// [must_use]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute +/// +/// # Example +/// +/// ``` +/// #![feature(hint_must_use)] +/// +/// use core::fmt; +/// +/// pub struct Error(/* ... */); +/// +/// #[macro_export] +/// macro_rules! make_error { +/// ($($args:expr),*) => { +/// core::hint::must_use({ +/// let error = $crate::make_error(core::format_args!($($args),*)); +/// error +/// }) +/// }; +/// } +/// +/// // Implementation detail of make_error! macro. +/// #[doc(hidden)] +/// pub fn make_error(args: fmt::Arguments<'_>) -> Error { +/// Error(/* ... */) +/// } +/// +/// fn demo() -> Option { +/// if true { +/// // Oops, meant to write `return Some(make_error!("..."));` +/// Some(make_error!("...")); +/// } +/// None +/// } +/// # +/// # // Make rustdoc not wrap the whole snippet in fn main, so that $crate::make_error works +/// # fn main() {} +/// ``` +/// +/// In the above example, we'd like an `unused_must_use` lint to apply to the +/// value created by `make_error!`. However, neither `#[must_use]` on a struct +/// nor `#[must_use]` on a function is appropriate here, so the macro expands +/// using `core::hint::must_use` instead. +/// +/// - We wouldn't want `#[must_use]` on the `struct Error` because that would +/// make the following unproblematic code trigger a warning: +/// +/// ``` +/// # struct Error; +/// # +/// fn f(arg: &str) -> Result<(), Error> +/// # { Ok(()) } +/// +/// #[test] +/// fn t() { +/// // Assert that `f` returns error if passed an empty string. +/// // A value of type `Error` is unused here but that's not a problem. +/// f("").unwrap_err(); +/// } +/// ``` +/// +/// - Using `#[must_use]` on `fn make_error` can't help because the return value +/// *is* used, as the right-hand side of a `let` statement. The `let` +/// statement looks useless but is in fact necessary for ensuring that +/// temporaries within the `format_args` expansion are not kept alive past the +/// creation of the `Error`, as keeping them alive past that point can cause +/// autotrait issues in async code: +/// +/// ``` +/// # #![feature(hint_must_use)] +/// # +/// # struct Error; +/// # +/// # macro_rules! make_error { +/// # ($($args:expr),*) => { +/// # core::hint::must_use({ +/// # // If `let` isn't used, then `f()` produces a non-Send future. +/// # let error = make_error(core::format_args!($($args),*)); +/// # error +/// # }) +/// # }; +/// # } +/// # +/// # fn make_error(args: core::fmt::Arguments<'_>) -> Error { +/// # Error +/// # } +/// # +/// async fn f() { +/// // Using `let` inside the make_error expansion causes temporaries like +/// // `unsync()` to drop at the semicolon of that `let` statement, which +/// // is prior to the await point. They would otherwise stay around until +/// // the semicolon on *this* statement, which is after the await point, +/// // and the enclosing Future would not implement Send. +/// log(make_error!("look: {:p}", unsync())).await; +/// } +/// +/// async fn log(error: Error) {/* ... */} +/// +/// // Returns something without a Sync impl. +/// fn unsync() -> *const () { +/// 0 as *const () +/// } +/// # +/// # fn test() { +/// # fn assert_send(_: impl Send) {} +/// # assert_send(f()); +/// # } +/// ``` +#[unstable(feature = "hint_must_use", issue = "94745")] +#[must_use] // <-- :) +#[inline(always)] +pub const fn must_use(value: T) -> T { + value +} diff --git a/CoqOfRust/core/internal_macros.rs b/CoqOfRust/core/internal_macros.rs new file mode 100644 index 000000000..fe4fa8026 --- /dev/null +++ b/CoqOfRust/core/internal_macros.rs @@ -0,0 +1,199 @@ +// implements the unary operator "op &T" +// based on "op T" where T is expected to be `Copy`able +macro_rules! forward_ref_unop { + (impl $imp:ident, $method:ident for $t:ty) => { + forward_ref_unop!(impl $imp, $method for $t, + #[stable(feature = "rust1", since = "1.0.0")]); + }; + (impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => { + #[$attr] + impl $imp for &$t { + type Output = <$t as $imp>::Output; + + #[inline] + fn $method(self) -> <$t as $imp>::Output { + $imp::$method(*self) + } + } + } +} + +// implements binary operators "&T op U", "T op &U", "&T op &U" +// based on "T op U" where T and U are expected to be `Copy`able +macro_rules! forward_ref_binop { + (impl $imp:ident, $method:ident for $t:ty, $u:ty) => { + forward_ref_binop!(impl $imp, $method for $t, $u, + #[stable(feature = "rust1", since = "1.0.0")]); + }; + (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { + #[$attr] + impl<'a> $imp<$u> for &'a $t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + #[track_caller] + fn $method(self, other: $u) -> <$t as $imp<$u>>::Output { + $imp::$method(*self, other) + } + } + + #[$attr] + impl $imp<&$u> for $t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + #[track_caller] + fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output { + $imp::$method(self, *other) + } + } + + #[$attr] + impl $imp<&$u> for &$t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + #[track_caller] + fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output { + $imp::$method(*self, *other) + } + } + } +} + +// implements "T op= &U", based on "T op= U" +// where U is expected to be `Copy`able +macro_rules! forward_ref_op_assign { + (impl $imp:ident, $method:ident for $t:ty, $u:ty) => { + forward_ref_op_assign!(impl $imp, $method for $t, $u, + #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]); + }; + (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { + #[$attr] + impl $imp<&$u> for $t { + #[inline] + #[track_caller] + fn $method(&mut self, other: &$u) { + $imp::$method(self, *other); + } + } + } +} + +/// Creates a zero-size type similar to a closure type, but named. +macro_rules! impl_fn_for_zst { + ($( + $( #[$attr: meta] )* + struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn = + |$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty + $body: block; + )+) => { + $( + $( #[$attr] )* + struct $Name; + + impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name { + #[inline] + extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy { + $body + } + } + + impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name { + #[inline] + extern "rust-call" fn call_mut( + &mut self, + ($( $arg, )*): ($( $ArgTy, )*) + ) -> $ReturnTy { + Fn::call(&*self, ($( $arg, )*)) + } + } + + impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name { + type Output = $ReturnTy; + + #[inline] + extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy { + Fn::call(&self, ($( $arg, )*)) + } + } + )+ + } +} + +/// A macro for defining `#[cfg]` if-else statements. +/// +/// `cfg_if` is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade +/// of `#[cfg]` cases, emitting the implementation which matches first. +/// +/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code without having to +/// rewrite each clause multiple times. +/// +/// # Example +/// +/// ```ignore(cannot-test-this-because-non-exported-macro) +/// cfg_if! { +/// if #[cfg(unix)] { +/// fn foo() { /* unix specific functionality */ } +/// } else if #[cfg(target_pointer_width = "32")] { +/// fn foo() { /* non-unix, 32-bit functionality */ } +/// } else { +/// fn foo() { /* fallback implementation */ } +/// } +/// } +/// +/// # fn main() {} +/// ``` +// This is a copy of `cfg_if!` from the `cfg_if` crate. +// The recursive invocations should use $crate if this is ever exported. +macro_rules! cfg_if { + // match if/else chains with a final `else` + ( + $( + if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* } + ) else+ + else { $( $e_tokens:tt )* } + ) => { + cfg_if! { + @__items () ; + $( + (( $i_meta ) ( $( $i_tokens )* )) , + )+ + (() ( $( $e_tokens )* )) , + } + }; + + // Internal and recursive macro to emit all the items + // + // Collects all the previous cfgs in a list at the beginning, so they can be + // negated. After the semicolon is all the remaining items. + (@__items ( $( $_:meta , )* ) ; ) => {}; + ( + @__items ( $( $no:meta , )* ) ; + (( $( $yes:meta )? ) ( $( $tokens:tt )* )) , + $( $rest:tt , )* + ) => { + // Emit all items within one block, applying an appropriate #[cfg]. The + // #[cfg] will require all `$yes` matchers specified and must also negate + // all previous matchers. + #[cfg(all( + $( $yes , )? + not(any( $( $no ),* )) + ))] + cfg_if! { @__identity $( $tokens )* } + + // Recurse to emit all other items in `$rest`, and when we do so add all + // our `$yes` matchers to the list of `$no` matchers as future emissions + // will have to negate everything we just matched as well. + cfg_if! { + @__items ( $( $no , )* $( $yes , )? ) ; + $( $rest , )* + } + }; + + // Internal macro to make __apply work out right for different match types, + // because of how macros match/expand stuff. + (@__identity $( $tokens:tt )* ) => { + $( $tokens )* + }; +} diff --git a/CoqOfRust/core/intrinsics/mir.rs b/CoqOfRust/core/intrinsics/mir.rs new file mode 100644 index 000000000..55dcf7cd4 --- /dev/null +++ b/CoqOfRust/core/intrinsics/mir.rs @@ -0,0 +1,736 @@ +//! Rustc internal tooling for hand-writing MIR. +//! +//! If for some reasons you are not writing rustc tests and have found yourself considering using +//! this feature, turn back. This is *exceptionally* unstable. There is no attempt at all to make +//! anything work besides those things which the rustc test suite happened to need. If you make a +//! typo you'll probably ICE. Really, this is not the solution to your problems. Consider instead +//! supporting the [stable MIR project group](https://github.com/rust-lang/project-stable-mir). +//! +//! The documentation for this module describes how to use this feature. If you are interested in +//! hacking on the implementation, most of that documentation lives at +//! `rustc_mir_build/src/build/custom/mod.rs`. +//! +//! Typical usage will look like this: +//! +//! ```rust +//! #![feature(core_intrinsics, custom_mir)] +//! #![allow(internal_features)] +//! +//! use core::intrinsics::mir::*; +//! +//! #[custom_mir(dialect = "built")] +//! pub fn simple(x: i32) -> i32 { +//! mir! { +//! let temp2: i32; +//! +//! { +//! let temp1 = x; +//! Goto(my_second_block) +//! } +//! +//! my_second_block = { +//! temp2 = Move(temp1); +//! RET = temp2; +//! Return() +//! } +//! } +//! } +//! ``` +//! +//! The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This +//! attribute only works on functions - there is no way to insert custom MIR into the middle of +//! another function. The `dialect` and `phase` parameters indicate which [version of MIR][dialect +//! docs] you are inserting here. Generally you'll want to use `#![custom_mir(dialect = "built")]` +//! if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect = +//! "runtime", phase = "optimized")]` if you don't. +//! +//! [dialect docs]: +//! https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.MirPhase.html +//! +//! The input to the [`mir!`] macro is: +//! +//! - An optional return type annotation in the form of `type RET = ...;`. This may be required +//! if the compiler cannot infer the type of RET. +//! - A possibly empty list of local declarations. Locals can also be declared inline on +//! assignments via `let`. Type inference generally works. Shadowing does not. +//! - A list of basic blocks. The first of these is the start block and is where execution begins. +//! All blocks other than the start block need to be given a name, so that they can be referred +//! to later. +//! - Each block is a list of semicolon terminated statements, followed by a terminator. The +//! syntax for the various statements and terminators is designed to be as similar as possible +//! to the syntax for analogous concepts in native Rust. See below for a list. +//! +//! # Examples +//! +//! ```rust +//! #![feature(core_intrinsics, custom_mir)] +//! #![allow(internal_features)] +//! #![allow(unused_assignments)] +//! +//! use core::intrinsics::mir::*; +//! +//! #[custom_mir(dialect = "built")] +//! pub fn choose_load(a: &i32, b: &i32, c: bool) -> i32 { +//! mir! { +//! { +//! match c { +//! true => t, +//! _ => f, +//! } +//! } +//! +//! t = { +//! let temp = a; +//! Goto(load_and_exit) +//! } +//! +//! f = { +//! temp = b; +//! Goto(load_and_exit) +//! } +//! +//! load_and_exit = { +//! RET = *temp; +//! Return() +//! } +//! } +//! } +//! +//! #[custom_mir(dialect = "built")] +//! fn unwrap_unchecked(opt: Option) -> T { +//! mir! { +//! { +//! RET = Move(Field(Variant(opt, 1), 0)); +//! Return() +//! } +//! } +//! } +//! +//! #[custom_mir(dialect = "runtime", phase = "optimized")] +//! fn push_and_pop(v: &mut Vec, value: T) { +//! mir! { +//! let _unused; +//! let popped; +//! +//! { +//! Call(_unused = Vec::push(v, value), ReturnTo(pop), UnwindContinue()) +//! } +//! +//! pop = { +//! Call(popped = Vec::pop(v), ReturnTo(drop), UnwindContinue()) +//! } +//! +//! drop = { +//! Drop(popped, ReturnTo(ret), UnwindContinue()) +//! } +//! +//! ret = { +//! Return() +//! } +//! } +//! } +//! +//! #[custom_mir(dialect = "runtime", phase = "optimized")] +//! fn annotated_return_type() -> (i32, bool) { +//! mir! { +//! type RET = (i32, bool); +//! { +//! RET.0 = 1; +//! RET.1 = true; +//! Return() +//! } +//! } +//! } +//! ``` +//! +//! We can also set off compilation failures that happen in sufficiently late stages of the +//! compiler: +//! +//! ```rust,compile_fail +//! #![feature(core_intrinsics, custom_mir)] +//! +//! extern crate core; +//! use core::intrinsics::mir::*; +//! +//! #[custom_mir(dialect = "built")] +//! fn borrow_error(should_init: bool) -> i32 { +//! mir! { +//! let temp: i32; +//! +//! { +//! match should_init { +//! true => init, +//! _ => use_temp, +//! } +//! } +//! +//! init = { +//! temp = 0; +//! Goto(use_temp) +//! } +//! +//! use_temp = { +//! RET = temp; +//! Return() +//! } +//! } +//! } +//! ``` +//! +//! ```text +//! error[E0381]: used binding is possibly-uninitialized +//! --> test.rs:24:13 +//! | +//! 8 | / mir! { +//! 9 | | let temp: i32; +//! 10 | | +//! 11 | | { +//! ... | +//! 19 | | temp = 0; +//! | | -------- binding initialized here in some conditions +//! ... | +//! 24 | | RET = temp; +//! | | ^^^^^^^^^^ value used here but it is possibly-uninitialized +//! 25 | | Return() +//! 26 | | } +//! 27 | | } +//! | |_____- binding declared here but left uninitialized +//! +//! error: aborting due to 1 previous error +//! +//! For more information about this error, try `rustc --explain E0381`. +//! ``` +//! +//! # Syntax +//! +//! The lists below are an exhaustive description of how various MIR constructs can be created. +//! Anything missing from the list should be assumed to not be supported, PRs welcome. +//! +//! #### Locals +//! +//! - The `_0` return local can always be accessed via `RET`. +//! - Arguments can be accessed via their regular name. +//! - All other locals need to be declared with `let` somewhere and then can be accessed by name. +//! +//! #### Places +//! - Locals implicitly convert to places. +//! - Field accesses, derefs, and indexing work normally. +//! - Fields in variants can be accessed via the [`Variant`] and [`Field`] associated functions, +//! see their documentation for details. +//! +//! #### Operands +//! - Places implicitly convert to `Copy` operands. +//! - `Move` operands can be created via [`Move`]. +//! - Const blocks, literals, named constants, and const params all just work. +//! - [`Static`] and [`StaticMut`] can be used to create `&T` and `*mut T`s to statics. These are +//! constants in MIR and the only way to access statics. +//! +//! #### Statements +//! - Assign statements work via normal Rust assignment. +//! - [`Retag`], [`StorageLive`], [`StorageDead`], [`Deinit`] statements have an associated function. +//! +//! #### Rvalues +//! +//! - Operands implicitly convert to `Use` rvalues. +//! - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue. +//! - [`Discriminant`], [`Len`], and [`CopyForDeref`] have associated functions. +//! - Unary and binary operations use their normal Rust syntax - `a * b`, `!c`, etc. +//! - The binary operation `Offset` can be created via [`Offset`]. +//! - Checked binary operations are represented by wrapping the associated binop in [`Checked`]. +//! - Array repetition syntax (`[foo; 10]`) creates the associated rvalue. +//! +//! #### Terminators +//! +//! - [`Goto`], [`Return`], [`Unreachable`] and [`Drop`](Drop()) have associated functions. +//! - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block` +//! - The exception is the last arm, which must be `_ => basic_block` and corresponds to the +//! otherwise branch. +//! - [`Call`] has an associated function as well, with special syntax: +//! `Call(ret_val = function(arg1, arg2, ...), ReturnTo(next_block), UnwindContinue())`. +//! - [`TailCall`] does not have a return destination or next block, so its syntax is just +//! `TailCall(function(arg1, arg2, ...))`. +//! +//! #### Debuginfo +//! +//! Debuginfo associates source code variable names (of variables that may not exist any more) with +//! MIR expressions that indicate where the value of that variable is stored. The syntax to do so +//! is: +//! ```text +//! debug source_var_name => expression; +//! ``` +//! Both places and constants are supported in the `expression`. +//! +//! ```rust +//! #![allow(internal_features)] +//! #![feature(core_intrinsics, custom_mir)] +//! +//! use core::intrinsics::mir::*; +//! +//! #[custom_mir(dialect = "built")] +//! fn debuginfo(arg: Option<&i32>) { +//! mir!( +//! // Debuginfo for a source variable `plain_local` that just duplicates `arg`. +//! debug plain_local => arg; +//! // Debuginfo for a source variable `projection` that can be computed by dereferencing +//! // a field of `arg`. +//! debug projection => *Field::<&i32>(Variant(arg, 1), 0); +//! // Debuginfo for a source variable `constant` that always holds the value `5`. +//! debug constant => 5_usize; +//! { +//! Return() +//! } +//! ) +//! } +//! ``` + +#![unstable( + feature = "custom_mir", + reason = "MIR is an implementation detail and extremely unstable", + issue = "none" +)] +#![allow(unused_variables, non_snake_case, missing_debug_implementations)] + +/// Type representing basic blocks. +/// +/// All terminators will have this type as a return type. It helps achieve some type safety. +#[rustc_diagnostic_item = "mir_basic_block"] +pub enum BasicBlock { + /// A non-cleanup basic block. + Normal, + /// A basic block that lies on an unwind path. + Cleanup, +} + +/// The reason we are terminating the process during unwinding. +#[rustc_diagnostic_item = "mir_unwind_terminate_reason"] +pub enum UnwindTerminateReason { + /// Unwinding is just not possible given the ABI of this function. + Abi, + /// We were already cleaning up for an ongoing unwind, and a *second*, *nested* unwind was + /// triggered by the drop glue. + InCleanup, +} + +pub use UnwindTerminateReason::{Abi as ReasonAbi, InCleanup as ReasonInCleanup}; + +macro_rules! define { + ($name:literal, $( #[ $meta:meta ] )* fn $($sig:tt)*) => { + #[rustc_diagnostic_item = $name] + #[inline] + $( #[ $meta ] )* + pub fn $($sig)* { panic!() } + } +} + +// Unwind actions +pub struct UnwindActionArg; +define!( + "mir_unwind_continue", + /// An unwind action that continues unwinding. + fn UnwindContinue() -> UnwindActionArg +); +define!( + "mir_unwind_unreachable", + /// An unwind action that triggers undefined behavior. + fn UnwindUnreachable() -> UnwindActionArg +); +define!( + "mir_unwind_terminate", + /// An unwind action that terminates the execution. + /// + /// `UnwindTerminate` can also be used as a terminator. + fn UnwindTerminate(reason: UnwindTerminateReason) -> UnwindActionArg +); +define!( + "mir_unwind_cleanup", + /// An unwind action that continues execution in a given basic block. + fn UnwindCleanup(goto: BasicBlock) -> UnwindActionArg +); + +// Return destination for `Call` +pub struct ReturnToArg; +define!("mir_return_to", fn ReturnTo(goto: BasicBlock) -> ReturnToArg); + +// Terminators +define!("mir_return", fn Return() -> BasicBlock); +define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock); +define!("mir_unreachable", fn Unreachable() -> BasicBlock); +define!("mir_drop", + /// Drop the contents of a place. + /// + /// The first argument must be a place. + /// + /// The second argument must be of the form `ReturnTo(bb)`, where `bb` is the basic block that + /// will be jumped to after the destructor returns. + /// + /// The third argument describes what happens on unwind. It can be one of: + /// - [`UnwindContinue`] + /// - [`UnwindUnreachable`] + /// - [`UnwindTerminate`] + /// - [`UnwindCleanup`] + fn Drop(place: T, goto: ReturnToArg, unwind_action: UnwindActionArg) +); +define!("mir_call", + /// Call a function. + /// + /// The first argument must be of the form `ret_val = fun(arg1, arg2, ...)`. + /// + /// The second argument must be of the form `ReturnTo(bb)`, where `bb` is the basic block that + /// will be jumped to after the function returns. + /// + /// The third argument describes what happens on unwind. It can be one of: + /// - [`UnwindContinue`] + /// - [`UnwindUnreachable`] + /// - [`UnwindTerminate`] + /// - [`UnwindCleanup`] + fn Call(call: (), goto: ReturnToArg, unwind_action: UnwindActionArg) +); +define!("mir_tail_call", + /// Call a function. + /// + /// The argument must be of the form `fun(arg1, arg2, ...)`. + fn TailCall(call: T) +); +define!("mir_unwind_resume", + /// A terminator that resumes the unwinding. + fn UnwindResume() +); + +define!("mir_storage_live", fn StorageLive(local: T)); +define!("mir_storage_dead", fn StorageDead(local: T)); +define!("mir_assume", fn Assume(operand: bool)); +define!("mir_deinit", fn Deinit(place: T)); +define!("mir_checked", fn Checked(binop: T) -> (T, bool)); +define!("mir_len", fn Len(place: T) -> usize); +define!( + "mir_ptr_metadata", + fn PtrMetadata(place: *const P) ->

::Metadata +); +define!("mir_copy_for_deref", fn CopyForDeref(place: T) -> T); +define!("mir_retag", fn Retag(place: T)); +define!("mir_move", fn Move(place: T) -> T); +define!("mir_static", fn Static(s: T) -> &'static T); +define!("mir_static_mut", fn StaticMut(s: T) -> *mut T); +define!( + "mir_discriminant", + /// Gets the discriminant of a place. + fn Discriminant(place: T) -> ::Discriminant +); +define!("mir_set_discriminant", fn SetDiscriminant(place: T, index: u32)); +define!("mir_offset", fn Offset(ptr: T, count: U) -> T); +define!( + "mir_field", + /// Access the field with the given index of some place. + /// + /// This only makes sense to use in conjunction with [`Variant`]. If the type you are looking to + /// access the field of does not have variants, you can use normal field projection syntax. + /// + /// There is no proper way to do a place projection to a variant in Rust, and so these two + /// functions are a workaround. You can access a field of a variant via `Field(Variant(place, + /// var_idx), field_idx)`, where `var_idx` and `field_idx` are appropriate literals. Some + /// caveats: + /// + /// - The return type of `Variant` is always `()`. Don't worry about that, the correct MIR will + /// still be generated. + /// - In some situations, the return type of `Field` cannot be inferred. You may need to + /// annotate it on the function in these cases. + /// - Since `Field` is a function call which is not a place expression, using this on the left + /// hand side of an expression is rejected by the compiler. [`place!`] is a macro provided to + /// work around that issue. Wrap the left hand side of an assignment in the macro to convince + /// the compiler that it's ok. + /// + /// # Examples + /// + /// ```rust + /// #![allow(internal_features)] + /// #![feature(custom_mir, core_intrinsics)] + /// + /// use core::intrinsics::mir::*; + /// + /// #[custom_mir(dialect = "built")] + /// fn unwrap_deref(opt: Option<&i32>) -> i32 { + /// mir! { + /// { + /// RET = *Field::<&i32>(Variant(opt, 1), 0); + /// Return() + /// } + /// } + /// } + /// + /// #[custom_mir(dialect = "built")] + /// fn set(opt: &mut Option) { + /// mir! { + /// { + /// place!(Field(Variant(*opt, 1), 0)) = 5; + /// Return() + /// } + /// } + /// } + /// ``` + fn Field(place: (), field: u32) -> F +); +define!( + "mir_variant", + /// Adds a variant projection with the given index to the place. + /// + /// See [`Field`] for documentation. + fn Variant(place: T, index: u32) -> () +); +define!( + "mir_cast_transmute", + /// Emits a `CastKind::Transmute` cast. + /// + /// Needed to test the UB when `sizeof(T) != sizeof(U)`, which can't be + /// generated via the normal `mem::transmute`. + fn CastTransmute(operand: T) -> U +); +define!( + "mir_cast_ptr_to_ptr", + /// Emits a `CastKind::PtrToPtr` cast. + /// + /// This allows bypassing normal validation to generate strange casts. + fn CastPtrToPtr(operand: T) -> U +); +define!( + "mir_make_place", + #[doc(hidden)] + fn __internal_make_place(place: T) -> *mut T +); +define!( + "mir_debuginfo", + #[doc(hidden)] + fn __debuginfo(name: &'static str, s: T) +); + +/// Macro for generating custom MIR. +/// +/// See the module documentation for syntax details. This macro is not magic - it only transforms +/// your MIR into something that is easier to parse in the compiler. +#[rustc_macro_transparency = "transparent"] +pub macro mir { + { + $(type RET = $ret_ty:ty ;)? + $(let $local_decl:ident $(: $local_decl_ty:ty)? ;)* + $(debug $dbg_name:ident => $dbg_data:expr ;)* + + { + $($entry:tt)* + } + + $( + $block_name:ident $(($block_cleanup:ident))? = { + $($block:tt)* + } + )* + } => {{ + // First, we declare all basic blocks. + __internal_declare_basic_blocks!($( + $block_name $(($block_cleanup))? + )*); + { + // Now all locals + #[allow(non_snake_case)] + let RET $(: $ret_ty)?; + $( + let $local_decl $(: $local_decl_ty)? ; + )* + ::core::intrinsics::mir::__internal_extract_let!($($entry)*); + $( + ::core::intrinsics::mir::__internal_extract_let!($($block)*); + )* + + { + // Now debuginfo + $( + __debuginfo(stringify!($dbg_name), $dbg_data); + )* + + { + // Finally, the contents of the basic blocks + ::core::intrinsics::mir::__internal_remove_let!({ + {} + { $($entry)* } + }); + $( + ::core::intrinsics::mir::__internal_remove_let!({ + {} + { $($block)* } + }); + )* + + RET + } + } + } + }} +} + +/// Helper macro that allows you to treat a value expression like a place expression. +/// +/// See the documentation on [`Variant`] for why this is necessary and how to use it. +pub macro place($e:expr) { + (*::core::intrinsics::mir::__internal_make_place($e)) +} + +/// Helper macro that extracts the `let` declarations out of a bunch of statements. +/// +/// This macro is written using the "statement muncher" strategy. Each invocation parses the first +/// statement out of the input, does the appropriate thing with it, and then recursively calls the +/// same macro on the remainder of the input. +#[doc(hidden)] +pub macro __internal_extract_let { + // If it's a `let` like statement, keep the `let` + ( + let $var:ident $(: $ty:ty)? = $expr:expr; $($rest:tt)* + ) => { + let $var $(: $ty)?; + ::core::intrinsics::mir::__internal_extract_let!($($rest)*); + }, + // Due to #86730, we have to handle const blocks separately + ( + let $var:ident $(: $ty:ty)? = const $block:block; $($rest:tt)* + ) => { + let $var $(: $ty)?; + ::core::intrinsics::mir::__internal_extract_let!($($rest)*); + }, + // Otherwise, output nothing + ( + $stmt:stmt; $($rest:tt)* + ) => { + ::core::intrinsics::mir::__internal_extract_let!($($rest)*); + }, + ( + $expr:expr + ) => {} +} + +/// Helper macro that removes the `let` declarations from a bunch of statements. +/// +/// Because expression position macros cannot expand to statements + expressions, we need to be +/// slightly creative here. The general strategy is also statement munching as above, but the output +/// of the macro is "stored" in the subsequent macro invocation. Easiest understood via example: +/// ```text +/// invoke!( +/// { +/// { +/// x = 5; +/// } +/// { +/// let d = e; +/// Call() +/// } +/// } +/// ) +/// ``` +/// becomes +/// ```text +/// invoke!( +/// { +/// { +/// x = 5; +/// d = e; +/// } +/// { +/// Call() +/// } +/// } +/// ) +/// ``` +#[doc(hidden)] +pub macro __internal_remove_let { + // If it's a `let` like statement, remove the `let` + ( + { + { + $($already_parsed:tt)* + } + { + let $var:ident $(: $ty:ty)? = $expr:expr; + $($rest:tt)* + } + } + ) => { ::core::intrinsics::mir::__internal_remove_let!( + { + { + $($already_parsed)* + $var = $expr; + } + { + $($rest)* + } + } + )}, + // Due to #86730 , we have to handle const blocks separately + ( + { + { + $($already_parsed:tt)* + } + { + let $var:ident $(: $ty:ty)? = const $block:block; + $($rest:tt)* + } + } + ) => { ::core::intrinsics::mir::__internal_remove_let!( + { + { + $($already_parsed)* + $var = const $block; + } + { + $($rest)* + } + } + )}, + // Otherwise, keep going + ( + { + { + $($already_parsed:tt)* + } + { + $stmt:stmt; + $($rest:tt)* + } + } + ) => { ::core::intrinsics::mir::__internal_remove_let!( + { + { + $($already_parsed)* + $stmt; + } + { + $($rest)* + } + } + )}, + ( + { + { + $($already_parsed:tt)* + } + { + $expr:expr + } + } + ) => { + { + $($already_parsed)* + $expr + } + }, +} + +/// Helper macro that declares the basic blocks. +#[doc(hidden)] +pub macro __internal_declare_basic_blocks { + () => {}, + ($name:ident (cleanup) $($rest:tt)*) => { + let $name = ::core::intrinsics::mir::BasicBlock::Cleanup; + __internal_declare_basic_blocks!($($rest)*) + }, + ($name:ident $($rest:tt)*) => { + let $name = ::core::intrinsics::mir::BasicBlock::Normal; + __internal_declare_basic_blocks!($($rest)*) + }, +} diff --git a/CoqOfRust/core/intrinsics/mod.rs b/CoqOfRust/core/intrinsics/mod.rs new file mode 100644 index 000000000..802b571c5 --- /dev/null +++ b/CoqOfRust/core/intrinsics/mod.rs @@ -0,0 +1,4764 @@ +//! Compiler intrinsics. +//! +//! The corresponding definitions are in . +//! The corresponding const implementations are in . +//! +//! # Const intrinsics +//! +//! Note: any changes to the constness of intrinsics should be discussed with the language team. +//! This includes changes in the stability of the constness. +//! +//! In order to make an intrinsic usable at compile-time, it needs to be declared in the "new" +//! style, i.e. as a `#[rustc_intrinsic]` function, not inside an `extern` block. Then copy the +//! implementation from to +//! +//! and make the intrinsic declaration a `const fn`. +//! +//! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute, +//! `#[rustc_intrinsic_const_stable_indirect]` needs to be added to the intrinsic. Such a change requires +//! T-lang approval, because it may bake a feature into the language that cannot be replicated in +//! user code without compiler support. +//! +//! # Volatiles +//! +//! The volatile intrinsics provide operations intended to act on I/O +//! memory, which are guaranteed to not be reordered by the compiler +//! across other volatile intrinsics. See the LLVM documentation on +//! [[volatile]]. +//! +//! [volatile]: https://llvm.org/docs/LangRef.html#volatile-memory-accesses +//! +//! # Atomics +//! +//! The atomic intrinsics provide common atomic operations on machine +//! words, with multiple possible memory orderings. They obey the same +//! semantics as C++11. See the LLVM documentation on [[atomics]]. +//! +//! [atomics]: https://llvm.org/docs/Atomics.html +//! +//! A quick refresher on memory ordering: +//! +//! * Acquire - a barrier for acquiring a lock. Subsequent reads and writes +//! take place after the barrier. +//! * Release - a barrier for releasing a lock. Preceding reads and writes +//! take place before the barrier. +//! * Sequentially consistent - sequentially consistent operations are +//! guaranteed to happen in order. This is the standard mode for working +//! with atomic types and is equivalent to Java's `volatile`. +//! +//! # Unwinding +//! +//! Rust intrinsics may, in general, unwind. If an intrinsic can never unwind, add the +//! `#[rustc_nounwind]` attribute so that the compiler can make use of this fact. +//! +//! However, even for intrinsics that may unwind, rustc assumes that a Rust intrinsics will never +//! initiate a foreign (non-Rust) unwind, and thus for panic=abort we can always assume that these +//! intrinsics cannot unwind. + +#![unstable( + feature = "core_intrinsics", + reason = "intrinsics are unlikely to ever be stabilized, instead \ + they should be used through stabilized interfaces \ + in the rest of the standard library", + issue = "none" +)] +#![allow(missing_docs)] + +use crate::marker::{DiscriminantKind, Tuple}; +use crate::mem::SizedTypeProperties; +use crate::{ptr, ub_checks}; + +pub mod mir; +pub mod simd; + +// These imports are used for simplifying intra-doc links +#[allow(unused_imports)] +#[cfg(all(target_has_atomic = "8", target_has_atomic = "32", target_has_atomic = "ptr"))] +use crate::sync::atomic::{self, AtomicBool, AtomicI32, AtomicIsize, AtomicU32, Ordering}; + +#[stable(feature = "drop_in_place", since = "1.8.0")] +#[rustc_allowed_through_unstable_modules] +#[deprecated(note = "no longer an intrinsic - use `ptr::drop_in_place` directly", since = "1.52.0")] +#[inline] +pub unsafe fn drop_in_place(to_drop: *mut T) { + // SAFETY: see `ptr::drop_in_place` + unsafe { crate::ptr::drop_in_place(to_drop) } +} + +// N.B., these intrinsics take raw pointers because they mutate aliased +// memory, which is not valid for either `&` or `&mut`. + +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::Relaxed`] as both the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_relaxed_relaxed(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::Relaxed`] and [`Ordering::Acquire`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_relaxed_acquire(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::Relaxed`] and [`Ordering::SeqCst`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_relaxed_seqcst(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::Acquire`] and [`Ordering::Relaxed`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_acquire_relaxed(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::Acquire`] as both the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_acquire_acquire(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::Acquire`] and [`Ordering::SeqCst`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_acquire_seqcst(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::Release`] and [`Ordering::Relaxed`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_release_relaxed(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::Release`] and [`Ordering::Acquire`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_release_acquire(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::Release`] and [`Ordering::SeqCst`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_release_seqcst(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::AcqRel`] and [`Ordering::Relaxed`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_acqrel_relaxed(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::AcqRel`] and [`Ordering::Acquire`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_acqrel_acquire(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::AcqRel`] and [`Ordering::SeqCst`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_acqrel_seqcst(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::SeqCst`] and [`Ordering::Relaxed`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_seqcst_relaxed(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::SeqCst`] and [`Ordering::Acquire`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_seqcst_acquire(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange` method by passing +/// [`Ordering::SeqCst`] as both the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchg_seqcst_seqcst(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} + +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::Relaxed`] as both the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_relaxed_relaxed( + _dst: *mut T, + _old: T, + _src: T, +) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::Relaxed`] and [`Ordering::Acquire`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_relaxed_acquire( + _dst: *mut T, + _old: T, + _src: T, +) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::Relaxed`] and [`Ordering::SeqCst`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_relaxed_seqcst( + _dst: *mut T, + _old: T, + _src: T, +) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::Acquire`] and [`Ordering::Relaxed`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_acquire_relaxed( + _dst: *mut T, + _old: T, + _src: T, +) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::Acquire`] as both the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_acquire_acquire( + _dst: *mut T, + _old: T, + _src: T, +) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::Acquire`] and [`Ordering::SeqCst`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_acquire_seqcst( + _dst: *mut T, + _old: T, + _src: T, +) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::Release`] and [`Ordering::Relaxed`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_release_relaxed( + _dst: *mut T, + _old: T, + _src: T, +) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::Release`] and [`Ordering::Acquire`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_release_acquire( + _dst: *mut T, + _old: T, + _src: T, +) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::Release`] and [`Ordering::SeqCst`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_release_seqcst( + _dst: *mut T, + _old: T, + _src: T, +) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::AcqRel`] and [`Ordering::Relaxed`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_acqrel_relaxed( + _dst: *mut T, + _old: T, + _src: T, +) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::AcqRel`] and [`Ordering::Acquire`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_acqrel_acquire( + _dst: *mut T, + _old: T, + _src: T, +) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::AcqRel`] and [`Ordering::SeqCst`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_acqrel_seqcst(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::SeqCst`] and [`Ordering::Relaxed`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_seqcst_relaxed( + _dst: *mut T, + _old: T, + _src: T, +) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::SeqCst`] and [`Ordering::Acquire`] as the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_seqcst_acquire( + _dst: *mut T, + _old: T, + _src: T, +) -> (T, bool) { + unreachable!() +} +/// Stores a value if the current value is the same as the `old` value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `compare_exchange_weak` method by passing +/// [`Ordering::SeqCst`] as both the success and failure parameters. +/// For example, [`AtomicBool::compare_exchange_weak`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_cxchgweak_seqcst_seqcst(_dst: *mut T, _old: T, _src: T) -> (T, bool) { + unreachable!() +} + +/// Loads the current value of the pointer. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `load` method by passing +/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::load`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_load_seqcst(_src: *const T) -> T { + unreachable!() +} +/// Loads the current value of the pointer. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `load` method by passing +/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::load`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_load_acquire(_src: *const T) -> T { + unreachable!() +} +/// Loads the current value of the pointer. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `load` method by passing +/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::load`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_load_relaxed(_src: *const T) -> T { + unreachable!() +} +/// Do NOT use this intrinsic; "unordered" operations do not exist in our memory model! +/// In terms of the Rust Abstract Machine, this operation is equivalent to `src.read()`, +/// i.e., it performs a non-atomic read. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_load_unordered(_src: *const T) -> T { + unreachable!() +} + +/// Stores the value at the specified memory location. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `store` method by passing +/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::store`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_store_seqcst(_dst: *mut T, _val: T) { + unreachable!() +} +/// Stores the value at the specified memory location. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `store` method by passing +/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::store`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_store_release(_dst: *mut T, _val: T) { + unreachable!() +} +/// Stores the value at the specified memory location. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `store` method by passing +/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::store`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_store_relaxed(_dst: *mut T, _val: T) { + unreachable!() +} +/// Do NOT use this intrinsic; "unordered" operations do not exist in our memory model! +/// In terms of the Rust Abstract Machine, this operation is equivalent to `dst.write(val)`, +/// i.e., it performs a non-atomic write. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_store_unordered(_dst: *mut T, _val: T) { + unreachable!() +} + +/// Stores the value at the specified memory location, returning the old value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `swap` method by passing +/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::swap`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xchg_seqcst(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Stores the value at the specified memory location, returning the old value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `swap` method by passing +/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::swap`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xchg_acquire(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Stores the value at the specified memory location, returning the old value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `swap` method by passing +/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::swap`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xchg_release(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Stores the value at the specified memory location, returning the old value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `swap` method by passing +/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::swap`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xchg_acqrel(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Stores the value at the specified memory location, returning the old value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `swap` method by passing +/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::swap`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xchg_relaxed(_dst: *mut T, _src: T) -> T { + unreachable!() +} + +/// Adds to the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_add` method by passing +/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_add`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xadd_seqcst(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Adds to the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_add` method by passing +/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_add`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xadd_acquire(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Adds to the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_add` method by passing +/// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_add`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xadd_release(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Adds to the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_add` method by passing +/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicIsize::fetch_add`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xadd_acqrel(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Adds to the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_add` method by passing +/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicIsize::fetch_add`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xadd_relaxed(_dst: *mut T, _src: T) -> T { + unreachable!() +} + +/// Subtract from the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_sub` method by passing +/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xsub_seqcst(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Subtract from the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_sub` method by passing +/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xsub_acquire(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Subtract from the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_sub` method by passing +/// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xsub_release(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Subtract from the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_sub` method by passing +/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xsub_acqrel(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Subtract from the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_sub` method by passing +/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xsub_relaxed(_dst: *mut T, _src: T) -> T { + unreachable!() +} + +/// Bitwise and with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_and` method by passing +/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_and`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_and_seqcst(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise and with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_and` method by passing +/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_and`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_and_acquire(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise and with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_and` method by passing +/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_and`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_and_release(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise and with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_and` method by passing +/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_and`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_and_acqrel(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise and with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_and` method by passing +/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_and`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_and_relaxed(_dst: *mut T, _src: T) -> T { + unreachable!() +} + +/// Bitwise nand with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`AtomicBool`] type via the `fetch_nand` method by passing +/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_nand`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_nand_seqcst(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise nand with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`AtomicBool`] type via the `fetch_nand` method by passing +/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_nand`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_nand_acquire(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise nand with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`AtomicBool`] type via the `fetch_nand` method by passing +/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_nand`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_nand_release(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise nand with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`AtomicBool`] type via the `fetch_nand` method by passing +/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_nand`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_nand_acqrel(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise nand with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`AtomicBool`] type via the `fetch_nand` method by passing +/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_nand`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_nand_relaxed(_dst: *mut T, _src: T) -> T { + unreachable!() +} + +/// Bitwise or with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_or` method by passing +/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_or`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_or_seqcst(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise or with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_or` method by passing +/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_or`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_or_acquire(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise or with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_or` method by passing +/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_or`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_or_release(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise or with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_or` method by passing +/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_or`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_or_acqrel(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise or with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_or` method by passing +/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_or`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_or_relaxed(_dst: *mut T, _src: T) -> T { + unreachable!() +} + +/// Bitwise xor with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_xor` method by passing +/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_xor`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xor_seqcst(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise xor with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_xor` method by passing +/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_xor`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xor_acquire(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise xor with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_xor` method by passing +/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_xor`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xor_release(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise xor with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_xor` method by passing +/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_xor`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xor_acqrel(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Bitwise xor with the current value, returning the previous value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] types via the `fetch_xor` method by passing +/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_xor`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_xor_relaxed(_dst: *mut T, _src: T) -> T { + unreachable!() +} + +/// Maximum with the current value using a signed comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] signed integer types via the `fetch_max` method by passing +/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_max`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_max_seqcst(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Maximum with the current value using a signed comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] signed integer types via the `fetch_max` method by passing +/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_max`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_max_acquire(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Maximum with the current value using a signed comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] signed integer types via the `fetch_max` method by passing +/// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_max`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_max_release(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Maximum with the current value using a signed comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] signed integer types via the `fetch_max` method by passing +/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_max`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_max_acqrel(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Maximum with the current value. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] signed integer types via the `fetch_max` method by passing +/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicI32::fetch_max`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_max_relaxed(_dst: *mut T, _src: T) -> T { + unreachable!() +} + +/// Minimum with the current value using a signed comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] signed integer types via the `fetch_min` method by passing +/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_min`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_min_seqcst(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Minimum with the current value using a signed comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] signed integer types via the `fetch_min` method by passing +/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_min`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_min_acquire(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Minimum with the current value using a signed comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] signed integer types via the `fetch_min` method by passing +/// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_min`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_min_release(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Minimum with the current value using a signed comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] signed integer types via the `fetch_min` method by passing +/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_min`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_min_acqrel(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Minimum with the current value using a signed comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] signed integer types via the `fetch_min` method by passing +/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicI32::fetch_min`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_min_relaxed(_dst: *mut T, _src: T) -> T { + unreachable!() +} + +/// Minimum with the current value using an unsigned comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] unsigned integer types via the `fetch_min` method by passing +/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_min`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_umin_seqcst(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Minimum with the current value using an unsigned comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] unsigned integer types via the `fetch_min` method by passing +/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_min`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_umin_acquire(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Minimum with the current value using an unsigned comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] unsigned integer types via the `fetch_min` method by passing +/// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_min`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_umin_release(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Minimum with the current value using an unsigned comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] unsigned integer types via the `fetch_min` method by passing +/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicU32::fetch_min`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_umin_acqrel(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Minimum with the current value using an unsigned comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] unsigned integer types via the `fetch_min` method by passing +/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_min`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_umin_relaxed(_dst: *mut T, _src: T) -> T { + unreachable!() +} + +/// Maximum with the current value using an unsigned comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] unsigned integer types via the `fetch_max` method by passing +/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_max`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_umax_seqcst(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Maximum with the current value using an unsigned comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] unsigned integer types via the `fetch_max` method by passing +/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_max`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_umax_acquire(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Maximum with the current value using an unsigned comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] unsigned integer types via the `fetch_max` method by passing +/// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_max`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_umax_release(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Maximum with the current value using an unsigned comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] unsigned integer types via the `fetch_max` method by passing +/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicU32::fetch_max`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_umax_acqrel(_dst: *mut T, _src: T) -> T { + unreachable!() +} +/// Maximum with the current value using an unsigned comparison. +/// +/// The stabilized version of this intrinsic is available on the +/// [`atomic`] unsigned integer types via the `fetch_max` method by passing +/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_max`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_umax_relaxed(_dst: *mut T, _src: T) -> T { + unreachable!() +} + +/// An atomic fence. +/// +/// The stabilized version of this intrinsic is available in +/// [`atomic::fence`] by passing [`Ordering::SeqCst`] +/// as the `order`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_fence_seqcst() { + unreachable!() +} +/// An atomic fence. +/// +/// The stabilized version of this intrinsic is available in +/// [`atomic::fence`] by passing [`Ordering::Acquire`] +/// as the `order`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_fence_acquire() { + unreachable!() +} +/// An atomic fence. +/// +/// The stabilized version of this intrinsic is available in +/// [`atomic::fence`] by passing [`Ordering::Release`] +/// as the `order`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_fence_release() { + unreachable!() +} +/// An atomic fence. +/// +/// The stabilized version of this intrinsic is available in +/// [`atomic::fence`] by passing [`Ordering::AcqRel`] +/// as the `order`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_fence_acqrel() { + unreachable!() +} + +/// A compiler-only memory barrier. +/// +/// Memory accesses will never be reordered across this barrier by the +/// compiler, but no instructions will be emitted for it. This is +/// appropriate for operations on the same thread that may be preempted, +/// such as when interacting with signal handlers. +/// +/// The stabilized version of this intrinsic is available in +/// [`atomic::compiler_fence`] by passing [`Ordering::SeqCst`] +/// as the `order`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_singlethreadfence_seqcst() { + unreachable!() +} +/// A compiler-only memory barrier. +/// +/// Memory accesses will never be reordered across this barrier by the +/// compiler, but no instructions will be emitted for it. This is +/// appropriate for operations on the same thread that may be preempted, +/// such as when interacting with signal handlers. +/// +/// The stabilized version of this intrinsic is available in +/// [`atomic::compiler_fence`] by passing [`Ordering::Acquire`] +/// as the `order`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_singlethreadfence_acquire() { + unreachable!() +} +/// A compiler-only memory barrier. +/// +/// Memory accesses will never be reordered across this barrier by the +/// compiler, but no instructions will be emitted for it. This is +/// appropriate for operations on the same thread that may be preempted, +/// such as when interacting with signal handlers. +/// +/// The stabilized version of this intrinsic is available in +/// [`atomic::compiler_fence`] by passing [`Ordering::Release`] +/// as the `order`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_singlethreadfence_release() { + unreachable!() +} +/// A compiler-only memory barrier. +/// +/// Memory accesses will never be reordered across this barrier by the +/// compiler, but no instructions will be emitted for it. This is +/// appropriate for operations on the same thread that may be preempted, +/// such as when interacting with signal handlers. +/// +/// The stabilized version of this intrinsic is available in +/// [`atomic::compiler_fence`] by passing [`Ordering::AcqRel`] +/// as the `order`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn atomic_singlethreadfence_acqrel() { + unreachable!() +} + +/// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction +/// if supported; otherwise, it is a no-op. +/// Prefetches have no effect on the behavior of the program but can change its performance +/// characteristics. +/// +/// The `locality` argument must be a constant integer and is a temporal locality specifier +/// ranging from (0) - no locality, to (3) - extremely local keep in cache. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn prefetch_read_data(_data: *const T, _locality: i32) { + unreachable!() +} +/// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction +/// if supported; otherwise, it is a no-op. +/// Prefetches have no effect on the behavior of the program but can change its performance +/// characteristics. +/// +/// The `locality` argument must be a constant integer and is a temporal locality specifier +/// ranging from (0) - no locality, to (3) - extremely local keep in cache. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn prefetch_write_data(_data: *const T, _locality: i32) { + unreachable!() +} +/// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction +/// if supported; otherwise, it is a no-op. +/// Prefetches have no effect on the behavior of the program but can change its performance +/// characteristics. +/// +/// The `locality` argument must be a constant integer and is a temporal locality specifier +/// ranging from (0) - no locality, to (3) - extremely local keep in cache. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn prefetch_read_instruction(_data: *const T, _locality: i32) { + unreachable!() +} +/// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction +/// if supported; otherwise, it is a no-op. +/// Prefetches have no effect on the behavior of the program but can change its performance +/// characteristics. +/// +/// The `locality` argument must be a constant integer and is a temporal locality specifier +/// ranging from (0) - no locality, to (3) - extremely local keep in cache. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn prefetch_write_instruction(_data: *const T, _locality: i32) { + unreachable!() +} + +/// Executes a breakpoint trap, for inspection by a debugger. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +#[cfg(not(bootstrap))] +pub fn breakpoint() { + unreachable!() +} + +/// Executes a breakpoint trap, for inspection by a debugger. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +#[cfg(bootstrap)] +pub unsafe fn breakpoint() { + unreachable!() +} + +/// Magic intrinsic that derives its meaning from attributes +/// attached to the function. +/// +/// For example, dataflow uses this to inject static assertions so +/// that `rustc_peek(potentially_uninitialized)` would actually +/// double-check that dataflow did indeed compute that it is +/// uninitialized at that point in the control flow. +/// +/// This intrinsic should not be used outside of the compiler. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn rustc_peek(_: T) -> T { + unreachable!() +} + +/// Aborts the execution of the process. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// [`std::process::abort`](../../std/process/fn.abort.html) is to be preferred if possible, +/// as its behavior is more user-friendly and more stable. +/// +/// The current implementation of `intrinsics::abort` is to invoke an invalid instruction, +/// on most platforms. +/// On Unix, the +/// process will probably terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or +/// `SIGBUS`. The precise behavior is not guaranteed and not stable. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn abort() -> ! { + unreachable!() +} + +/// Informs the optimizer that this point in the code is not reachable, +/// enabling further optimizations. +/// +/// N.B., this is very different from the `unreachable!()` macro: Unlike the +/// macro, which panics when it is executed, it is *undefined behavior* to +/// reach code marked with this function. +/// +/// The stabilized version of this intrinsic is [`core::hint::unreachable_unchecked`]. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unreachable() -> ! { + unreachable!() +} + +/// Informs the optimizer that a condition is always true. +/// If the condition is false, the behavior is undefined. +/// +/// No code is generated for this intrinsic, but the optimizer will try +/// to preserve it (and its condition) between passes, which may interfere +/// with optimization of surrounding code and reduce performance. It should +/// not be used if the invariant can be discovered by the optimizer on its +/// own, or if it does not enable any significant optimizations. +/// +/// The stabilized version of this intrinsic is [`core::hint::assert_unchecked`]. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +pub const unsafe fn assume(b: bool) { + if !b { + // SAFETY: the caller must guarantee the argument is never `false` + unsafe { unreachable() } + } +} + +/// Hints to the compiler that current code path is cold. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// This intrinsic does not have a stable counterpart. +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +#[rustc_nounwind] +#[miri::intrinsic_fallback_is_spec] +#[cold] +pub const fn cold_path() {} + +/// Hints to the compiler that branch condition is likely to be true. +/// Returns the value passed to it. +/// +/// Any use other than with `if` statements will probably not have an effect. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// This intrinsic does not have a stable counterpart. +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_nounwind] +#[inline(always)] +pub const fn likely(b: bool) -> bool { + if b { + true + } else { + cold_path(); + false + } +} + +/// Hints to the compiler that branch condition is likely to be false. +/// Returns the value passed to it. +/// +/// Any use other than with `if` statements will probably not have an effect. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// This intrinsic does not have a stable counterpart. +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_nounwind] +#[inline(always)] +pub const fn unlikely(b: bool) -> bool { + if b { + cold_path(); + true + } else { + false + } +} + +/// Returns either `true_val` or `false_val` depending on condition `b` with a +/// hint to the compiler that this condition is unlikely to be correctly +/// predicted by a CPU's branch predictor (e.g. a binary search). +/// +/// This is otherwise functionally equivalent to `if b { true_val } else { false_val }`. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// This intrinsic does not have a stable counterpart. +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +#[rustc_nounwind] +#[miri::intrinsic_fallback_is_spec] +#[inline] +pub fn select_unpredictable(b: bool, true_val: T, false_val: T) -> T { + if b { true_val } else { false_val } +} + +/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited: +/// This will statically either panic, or do nothing. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn assert_inhabited() { + unreachable!() +} + +/// A guard for unsafe functions that cannot ever be executed if `T` does not permit +/// zero-initialization: This will statically either panic, or do nothing. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn assert_zero_valid() { + unreachable!() +} + +/// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn assert_mem_uninitialized_valid() { + unreachable!() +} + +/// Gets a reference to a static `Location` indicating where it was called. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// Consider using [`core::panic::Location::caller`] instead. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn caller_location() -> &'static crate::panic::Location<'static> { + unreachable!() +} + +/// Moves a value out of scope without running drop glue. +/// +/// This exists solely for [`crate::mem::forget_unsized`]; normal `forget` uses +/// `ManuallyDrop` instead. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn forget(_: T) { + unreachable!() +} + +/// Reinterprets the bits of a value of one type as another type. +/// +/// Both types must have the same size. Compilation will fail if this is not guaranteed. +/// +/// `transmute` is semantically equivalent to a bitwise move of one type +/// into another. It copies the bits from the source value into the +/// destination value, then forgets the original. Note that source and destination +/// are passed by-value, which means if `Src` or `Dst` contain padding, that padding +/// is *not* guaranteed to be preserved by `transmute`. +/// +/// Both the argument and the result must be [valid](../../nomicon/what-unsafe-does.html) at +/// their given type. Violating this condition leads to [undefined behavior][ub]. The compiler +/// will generate code *assuming that you, the programmer, ensure that there will never be +/// undefined behavior*. It is therefore your responsibility to guarantee that every value +/// passed to `transmute` is valid at both types `Src` and `Dst`. Failing to uphold this condition +/// may lead to unexpected and unstable compilation results. This makes `transmute` **incredibly +/// unsafe**. `transmute` should be the absolute last resort. +/// +/// Because `transmute` is a by-value operation, alignment of the *transmuted values +/// themselves* is not a concern. As with any other function, the compiler already ensures +/// both `Src` and `Dst` are properly aligned. However, when transmuting values that *point +/// elsewhere* (such as pointers, references, boxes…), the caller has to ensure proper +/// alignment of the pointed-to values. +/// +/// The [nomicon](../../nomicon/transmutes.html) has additional documentation. +/// +/// [ub]: ../../reference/behavior-considered-undefined.html +/// +/// # Transmutation between pointers and integers +/// +/// Special care has to be taken when transmuting between pointers and integers, e.g. +/// transmuting between `*const ()` and `usize`. +/// +/// Transmuting *pointers to integers* in a `const` context is [undefined behavior][ub], unless +/// the pointer was originally created *from* an integer. (That includes this function +/// specifically, integer-to-pointer casts, and helpers like [`dangling`][crate::ptr::dangling], +/// but also semantically-equivalent conversions such as punning through `repr(C)` union +/// fields.) Any attempt to use the resulting value for integer operations will abort +/// const-evaluation. (And even outside `const`, such transmutation is touching on many +/// unspecified aspects of the Rust memory model and should be avoided. See below for +/// alternatives.) +/// +/// Transmuting *integers to pointers* is a largely unspecified operation. It is likely *not* +/// equivalent to an `as` cast. Doing non-zero-sized memory accesses with a pointer constructed +/// this way is currently considered undefined behavior. +/// +/// All this also applies when the integer is nested inside an array, tuple, struct, or enum. +/// However, `MaybeUninit` is not considered an integer type for the purpose of this +/// section. Transmuting `*const ()` to `MaybeUninit` is fine---but then calling +/// `assume_init()` on that result is considered as completing the pointer-to-integer transmute +/// and thus runs into the issues discussed above. +/// +/// In particular, doing a pointer-to-integer-to-pointer roundtrip via `transmute` is *not* a +/// lossless process. If you want to round-trip a pointer through an integer in a way that you +/// can get back the original pointer, you need to use `as` casts, or replace the integer type +/// by `MaybeUninit<$int>` (and never call `assume_init()`). If you are looking for a way to +/// store data of arbitrary type, also use `MaybeUninit` (that will also handle uninitialized +/// memory due to padding). If you specifically need to store something that is "either an +/// integer or a pointer", use `*mut ()`: integers can be converted to pointers and back without +/// any loss (via `as` casts or via `transmute`). +/// +/// # Examples +/// +/// There are a few things that `transmute` is really useful for. +/// +/// Turning a pointer into a function pointer. This is *not* portable to +/// machines where function pointers and data pointers have different sizes. +/// +/// ``` +/// fn foo() -> i32 { +/// 0 +/// } +/// // Crucially, we `as`-cast to a raw pointer before `transmute`ing to a function pointer. +/// // This avoids an integer-to-pointer `transmute`, which can be problematic. +/// // Transmuting between raw pointers and function pointers (i.e., two pointer types) is fine. +/// let pointer = foo as *const (); +/// let function = unsafe { +/// std::mem::transmute::<*const (), fn() -> i32>(pointer) +/// }; +/// assert_eq!(function(), 0); +/// ``` +/// +/// Extending a lifetime, or shortening an invariant lifetime. This is +/// advanced, very unsafe Rust! +/// +/// ``` +/// struct R<'a>(&'a i32); +/// unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> { +/// std::mem::transmute::, R<'static>>(r) +/// } +/// +/// unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>) +/// -> &'b mut R<'c> { +/// std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r) +/// } +/// ``` +/// +/// # Alternatives +/// +/// Don't despair: many uses of `transmute` can be achieved through other means. +/// Below are common applications of `transmute` which can be replaced with safer +/// constructs. +/// +/// Turning raw bytes (`[u8; SZ]`) into `u32`, `f64`, etc.: +/// +/// ``` +/// let raw_bytes = [0x78, 0x56, 0x34, 0x12]; +/// +/// let num = unsafe { +/// std::mem::transmute::<[u8; 4], u32>(raw_bytes) +/// }; +/// +/// // use `u32::from_ne_bytes` instead +/// let num = u32::from_ne_bytes(raw_bytes); +/// // or use `u32::from_le_bytes` or `u32::from_be_bytes` to specify the endianness +/// let num = u32::from_le_bytes(raw_bytes); +/// assert_eq!(num, 0x12345678); +/// let num = u32::from_be_bytes(raw_bytes); +/// assert_eq!(num, 0x78563412); +/// ``` +/// +/// Turning a pointer into a `usize`: +/// +/// ```no_run +/// let ptr = &0; +/// let ptr_num_transmute = unsafe { +/// std::mem::transmute::<&i32, usize>(ptr) +/// }; +/// +/// // Use an `as` cast instead +/// let ptr_num_cast = ptr as *const i32 as usize; +/// ``` +/// +/// Note that using `transmute` to turn a pointer to a `usize` is (as noted above) [undefined +/// behavior][ub] in `const` contexts. Also outside of consts, this operation might not behave +/// as expected -- this is touching on many unspecified aspects of the Rust memory model. +/// Depending on what the code is doing, the following alternatives are preferable to +/// pointer-to-integer transmutation: +/// - If the code just wants to store data of arbitrary type in some buffer and needs to pick a +/// type for that buffer, it can use [`MaybeUninit`][crate::mem::MaybeUninit]. +/// - If the code actually wants to work on the address the pointer points to, it can use `as` +/// casts or [`ptr.addr()`][pointer::addr]. +/// +/// Turning a `*mut T` into a `&mut T`: +/// +/// ``` +/// let ptr: *mut i32 = &mut 0; +/// let ref_transmuted = unsafe { +/// std::mem::transmute::<*mut i32, &mut i32>(ptr) +/// }; +/// +/// // Use a reborrow instead +/// let ref_casted = unsafe { &mut *ptr }; +/// ``` +/// +/// Turning a `&mut T` into a `&mut U`: +/// +/// ``` +/// let ptr = &mut 0; +/// let val_transmuted = unsafe { +/// std::mem::transmute::<&mut i32, &mut u32>(ptr) +/// }; +/// +/// // Now, put together `as` and reborrowing - note the chaining of `as` +/// // `as` is not transitive +/// let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) }; +/// ``` +/// +/// Turning a `&str` into a `&[u8]`: +/// +/// ``` +/// // this is not a good way to do this. +/// let slice = unsafe { std::mem::transmute::<&str, &[u8]>("Rust") }; +/// assert_eq!(slice, &[82, 117, 115, 116]); +/// +/// // You could use `str::as_bytes` +/// let slice = "Rust".as_bytes(); +/// assert_eq!(slice, &[82, 117, 115, 116]); +/// +/// // Or, just use a byte string, if you have control over the string +/// // literal +/// assert_eq!(b"Rust", &[82, 117, 115, 116]); +/// ``` +/// +/// Turning a `Vec<&T>` into a `Vec>`. +/// +/// To transmute the inner type of the contents of a container, you must make sure to not +/// violate any of the container's invariants. For `Vec`, this means that both the size +/// *and alignment* of the inner types have to match. Other containers might rely on the +/// size of the type, alignment, or even the `TypeId`, in which case transmuting wouldn't +/// be possible at all without violating the container invariants. +/// +/// ``` +/// let store = [0, 1, 2, 3]; +/// let v_orig = store.iter().collect::>(); +/// +/// // clone the vector as we will reuse them later +/// let v_clone = v_orig.clone(); +/// +/// // Using transmute: this relies on the unspecified data layout of `Vec`, which is a +/// // bad idea and could cause Undefined Behavior. +/// // However, it is no-copy. +/// let v_transmuted = unsafe { +/// std::mem::transmute::, Vec>>(v_clone) +/// }; +/// +/// let v_clone = v_orig.clone(); +/// +/// // This is the suggested, safe way. +/// // It may copy the entire vector into a new one though, but also may not. +/// let v_collected = v_clone.into_iter() +/// .map(Some) +/// .collect::>>(); +/// +/// let v_clone = v_orig.clone(); +/// +/// // This is the proper no-copy, unsafe way of "transmuting" a `Vec`, without relying on the +/// // data layout. Instead of literally calling `transmute`, we perform a pointer cast, but +/// // in terms of converting the original inner type (`&i32`) to the new one (`Option<&i32>`), +/// // this has all the same caveats. Besides the information provided above, also consult the +/// // [`from_raw_parts`] documentation. +/// let v_from_raw = unsafe { +// FIXME Update this when vec_into_raw_parts is stabilized +/// // Ensure the original vector is not dropped. +/// let mut v_clone = std::mem::ManuallyDrop::new(v_clone); +/// Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>, +/// v_clone.len(), +/// v_clone.capacity()) +/// }; +/// ``` +/// +/// [`from_raw_parts`]: ../../std/vec/struct.Vec.html#method.from_raw_parts +/// +/// Implementing `split_at_mut`: +/// +/// ``` +/// use std::{slice, mem}; +/// +/// // There are multiple ways to do this, and there are multiple problems +/// // with the following (transmute) way. +/// fn split_at_mut_transmute(slice: &mut [T], mid: usize) +/// -> (&mut [T], &mut [T]) { +/// let len = slice.len(); +/// assert!(mid <= len); +/// unsafe { +/// let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice); +/// // first: transmute is not type safe; all it checks is that T and +/// // U are of the same size. Second, right here, you have two +/// // mutable references pointing to the same memory. +/// (&mut slice[0..mid], &mut slice2[mid..len]) +/// } +/// } +/// +/// // This gets rid of the type safety problems; `&mut *` will *only* give +/// // you a `&mut T` from a `&mut T` or `*mut T`. +/// fn split_at_mut_casts(slice: &mut [T], mid: usize) +/// -> (&mut [T], &mut [T]) { +/// let len = slice.len(); +/// assert!(mid <= len); +/// unsafe { +/// let slice2 = &mut *(slice as *mut [T]); +/// // however, you still have two mutable references pointing to +/// // the same memory. +/// (&mut slice[0..mid], &mut slice2[mid..len]) +/// } +/// } +/// +/// // This is how the standard library does it. This is the best method, if +/// // you need to do something like this +/// fn split_at_stdlib(slice: &mut [T], mid: usize) +/// -> (&mut [T], &mut [T]) { +/// let len = slice.len(); +/// assert!(mid <= len); +/// unsafe { +/// let ptr = slice.as_mut_ptr(); +/// // This now has three mutable references pointing at the same +/// // memory. `slice`, the rvalue ret.0, and the rvalue ret.1. +/// // `slice` is never used after `let ptr = ...`, and so one can +/// // treat it as "dead", and therefore, you only have two real +/// // mutable slices. +/// (slice::from_raw_parts_mut(ptr, mid), +/// slice::from_raw_parts_mut(ptr.add(mid), len - mid)) +/// } +/// } +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_allowed_through_unstable_modules] +#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")] +#[rustc_diagnostic_item = "transmute"] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn transmute(_src: Src) -> Dst { + unreachable!() +} + +/// Like [`transmute`], but even less checked at compile-time: rather than +/// giving an error for `size_of::() != size_of::()`, it's +/// **Undefined Behavior** at runtime. +/// +/// Prefer normal `transmute` where possible, for the extra checking, since +/// both do exactly the same thing at runtime, if they both compile. +/// +/// This is not expected to ever be exposed directly to users, rather it +/// may eventually be exposed through some more-constrained API. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn transmute_unchecked(_src: Src) -> Dst { + unreachable!() +} + +/// Returns `true` if the actual type given as `T` requires drop +/// glue; returns `false` if the actual type provided for `T` +/// implements `Copy`. +/// +/// If the actual type neither requires drop glue nor implements +/// `Copy`, then the return value of this function is unspecified. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop). +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn needs_drop() -> bool { + unreachable!() +} + +/// Calculates the offset from a pointer. +/// +/// This is implemented as an intrinsic to avoid converting to and from an +/// integer, since the conversion would throw away aliasing information. +/// +/// This can only be used with `Ptr` as a raw pointer type (`*mut` or `*const`) +/// to a `Sized` pointee and with `Delta` as `usize` or `isize`. Any other +/// instantiations may arbitrarily misbehave, and that's *not* a compiler bug. +/// +/// # Safety +/// +/// If the computed offset is non-zero, then both the starting and resulting pointer must be +/// either in bounds or at the end of an allocated object. If either pointer is out +/// of bounds or arithmetic overflow occurs then this operation is undefined behavior. +/// +/// The stabilized version of this intrinsic is [`pointer::offset`]. +#[must_use = "returns a new pointer rather than modifying its argument"] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn offset(_dst: Ptr, _offset: Delta) -> Ptr { + unreachable!() +} + +/// Calculates the offset from a pointer, potentially wrapping. +/// +/// This is implemented as an intrinsic to avoid converting to and from an +/// integer, since the conversion inhibits certain optimizations. +/// +/// # Safety +/// +/// Unlike the `offset` intrinsic, this intrinsic does not restrict the +/// resulting pointer to point into or at the end of an allocated +/// object, and it wraps with two's complement arithmetic. The resulting +/// value is not necessarily valid to be used to actually access memory. +/// +/// The stabilized version of this intrinsic is [`pointer::wrapping_offset`]. +#[must_use = "returns a new pointer rather than modifying its argument"] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn arith_offset(_dst: *const T, _offset: isize) -> *const T { + unreachable!() +} + +/// Masks out bits of the pointer according to a mask. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// Consider using [`pointer::mask`] instead. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn ptr_mask(_ptr: *const T, _mask: usize) -> *const T { + unreachable!() +} + +/// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with +/// a size of `count` * `size_of::()` and an alignment of +/// `min_align_of::()` +/// +/// The volatile parameter is set to `true`, so it will not be optimized out +/// unless size is equal to zero. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_copy_nonoverlapping_memory(_dst: *mut T, _src: *const T, _count: usize) { + unreachable!() +} +/// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with +/// a size of `count * size_of::()` and an alignment of +/// `min_align_of::()` +/// +/// The volatile parameter is set to `true`, so it will not be optimized out +/// unless size is equal to zero. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_copy_memory(_dst: *mut T, _src: *const T, _count: usize) { + unreachable!() +} +/// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a +/// size of `count * size_of::()` and an alignment of +/// `min_align_of::()`. +/// +/// The volatile parameter is set to `true`, so it will not be optimized out +/// unless size is equal to zero. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_set_memory(_dst: *mut T, _val: u8, _count: usize) { + unreachable!() +} + +/// Performs a volatile load from the `src` pointer. +/// +/// The stabilized version of this intrinsic is [`core::ptr::read_volatile`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_load(_src: *const T) -> T { + unreachable!() +} +/// Performs a volatile store to the `dst` pointer. +/// +/// The stabilized version of this intrinsic is [`core::ptr::write_volatile`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_store(_dst: *mut T, _val: T) { + unreachable!() +} + +/// Performs a volatile load from the `src` pointer +/// The pointer is not required to be aligned. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +#[rustc_diagnostic_item = "intrinsics_unaligned_volatile_load"] +pub unsafe fn unaligned_volatile_load(_src: *const T) -> T { + unreachable!() +} +/// Performs a volatile store to the `dst` pointer. +/// The pointer is not required to be aligned. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +#[rustc_diagnostic_item = "intrinsics_unaligned_volatile_store"] +pub unsafe fn unaligned_volatile_store(_dst: *mut T, _val: T) { + unreachable!() +} + +/// Returns the square root of an `f16` +/// +/// The stabilized version of this intrinsic is +/// [`f16::sqrt`](../../std/primitive.f16.html#method.sqrt) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sqrtf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the square root of an `f32` +/// +/// The stabilized version of this intrinsic is +/// [`f32::sqrt`](../../std/primitive.f32.html#method.sqrt) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sqrtf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the square root of an `f64` +/// +/// The stabilized version of this intrinsic is +/// [`f64::sqrt`](../../std/primitive.f64.html#method.sqrt) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sqrtf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the square root of an `f128` +/// +/// The stabilized version of this intrinsic is +/// [`f128::sqrt`](../../std/primitive.f128.html#method.sqrt) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sqrtf128(_x: f128) -> f128 { + unreachable!() +} + +/// Raises an `f16` to an integer power. +/// +/// The stabilized version of this intrinsic is +/// [`f16::powi`](../../std/primitive.f16.html#method.powi) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powif16(_a: f16, _x: i32) -> f16 { + unreachable!() +} +/// Raises an `f32` to an integer power. +/// +/// The stabilized version of this intrinsic is +/// [`f32::powi`](../../std/primitive.f32.html#method.powi) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powif32(_a: f32, _x: i32) -> f32 { + unreachable!() +} +/// Raises an `f64` to an integer power. +/// +/// The stabilized version of this intrinsic is +/// [`f64::powi`](../../std/primitive.f64.html#method.powi) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powif64(_a: f64, _x: i32) -> f64 { + unreachable!() +} +/// Raises an `f128` to an integer power. +/// +/// The stabilized version of this intrinsic is +/// [`f128::powi`](../../std/primitive.f128.html#method.powi) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powif128(_a: f128, _x: i32) -> f128 { + unreachable!() +} + +/// Returns the sine of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::sin`](../../std/primitive.f16.html#method.sin) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sinf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the sine of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::sin`](../../std/primitive.f32.html#method.sin) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sinf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the sine of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::sin`](../../std/primitive.f64.html#method.sin) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sinf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the sine of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::sin`](../../std/primitive.f128.html#method.sin) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sinf128(_x: f128) -> f128 { + unreachable!() +} + +/// Returns the cosine of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::cos`](../../std/primitive.f16.html#method.cos) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn cosf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the cosine of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::cos`](../../std/primitive.f32.html#method.cos) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn cosf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the cosine of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::cos`](../../std/primitive.f64.html#method.cos) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn cosf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the cosine of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::cos`](../../std/primitive.f128.html#method.cos) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn cosf128(_x: f128) -> f128 { + unreachable!() +} + +/// Raises an `f16` to an `f16` power. +/// +/// The stabilized version of this intrinsic is +/// [`f16::powf`](../../std/primitive.f16.html#method.powf) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powf16(_a: f16, _x: f16) -> f16 { + unreachable!() +} +/// Raises an `f32` to an `f32` power. +/// +/// The stabilized version of this intrinsic is +/// [`f32::powf`](../../std/primitive.f32.html#method.powf) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powf32(_a: f32, _x: f32) -> f32 { + unreachable!() +} +/// Raises an `f64` to an `f64` power. +/// +/// The stabilized version of this intrinsic is +/// [`f64::powf`](../../std/primitive.f64.html#method.powf) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powf64(_a: f64, _x: f64) -> f64 { + unreachable!() +} +/// Raises an `f128` to an `f128` power. +/// +/// The stabilized version of this intrinsic is +/// [`f128::powf`](../../std/primitive.f128.html#method.powf) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powf128(_a: f128, _x: f128) -> f128 { + unreachable!() +} + +/// Returns the exponential of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::exp`](../../std/primitive.f16.html#method.exp) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn expf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the exponential of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::exp`](../../std/primitive.f32.html#method.exp) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn expf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the exponential of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::exp`](../../std/primitive.f64.html#method.exp) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn expf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the exponential of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::exp`](../../std/primitive.f128.html#method.exp) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn expf128(_x: f128) -> f128 { + unreachable!() +} + +/// Returns 2 raised to the power of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::exp2`](../../std/primitive.f16.html#method.exp2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn exp2f16(_x: f16) -> f16 { + unreachable!() +} +/// Returns 2 raised to the power of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::exp2`](../../std/primitive.f32.html#method.exp2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn exp2f32(_x: f32) -> f32 { + unreachable!() +} +/// Returns 2 raised to the power of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::exp2`](../../std/primitive.f64.html#method.exp2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn exp2f64(_x: f64) -> f64 { + unreachable!() +} +/// Returns 2 raised to the power of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::exp2`](../../std/primitive.f128.html#method.exp2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn exp2f128(_x: f128) -> f128 { + unreachable!() +} + +/// Returns the natural logarithm of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::ln`](../../std/primitive.f16.html#method.ln) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn logf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the natural logarithm of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::ln`](../../std/primitive.f32.html#method.ln) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn logf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the natural logarithm of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::ln`](../../std/primitive.f64.html#method.ln) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn logf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the natural logarithm of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::ln`](../../std/primitive.f128.html#method.ln) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn logf128(_x: f128) -> f128 { + unreachable!() +} + +/// Returns the base 10 logarithm of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::log10`](../../std/primitive.f16.html#method.log10) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log10f16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the base 10 logarithm of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::log10`](../../std/primitive.f32.html#method.log10) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log10f32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the base 10 logarithm of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::log10`](../../std/primitive.f64.html#method.log10) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log10f64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the base 10 logarithm of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::log10`](../../std/primitive.f128.html#method.log10) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log10f128(_x: f128) -> f128 { + unreachable!() +} + +/// Returns the base 2 logarithm of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::log2`](../../std/primitive.f16.html#method.log2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log2f16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the base 2 logarithm of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::log2`](../../std/primitive.f32.html#method.log2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log2f32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the base 2 logarithm of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::log2`](../../std/primitive.f64.html#method.log2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log2f64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the base 2 logarithm of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::log2`](../../std/primitive.f128.html#method.log2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log2f128(_x: f128) -> f128 { + unreachable!() +} + +/// Returns `a * b + c` for `f16` values. +/// +/// The stabilized version of this intrinsic is +/// [`f16::mul_add`](../../std/primitive.f16.html#method.mul_add) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmaf16(_a: f16, _b: f16, _c: f16) -> f16 { + unreachable!() +} +/// Returns `a * b + c` for `f32` values. +/// +/// The stabilized version of this intrinsic is +/// [`f32::mul_add`](../../std/primitive.f32.html#method.mul_add) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmaf32(_a: f32, _b: f32, _c: f32) -> f32 { + unreachable!() +} +/// Returns `a * b + c` for `f64` values. +/// +/// The stabilized version of this intrinsic is +/// [`f64::mul_add`](../../std/primitive.f64.html#method.mul_add) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmaf64(_a: f64, _b: f64, _c: f64) -> f64 { + unreachable!() +} +/// Returns `a * b + c` for `f128` values. +/// +/// The stabilized version of this intrinsic is +/// [`f128::mul_add`](../../std/primitive.f128.html#method.mul_add) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmaf128(_a: f128, _b: f128, _c: f128) -> f128 { + unreachable!() +} + +/// Returns `a * b + c` for `f16` values, non-deterministically executing +/// either a fused multiply-add or two operations with rounding of the +/// intermediate result. +/// +/// The operation is fused if the code generator determines that target +/// instruction set has support for a fused operation, and that the fused +/// operation is more efficient than the equivalent, separate pair of mul +/// and add instructions. It is unspecified whether or not a fused operation +/// is selected, and that may depend on optimization level and context, for +/// example. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmuladdf16(_a: f16, _b: f16, _c: f16) -> f16 { + unreachable!() +} +/// Returns `a * b + c` for `f32` values, non-deterministically executing +/// either a fused multiply-add or two operations with rounding of the +/// intermediate result. +/// +/// The operation is fused if the code generator determines that target +/// instruction set has support for a fused operation, and that the fused +/// operation is more efficient than the equivalent, separate pair of mul +/// and add instructions. It is unspecified whether or not a fused operation +/// is selected, and that may depend on optimization level and context, for +/// example. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmuladdf32(_a: f32, _b: f32, _c: f32) -> f32 { + unreachable!() +} +/// Returns `a * b + c` for `f64` values, non-deterministically executing +/// either a fused multiply-add or two operations with rounding of the +/// intermediate result. +/// +/// The operation is fused if the code generator determines that target +/// instruction set has support for a fused operation, and that the fused +/// operation is more efficient than the equivalent, separate pair of mul +/// and add instructions. It is unspecified whether or not a fused operation +/// is selected, and that may depend on optimization level and context, for +/// example. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmuladdf64(_a: f64, _b: f64, _c: f64) -> f64 { + unreachable!() +} +/// Returns `a * b + c` for `f128` values, non-deterministically executing +/// either a fused multiply-add or two operations with rounding of the +/// intermediate result. +/// +/// The operation is fused if the code generator determines that target +/// instruction set has support for a fused operation, and that the fused +/// operation is more efficient than the equivalent, separate pair of mul +/// and add instructions. It is unspecified whether or not a fused operation +/// is selected, and that may depend on optimization level and context, for +/// example. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmuladdf128(_a: f128, _b: f128, _c: f128) -> f128 { + unreachable!() +} + +/// Returns the largest integer less than or equal to an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::floor`](../../std/primitive.f16.html#method.floor) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn floorf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the largest integer less than or equal to an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::floor`](../../std/primitive.f32.html#method.floor) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn floorf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the largest integer less than or equal to an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::floor`](../../std/primitive.f64.html#method.floor) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn floorf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the largest integer less than or equal to an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::floor`](../../std/primitive.f128.html#method.floor) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn floorf128(_x: f128) -> f128 { + unreachable!() +} + +/// Returns the smallest integer greater than or equal to an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::ceil`](../../std/primitive.f16.html#method.ceil) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn ceilf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the smallest integer greater than or equal to an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::ceil`](../../std/primitive.f32.html#method.ceil) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn ceilf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the smallest integer greater than or equal to an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::ceil`](../../std/primitive.f64.html#method.ceil) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn ceilf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the smallest integer greater than or equal to an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::ceil`](../../std/primitive.f128.html#method.ceil) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn ceilf128(_x: f128) -> f128 { + unreachable!() +} + +/// Returns the integer part of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::trunc`](../../std/primitive.f16.html#method.trunc) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn truncf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the integer part of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::trunc`](../../std/primitive.f32.html#method.trunc) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn truncf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the integer part of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::trunc`](../../std/primitive.f64.html#method.trunc) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn truncf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the integer part of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::trunc`](../../std/primitive.f128.html#method.trunc) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn truncf128(_x: f128) -> f128 { + unreachable!() +} + +/// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// May raise an inexact floating-point exception if the argument is not an integer. +/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions +/// cannot actually be utilized from Rust code. +/// In other words, this intrinsic is equivalent in behavior to `nearbyintf16` and `roundevenf16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn rintf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// May raise an inexact floating-point exception if the argument is not an integer. +/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions +/// cannot actually be utilized from Rust code. +/// In other words, this intrinsic is equivalent in behavior to `nearbyintf32` and `roundevenf32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn rintf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// May raise an inexact floating-point exception if the argument is not an integer. +/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions +/// cannot actually be utilized from Rust code. +/// In other words, this intrinsic is equivalent in behavior to `nearbyintf64` and `roundevenf64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn rintf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// May raise an inexact floating-point exception if the argument is not an integer. +/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions +/// cannot actually be utilized from Rust code. +/// In other words, this intrinsic is equivalent in behavior to `nearbyintf128` and `roundevenf128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn rintf128(_x: f128) -> f128 { + unreachable!() +} + +/// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn nearbyintf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn nearbyintf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn nearbyintf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn nearbyintf128(_x: f128) -> f128 { + unreachable!() +} + +/// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero. +/// +/// The stabilized version of this intrinsic is +/// [`f16::round`](../../std/primitive.f16.html#method.round) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero. +/// +/// The stabilized version of this intrinsic is +/// [`f32::round`](../../std/primitive.f32.html#method.round) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero. +/// +/// The stabilized version of this intrinsic is +/// [`f64::round`](../../std/primitive.f64.html#method.round) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the nearest integer to an `f128`. Rounds half-way cases away from zero. +/// +/// The stabilized version of this intrinsic is +/// [`f128::round`](../../std/primitive.f128.html#method.round) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundf128(_x: f128) -> f128 { + unreachable!() +} + +/// Returns the nearest integer to an `f16`. Rounds half-way cases to the number +/// with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundevenf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the nearest integer to an `f32`. Rounds half-way cases to the number +/// with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundevenf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the nearest integer to an `f64`. Rounds half-way cases to the number +/// with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundevenf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the nearest integer to an `f128`. Rounds half-way cases to the number +/// with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundevenf128(_x: f128) -> f128 { + unreachable!() +} + +/// Float addition that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fadd_fast(_a: T, _b: T) -> T { + unreachable!() +} + +/// Float subtraction that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fsub_fast(_a: T, _b: T) -> T { + unreachable!() +} + +/// Float multiplication that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmul_fast(_a: T, _b: T) -> T { + unreachable!() +} + +/// Float division that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fdiv_fast(_a: T, _b: T) -> T { + unreachable!() +} + +/// Float remainder that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn frem_fast(_a: T, _b: T) -> T { + unreachable!() +} + +/// Converts with LLVM’s fptoui/fptosi, which may return undef for values out of range +/// () +/// +/// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn float_to_int_unchecked(_value: Float) -> Int { + unreachable!() +} + +/// Float addition that allows optimizations based on algebraic rules. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn fadd_algebraic(_a: T, _b: T) -> T { + unimplemented!() +} + +/// Float subtraction that allows optimizations based on algebraic rules. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn fsub_algebraic(_a: T, _b: T) -> T { + unimplemented!() +} + +/// Float multiplication that allows optimizations based on algebraic rules. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn fmul_algebraic(_a: T, _b: T) -> T { + unimplemented!() +} + +/// Float division that allows optimizations based on algebraic rules. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn fdiv_algebraic(_a: T, _b: T) -> T { + unimplemented!() +} + +/// Float remainder that allows optimizations based on algebraic rules. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn frem_algebraic(_a: T, _b: T) -> T { + unimplemented!() +} + +/// Returns the number of bits set in an integer type `T` +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `count_ones` method. For example, +/// [`u32::count_ones`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn ctpop(_x: T) -> u32 { + unimplemented!() +} + +/// Returns the number of leading unset bits (zeroes) in an integer type `T`. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `leading_zeros` method. For example, +/// [`u32::leading_zeros`] +/// +/// # Examples +/// +/// ``` +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// +/// use std::intrinsics::ctlz; +/// +/// let x = 0b0001_1100_u8; +/// let num_leading = ctlz(x); +/// assert_eq!(num_leading, 3); +/// ``` +/// +/// An `x` with value `0` will return the bit width of `T`. +/// +/// ``` +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// +/// use std::intrinsics::ctlz; +/// +/// let x = 0u16; +/// let num_leading = ctlz(x); +/// assert_eq!(num_leading, 16); +/// ``` +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn ctlz(_x: T) -> u32 { + unimplemented!() +} + +/// Like `ctlz`, but extra-unsafe as it returns `undef` when +/// given an `x` with value `0`. +/// +/// This intrinsic does not have a stable counterpart. +/// +/// # Examples +/// +/// ``` +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// +/// use std::intrinsics::ctlz_nonzero; +/// +/// let x = 0b0001_1100_u8; +/// let num_leading = unsafe { ctlz_nonzero(x) }; +/// assert_eq!(num_leading, 3); +/// ``` +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn ctlz_nonzero(_x: T) -> u32 { + unimplemented!() +} + +/// Returns the number of trailing unset bits (zeroes) in an integer type `T`. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `trailing_zeros` method. For example, +/// [`u32::trailing_zeros`] +/// +/// # Examples +/// +/// ``` +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// +/// use std::intrinsics::cttz; +/// +/// let x = 0b0011_1000_u8; +/// let num_trailing = cttz(x); +/// assert_eq!(num_trailing, 3); +/// ``` +/// +/// An `x` with value `0` will return the bit width of `T`: +/// +/// ``` +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// +/// use std::intrinsics::cttz; +/// +/// let x = 0u16; +/// let num_trailing = cttz(x); +/// assert_eq!(num_trailing, 16); +/// ``` +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn cttz(_x: T) -> u32 { + unimplemented!() +} + +/// Like `cttz`, but extra-unsafe as it returns `undef` when +/// given an `x` with value `0`. +/// +/// This intrinsic does not have a stable counterpart. +/// +/// # Examples +/// +/// ``` +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// +/// use std::intrinsics::cttz_nonzero; +/// +/// let x = 0b0011_1000_u8; +/// let num_trailing = unsafe { cttz_nonzero(x) }; +/// assert_eq!(num_trailing, 3); +/// ``` +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn cttz_nonzero(_x: T) -> u32 { + unimplemented!() +} + +/// Reverses the bytes in an integer type `T`. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `swap_bytes` method. For example, +/// [`u32::swap_bytes`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn bswap(_x: T) -> T { + unimplemented!() +} + +/// Reverses the bits in an integer type `T`. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `reverse_bits` method. For example, +/// [`u32::reverse_bits`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn bitreverse(_x: T) -> T { + unimplemented!() +} + +/// Does a three-way comparison between the two integer arguments. +/// +/// This is included as an intrinsic as it's useful to let it be one thing +/// in MIR, rather than the multiple checks and switches that make its IR +/// large and difficult to optimize. +/// +/// The stabilized version of this intrinsic is [`Ord::cmp`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn three_way_compare(_lhs: T, _rhss: T) -> crate::cmp::Ordering { + unimplemented!() +} + +/// Performs checked integer addition. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `overflowing_add` method. For example, +/// [`u32::overflowing_add`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn add_with_overflow(_x: T, _y: T) -> (T, bool) { + unimplemented!() +} + +/// Performs checked integer subtraction +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `overflowing_sub` method. For example, +/// [`u32::overflowing_sub`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn sub_with_overflow(_x: T, _y: T) -> (T, bool) { + unimplemented!() +} + +/// Performs checked integer multiplication +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `overflowing_mul` method. For example, +/// [`u32::overflowing_mul`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn mul_with_overflow(_x: T, _y: T) -> (T, bool) { + unimplemented!() +} + +/// Performs an exact division, resulting in undefined behavior where +/// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1` +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn exact_div(_x: T, _y: T) -> T { + unimplemented!() +} + +/// Performs an unchecked division, resulting in undefined behavior +/// where `y == 0` or `x == T::MIN && y == -1` +/// +/// Safe wrappers for this intrinsic are available on the integer +/// primitives via the `checked_div` method. For example, +/// [`u32::checked_div`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unchecked_div(_x: T, _y: T) -> T { + unimplemented!() +} +/// Returns the remainder of an unchecked division, resulting in +/// undefined behavior when `y == 0` or `x == T::MIN && y == -1` +/// +/// Safe wrappers for this intrinsic are available on the integer +/// primitives via the `checked_rem` method. For example, +/// [`u32::checked_rem`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unchecked_rem(_x: T, _y: T) -> T { + unimplemented!() +} + +/// Performs an unchecked left shift, resulting in undefined behavior when +/// `y < 0` or `y >= N`, where N is the width of T in bits. +/// +/// Safe wrappers for this intrinsic are available on the integer +/// primitives via the `checked_shl` method. For example, +/// [`u32::checked_shl`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unchecked_shl(_x: T, _y: U) -> T { + unimplemented!() +} +/// Performs an unchecked right shift, resulting in undefined behavior when +/// `y < 0` or `y >= N`, where N is the width of T in bits. +/// +/// Safe wrappers for this intrinsic are available on the integer +/// primitives via the `checked_shr` method. For example, +/// [`u32::checked_shr`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unchecked_shr(_x: T, _y: U) -> T { + unimplemented!() +} + +/// Returns the result of an unchecked addition, resulting in +/// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`. +/// +/// The stable counterpart of this intrinsic is `unchecked_add` on the various +/// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`]. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unchecked_add(_x: T, _y: T) -> T { + unimplemented!() +} + +/// Returns the result of an unchecked subtraction, resulting in +/// undefined behavior when `x - y > T::MAX` or `x - y < T::MIN`. +/// +/// The stable counterpart of this intrinsic is `unchecked_sub` on the various +/// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`]. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unchecked_sub(_x: T, _y: T) -> T { + unimplemented!() +} + +/// Returns the result of an unchecked multiplication, resulting in +/// undefined behavior when `x * y > T::MAX` or `x * y < T::MIN`. +/// +/// The stable counterpart of this intrinsic is `unchecked_mul` on the various +/// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`]. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unchecked_mul(_x: T, _y: T) -> T { + unimplemented!() +} + +/// Performs rotate left. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `rotate_left` method. For example, +/// [`u32::rotate_left`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn rotate_left(_x: T, _shift: u32) -> T { + unimplemented!() +} + +/// Performs rotate right. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `rotate_right` method. For example, +/// [`u32::rotate_right`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn rotate_right(_x: T, _shift: u32) -> T { + unimplemented!() +} + +/// Returns (a + b) mod 2N, where N is the width of T in bits. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `wrapping_add` method. For example, +/// [`u32::wrapping_add`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn wrapping_add(_a: T, _b: T) -> T { + unimplemented!() +} +/// Returns (a - b) mod 2N, where N is the width of T in bits. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `wrapping_sub` method. For example, +/// [`u32::wrapping_sub`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn wrapping_sub(_a: T, _b: T) -> T { + unimplemented!() +} +/// Returns (a * b) mod 2N, where N is the width of T in bits. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `wrapping_mul` method. For example, +/// [`u32::wrapping_mul`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn wrapping_mul(_a: T, _b: T) -> T { + unimplemented!() +} + +/// Computes `a + b`, saturating at numeric bounds. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `saturating_add` method. For example, +/// [`u32::saturating_add`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn saturating_add(_a: T, _b: T) -> T { + unimplemented!() +} +/// Computes `a - b`, saturating at numeric bounds. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `saturating_sub` method. For example, +/// [`u32::saturating_sub`] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn saturating_sub(_a: T, _b: T) -> T { + unimplemented!() +} + +/// This is an implementation detail of [`crate::ptr::read`] and should +/// not be used anywhere else. See its comments for why this exists. +/// +/// This intrinsic can *only* be called where the pointer is a local without +/// projections (`read_via_copy(ptr)`, not `read_via_copy(*ptr)`) so that it +/// trivially obeys runtime-MIR rules about derefs in operands. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn read_via_copy(_ptr: *const T) -> T { + unimplemented!() +} + +/// This is an implementation detail of [`crate::ptr::write`] and should +/// not be used anywhere else. See its comments for why this exists. +/// +/// This intrinsic can *only* be called where the pointer is a local without +/// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so +/// that it trivially obeys runtime-MIR rules about derefs in operands. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn write_via_move(_ptr: *mut T, _value: T) { + unimplemented!() +} + +/// Returns the value of the discriminant for the variant in 'v'; +/// if `T` has no discriminant, returns `0`. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is [`core::mem::discriminant`]. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn discriminant_value(_v: &T) -> ::Discriminant { + unimplemented!() +} + +extern "rust-intrinsic" { + /// Rust's "try catch" construct for unwinding. Invokes the function pointer `try_fn` with the + /// data pointer `data`, and calls `catch_fn` if unwinding occurs while `try_fn` runs. + /// + /// `catch_fn` must not unwind. + /// + /// The third argument is a function called if an unwind occurs (both Rust `panic` and foreign + /// unwinds). This function takes the data pointer and a pointer to the target- and + /// runtime-specific exception object that was caught. + /// + /// Note that in the case of a foreign unwinding operation, the exception object data may not be + /// safely usable from Rust, and should not be directly exposed via the standard library. To + /// prevent unsafe access, the library implementation may either abort the process or present an + /// opaque error type to the user. + /// + /// For more information, see the compiler's source, as well as the documentation for the stable + /// version of this intrinsic, `std::panic::catch_unwind`. + #[rustc_nounwind] + pub fn catch_unwind(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32; + + /// Emits a `nontemporal` store, which gives a hint to the CPU that the data should not be held + /// in cache. Except for performance, this is fully equivalent to `ptr.write(val)`. + /// + /// Not all architectures provide such an operation. For instance, x86 does not: while `MOVNT` + /// exists, that operation is *not* equivalent to `ptr.write(val)` (`MOVNT` writes can be reordered + /// in ways that are not allowed for regular writes). + #[rustc_nounwind] + pub fn nontemporal_store(ptr: *mut T, val: T); +} + +/// See documentation of `<*const T>::offset_from` for details. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn ptr_offset_from(_ptr: *const T, _base: *const T) -> isize { + unimplemented!() +} + +/// See documentation of `<*const T>::sub_ptr` for details. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn ptr_offset_from_unsigned(_ptr: *const T, _base: *const T) -> usize { + unimplemented!() +} + +/// See documentation of `<*const T>::guaranteed_eq` for details. +/// Returns `2` if the result is unknown. +/// Returns `1` if the pointers are guaranteed equal. +/// Returns `0` if the pointers are guaranteed inequal. +#[rustc_intrinsic] +#[rustc_nounwind] +#[rustc_do_not_const_check] +#[inline] +#[miri::intrinsic_fallback_is_spec] +pub const fn ptr_guaranteed_cmp(ptr: *const T, other: *const T) -> u8 { + (ptr == other) as u8 +} + +/// Determines whether the raw bytes of the two values are equal. +/// +/// This is particularly handy for arrays, since it allows things like just +/// comparing `i96`s instead of forcing `alloca`s for `[6 x i16]`. +/// +/// Above some backend-decided threshold this will emit calls to `memcmp`, +/// like slice equality does, instead of causing massive code size. +/// +/// Since this works by comparing the underlying bytes, the actual `T` is +/// not particularly important. It will be used for its size and alignment, +/// but any validity restrictions will be ignored, not enforced. +/// +/// # Safety +/// +/// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized. +/// Note that this is a stricter criterion than just the *values* being +/// fully-initialized: if `T` has padding, it's UB to call this intrinsic. +/// +/// At compile-time, it is furthermore UB to call this if any of the bytes +/// in `*a` or `*b` have provenance. +/// +/// (The implementation is allowed to branch on the results of comparisons, +/// which is UB if any of their inputs are `undef`.) +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn raw_eq(_a: &T, _b: &T) -> bool { + unimplemented!() +} + +/// Lexicographically compare `[left, left + bytes)` and `[right, right + bytes)` +/// as unsigned bytes, returning negative if `left` is less, zero if all the +/// bytes match, or positive if `left` is greater. +/// +/// This underlies things like `<[u8]>::cmp`, and will usually lower to `memcmp`. +/// +/// # Safety +/// +/// `left` and `right` must each be [valid] for reads of `bytes` bytes. +/// +/// Note that this applies to the whole range, not just until the first byte +/// that differs. That allows optimizations that can read in large chunks. +/// +/// [valid]: crate::ptr#safety +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn compare_bytes(_left: *const u8, _right: *const u8, _bytes: usize) -> i32 { + unimplemented!() +} + +/// See documentation of [`std::hint::black_box`] for details. +/// +/// [`std::hint::black_box`]: crate::hint::black_box +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn black_box(_dummy: T) -> T { + unimplemented!() +} + +/// Selects which function to call depending on the context. +/// +/// If this function is evaluated at compile-time, then a call to this +/// intrinsic will be replaced with a call to `called_in_const`. It gets +/// replaced with a call to `called_at_rt` otherwise. +/// +/// This function is safe to call, but note the stability concerns below. +/// +/// # Type Requirements +/// +/// The two functions must be both function items. They cannot be function +/// pointers or closures. The first function must be a `const fn`. +/// +/// `arg` will be the tupled arguments that will be passed to either one of +/// the two functions, therefore, both functions must accept the same type of +/// arguments. Both functions must return RET. +/// +/// # Stability concerns +/// +/// Rust has not yet decided that `const fn` are allowed to tell whether +/// they run at compile-time or at runtime. Therefore, when using this +/// intrinsic anywhere that can be reached from stable, it is crucial that +/// the end-to-end behavior of the stable `const fn` is the same for both +/// modes of execution. (Here, Undefined Behavior is considered "the same" +/// as any other behavior, so if the function exhibits UB at runtime then +/// it may do whatever it wants at compile-time.) +/// +/// Here is an example of how this could cause a problem: +/// ```no_run +/// #![feature(const_eval_select)] +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// use std::intrinsics::const_eval_select; +/// +/// // Standard library +/// pub const fn inconsistent() -> i32 { +/// fn runtime() -> i32 { 1 } +/// const fn compiletime() -> i32 { 2 } +/// +/// // ⚠ This code violates the required equivalence of `compiletime` +/// // and `runtime`. +/// const_eval_select((), compiletime, runtime) +/// } +/// +/// // User Crate +/// const X: i32 = inconsistent(); +/// let x = inconsistent(); +/// assert_eq!(x, X); +/// ``` +/// +/// Currently such an assertion would always succeed; until Rust decides +/// otherwise, that principle should not be violated. +#[rustc_const_unstable(feature = "const_eval_select", issue = "124625")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn const_eval_select( + _arg: ARG, + _called_in_const: F, + _called_at_rt: G, +) -> RET +where + G: FnOnce, + F: FnOnce, +{ + unreachable!() +} + +/// A macro to make it easier to invoke const_eval_select. Use as follows: +/// ```rust,ignore (just a macro example) +/// const_eval_select!( +/// @capture { arg1: i32 = some_expr, arg2: T = other_expr } -> U: +/// if const #[attributes_for_const_arm] { +/// // Compile-time code goes here. +/// } else #[attributes_for_runtime_arm] { +/// // Run-time code goes here. +/// } +/// ) +/// ``` +/// The `@capture` block declares which surrounding variables / expressions can be +/// used inside the `if const`. +/// Note that the two arms of this `if` really each become their own function, which is why the +/// macro supports setting attributes for those functions. The runtime function is always +/// markes as `#[inline]`. +/// +/// See [`const_eval_select()`] for the rules and requirements around that intrinsic. +pub(crate) macro const_eval_select { + ( + @capture { $($arg:ident : $ty:ty = $val:expr),* $(,)? } $( -> $ret:ty )? : + if const + $(#[$compiletime_attr:meta])* $compiletime:block + else + $(#[$runtime_attr:meta])* $runtime:block + ) => { + // Use the `noinline` arm, after adding explicit `inline` attributes + $crate::intrinsics::const_eval_select!( + @capture { $($arg : $ty = $val),* } $(-> $ret)? : + #[noinline] + if const + #[inline] // prevent codegen on this function + $(#[$compiletime_attr])* + $compiletime + else + #[inline] // avoid the overhead of an extra fn call + $(#[$runtime_attr])* + $runtime + ) + }, + // With a leading #[noinline], we don't add inline attributes + ( + @capture { $($arg:ident : $ty:ty = $val:expr),* $(,)? } $( -> $ret:ty )? : + #[noinline] + if const + $(#[$compiletime_attr:meta])* $compiletime:block + else + $(#[$runtime_attr:meta])* $runtime:block + ) => {{ + $(#[$runtime_attr])* + fn runtime($($arg: $ty),*) $( -> $ret )? { + $runtime + } + + $(#[$compiletime_attr])* + const fn compiletime($($arg: $ty),*) $( -> $ret )? { + // Don't warn if one of the arguments is unused. + $(let _ = $arg;)* + + $compiletime + } + + const_eval_select(($($val,)*), compiletime, runtime) + }}, + // We support leaving away the `val` expressions for *all* arguments + // (but not for *some* arguments, that's too tricky). + ( + @capture { $($arg:ident : $ty:ty),* $(,)? } $( -> $ret:ty )? : + if const + $(#[$compiletime_attr:meta])* $compiletime:block + else + $(#[$runtime_attr:meta])* $runtime:block + ) => { + $crate::intrinsics::const_eval_select!( + @capture { $($arg : $ty = $arg),* } $(-> $ret)? : + if const + $(#[$compiletime_attr])* $compiletime + else + $(#[$runtime_attr])* $runtime + ) + }, +} + +/// Returns whether the argument's value is statically known at +/// compile-time. +/// +/// This is useful when there is a way of writing the code that will +/// be *faster* when some variables have known values, but *slower* +/// in the general case: an `if is_val_statically_known(var)` can be used +/// to select between these two variants. The `if` will be optimized away +/// and only the desired branch remains. +/// +/// Formally speaking, this function non-deterministically returns `true` +/// or `false`, and the caller has to ensure sound behavior for both cases. +/// In other words, the following code has *Undefined Behavior*: +/// +/// ```no_run +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// use std::hint::unreachable_unchecked; +/// use std::intrinsics::is_val_statically_known; +/// +/// if !is_val_statically_known(0) { unsafe { unreachable_unchecked(); } } +/// ``` +/// +/// This also means that the following code's behavior is unspecified; it +/// may panic, or it may not: +/// +/// ```no_run +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// use std::intrinsics::is_val_statically_known; +/// +/// assert_eq!(is_val_statically_known(0), is_val_statically_known(0)); +/// ``` +/// +/// Unsafe code may not rely on `is_val_statically_known` returning any +/// particular value, ever. However, the compiler will generally make it +/// return `true` only if the value of the argument is actually known. +/// +/// # Stability concerns +/// +/// While it is safe to call, this intrinsic may behave differently in +/// a `const` context than otherwise. See the [`const_eval_select()`] +/// documentation for an explanation of the issues this can cause. Unlike +/// `const_eval_select`, this intrinsic isn't guaranteed to behave +/// deterministically even in a `const` context. +/// +/// # Type Requirements +/// +/// `T` must be either a `bool`, a `char`, a primitive numeric type (e.g. `f32`, +/// but not `NonZeroISize`), or any thin pointer (e.g. `*mut String`). +/// Any other argument types *may* cause a compiler error. +/// +/// ## Pointers +/// +/// When the input is a pointer, only the pointer itself is +/// ever considered. The pointee has no effect. Currently, these functions +/// behave identically: +/// +/// ``` +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// use std::intrinsics::is_val_statically_known; +/// +/// fn foo(x: &i32) -> bool { +/// is_val_statically_known(x) +/// } +/// +/// fn bar(x: &i32) -> bool { +/// is_val_statically_known( +/// (x as *const i32).addr() +/// ) +/// } +/// # _ = foo(&5_i32); +/// # _ = bar(&5_i32); +/// ``` +#[rustc_const_stable_indirect] +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +pub const fn is_val_statically_known(_arg: T) -> bool { + false +} + +/// Non-overlapping *typed* swap of a single value. +/// +/// The codegen backends will replace this with a better implementation when +/// `T` is a simple type that can be loaded and stored as an immediate. +/// +/// The stabilized form of this intrinsic is [`crate::mem::swap`]. +/// +/// # Safety +/// +/// `x` and `y` are readable and writable as `T`, and non-overlapping. +#[rustc_nounwind] +#[inline] +#[rustc_intrinsic] +// Const-unstable because `swap_nonoverlapping` is const-unstable. +#[rustc_const_unstable(feature = "const_typed_swap", issue = "none")] +pub const unsafe fn typed_swap(x: *mut T, y: *mut T) { + // SAFETY: The caller provided single non-overlapping items behind + // pointers, so swapping them with `count: 1` is fine. + unsafe { ptr::swap_nonoverlapping(x, y, 1) }; +} + +/// Returns whether we should perform some UB-checking at runtime. This eventually evaluates to +/// `cfg!(ub_checks)`, but behaves different from `cfg!` when mixing crates built with different +/// flags: if the crate has UB checks enabled or carries the `#[rustc_preserve_ub_checks]` +/// attribute, evaluation is delayed until monomorphization (or until the call gets inlined into +/// a crate that does not delay evaluation further); otherwise it can happen any time. +/// +/// The common case here is a user program built with ub_checks linked against the distributed +/// sysroot which is built without ub_checks but with `#[rustc_preserve_ub_checks]`. +/// For code that gets monomorphized in the user crate (i.e., generic functions and functions with +/// `#[inline]`), gating assertions on `ub_checks()` rather than `cfg!(ub_checks)` means that +/// assertions are enabled whenever the *user crate* has UB checks enabled. However, if the +/// user has UB checks disabled, the checks will still get optimized out. This intrinsic is +/// primarily used by [`ub_checks::assert_unsafe_precondition`]. +#[rustc_intrinsic_const_stable_indirect] // just for UB checks +#[inline(always)] +#[rustc_intrinsic] +pub const fn ub_checks() -> bool { + cfg!(ub_checks) +} + +/// Allocates a block of memory at compile time. +/// At runtime, just returns a null pointer. +/// +/// # Safety +/// +/// - The `align` argument must be a power of two. +/// - At compile time, a compile error occurs if this constraint is violated. +/// - At runtime, it is not checked. +#[rustc_const_unstable(feature = "const_heap", issue = "79597")] +#[rustc_nounwind] +#[rustc_intrinsic] +#[miri::intrinsic_fallback_is_spec] +pub const unsafe fn const_allocate(_size: usize, _align: usize) -> *mut u8 { + // const eval overrides this function, but runtime code for now just returns null pointers. + // See . + crate::ptr::null_mut() +} + +/// Deallocates a memory which allocated by `intrinsics::const_allocate` at compile time. +/// At runtime, does nothing. +/// +/// # Safety +/// +/// - The `align` argument must be a power of two. +/// - At compile time, a compile error occurs if this constraint is violated. +/// - At runtime, it is not checked. +/// - If the `ptr` is created in an another const, this intrinsic doesn't deallocate it. +/// - If the `ptr` is pointing to a local variable, this intrinsic doesn't deallocate it. +#[rustc_const_unstable(feature = "const_heap", issue = "79597")] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_nounwind] +#[rustc_intrinsic] +#[miri::intrinsic_fallback_is_spec] +pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) { + // Runtime NOP +} + +/// The intrinsic will return the size stored in that vtable. +/// +/// # Safety +/// +/// `ptr` must point to a vtable. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub unsafe fn vtable_size(_ptr: *const ()) -> usize { + unreachable!() +} + +/// The intrinsic will return the alignment stored in that vtable. +/// +/// # Safety +/// +/// `ptr` must point to a vtable. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub unsafe fn vtable_align(_ptr: *const ()) -> usize { + unreachable!() +} + +/// The size of a type in bytes. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// More specifically, this is the offset in bytes between successive +/// items of the same type, including alignment padding. +/// +/// The stabilized version of this intrinsic is [`core::mem::size_of`]. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn size_of() -> usize { + unreachable!() +} + +/// The minimum alignment of a type. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is [`core::mem::align_of`]. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn min_align_of() -> usize { + unreachable!() +} + +/// The preferred alignment of a type. +/// +/// This intrinsic does not have a stable counterpart. +/// It's "tracking issue" is [#91971](https://github.com/rust-lang/rust/issues/91971). +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn pref_align_of() -> usize { + unreachable!() +} + +/// Returns the number of variants of the type `T` cast to a `usize`; +/// if `T` has no variants, returns `0`. Uninhabited variants will be counted. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The to-be-stabilized version of this intrinsic is [`crate::mem::variant_count`]. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn variant_count() -> usize { + unreachable!() +} + +/// The size of the referenced value in bytes. +/// +/// The stabilized version of this intrinsic is [`crate::mem::size_of_val`]. +/// +/// # Safety +/// +/// See [`crate::mem::size_of_val_raw`] for safety conditions. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_intrinsic_const_stable_indirect] +pub const unsafe fn size_of_val(_ptr: *const T) -> usize { + unreachable!() +} + +/// The required alignment of the referenced value. +/// +/// The stabilized version of this intrinsic is [`core::mem::align_of_val`]. +/// +/// # Safety +/// +/// See [`crate::mem::align_of_val_raw`] for safety conditions. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_intrinsic_const_stable_indirect] +pub const unsafe fn min_align_of_val(_ptr: *const T) -> usize { + unreachable!() +} + +/// Gets a static string slice containing the name of a type. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is [`core::any::type_name`]. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn type_name() -> &'static str { + unreachable!() +} + +/// Gets an identifier which is globally unique to the specified type. This +/// function will return the same value for a type regardless of whichever +/// crate it is invoked in. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is [`core::any::TypeId::of`]. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn type_id() -> u128 { + unreachable!() +} + +/// Lowers in MIR to `Rvalue::Aggregate` with `AggregateKind::RawPtr`. +/// +/// This is used to implement functions like `slice::from_raw_parts_mut` and +/// `ptr::from_raw_parts` in a way compatible with the compiler being able to +/// change the possible layouts of pointers. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn aggregate_raw_ptr, D, M>(_data: D, _meta: M) -> P { + // To implement a fallback we'd have to assume the layout of the pointer, + // but the whole point of this intrinsic is that we shouldn't do that. + unreachable!() +} + +#[unstable(feature = "core_intrinsics", issue = "none")] +pub trait AggregateRawPtr { + type Metadata: Copy; +} +impl AggregateRawPtr<*const T> for *const P { + type Metadata =

::Metadata; +} +impl AggregateRawPtr<*mut T> for *mut P { + type Metadata =

::Metadata; +} + +/// Lowers in MIR to `Rvalue::UnaryOp` with `UnOp::PtrMetadata`. +/// +/// This is used to implement functions like `ptr::metadata`. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn ptr_metadata + ?Sized, M>(_ptr: *const P) -> M { + // To implement a fallback we'd have to assume the layout of the pointer, + // but the whole point of this intrinsic is that we shouldn't do that. + unreachable!() +} + +// Some functions are defined here because they accidentally got made +// available in this module on stable. See . +// (`transmute` also falls into this category, but it cannot be wrapped due to the +// check that `T` and `U` have the same size.) + +/// Copies `count * size_of::()` bytes from `src` to `dst`. The source +/// and destination must *not* overlap. +/// +/// For regions of memory which might overlap, use [`copy`] instead. +/// +/// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but +/// with the argument order swapped. +/// +/// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the +/// requirements of `T`. The initialization state is preserved exactly. +/// +/// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `src` must be [valid] for reads of `count * size_of::()` bytes. +/// +/// * `dst` must be [valid] for writes of `count * size_of::()` bytes. +/// +/// * Both `src` and `dst` must be properly aligned. +/// +/// * The region of memory beginning at `src` with a size of `count * +/// size_of::()` bytes must *not* overlap with the region of memory +/// beginning at `dst` with the same size. +/// +/// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of +/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values +/// in the region beginning at `*src` and the region beginning at `*dst` can +/// [violate memory safety][read-ownership]. +/// +/// Note that even if the effectively copied size (`count * size_of::()`) is +/// `0`, the pointers must be properly aligned. +/// +/// [`read`]: crate::ptr::read +/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value +/// [valid]: crate::ptr#safety +/// +/// # Examples +/// +/// Manually implement [`Vec::append`]: +/// +/// ``` +/// use std::ptr; +/// +/// /// Moves all the elements of `src` into `dst`, leaving `src` empty. +/// fn append(dst: &mut Vec, src: &mut Vec) { +/// let src_len = src.len(); +/// let dst_len = dst.len(); +/// +/// // Ensure that `dst` has enough capacity to hold all of `src`. +/// dst.reserve(src_len); +/// +/// unsafe { +/// // The call to add is always safe because `Vec` will never +/// // allocate more than `isize::MAX` bytes. +/// let dst_ptr = dst.as_mut_ptr().add(dst_len); +/// let src_ptr = src.as_ptr(); +/// +/// // Truncate `src` without dropping its contents. We do this first, +/// // to avoid problems in case something further down panics. +/// src.set_len(0); +/// +/// // The two regions cannot overlap because mutable references do +/// // not alias, and two different vectors cannot own the same +/// // memory. +/// ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len); +/// +/// // Notify `dst` that it now holds the contents of `src`. +/// dst.set_len(dst_len + src_len); +/// } +/// } +/// +/// let mut a = vec!['r']; +/// let mut b = vec!['u', 's', 't']; +/// +/// append(&mut a, &mut b); +/// +/// assert_eq!(a, &['r', 'u', 's', 't']); +/// assert!(b.is_empty()); +/// ``` +/// +/// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append +#[doc(alias = "memcpy")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_allowed_through_unstable_modules] +#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] +#[inline(always)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] +pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { + #[rustc_intrinsic_const_stable_indirect] + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + const unsafe fn copy_nonoverlapping(_src: *const T, _dst: *mut T, _count: usize) { + unreachable!() + } + + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \ + and the specified memory ranges do not overlap", + ( + src: *const () = src as *const (), + dst: *mut () = dst as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + count: usize = count, + ) => { + let zero_size = count == 0 || size == 0; + ub_checks::maybe_is_aligned_and_not_null(src, align, zero_size) + && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) + && ub_checks::maybe_is_nonoverlapping(src, dst, size, count) + } + ); + + // SAFETY: the safety contract for `copy_nonoverlapping` must be + // upheld by the caller. + unsafe { copy_nonoverlapping(src, dst, count) } +} + +/// Copies `count * size_of::()` bytes from `src` to `dst`. The source +/// and destination may overlap. +/// +/// If the source and destination will *never* overlap, +/// [`copy_nonoverlapping`] can be used instead. +/// +/// `copy` is semantically equivalent to C's [`memmove`], but with the argument +/// order swapped. Copying takes place as if the bytes were copied from `src` +/// to a temporary array and then copied from the array to `dst`. +/// +/// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the +/// requirements of `T`. The initialization state is preserved exactly. +/// +/// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `src` must be [valid] for reads of `count * size_of::()` bytes, and must remain valid even +/// when `dst` is written for `count * size_of::()` bytes. (This means if the memory ranges +/// overlap, the two pointers must not be subject to aliasing restrictions relative to each +/// other.) +/// +/// * `dst` must be [valid] for writes of `count * size_of::()` bytes, and must remain valid even +/// when `src` is read for `count * size_of::()` bytes. +/// +/// * Both `src` and `dst` must be properly aligned. +/// +/// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of +/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the values +/// in the region beginning at `*src` and the region beginning at `*dst` can +/// [violate memory safety][read-ownership]. +/// +/// Note that even if the effectively copied size (`count * size_of::()`) is +/// `0`, the pointers must be properly aligned. +/// +/// [`read`]: crate::ptr::read +/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value +/// [valid]: crate::ptr#safety +/// +/// # Examples +/// +/// Efficiently create a Rust vector from an unsafe buffer: +/// +/// ``` +/// use std::ptr; +/// +/// /// # Safety +/// /// +/// /// * `ptr` must be correctly aligned for its type and non-zero. +/// /// * `ptr` must be valid for reads of `elts` contiguous elements of type `T`. +/// /// * Those elements must not be used after calling this function unless `T: Copy`. +/// # #[allow(dead_code)] +/// unsafe fn from_buf_raw(ptr: *const T, elts: usize) -> Vec { +/// let mut dst = Vec::with_capacity(elts); +/// +/// // SAFETY: Our precondition ensures the source is aligned and valid, +/// // and `Vec::with_capacity` ensures that we have usable space to write them. +/// ptr::copy(ptr, dst.as_mut_ptr(), elts); +/// +/// // SAFETY: We created it with this much capacity earlier, +/// // and the previous `copy` has initialized these elements. +/// dst.set_len(elts); +/// dst +/// } +/// ``` +#[doc(alias = "memmove")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_allowed_through_unstable_modules] +#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] +#[inline(always)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[rustc_diagnostic_item = "ptr_copy"] +pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { + #[rustc_intrinsic_const_stable_indirect] + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + const unsafe fn copy(_src: *const T, _dst: *mut T, _count: usize) { + unreachable!() + } + + // SAFETY: the safety contract for `copy` must be upheld by the caller. + unsafe { + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::copy requires that both pointer arguments are aligned and non-null", + ( + src: *const () = src as *const (), + dst: *mut () = dst as *mut (), + align: usize = align_of::(), + zero_size: bool = T::IS_ZST || count == 0, + ) => + ub_checks::maybe_is_aligned_and_not_null(src, align, zero_size) + && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) + ); + copy(src, dst, count) + } +} + +/// Sets `count * size_of::()` bytes of memory starting at `dst` to +/// `val`. +/// +/// `write_bytes` is similar to C's [`memset`], but sets `count * +/// size_of::()` bytes to `val`. +/// +/// [`memset`]: https://en.cppreference.com/w/c/string/byte/memset +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `dst` must be [valid] for writes of `count * size_of::()` bytes. +/// +/// * `dst` must be properly aligned. +/// +/// Note that even if the effectively copied size (`count * size_of::()`) is +/// `0`, the pointer must be properly aligned. +/// +/// Additionally, note that changing `*dst` in this way can easily lead to undefined behavior (UB) +/// later if the written bytes are not a valid representation of some `T`. For instance, the +/// following is an **incorrect** use of this function: +/// +/// ```rust,no_run +/// unsafe { +/// let mut value: u8 = 0; +/// let ptr: *mut bool = &mut value as *mut u8 as *mut bool; +/// let _bool = ptr.read(); // This is fine, `ptr` points to a valid `bool`. +/// ptr.write_bytes(42u8, 1); // This function itself does not cause UB... +/// let _bool = ptr.read(); // ...but it makes this operation UB! ⚠️ +/// } +/// ``` +/// +/// [valid]: crate::ptr#safety +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::ptr; +/// +/// let mut vec = vec![0u32; 4]; +/// unsafe { +/// let vec_ptr = vec.as_mut_ptr(); +/// ptr::write_bytes(vec_ptr, 0xfe, 2); +/// } +/// assert_eq!(vec, [0xfefefefe, 0xfefefefe, 0, 0]); +/// ``` +#[doc(alias = "memset")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_allowed_through_unstable_modules] +#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] +#[inline(always)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[rustc_diagnostic_item = "ptr_write_bytes"] +pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { + #[rustc_intrinsic_const_stable_indirect] + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + const unsafe fn write_bytes(_dst: *mut T, _val: u8, _count: usize) { + unreachable!() + } + + // SAFETY: the safety contract for `write_bytes` must be upheld by the caller. + unsafe { + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::write_bytes requires that the destination pointer is aligned and non-null", + ( + addr: *const () = dst as *const (), + align: usize = align_of::(), + zero_size: bool = T::IS_ZST || count == 0, + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, zero_size) + ); + write_bytes(dst, val, count) + } +} + +/// Returns the minimum of two `f16` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f16::min`] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn minnumf16(_x: f16, _y: f16) -> f16 { + unimplemented!(); +} + +/// Returns the minimum of two `f32` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f32::min`] +#[rustc_nounwind] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn minnumf32(_x: f32, _y: f32) -> f32 { + unimplemented!(); +} + +/// Returns the minimum of two `f64` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f64::min`] +#[rustc_nounwind] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn minnumf64(_x: f64, _y: f64) -> f64 { + unimplemented!(); +} + +/// Returns the minimum of two `f128` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f128::min`] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn minnumf128(_x: f128, _y: f128) -> f128 { + unimplemented!(); +} + +/// Returns the maximum of two `f16` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f16::max`] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn maxnumf16(_x: f16, _y: f16) -> f16 { + unimplemented!(); +} + +/// Returns the maximum of two `f32` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f32::max`] +#[rustc_nounwind] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn maxnumf32(_x: f32, _y: f32) -> f32 { + unimplemented!(); +} + +/// Returns the maximum of two `f64` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f64::max`] +#[rustc_nounwind] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn maxnumf64(_x: f64, _y: f64) -> f64 { + unimplemented!(); +} + +/// Returns the maximum of two `f128` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f128::max`] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn maxnumf128(_x: f128, _y: f128) -> f128 { + unimplemented!(); +} + +/// Returns the absolute value of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::abs`](../../std/primitive.f16.html#method.abs) +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn fabsf16(_x: f16) -> f16 { + unimplemented!(); +} + +/// Returns the absolute value of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::abs`](../../std/primitive.f32.html#method.abs) +#[rustc_nounwind] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn fabsf32(_x: f32) -> f32 { + unimplemented!(); +} + +/// Returns the absolute value of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::abs`](../../std/primitive.f64.html#method.abs) +#[rustc_nounwind] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn fabsf64(_x: f64) -> f64 { + unimplemented!(); +} + +/// Returns the absolute value of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::abs`](../../std/primitive.f128.html#method.abs) +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn fabsf128(_x: f128) -> f128 { + unimplemented!(); +} + +/// Copies the sign from `y` to `x` for `f16` values. +/// +/// The stabilized version of this intrinsic is +/// [`f16::copysign`](../../std/primitive.f16.html#method.copysign) +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 { + unimplemented!(); +} + +/// Copies the sign from `y` to `x` for `f32` values. +/// +/// The stabilized version of this intrinsic is +/// [`f32::copysign`](../../std/primitive.f32.html#method.copysign) +#[rustc_nounwind] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 { + unimplemented!(); +} +/// Copies the sign from `y` to `x` for `f64` values. +/// +/// The stabilized version of this intrinsic is +/// [`f64::copysign`](../../std/primitive.f64.html#method.copysign) +#[rustc_nounwind] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 { + unimplemented!(); +} + +/// Copies the sign from `y` to `x` for `f128` values. +/// +/// The stabilized version of this intrinsic is +/// [`f128::copysign`](../../std/primitive.f128.html#method.copysign) +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn copysignf128(_x: f128, _y: f128) -> f128 { + unimplemented!(); +} + +/// Inform Miri that a given pointer definitely has a certain alignment. +#[cfg(miri)] +#[rustc_allow_const_fn_unstable(const_eval_select)] +pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize) { + extern "Rust" { + /// Miri-provided extern function to promise that a given pointer is properly aligned for + /// "symbolic" alignment checks. Will fail if the pointer is not actually aligned or `align` is + /// not a power of two. Has no effect when alignment checks are concrete (which is the default). + fn miri_promise_symbolic_alignment(ptr: *const (), align: usize); + } + + const_eval_select!( + @capture { ptr: *const (), align: usize}: + if const { + // Do nothing. + } else { + // SAFETY: this call is always safe. + unsafe { + miri_promise_symbolic_alignment(ptr, align); + } + } + ) +} diff --git a/CoqOfRust/core/intrinsics/simd.rs b/CoqOfRust/core/intrinsics/simd.rs new file mode 100644 index 000000000..f80a60d47 --- /dev/null +++ b/CoqOfRust/core/intrinsics/simd.rs @@ -0,0 +1,671 @@ +//! SIMD compiler intrinsics. +//! +//! In this module, a "vector" is any `repr(simd)` type. + +extern "rust-intrinsic" { + /// Inserts an element into a vector, returning the updated vector. + /// + /// `T` must be a vector with element type `U`. + /// + /// # Safety + /// + /// `idx` must be in-bounds of the vector. + #[rustc_nounwind] + pub fn simd_insert(x: T, idx: u32, val: U) -> T; + + /// Extracts an element from a vector. + /// + /// `T` must be a vector with element type `U`. + /// + /// # Safety + /// + /// `idx` must be in-bounds of the vector. + #[rustc_nounwind] + pub fn simd_extract(x: T, idx: u32) -> U; + + /// Adds two simd vectors elementwise. + /// + /// `T` must be a vector of integer or floating point primitive types. + #[rustc_nounwind] + pub fn simd_add(x: T, y: T) -> T; + + /// Subtracts `rhs` from `lhs` elementwise. + /// + /// `T` must be a vector of integer or floating point primitive types. + #[rustc_nounwind] + pub fn simd_sub(lhs: T, rhs: T) -> T; + + /// Multiplies two simd vectors elementwise. + /// + /// `T` must be a vector of integer or floating point primitive types. + #[rustc_nounwind] + pub fn simd_mul(x: T, y: T) -> T; + + /// Divides `lhs` by `rhs` elementwise. + /// + /// `T` must be a vector of integer or floating point primitive types. + /// + /// # Safety + /// For integers, `rhs` must not contain any zero elements. + /// Additionally for signed integers, `::MIN / -1` is undefined behavior. + #[rustc_nounwind] + pub fn simd_div(lhs: T, rhs: T) -> T; + + /// Returns remainder of two vectors elementwise. + /// + /// `T` must be a vector of integer or floating point primitive types. + /// + /// # Safety + /// For integers, `rhs` must not contain any zero elements. + /// Additionally for signed integers, `::MIN / -1` is undefined behavior. + #[rustc_nounwind] + pub fn simd_rem(lhs: T, rhs: T) -> T; + + /// Shifts vector left elementwise, with UB on overflow. + /// + /// Shifts `lhs` left by `rhs`, shifting in sign bits for signed types. + /// + /// `T` must be a vector of integer primitive types. + /// + /// # Safety + /// + /// Each element of `rhs` must be less than `::BITS`. + #[rustc_nounwind] + pub fn simd_shl(lhs: T, rhs: T) -> T; + + /// Shifts vector right elementwise, with UB on overflow. + /// + /// `T` must be a vector of integer primitive types. + /// + /// Shifts `lhs` right by `rhs`, shifting in sign bits for signed types. + /// + /// # Safety + /// + /// Each element of `rhs` must be less than `::BITS`. + #[rustc_nounwind] + pub fn simd_shr(lhs: T, rhs: T) -> T; + + /// "Ands" vectors elementwise. + /// + /// `T` must be a vector of integer primitive types. + #[rustc_nounwind] + pub fn simd_and(x: T, y: T) -> T; + + /// "Ors" vectors elementwise. + /// + /// `T` must be a vector of integer primitive types. + #[rustc_nounwind] + pub fn simd_or(x: T, y: T) -> T; + + /// "Exclusive ors" vectors elementwise. + /// + /// `T` must be a vector of integer primitive types. + #[rustc_nounwind] + pub fn simd_xor(x: T, y: T) -> T; + + /// Numerically casts a vector, elementwise. + /// + /// `T` and `U` must be vectors of integer or floating point primitive types, and must have the + /// same length. + /// + /// When casting floats to integers, the result is truncated. Out-of-bounds result lead to UB. + /// When casting integers to floats, the result is rounded. + /// Otherwise, truncates or extends the value, maintaining the sign for signed integers. + /// + /// # Safety + /// Casting from integer types is always safe. + /// Casting between two float types is also always safe. + /// + /// Casting floats to integers truncates, following the same rules as `to_int_unchecked`. + /// Specifically, each element must: + /// * Not be `NaN` + /// * Not be infinite + /// * Be representable in the return type, after truncating off its fractional part + #[rustc_nounwind] + pub fn simd_cast(x: T) -> U; + + /// Numerically casts a vector, elementwise. + /// + /// `T` and `U` be a vectors of integer or floating point primitive types, and must have the + /// same length. + /// + /// Like `simd_cast`, but saturates float-to-integer conversions (NaN becomes 0). + /// This matches regular `as` and is always safe. + /// + /// When casting floats to integers, the result is truncated. + /// When casting integers to floats, the result is rounded. + /// Otherwise, truncates or extends the value, maintaining the sign for signed integers. + #[rustc_nounwind] + pub fn simd_as(x: T) -> U; + + /// Negates a vector elementwise. + /// + /// `T` must be a vector of integer or floating-point primitive types. + /// + /// Rust panics for `-::Min` due to overflow, but it is not UB with this intrinsic. + #[rustc_nounwind] + pub fn simd_neg(x: T) -> T; + + /// Returns absolute value of a vector, elementwise. + /// + /// `T` must be a vector of floating-point primitive types. + #[rustc_nounwind] + pub fn simd_fabs(x: T) -> T; + + /// Returns the minimum of two vectors, elementwise. + /// + /// `T` must be a vector of floating-point primitive types. + /// + /// Follows IEEE-754 `minNum` semantics. + #[rustc_nounwind] + pub fn simd_fmin(x: T, y: T) -> T; + + /// Returns the maximum of two vectors, elementwise. + /// + /// `T` must be a vector of floating-point primitive types. + /// + /// Follows IEEE-754 `maxNum` semantics. + #[rustc_nounwind] + pub fn simd_fmax(x: T, y: T) -> T; + + /// Tests elementwise equality of two vectors. + /// + /// `T` must be a vector of floating-point primitive types. + /// + /// `U` must be a vector of integers with the same number of elements and element size as `T`. + /// + /// Returns `0` for false and `!0` for true. + #[rustc_nounwind] + pub fn simd_eq(x: T, y: T) -> U; + + /// Tests elementwise inequality equality of two vectors. + /// + /// `T` must be a vector of floating-point primitive types. + /// + /// `U` must be a vector of integers with the same number of elements and element size as `T`. + /// + /// Returns `0` for false and `!0` for true. + #[rustc_nounwind] + pub fn simd_ne(x: T, y: T) -> U; + + /// Tests if `x` is less than `y`, elementwise. + /// + /// `T` must be a vector of floating-point primitive types. + /// + /// `U` must be a vector of integers with the same number of elements and element size as `T`. + /// + /// Returns `0` for false and `!0` for true. + #[rustc_nounwind] + pub fn simd_lt(x: T, y: T) -> U; + + /// Tests if `x` is less than or equal to `y`, elementwise. + /// + /// `T` must be a vector of floating-point primitive types. + /// + /// `U` must be a vector of integers with the same number of elements and element size as `T`. + /// + /// Returns `0` for false and `!0` for true. + #[rustc_nounwind] + pub fn simd_le(x: T, y: T) -> U; + + /// Tests if `x` is greater than `y`, elementwise. + /// + /// `T` must be a vector of floating-point primitive types. + /// + /// `U` must be a vector of integers with the same number of elements and element size as `T`. + /// + /// Returns `0` for false and `!0` for true. + #[rustc_nounwind] + pub fn simd_gt(x: T, y: T) -> U; + + /// Tests if `x` is greater than or equal to `y`, elementwise. + /// + /// `T` must be a vector of floating-point primitive types. + /// + /// `U` must be a vector of integers with the same number of elements and element size as `T`. + /// + /// Returns `0` for false and `!0` for true. + #[rustc_nounwind] + pub fn simd_ge(x: T, y: T) -> U; + + /// Shuffles two vectors by const indices. + /// + /// `T` must be a vector. + /// + /// `U` must be a **const** vector of `u32`s. This means it must either refer to a named + /// const or be given as an inline const expression (`const { ... }`). + /// + /// `V` must be a vector with the same element type as `T` and the same length as `U`. + /// + /// Returns a new vector such that element `i` is selected from `xy[idx[i]]`, where `xy` + /// is the concatenation of `x` and `y`. It is a compile-time error if `idx[i]` is out-of-bounds + /// of `xy`. + #[rustc_nounwind] + pub fn simd_shuffle(x: T, y: T, idx: U) -> V; + + /// Reads a vector of pointers. + /// + /// `T` must be a vector. + /// + /// `U` must be a vector of pointers to the element type of `T`, with the same length as `T`. + /// + /// `V` must be a vector of integers with the same length as `T` (but any element size). + /// + /// For each pointer in `ptr`, if the corresponding value in `mask` is `!0`, read the pointer. + /// Otherwise if the corresponding value in `mask` is `0`, return the corresponding value from + /// `val`. + /// + /// # Safety + /// Unmasked values in `T` must be readable as if by `::read` (e.g. aligned to the element + /// type). + /// + /// `mask` must only contain `0` or `!0` values. + #[rustc_nounwind] + pub fn simd_gather(val: T, ptr: U, mask: V) -> T; + + /// Writes to a vector of pointers. + /// + /// `T` must be a vector. + /// + /// `U` must be a vector of pointers to the element type of `T`, with the same length as `T`. + /// + /// `V` must be a vector of integers with the same length as `T` (but any element size). + /// + /// For each pointer in `ptr`, if the corresponding value in `mask` is `!0`, write the + /// corresponding value in `val` to the pointer. + /// Otherwise if the corresponding value in `mask` is `0`, do nothing. + /// + /// The stores happen in left-to-right order. + /// (This is relevant in case two of the stores overlap.) + /// + /// # Safety + /// Unmasked values in `T` must be writeable as if by `::write` (e.g. aligned to the element + /// type). + /// + /// `mask` must only contain `0` or `!0` values. + #[rustc_nounwind] + pub fn simd_scatter(val: T, ptr: U, mask: V); + + /// Reads a vector of pointers. + /// + /// `T` must be a vector. + /// + /// `U` must be a pointer to the element type of `T` + /// + /// `V` must be a vector of integers with the same length as `T` (but any element size). + /// + /// For each element, if the corresponding value in `mask` is `!0`, read the corresponding + /// pointer offset from `ptr`. + /// The first element is loaded from `ptr`, the second from `ptr.wrapping_offset(1)` and so on. + /// Otherwise if the corresponding value in `mask` is `0`, return the corresponding value from + /// `val`. + /// + /// # Safety + /// Unmasked values in `T` must be readable as if by `::read` (e.g. aligned to the element + /// type). + /// + /// `mask` must only contain `0` or `!0` values. + #[rustc_nounwind] + pub fn simd_masked_load(mask: V, ptr: U, val: T) -> T; + + /// Writes to a vector of pointers. + /// + /// `T` must be a vector. + /// + /// `U` must be a pointer to the element type of `T` + /// + /// `V` must be a vector of integers with the same length as `T` (but any element size). + /// + /// For each element, if the corresponding value in `mask` is `!0`, write the corresponding + /// value in `val` to the pointer offset from `ptr`. + /// The first element is written to `ptr`, the second to `ptr.wrapping_offset(1)` and so on. + /// Otherwise if the corresponding value in `mask` is `0`, do nothing. + /// + /// # Safety + /// Unmasked values in `T` must be writeable as if by `::write` (e.g. aligned to the element + /// type). + /// + /// `mask` must only contain `0` or `!0` values. + #[rustc_nounwind] + pub fn simd_masked_store(mask: V, ptr: U, val: T); + + /// Adds two simd vectors elementwise, with saturation. + /// + /// `T` must be a vector of integer primitive types. + #[rustc_nounwind] + pub fn simd_saturating_add(x: T, y: T) -> T; + + /// Subtracts two simd vectors elementwise, with saturation. + /// + /// `T` must be a vector of integer primitive types. + /// + /// Subtract `rhs` from `lhs`. + #[rustc_nounwind] + pub fn simd_saturating_sub(lhs: T, rhs: T) -> T; + + /// Adds elements within a vector from left to right. + /// + /// `T` must be a vector of integer or floating-point primitive types. + /// + /// `U` must be the element type of `T`. + /// + /// Starting with the value `y`, add the elements of `x` and accumulate. + #[rustc_nounwind] + pub fn simd_reduce_add_ordered(x: T, y: U) -> U; + + /// Adds elements within a vector in arbitrary order. May also be re-associated with + /// unordered additions on the inputs/outputs. + /// + /// `T` must be a vector of integer or floating-point primitive types. + /// + /// `U` must be the element type of `T`. + #[rustc_nounwind] + pub fn simd_reduce_add_unordered(x: T) -> U; + + /// Multiplies elements within a vector from left to right. + /// + /// `T` must be a vector of integer or floating-point primitive types. + /// + /// `U` must be the element type of `T`. + /// + /// Starting with the value `y`, multiply the elements of `x` and accumulate. + #[rustc_nounwind] + pub fn simd_reduce_mul_ordered(x: T, y: U) -> U; + + /// Multiplies elements within a vector in arbitrary order. May also be re-associated with + /// unordered additions on the inputs/outputs. + /// + /// `T` must be a vector of integer or floating-point primitive types. + /// + /// `U` must be the element type of `T`. + #[rustc_nounwind] + pub fn simd_reduce_mul_unordered(x: T) -> U; + + /// Checks if all mask values are true. + /// + /// `T` must be a vector of integer primitive types. + /// + /// # Safety + /// `x` must contain only `0` or `!0`. + #[rustc_nounwind] + pub fn simd_reduce_all(x: T) -> bool; + + /// Checks if any mask value is true. + /// + /// `T` must be a vector of integer primitive types. + /// + /// # Safety + /// `x` must contain only `0` or `!0`. + #[rustc_nounwind] + pub fn simd_reduce_any(x: T) -> bool; + + /// Returns the maximum element of a vector. + /// + /// `T` must be a vector of integer or floating-point primitive types. + /// + /// `U` must be the element type of `T`. + /// + /// For floating-point values, uses IEEE-754 `maxNum`. + #[rustc_nounwind] + pub fn simd_reduce_max(x: T) -> U; + + /// Returns the minimum element of a vector. + /// + /// `T` must be a vector of integer or floating-point primitive types. + /// + /// `U` must be the element type of `T`. + /// + /// For floating-point values, uses IEEE-754 `minNum`. + #[rustc_nounwind] + pub fn simd_reduce_min(x: T) -> U; + + /// Logical "ands" all elements together. + /// + /// `T` must be a vector of integer or floating-point primitive types. + /// + /// `U` must be the element type of `T`. + #[rustc_nounwind] + pub fn simd_reduce_and(x: T) -> U; + + /// Logical "ors" all elements together. + /// + /// `T` must be a vector of integer or floating-point primitive types. + /// + /// `U` must be the element type of `T`. + #[rustc_nounwind] + pub fn simd_reduce_or(x: T) -> U; + + /// Logical "exclusive ors" all elements together. + /// + /// `T` must be a vector of integer or floating-point primitive types. + /// + /// `U` must be the element type of `T`. + #[rustc_nounwind] + pub fn simd_reduce_xor(x: T) -> U; + + /// Truncates an integer vector to a bitmask. + /// + /// `T` must be an integer vector. + /// + /// `U` must be either the smallest unsigned integer with at least as many bits as the length + /// of `T`, or the smallest array of `u8` with at least as many bits as the length of `T`. + /// + /// Each element is truncated to a single bit and packed into the result. + /// + /// No matter whether the output is an array or an unsigned integer, it is treated as a single + /// contiguous list of bits. The bitmask is always packed on the least-significant side of the + /// output, and padded with 0s in the most-significant bits. The order of the bits depends on + /// endianness: + /// + /// * On little endian, the least significant bit corresponds to the first vector element. + /// * On big endian, the least significant bit corresponds to the last vector element. + /// + /// For example, `[!0, 0, !0, !0]` packs to + /// - `0b1101u8` or `[0b1101]` on little endian, and + /// - `0b1011u8` or `[0b1011]` on big endian. + /// + /// To consider a larger example, + /// `[!0, 0, 0, 0, 0, 0, 0, 0, !0, !0, 0, 0, 0, 0, !0, 0]` packs to + /// - `0b0100001100000001u16` or `[0b00000001, 0b01000011]` on little endian, and + /// - `0b1000000011000010u16` or `[0b10000000, 0b11000010]` on big endian. + /// + /// And finally, a non-power-of-2 example with multiple bytes: + /// `[!0, !0, 0, !0, 0, 0, !0, 0, !0, 0]` packs to + /// - `0b0101001011u16` or `[0b01001011, 0b01]` on little endian, and + /// - `0b1101001010u16` or `[0b11, 0b01001010]` on big endian. + /// + /// # Safety + /// `x` must contain only `0` and `!0`. + #[rustc_nounwind] + pub fn simd_bitmask(x: T) -> U; + + /// Selects elements from a mask. + /// + /// `M` must be an integer vector. + /// + /// `T` must be a vector with the same number of elements as `M`. + /// + /// For each element, if the corresponding value in `mask` is `!0`, select the element from + /// `if_true`. If the corresponding value in `mask` is `0`, select the element from + /// `if_false`. + /// + /// # Safety + /// `mask` must only contain `0` and `!0`. + #[rustc_nounwind] + pub fn simd_select(mask: M, if_true: T, if_false: T) -> T; + + /// Selects elements from a bitmask. + /// + /// `M` must be an unsigned integer or array of `u8`, matching `simd_bitmask`. + /// + /// `T` must be a vector. + /// + /// For each element, if the bit in `mask` is `1`, select the element from + /// `if_true`. If the corresponding bit in `mask` is `0`, select the element from + /// `if_false`. + /// + /// The bitmask bit order matches `simd_bitmask`. + /// + /// # Safety + /// Padding bits must be all zero. + #[rustc_nounwind] + pub fn simd_select_bitmask(m: M, yes: T, no: T) -> T; + + /// Calculates the offset from a pointer vector elementwise, potentially + /// wrapping. + /// + /// `T` must be a vector of pointers. + /// + /// `U` must be a vector of `isize` or `usize` with the same number of elements as `T`. + /// + /// Operates as if by `::wrapping_offset`. + #[rustc_nounwind] + pub fn simd_arith_offset(ptr: T, offset: U) -> T; + + /// Casts a vector of pointers. + /// + /// `T` and `U` must be vectors of pointers with the same number of elements. + #[rustc_nounwind] + pub fn simd_cast_ptr(ptr: T) -> U; + + /// Exposes a vector of pointers as a vector of addresses. + /// + /// `T` must be a vector of pointers. + /// + /// `U` must be a vector of `usize` with the same length as `T`. + #[rustc_nounwind] + pub fn simd_expose_provenance(ptr: T) -> U; + + /// Creates a vector of pointers from a vector of addresses. + /// + /// `T` must be a vector of `usize`. + /// + /// `U` must be a vector of pointers, with the same length as `T`. + #[rustc_nounwind] + pub fn simd_with_exposed_provenance(addr: T) -> U; + + /// Swaps bytes of each element. + /// + /// `T` must be a vector of integers. + #[rustc_nounwind] + pub fn simd_bswap(x: T) -> T; + + /// Reverses bits of each element. + /// + /// `T` must be a vector of integers. + #[rustc_nounwind] + pub fn simd_bitreverse(x: T) -> T; + + /// Counts the leading zeros of each element. + /// + /// `T` must be a vector of integers. + #[rustc_nounwind] + pub fn simd_ctlz(x: T) -> T; + + /// Counts the number of ones in each element. + /// + /// `T` must be a vector of integers. + #[rustc_nounwind] + pub fn simd_ctpop(x: T) -> T; + + /// Counts the trailing zeros of each element. + /// + /// `T` must be a vector of integers. + #[rustc_nounwind] + pub fn simd_cttz(x: T) -> T; + + /// Rounds up each element to the next highest integer-valued float. + /// + /// `T` must be a vector of floats. + #[rustc_nounwind] + pub fn simd_ceil(x: T) -> T; + + /// Rounds down each element to the next lowest integer-valued float. + /// + /// `T` must be a vector of floats. + #[rustc_nounwind] + pub fn simd_floor(x: T) -> T; + + /// Rounds each element to the closest integer-valued float. + /// Ties are resolved by rounding away from 0. + /// + /// `T` must be a vector of floats. + #[rustc_nounwind] + pub fn simd_round(x: T) -> T; + + /// Returns the integer part of each element as an integer-valued float. + /// In other words, non-integer values are truncated towards zero. + /// + /// `T` must be a vector of floats. + #[rustc_nounwind] + pub fn simd_trunc(x: T) -> T; + + /// Takes the square root of each element. + /// + /// `T` must be a vector of floats. + #[rustc_nounwind] + pub fn simd_fsqrt(x: T) -> T; + + /// Computes `(x*y) + z` for each element, but without any intermediate rounding. + /// + /// `T` must be a vector of floats. + #[rustc_nounwind] + pub fn simd_fma(x: T, y: T, z: T) -> T; + + /// Computes `(x*y) + z` for each element, non-deterministically executing either + /// a fused multiply-add or two operations with rounding of the intermediate result. + /// + /// The operation is fused if the code generator determines that target instruction + /// set has support for a fused operation, and that the fused operation is more efficient + /// than the equivalent, separate pair of mul and add instructions. It is unspecified + /// whether or not a fused operation is selected, and that may depend on optimization + /// level and context, for example. It may even be the case that some SIMD lanes get fused + /// and others do not. + /// + /// `T` must be a vector of floats. + #[cfg(not(bootstrap))] + #[rustc_nounwind] + pub fn simd_relaxed_fma(x: T, y: T, z: T) -> T; + + // Computes the sine of each element. + /// + /// `T` must be a vector of floats. + #[rustc_nounwind] + pub fn simd_fsin(a: T) -> T; + + // Computes the cosine of each element. + /// + /// `T` must be a vector of floats. + #[rustc_nounwind] + pub fn simd_fcos(a: T) -> T; + + // Computes the exponential function of each element. + /// + /// `T` must be a vector of floats. + #[rustc_nounwind] + pub fn simd_fexp(a: T) -> T; + + // Computes 2 raised to the power of each element. + /// + /// `T` must be a vector of floats. + #[rustc_nounwind] + pub fn simd_fexp2(a: T) -> T; + + // Computes the base 10 logarithm of each element. + /// + /// `T` must be a vector of floats. + #[rustc_nounwind] + pub fn simd_flog10(a: T) -> T; + + // Computes the base 2 logarithm of each element. + /// + /// `T` must be a vector of floats. + #[rustc_nounwind] + pub fn simd_flog2(a: T) -> T; + + // Computes the natural logarithm of each element. + /// + /// `T` must be a vector of floats. + #[rustc_nounwind] + pub fn simd_flog(a: T) -> T; +} diff --git a/CoqOfRust/core/io/borrowed_buf.rs b/CoqOfRust/core/io/borrowed_buf.rs new file mode 100644 index 000000000..4227e503b --- /dev/null +++ b/CoqOfRust/core/io/borrowed_buf.rs @@ -0,0 +1,356 @@ +#![unstable(feature = "core_io_borrowed_buf", issue = "117693")] + +use crate::fmt::{self, Debug, Formatter}; +use crate::mem::{self, MaybeUninit}; +use crate::{cmp, ptr}; + +/// A borrowed byte buffer which is incrementally filled and initialized. +/// +/// This type is a sort of "double cursor". It tracks three regions in the buffer: a region at the beginning of the +/// buffer that has been logically filled with data, a region that has been initialized at some point but not yet +/// logically filled, and a region at the end that is fully uninitialized. The filled region is guaranteed to be a +/// subset of the initialized region. +/// +/// In summary, the contents of the buffer can be visualized as: +/// ```not_rust +/// [ capacity ] +/// [ filled | unfilled ] +/// [ initialized | uninitialized ] +/// ``` +/// +/// A `BorrowedBuf` is created around some existing data (or capacity for data) via a unique reference +/// (`&mut`). The `BorrowedBuf` can be configured (e.g., using `clear` or `set_init`), but cannot be +/// directly written. To write into the buffer, use `unfilled` to create a `BorrowedCursor`. The cursor +/// has write-only access to the unfilled portion of the buffer (you can think of it as a +/// write-only iterator). +/// +/// The lifetime `'data` is a bound on the lifetime of the underlying data. +pub struct BorrowedBuf<'data> { + /// The buffer's underlying data. + buf: &'data mut [MaybeUninit], + /// The length of `self.buf` which is known to be filled. + filled: usize, + /// The length of `self.buf` which is known to be initialized. + init: usize, +} + +impl Debug for BorrowedBuf<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_struct("BorrowedBuf") + .field("init", &self.init) + .field("filled", &self.filled) + .field("capacity", &self.capacity()) + .finish() + } +} + +/// Creates a new `BorrowedBuf` from a fully initialized slice. +impl<'data> From<&'data mut [u8]> for BorrowedBuf<'data> { + #[inline] + fn from(slice: &'data mut [u8]) -> BorrowedBuf<'data> { + let len = slice.len(); + + BorrowedBuf { + // SAFETY: initialized data never becoming uninitialized is an invariant of BorrowedBuf + buf: unsafe { (slice as *mut [u8]).as_uninit_slice_mut().unwrap() }, + filled: 0, + init: len, + } + } +} + +/// Creates a new `BorrowedBuf` from an uninitialized buffer. +/// +/// Use `set_init` if part of the buffer is known to be already initialized. +impl<'data> From<&'data mut [MaybeUninit]> for BorrowedBuf<'data> { + #[inline] + fn from(buf: &'data mut [MaybeUninit]) -> BorrowedBuf<'data> { + BorrowedBuf { buf, filled: 0, init: 0 } + } +} + +impl<'data> BorrowedBuf<'data> { + /// Returns the total capacity of the buffer. + #[inline] + pub fn capacity(&self) -> usize { + self.buf.len() + } + + /// Returns the length of the filled part of the buffer. + #[inline] + pub fn len(&self) -> usize { + self.filled + } + + /// Returns the length of the initialized part of the buffer. + #[inline] + pub fn init_len(&self) -> usize { + self.init + } + + /// Returns a shared reference to the filled portion of the buffer. + #[inline] + pub fn filled(&self) -> &[u8] { + // SAFETY: We only slice the filled part of the buffer, which is always valid + unsafe { + let buf = self.buf.get_unchecked(..self.filled); + MaybeUninit::slice_assume_init_ref(buf) + } + } + + /// Returns a mutable reference to the filled portion of the buffer. + #[inline] + pub fn filled_mut(&mut self) -> &mut [u8] { + // SAFETY: We only slice the filled part of the buffer, which is always valid + unsafe { + let buf = self.buf.get_unchecked_mut(..self.filled); + MaybeUninit::slice_assume_init_mut(buf) + } + } + + /// Returns a shared reference to the filled portion of the buffer with its original lifetime. + #[inline] + pub fn into_filled(self) -> &'data [u8] { + // SAFETY: We only slice the filled part of the buffer, which is always valid + unsafe { + let buf = self.buf.get_unchecked(..self.filled); + MaybeUninit::slice_assume_init_ref(buf) + } + } + + /// Returns a mutable reference to the filled portion of the buffer with its original lifetime. + #[inline] + pub fn into_filled_mut(self) -> &'data mut [u8] { + // SAFETY: We only slice the filled part of the buffer, which is always valid + unsafe { + let buf = self.buf.get_unchecked_mut(..self.filled); + MaybeUninit::slice_assume_init_mut(buf) + } + } + + /// Returns a cursor over the unfilled part of the buffer. + #[inline] + pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this> { + BorrowedCursor { + start: self.filled, + // SAFETY: we never assign into `BorrowedCursor::buf`, so treating its + // lifetime covariantly is safe. + buf: unsafe { + mem::transmute::<&'this mut BorrowedBuf<'data>, &'this mut BorrowedBuf<'this>>(self) + }, + } + } + + /// Clears the buffer, resetting the filled region to empty. + /// + /// The number of initialized bytes is not changed, and the contents of the buffer are not modified. + #[inline] + pub fn clear(&mut self) -> &mut Self { + self.filled = 0; + self + } + + /// Asserts that the first `n` bytes of the buffer are initialized. + /// + /// `BorrowedBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer + /// bytes than are already known to be initialized. + /// + /// # Safety + /// + /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized. + #[inline] + pub unsafe fn set_init(&mut self, n: usize) -> &mut Self { + self.init = cmp::max(self.init, n); + self + } +} + +/// A writeable view of the unfilled portion of a [`BorrowedBuf`]. +/// +/// The unfilled portion consists of an initialized and an uninitialized part; see [`BorrowedBuf`] +/// for details. +/// +/// Data can be written directly to the cursor by using [`append`](BorrowedCursor::append) or +/// indirectly by getting a slice of part or all of the cursor and writing into the slice. In the +/// indirect case, the caller must call [`advance`](BorrowedCursor::advance) after writing to inform +/// the cursor how many bytes have been written. +/// +/// Once data is written to the cursor, it becomes part of the filled portion of the underlying +/// `BorrowedBuf` and can no longer be accessed or re-written by the cursor. I.e., the cursor tracks +/// the unfilled part of the underlying `BorrowedBuf`. +/// +/// The lifetime `'a` is a bound on the lifetime of the underlying buffer (which means it is a bound +/// on the data in that buffer by transitivity). +#[derive(Debug)] +pub struct BorrowedCursor<'a> { + /// The underlying buffer. + // Safety invariant: we treat the type of buf as covariant in the lifetime of `BorrowedBuf` when + // we create a `BorrowedCursor`. This is only safe if we never replace `buf` by assigning into + // it, so don't do that! + buf: &'a mut BorrowedBuf<'a>, + /// The length of the filled portion of the underlying buffer at the time of the cursor's + /// creation. + start: usize, +} + +impl<'a> BorrowedCursor<'a> { + /// Reborrows this cursor by cloning it with a smaller lifetime. + /// + /// Since a cursor maintains unique access to its underlying buffer, the borrowed cursor is + /// not accessible while the new cursor exists. + #[inline] + pub fn reborrow<'this>(&'this mut self) -> BorrowedCursor<'this> { + BorrowedCursor { + // SAFETY: we never assign into `BorrowedCursor::buf`, so treating its + // lifetime covariantly is safe. + buf: unsafe { + mem::transmute::<&'this mut BorrowedBuf<'a>, &'this mut BorrowedBuf<'this>>( + self.buf, + ) + }, + start: self.start, + } + } + + /// Returns the available space in the cursor. + #[inline] + pub fn capacity(&self) -> usize { + self.buf.capacity() - self.buf.filled + } + + /// Returns the number of bytes written to this cursor since it was created from a `BorrowedBuf`. + /// + /// Note that if this cursor is a reborrowed clone of another, then the count returned is the + /// count written via either cursor, not the count since the cursor was reborrowed. + #[inline] + pub fn written(&self) -> usize { + self.buf.filled - self.start + } + + /// Returns a shared reference to the initialized portion of the cursor. + #[inline] + pub fn init_ref(&self) -> &[u8] { + // SAFETY: We only slice the initialized part of the buffer, which is always valid + unsafe { + let buf = self.buf.buf.get_unchecked(self.buf.filled..self.buf.init); + MaybeUninit::slice_assume_init_ref(buf) + } + } + + /// Returns a mutable reference to the initialized portion of the cursor. + #[inline] + pub fn init_mut(&mut self) -> &mut [u8] { + // SAFETY: We only slice the initialized part of the buffer, which is always valid + unsafe { + let buf = self.buf.buf.get_unchecked_mut(self.buf.filled..self.buf.init); + MaybeUninit::slice_assume_init_mut(buf) + } + } + + /// Returns a mutable reference to the uninitialized part of the cursor. + /// + /// It is safe to uninitialize any of these bytes. + #[inline] + pub fn uninit_mut(&mut self) -> &mut [MaybeUninit] { + // SAFETY: always in bounds + unsafe { self.buf.buf.get_unchecked_mut(self.buf.init..) } + } + + /// Returns a mutable reference to the whole cursor. + /// + /// # Safety + /// + /// The caller must not uninitialize any bytes in the initialized portion of the cursor. + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit] { + // SAFETY: always in bounds + unsafe { self.buf.buf.get_unchecked_mut(self.buf.filled..) } + } + + /// Advances the cursor by asserting that `n` bytes have been filled. + /// + /// After advancing, the `n` bytes are no longer accessible via the cursor and can only be + /// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements + /// and its unfilled portion (and the capacity of this cursor) shrinks by `n` elements. + /// + /// If less than `n` bytes initialized (by the cursor's point of view), `set_init` should be + /// called first. + /// + /// # Panics + /// + /// Panics if there are less than `n` bytes initialized. + #[inline] + pub fn advance(&mut self, n: usize) -> &mut Self { + let filled = self.buf.filled.strict_add(n); + assert!(filled <= self.buf.init); + + self.buf.filled = filled; + self + } + + /// Advances the cursor by asserting that `n` bytes have been filled. + /// + /// After advancing, the `n` bytes are no longer accessible via the cursor and can only be + /// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements + /// and its unfilled portion (and the capacity of this cursor) shrinks by `n` elements. + /// + /// # Safety + /// + /// The caller must ensure that the first `n` bytes of the cursor have been properly + /// initialised. + #[inline] + pub unsafe fn advance_unchecked(&mut self, n: usize) -> &mut Self { + self.buf.filled += n; + self.buf.init = cmp::max(self.buf.init, self.buf.filled); + self + } + + /// Initializes all bytes in the cursor. + #[inline] + pub fn ensure_init(&mut self) -> &mut Self { + let uninit = self.uninit_mut(); + // SAFETY: 0 is a valid value for MaybeUninit and the length matches the allocation + // since it is comes from a slice reference. + unsafe { + ptr::write_bytes(uninit.as_mut_ptr(), 0, uninit.len()); + } + self.buf.init = self.buf.capacity(); + + self + } + + /// Asserts that the first `n` unfilled bytes of the cursor are initialized. + /// + /// `BorrowedBuf` assumes that bytes are never de-initialized, so this method does nothing when + /// called with fewer bytes than are already known to be initialized. + /// + /// # Safety + /// + /// The caller must ensure that the first `n` bytes of the buffer have already been initialized. + #[inline] + pub unsafe fn set_init(&mut self, n: usize) -> &mut Self { + self.buf.init = cmp::max(self.buf.init, self.buf.filled + n); + self + } + + /// Appends data to the cursor, advancing position within its buffer. + /// + /// # Panics + /// + /// Panics if `self.capacity()` is less than `buf.len()`. + #[inline] + pub fn append(&mut self, buf: &[u8]) { + assert!(self.capacity() >= buf.len()); + + // SAFETY: we do not de-initialize any of the elements of the slice + unsafe { + MaybeUninit::copy_from_slice(&mut self.as_mut()[..buf.len()], buf); + } + + // SAFETY: We just added the entire contents of buf to the filled section. + unsafe { + self.set_init(buf.len()); + } + self.buf.filled += buf.len(); + } +} diff --git a/CoqOfRust/core/io/mod.rs b/CoqOfRust/core/io/mod.rs new file mode 100644 index 000000000..2f20180cd --- /dev/null +++ b/CoqOfRust/core/io/mod.rs @@ -0,0 +1,6 @@ +//! Traits, helpers, and type definitions for core I/O functionality. + +mod borrowed_buf; + +#[unstable(feature = "core_io_borrowed_buf", issue = "117693")] +pub use self::borrowed_buf::{BorrowedBuf, BorrowedCursor}; diff --git a/CoqOfRust/core/iter/adapters/array_chunks.rs b/CoqOfRust/core/iter/adapters/array_chunks.rs new file mode 100644 index 000000000..8f1744fc5 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/array_chunks.rs @@ -0,0 +1,276 @@ +use crate::array; +use crate::iter::adapters::SourceIter; +use crate::iter::{ + ByRefSized, FusedIterator, InPlaceIterable, TrustedFused, TrustedRandomAccessNoCoerce, +}; +use crate::num::NonZero; +use crate::ops::{ControlFlow, NeverShortCircuit, Try}; + +/// An iterator over `N` elements of the iterator at a time. +/// +/// The chunks do not overlap. If `N` does not divide the length of the +/// iterator, then the last up to `N-1` elements will be omitted. +/// +/// This `struct` is created by the [`array_chunks`][Iterator::array_chunks] +/// method on [`Iterator`]. See its documentation for more. +#[derive(Debug, Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] +pub struct ArrayChunks { + iter: I, + remainder: Option>, +} + +impl ArrayChunks +where + I: Iterator, +{ + #[track_caller] + pub(in crate::iter) fn new(iter: I) -> Self { + assert!(N != 0, "chunk size must be non-zero"); + Self { iter, remainder: None } + } + + /// Returns an iterator over the remaining elements of the original iterator + /// that are not going to be returned by this iterator. The returned + /// iterator will yield at most `N-1` elements. + /// + /// # Example + /// ``` + /// # // Also serves as a regression test for https://github.com/rust-lang/rust/issues/123333 + /// # #![feature(iter_array_chunks)] + /// let x = [1,2,3,4,5].into_iter().array_chunks::<2>(); + /// let mut rem = x.into_remainder().unwrap(); + /// assert_eq!(rem.next(), Some(5)); + /// assert_eq!(rem.next(), None); + /// ``` + #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] + #[inline] + pub fn into_remainder(mut self) -> Option> { + if self.remainder.is_none() { + while let Some(_) = self.next() {} + } + self.remainder + } +} + +#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] +impl Iterator for ArrayChunks +where + I: Iterator, +{ + type Item = [I::Item; N]; + + #[inline] + fn next(&mut self) -> Option { + self.try_for_each(ControlFlow::Break).break_value() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (lower, upper) = self.iter.size_hint(); + + (lower / N, upper.map(|n| n / N)) + } + + #[inline] + fn count(self) -> usize { + self.iter.count() / N + } + + fn try_fold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let mut acc = init; + loop { + match self.iter.next_chunk() { + Ok(chunk) => acc = f(acc, chunk)?, + Err(remainder) => { + // Make sure to not override `self.remainder` with an empty array + // when `next` is called after `ArrayChunks` exhaustion. + self.remainder.get_or_insert(remainder); + + break try { acc }; + } + } + } + } + + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + ::fold(self, init, f) + } +} + +#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] +impl DoubleEndedIterator for ArrayChunks +where + I: DoubleEndedIterator + ExactSizeIterator, +{ + #[inline] + fn next_back(&mut self) -> Option { + self.try_rfold((), |(), x| ControlFlow::Break(x)).break_value() + } + + fn try_rfold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + // We are iterating from the back we need to first handle the remainder. + self.next_back_remainder(); + + let mut acc = init; + let mut iter = ByRefSized(&mut self.iter).rev(); + + // NB remainder is handled by `next_back_remainder`, so + // `next_chunk` can't return `Err` with non-empty remainder + // (assuming correct `I as ExactSizeIterator` impl). + while let Ok(mut chunk) = iter.next_chunk() { + // FIXME: do not do double reverse + // (we could instead add `next_chunk_back` for example) + chunk.reverse(); + acc = f(acc, chunk)? + } + + try { acc } + } + + impl_fold_via_try_fold! { rfold -> try_rfold } +} + +impl ArrayChunks +where + I: DoubleEndedIterator + ExactSizeIterator, +{ + /// Updates `self.remainder` such that `self.iter.len` is divisible by `N`. + fn next_back_remainder(&mut self) { + // Make sure to not override `self.remainder` with an empty array + // when `next_back` is called after `ArrayChunks` exhaustion. + if self.remainder.is_some() { + return; + } + + // We use the `ExactSizeIterator` implementation of the underlying + // iterator to know how many remaining elements there are. + let rem = self.iter.len() % N; + + // Take the last `rem` elements out of `self.iter`. + let mut remainder = + // SAFETY: `unwrap_err` always succeeds because x % N < N for all x. + unsafe { self.iter.by_ref().rev().take(rem).next_chunk().unwrap_err_unchecked() }; + + // We used `.rev()` above, so we need to re-reverse the reminder + remainder.as_mut_slice().reverse(); + self.remainder = Some(remainder); + } +} + +#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] +impl FusedIterator for ArrayChunks where I: FusedIterator {} + +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for ArrayChunks where I: TrustedFused + Iterator {} + +#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] +impl ExactSizeIterator for ArrayChunks +where + I: ExactSizeIterator, +{ + #[inline] + fn len(&self) -> usize { + self.iter.len() / N + } + + #[inline] + fn is_empty(&self) -> bool { + self.iter.len() < N + } +} + +trait SpecFold: Iterator { + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B; +} + +impl SpecFold for ArrayChunks +where + I: Iterator, +{ + #[inline] + default fn fold(mut self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 + } +} + +impl SpecFold for ArrayChunks +where + I: Iterator + TrustedRandomAccessNoCoerce, +{ + #[inline] + fn fold(mut self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + let mut accum = init; + let inner_len = self.iter.size(); + let mut i = 0; + // Use a while loop because (0..len).step_by(N) doesn't optimize well. + while inner_len - i >= N { + let chunk = crate::array::from_fn(|local| { + // SAFETY: The method consumes the iterator and the loop condition ensures that + // all accesses are in bounds and only happen once. + unsafe { + let idx = i + local; + self.iter.__iterator_get_unchecked(idx) + } + }); + accum = f(accum, chunk); + i += N; + } + + // unlike try_fold this method does not need to take care of the remainder + // since `self` will be dropped + + accum + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for ArrayChunks +where + I: SourceIter + Iterator, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for ArrayChunks { + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = const { + match (I::MERGE_BY, NonZero::new(N)) { + (Some(m), Some(n)) => m.checked_mul(n), + _ => None, + } + }; +} diff --git a/CoqOfRust/core/iter/adapters/by_ref_sized.rs b/CoqOfRust/core/iter/adapters/by_ref_sized.rs new file mode 100644 index 000000000..d084bede1 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/by_ref_sized.rs @@ -0,0 +1,92 @@ +use crate::num::NonZero; +use crate::ops::{NeverShortCircuit, Try}; + +/// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics. +/// +/// Ideally this will no longer be required, eventually, but as can be seen in +/// the benchmarks (as of Feb 2022 at least) `by_ref` can have performance cost. +#[unstable(feature = "std_internals", issue = "none")] +#[derive(Debug)] +pub struct ByRefSized<'a, I>(pub &'a mut I); + +// The following implementations use UFCS-style, rather than trusting autoderef, +// to avoid accidentally calling the `&mut Iterator` implementations. + +#[unstable(feature = "std_internals", issue = "none")] +impl Iterator for ByRefSized<'_, I> { + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + I::next(self.0) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + I::size_hint(self.0) + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + I::advance_by(self.0, n) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + I::nth(self.0, n) + } + + #[inline] + fn fold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + // `fold` needs ownership, so this can't forward directly. + I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 + } + + #[inline] + fn try_fold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + I::try_fold(self.0, init, f) + } +} + +#[unstable(feature = "std_internals", issue = "none")] +impl DoubleEndedIterator for ByRefSized<'_, I> { + #[inline] + fn next_back(&mut self) -> Option { + I::next_back(self.0) + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + I::advance_back_by(self.0, n) + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + I::nth_back(self.0, n) + } + + #[inline] + fn rfold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + // `rfold` needs ownership, so this can't forward directly. + I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 + } + + #[inline] + fn try_rfold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + I::try_rfold(self.0, init, f) + } +} diff --git a/CoqOfRust/core/iter/adapters/chain.rs b/CoqOfRust/core/iter/adapters/chain.rs new file mode 100644 index 000000000..dad3d79ac --- /dev/null +++ b/CoqOfRust/core/iter/adapters/chain.rs @@ -0,0 +1,338 @@ +use crate::iter::{FusedIterator, TrustedLen}; +use crate::num::NonZero; +use crate::ops::Try; + +/// An iterator that links two iterators together, in a chain. +/// +/// This `struct` is created by [`chain`] or [`Iterator::chain`]. See their +/// documentation for more. +/// +/// # Examples +/// +/// ``` +/// use std::iter::Chain; +/// use std::slice::Iter; +/// +/// let a1 = [1, 2, 3]; +/// let a2 = [4, 5, 6]; +/// let iter: Chain, Iter<'_, _>> = a1.iter().chain(a2.iter()); +/// ``` +#[derive(Clone, Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Chain { + // These are "fused" with `Option` so we don't need separate state to track which part is + // already exhausted, and we may also get niche layout for `None`. We don't use the real `Fuse` + // adapter because its specialization for `FusedIterator` unconditionally descends into the + // iterator, and that could be expensive to keep revisiting stuff like nested chains. It also + // hurts compiler performance to add more iterator layers to `Chain`. + // + // Only the "first" iterator is actually set `None` when exhausted, depending on whether you + // iterate forward or backward. If you mix directions, then both sides may be `None`. + a: Option, + b: Option, +} +impl Chain { + pub(in super::super) fn new(a: A, b: B) -> Chain { + Chain { a: Some(a), b: Some(b) } + } +} + +/// Converts the arguments to iterators and links them together, in a chain. +/// +/// See the documentation of [`Iterator::chain`] for more. +/// +/// # Examples +/// +/// ``` +/// #![feature(iter_chain)] +/// +/// use std::iter::chain; +/// +/// let a = [1, 2, 3]; +/// let b = [4, 5, 6]; +/// +/// let mut iter = chain(a, b); +/// +/// assert_eq!(iter.next(), Some(1)); +/// assert_eq!(iter.next(), Some(2)); +/// assert_eq!(iter.next(), Some(3)); +/// assert_eq!(iter.next(), Some(4)); +/// assert_eq!(iter.next(), Some(5)); +/// assert_eq!(iter.next(), Some(6)); +/// assert_eq!(iter.next(), None); +/// ``` +#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")] +pub fn chain(a: A, b: B) -> Chain +where + A: IntoIterator, + B: IntoIterator, +{ + Chain::new(a.into_iter(), b.into_iter()) +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Chain +where + A: Iterator, + B: Iterator, +{ + type Item = A::Item; + + #[inline] + fn next(&mut self) -> Option { + and_then_or_clear(&mut self.a, Iterator::next).or_else(|| self.b.as_mut()?.next()) + } + + #[inline] + #[rustc_inherit_overflow_checks] + fn count(self) -> usize { + let a_count = match self.a { + Some(a) => a.count(), + None => 0, + }; + let b_count = match self.b { + Some(b) => b.count(), + None => 0, + }; + a_count + b_count + } + + fn try_fold(&mut self, mut acc: Acc, mut f: F) -> R + where + Self: Sized, + F: FnMut(Acc, Self::Item) -> R, + R: Try, + { + if let Some(ref mut a) = self.a { + acc = a.try_fold(acc, &mut f)?; + self.a = None; + } + if let Some(ref mut b) = self.b { + acc = b.try_fold(acc, f)?; + // we don't fuse the second iterator + } + try { acc } + } + + fn fold(self, mut acc: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + if let Some(a) = self.a { + acc = a.fold(acc, &mut f); + } + if let Some(b) = self.b { + acc = b.fold(acc, f); + } + acc + } + + #[inline] + fn advance_by(&mut self, mut n: usize) -> Result<(), NonZero> { + if let Some(ref mut a) = self.a { + n = match a.advance_by(n) { + Ok(()) => return Ok(()), + Err(k) => k.get(), + }; + self.a = None; + } + + if let Some(ref mut b) = self.b { + return b.advance_by(n); + // we don't fuse the second iterator + } + + NonZero::new(n).map_or(Ok(()), Err) + } + + #[inline] + fn nth(&mut self, mut n: usize) -> Option { + if let Some(ref mut a) = self.a { + n = match a.advance_by(n) { + Ok(()) => match a.next() { + None => 0, + x => return x, + }, + Err(k) => k.get(), + }; + + self.a = None; + } + + self.b.as_mut()?.nth(n) + } + + #[inline] + fn find

(&mut self, mut predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + and_then_or_clear(&mut self.a, |a| a.find(&mut predicate)) + .or_else(|| self.b.as_mut()?.find(predicate)) + } + + #[inline] + fn last(self) -> Option { + // Must exhaust a before b. + let a_last = self.a.and_then(Iterator::last); + let b_last = self.b.and_then(Iterator::last); + b_last.or(a_last) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + match self { + Chain { a: Some(a), b: Some(b) } => { + let (a_lower, a_upper) = a.size_hint(); + let (b_lower, b_upper) = b.size_hint(); + + let lower = a_lower.saturating_add(b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => x.checked_add(y), + _ => None, + }; + + (lower, upper) + } + Chain { a: Some(a), b: None } => a.size_hint(), + Chain { a: None, b: Some(b) } => b.size_hint(), + Chain { a: None, b: None } => (0, Some(0)), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Chain +where + A: DoubleEndedIterator, + B: DoubleEndedIterator, +{ + #[inline] + fn next_back(&mut self) -> Option { + and_then_or_clear(&mut self.b, |b| b.next_back()).or_else(|| self.a.as_mut()?.next_back()) + } + + #[inline] + fn advance_back_by(&mut self, mut n: usize) -> Result<(), NonZero> { + if let Some(ref mut b) = self.b { + n = match b.advance_back_by(n) { + Ok(()) => return Ok(()), + Err(k) => k.get(), + }; + self.b = None; + } + + if let Some(ref mut a) = self.a { + return a.advance_back_by(n); + // we don't fuse the second iterator + } + + NonZero::new(n).map_or(Ok(()), Err) + } + + #[inline] + fn nth_back(&mut self, mut n: usize) -> Option { + if let Some(ref mut b) = self.b { + n = match b.advance_back_by(n) { + Ok(()) => match b.next_back() { + None => 0, + x => return x, + }, + Err(k) => k.get(), + }; + + self.b = None; + } + + self.a.as_mut()?.nth_back(n) + } + + #[inline] + fn rfind

(&mut self, mut predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + and_then_or_clear(&mut self.b, |b| b.rfind(&mut predicate)) + .or_else(|| self.a.as_mut()?.rfind(predicate)) + } + + fn try_rfold(&mut self, mut acc: Acc, mut f: F) -> R + where + Self: Sized, + F: FnMut(Acc, Self::Item) -> R, + R: Try, + { + if let Some(ref mut b) = self.b { + acc = b.try_rfold(acc, &mut f)?; + self.b = None; + } + if let Some(ref mut a) = self.a { + acc = a.try_rfold(acc, f)?; + // we don't fuse the second iterator + } + try { acc } + } + + fn rfold(self, mut acc: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + if let Some(b) = self.b { + acc = b.rfold(acc, &mut f); + } + if let Some(a) = self.a { + acc = a.rfold(acc, f); + } + acc + } +} + +// Note: *both* must be fused to handle double-ended iterators. +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Chain +where + A: FusedIterator, + B: FusedIterator, +{ +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Chain +where + A: TrustedLen, + B: TrustedLen, +{ +} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for Chain { + /// Creates a `Chain` from the default values for `A` and `B`. + /// + /// ``` + /// # use core::iter::Chain; + /// # use core::slice; + /// # use std::collections::{btree_set, BTreeSet}; + /// # use std::mem; + /// struct Foo<'a>(Chain, btree_set::Iter<'a, u8>>); + /// + /// let set = BTreeSet::::new(); + /// let slice: &[u8] = &[]; + /// let mut foo = Foo(slice.iter().chain(set.iter())); + /// + /// // take requires `Default` + /// let _: Chain<_, _> = mem::take(&mut foo.0); + fn default() -> Self { + Chain::new(Default::default(), Default::default()) + } +} + +#[inline] +fn and_then_or_clear(opt: &mut Option, f: impl FnOnce(&mut T) -> Option) -> Option { + let x = f(opt.as_mut()?); + if x.is_none() { + *opt = None; + } + x +} diff --git a/CoqOfRust/core/iter/adapters/cloned.rs b/CoqOfRust/core/iter/adapters/cloned.rs new file mode 100644 index 000000000..aea6d6428 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/cloned.rs @@ -0,0 +1,190 @@ +use core::num::NonZero; + +use crate::iter::adapters::zip::try_get_unchecked; +use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; +use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator}; +use crate::ops::Try; + +/// An iterator that clones the elements of an underlying iterator. +/// +/// This `struct` is created by the [`cloned`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`cloned`]: Iterator::cloned +/// [`Iterator`]: trait.Iterator.html +#[stable(feature = "iter_cloned", since = "1.1.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[derive(Clone, Debug)] +pub struct Cloned { + it: I, +} + +impl Cloned { + pub(in crate::iter) fn new(it: I) -> Cloned { + Cloned { it } + } +} + +fn clone_try_fold(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R { + move |acc, elt| f(acc, elt.clone()) +} + +#[stable(feature = "iter_cloned", since = "1.1.0")] +impl<'a, I, T: 'a> Iterator for Cloned +where + I: Iterator, + T: Clone, +{ + type Item = T; + + fn next(&mut self) -> Option { + self.it.next().cloned() + } + + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } + + fn try_fold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.it.try_fold(init, clone_try_fold(f)) + } + + fn fold(self, init: Acc, f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + self.it.map(T::clone).fold(init, f) + } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T + where + Self: TrustedRandomAccessNoCoerce, + { + // SAFETY: the caller must uphold the contract for + // `Iterator::__iterator_get_unchecked`. + unsafe { try_get_unchecked(&mut self.it, idx).clone() } + } +} + +#[stable(feature = "iter_cloned", since = "1.1.0")] +impl<'a, I, T: 'a> DoubleEndedIterator for Cloned +where + I: DoubleEndedIterator, + T: Clone, +{ + fn next_back(&mut self) -> Option { + self.it.next_back().cloned() + } + + fn try_rfold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.it.try_rfold(init, clone_try_fold(f)) + } + + fn rfold(self, init: Acc, f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + self.it.map(T::clone).rfold(init, f) + } +} + +#[stable(feature = "iter_cloned", since = "1.1.0")] +impl<'a, I, T: 'a> ExactSizeIterator for Cloned +where + I: ExactSizeIterator, + T: Clone, +{ + fn len(&self) -> usize { + self.it.len() + } + + fn is_empty(&self) -> bool { + self.it.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl<'a, I, T: 'a> FusedIterator for Cloned +where + I: FusedIterator, + T: Clone, +{ +} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for Cloned where I: TrustedRandomAccess {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccessNoCoerce for Cloned +where + I: TrustedRandomAccessNoCoerce, +{ + const MAY_HAVE_SIDE_EFFECT: bool = true; +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a, I, T: 'a> TrustedLen for Cloned +where + I: TrustedLen, + T: Clone, +{ +} + +impl<'a, I, T: 'a> UncheckedIterator for Cloned +where + I: UncheckedIterator, + T: Clone, +{ + unsafe fn next_unchecked(&mut self) -> T { + // SAFETY: `Cloned` is 1:1 with the inner iterator, so if the caller promised + // that there's an element left, the inner iterator has one too. + let item = unsafe { self.it.next_unchecked() }; + item.clone() + } +} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for Cloned { + /// Creates a `Cloned` iterator from the default value of `I` + /// ``` + /// # use core::slice; + /// # use core::iter::Cloned; + /// let iter: Cloned> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Self::new(Default::default()) + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Cloned +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.it) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for Cloned { + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = I::MERGE_BY; +} diff --git a/CoqOfRust/core/iter/adapters/copied.rs b/CoqOfRust/core/iter/adapters/copied.rs new file mode 100644 index 000000000..23e4e25ab --- /dev/null +++ b/CoqOfRust/core/iter/adapters/copied.rs @@ -0,0 +1,275 @@ +use crate::iter::adapters::zip::try_get_unchecked; +use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; +use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; +use crate::mem::{MaybeUninit, SizedTypeProperties}; +use crate::num::NonZero; +use crate::ops::Try; +use crate::{array, ptr}; + +/// An iterator that copies the elements of an underlying iterator. +/// +/// This `struct` is created by the [`copied`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`copied`]: Iterator::copied +/// [`Iterator`]: trait.Iterator.html +#[stable(feature = "iter_copied", since = "1.36.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[derive(Clone, Debug)] +pub struct Copied { + it: I, +} + +impl Copied { + pub(in crate::iter) fn new(it: I) -> Copied { + Copied { it } + } +} + +fn copy_fold(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, &T) -> Acc { + move |acc, &elt| f(acc, elt) +} + +fn copy_try_fold(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R { + move |acc, &elt| f(acc, elt) +} + +#[stable(feature = "iter_copied", since = "1.36.0")] +impl<'a, I, T: 'a> Iterator for Copied +where + I: Iterator, + T: Copy, +{ + type Item = T; + + fn next(&mut self) -> Option { + self.it.next().copied() + } + + fn next_chunk( + &mut self, + ) -> Result<[Self::Item; N], array::IntoIter> + where + Self: Sized, + { + >::spec_next_chunk(&mut self.it) + } + + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } + + fn try_fold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.it.try_fold(init, copy_try_fold(f)) + } + + fn fold(self, init: Acc, f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + self.it.fold(init, copy_fold(f)) + } + + fn nth(&mut self, n: usize) -> Option { + self.it.nth(n).copied() + } + + fn last(self) -> Option { + self.it.last().copied() + } + + fn count(self) -> usize { + self.it.count() + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.it.advance_by(n) + } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T + where + Self: TrustedRandomAccessNoCoerce, + { + // SAFETY: the caller must uphold the contract for + // `Iterator::__iterator_get_unchecked`. + *unsafe { try_get_unchecked(&mut self.it, idx) } + } +} + +#[stable(feature = "iter_copied", since = "1.36.0")] +impl<'a, I, T: 'a> DoubleEndedIterator for Copied +where + I: DoubleEndedIterator, + T: Copy, +{ + fn next_back(&mut self) -> Option { + self.it.next_back().copied() + } + + fn try_rfold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.it.try_rfold(init, copy_try_fold(f)) + } + + fn rfold(self, init: Acc, f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + self.it.rfold(init, copy_fold(f)) + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.it.advance_back_by(n) + } +} + +#[stable(feature = "iter_copied", since = "1.36.0")] +impl<'a, I, T: 'a> ExactSizeIterator for Copied +where + I: ExactSizeIterator, + T: Copy, +{ + fn len(&self) -> usize { + self.it.len() + } + + fn is_empty(&self) -> bool { + self.it.is_empty() + } +} + +#[stable(feature = "iter_copied", since = "1.36.0")] +impl<'a, I, T: 'a> FusedIterator for Copied +where + I: FusedIterator, + T: Copy, +{ +} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for Copied where I: TrustedRandomAccess {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccessNoCoerce for Copied +where + I: TrustedRandomAccessNoCoerce, +{ + const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT; +} + +#[stable(feature = "iter_copied", since = "1.36.0")] +unsafe impl<'a, I, T: 'a> TrustedLen for Copied +where + I: TrustedLen, + T: Copy, +{ +} + +trait SpecNextChunk<'a, const N: usize, T: 'a>: Iterator +where + T: Copy, +{ + fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter>; +} + +impl<'a, const N: usize, I, T: 'a> SpecNextChunk<'a, N, T> for I +where + I: Iterator, + T: Copy, +{ + default fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter> { + array::iter_next_chunk(&mut self.copied()) + } +} + +impl<'a, const N: usize, T: 'a> SpecNextChunk<'a, N, T> for crate::slice::Iter<'a, T> +where + T: Copy, +{ + fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter> { + let mut raw_array = [const { MaybeUninit::uninit() }; N]; + + let len = self.len(); + + if T::IS_ZST { + if len < N { + let _ = self.advance_by(len); + // SAFETY: ZSTs can be conjured ex nihilo; only the amount has to be correct + return Err(unsafe { array::IntoIter::new_unchecked(raw_array, 0..len) }); + } + + let _ = self.advance_by(N); + // SAFETY: ditto + return Ok(unsafe { MaybeUninit::array_assume_init(raw_array) }); + } + + if len < N { + // SAFETY: `len` indicates that this many elements are available and we just checked that + // it fits into the array. + unsafe { + ptr::copy_nonoverlapping( + self.as_ref().as_ptr(), + raw_array.as_mut_ptr() as *mut T, + len, + ); + let _ = self.advance_by(len); + return Err(array::IntoIter::new_unchecked(raw_array, 0..len)); + } + } + + // SAFETY: `len` is larger than the array size. Copy a fixed amount here to fully initialize + // the array. + unsafe { + ptr::copy_nonoverlapping(self.as_ref().as_ptr(), raw_array.as_mut_ptr() as *mut T, N); + let _ = self.advance_by(N); + Ok(MaybeUninit::array_assume_init(raw_array)) + } + } +} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for Copied { + /// Creates a `Copied` iterator from the default value of `I` + /// ``` + /// # use core::slice; + /// # use core::iter::Copied; + /// let iter: Copied> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Self::new(Default::default()) + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Copied +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.it) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for Copied { + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = I::MERGE_BY; +} diff --git a/CoqOfRust/core/iter/adapters/cycle.rs b/CoqOfRust/core/iter/adapters/cycle.rs new file mode 100644 index 000000000..6cb1a3a46 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/cycle.rs @@ -0,0 +1,109 @@ +use crate::iter::FusedIterator; +use crate::num::NonZero; +use crate::ops::Try; + +/// An iterator that repeats endlessly. +/// +/// This `struct` is created by the [`cycle`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`cycle`]: Iterator::cycle +/// [`Iterator`]: trait.Iterator.html +#[derive(Clone, Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Cycle { + orig: I, + iter: I, +} + +impl Cycle { + pub(in crate::iter) fn new(iter: I) -> Cycle { + Cycle { orig: iter.clone(), iter } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Cycle +where + I: Clone + Iterator, +{ + type Item = ::Item; + + #[inline] + fn next(&mut self) -> Option<::Item> { + match self.iter.next() { + None => { + self.iter = self.orig.clone(); + self.iter.next() + } + y => y, + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + // the cycle iterator is either empty or infinite + match self.orig.size_hint() { + sz @ (0, Some(0)) => sz, + (0, _) => (0, None), + _ => (usize::MAX, None), + } + } + + #[inline] + fn try_fold(&mut self, mut acc: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try, + { + // fully iterate the current iterator. this is necessary because + // `self.iter` may be empty even when `self.orig` isn't + acc = self.iter.try_fold(acc, &mut f)?; + self.iter = self.orig.clone(); + + // complete a full cycle, keeping track of whether the cycled + // iterator is empty or not. we need to return early in case + // of an empty iterator to prevent an infinite loop + let mut is_empty = true; + acc = self.iter.try_fold(acc, |acc, x| { + is_empty = false; + f(acc, x) + })?; + + if is_empty { + return try { acc }; + } + + loop { + self.iter = self.orig.clone(); + acc = self.iter.try_fold(acc, &mut f)?; + } + } + + #[inline] + #[rustc_inherit_overflow_checks] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + let mut n = match self.iter.advance_by(n) { + Ok(()) => return Ok(()), + Err(rem) => rem.get(), + }; + + while n > 0 { + self.iter = self.orig.clone(); + n = match self.iter.advance_by(n) { + Ok(()) => return Ok(()), + e @ Err(rem) if rem.get() == n => return e, + Err(rem) => rem.get(), + }; + } + + NonZero::new(n).map_or(Ok(()), Err) + } + + // No `fold` override, because `fold` doesn't make much sense for `Cycle`, + // and we can't do anything better than the default. +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Cycle where I: Clone + Iterator {} diff --git a/CoqOfRust/core/iter/adapters/enumerate.rs b/CoqOfRust/core/iter/adapters/enumerate.rs new file mode 100644 index 000000000..ac15e3767 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/enumerate.rs @@ -0,0 +1,284 @@ +use crate::iter::adapters::zip::try_get_unchecked; +use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; +use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen}; +use crate::num::NonZero; +use crate::ops::Try; + +/// An iterator that yields the current count and the element during iteration. +/// +/// This `struct` is created by the [`enumerate`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`enumerate`]: Iterator::enumerate +/// [`Iterator`]: trait.Iterator.html +#[derive(Clone, Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Enumerate")] +pub struct Enumerate { + iter: I, + count: usize, +} +impl Enumerate { + pub(in crate::iter) fn new(iter: I) -> Enumerate { + Enumerate { iter, count: 0 } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Enumerate +where + I: Iterator, +{ + type Item = (usize, ::Item); + + /// # Overflow Behavior + /// + /// The method does no guarding against overflows, so enumerating more than + /// `usize::MAX` elements either produces the wrong result or panics. If + /// debug assertions are enabled, a panic is guaranteed. + /// + /// # Panics + /// + /// Might panic if the index of the element overflows a `usize`. + #[inline] + #[rustc_inherit_overflow_checks] + fn next(&mut self) -> Option<(usize, ::Item)> { + let a = self.iter.next()?; + let i = self.count; + self.count += 1; + Some((i, a)) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + #[inline] + #[rustc_inherit_overflow_checks] + fn nth(&mut self, n: usize) -> Option<(usize, I::Item)> { + let a = self.iter.nth(n)?; + let i = self.count + n; + self.count = i + 1; + Some((i, a)) + } + + #[inline] + fn count(self) -> usize { + self.iter.count() + } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + #[inline] + fn enumerate<'a, T, Acc, R>( + count: &'a mut usize, + mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a, + ) -> impl FnMut(Acc, T) -> R + 'a { + #[rustc_inherit_overflow_checks] + move |acc, item| { + let acc = fold(acc, (*count, item)); + *count += 1; + acc + } + } + + self.iter.try_fold(init, enumerate(&mut self.count, fold)) + } + + #[inline] + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + #[inline] + fn enumerate( + mut count: usize, + mut fold: impl FnMut(Acc, (usize, T)) -> Acc, + ) -> impl FnMut(Acc, T) -> Acc { + #[rustc_inherit_overflow_checks] + move |acc, item| { + let acc = fold(acc, (count, item)); + count += 1; + acc + } + } + + self.iter.fold(init, enumerate(self.count, fold)) + } + + #[inline] + #[rustc_inherit_overflow_checks] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + let remaining = self.iter.advance_by(n); + let advanced = match remaining { + Ok(()) => n, + Err(rem) => n - rem.get(), + }; + self.count += advanced; + remaining + } + + #[rustc_inherit_overflow_checks] + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> ::Item + where + Self: TrustedRandomAccessNoCoerce, + { + // SAFETY: the caller must uphold the contract for + // `Iterator::__iterator_get_unchecked`. + let value = unsafe { try_get_unchecked(&mut self.iter, idx) }; + (self.count + idx, value) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Enumerate +where + I: ExactSizeIterator + DoubleEndedIterator, +{ + #[inline] + fn next_back(&mut self) -> Option<(usize, ::Item)> { + let a = self.iter.next_back()?; + let len = self.iter.len(); + // Can safely add, `ExactSizeIterator` promises that the number of + // elements fits into a `usize`. + Some((self.count + len, a)) + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option<(usize, ::Item)> { + let a = self.iter.nth_back(n)?; + let len = self.iter.len(); + // Can safely add, `ExactSizeIterator` promises that the number of + // elements fits into a `usize`. + Some((self.count + len, a)) + } + + #[inline] + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + // Can safely add and subtract the count, as `ExactSizeIterator` promises + // that the number of elements fits into a `usize`. + fn enumerate( + mut count: usize, + mut fold: impl FnMut(Acc, (usize, T)) -> R, + ) -> impl FnMut(Acc, T) -> R { + move |acc, item| { + count -= 1; + fold(acc, (count, item)) + } + } + + let count = self.count + self.iter.len(); + self.iter.try_rfold(init, enumerate(count, fold)) + } + + #[inline] + fn rfold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + // Can safely add and subtract the count, as `ExactSizeIterator` promises + // that the number of elements fits into a `usize`. + fn enumerate( + mut count: usize, + mut fold: impl FnMut(Acc, (usize, T)) -> Acc, + ) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| { + count -= 1; + fold(acc, (count, item)) + } + } + + let count = self.count + self.iter.len(); + self.iter.rfold(init, enumerate(count, fold)) + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + // we do not need to update the count since that only tallies the number of items + // consumed from the front. consuming items from the back can never reduce that. + self.iter.advance_back_by(n) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Enumerate +where + I: ExactSizeIterator, +{ + fn len(&self) -> usize { + self.iter.len() + } + + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for Enumerate where I: TrustedRandomAccess {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccessNoCoerce for Enumerate +where + I: TrustedRandomAccessNoCoerce, +{ + const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT; +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Enumerate where I: FusedIterator {} + +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Enumerate {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Enumerate where I: TrustedLen {} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Enumerate +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for Enumerate { + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = I::MERGE_BY; +} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for Enumerate { + /// Creates an `Enumerate` iterator from the default value of `I` + /// ``` + /// # use core::slice; + /// # use std::iter::Enumerate; + /// let iter: Enumerate> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Enumerate::new(Default::default()) + } +} diff --git a/CoqOfRust/core/iter/adapters/filter.rs b/CoqOfRust/core/iter/adapters/filter.rs new file mode 100644 index 000000000..dd08cd6f6 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/filter.rs @@ -0,0 +1,216 @@ +use core::array; +use core::mem::MaybeUninit; +use core::ops::ControlFlow; + +use crate::fmt; +use crate::iter::adapters::SourceIter; +use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused}; +use crate::num::NonZero; +use crate::ops::Try; + +/// An iterator that filters the elements of `iter` with `predicate`. +/// +/// This `struct` is created by the [`filter`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`filter`]: Iterator::filter +/// [`Iterator`]: trait.Iterator.html +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] +pub struct Filter { + // Used for `SplitWhitespace` and `SplitAsciiWhitespace` `as_str` methods + pub(crate) iter: I, + predicate: P, +} +impl Filter { + pub(in crate::iter) fn new(iter: I, predicate: P) -> Filter { + Filter { iter, predicate } + } +} + +impl Filter +where + I: Iterator, + P: FnMut(&I::Item) -> bool, +{ + #[inline] + fn next_chunk_dropless( + &mut self, + ) -> Result<[I::Item; N], array::IntoIter> { + let mut array: [MaybeUninit; N] = [const { MaybeUninit::uninit() }; N]; + let mut initialized = 0; + + let result = self.iter.try_for_each(|element| { + let idx = initialized; + // branchless index update combined with unconditionally copying the value even when + // it is filtered reduces branching and dependencies in the loop. + initialized = idx + (self.predicate)(&element) as usize; + // SAFETY: Loop conditions ensure the index is in bounds. + unsafe { array.get_unchecked_mut(idx) }.write(element); + + if initialized < N { ControlFlow::Continue(()) } else { ControlFlow::Break(()) } + }); + + match result { + ControlFlow::Break(()) => { + // SAFETY: The loop above is only explicitly broken when the array has been fully initialized + Ok(unsafe { MaybeUninit::array_assume_init(array) }) + } + ControlFlow::Continue(()) => { + // SAFETY: The range is in bounds since the loop breaks when reaching N elements. + Err(unsafe { array::IntoIter::new_unchecked(array, 0..initialized) }) + } + } + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for Filter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Filter").field("iter", &self.iter).finish() + } +} + +fn filter_fold( + mut predicate: impl FnMut(&T) -> bool, + mut fold: impl FnMut(Acc, T) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| if predicate(&item) { fold(acc, item) } else { acc } +} + +fn filter_try_fold<'a, T, Acc, R: Try>( + predicate: &'a mut impl FnMut(&T) -> bool, + mut fold: impl FnMut(Acc, T) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| if predicate(&item) { fold(acc, item) } else { try { acc } } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Filter +where + P: FnMut(&I::Item) -> bool, +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + self.iter.find(&mut self.predicate) + } + + #[inline] + fn next_chunk( + &mut self, + ) -> Result<[Self::Item; N], array::IntoIter> { + // avoid codegen for the dead branch + let fun = const { + if crate::mem::needs_drop::() { + array::iter_next_chunk:: + } else { + Self::next_chunk_dropless:: + } + }; + + fun(self) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } + + // this special case allows the compiler to make `.filter(_).count()` + // branchless. Barring perfect branch prediction (which is unattainable in + // the general case), this will be much faster in >90% of cases (containing + // virtually all real workloads) and only a tiny bit slower in the rest. + // + // Having this specialization thus allows us to write `.filter(p).count()` + // where we would otherwise write `.map(|x| p(x) as usize).sum()`, which is + // less readable and also less backwards-compatible to Rust before 1.10. + // + // Using the branchless version will also simplify the LLVM byte code, thus + // leaving more budget for LLVM optimizations. + #[inline] + fn count(self) -> usize { + #[inline] + fn to_usize(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> usize { + move |x| predicate(&x) as usize + } + + self.iter.map(to_usize(self.predicate)).sum() + } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.iter.try_fold(init, filter_try_fold(&mut self.predicate, fold)) + } + + #[inline] + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.fold(init, filter_fold(self.predicate, fold)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Filter +where + P: FnMut(&I::Item) -> bool, +{ + #[inline] + fn next_back(&mut self) -> Option { + self.iter.rfind(&mut self.predicate) + } + + #[inline] + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.iter.try_rfold(init, filter_try_fold(&mut self.predicate, fold)) + } + + #[inline] + fn rfold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.rfold(init, filter_fold(self.predicate, fold)) + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Filter where P: FnMut(&I::Item) -> bool {} + +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Filter {} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Filter +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for Filter { + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = I::MERGE_BY; +} diff --git a/CoqOfRust/core/iter/adapters/filter_map.rs b/CoqOfRust/core/iter/adapters/filter_map.rs new file mode 100644 index 000000000..cc64ceb13 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/filter_map.rs @@ -0,0 +1,215 @@ +use crate::iter::adapters::SourceIter; +use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused}; +use crate::mem::{ManuallyDrop, MaybeUninit}; +use crate::num::NonZero; +use crate::ops::{ControlFlow, Try}; +use crate::{array, fmt}; + +/// An iterator that uses `f` to both filter and map elements from `iter`. +/// +/// This `struct` is created by the [`filter_map`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`filter_map`]: Iterator::filter_map +/// [`Iterator`]: trait.Iterator.html +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] +pub struct FilterMap { + iter: I, + f: F, +} +impl FilterMap { + pub(in crate::iter) fn new(iter: I, f: F) -> FilterMap { + FilterMap { iter, f } + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for FilterMap { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FilterMap").field("iter", &self.iter).finish() + } +} + +fn filter_map_fold( + mut f: impl FnMut(T) -> Option, + mut fold: impl FnMut(Acc, B) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| match f(item) { + Some(x) => fold(acc, x), + None => acc, + } +} + +fn filter_map_try_fold<'a, T, B, Acc, R: Try>( + f: &'a mut impl FnMut(T) -> Option, + mut fold: impl FnMut(Acc, B) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| match f(item) { + Some(x) => fold(acc, x), + None => try { acc }, + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for FilterMap +where + F: FnMut(I::Item) -> Option, +{ + type Item = B; + + #[inline] + fn next(&mut self) -> Option { + self.iter.find_map(&mut self.f) + } + + #[inline] + fn next_chunk( + &mut self, + ) -> Result<[Self::Item; N], array::IntoIter> { + let mut array: [MaybeUninit; N] = [const { MaybeUninit::uninit() }; N]; + + struct Guard<'a, T> { + array: &'a mut [MaybeUninit], + initialized: usize, + } + + impl Drop for Guard<'_, T> { + #[inline] + fn drop(&mut self) { + if const { crate::mem::needs_drop::() } { + // SAFETY: self.initialized is always <= N, which also is the length of the array. + unsafe { + core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut( + self.array.get_unchecked_mut(..self.initialized), + )); + } + } + } + } + + let mut guard = Guard { array: &mut array, initialized: 0 }; + + let result = self.iter.try_for_each(|element| { + let idx = guard.initialized; + let val = (self.f)(element); + guard.initialized = idx + val.is_some() as usize; + + // SAFETY: Loop conditions ensure the index is in bounds. + + unsafe { + let opt_payload_at: *const MaybeUninit = + (&raw const val).byte_add(core::mem::offset_of!(Option, Some.0)).cast(); + let dst = guard.array.as_mut_ptr().add(idx); + crate::ptr::copy_nonoverlapping(opt_payload_at, dst, 1); + crate::mem::forget(val); + }; + + if guard.initialized < N { ControlFlow::Continue(()) } else { ControlFlow::Break(()) } + }); + + let guard = ManuallyDrop::new(guard); + + match result { + ControlFlow::Break(()) => { + // SAFETY: The loop above is only explicitly broken when the array has been fully initialized + Ok(unsafe { MaybeUninit::array_assume_init(array) }) + } + ControlFlow::Continue(()) => { + let initialized = guard.initialized; + // SAFETY: The range is in bounds since the loop breaks when reaching N elements. + Err(unsafe { array::IntoIter::new_unchecked(array, 0..initialized) }) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.iter.try_fold(init, filter_map_try_fold(&mut self.f, fold)) + } + + #[inline] + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.fold(init, filter_map_fold(self.f, fold)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for FilterMap +where + F: FnMut(I::Item) -> Option, +{ + #[inline] + fn next_back(&mut self) -> Option { + #[inline] + fn find( + f: &mut impl FnMut(T) -> Option, + ) -> impl FnMut((), T) -> ControlFlow + '_ { + move |(), x| match f(x) { + Some(x) => ControlFlow::Break(x), + None => ControlFlow::Continue(()), + } + } + + self.iter.try_rfold((), find(&mut self.f)).break_value() + } + + #[inline] + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.iter.try_rfold(init, filter_map_try_fold(&mut self.f, fold)) + } + + #[inline] + fn rfold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.rfold(init, filter_map_fold(self.f, fold)) + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for FilterMap where F: FnMut(I::Item) -> Option {} + +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for FilterMap {} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for FilterMap +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for FilterMap { + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = I::MERGE_BY; +} diff --git a/CoqOfRust/core/iter/adapters/flatten.rs b/CoqOfRust/core/iter/adapters/flatten.rs new file mode 100644 index 000000000..0023b4603 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/flatten.rs @@ -0,0 +1,1038 @@ +use crate::iter::adapters::SourceIter; +use crate::iter::{ + Cloned, Copied, Empty, Filter, FilterMap, Fuse, FusedIterator, InPlaceIterable, Map, Once, + OnceWith, TrustedFused, TrustedLen, +}; +use crate::num::NonZero; +use crate::ops::{ControlFlow, Try}; +use crate::{array, fmt, option, result}; + +/// An iterator that maps each element to an iterator, and yields the elements +/// of the produced iterators. +/// +/// This `struct` is created by [`Iterator::flat_map`]. See its documentation +/// for more. +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct FlatMap { + inner: FlattenCompat, ::IntoIter>, +} + +impl U> FlatMap { + pub(in crate::iter) fn new(iter: I, f: F) -> FlatMap { + FlatMap { inner: FlattenCompat::new(iter.map(f)) } + } + + pub(crate) fn into_parts(self) -> (Option, Option, Option) { + ( + self.inner.frontiter, + self.inner.iter.into_inner().map(Map::into_inner), + self.inner.backiter, + ) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for FlatMap +where + U: Clone + IntoIterator, +{ + fn clone(&self) -> Self { + FlatMap { inner: self.inner.clone() } + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for FlatMap +where + U: IntoIterator, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FlatMap").field("inner", &self.inner).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for FlatMap +where + F: FnMut(I::Item) -> U, +{ + type Item = U::Item; + + #[inline] + fn next(&mut self) -> Option { + self.inner.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.inner.try_fold(init, fold) + } + + #[inline] + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.inner.fold(init, fold) + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.inner.advance_by(n) + } + + #[inline] + fn count(self) -> usize { + self.inner.count() + } + + #[inline] + fn last(self) -> Option { + self.inner.last() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for FlatMap +where + F: FnMut(I::Item) -> U, + U: IntoIterator, +{ + #[inline] + fn next_back(&mut self) -> Option { + self.inner.next_back() + } + + #[inline] + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.inner.try_rfold(init, fold) + } + + #[inline] + fn rfold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.inner.rfold(init, fold) + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.inner.advance_back_by(n) + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for FlatMap +where + I: FusedIterator, + U: IntoIterator, + F: FnMut(I::Item) -> U, +{ +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for FlatMap +where + I: Iterator, + U: IntoIterator, + F: FnMut(I::Item) -> U, + FlattenCompat, ::IntoIter>: TrustedLen, +{ +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for FlatMap +where + I: InPlaceIterable, + U: BoundedSize + IntoIterator, +{ + const EXPAND_BY: Option> = const { + match (I::EXPAND_BY, U::UPPER_BOUND) { + (Some(m), Some(n)) => m.checked_mul(n), + _ => None, + } + }; + const MERGE_BY: Option> = I::MERGE_BY; +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for FlatMap +where + I: SourceIter + TrustedFused, + U: IntoIterator, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.inner.iter) } + } +} + +/// Marker trait for iterators/iterables which have a statically known upper +/// bound of the number of items they can produce. +/// +/// # Safety +/// +/// Implementations must not yield more elements than indicated by UPPER_BOUND if it is `Some`. +/// Used in specializations. Implementations must not be conditional on lifetimes or +/// user-implementable traits. +#[rustc_specialization_trait] +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe trait BoundedSize { + const UPPER_BOUND: Option> = NonZero::new(1); +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for Option {} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for option::IntoIter {} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for Result {} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for result::IntoIter {} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for Once {} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for OnceWith {} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for [T; N] { + const UPPER_BOUND: Option> = NonZero::new(N); +} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for array::IntoIter { + const UPPER_BOUND: Option> = NonZero::new(N); +} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for Filter { + const UPPER_BOUND: Option> = I::UPPER_BOUND; +} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for FilterMap { + const UPPER_BOUND: Option> = I::UPPER_BOUND; +} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for Map { + const UPPER_BOUND: Option> = I::UPPER_BOUND; +} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for Copied { + const UPPER_BOUND: Option> = I::UPPER_BOUND; +} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for Cloned { + const UPPER_BOUND: Option> = I::UPPER_BOUND; +} + +/// An iterator that flattens one level of nesting in an iterator of things +/// that can be turned into iterators. +/// +/// This `struct` is created by the [`flatten`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`flatten`]: Iterator::flatten() +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "iterator_flatten", since = "1.29.0")] +pub struct Flatten> { + inner: FlattenCompat::IntoIter>, +} + +impl> Flatten { + pub(in super::super) fn new(iter: I) -> Flatten { + Flatten { inner: FlattenCompat::new(iter) } + } +} + +#[stable(feature = "iterator_flatten", since = "1.29.0")] +impl fmt::Debug for Flatten +where + I: fmt::Debug + Iterator>, + U: fmt::Debug + Iterator, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Flatten").field("inner", &self.inner).finish() + } +} + +#[stable(feature = "iterator_flatten", since = "1.29.0")] +impl Clone for Flatten +where + I: Clone + Iterator>, + U: Clone + Iterator, +{ + fn clone(&self) -> Self { + Flatten { inner: self.inner.clone() } + } +} + +#[stable(feature = "iterator_flatten", since = "1.29.0")] +impl Iterator for Flatten +where + I: Iterator>, + U: Iterator, +{ + type Item = U::Item; + + #[inline] + fn next(&mut self) -> Option { + self.inner.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.inner.try_fold(init, fold) + } + + #[inline] + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.inner.fold(init, fold) + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.inner.advance_by(n) + } + + #[inline] + fn count(self) -> usize { + self.inner.count() + } + + #[inline] + fn last(self) -> Option { + self.inner.last() + } +} + +#[stable(feature = "iterator_flatten", since = "1.29.0")] +impl DoubleEndedIterator for Flatten +where + I: DoubleEndedIterator>, + U: DoubleEndedIterator, +{ + #[inline] + fn next_back(&mut self) -> Option { + self.inner.next_back() + } + + #[inline] + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.inner.try_rfold(init, fold) + } + + #[inline] + fn rfold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.inner.rfold(init, fold) + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.inner.advance_back_by(n) + } +} + +#[stable(feature = "iterator_flatten", since = "1.29.0")] +impl FusedIterator for Flatten +where + I: FusedIterator>, + U: Iterator, +{ +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Flatten +where + I: Iterator, + FlattenCompat::IntoIter>: TrustedLen, +{ +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for Flatten +where + I: InPlaceIterable + Iterator, + ::Item: IntoIterator + BoundedSize, +{ + const EXPAND_BY: Option> = const { + match (I::EXPAND_BY, I::Item::UPPER_BOUND) { + (Some(m), Some(n)) => m.checked_mul(n), + _ => None, + } + }; + const MERGE_BY: Option> = I::MERGE_BY; +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Flatten +where + I: SourceIter + TrustedFused + Iterator, + ::Item: IntoIterator, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.inner.iter) } + } +} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for Flatten +where + I: Default + Iterator, +{ + /// Creates a `Flatten` iterator from the default value of `I`. + /// + /// ``` + /// # use core::slice; + /// # use std::iter::Flatten; + /// let iter: Flatten> = Default::default(); + /// assert_eq!(iter.count(), 0); + /// ``` + fn default() -> Self { + Flatten::new(Default::default()) + } +} + +/// Real logic of both `Flatten` and `FlatMap` which simply delegate to +/// this type. +#[derive(Clone, Debug)] +#[unstable(feature = "trusted_len", issue = "37572")] +struct FlattenCompat { + iter: Fuse, + frontiter: Option, + backiter: Option, +} +impl FlattenCompat +where + I: Iterator, +{ + /// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`. + fn new(iter: I) -> FlattenCompat { + FlattenCompat { iter: iter.fuse(), frontiter: None, backiter: None } + } +} + +impl FlattenCompat +where + I: Iterator>, +{ + /// Folds the inner iterators into an accumulator by applying an operation. + /// + /// Folds over the inner iterators, not over their elements. Is used by the `fold`, `count`, + /// and `last` methods. + #[inline] + fn iter_fold(self, mut acc: Acc, mut fold: Fold) -> Acc + where + Fold: FnMut(Acc, U) -> Acc, + { + #[inline] + fn flatten( + fold: &mut impl FnMut(Acc, T::IntoIter) -> Acc, + ) -> impl FnMut(Acc, T) -> Acc + '_ { + move |acc, iter| fold(acc, iter.into_iter()) + } + + if let Some(iter) = self.frontiter { + acc = fold(acc, iter); + } + + acc = self.iter.fold(acc, flatten(&mut fold)); + + if let Some(iter) = self.backiter { + acc = fold(acc, iter); + } + + acc + } + + /// Folds over the inner iterators as long as the given function returns successfully, + /// always storing the most recent inner iterator in `self.frontiter`. + /// + /// Folds over the inner iterators, not over their elements. Is used by the `try_fold` and + /// `advance_by` methods. + #[inline] + fn iter_try_fold(&mut self, mut acc: Acc, mut fold: Fold) -> R + where + Fold: FnMut(Acc, &mut U) -> R, + R: Try, + { + #[inline] + fn flatten<'a, T: IntoIterator, Acc, R: Try>( + frontiter: &'a mut Option, + fold: &'a mut impl FnMut(Acc, &mut T::IntoIter) -> R, + ) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, iter| fold(acc, frontiter.insert(iter.into_iter())) + } + + if let Some(iter) = &mut self.frontiter { + acc = fold(acc, iter)?; + } + self.frontiter = None; + + acc = self.iter.try_fold(acc, flatten(&mut self.frontiter, &mut fold))?; + self.frontiter = None; + + if let Some(iter) = &mut self.backiter { + acc = fold(acc, iter)?; + } + self.backiter = None; + + try { acc } + } +} + +impl FlattenCompat +where + I: DoubleEndedIterator>, +{ + /// Folds the inner iterators into an accumulator by applying an operation, starting form the + /// back. + /// + /// Folds over the inner iterators, not over their elements. Is used by the `rfold` method. + #[inline] + fn iter_rfold(self, mut acc: Acc, mut fold: Fold) -> Acc + where + Fold: FnMut(Acc, U) -> Acc, + { + #[inline] + fn flatten( + fold: &mut impl FnMut(Acc, T::IntoIter) -> Acc, + ) -> impl FnMut(Acc, T) -> Acc + '_ { + move |acc, iter| fold(acc, iter.into_iter()) + } + + if let Some(iter) = self.backiter { + acc = fold(acc, iter); + } + + acc = self.iter.rfold(acc, flatten(&mut fold)); + + if let Some(iter) = self.frontiter { + acc = fold(acc, iter); + } + + acc + } + + /// Folds over the inner iterators in reverse order as long as the given function returns + /// successfully, always storing the most recent inner iterator in `self.backiter`. + /// + /// Folds over the inner iterators, not over their elements. Is used by the `try_rfold` and + /// `advance_back_by` methods. + #[inline] + fn iter_try_rfold(&mut self, mut acc: Acc, mut fold: Fold) -> R + where + Fold: FnMut(Acc, &mut U) -> R, + R: Try, + { + #[inline] + fn flatten<'a, T: IntoIterator, Acc, R: Try>( + backiter: &'a mut Option, + fold: &'a mut impl FnMut(Acc, &mut T::IntoIter) -> R, + ) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, iter| fold(acc, backiter.insert(iter.into_iter())) + } + + if let Some(iter) = &mut self.backiter { + acc = fold(acc, iter)?; + } + self.backiter = None; + + acc = self.iter.try_rfold(acc, flatten(&mut self.backiter, &mut fold))?; + self.backiter = None; + + if let Some(iter) = &mut self.frontiter { + acc = fold(acc, iter)?; + } + self.frontiter = None; + + try { acc } + } +} + +// See also the `OneShot` specialization below. +impl Iterator for FlattenCompat +where + I: Iterator>, + U: Iterator, +{ + type Item = U::Item; + + #[inline] + default fn next(&mut self) -> Option { + loop { + if let elt @ Some(_) = and_then_or_clear(&mut self.frontiter, Iterator::next) { + return elt; + } + match self.iter.next() { + None => return and_then_or_clear(&mut self.backiter, Iterator::next), + Some(inner) => self.frontiter = Some(inner.into_iter()), + } + } + } + + #[inline] + default fn size_hint(&self) -> (usize, Option) { + let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint); + let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint); + let lo = flo.saturating_add(blo); + + if let Some(fixed_size) = <::Item as ConstSizeIntoIterator>::size() { + let (lower, upper) = self.iter.size_hint(); + + let lower = lower.saturating_mul(fixed_size).saturating_add(lo); + let upper = + try { fhi?.checked_add(bhi?)?.checked_add(fixed_size.checked_mul(upper?)?)? }; + + return (lower, upper); + } + + match (self.iter.size_hint(), fhi, bhi) { + ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)), + _ => (lo, None), + } + } + + #[inline] + default fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + #[inline] + fn flatten>( + mut fold: impl FnMut(Acc, U::Item) -> R, + ) -> impl FnMut(Acc, &mut U) -> R { + move |acc, iter| iter.try_fold(acc, &mut fold) + } + + self.iter_try_fold(init, flatten(fold)) + } + + #[inline] + default fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + #[inline] + fn flatten( + mut fold: impl FnMut(Acc, U::Item) -> Acc, + ) -> impl FnMut(Acc, U) -> Acc { + move |acc, iter| iter.fold(acc, &mut fold) + } + + self.iter_fold(init, flatten(fold)) + } + + #[inline] + #[rustc_inherit_overflow_checks] + default fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + #[inline] + #[rustc_inherit_overflow_checks] + fn advance(n: usize, iter: &mut U) -> ControlFlow<(), usize> { + match iter.advance_by(n) { + Ok(()) => ControlFlow::Break(()), + Err(remaining) => ControlFlow::Continue(remaining.get()), + } + } + + match self.iter_try_fold(n, advance) { + ControlFlow::Continue(remaining) => NonZero::new(remaining).map_or(Ok(()), Err), + _ => Ok(()), + } + } + + #[inline] + default fn count(self) -> usize { + #[inline] + #[rustc_inherit_overflow_checks] + fn count(acc: usize, iter: U) -> usize { + acc + iter.count() + } + + self.iter_fold(0, count) + } + + #[inline] + default fn last(self) -> Option { + #[inline] + fn last(last: Option, iter: U) -> Option { + iter.last().or(last) + } + + self.iter_fold(None, last) + } +} + +// See also the `OneShot` specialization below. +impl DoubleEndedIterator for FlattenCompat +where + I: DoubleEndedIterator>, + U: DoubleEndedIterator, +{ + #[inline] + default fn next_back(&mut self) -> Option { + loop { + if let elt @ Some(_) = and_then_or_clear(&mut self.backiter, |b| b.next_back()) { + return elt; + } + match self.iter.next_back() { + None => return and_then_or_clear(&mut self.frontiter, |f| f.next_back()), + Some(inner) => self.backiter = Some(inner.into_iter()), + } + } + } + + #[inline] + default fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + #[inline] + fn flatten>( + mut fold: impl FnMut(Acc, U::Item) -> R, + ) -> impl FnMut(Acc, &mut U) -> R { + move |acc, iter| iter.try_rfold(acc, &mut fold) + } + + self.iter_try_rfold(init, flatten(fold)) + } + + #[inline] + default fn rfold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + #[inline] + fn flatten( + mut fold: impl FnMut(Acc, U::Item) -> Acc, + ) -> impl FnMut(Acc, U) -> Acc { + move |acc, iter| iter.rfold(acc, &mut fold) + } + + self.iter_rfold(init, flatten(fold)) + } + + #[inline] + #[rustc_inherit_overflow_checks] + default fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + #[inline] + #[rustc_inherit_overflow_checks] + fn advance(n: usize, iter: &mut U) -> ControlFlow<(), usize> { + match iter.advance_back_by(n) { + Ok(()) => ControlFlow::Break(()), + Err(remaining) => ControlFlow::Continue(remaining.get()), + } + } + + match self.iter_try_rfold(n, advance) { + ControlFlow::Continue(remaining) => NonZero::new(remaining).map_or(Ok(()), Err), + _ => Ok(()), + } + } +} + +unsafe impl TrustedLen + for FlattenCompat::IntoIter> +where + I: TrustedLen, +{ +} + +unsafe impl<'a, const N: usize, I, T> TrustedLen + for FlattenCompat::IntoIter> +where + I: TrustedLen, +{ +} + +unsafe impl<'a, const N: usize, I, T> TrustedLen + for FlattenCompat::IntoIter> +where + I: TrustedLen, +{ +} + +trait ConstSizeIntoIterator: IntoIterator { + // FIXME(#31844): convert to an associated const once specialization supports that + fn size() -> Option; +} + +impl ConstSizeIntoIterator for T +where + T: IntoIterator, +{ + #[inline] + default fn size() -> Option { + None + } +} + +impl ConstSizeIntoIterator for [T; N] { + #[inline] + fn size() -> Option { + Some(N) + } +} + +impl ConstSizeIntoIterator for &[T; N] { + #[inline] + fn size() -> Option { + Some(N) + } +} + +impl ConstSizeIntoIterator for &mut [T; N] { + #[inline] + fn size() -> Option { + Some(N) + } +} + +#[inline] +fn and_then_or_clear(opt: &mut Option, f: impl FnOnce(&mut T) -> Option) -> Option { + let x = f(opt.as_mut()?); + if x.is_none() { + *opt = None; + } + x +} + +/// Specialization trait for iterator types that never return more than one item. +/// +/// Note that we still have to deal with the possibility that the iterator was +/// already exhausted before it came into our control. +#[rustc_specialization_trait] +trait OneShot {} + +// These all have exactly one item, if not already consumed. +impl OneShot for Once {} +impl OneShot for OnceWith {} +impl OneShot for array::IntoIter {} +impl OneShot for option::IntoIter {} +impl OneShot for option::Iter<'_, T> {} +impl OneShot for option::IterMut<'_, T> {} +impl OneShot for result::IntoIter {} +impl OneShot for result::Iter<'_, T> {} +impl OneShot for result::IterMut<'_, T> {} + +// These are always empty, which is fine to optimize too. +impl OneShot for Empty {} +impl OneShot for array::IntoIter {} + +// These adaptors never increase the number of items. +// (There are more possible, but for now this matches BoundedSize above.) +impl OneShot for Cloned {} +impl OneShot for Copied {} +impl OneShot for Filter {} +impl OneShot for FilterMap {} +impl OneShot for Map {} + +// Blanket impls pass this property through as well +// (but we can't do `Box` unless we expose this trait to alloc) +impl OneShot for &mut I {} + +#[inline] +fn into_item(inner: I) -> Option +where + I: IntoIterator, +{ + inner.into_iter().next() +} + +#[inline] +fn flatten_one, Acc>( + mut fold: impl FnMut(Acc, I::Item) -> Acc, +) -> impl FnMut(Acc, I) -> Acc { + move |acc, inner| match inner.into_iter().next() { + Some(item) => fold(acc, item), + None => acc, + } +} + +#[inline] +fn try_flatten_one, Acc, R: Try>( + mut fold: impl FnMut(Acc, I::Item) -> R, +) -> impl FnMut(Acc, I) -> R { + move |acc, inner| match inner.into_iter().next() { + Some(item) => fold(acc, item), + None => try { acc }, + } +} + +#[inline] +fn advance_by_one(n: NonZero, inner: I) -> Option> +where + I: IntoIterator, +{ + match inner.into_iter().next() { + Some(_) => NonZero::new(n.get() - 1), + None => Some(n), + } +} + +// Specialization: When the inner iterator `U` never returns more than one item, the `frontiter` and +// `backiter` states are a waste, because they'll always have already consumed their item. So in +// this impl, we completely ignore them and just focus on `self.iter`, and we only call the inner +// `U::next()` one time. +// +// It's mostly fine if we accidentally mix this with the more generic impls, e.g. by forgetting to +// specialize one of the methods. If the other impl did set the front or back, we wouldn't see it +// here, but it would be empty anyway; and if the other impl looked for a front or back that we +// didn't bother setting, it would just see `None` (or a previous empty) and move on. +// +// An exception to that is `advance_by(0)` and `advance_back_by(0)`, where the generic impls may set +// `frontiter` or `backiter` without consuming the item, so we **must** override those. +impl Iterator for FlattenCompat +where + I: Iterator>, + U: Iterator + OneShot, +{ + #[inline] + fn next(&mut self) -> Option { + while let Some(inner) = self.iter.next() { + if let item @ Some(_) = inner.into_iter().next() { + return item; + } + } + None + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (lower, upper) = self.iter.size_hint(); + match ::size() { + Some(0) => (0, Some(0)), + Some(1) => (lower, upper), + _ => (0, upper), + } + } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.iter.try_fold(init, try_flatten_one(fold)) + } + + #[inline] + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.fold(init, flatten_one(fold)) + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + if let Some(n) = NonZero::new(n) { + self.iter.try_fold(n, advance_by_one).map_or(Ok(()), Err) + } else { + // Just advance the outer iterator + self.iter.advance_by(0) + } + } + + #[inline] + fn count(self) -> usize { + self.iter.filter_map(into_item).count() + } + + #[inline] + fn last(self) -> Option { + self.iter.filter_map(into_item).last() + } +} + +// Note: We don't actually care about `U: DoubleEndedIterator`, since forward and backward are the +// same for a one-shot iterator, but we have to keep that to match the default specialization. +impl DoubleEndedIterator for FlattenCompat +where + I: DoubleEndedIterator>, + U: DoubleEndedIterator + OneShot, +{ + #[inline] + fn next_back(&mut self) -> Option { + while let Some(inner) = self.iter.next_back() { + if let item @ Some(_) = inner.into_iter().next() { + return item; + } + } + None + } + + #[inline] + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.iter.try_rfold(init, try_flatten_one(fold)) + } + + #[inline] + fn rfold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.rfold(init, flatten_one(fold)) + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + if let Some(n) = NonZero::new(n) { + self.iter.try_rfold(n, advance_by_one).map_or(Ok(()), Err) + } else { + // Just advance the outer iterator + self.iter.advance_back_by(0) + } + } +} diff --git a/CoqOfRust/core/iter/adapters/fuse.rs b/CoqOfRust/core/iter/adapters/fuse.rs new file mode 100644 index 000000000..e9765f911 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/fuse.rs @@ -0,0 +1,452 @@ +use crate::intrinsics; +use crate::iter::adapters::SourceIter; +use crate::iter::adapters::zip::try_get_unchecked; +use crate::iter::{ + FusedIterator, TrustedFused, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, +}; +use crate::ops::Try; + +/// An iterator that yields `None` forever after the underlying iterator +/// yields `None` once. +/// +/// This `struct` is created by [`Iterator::fuse`]. See its documentation +/// for more. +#[derive(Clone, Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Fuse { + // NOTE: for `I: FusedIterator`, we never bother setting `None`, but + // we still have to be prepared for that state due to variance. + // See rust-lang/rust#85863 + iter: Option, +} +impl Fuse { + pub(in crate::iter) fn new(iter: I) -> Fuse { + Fuse { iter: Some(iter) } + } + + pub(crate) fn into_inner(self) -> Option { + self.iter + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Fuse where I: Iterator {} + +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Fuse where I: TrustedFused {} + +// Any specialized implementation here is made internal +// to avoid exposing default fns outside this trait. +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Fuse +where + I: Iterator, +{ + type Item = ::Item; + + #[inline] + fn next(&mut self) -> Option { + FuseImpl::next(self) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + FuseImpl::nth(self, n) + } + + #[inline] + fn last(self) -> Option { + match self.iter { + Some(iter) => iter.last(), + None => None, + } + } + + #[inline] + fn count(self) -> usize { + match self.iter { + Some(iter) => iter.count(), + None => 0, + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + match self.iter { + Some(ref iter) => iter.size_hint(), + None => (0, Some(0)), + } + } + + #[inline] + fn try_fold(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + FuseImpl::try_fold(self, acc, fold) + } + + #[inline] + fn fold(self, mut acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + if let Some(iter) = self.iter { + acc = iter.fold(acc, fold); + } + acc + } + + #[inline] + fn find

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + FuseImpl::find(self, predicate) + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccessNoCoerce, + { + match self.iter { + // SAFETY: the caller must uphold the contract for + // `Iterator::__iterator_get_unchecked`. + Some(ref mut iter) => unsafe { try_get_unchecked(iter, idx) }, + // SAFETY: the caller asserts there is an item at `i`, so we're not exhausted. + None => unsafe { intrinsics::unreachable() }, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Fuse +where + I: DoubleEndedIterator, +{ + #[inline] + fn next_back(&mut self) -> Option<::Item> { + FuseImpl::next_back(self) + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option<::Item> { + FuseImpl::nth_back(self, n) + } + + #[inline] + fn try_rfold(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + FuseImpl::try_rfold(self, acc, fold) + } + + #[inline] + fn rfold(self, mut acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + if let Some(iter) = self.iter { + acc = iter.rfold(acc, fold); + } + acc + } + + #[inline] + fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + FuseImpl::rfind(self, predicate) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Fuse +where + I: ExactSizeIterator, +{ + fn len(&self) -> usize { + match self.iter { + Some(ref iter) => iter.len(), + None => 0, + } + } + + fn is_empty(&self) -> bool { + match self.iter { + Some(ref iter) => iter.is_empty(), + None => true, + } + } +} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for Fuse { + /// Creates a `Fuse` iterator from the default value of `I`. + /// + /// ``` + /// # use core::slice; + /// # use std::iter::Fuse; + /// let iter: Fuse> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Fuse { iter: Default::default() } + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +// SAFETY: `TrustedLen` requires that an accurate length is reported via `size_hint()`. As `Fuse` +// is just forwarding this to the wrapped iterator `I` this property is preserved and it is safe to +// implement `TrustedLen` here. +unsafe impl TrustedLen for Fuse where I: TrustedLen {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +// SAFETY: `TrustedRandomAccess` requires that `size_hint()` must be exact and cheap to call, and +// `Iterator::__iterator_get_unchecked()` must be implemented accordingly. +// +// This is safe to implement as `Fuse` is just forwarding these to the wrapped iterator `I`, which +// preserves these properties. +unsafe impl TrustedRandomAccess for Fuse where I: TrustedRandomAccess {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccessNoCoerce for Fuse +where + I: TrustedRandomAccessNoCoerce, +{ + const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT; +} + +/// Fuse specialization trait +/// +/// We only need to worry about `&mut self` methods, which +/// may exhaust the iterator without consuming it. +#[doc(hidden)] +trait FuseImpl { + type Item; + + // Functions specific to any normal Iterators + fn next(&mut self) -> Option; + fn nth(&mut self, n: usize) -> Option; + fn try_fold(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try; + fn find

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool; + + // Functions specific to DoubleEndedIterators + fn next_back(&mut self) -> Option + where + I: DoubleEndedIterator; + fn nth_back(&mut self, n: usize) -> Option + where + I: DoubleEndedIterator; + fn try_rfold(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + I: DoubleEndedIterator; + fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + I: DoubleEndedIterator; +} + +/// General `Fuse` impl which sets `iter = None` when exhausted. +#[doc(hidden)] +impl FuseImpl for Fuse +where + I: Iterator, +{ + type Item = ::Item; + + #[inline] + default fn next(&mut self) -> Option<::Item> { + and_then_or_clear(&mut self.iter, Iterator::next) + } + + #[inline] + default fn nth(&mut self, n: usize) -> Option { + and_then_or_clear(&mut self.iter, |iter| iter.nth(n)) + } + + #[inline] + default fn try_fold(&mut self, mut acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + if let Some(ref mut iter) = self.iter { + acc = iter.try_fold(acc, fold)?; + self.iter = None; + } + try { acc } + } + + #[inline] + default fn find

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + and_then_or_clear(&mut self.iter, |iter| iter.find(predicate)) + } + + #[inline] + default fn next_back(&mut self) -> Option<::Item> + where + I: DoubleEndedIterator, + { + and_then_or_clear(&mut self.iter, |iter| iter.next_back()) + } + + #[inline] + default fn nth_back(&mut self, n: usize) -> Option<::Item> + where + I: DoubleEndedIterator, + { + and_then_or_clear(&mut self.iter, |iter| iter.nth_back(n)) + } + + #[inline] + default fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + I: DoubleEndedIterator, + { + if let Some(ref mut iter) = self.iter { + acc = iter.try_rfold(acc, fold)?; + self.iter = None; + } + try { acc } + } + + #[inline] + default fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + I: DoubleEndedIterator, + { + and_then_or_clear(&mut self.iter, |iter| iter.rfind(predicate)) + } +} + +/// Specialized `Fuse` impl which doesn't bother clearing `iter` when exhausted. +/// However, we must still be prepared for the possibility that it was already cleared! +#[doc(hidden)] +impl FuseImpl for Fuse +where + I: FusedIterator, +{ + #[inline] + fn next(&mut self) -> Option<::Item> { + self.iter.as_mut()?.next() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.iter.as_mut()?.nth(n) + } + + #[inline] + fn try_fold(&mut self, mut acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + if let Some(ref mut iter) = self.iter { + acc = iter.try_fold(acc, fold)?; + } + try { acc } + } + + #[inline] + fn find

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + self.iter.as_mut()?.find(predicate) + } + + #[inline] + fn next_back(&mut self) -> Option<::Item> + where + I: DoubleEndedIterator, + { + self.iter.as_mut()?.next_back() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option<::Item> + where + I: DoubleEndedIterator, + { + self.iter.as_mut()?.nth_back(n) + } + + #[inline] + fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + I: DoubleEndedIterator, + { + if let Some(ref mut iter) = self.iter { + acc = iter.try_rfold(acc, fold)?; + } + try { acc } + } + + #[inline] + fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + I: DoubleEndedIterator, + { + self.iter.as_mut()?.rfind(predicate) + } +} + +// This is used by Flatten's SourceIter impl +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Fuse +where + I: SourceIter + TrustedFused, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements. + // TrustedFused guarantees that we'll never encounter a case where `self.iter` would + // be set to None. + unsafe { SourceIter::as_inner(self.iter.as_mut().unwrap_unchecked()) } + } +} + +#[inline] +fn and_then_or_clear(opt: &mut Option, f: impl FnOnce(&mut T) -> Option) -> Option { + let x = f(opt.as_mut()?); + if x.is_none() { + *opt = None; + } + x +} diff --git a/CoqOfRust/core/iter/adapters/inspect.rs b/CoqOfRust/core/iter/adapters/inspect.rs new file mode 100644 index 000000000..0e2a68a50 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/inspect.rs @@ -0,0 +1,174 @@ +use crate::fmt; +use crate::iter::adapters::SourceIter; +use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused}; +use crate::num::NonZero; +use crate::ops::Try; + +/// An iterator that calls a function with a reference to each element before +/// yielding it. +/// +/// This `struct` is created by the [`inspect`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`inspect`]: Iterator::inspect +/// [`Iterator`]: trait.Iterator.html +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] +pub struct Inspect { + iter: I, + f: F, +} +impl Inspect { + pub(in crate::iter) fn new(iter: I, f: F) -> Inspect { + Inspect { iter, f } + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for Inspect { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Inspect").field("iter", &self.iter).finish() + } +} + +impl Inspect +where + F: FnMut(&I::Item), +{ + #[inline] + fn do_inspect(&mut self, elt: Option) -> Option { + if let Some(ref a) = elt { + (self.f)(a); + } + + elt + } +} + +fn inspect_fold( + mut f: impl FnMut(&T), + mut fold: impl FnMut(Acc, T) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| { + f(&item); + fold(acc, item) + } +} + +fn inspect_try_fold<'a, T, Acc, R>( + f: &'a mut impl FnMut(&T), + mut fold: impl FnMut(Acc, T) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| { + f(&item); + fold(acc, item) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Inspect +where + F: FnMut(&I::Item), +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + let next = self.iter.next(); + self.do_inspect(next) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.iter.try_fold(init, inspect_try_fold(&mut self.f, fold)) + } + + #[inline] + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.fold(init, inspect_fold(self.f, fold)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Inspect +where + F: FnMut(&I::Item), +{ + #[inline] + fn next_back(&mut self) -> Option { + let next = self.iter.next_back(); + self.do_inspect(next) + } + + #[inline] + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.iter.try_rfold(init, inspect_try_fold(&mut self.f, fold)) + } + + #[inline] + fn rfold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.rfold(init, inspect_fold(self.f, fold)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Inspect +where + F: FnMut(&I::Item), +{ + fn len(&self) -> usize { + self.iter.len() + } + + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Inspect where F: FnMut(&I::Item) {} + +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Inspect {} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Inspect +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for Inspect { + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = I::MERGE_BY; +} diff --git a/CoqOfRust/core/iter/adapters/intersperse.rs b/CoqOfRust/core/iter/adapters/intersperse.rs new file mode 100644 index 000000000..c97a59b61 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/intersperse.rs @@ -0,0 +1,236 @@ +use crate::fmt; +use crate::iter::{Fuse, FusedIterator}; + +/// An iterator adapter that places a separator between all elements. +/// +/// This `struct` is created by [`Iterator::intersperse`]. See its documentation +/// for more information. +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +#[derive(Debug, Clone)] +pub struct Intersperse +where + I::Item: Clone, +{ + started: bool, + separator: I::Item, + next_item: Option, + iter: Fuse, +} + +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +impl FusedIterator for Intersperse +where + I: FusedIterator, + I::Item: Clone, +{ +} + +impl Intersperse +where + I::Item: Clone, +{ + pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self { + Self { started: false, separator, next_item: None, iter: iter.fuse() } + } +} + +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +impl Iterator for Intersperse +where + I: Iterator, + I::Item: Clone, +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + if self.started { + if let Some(v) = self.next_item.take() { + Some(v) + } else { + let next_item = self.iter.next(); + if next_item.is_some() { + self.next_item = next_item; + Some(self.separator.clone()) + } else { + None + } + } + } else { + self.started = true; + self.iter.next() + } + } + + fn size_hint(&self) -> (usize, Option) { + intersperse_size_hint(&self.iter, self.started, self.next_item.is_some()) + } + + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + let separator = self.separator; + intersperse_fold( + self.iter, + init, + f, + move || separator.clone(), + self.started, + self.next_item, + ) + } +} + +/// An iterator adapter that places a separator between all elements. +/// +/// This `struct` is created by [`Iterator::intersperse_with`]. See its +/// documentation for more information. +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +pub struct IntersperseWith +where + I: Iterator, +{ + started: bool, + separator: G, + next_item: Option, + iter: Fuse, +} + +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +impl FusedIterator for IntersperseWith +where + I: FusedIterator, + G: FnMut() -> I::Item, +{ +} + +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +impl fmt::Debug for IntersperseWith +where + I: Iterator + fmt::Debug, + I::Item: fmt::Debug, + G: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("IntersperseWith") + .field("started", &self.started) + .field("separator", &self.separator) + .field("iter", &self.iter) + .field("next_item", &self.next_item) + .finish() + } +} + +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +impl Clone for IntersperseWith +where + I: Iterator + Clone, + I::Item: Clone, + G: Clone, +{ + fn clone(&self) -> Self { + Self { + started: self.started, + separator: self.separator.clone(), + iter: self.iter.clone(), + next_item: self.next_item.clone(), + } + } +} + +impl IntersperseWith +where + I: Iterator, + G: FnMut() -> I::Item, +{ + pub(in crate::iter) fn new(iter: I, separator: G) -> Self { + Self { started: false, separator, next_item: None, iter: iter.fuse() } + } +} + +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +impl Iterator for IntersperseWith +where + I: Iterator, + G: FnMut() -> I::Item, +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + if self.started { + if let Some(v) = self.next_item.take() { + Some(v) + } else { + let next_item = self.iter.next(); + if next_item.is_some() { + self.next_item = next_item; + Some((self.separator)()) + } else { + None + } + } + } else { + self.started = true; + self.iter.next() + } + } + + fn size_hint(&self) -> (usize, Option) { + intersperse_size_hint(&self.iter, self.started, self.next_item.is_some()) + } + + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + intersperse_fold(self.iter, init, f, self.separator, self.started, self.next_item) + } +} + +fn intersperse_size_hint(iter: &I, started: bool, next_is_some: bool) -> (usize, Option) +where + I: Iterator, +{ + let (lo, hi) = iter.size_hint(); + ( + lo.saturating_sub(!started as usize) + .saturating_add(next_is_some as usize) + .saturating_add(lo), + hi.and_then(|hi| { + hi.saturating_sub(!started as usize) + .saturating_add(next_is_some as usize) + .checked_add(hi) + }), + ) +} + +fn intersperse_fold( + mut iter: I, + init: B, + mut f: F, + mut separator: G, + started: bool, + mut next_item: Option, +) -> B +where + I: Iterator, + F: FnMut(B, I::Item) -> B, + G: FnMut() -> I::Item, +{ + let mut accum = init; + + let first = if started { next_item.take() } else { iter.next() }; + if let Some(x) = first { + accum = f(accum, x); + } + + iter.fold(accum, |mut accum, x| { + accum = f(accum, separator()); + accum = f(accum, x); + accum + }) +} diff --git a/CoqOfRust/core/iter/adapters/map.rs b/CoqOfRust/core/iter/adapters/map.rs new file mode 100644 index 000000000..007c2d5ac --- /dev/null +++ b/CoqOfRust/core/iter/adapters/map.rs @@ -0,0 +1,241 @@ +use crate::fmt; +use crate::iter::adapters::zip::try_get_unchecked; +use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; +use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen, UncheckedIterator}; +use crate::num::NonZero; +use crate::ops::Try; + +/// An iterator that maps the values of `iter` with `f`. +/// +/// This `struct` is created by the [`map`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`map`]: Iterator::map +/// [`Iterator`]: trait.Iterator.html +/// +/// # Notes about side effects +/// +/// The [`map`] iterator implements [`DoubleEndedIterator`], meaning that +/// you can also [`map`] backwards: +/// +/// ```rust +/// let v: Vec = [1, 2, 3].into_iter().map(|x| x + 1).rev().collect(); +/// +/// assert_eq!(v, [4, 3, 2]); +/// ``` +/// +/// [`DoubleEndedIterator`]: trait.DoubleEndedIterator.html +/// +/// But if your closure has state, iterating backwards may act in a way you do +/// not expect. Let's go through an example. First, in the forward direction: +/// +/// ```rust +/// let mut c = 0; +/// +/// for pair in ['a', 'b', 'c'].into_iter() +/// .map(|letter| { c += 1; (letter, c) }) { +/// println!("{pair:?}"); +/// } +/// ``` +/// +/// This will print `('a', 1), ('b', 2), ('c', 3)`. +/// +/// Now consider this twist where we add a call to `rev`. This version will +/// print `('c', 1), ('b', 2), ('a', 3)`. Note that the letters are reversed, +/// but the values of the counter still go in order. This is because `map()` is +/// still being called lazily on each item, but we are popping items off the +/// back of the vector now, instead of shifting them from the front. +/// +/// ```rust +/// let mut c = 0; +/// +/// for pair in ['a', 'b', 'c'].into_iter() +/// .map(|letter| { c += 1; (letter, c) }) +/// .rev() { +/// println!("{pair:?}"); +/// } +/// ``` +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] +pub struct Map { + // Used for `SplitWhitespace` and `SplitAsciiWhitespace` `as_str` methods + pub(crate) iter: I, + f: F, +} + +impl Map { + pub(in crate::iter) fn new(iter: I, f: F) -> Map { + Map { iter, f } + } + + pub(crate) fn into_inner(self) -> I { + self.iter + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for Map { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Map").field("iter", &self.iter).finish() + } +} + +fn map_fold( + mut f: impl FnMut(T) -> B, + mut g: impl FnMut(Acc, B) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, elt| g(acc, f(elt)) +} + +fn map_try_fold<'a, T, B, Acc, R>( + f: &'a mut impl FnMut(T) -> B, + mut g: impl FnMut(Acc, B) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, elt| g(acc, f(elt)) +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Map +where + F: FnMut(I::Item) -> B, +{ + type Item = B; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().map(&mut self.f) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + fn try_fold(&mut self, init: Acc, g: G) -> R + where + Self: Sized, + G: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.iter.try_fold(init, map_try_fold(&mut self.f, g)) + } + + fn fold(self, init: Acc, g: G) -> Acc + where + G: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.fold(init, map_fold(self.f, g)) + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> B + where + Self: TrustedRandomAccessNoCoerce, + { + // SAFETY: the caller must uphold the contract for + // `Iterator::__iterator_get_unchecked`. + unsafe { (self.f)(try_get_unchecked(&mut self.iter, idx)) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Map +where + F: FnMut(I::Item) -> B, +{ + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back().map(&mut self.f) + } + + fn try_rfold(&mut self, init: Acc, g: G) -> R + where + Self: Sized, + G: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.iter.try_rfold(init, map_try_fold(&mut self.f, g)) + } + + fn rfold(self, init: Acc, g: G) -> Acc + where + G: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.rfold(init, map_fold(self.f, g)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Map +where + F: FnMut(I::Item) -> B, +{ + fn len(&self) -> usize { + self.iter.len() + } + + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Map where F: FnMut(I::Item) -> B {} + +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Map {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Map +where + I: TrustedLen, + F: FnMut(I::Item) -> B, +{ +} + +impl UncheckedIterator for Map +where + I: UncheckedIterator, + F: FnMut(I::Item) -> B, +{ + unsafe fn next_unchecked(&mut self) -> B { + // SAFETY: `Map` is 1:1 with the inner iterator, so if the caller promised + // that there's an element left, the inner iterator has one too. + let item = unsafe { self.iter.next_unchecked() }; + (self.f)(item) + } +} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for Map where I: TrustedRandomAccess {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccessNoCoerce for Map +where + I: TrustedRandomAccessNoCoerce, +{ + const MAY_HAVE_SIDE_EFFECT: bool = true; +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Map +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for Map { + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = I::MERGE_BY; +} diff --git a/CoqOfRust/core/iter/adapters/map_while.rs b/CoqOfRust/core/iter/adapters/map_while.rs new file mode 100644 index 000000000..c047c40de --- /dev/null +++ b/CoqOfRust/core/iter/adapters/map_while.rs @@ -0,0 +1,90 @@ +use crate::fmt; +use crate::iter::InPlaceIterable; +use crate::iter::adapters::SourceIter; +use crate::num::NonZero; +use crate::ops::{ControlFlow, Try}; + +/// An iterator that only accepts elements while `predicate` returns `Some(_)`. +/// +/// This `struct` is created by the [`map_while`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`map_while`]: Iterator::map_while +/// [`Iterator`]: trait.Iterator.html +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "iter_map_while", since = "1.57.0")] +#[derive(Clone)] +pub struct MapWhile { + iter: I, + predicate: P, +} + +impl MapWhile { + pub(in crate::iter) fn new(iter: I, predicate: P) -> MapWhile { + MapWhile { iter, predicate } + } +} + +#[stable(feature = "iter_map_while", since = "1.57.0")] +impl fmt::Debug for MapWhile { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MapWhile").field("iter", &self.iter).finish() + } +} + +#[stable(feature = "iter_map_while", since = "1.57.0")] +impl Iterator for MapWhile +where + P: FnMut(I::Item) -> Option, +{ + type Item = B; + + #[inline] + fn next(&mut self) -> Option { + let x = self.iter.next()?; + (self.predicate)(x) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } + + #[inline] + fn try_fold(&mut self, init: Acc, mut fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + let Self { iter, predicate } = self; + iter.try_fold(init, |acc, x| match predicate(x) { + Some(item) => ControlFlow::from_try(fold(acc, item)), + None => ControlFlow::Break(try { acc }), + }) + .into_try() + } + + impl_fold_via_try_fold! { fold -> try_fold } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for MapWhile +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for MapWhile { + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = I::MERGE_BY; +} diff --git a/CoqOfRust/core/iter/adapters/map_windows.rs b/CoqOfRust/core/iter/adapters/map_windows.rs new file mode 100644 index 000000000..cb13023c8 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/map_windows.rs @@ -0,0 +1,291 @@ +use crate::iter::FusedIterator; +use crate::mem::{self, MaybeUninit}; +use crate::{fmt, ptr}; + +/// An iterator over the mapped windows of another iterator. +/// +/// This `struct` is created by the [`Iterator::map_windows`]. See its +/// documentation for more information. +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[unstable(feature = "iter_map_windows", reason = "recently added", issue = "87155")] +pub struct MapWindows { + f: F, + inner: MapWindowsInner, +} + +struct MapWindowsInner { + // We fuse the inner iterator because there shouldn't be "holes" in + // the sliding window. Once the iterator returns a `None`, we make + // our `MapWindows` iterator return `None` forever. + iter: Option, + // Since iterators are assumed lazy, i.e. it only yields an item when + // `Iterator::next()` is called, and `MapWindows` is not an exception. + // + // Before the first iteration, we keep the buffer `None`. When the user + // first call `next` or other methods that makes the iterator advance, + // we collect the first `N` items yielded from the inner iterator and + // put it into the buffer. + // + // When the inner iterator has returned a `None` (i.e. fused), we take + // away this `buffer` and leave it `None` to reclaim its resources. + // + // FIXME: should we shrink the size of `buffer` using niche optimization? + buffer: Option>, +} + +// `Buffer` uses two times of space to reduce moves among the iterations. +// `Buffer` is semantically `[MaybeUninit; 2 * N]`. However, due +// to limitations of const generics, we use this different type. Note that +// it has the same underlying memory layout. +struct Buffer { + // Invariant: `self.buffer[self.start..self.start + N]` is initialized, + // with all other elements being uninitialized. This also + // implies that `self.start <= N`. + buffer: [[MaybeUninit; N]; 2], + start: usize, +} + +impl MapWindows { + pub(in crate::iter) fn new(iter: I, f: F) -> Self { + assert!(N != 0, "array in `Iterator::map_windows` must contain more than 0 elements"); + + // Only ZST arrays' length can be so large. + if mem::size_of::() == 0 { + assert!( + N.checked_mul(2).is_some(), + "array size of `Iterator::map_windows` is too large" + ); + } + + Self { inner: MapWindowsInner::new(iter), f } + } +} + +impl MapWindowsInner { + #[inline] + fn new(iter: I) -> Self { + Self { iter: Some(iter), buffer: None } + } + + fn next_window(&mut self) -> Option<&[I::Item; N]> { + let iter = self.iter.as_mut()?; + match self.buffer { + // It is the first time to advance. We collect + // the first `N` items from `self.iter` to initialize `self.buffer`. + None => self.buffer = Buffer::try_from_iter(iter), + Some(ref mut buffer) => match iter.next() { + None => { + // Fuse the inner iterator since it yields a `None`. + self.iter.take(); + self.buffer.take(); + } + // Advance the iterator. We first call `next` before changing our buffer + // at all. This means that if `next` panics, our invariant is upheld and + // our `Drop` impl drops the correct elements. + Some(item) => buffer.push(item), + }, + } + self.buffer.as_ref().map(Buffer::as_array_ref) + } + + fn size_hint(&self) -> (usize, Option) { + let Some(ref iter) = self.iter else { return (0, Some(0)) }; + let (lo, hi) = iter.size_hint(); + if self.buffer.is_some() { + // If the first `N` items are already yielded by the inner iterator, + // the size hint is then equal to the that of the inner iterator's. + (lo, hi) + } else { + // If the first `N` items are not yet yielded by the inner iterator, + // the first `N` elements should be counted as one window, so both bounds + // should subtract `N - 1`. + (lo.saturating_sub(N - 1), hi.map(|hi| hi.saturating_sub(N - 1))) + } + } +} + +impl Buffer { + fn try_from_iter(iter: &mut impl Iterator) -> Option { + let first_half = crate::array::iter_next_chunk(iter).ok()?; + let buffer = + [MaybeUninit::new(first_half).transpose(), [const { MaybeUninit::uninit() }; N]]; + Some(Self { buffer, start: 0 }) + } + + #[inline] + fn buffer_ptr(&self) -> *const MaybeUninit { + self.buffer.as_ptr().cast() + } + + #[inline] + fn buffer_mut_ptr(&mut self) -> *mut MaybeUninit { + self.buffer.as_mut_ptr().cast() + } + + #[inline] + fn as_array_ref(&self) -> &[T; N] { + debug_assert!(self.start + N <= 2 * N); + + // SAFETY: our invariant guarantees these elements are initialized. + unsafe { &*self.buffer_ptr().add(self.start).cast() } + } + + #[inline] + fn as_uninit_array_mut(&mut self) -> &mut MaybeUninit<[T; N]> { + debug_assert!(self.start + N <= 2 * N); + + // SAFETY: our invariant guarantees these elements are in bounds. + unsafe { &mut *self.buffer_mut_ptr().add(self.start).cast() } + } + + /// Pushes a new item `next` to the back, and pops the front-most one. + /// + /// All the elements will be shifted to the front end when pushing reaches + /// the back end. + fn push(&mut self, next: T) { + let buffer_mut_ptr = self.buffer_mut_ptr(); + debug_assert!(self.start + N <= 2 * N); + + let to_drop = if self.start == N { + // We have reached the end of our buffer and have to copy + // everything to the start. Example layout for N = 3. + // + // 0 1 2 3 4 5 0 1 2 3 4 5 + // ┌───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┐ + // │ - │ - │ - │ a │ b │ c │ -> │ b │ c │ n │ - │ - │ - │ + // └───┴───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┴───┘ + // ↑ ↑ + // start start + + // SAFETY: the two pointers are valid for reads/writes of N -1 + // elements because our array's size is semantically 2 * N. The + // regions also don't overlap for the same reason. + // + // We leave the old elements in place. As soon as `start` is set + // to 0, we treat them as uninitialized and treat their copies + // as initialized. + let to_drop = unsafe { + ptr::copy_nonoverlapping(buffer_mut_ptr.add(self.start + 1), buffer_mut_ptr, N - 1); + (*buffer_mut_ptr.add(N - 1)).write(next); + buffer_mut_ptr.add(self.start) + }; + self.start = 0; + to_drop + } else { + // SAFETY: `self.start` is < N as guaranteed by the invariant + // plus the check above. Even if the drop at the end panics, + // the invariant is upheld. + // + // Example layout for N = 3: + // + // 0 1 2 3 4 5 0 1 2 3 4 5 + // ┌───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┐ + // │ - │ a │ b │ c │ - │ - │ -> │ - │ - │ b │ c │ n │ - │ + // └───┴───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┴───┘ + // ↑ ↑ + // start start + // + let to_drop = unsafe { + (*buffer_mut_ptr.add(self.start + N)).write(next); + buffer_mut_ptr.add(self.start) + }; + self.start += 1; + to_drop + }; + + // SAFETY: the index is valid and this is element `a` in the + // diagram above and has not been dropped yet. + unsafe { ptr::drop_in_place(to_drop.cast::()) }; + } +} + +impl Clone for Buffer { + fn clone(&self) -> Self { + let mut buffer = Buffer { + buffer: [[const { MaybeUninit::uninit() }; N], [const { MaybeUninit::uninit() }; N]], + start: self.start, + }; + buffer.as_uninit_array_mut().write(self.as_array_ref().clone()); + buffer + } +} + +impl Clone for MapWindowsInner +where + I: Iterator + Clone, + I::Item: Clone, +{ + fn clone(&self) -> Self { + Self { iter: self.iter.clone(), buffer: self.buffer.clone() } + } +} + +impl Drop for Buffer { + fn drop(&mut self) { + // SAFETY: our invariant guarantees that N elements starting from + // `self.start` are initialized. We drop them here. + unsafe { + let initialized_part: *mut [T] = crate::ptr::slice_from_raw_parts_mut( + self.buffer_mut_ptr().add(self.start).cast(), + N, + ); + ptr::drop_in_place(initialized_part); + } + } +} + +#[unstable(feature = "iter_map_windows", reason = "recently added", issue = "87155")] +impl Iterator for MapWindows +where + I: Iterator, + F: FnMut(&[I::Item; N]) -> R, +{ + type Item = R; + + fn next(&mut self) -> Option { + let window = self.inner.next_window()?; + let out = (self.f)(window); + Some(out) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +// Note that even if the inner iterator not fused, the `MapWindows` is still fused, +// because we don't allow "holes" in the mapping window. +#[unstable(feature = "iter_map_windows", reason = "recently added", issue = "87155")] +impl FusedIterator for MapWindows +where + I: Iterator, + F: FnMut(&[I::Item; N]) -> R, +{ +} + +#[unstable(feature = "iter_map_windows", reason = "recently added", issue = "87155")] +impl ExactSizeIterator for MapWindows +where + I: ExactSizeIterator, + F: FnMut(&[I::Item; N]) -> R, +{ +} + +#[unstable(feature = "iter_map_windows", reason = "recently added", issue = "87155")] +impl fmt::Debug for MapWindows { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MapWindows").field("iter", &self.inner.iter).finish() + } +} + +#[unstable(feature = "iter_map_windows", reason = "recently added", issue = "87155")] +impl Clone for MapWindows +where + I: Iterator + Clone, + F: Clone, + I::Item: Clone, +{ + fn clone(&self) -> Self { + Self { f: self.f.clone(), inner: self.inner.clone() } + } +} diff --git a/CoqOfRust/core/iter/adapters/mod.rs b/CoqOfRust/core/iter/adapters/mod.rs new file mode 100644 index 000000000..2a0ef0189 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/mod.rs @@ -0,0 +1,229 @@ +use crate::iter::InPlaceIterable; +use crate::num::NonZero; +use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; + +mod array_chunks; +mod by_ref_sized; +mod chain; +mod cloned; +mod copied; +mod cycle; +mod enumerate; +mod filter; +mod filter_map; +mod flatten; +mod fuse; +mod inspect; +mod intersperse; +mod map; +mod map_while; +mod map_windows; +mod peekable; +mod rev; +mod scan; +mod skip; +mod skip_while; +mod step_by; +mod take; +mod take_while; +mod zip; + +#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] +pub use self::array_chunks::ArrayChunks; +#[unstable(feature = "std_internals", issue = "none")] +pub use self::by_ref_sized::ByRefSized; +#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")] +pub use self::chain::chain; +#[stable(feature = "iter_cloned", since = "1.1.0")] +pub use self::cloned::Cloned; +#[stable(feature = "iter_copied", since = "1.36.0")] +pub use self::copied::Copied; +#[stable(feature = "iterator_flatten", since = "1.29.0")] +pub use self::flatten::Flatten; +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +pub use self::intersperse::{Intersperse, IntersperseWith}; +#[stable(feature = "iter_map_while", since = "1.57.0")] +pub use self::map_while::MapWhile; +#[unstable(feature = "iter_map_windows", reason = "recently added", issue = "87155")] +pub use self::map_windows::MapWindows; +#[stable(feature = "iterator_step_by", since = "1.28.0")] +pub use self::step_by::StepBy; +#[unstable(feature = "trusted_random_access", issue = "none")] +pub use self::zip::TrustedRandomAccess; +#[unstable(feature = "trusted_random_access", issue = "none")] +pub use self::zip::TrustedRandomAccessNoCoerce; +#[stable(feature = "iter_zip", since = "1.59.0")] +pub use self::zip::zip; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::{ + chain::Chain, cycle::Cycle, enumerate::Enumerate, filter::Filter, filter_map::FilterMap, + flatten::FlatMap, fuse::Fuse, inspect::Inspect, map::Map, peekable::Peekable, rev::Rev, + scan::Scan, skip::Skip, skip_while::SkipWhile, take::Take, take_while::TakeWhile, zip::Zip, +}; + +/// This trait provides transitive access to source-stage in an iterator-adapter pipeline +/// under the conditions that +/// * the iterator source `S` itself implements `SourceIter` +/// * there is a delegating implementation of this trait for each adapter in the pipeline between +/// the source and the pipeline consumer. +/// +/// When the source is an owning iterator struct (commonly called `IntoIter`) then +/// this can be useful for specializing [`FromIterator`] implementations or recovering the +/// remaining elements after an iterator has been partially exhausted. +/// +/// Note that implementations do not necessarily have to provide access to the innermost +/// source of a pipeline. A stateful intermediate adapter might eagerly evaluate a part +/// of the pipeline and expose its internal storage as source. +/// +/// The trait is unsafe because implementers must uphold additional safety properties. +/// See [`as_inner`] for details. +/// +/// The primary use of this trait is in-place iteration. Refer to the [`vec::in_place_collect`] +/// module documentation for more information. +/// +/// [`vec::in_place_collect`]: ../../../../alloc/vec/in_place_collect/index.html +/// +/// # Examples +/// +/// Retrieving a partially consumed source: +/// +/// ``` +/// # #![feature(inplace_iteration)] +/// # use std::iter::SourceIter; +/// +/// let mut iter = vec![9, 9, 9].into_iter().map(|i| i * i); +/// let _ = iter.next(); +/// let mut remainder = std::mem::replace(unsafe { iter.as_inner() }, Vec::new().into_iter()); +/// println!("n = {} elements remaining", remainder.len()); +/// ``` +/// +/// [`FromIterator`]: crate::iter::FromIterator +/// [`as_inner`]: SourceIter::as_inner +#[unstable(issue = "none", feature = "inplace_iteration")] +#[doc(hidden)] +#[rustc_specialization_trait] +pub unsafe trait SourceIter { + /// A source stage in an iterator pipeline. + type Source; + + /// Retrieve the source of an iterator pipeline. + /// + /// # Safety + /// + /// Implementations must return the same mutable reference for their lifetime, unless + /// replaced by a caller. + /// + /// Callers may only replace the reference when they stopped iteration and drop the + /// iterator pipeline after extracting the source. + /// + /// This means iterator adapters can rely on the source not changing during + /// iteration but they cannot rely on it in their Drop implementations. + /// + /// Implementing this method means adapters relinquish private-only access to their + /// source and can only rely on guarantees made based on method receiver types. + /// The lack of restricted access also requires that adapters must uphold the source's + /// public API even when they have access to its internals. + /// + /// Callers in turn must expect the source to be in any state that is consistent with + /// its public API since adapters sitting between it and the source have the same + /// access. In particular an adapter may have consumed more elements than strictly necessary. + /// + /// The overall goal of these requirements is to let the consumer of a pipeline use + /// * whatever remains in the source after iteration has stopped + /// * the memory that has become unused by advancing a consuming iterator + /// + /// [`next()`]: Iterator::next() + unsafe fn as_inner(&mut self) -> &mut Self::Source; +} + +/// An iterator adapter that produces output as long as the underlying +/// iterator produces values where `Try::branch` says to `ControlFlow::Continue`. +/// +/// If a `ControlFlow::Break` is encountered, the iterator stops and the +/// residual is stored. +pub(crate) struct GenericShunt<'a, I, R> { + iter: I, + residual: &'a mut Option, +} + +/// Process the given iterator as if it yielded the item's `Try::Output` +/// type instead. Any `Try::Residual`s encountered will stop the inner iterator +/// and be propagated back to the overall result. +pub(crate) fn try_process(iter: I, mut f: F) -> ChangeOutputType +where + I: Iterator>, + for<'a> F: FnMut(GenericShunt<'a, I, R>) -> U, + R: Residual, +{ + let mut residual = None; + let shunt = GenericShunt { iter, residual: &mut residual }; + let value = f(shunt); + match residual { + Some(r) => FromResidual::from_residual(r), + None => Try::from_output(value), + } +} + +impl Iterator for GenericShunt<'_, I, R> +where + I: Iterator>, +{ + type Item = ::Output; + + fn next(&mut self) -> Option { + self.try_for_each(ControlFlow::Break).break_value() + } + + fn size_hint(&self) -> (usize, Option) { + if self.residual.is_some() { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } + } + + fn try_fold(&mut self, init: B, mut f: F) -> T + where + F: FnMut(B, Self::Item) -> T, + T: Try, + { + self.iter + .try_fold(init, |acc, x| match Try::branch(x) { + ControlFlow::Continue(x) => ControlFlow::from_try(f(acc, x)), + ControlFlow::Break(r) => { + *self.residual = Some(r); + ControlFlow::Break(try { acc }) + } + }) + .into_try() + } + + impl_fold_via_try_fold! { fold -> try_fold } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for GenericShunt<'_, I, R> +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut Self::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +// SAFETY: GenericShunt::next calls `I::try_for_each`, which has to advance `iter` +// in order to return `Some(_)`. Since `iter` has type `I: InPlaceIterable` it's +// guaranteed that at least one item will be moved out from the underlying source. +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for GenericShunt<'_, I, R> +where + I: InPlaceIterable, +{ + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = I::MERGE_BY; +} diff --git a/CoqOfRust/core/iter/adapters/peekable.rs b/CoqOfRust/core/iter/adapters/peekable.rs new file mode 100644 index 000000000..cc12cd9c3 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/peekable.rs @@ -0,0 +1,337 @@ +use crate::iter::adapters::SourceIter; +use crate::iter::{FusedIterator, TrustedLen}; +use crate::ops::{ControlFlow, Try}; + +/// An iterator with a `peek()` that returns an optional reference to the next +/// element. +/// +/// This `struct` is created by the [`peekable`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`peekable`]: Iterator::peekable +/// [`Iterator`]: trait.Iterator.html +#[derive(Clone, Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "IterPeekable"] +pub struct Peekable { + iter: I, + /// Remember a peeked value, even if it was None. + peeked: Option>, +} + +impl Peekable { + pub(in crate::iter) fn new(iter: I) -> Peekable { + Peekable { iter, peeked: None } + } +} + +// Peekable must remember if a None has been seen in the `.peek()` method. +// It ensures that `.peek(); .peek();` or `.peek(); .next();` only advances the +// underlying iterator at most once. This does not by itself make the iterator +// fused. +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Peekable { + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + match self.peeked.take() { + Some(v) => v, + None => self.iter.next(), + } + } + + #[inline] + #[rustc_inherit_overflow_checks] + fn count(mut self) -> usize { + match self.peeked.take() { + Some(None) => 0, + Some(Some(_)) => 1 + self.iter.count(), + None => self.iter.count(), + } + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + match self.peeked.take() { + Some(None) => None, + Some(v @ Some(_)) if n == 0 => v, + Some(Some(_)) => self.iter.nth(n - 1), + None => self.iter.nth(n), + } + } + + #[inline] + fn last(mut self) -> Option { + let peek_opt = match self.peeked.take() { + Some(None) => return None, + Some(v) => v, + None => None, + }; + self.iter.last().or(peek_opt) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let peek_len = match self.peeked { + Some(None) => return (0, Some(0)), + Some(Some(_)) => 1, + None => 0, + }; + let (lo, hi) = self.iter.size_hint(); + let lo = lo.saturating_add(peek_len); + let hi = match hi { + Some(x) => x.checked_add(peek_len), + None => None, + }; + (lo, hi) + } + + #[inline] + fn try_fold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let acc = match self.peeked.take() { + Some(None) => return try { init }, + Some(Some(v)) => f(init, v)?, + None => init, + }; + self.iter.try_fold(acc, f) + } + + #[inline] + fn fold(self, init: Acc, mut fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + let acc = match self.peeked { + Some(None) => return init, + Some(Some(v)) => fold(init, v), + None => init, + }; + self.iter.fold(acc, fold) + } +} + +#[stable(feature = "double_ended_peek_iterator", since = "1.38.0")] +impl DoubleEndedIterator for Peekable +where + I: DoubleEndedIterator, +{ + #[inline] + fn next_back(&mut self) -> Option { + match self.peeked.as_mut() { + Some(v @ Some(_)) => self.iter.next_back().or_else(|| v.take()), + Some(None) => None, + None => self.iter.next_back(), + } + } + + #[inline] + fn try_rfold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + match self.peeked.take() { + Some(None) => try { init }, + Some(Some(v)) => match self.iter.try_rfold(init, &mut f).branch() { + ControlFlow::Continue(acc) => f(acc, v), + ControlFlow::Break(r) => { + self.peeked = Some(Some(v)); + R::from_residual(r) + } + }, + None => self.iter.try_rfold(init, f), + } + } + + #[inline] + fn rfold(self, init: Acc, mut fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + match self.peeked { + Some(None) => init, + Some(Some(v)) => { + let acc = self.iter.rfold(init, &mut fold); + fold(acc, v) + } + None => self.iter.rfold(init, fold), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Peekable {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Peekable {} + +impl Peekable { + /// Returns a reference to the next() value without advancing the iterator. + /// + /// Like [`next`], if there is a value, it is wrapped in a `Some(T)`. + /// But if the iteration is over, `None` is returned. + /// + /// [`next`]: Iterator::next + /// + /// Because `peek()` returns a reference, and many iterators iterate over + /// references, there can be a possibly confusing situation where the + /// return value is a double reference. You can see this effect in the + /// examples below. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let xs = [1, 2, 3]; + /// + /// let mut iter = xs.iter().peekable(); + /// + /// // peek() lets us see into the future + /// assert_eq!(iter.peek(), Some(&&1)); + /// assert_eq!(iter.next(), Some(&1)); + /// + /// assert_eq!(iter.next(), Some(&2)); + /// + /// // The iterator does not advance even if we `peek` multiple times + /// assert_eq!(iter.peek(), Some(&&3)); + /// assert_eq!(iter.peek(), Some(&&3)); + /// + /// assert_eq!(iter.next(), Some(&3)); + /// + /// // After the iterator is finished, so is `peek()` + /// assert_eq!(iter.peek(), None); + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn peek(&mut self) -> Option<&I::Item> { + let iter = &mut self.iter; + self.peeked.get_or_insert_with(|| iter.next()).as_ref() + } + + /// Returns a mutable reference to the next() value without advancing the iterator. + /// + /// Like [`next`], if there is a value, it is wrapped in a `Some(T)`. + /// But if the iteration is over, `None` is returned. + /// + /// Because `peek_mut()` returns a reference, and many iterators iterate over + /// references, there can be a possibly confusing situation where the + /// return value is a double reference. You can see this effect in the examples + /// below. + /// + /// [`next`]: Iterator::next + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut iter = [1, 2, 3].iter().peekable(); + /// + /// // Like with `peek()`, we can see into the future without advancing the iterator. + /// assert_eq!(iter.peek_mut(), Some(&mut &1)); + /// assert_eq!(iter.peek_mut(), Some(&mut &1)); + /// assert_eq!(iter.next(), Some(&1)); + /// + /// // Peek into the iterator and set the value behind the mutable reference. + /// if let Some(p) = iter.peek_mut() { + /// assert_eq!(*p, &2); + /// *p = &5; + /// } + /// + /// // The value we put in reappears as the iterator continues. + /// assert_eq!(iter.collect::>(), vec![&5, &3]); + /// ``` + #[inline] + #[stable(feature = "peekable_peek_mut", since = "1.53.0")] + pub fn peek_mut(&mut self) -> Option<&mut I::Item> { + let iter = &mut self.iter; + self.peeked.get_or_insert_with(|| iter.next()).as_mut() + } + + /// Consume and return the next value of this iterator if a condition is true. + /// + /// If `func` returns `true` for the next value of this iterator, consume and return it. + /// Otherwise, return `None`. + /// + /// # Examples + /// Consume a number if it's equal to 0. + /// ``` + /// let mut iter = (0..5).peekable(); + /// // The first item of the iterator is 0; consume it. + /// assert_eq!(iter.next_if(|&x| x == 0), Some(0)); + /// // The next item returned is now 1, so `next_if` will return `None`. + /// assert_eq!(iter.next_if(|&x| x == 0), None); + /// // `next_if` saves the value of the next item if it was not equal to `expected`. + /// assert_eq!(iter.next(), Some(1)); + /// ``` + /// + /// Consume any number less than 10. + /// ``` + /// let mut iter = (1..20).peekable(); + /// // Consume all numbers less than 10 + /// while iter.next_if(|&x| x < 10).is_some() {} + /// // The next value returned will be 10 + /// assert_eq!(iter.next(), Some(10)); + /// ``` + #[stable(feature = "peekable_next_if", since = "1.51.0")] + pub fn next_if(&mut self, func: impl FnOnce(&I::Item) -> bool) -> Option { + match self.next() { + Some(matched) if func(&matched) => Some(matched), + other => { + // Since we called `self.next()`, we consumed `self.peeked`. + assert!(self.peeked.is_none()); + self.peeked = Some(other); + None + } + } + } + + /// Consume and return the next item if it is equal to `expected`. + /// + /// # Example + /// Consume a number if it's equal to 0. + /// ``` + /// let mut iter = (0..5).peekable(); + /// // The first item of the iterator is 0; consume it. + /// assert_eq!(iter.next_if_eq(&0), Some(0)); + /// // The next item returned is now 1, so `next_if` will return `None`. + /// assert_eq!(iter.next_if_eq(&0), None); + /// // `next_if_eq` saves the value of the next item if it was not equal to `expected`. + /// assert_eq!(iter.next(), Some(1)); + /// ``` + #[stable(feature = "peekable_next_if", since = "1.51.0")] + pub fn next_if_eq(&mut self, expected: &T) -> Option + where + T: ?Sized, + I::Item: PartialEq, + { + self.next_if(|next| next == expected) + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Peekable where I: TrustedLen {} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Peekable +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} diff --git a/CoqOfRust/core/iter/adapters/rev.rs b/CoqOfRust/core/iter/adapters/rev.rs new file mode 100644 index 000000000..06ab15d5e --- /dev/null +++ b/CoqOfRust/core/iter/adapters/rev.rs @@ -0,0 +1,152 @@ +use crate::iter::{FusedIterator, TrustedLen}; +use crate::num::NonZero; +use crate::ops::Try; + +/// A double-ended iterator with the direction inverted. +/// +/// This `struct` is created by the [`rev`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`rev`]: Iterator::rev +/// [`Iterator`]: trait.Iterator.html +#[derive(Clone, Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Rev { + iter: T, +} + +impl Rev { + pub(in crate::iter) fn new(iter: T) -> Rev { + Rev { iter } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Rev +where + I: DoubleEndedIterator, +{ + type Item = ::Item; + + #[inline] + fn next(&mut self) -> Option<::Item> { + self.iter.next_back() + } + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.iter.advance_back_by(n) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option<::Item> { + self.iter.nth_back(n) + } + + fn try_fold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.iter.try_rfold(init, f) + } + + fn fold(self, init: Acc, f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.rfold(init, f) + } + + #[inline] + fn find

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + self.iter.rfind(predicate) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Rev +where + I: DoubleEndedIterator, +{ + #[inline] + fn next_back(&mut self) -> Option<::Item> { + self.iter.next() + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.iter.advance_by(n) + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option<::Item> { + self.iter.nth(n) + } + + fn try_rfold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.iter.try_fold(init, f) + } + + fn rfold(self, init: Acc, f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.fold(init, f) + } + + fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + self.iter.find(predicate) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Rev +where + I: ExactSizeIterator + DoubleEndedIterator, +{ + fn len(&self) -> usize { + self.iter.len() + } + + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Rev where I: FusedIterator + DoubleEndedIterator {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Rev where I: TrustedLen + DoubleEndedIterator {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for Rev { + /// Creates a `Rev` iterator from the default value of `I` + /// ``` + /// # use core::slice; + /// # use core::iter::Rev; + /// let iter: Rev> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Rev::new(Default::default()) + } +} diff --git a/CoqOfRust/core/iter/adapters/scan.rs b/CoqOfRust/core/iter/adapters/scan.rs new file mode 100644 index 000000000..e12375c94 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/scan.rs @@ -0,0 +1,100 @@ +use crate::fmt; +use crate::iter::InPlaceIterable; +use crate::iter::adapters::SourceIter; +use crate::num::NonZero; +use crate::ops::{ControlFlow, Try}; + +/// An iterator to maintain state while iterating another iterator. +/// +/// This `struct` is created by the [`scan`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`scan`]: Iterator::scan +/// [`Iterator`]: trait.Iterator.html +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] +pub struct Scan { + iter: I, + f: F, + state: St, +} + +impl Scan { + pub(in crate::iter) fn new(iter: I, state: St, f: F) -> Scan { + Scan { iter, state, f } + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for Scan { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Scan").field("iter", &self.iter).field("state", &self.state).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Scan +where + I: Iterator, + F: FnMut(&mut St, I::Item) -> Option, +{ + type Item = B; + + #[inline] + fn next(&mut self) -> Option { + let a = self.iter.next()?; + (self.f)(&mut self.state, a) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the scan function + } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + fn scan<'a, T, St, B, Acc, R: Try>( + state: &'a mut St, + f: &'a mut impl FnMut(&mut St, T) -> Option, + mut fold: impl FnMut(Acc, B) -> R + 'a, + ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { + move |acc, x| match f(state, x) { + None => ControlFlow::Break(try { acc }), + Some(x) => ControlFlow::from_try(fold(acc, x)), + } + } + + let state = &mut self.state; + let f = &mut self.f; + self.iter.try_fold(init, scan(state, f, fold)).into_try() + } + + impl_fold_via_try_fold! { fold -> try_fold } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Scan +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for Scan { + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = I::MERGE_BY; +} diff --git a/CoqOfRust/core/iter/adapters/skip.rs b/CoqOfRust/core/iter/adapters/skip.rs new file mode 100644 index 000000000..55c4a7f14 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/skip.rs @@ -0,0 +1,289 @@ +use crate::intrinsics::unlikely; +use crate::iter::adapters::SourceIter; +use crate::iter::adapters::zip::try_get_unchecked; +use crate::iter::{ + FusedIterator, InPlaceIterable, TrustedFused, TrustedLen, TrustedRandomAccess, + TrustedRandomAccessNoCoerce, +}; +use crate::num::NonZero; +use crate::ops::{ControlFlow, Try}; + +/// An iterator that skips over `n` elements of `iter`. +/// +/// This `struct` is created by the [`skip`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`skip`]: Iterator::skip +/// [`Iterator`]: trait.Iterator.html +#[derive(Clone, Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Skip { + iter: I, + n: usize, +} + +impl Skip { + pub(in crate::iter) fn new(iter: I, n: usize) -> Skip { + Skip { iter, n } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Skip +where + I: Iterator, +{ + type Item = ::Item; + + #[inline] + fn next(&mut self) -> Option { + if unlikely(self.n > 0) { + self.iter.nth(crate::mem::take(&mut self.n)) + } else { + self.iter.next() + } + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + if self.n > 0 { + let skip: usize = crate::mem::take(&mut self.n); + // Checked add to handle overflow case. + let n = match skip.checked_add(n) { + Some(nth) => nth, + None => { + // In case of overflow, load skip value, before loading `n`. + // Because the amount of elements to iterate is beyond `usize::MAX`, this + // is split into two `nth` calls where the `skip` `nth` call is discarded. + self.iter.nth(skip - 1)?; + n + } + }; + // Load nth element including skip. + self.iter.nth(n) + } else { + self.iter.nth(n) + } + } + + #[inline] + fn count(mut self) -> usize { + if self.n > 0 { + // nth(n) skips n+1 + if self.iter.nth(self.n - 1).is_none() { + return 0; + } + } + self.iter.count() + } + + #[inline] + fn last(mut self) -> Option { + if self.n > 0 { + // nth(n) skips n+1 + self.iter.nth(self.n - 1)?; + } + self.iter.last() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (lower, upper) = self.iter.size_hint(); + + let lower = lower.saturating_sub(self.n); + let upper = match upper { + Some(x) => Some(x.saturating_sub(self.n)), + None => None, + }; + + (lower, upper) + } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + let n = self.n; + self.n = 0; + if n > 0 { + // nth(n) skips n+1 + if self.iter.nth(n - 1).is_none() { + return try { init }; + } + } + self.iter.try_fold(init, fold) + } + + #[inline] + fn fold(mut self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + if self.n > 0 { + // nth(n) skips n+1 + if self.iter.nth(self.n - 1).is_none() { + return init; + } + } + self.iter.fold(init, fold) + } + + #[inline] + #[rustc_inherit_overflow_checks] + fn advance_by(&mut self, mut n: usize) -> Result<(), NonZero> { + let skip_inner = self.n; + let skip_and_advance = skip_inner.saturating_add(n); + + let remainder = match self.iter.advance_by(skip_and_advance) { + Ok(()) => 0, + Err(n) => n.get(), + }; + let advanced_inner = skip_and_advance - remainder; + n -= advanced_inner.saturating_sub(skip_inner); + self.n = self.n.saturating_sub(advanced_inner); + + // skip_and_advance may have saturated + if unlikely(remainder == 0 && n > 0) { + n = match self.iter.advance_by(n) { + Ok(()) => 0, + Err(n) => n.get(), + } + } + + NonZero::new(n).map_or(Ok(()), Err) + } + + #[doc(hidden)] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccessNoCoerce, + { + // SAFETY: the caller must uphold the contract for + // `Iterator::__iterator_get_unchecked`. + // + // Dropping the skipped prefix when index 0 is passed is safe + // since + // * the caller passing index 0 means that the inner iterator has more items than `self.n` + // * TRA contract requires that get_unchecked will only be called once + // (unless elements are copyable) + // * it does not conflict with in-place iteration since index 0 must be accessed + // before something is written into the storage used by the prefix + unsafe { + if Self::MAY_HAVE_SIDE_EFFECT && idx == 0 { + for skipped_idx in 0..self.n { + drop(try_get_unchecked(&mut self.iter, skipped_idx)); + } + } + + try_get_unchecked(&mut self.iter, idx + self.n) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Skip where I: ExactSizeIterator {} + +#[stable(feature = "double_ended_skip_iterator", since = "1.9.0")] +impl DoubleEndedIterator for Skip +where + I: DoubleEndedIterator + ExactSizeIterator, +{ + fn next_back(&mut self) -> Option { + if self.len() > 0 { self.iter.next_back() } else { None } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n < len { + self.iter.nth_back(n) + } else { + if len > 0 { + // consume the original iterator + self.iter.nth_back(len - 1); + } + None + } + } + + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + fn check>( + mut n: usize, + mut fold: impl FnMut(Acc, T) -> R, + ) -> impl FnMut(Acc, T) -> ControlFlow { + move |acc, x| { + n -= 1; + let r = fold(acc, x); + if n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) } + } + } + + let n = self.len(); + if n == 0 { try { init } } else { self.iter.try_rfold(init, check(n, fold)).into_try() } + } + + impl_fold_via_try_fold! { rfold -> try_rfold } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + let min = crate::cmp::min(self.len(), n); + let rem = self.iter.advance_back_by(min); + assert!(rem.is_ok(), "ExactSizeIterator contract violation"); + NonZero::new(n - min).map_or(Ok(()), Err) + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Skip where I: FusedIterator {} + +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Skip {} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Skip +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for Skip { + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = I::MERGE_BY; +} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for Skip where I: TrustedRandomAccess {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccessNoCoerce for Skip +where + I: TrustedRandomAccessNoCoerce, +{ + const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT; +} + +// SAFETY: This adapter is shortening. TrustedLen requires the upper bound to be calculated correctly. +// These requirements can only be satisfied when the upper bound of the inner iterator's upper +// bound is never `None`. I: TrustedRandomAccess happens to provide this guarantee while +// I: TrustedLen would not. +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Skip where I: Iterator + TrustedRandomAccess {} diff --git a/CoqOfRust/core/iter/adapters/skip_while.rs b/CoqOfRust/core/iter/adapters/skip_while.rs new file mode 100644 index 000000000..8ae453e76 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/skip_while.rs @@ -0,0 +1,130 @@ +use crate::fmt; +use crate::iter::adapters::SourceIter; +use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused}; +use crate::num::NonZero; +use crate::ops::Try; + +/// An iterator that rejects elements while `predicate` returns `true`. +/// +/// This `struct` is created by the [`skip_while`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`skip_while`]: Iterator::skip_while +/// [`Iterator`]: trait.Iterator.html +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] +pub struct SkipWhile { + iter: I, + flag: bool, + predicate: P, +} + +impl SkipWhile { + pub(in crate::iter) fn new(iter: I, predicate: P) -> SkipWhile { + SkipWhile { iter, flag: false, predicate } + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for SkipWhile { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SkipWhile").field("iter", &self.iter).field("flag", &self.flag).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for SkipWhile +where + P: FnMut(&I::Item) -> bool, +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + fn check<'a, T>( + flag: &'a mut bool, + pred: &'a mut impl FnMut(&T) -> bool, + ) -> impl FnMut(&T) -> bool + 'a { + move |x| { + if *flag || !pred(x) { + *flag = true; + true + } else { + false + } + } + } + + let flag = &mut self.flag; + let pred = &mut self.predicate; + self.iter.find(check(flag, pred)) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } + + #[inline] + fn try_fold(&mut self, mut init: Acc, mut fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + if !self.flag { + match self.next() { + Some(v) => init = fold(init, v)?, + None => return try { init }, + } + } + self.iter.try_fold(init, fold) + } + + #[inline] + fn fold(mut self, mut init: Acc, mut fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + if !self.flag { + match self.next() { + Some(v) => init = fold(init, v), + None => return init, + } + } + self.iter.fold(init, fold) + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for SkipWhile +where + I: FusedIterator, + P: FnMut(&I::Item) -> bool, +{ +} + +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for SkipWhile {} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for SkipWhile +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for SkipWhile { + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = I::MERGE_BY; +} diff --git a/CoqOfRust/core/iter/adapters/step_by.rs b/CoqOfRust/core/iter/adapters/step_by.rs new file mode 100644 index 000000000..2d0f21042 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/step_by.rs @@ -0,0 +1,581 @@ +use crate::intrinsics; +use crate::iter::{TrustedLen, TrustedRandomAccess, from_fn}; +use crate::num::NonZero; +use crate::ops::{Range, Try}; + +/// An iterator for stepping iterators by a custom amount. +/// +/// This `struct` is created by the [`step_by`] method on [`Iterator`]. See +/// its documentation for more. +/// +/// [`step_by`]: Iterator::step_by +/// [`Iterator`]: trait.Iterator.html +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "iterator_step_by", since = "1.28.0")] +#[derive(Clone, Debug)] +pub struct StepBy { + /// This field is guaranteed to be preprocessed by the specialized `SpecRangeSetup::setup` + /// in the constructor. + /// For most iterators that processing is a no-op, but for Range<{integer}> types it is lossy + /// which means the inner iterator cannot be returned to user code. + /// Additionally this type-dependent preprocessing means specialized implementations + /// cannot be used interchangeably. + iter: I, + /// This field is `step - 1`, aka the correct amount to pass to `nth` when iterating. + /// It MUST NOT be `usize::MAX`, as `unsafe` code depends on being able to add one + /// without the risk of overflow. (This is important so that length calculations + /// don't need to check for division-by-zero, for example.) + step_minus_one: usize, + first_take: bool, +} + +impl StepBy { + #[inline] + pub(in crate::iter) fn new(iter: I, step: usize) -> StepBy { + assert!(step != 0); + let iter = >::setup(iter, step); + StepBy { iter, step_minus_one: step - 1, first_take: true } + } + + /// The `step` that was originally passed to `Iterator::step_by(step)`, + /// aka `self.step_minus_one + 1`. + #[inline] + fn original_step(&self) -> NonZero { + // SAFETY: By type invariant, `step_minus_one` cannot be `MAX`, which + // means the addition cannot overflow and the result cannot be zero. + unsafe { NonZero::new_unchecked(intrinsics::unchecked_add(self.step_minus_one, 1)) } + } +} + +#[stable(feature = "iterator_step_by", since = "1.28.0")] +impl Iterator for StepBy +where + I: Iterator, +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + self.spec_next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.spec_size_hint() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.spec_nth(n) + } + + fn try_fold(&mut self, acc: Acc, f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.spec_try_fold(acc, f) + } + + #[inline] + fn fold(self, acc: Acc, f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + self.spec_fold(acc, f) + } +} + +impl StepBy +where + I: ExactSizeIterator, +{ + // The zero-based index starting from the end of the iterator of the + // last element. Used in the `DoubleEndedIterator` implementation. + fn next_back_index(&self) -> usize { + let rem = self.iter.len() % self.original_step(); + if self.first_take { if rem == 0 { self.step_minus_one } else { rem - 1 } } else { rem } + } +} + +#[stable(feature = "double_ended_step_by_iterator", since = "1.38.0")] +impl DoubleEndedIterator for StepBy +where + I: DoubleEndedIterator + ExactSizeIterator, +{ + #[inline] + fn next_back(&mut self) -> Option { + self.spec_next_back() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.spec_nth_back(n) + } + + fn try_rfold(&mut self, init: Acc, f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.spec_try_rfold(init, f) + } + + #[inline] + fn rfold(self, init: Acc, f: F) -> Acc + where + Self: Sized, + F: FnMut(Acc, Self::Item) -> Acc, + { + self.spec_rfold(init, f) + } +} + +// StepBy can only make the iterator shorter, so the len will still fit. +#[stable(feature = "iterator_step_by", since = "1.28.0")] +impl ExactSizeIterator for StepBy where I: ExactSizeIterator {} + +// SAFETY: This adapter is shortening. TrustedLen requires the upper bound to be calculated correctly. +// These requirements can only be satisfied when the upper bound of the inner iterator's upper +// bound is never `None`. I: TrustedRandomAccess happens to provide this guarantee while +// I: TrustedLen would not. +// This also covers the Range specializations since the ranges also implement TRA +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for StepBy where I: Iterator + TrustedRandomAccess {} + +trait SpecRangeSetup { + fn setup(inner: T, step: usize) -> T; +} + +impl SpecRangeSetup for T { + #[inline] + default fn setup(inner: T, _step: usize) -> T { + inner + } +} + +/// Specialization trait to optimize `StepBy>` iteration. +/// +/// # Safety +/// +/// Technically this is safe to implement (look ma, no unsafe!), but in reality +/// a lot of unsafe code relies on ranges over integers being correct. +/// +/// For correctness *all* public StepBy methods must be specialized +/// because `setup` drastically alters the meaning of the struct fields so that mixing +/// different implementations would lead to incorrect results. +unsafe trait StepByImpl { + type Item; + + fn spec_next(&mut self) -> Option; + + fn spec_size_hint(&self) -> (usize, Option); + + fn spec_nth(&mut self, n: usize) -> Option; + + fn spec_try_fold(&mut self, acc: Acc, f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try; + + fn spec_fold(self, acc: Acc, f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc; +} + +/// Specialization trait for double-ended iteration. +/// +/// See also: `StepByImpl` +/// +/// # Safety +/// +/// The specializations must be implemented together with `StepByImpl` +/// where applicable. I.e. if `StepBy` does support backwards iteration +/// for a given iterator and that is specialized for forward iteration then +/// it must also be specialized for backwards iteration. +unsafe trait StepByBackImpl { + type Item; + + fn spec_next_back(&mut self) -> Option + where + I: DoubleEndedIterator + ExactSizeIterator; + + fn spec_nth_back(&mut self, n: usize) -> Option + where + I: DoubleEndedIterator + ExactSizeIterator; + + fn spec_try_rfold(&mut self, init: Acc, f: F) -> R + where + I: DoubleEndedIterator + ExactSizeIterator, + F: FnMut(Acc, Self::Item) -> R, + R: Try; + + fn spec_rfold(self, init: Acc, f: F) -> Acc + where + I: DoubleEndedIterator + ExactSizeIterator, + F: FnMut(Acc, Self::Item) -> Acc; +} + +unsafe impl StepByImpl for StepBy { + type Item = I::Item; + + #[inline] + default fn spec_next(&mut self) -> Option { + let step_size = if self.first_take { 0 } else { self.step_minus_one }; + self.first_take = false; + self.iter.nth(step_size) + } + + #[inline] + default fn spec_size_hint(&self) -> (usize, Option) { + #[inline] + fn first_size(step: NonZero) -> impl Fn(usize) -> usize { + move |n| if n == 0 { 0 } else { 1 + (n - 1) / step } + } + + #[inline] + fn other_size(step: NonZero) -> impl Fn(usize) -> usize { + move |n| n / step + } + + let (low, high) = self.iter.size_hint(); + + if self.first_take { + let f = first_size(self.original_step()); + (f(low), high.map(f)) + } else { + let f = other_size(self.original_step()); + (f(low), high.map(f)) + } + } + + #[inline] + default fn spec_nth(&mut self, mut n: usize) -> Option { + if self.first_take { + self.first_take = false; + let first = self.iter.next(); + if n == 0 { + return first; + } + n -= 1; + } + // n and self.step_minus_one are indices, we need to add 1 to get the amount of elements + // When calling `.nth`, we need to subtract 1 again to convert back to an index + let mut step = self.original_step().get(); + // n + 1 could overflow + // thus, if n is usize::MAX, instead of adding one, we call .nth(step) + if n == usize::MAX { + self.iter.nth(step - 1); + } else { + n += 1; + } + + // overflow handling + loop { + let mul = n.checked_mul(step); + { + 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; + let nth_step = div_step * step; + let nth = if nth_n > nth_step { + step -= div_n; + nth_n + } else { + n -= div_step; + nth_step + }; + self.iter.nth(nth - 1); + } + } + + default fn spec_try_fold(&mut self, mut acc: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try, + { + #[inline] + fn nth( + iter: &mut I, + step_minus_one: usize, + ) -> impl FnMut() -> Option + '_ { + move || iter.nth(step_minus_one) + } + + if self.first_take { + self.first_take = false; + match self.iter.next() { + None => return try { acc }, + Some(x) => acc = f(acc, x)?, + } + } + from_fn(nth(&mut self.iter, self.step_minus_one)).try_fold(acc, f) + } + + default fn spec_fold(mut self, mut acc: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + #[inline] + fn nth( + iter: &mut I, + step_minus_one: usize, + ) -> impl FnMut() -> Option + '_ { + move || iter.nth(step_minus_one) + } + + if self.first_take { + self.first_take = false; + match self.iter.next() { + None => return acc, + Some(x) => acc = f(acc, x), + } + } + from_fn(nth(&mut self.iter, self.step_minus_one)).fold(acc, f) + } +} + +unsafe impl StepByBackImpl for StepBy { + type Item = I::Item; + + #[inline] + default fn spec_next_back(&mut self) -> Option { + self.iter.nth_back(self.next_back_index()) + } + + #[inline] + default fn spec_nth_back(&mut self, n: usize) -> Option { + // `self.iter.nth_back(usize::MAX)` does the right thing here when `n` + // is out of bounds because the length of `self.iter` does not exceed + // `usize::MAX` (because `I: ExactSizeIterator`) and `nth_back` is + // zero-indexed + let n = n.saturating_mul(self.original_step().get()).saturating_add(self.next_back_index()); + self.iter.nth_back(n) + } + + default fn spec_try_rfold(&mut self, init: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try, + { + #[inline] + fn nth_back( + iter: &mut I, + step_minus_one: usize, + ) -> impl FnMut() -> Option + '_ { + move || iter.nth_back(step_minus_one) + } + + match self.next_back() { + None => try { init }, + Some(x) => { + let acc = f(init, x)?; + from_fn(nth_back(&mut self.iter, self.step_minus_one)).try_fold(acc, f) + } + } + } + + #[inline] + default fn spec_rfold(mut self, init: Acc, mut f: F) -> Acc + where + Self: Sized, + F: FnMut(Acc, I::Item) -> Acc, + { + #[inline] + fn nth_back( + iter: &mut I, + step_minus_one: usize, + ) -> impl FnMut() -> Option + '_ { + move || iter.nth_back(step_minus_one) + } + + match self.next_back() { + None => init, + Some(x) => { + let acc = f(init, x); + from_fn(nth_back(&mut self.iter, self.step_minus_one)).fold(acc, f) + } + } + } +} + +/// For these implementations, `SpecRangeSetup` calculates the number +/// of iterations that will be needed and stores that in `iter.end`. +/// +/// The various iterator implementations then rely on that to not need +/// overflow checking, letting loops just be counted instead. +/// +/// These only work for unsigned types, and will need to be reworked +/// if you want to use it to specialize on signed types. +/// +/// Currently these are only implemented for integers up to `usize` due to +/// correctness issues around `ExactSizeIterator` impls on 16bit platforms. +/// And since `ExactSizeIterator` is a prerequisite for backwards iteration +/// and we must consistently specialize backwards and forwards iteration +/// that makes the situation complicated enough that it's not covered +/// for now. +macro_rules! spec_int_ranges { + ($($t:ty)*) => ($( + + const _: () = assert!(usize::BITS >= <$t>::BITS); + + impl SpecRangeSetup> for Range<$t> { + #[inline] + fn setup(mut r: Range<$t>, step: usize) -> Range<$t> { + let inner_len = r.size_hint().0; + // If step exceeds $t::MAX, then the count will be at most 1 and + // thus always fit into $t. + let yield_count = inner_len.div_ceil(step); + // Turn the range end into an iteration counter + r.end = yield_count as $t; + r + } + } + + unsafe impl StepByImpl> for StepBy> { + #[inline] + fn spec_next(&mut self) -> Option<$t> { + // if a step size larger than the type has been specified fall back to + // t::MAX, in which case remaining will be at most 1. + let step = <$t>::try_from(self.original_step().get()).unwrap_or(<$t>::MAX); + let remaining = self.iter.end; + if remaining > 0 { + let val = self.iter.start; + // this can only overflow during the last step, after which the value + // will not be used + self.iter.start = val.wrapping_add(step); + self.iter.end = remaining - 1; + Some(val) + } else { + None + } + } + + #[inline] + fn spec_size_hint(&self) -> (usize, Option) { + let remaining = self.iter.end as usize; + (remaining, Some(remaining)) + } + + // The methods below are all copied from the Iterator trait default impls. + // We have to repeat them here so that the specialization overrides the StepByImpl defaults + + #[inline] + fn spec_nth(&mut self, n: usize) -> Option { + self.advance_by(n).ok()?; + self.next() + } + + #[inline] + fn spec_try_fold(&mut self, init: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try + { + let mut accum = init; + while let Some(x) = self.next() { + accum = f(accum, x)?; + } + try { accum } + } + + #[inline] + fn spec_fold(self, init: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc + { + // if a step size larger than the type has been specified fall back to + // t::MAX, in which case remaining will be at most 1. + let step = <$t>::try_from(self.original_step().get()).unwrap_or(<$t>::MAX); + let remaining = self.iter.end; + let mut acc = init; + let mut val = self.iter.start; + for _ in 0..remaining { + acc = f(acc, val); + // this can only overflow during the last step, after which the value + // will no longer be used + val = val.wrapping_add(step); + } + acc + } + } + )*) +} + +macro_rules! spec_int_ranges_r { + ($($t:ty)*) => ($( + const _: () = assert!(usize::BITS >= <$t>::BITS); + + unsafe impl StepByBackImpl> for StepBy> { + + #[inline] + fn spec_next_back(&mut self) -> Option { + let step = self.original_step().get() as $t; + let remaining = self.iter.end; + if remaining > 0 { + let start = self.iter.start; + self.iter.end = remaining - 1; + Some(start + step * (remaining - 1)) + } else { + None + } + } + + // The methods below are all copied from the Iterator trait default impls. + // We have to repeat them here so that the specialization overrides the StepByImplBack defaults + + #[inline] + fn spec_nth_back(&mut self, n: usize) -> Option { + if self.advance_back_by(n).is_err() { + return None; + } + self.next_back() + } + + #[inline] + fn spec_try_rfold(&mut self, init: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x)?; + } + try { accum } + } + + #[inline] + fn spec_rfold(mut self, init: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x); + } + accum + } + } + )*) +} + +#[cfg(target_pointer_width = "64")] +spec_int_ranges!(u8 u16 u32 u64 usize); +// DoubleEndedIterator requires ExactSizeIterator, which isn't implemented for Range +#[cfg(target_pointer_width = "64")] +spec_int_ranges_r!(u8 u16 u32 usize); + +#[cfg(target_pointer_width = "32")] +spec_int_ranges!(u8 u16 u32 usize); +#[cfg(target_pointer_width = "32")] +spec_int_ranges_r!(u8 u16 u32 usize); + +#[cfg(target_pointer_width = "16")] +spec_int_ranges!(u8 u16 usize); +#[cfg(target_pointer_width = "16")] +spec_int_ranges_r!(u8 u16 usize); diff --git a/CoqOfRust/core/iter/adapters/take.rs b/CoqOfRust/core/iter/adapters/take.rs new file mode 100644 index 000000000..b96335f41 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/take.rs @@ -0,0 +1,376 @@ +use crate::cmp; +use crate::iter::adapters::SourceIter; +use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen, TrustedRandomAccess}; +use crate::num::NonZero; +use crate::ops::{ControlFlow, Try}; + +/// An iterator that only iterates over the first `n` iterations of `iter`. +/// +/// This `struct` is created by the [`take`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`take`]: Iterator::take +/// [`Iterator`]: trait.Iterator.html +#[derive(Clone, Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Take { + iter: I, + n: usize, +} + +impl Take { + pub(in crate::iter) fn new(iter: I, n: usize) -> Take { + Take { iter, n } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Take +where + I: Iterator, +{ + type Item = ::Item; + + #[inline] + fn next(&mut self) -> Option<::Item> { + if self.n != 0 { + self.n -= 1; + self.iter.next() + } else { + None + } + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + if self.n > n { + self.n -= n + 1; + self.iter.nth(n) + } else { + if self.n > 0 { + self.iter.nth(self.n - 1); + self.n = 0; + } + None + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.n == 0 { + return (0, Some(0)); + } + + let (lower, upper) = self.iter.size_hint(); + + let lower = cmp::min(lower, self.n); + + let upper = match upper { + Some(x) if x < self.n => Some(x), + _ => Some(self.n), + }; + + (lower, upper) + } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + fn check<'a, T, Acc, R: Try>( + n: &'a mut usize, + mut fold: impl FnMut(Acc, T) -> R + 'a, + ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { + move |acc, x| { + *n -= 1; + let r = fold(acc, x); + if *n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) } + } + } + + if self.n == 0 { + try { init } + } else { + let n = &mut self.n; + self.iter.try_fold(init, check(n, fold)).into_try() + } + } + + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + Self::spec_fold(self, init, f) + } + + #[inline] + fn for_each(self, f: F) { + Self::spec_for_each(self, f) + } + + #[inline] + #[rustc_inherit_overflow_checks] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + let min = self.n.min(n); + let rem = match self.iter.advance_by(min) { + Ok(()) => 0, + Err(rem) => rem.get(), + }; + let advanced = min - rem; + self.n -= advanced; + NonZero::new(n - advanced).map_or(Ok(()), Err) + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Take +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for Take { + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = I::MERGE_BY; +} + +#[stable(feature = "double_ended_take_iterator", since = "1.38.0")] +impl DoubleEndedIterator for Take +where + I: DoubleEndedIterator + ExactSizeIterator, +{ + #[inline] + fn next_back(&mut self) -> Option { + if self.n == 0 { + None + } else { + let n = self.n; + self.n -= 1; + self.iter.nth_back(self.iter.len().saturating_sub(n)) + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.iter.len(); + if self.n > n { + let m = len.saturating_sub(self.n) + n; + self.n -= n + 1; + self.iter.nth_back(m) + } else { + if len > 0 { + self.iter.nth_back(len - 1); + } + None + } + } + + #[inline] + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + if self.n == 0 { + try { init } + } else { + let len = self.iter.len(); + if len > self.n && self.iter.nth_back(len - self.n - 1).is_none() { + try { init } + } else { + self.iter.try_rfold(init, fold) + } + } + } + + #[inline] + fn rfold(mut self, init: Acc, fold: Fold) -> Acc + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> Acc, + { + if self.n == 0 { + init + } else { + let len = self.iter.len(); + if len > self.n && self.iter.nth_back(len - self.n - 1).is_none() { + init + } else { + self.iter.rfold(init, fold) + } + } + } + + #[inline] + #[rustc_inherit_overflow_checks] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + // The amount by which the inner iterator needs to be shortened for it to be + // at most as long as the take() amount. + let trim_inner = self.iter.len().saturating_sub(self.n); + // The amount we need to advance inner to fulfill the caller's request. + // take(), advance_by() and len() all can be at most usize, so we don't have to worry + // about having to advance more than usize::MAX here. + let advance_by = trim_inner.saturating_add(n); + + let remainder = match self.iter.advance_back_by(advance_by) { + Ok(()) => 0, + Err(rem) => rem.get(), + }; + let advanced_by_inner = advance_by - remainder; + let advanced_by = advanced_by_inner - trim_inner; + self.n -= advanced_by; + NonZero::new(n - advanced_by).map_or(Ok(()), Err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Take where I: ExactSizeIterator {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Take where I: FusedIterator {} + +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Take {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Take {} + +trait SpecTake: Iterator { + fn spec_fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B; + + fn spec_for_each(self, f: F); +} + +impl SpecTake for Take { + #[inline] + default fn spec_fold(mut self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + use crate::ops::NeverShortCircuit; + self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 + } + + #[inline] + default fn spec_for_each(mut self, f: F) { + // The default implementation would use a unit accumulator, so we can + // avoid a stateful closure by folding over the remaining number + // of items we wish to return instead. + fn check<'a, Item>( + mut action: impl FnMut(Item) + 'a, + ) -> impl FnMut(usize, Item) -> Option + 'a { + move |more, x| { + action(x); + more.checked_sub(1) + } + } + + let remaining = self.n; + if remaining > 0 { + self.iter.try_fold(remaining - 1, check(f)); + } + } +} + +impl SpecTake for Take { + #[inline] + fn spec_fold(mut self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + let mut acc = init; + let end = self.n.min(self.iter.size()); + for i in 0..end { + // SAFETY: i < end <= self.iter.size() and we discard the iterator at the end + let val = unsafe { self.iter.__iterator_get_unchecked(i) }; + acc = f(acc, val); + } + acc + } + + #[inline] + fn spec_for_each(mut self, mut f: F) { + let end = self.n.min(self.iter.size()); + for i in 0..end { + // SAFETY: i < end <= self.iter.size() and we discard the iterator at the end + let val = unsafe { self.iter.__iterator_get_unchecked(i) }; + f(val); + } + } +} + +#[stable(feature = "exact_size_take_repeat", since = "1.82.0")] +impl DoubleEndedIterator for Take> { + #[inline] + fn next_back(&mut self) -> Option { + self.next() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.nth(n) + } + + #[inline] + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.try_fold(init, fold) + } + + #[inline] + fn rfold(self, init: Acc, fold: Fold) -> Acc + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.fold(init, fold) + } + + #[inline] + #[rustc_inherit_overflow_checks] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.advance_by(n) + } +} + +// Note: It may be tempting to impl DoubleEndedIterator for Take. +// One must fight that temptation since such implementation wouldn’t be correct +// because we have no way to return value of nth invocation of repeater followed +// by n-1st without remembering all results. + +#[stable(feature = "exact_size_take_repeat", since = "1.82.0")] +impl ExactSizeIterator for Take> { + fn len(&self) -> usize { + self.n + } +} + +#[stable(feature = "exact_size_take_repeat", since = "1.82.0")] +impl A, A> ExactSizeIterator for Take> { + fn len(&self) -> usize { + self.n + } +} diff --git a/CoqOfRust/core/iter/adapters/take_while.rs b/CoqOfRust/core/iter/adapters/take_while.rs new file mode 100644 index 000000000..06028ea98 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/take_while.rs @@ -0,0 +1,131 @@ +use crate::fmt; +use crate::iter::adapters::SourceIter; +use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused}; +use crate::num::NonZero; +use crate::ops::{ControlFlow, Try}; + +/// An iterator that only accepts elements while `predicate` returns `true`. +/// +/// This `struct` is created by the [`take_while`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`take_while`]: Iterator::take_while +/// [`Iterator`]: trait.Iterator.html +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] +pub struct TakeWhile { + iter: I, + flag: bool, + predicate: P, +} + +impl TakeWhile { + pub(in crate::iter) fn new(iter: I, predicate: P) -> TakeWhile { + TakeWhile { iter, flag: false, predicate } + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for TakeWhile { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TakeWhile").field("iter", &self.iter).field("flag", &self.flag).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for TakeWhile +where + P: FnMut(&I::Item) -> bool, +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + if self.flag { + None + } else { + let x = self.iter.next()?; + if (self.predicate)(&x) { + Some(x) + } else { + self.flag = true; + None + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.flag { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } + } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + fn check<'a, T, Acc, R: Try>( + flag: &'a mut bool, + p: &'a mut impl FnMut(&T) -> bool, + mut fold: impl FnMut(Acc, T) -> R + 'a, + ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { + move |acc, x| { + if p(&x) { + ControlFlow::from_try(fold(acc, x)) + } else { + *flag = true; + ControlFlow::Break(try { acc }) + } + } + } + + if self.flag { + try { init } + } else { + let flag = &mut self.flag; + let p = &mut self.predicate; + self.iter.try_fold(init, check(flag, p, fold)).into_try() + } + } + + impl_fold_via_try_fold! { fold -> try_fold } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for TakeWhile +where + I: FusedIterator, + P: FnMut(&I::Item) -> bool, +{ +} + +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for TakeWhile {} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for TakeWhile +where + I: SourceIter, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for TakeWhile { + const EXPAND_BY: Option> = I::EXPAND_BY; + const MERGE_BY: Option> = I::MERGE_BY; +} diff --git a/CoqOfRust/core/iter/adapters/zip.rs b/CoqOfRust/core/iter/adapters/zip.rs new file mode 100644 index 000000000..0c3881159 --- /dev/null +++ b/CoqOfRust/core/iter/adapters/zip.rs @@ -0,0 +1,695 @@ +use crate::cmp; +use crate::fmt::{self, Debug}; +use crate::iter::{ + FusedIterator, InPlaceIterable, SourceIter, TrustedFused, TrustedLen, UncheckedIterator, +}; +use crate::num::NonZero; + +/// An iterator that iterates two other iterators simultaneously. +/// +/// This `struct` is created by [`zip`] or [`Iterator::zip`]. +/// See their documentation for more. +#[derive(Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Zip { + a: A, + b: B, + // index, len and a_len are only used by the specialized version of zip + index: usize, + len: usize, + a_len: usize, +} +impl Zip { + pub(in crate::iter) fn new(a: A, b: B) -> Zip { + ZipImpl::new(a, b) + } + fn super_nth(&mut self, mut n: usize) -> Option<(A::Item, B::Item)> { + while let Some(x) = Iterator::next(self) { + if n == 0 { + return Some(x); + } + n -= 1; + } + None + } +} + +/// Converts the arguments to iterators and zips them. +/// +/// See the documentation of [`Iterator::zip`] for more. +/// +/// # Examples +/// +/// ``` +/// use std::iter::zip; +/// +/// let xs = [1, 2, 3]; +/// let ys = [4, 5, 6]; +/// +/// let mut iter = zip(xs, ys); +/// +/// assert_eq!(iter.next().unwrap(), (1, 4)); +/// assert_eq!(iter.next().unwrap(), (2, 5)); +/// assert_eq!(iter.next().unwrap(), (3, 6)); +/// assert!(iter.next().is_none()); +/// +/// // Nested zips are also possible: +/// let zs = [7, 8, 9]; +/// +/// let mut iter = zip(zip(xs, ys), zs); +/// +/// assert_eq!(iter.next().unwrap(), ((1, 4), 7)); +/// assert_eq!(iter.next().unwrap(), ((2, 5), 8)); +/// assert_eq!(iter.next().unwrap(), ((3, 6), 9)); +/// assert!(iter.next().is_none()); +/// ``` +#[stable(feature = "iter_zip", since = "1.59.0")] +pub fn zip(a: A, b: B) -> Zip +where + A: IntoIterator, + B: IntoIterator, +{ + ZipImpl::new(a.into_iter(), b.into_iter()) +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Zip +where + A: Iterator, + B: Iterator, +{ + type Item = (A::Item, B::Item); + + #[inline] + fn next(&mut self) -> Option { + ZipImpl::next(self) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + ZipImpl::size_hint(self) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + ZipImpl::nth(self, n) + } + + #[inline] + fn fold(self, init: Acc, f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + ZipImpl::fold(self, init, f) + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccessNoCoerce, + { + // SAFETY: `ZipImpl::__iterator_get_unchecked` has same safety + // requirements as `Iterator::__iterator_get_unchecked`. + unsafe { ZipImpl::get_unchecked(self, idx) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Zip +where + A: DoubleEndedIterator + ExactSizeIterator, + B: DoubleEndedIterator + ExactSizeIterator, +{ + #[inline] + fn next_back(&mut self) -> Option<(A::Item, B::Item)> { + ZipImpl::next_back(self) + } +} + +// Zip specialization trait +#[doc(hidden)] +trait ZipImpl { + type Item; + fn new(a: A, b: B) -> Self; + fn next(&mut self) -> Option; + fn size_hint(&self) -> (usize, Option); + fn nth(&mut self, n: usize) -> Option; + fn next_back(&mut self) -> Option + where + A: DoubleEndedIterator + ExactSizeIterator, + B: DoubleEndedIterator + ExactSizeIterator; + fn fold(self, init: Acc, f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc; + // This has the same safety requirements as `Iterator::__iterator_get_unchecked` + unsafe fn get_unchecked(&mut self, idx: usize) -> ::Item + where + Self: Iterator + TrustedRandomAccessNoCoerce; +} + +// Work around limitations of specialization, requiring `default` impls to be repeated +// in intermediary impls. +macro_rules! zip_impl_general_defaults { + () => { + default fn new(a: A, b: B) -> Self { + Zip { + a, + b, + index: 0, // unused + len: 0, // unused + a_len: 0, // unused + } + } + + #[inline] + default fn next(&mut self) -> Option<(A::Item, B::Item)> { + let x = self.a.next()?; + let y = self.b.next()?; + Some((x, y)) + } + + #[inline] + default fn nth(&mut self, n: usize) -> Option { + self.super_nth(n) + } + + #[inline] + default fn next_back(&mut self) -> Option<(A::Item, B::Item)> + where + A: DoubleEndedIterator + ExactSizeIterator, + B: DoubleEndedIterator + ExactSizeIterator, + { + // The function body below only uses `self.a/b.len()` and `self.a/b.next_back()` + // and doesn’t call `next_back` too often, so this implementation is safe in + // the `TrustedRandomAccessNoCoerce` specialization + + let a_sz = self.a.len(); + let b_sz = self.b.len(); + if a_sz != b_sz { + // Adjust a, b to equal length + if a_sz > b_sz { + for _ in 0..a_sz - b_sz { + self.a.next_back(); + } + } else { + for _ in 0..b_sz - a_sz { + self.b.next_back(); + } + } + } + match (self.a.next_back(), self.b.next_back()) { + (Some(x), Some(y)) => Some((x, y)), + (None, None) => None, + _ => unreachable!(), + } + } + }; +} + +// General Zip impl +#[doc(hidden)] +impl ZipImpl for Zip +where + A: Iterator, + B: Iterator, +{ + type Item = (A::Item, B::Item); + + zip_impl_general_defaults! {} + + #[inline] + default fn size_hint(&self) -> (usize, Option) { + let (a_lower, a_upper) = self.a.size_hint(); + let (b_lower, b_upper) = self.b.size_hint(); + + let lower = cmp::min(a_lower, b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => Some(cmp::min(x, y)), + (Some(x), None) => Some(x), + (None, Some(y)) => Some(y), + (None, None) => None, + }; + + (lower, upper) + } + + default unsafe fn get_unchecked(&mut self, _idx: usize) -> ::Item + where + Self: TrustedRandomAccessNoCoerce, + { + unreachable!("Always specialized"); + } + + #[inline] + default fn fold(self, init: Acc, f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + SpecFold::spec_fold(self, init, f) + } +} + +#[doc(hidden)] +impl ZipImpl for Zip +where + A: TrustedRandomAccessNoCoerce + Iterator, + B: TrustedRandomAccessNoCoerce + Iterator, +{ + zip_impl_general_defaults! {} + + #[inline] + default fn size_hint(&self) -> (usize, Option) { + let size = cmp::min(self.a.size(), self.b.size()); + (size, Some(size)) + } + + #[inline] + unsafe fn get_unchecked(&mut self, idx: usize) -> ::Item { + let idx = self.index + idx; + // SAFETY: the caller must uphold the contract for + // `Iterator::__iterator_get_unchecked`. + unsafe { (self.a.__iterator_get_unchecked(idx), self.b.__iterator_get_unchecked(idx)) } + } + + #[inline] + fn fold(mut self, init: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let mut accum = init; + let len = ZipImpl::size_hint(&self).0; + for i in 0..len { + // SAFETY: since Self: TrustedRandomAccessNoCoerce we can trust the size-hint to + // calculate the length and then use that to do unchecked iteration. + // fold consumes the iterator so we don't need to fixup any state. + unsafe { + accum = f(accum, self.get_unchecked(i)); + } + } + accum + } +} + +#[doc(hidden)] +impl ZipImpl for Zip +where + A: TrustedRandomAccess + Iterator, + B: TrustedRandomAccess + Iterator, +{ + fn new(a: A, b: B) -> Self { + let a_len = a.size(); + let len = cmp::min(a_len, b.size()); + Zip { a, b, index: 0, len, a_len } + } + + #[inline] + fn next(&mut self) -> Option<(A::Item, B::Item)> { + if self.index < self.len { + let i = self.index; + // since get_unchecked executes code which can panic we increment the counters beforehand + // so that the same index won't be accessed twice, as required by TrustedRandomAccess + self.index += 1; + // SAFETY: `i` is smaller than `self.len`, thus smaller than `self.a.len()` and `self.b.len()` + unsafe { + Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i))) + } + } else if A::MAY_HAVE_SIDE_EFFECT && self.index < self.a_len { + let i = self.index; + // as above, increment before executing code that may panic + self.index += 1; + self.len += 1; + // match the base implementation's potential side effects + // SAFETY: we just checked that `i` < `self.a.len()` + unsafe { + self.a.__iterator_get_unchecked(i); + } + None + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len - self.index; + (len, Some(len)) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + let delta = cmp::min(n, self.len - self.index); + let end = self.index + delta; + while self.index < end { + let i = self.index; + // since get_unchecked executes code which can panic we increment the counters beforehand + // so that the same index won't be accessed twice, as required by TrustedRandomAccess + self.index += 1; + if A::MAY_HAVE_SIDE_EFFECT { + // SAFETY: the usage of `cmp::min` to calculate `delta` + // ensures that `end` is smaller than or equal to `self.len`, + // so `i` is also smaller than `self.len`. + unsafe { + self.a.__iterator_get_unchecked(i); + } + } + if B::MAY_HAVE_SIDE_EFFECT { + // SAFETY: same as above. + unsafe { + self.b.__iterator_get_unchecked(i); + } + } + } + + self.super_nth(n - delta) + } + + #[inline] + fn next_back(&mut self) -> Option<(A::Item, B::Item)> + where + A: DoubleEndedIterator + ExactSizeIterator, + B: DoubleEndedIterator + ExactSizeIterator, + { + if A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT { + let sz_a = self.a.size(); + let sz_b = self.b.size(); + // Adjust a, b to equal length, make sure that only the first call + // of `next_back` does this, otherwise we will break the restriction + // on calls to `self.next_back()` after calling `get_unchecked()`. + if sz_a != sz_b { + let sz_a = self.a.size(); + if A::MAY_HAVE_SIDE_EFFECT && sz_a > self.len { + for _ in 0..sz_a - self.len { + // since next_back() may panic we increment the counters beforehand + // to keep Zip's state in sync with the underlying iterator source + self.a_len -= 1; + self.a.next_back(); + } + debug_assert_eq!(self.a_len, self.len); + } + let sz_b = self.b.size(); + if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len { + for _ in 0..sz_b - self.len { + self.b.next_back(); + } + } + } + } + if self.index < self.len { + // since get_unchecked executes code which can panic we increment the counters beforehand + // so that the same index won't be accessed twice, as required by TrustedRandomAccess + self.len -= 1; + self.a_len -= 1; + let i = self.len; + // SAFETY: `i` is smaller than the previous value of `self.len`, + // which is also smaller than or equal to `self.a.len()` and `self.b.len()` + unsafe { + Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i))) + } + } else { + None + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Zip +where + A: ExactSizeIterator, + B: ExactSizeIterator, +{ +} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for Zip +where + A: TrustedRandomAccess, + B: TrustedRandomAccess, +{ +} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccessNoCoerce for Zip +where + A: TrustedRandomAccessNoCoerce, + B: TrustedRandomAccessNoCoerce, +{ + const MAY_HAVE_SIDE_EFFECT: bool = A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT; +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Zip +where + A: FusedIterator, + B: FusedIterator, +{ +} + +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Zip +where + A: TrustedFused, + B: TrustedFused, +{ +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Zip +where + A: TrustedLen, + B: TrustedLen, +{ +} + +impl UncheckedIterator for Zip +where + A: UncheckedIterator, + B: UncheckedIterator, +{ +} + +// Arbitrarily selects the left side of the zip iteration as extractable "source" +// it would require negative trait bounds to be able to try both +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Zip +where + A: SourceIter, +{ + type Source = A::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut A::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.a) } + } +} + +// Since SourceIter forwards the left hand side we do the same here +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for Zip { + const EXPAND_BY: Option> = A::EXPAND_BY; + const MERGE_BY: Option> = A::MERGE_BY; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for Zip { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ZipFmt::fmt(self, f) + } +} + +trait ZipFmt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result; +} + +impl ZipFmt for Zip { + default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Zip").field("a", &self.a).field("b", &self.b).finish() + } +} + +impl ZipFmt + for Zip +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // It's *not safe* to call fmt on the contained iterators, since once + // we start iterating they're in strange, potentially unsafe, states. + f.debug_struct("Zip").finish() + } +} + +/// An iterator whose items are random-accessible efficiently +/// +/// # Safety +/// +/// The iterator's `size_hint` must be exact and cheap to call. +/// +/// `TrustedRandomAccessNoCoerce::size` may not be overridden. +/// +/// All subtypes and all supertypes of `Self` must also implement `TrustedRandomAccess`. +/// In particular, this means that types with non-invariant parameters usually can not have +/// an impl for `TrustedRandomAccess` that depends on any trait bounds on such parameters, except +/// for bounds that come from the respective struct/enum definition itself, or bounds involving +/// traits that themselves come with a guarantee similar to this one. +/// +/// If `Self: ExactSizeIterator` then `self.len()` must always produce results consistent +/// with `self.size()`. +/// +/// If `Self: Iterator`, then `::__iterator_get_unchecked(&mut self, idx)` +/// must be safe to call provided the following conditions are met. +/// +/// 1. `0 <= idx` and `idx < self.size()`. +/// 2. If `Self: !Clone`, then `self.__iterator_get_unchecked(idx)` is never called with the same +/// index on `self` more than once. +/// 3. After `self.__iterator_get_unchecked(idx)` has been called, then `self.next_back()` will +/// only be called at most `self.size() - idx - 1` times. If `Self: Clone` and `self` is cloned, +/// then this number is calculated for `self` and its clone individually, +/// but `self.next_back()` calls that happened before the cloning count for both `self` and the clone. +/// 4. After `self.__iterator_get_unchecked(idx)` has been called, then only the following methods +/// will be called on `self` or on any new clones of `self`: +/// * `std::clone::Clone::clone` +/// * `std::iter::Iterator::size_hint` +/// * `std::iter::DoubleEndedIterator::next_back` +/// * `std::iter::ExactSizeIterator::len` +/// * `std::iter::Iterator::__iterator_get_unchecked` +/// * `std::iter::TrustedRandomAccessNoCoerce::size` +/// 5. If `T` is a subtype of `Self`, then `self` is allowed to be coerced +/// to `T`. If `self` is coerced to `T` after `self.__iterator_get_unchecked(idx)` has already +/// been called, then no methods except for the ones listed under 4. are allowed to be called +/// on the resulting value of type `T`, either. Multiple such coercion steps are allowed. +/// Regarding 2. and 3., the number of times `__iterator_get_unchecked(idx)` or `next_back()` is +/// called on `self` and the resulting value of type `T` (and on further coercion results with +/// sub-subtypes) are added together and their sums must not exceed the specified bounds. +/// +/// Further, given that these conditions are met, it must guarantee that: +/// +/// * It does not change the value returned from `size_hint` +/// * It must be safe to call the methods listed above on `self` after calling +/// `self.__iterator_get_unchecked(idx)`, assuming that the required traits are implemented. +/// * It must also be safe to drop `self` after calling `self.__iterator_get_unchecked(idx)`. +/// * If `T` is a subtype of `Self`, then it must be safe to coerce `self` to `T`. +// +// FIXME: Clarify interaction with SourceIter/InPlaceIterable. Calling `SourceIter::as_inner` +// after `__iterator_get_unchecked` is supposed to be allowed. +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +#[rustc_specialization_trait] +pub unsafe trait TrustedRandomAccess: TrustedRandomAccessNoCoerce {} + +/// Like [`TrustedRandomAccess`] but without any of the requirements / guarantees around +/// coercions to subtypes after `__iterator_get_unchecked` (they aren’t allowed here!), and +/// without the requirement that subtypes / supertypes implement `TrustedRandomAccessNoCoerce`. +/// +/// This trait was created in PR #85874 to fix soundness issue #85873 without performance regressions. +/// It is subject to change as we might want to build a more generally useful (for performance +/// optimizations) and more sophisticated trait or trait hierarchy that replaces or extends +/// [`TrustedRandomAccess`] and `TrustedRandomAccessNoCoerce`. +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +#[rustc_specialization_trait] +pub unsafe trait TrustedRandomAccessNoCoerce: Sized { + // Convenience method. + fn size(&self) -> usize + where + Self: Iterator, + { + self.size_hint().0 + } + /// `true` if getting an iterator element may have side effects. + /// Remember to take inner iterators into account. + const MAY_HAVE_SIDE_EFFECT: bool; +} + +/// Like `Iterator::__iterator_get_unchecked`, but doesn't require the compiler to +/// know that `U: TrustedRandomAccess`. +/// +/// ## Safety +/// +/// Same requirements calling `get_unchecked` directly. +#[doc(hidden)] +#[inline] +pub(in crate::iter::adapters) unsafe fn try_get_unchecked(it: &mut I, idx: usize) -> I::Item +where + I: Iterator, +{ + // SAFETY: the caller must uphold the contract for + // `Iterator::__iterator_get_unchecked`. + unsafe { it.try_get_unchecked(idx) } +} + +unsafe trait SpecTrustedRandomAccess: Iterator { + /// If `Self: TrustedRandomAccess`, it must be safe to call + /// `Iterator::__iterator_get_unchecked(self, index)`. + unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item; +} + +unsafe impl SpecTrustedRandomAccess for I { + default unsafe fn try_get_unchecked(&mut self, _: usize) -> Self::Item { + panic!("Should only be called on TrustedRandomAccess iterators"); + } +} + +unsafe impl SpecTrustedRandomAccess for I { + #[inline] + unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item { + // SAFETY: the caller must uphold the contract for + // `Iterator::__iterator_get_unchecked`. + unsafe { self.__iterator_get_unchecked(index) } + } +} + +trait SpecFold: Iterator { + fn spec_fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B; +} + +impl SpecFold for Zip { + // Adapted from default impl from the Iterator trait + #[inline] + default fn spec_fold(mut self, init: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let mut accum = init; + while let Some(x) = ZipImpl::next(&mut self) { + accum = f(accum, x); + } + accum + } +} + +impl SpecFold for Zip { + #[inline] + fn spec_fold(mut self, init: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let mut accum = init; + loop { + let (upper, more) = if let Some(upper) = ZipImpl::size_hint(&self).1 { + (upper, false) + } else { + // Per TrustedLen contract a None upper bound means more than usize::MAX items + (usize::MAX, true) + }; + + for _ in 0..upper { + let pair = + // SAFETY: TrustedLen guarantees that at least `upper` many items are available + // therefore we know they can't be None + unsafe { (self.a.next().unwrap_unchecked(), self.b.next().unwrap_unchecked()) }; + accum = f(accum, pair); + } + + if !more { + break; + } + } + accum + } +} diff --git a/CoqOfRust/core/iter/mod.rs b/CoqOfRust/core/iter/mod.rs new file mode 100644 index 000000000..635e14e76 --- /dev/null +++ b/CoqOfRust/core/iter/mod.rs @@ -0,0 +1,466 @@ +//! Composable external iteration. +//! +//! If you've found yourself with a collection of some kind, and needed to +//! perform an operation on the elements of said collection, you'll quickly run +//! into 'iterators'. Iterators are heavily used in idiomatic Rust code, so +//! it's worth becoming familiar with them. +//! +//! Before explaining more, let's talk about how this module is structured: +//! +//! # Organization +//! +//! This module is largely organized by type: +//! +//! * [Traits] are the core portion: these traits define what kind of iterators +//! exist and what you can do with them. The methods of these traits are worth +//! putting some extra study time into. +//! * [Functions] provide some helpful ways to create some basic iterators. +//! * [Structs] are often the return types of the various methods on this +//! module's traits. You'll usually want to look at the method that creates +//! the `struct`, rather than the `struct` itself. For more detail about why, +//! see '[Implementing Iterator](#implementing-iterator)'. +//! +//! [Traits]: #traits +//! [Functions]: #functions +//! [Structs]: #structs +//! +//! That's it! Let's dig into iterators. +//! +//! # Iterator +//! +//! The heart and soul of this module is the [`Iterator`] trait. The core of +//! [`Iterator`] looks like this: +//! +//! ``` +//! trait Iterator { +//! type Item; +//! fn next(&mut self) -> Option; +//! } +//! ``` +//! +//! An iterator has a method, [`next`], which when called, returns an +//! [Option]\. Calling [`next`] will return [`Some(Item)`] as long as there +//! are elements, and once they've all been exhausted, will return `None` to +//! indicate that iteration is finished. Individual iterators may choose to +//! resume iteration, and so calling [`next`] again may or may not eventually +//! start returning [`Some(Item)`] again at some point (for example, see [`TryIter`]). +//! +//! [`Iterator`]'s full definition includes a number of other methods as well, +//! but they are default methods, built on top of [`next`], and so you get +//! them for free. +//! +//! Iterators are also composable, and it's common to chain them together to do +//! more complex forms of processing. See the [Adapters](#adapters) section +//! below for more details. +//! +//! [`Some(Item)`]: Some +//! [`next`]: Iterator::next +//! [`TryIter`]: ../../std/sync/mpsc/struct.TryIter.html +//! +//! # The three forms of iteration +//! +//! There are three common methods which can create iterators from a collection: +//! +//! * `iter()`, which iterates over `&T`. +//! * `iter_mut()`, which iterates over `&mut T`. +//! * `into_iter()`, which iterates over `T`. +//! +//! Various things in the standard library may implement one or more of the +//! three, where appropriate. +//! +//! # Implementing Iterator +//! +//! Creating an iterator of your own involves two steps: creating a `struct` to +//! hold the iterator's state, and then implementing [`Iterator`] for that `struct`. +//! This is why there are so many `struct`s in this module: there is one for +//! each iterator and iterator adapter. +//! +//! Let's make an iterator named `Counter` which counts from `1` to `5`: +//! +//! ``` +//! // First, the struct: +//! +//! /// An iterator which counts from one to five +//! struct Counter { +//! count: usize, +//! } +//! +//! // we want our count to start at one, so let's add a new() method to help. +//! // This isn't strictly necessary, but is convenient. Note that we start +//! // `count` at zero, we'll see why in `next()`'s implementation below. +//! impl Counter { +//! fn new() -> Counter { +//! Counter { count: 0 } +//! } +//! } +//! +//! // Then, we implement `Iterator` for our `Counter`: +//! +//! impl Iterator for Counter { +//! // we will be counting with usize +//! type Item = usize; +//! +//! // next() is the only required method +//! fn next(&mut self) -> Option { +//! // Increment our count. This is why we started at zero. +//! self.count += 1; +//! +//! // Check to see if we've finished counting or not. +//! if self.count < 6 { +//! Some(self.count) +//! } else { +//! None +//! } +//! } +//! } +//! +//! // And now we can use it! +//! +//! let mut counter = Counter::new(); +//! +//! assert_eq!(counter.next(), Some(1)); +//! assert_eq!(counter.next(), Some(2)); +//! assert_eq!(counter.next(), Some(3)); +//! assert_eq!(counter.next(), Some(4)); +//! assert_eq!(counter.next(), Some(5)); +//! assert_eq!(counter.next(), None); +//! ``` +//! +//! Calling [`next`] this way gets repetitive. Rust has a construct which can +//! call [`next`] on your iterator, until it reaches `None`. Let's go over that +//! next. +//! +//! Also note that `Iterator` provides a default implementation of methods such as `nth` and `fold` +//! which call `next` internally. However, it is also possible to write a custom implementation of +//! methods like `nth` and `fold` if an iterator can compute them more efficiently without calling +//! `next`. +//! +//! # `for` loops and `IntoIterator` +//! +//! Rust's `for` loop syntax is actually sugar for iterators. Here's a basic +//! example of `for`: +//! +//! ``` +//! let values = vec![1, 2, 3, 4, 5]; +//! +//! for x in values { +//! println!("{x}"); +//! } +//! ``` +//! +//! This will print the numbers one through five, each on their own line. But +//! you'll notice something here: we never called anything on our vector to +//! produce an iterator. What gives? +//! +//! There's a trait in the standard library for converting something into an +//! iterator: [`IntoIterator`]. This trait has one method, [`into_iter`], +//! which converts the thing implementing [`IntoIterator`] into an iterator. +//! Let's take a look at that `for` loop again, and what the compiler converts +//! it into: +//! +//! [`into_iter`]: IntoIterator::into_iter +//! +//! ``` +//! let values = vec![1, 2, 3, 4, 5]; +//! +//! for x in values { +//! println!("{x}"); +//! } +//! ``` +//! +//! Rust de-sugars this into: +//! +//! ``` +//! let values = vec![1, 2, 3, 4, 5]; +//! { +//! let result = match IntoIterator::into_iter(values) { +//! mut iter => loop { +//! let next; +//! match iter.next() { +//! Some(val) => next = val, +//! None => break, +//! }; +//! let x = next; +//! let () = { println!("{x}"); }; +//! }, +//! }; +//! result +//! } +//! ``` +//! +//! First, we call `into_iter()` on the value. Then, we match on the iterator +//! that returns, calling [`next`] over and over until we see a `None`. At +//! that point, we `break` out of the loop, and we're done iterating. +//! +//! There's one more subtle bit here: the standard library contains an +//! interesting implementation of [`IntoIterator`]: +//! +//! ```ignore (only-for-syntax-highlight) +//! impl IntoIterator for I +//! ``` +//! +//! In other words, all [`Iterator`]s implement [`IntoIterator`], by just +//! returning themselves. This means two things: +//! +//! 1. If you're writing an [`Iterator`], you can use it with a `for` loop. +//! 2. If you're creating a collection, implementing [`IntoIterator`] for it +//! will allow your collection to be used with the `for` loop. +//! +//! # Iterating by reference +//! +//! Since [`into_iter()`] takes `self` by value, using a `for` loop to iterate +//! over a collection consumes that collection. Often, you may want to iterate +//! over a collection without consuming it. Many collections offer methods that +//! provide iterators over references, conventionally called `iter()` and +//! `iter_mut()` respectively: +//! +//! ``` +//! let mut values = vec![41]; +//! for x in values.iter_mut() { +//! *x += 1; +//! } +//! for x in values.iter() { +//! assert_eq!(*x, 42); +//! } +//! assert_eq!(values.len(), 1); // `values` is still owned by this function. +//! ``` +//! +//! If a collection type `C` provides `iter()`, it usually also implements +//! `IntoIterator` for `&C`, with an implementation that just calls `iter()`. +//! Likewise, a collection `C` that provides `iter_mut()` generally implements +//! `IntoIterator` for `&mut C` by delegating to `iter_mut()`. This enables a +//! convenient shorthand: +//! +//! ``` +//! let mut values = vec![41]; +//! for x in &mut values { // same as `values.iter_mut()` +//! *x += 1; +//! } +//! for x in &values { // same as `values.iter()` +//! assert_eq!(*x, 42); +//! } +//! assert_eq!(values.len(), 1); +//! ``` +//! +//! While many collections offer `iter()`, not all offer `iter_mut()`. For +//! example, mutating the keys of a [`HashSet`] could put the collection +//! into an inconsistent state if the key hashes change, so this collection +//! only offers `iter()`. +//! +//! [`into_iter()`]: IntoIterator::into_iter +//! [`HashSet`]: ../../std/collections/struct.HashSet.html +//! +//! # Adapters +//! +//! Functions which take an [`Iterator`] and return another [`Iterator`] are +//! often called 'iterator adapters', as they're a form of the 'adapter +//! pattern'. +//! +//! Common iterator adapters include [`map`], [`take`], and [`filter`]. +//! For more, see their documentation. +//! +//! If an iterator adapter panics, the iterator will be in an unspecified (but +//! memory safe) state. This state is also not guaranteed to stay the same +//! across versions of Rust, so you should avoid relying on the exact values +//! returned by an iterator which panicked. +//! +//! [`map`]: Iterator::map +//! [`take`]: Iterator::take +//! [`filter`]: Iterator::filter +//! +//! # Laziness +//! +//! Iterators (and iterator [adapters](#adapters)) are *lazy*. This means that +//! just creating an iterator doesn't _do_ a whole lot. Nothing really happens +//! until you call [`next`]. This is sometimes a source of confusion when +//! creating an iterator solely for its side effects. For example, the [`map`] +//! method calls a closure on each element it iterates over: +//! +//! ``` +//! # #![allow(unused_must_use)] +//! # #![allow(map_unit_fn)] +//! let v = vec![1, 2, 3, 4, 5]; +//! v.iter().map(|x| println!("{x}")); +//! ``` +//! +//! This will not print any values, as we only created an iterator, rather than +//! using it. The compiler will warn us about this kind of behavior: +//! +//! ```text +//! warning: unused result that must be used: iterators are lazy and +//! do nothing unless consumed +//! ``` +//! +//! The idiomatic way to write a [`map`] for its side effects is to use a +//! `for` loop or call the [`for_each`] method: +//! +//! ``` +//! let v = vec![1, 2, 3, 4, 5]; +//! +//! v.iter().for_each(|x| println!("{x}")); +//! // or +//! for x in &v { +//! println!("{x}"); +//! } +//! ``` +//! +//! [`map`]: Iterator::map +//! [`for_each`]: Iterator::for_each +//! +//! Another common way to evaluate an iterator is to use the [`collect`] +//! method to produce a new collection. +//! +//! [`collect`]: Iterator::collect +//! +//! # Infinity +//! +//! Iterators do not have to be finite. As an example, an open-ended range is +//! an infinite iterator: +//! +//! ``` +//! let numbers = 0..; +//! ``` +//! +//! It is common to use the [`take`] iterator adapter to turn an infinite +//! iterator into a finite one: +//! +//! ``` +//! let numbers = 0..; +//! let five_numbers = numbers.take(5); +//! +//! for number in five_numbers { +//! println!("{number}"); +//! } +//! ``` +//! +//! This will print the numbers `0` through `4`, each on their own line. +//! +//! Bear in mind that methods on infinite iterators, even those for which a +//! result can be determined mathematically in finite time, might not terminate. +//! Specifically, methods such as [`min`], which in the general case require +//! traversing every element in the iterator, are likely not to return +//! successfully for any infinite iterators. +//! +//! ```no_run +//! let ones = std::iter::repeat(1); +//! let least = ones.min().unwrap(); // Oh no! An infinite loop! +//! // `ones.min()` causes an infinite loop, so we won't reach this point! +//! println!("The smallest number one is {least}."); +//! ``` +//! +//! [`take`]: Iterator::take +//! [`min`]: Iterator::min + +#![stable(feature = "rust1", since = "1.0.0")] + +// This needs to be up here in order to be usable in the child modules +macro_rules! impl_fold_via_try_fold { + (fold -> try_fold) => { + impl_fold_via_try_fold! { @internal fold -> try_fold } + }; + (rfold -> try_rfold) => { + impl_fold_via_try_fold! { @internal rfold -> try_rfold } + }; + (spec_fold -> spec_try_fold) => { + impl_fold_via_try_fold! { @internal spec_fold -> spec_try_fold } + }; + (spec_rfold -> spec_try_rfold) => { + impl_fold_via_try_fold! { @internal spec_rfold -> spec_try_rfold } + }; + (@internal $fold:ident -> $try_fold:ident) => { + #[inline] + fn $fold(mut self, init: AAA, fold: FFF) -> AAA + where + FFF: FnMut(AAA, Self::Item) -> AAA, + { + use crate::ops::NeverShortCircuit; + + self.$try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0 + } + }; +} + +#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] +pub use self::adapters::ArrayChunks; +#[unstable(feature = "std_internals", issue = "none")] +pub use self::adapters::ByRefSized; +#[stable(feature = "iter_cloned", since = "1.1.0")] +pub use self::adapters::Cloned; +#[stable(feature = "iter_copied", since = "1.36.0")] +pub use self::adapters::Copied; +#[stable(feature = "iterator_flatten", since = "1.29.0")] +pub use self::adapters::Flatten; +#[stable(feature = "iter_map_while", since = "1.57.0")] +pub use self::adapters::MapWhile; +#[unstable(feature = "iter_map_windows", reason = "recently added", issue = "87155")] +pub use self::adapters::MapWindows; +#[unstable(feature = "inplace_iteration", issue = "none")] +pub use self::adapters::SourceIter; +#[stable(feature = "iterator_step_by", since = "1.28.0")] +pub use self::adapters::StepBy; +#[unstable(feature = "trusted_random_access", issue = "none")] +pub use self::adapters::TrustedRandomAccess; +#[unstable(feature = "trusted_random_access", issue = "none")] +pub use self::adapters::TrustedRandomAccessNoCoerce; +#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")] +pub use self::adapters::chain; +pub(crate) use self::adapters::try_process; +#[stable(feature = "iter_zip", since = "1.59.0")] +pub use self::adapters::zip; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::adapters::{ + Chain, Cycle, Enumerate, Filter, FilterMap, FlatMap, Fuse, Inspect, Map, Peekable, Rev, Scan, + Skip, SkipWhile, Take, TakeWhile, Zip, +}; +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +pub use self::adapters::{Intersperse, IntersperseWith}; +#[unstable( + feature = "step_trait", + reason = "likely to be replaced by finer-grained traits", + issue = "42168" +)] +pub use self::range::Step; +#[unstable( + feature = "iter_from_coroutine", + issue = "43122", + reason = "coroutines are unstable" +)] +pub use self::sources::from_coroutine; +#[stable(feature = "iter_empty", since = "1.2.0")] +pub use self::sources::{Empty, empty}; +#[stable(feature = "iter_from_fn", since = "1.34.0")] +pub use self::sources::{FromFn, from_fn}; +#[stable(feature = "iter_once", since = "1.2.0")] +pub use self::sources::{Once, once}; +#[stable(feature = "iter_once_with", since = "1.43.0")] +pub use self::sources::{OnceWith, once_with}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::sources::{Repeat, repeat}; +#[stable(feature = "iter_repeat_n", since = "1.82.0")] +pub use self::sources::{RepeatN, repeat_n}; +#[stable(feature = "iterator_repeat_with", since = "1.28.0")] +pub use self::sources::{RepeatWith, repeat_with}; +#[stable(feature = "iter_successors", since = "1.34.0")] +pub use self::sources::{Successors, successors}; +#[stable(feature = "fused", since = "1.26.0")] +pub use self::traits::FusedIterator; +#[unstable(issue = "none", feature = "inplace_iteration")] +pub use self::traits::InPlaceIterable; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::traits::Iterator; +#[unstable(issue = "none", feature = "trusted_fused")] +pub use self::traits::TrustedFused; +#[unstable(feature = "trusted_len", issue = "37572")] +pub use self::traits::TrustedLen; +#[unstable(feature = "trusted_step", issue = "85731")] +pub use self::traits::TrustedStep; +pub(crate) use self::traits::UncheckedIterator; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::traits::{ + DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, IntoIterator, Product, Sum, +}; + +mod adapters; +mod range; +mod sources; +mod traits; diff --git a/CoqOfRust/core/iter/range.rs b/CoqOfRust/core/iter/range.rs new file mode 100644 index 000000000..4fa719de5 --- /dev/null +++ b/CoqOfRust/core/iter/range.rs @@ -0,0 +1,1397 @@ +use super::{ + FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, TrustedStep, +}; +use crate::ascii::Char as AsciiChar; +use crate::mem; +use crate::net::{Ipv4Addr, Ipv6Addr}; +use crate::num::NonZero; +use crate::ops::{self, Try}; + +// Safety: All invariants are upheld. +macro_rules! unsafe_impl_trusted_step { + ($($type:ty)*) => {$( + #[unstable(feature = "trusted_step", issue = "85731")] + unsafe impl TrustedStep for $type {} + )*}; +} +unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize Ipv4Addr Ipv6Addr]; + +/// Objects that have a notion of *successor* and *predecessor* operations. +/// +/// The *successor* operation moves towards values that compare greater. +/// The *predecessor* operation moves towards values that compare lesser. +#[unstable(feature = "step_trait", issue = "42168")] +pub trait Step: Clone + PartialOrd + Sized { + /// Returns the bounds on the number of *successor* steps required to get from `start` to `end` + /// like [`Iterator::size_hint()`][Iterator::size_hint()]. + /// + /// Returns `(usize::MAX, None)` if the number of steps would overflow `usize`, or is infinite. + /// + /// # Invariants + /// + /// For any `a`, `b`, and `n`: + /// + /// * `steps_between(&a, &b) == (n, Some(n))` if and only if `Step::forward_checked(&a, n) == Some(b)` + /// * `steps_between(&a, &b) == (n, Some(n))` if and only if `Step::backward_checked(&b, n) == Some(a)` + /// * `steps_between(&a, &b) == (n, Some(n))` only if `a <= b` + /// * Corollary: `steps_between(&a, &b) == (0, Some(0))` if and only if `a == b` + /// * `steps_between(&a, &b) == (0, None)` if `a > b` + fn steps_between(start: &Self, end: &Self) -> (usize, Option); + + /// Returns the value that would be obtained by taking the *successor* + /// of `self` `count` times. + /// + /// If this would overflow the range of values supported by `Self`, returns `None`. + /// + /// # Invariants + /// + /// For any `a`, `n`, and `m`: + /// + /// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == Step::forward_checked(a, m).and_then(|x| Step::forward_checked(x, n))` + /// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == try { Step::forward_checked(a, n.checked_add(m)) }` + /// + /// For any `a` and `n`: + /// + /// * `Step::forward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::forward_checked(&x, 1))` + /// * Corollary: `Step::forward_checked(a, 0) == Some(a)` + fn forward_checked(start: Self, count: usize) -> Option; + + /// Returns the value that would be obtained by taking the *successor* + /// of `self` `count` times. + /// + /// If this would overflow the range of values supported by `Self`, + /// this function is allowed to panic, wrap, or saturate. + /// The suggested behavior is to panic when debug assertions are enabled, + /// and to wrap or saturate otherwise. + /// + /// Unsafe code should not rely on the correctness of behavior after overflow. + /// + /// # Invariants + /// + /// For any `a`, `n`, and `m`, where no overflow occurs: + /// + /// * `Step::forward(Step::forward(a, n), m) == Step::forward(a, n + m)` + /// + /// For any `a` and `n`, where no overflow occurs: + /// + /// * `Step::forward_checked(a, n) == Some(Step::forward(a, n))` + /// * `Step::forward(a, n) == (0..n).fold(a, |x, _| Step::forward(x, 1))` + /// * Corollary: `Step::forward(a, 0) == a` + /// * `Step::forward(a, n) >= a` + /// * `Step::backward(Step::forward(a, n), n) == a` + fn forward(start: Self, count: usize) -> Self { + Step::forward_checked(start, count).expect("overflow in `Step::forward`") + } + + /// Returns the value that would be obtained by taking the *successor* + /// of `self` `count` times. + /// + /// # Safety + /// + /// It is undefined behavior for this operation to overflow the + /// range of values supported by `Self`. If you cannot guarantee that this + /// will not overflow, use `forward` or `forward_checked` instead. + /// + /// # Invariants + /// + /// For any `a`: + /// + /// * if there exists `b` such that `b > a`, it is safe to call `Step::forward_unchecked(a, 1)` + /// * if there exists `b`, `n` such that `steps_between(&a, &b) == Some(n)`, + /// it is safe to call `Step::forward_unchecked(a, m)` for any `m <= n`. + /// * Corollary: `Step::forward_unchecked(a, 0)` is always safe. + /// + /// For any `a` and `n`, where no overflow occurs: + /// + /// * `Step::forward_unchecked(a, n)` is equivalent to `Step::forward(a, n)` + unsafe fn forward_unchecked(start: Self, count: usize) -> Self { + Step::forward(start, count) + } + + /// Returns the value that would be obtained by taking the *predecessor* + /// of `self` `count` times. + /// + /// If this would overflow the range of values supported by `Self`, returns `None`. + /// + /// # Invariants + /// + /// For any `a`, `n`, and `m`: + /// + /// * `Step::backward_checked(a, n).and_then(|x| Step::backward_checked(x, m)) == n.checked_add(m).and_then(|x| Step::backward_checked(a, x))` + /// * `Step::backward_checked(a, n).and_then(|x| Step::backward_checked(x, m)) == try { Step::backward_checked(a, n.checked_add(m)?) }` + /// + /// For any `a` and `n`: + /// + /// * `Step::backward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::backward_checked(x, 1))` + /// * Corollary: `Step::backward_checked(a, 0) == Some(a)` + fn backward_checked(start: Self, count: usize) -> Option; + + /// Returns the value that would be obtained by taking the *predecessor* + /// of `self` `count` times. + /// + /// If this would overflow the range of values supported by `Self`, + /// this function is allowed to panic, wrap, or saturate. + /// The suggested behavior is to panic when debug assertions are enabled, + /// and to wrap or saturate otherwise. + /// + /// Unsafe code should not rely on the correctness of behavior after overflow. + /// + /// # Invariants + /// + /// For any `a`, `n`, and `m`, where no overflow occurs: + /// + /// * `Step::backward(Step::backward(a, n), m) == Step::backward(a, n + m)` + /// + /// For any `a` and `n`, where no overflow occurs: + /// + /// * `Step::backward_checked(a, n) == Some(Step::backward(a, n))` + /// * `Step::backward(a, n) == (0..n).fold(a, |x, _| Step::backward(x, 1))` + /// * Corollary: `Step::backward(a, 0) == a` + /// * `Step::backward(a, n) <= a` + /// * `Step::forward(Step::backward(a, n), n) == a` + fn backward(start: Self, count: usize) -> Self { + Step::backward_checked(start, count).expect("overflow in `Step::backward`") + } + + /// Returns the value that would be obtained by taking the *predecessor* + /// of `self` `count` times. + /// + /// # Safety + /// + /// It is undefined behavior for this operation to overflow the + /// range of values supported by `Self`. If you cannot guarantee that this + /// will not overflow, use `backward` or `backward_checked` instead. + /// + /// # Invariants + /// + /// For any `a`: + /// + /// * if there exists `b` such that `b < a`, it is safe to call `Step::backward_unchecked(a, 1)` + /// * if there exists `b`, `n` such that `steps_between(&b, &a) == (n, Some(n))`, + /// it is safe to call `Step::backward_unchecked(a, m)` for any `m <= n`. + /// * Corollary: `Step::backward_unchecked(a, 0)` is always safe. + /// + /// For any `a` and `n`, where no overflow occurs: + /// + /// * `Step::backward_unchecked(a, n)` is equivalent to `Step::backward(a, n)` + unsafe fn backward_unchecked(start: Self, count: usize) -> Self { + Step::backward(start, count) + } +} + +// Separate impls for signed ranges because the distance within a signed range can be larger +// than the signed::MAX value. Therefore `as` casting to the signed type would be incorrect. +macro_rules! step_signed_methods { + ($unsigned: ty) => { + #[inline] + unsafe fn forward_unchecked(start: Self, n: usize) -> Self { + // SAFETY: the caller has to guarantee that `start + n` doesn't overflow. + unsafe { start.checked_add_unsigned(n as $unsigned).unwrap_unchecked() } + } + + #[inline] + unsafe fn backward_unchecked(start: Self, n: usize) -> Self { + // SAFETY: the caller has to guarantee that `start - n` doesn't overflow. + unsafe { start.checked_sub_unsigned(n as $unsigned).unwrap_unchecked() } + } + }; +} + +macro_rules! step_unsigned_methods { + () => { + #[inline] + unsafe fn forward_unchecked(start: Self, n: usize) -> Self { + // SAFETY: the caller has to guarantee that `start + n` doesn't overflow. + unsafe { start.unchecked_add(n as Self) } + } + + #[inline] + unsafe fn backward_unchecked(start: Self, n: usize) -> Self { + // SAFETY: the caller has to guarantee that `start - n` doesn't overflow. + unsafe { start.unchecked_sub(n as Self) } + } + }; +} + +// These are still macro-generated because the integer literals resolve to different types. +macro_rules! step_identical_methods { + () => { + #[inline] + #[allow(arithmetic_overflow)] + #[rustc_inherit_overflow_checks] + fn forward(start: Self, n: usize) -> Self { + // In debug builds, trigger a panic on overflow. + // This should optimize completely out in release builds. + if Self::forward_checked(start, n).is_none() { + let _ = Self::MAX + 1; + } + // Do wrapping math to allow e.g. `Step::forward(-128i8, 255)`. + start.wrapping_add(n as Self) + } + + #[inline] + #[allow(arithmetic_overflow)] + #[rustc_inherit_overflow_checks] + fn backward(start: Self, n: usize) -> Self { + // In debug builds, trigger a panic on overflow. + // This should optimize completely out in release builds. + if Self::backward_checked(start, n).is_none() { + let _ = Self::MIN - 1; + } + // Do wrapping math to allow e.g. `Step::backward(127i8, 255)`. + start.wrapping_sub(n as Self) + } + }; +} + +macro_rules! step_integer_impls { + { + narrower than or same width as usize: + $( [ $u_narrower:ident $i_narrower:ident ] ),+; + wider than usize: + $( [ $u_wider:ident $i_wider:ident ] ),+; + } => { + $( + #[allow(unreachable_patterns)] + #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] + impl Step for $u_narrower { + step_identical_methods!(); + step_unsigned_methods!(); + + #[inline] + fn steps_between(start: &Self, end: &Self) -> (usize, Option) { + if *start <= *end { + // This relies on $u_narrower <= usize + let steps = (*end - *start) as usize; + (steps, Some(steps)) + } else { + (0, None) + } + } + + #[inline] + fn forward_checked(start: Self, n: usize) -> Option { + match Self::try_from(n) { + Ok(n) => start.checked_add(n), + Err(_) => None, // if n is out of range, `unsigned_start + n` is too + } + } + + #[inline] + fn backward_checked(start: Self, n: usize) -> Option { + match Self::try_from(n) { + Ok(n) => start.checked_sub(n), + Err(_) => None, // if n is out of range, `unsigned_start - n` is too + } + } + } + + #[allow(unreachable_patterns)] + #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] + impl Step for $i_narrower { + step_identical_methods!(); + step_signed_methods!($u_narrower); + + #[inline] + fn steps_between(start: &Self, end: &Self) -> (usize, Option) { + if *start <= *end { + // This relies on $i_narrower <= usize + // + // Casting to isize extends the width but preserves the sign. + // Use wrapping_sub in isize space and cast to usize to compute + // the difference that might not fit inside the range of isize. + let steps = (*end as isize).wrapping_sub(*start as isize) as usize; + (steps, Some(steps)) + } else { + (0, None) + } + } + + #[inline] + fn forward_checked(start: Self, n: usize) -> Option { + match $u_narrower::try_from(n) { + Ok(n) => { + // Wrapping handles cases like + // `Step::forward(-120_i8, 200) == Some(80_i8)`, + // even though 200 is out of range for i8. + let wrapped = start.wrapping_add(n as Self); + if wrapped >= start { + Some(wrapped) + } else { + None // Addition overflowed + } + } + // If n is out of range of e.g. u8, + // then it is bigger than the entire range for i8 is wide + // so `any_i8 + n` necessarily overflows i8. + Err(_) => None, + } + } + + #[inline] + fn backward_checked(start: Self, n: usize) -> Option { + match $u_narrower::try_from(n) { + Ok(n) => { + // Wrapping handles cases like + // `Step::forward(-120_i8, 200) == Some(80_i8)`, + // even though 200 is out of range for i8. + let wrapped = start.wrapping_sub(n as Self); + if wrapped <= start { + Some(wrapped) + } else { + None // Subtraction overflowed + } + } + // If n is out of range of e.g. u8, + // then it is bigger than the entire range for i8 is wide + // so `any_i8 - n` necessarily overflows i8. + Err(_) => None, + } + } + } + )+ + + $( + #[allow(unreachable_patterns)] + #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] + impl Step for $u_wider { + step_identical_methods!(); + step_unsigned_methods!(); + + #[inline] + fn steps_between(start: &Self, end: &Self) -> (usize, Option) { + if *start <= *end { + if let Ok(steps) = usize::try_from(*end - *start) { + (steps, Some(steps)) + } else { + (usize::MAX, None) + } + } else { + (0, None) + } + } + + #[inline] + fn forward_checked(start: Self, n: usize) -> Option { + start.checked_add(n as Self) + } + + #[inline] + fn backward_checked(start: Self, n: usize) -> Option { + start.checked_sub(n as Self) + } + } + + #[allow(unreachable_patterns)] + #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] + impl Step for $i_wider { + step_identical_methods!(); + step_signed_methods!($u_wider); + + #[inline] + fn steps_between(start: &Self, end: &Self) -> (usize, Option) { + if *start <= *end { + match end.checked_sub(*start) { + Some(result) => { + if let Ok(steps) = usize::try_from(result) { + (steps, Some(steps)) + } else { + (usize::MAX, None) + } + } + // If the difference is too big for e.g. i128, + // it's also gonna be too big for usize with fewer bits. + None => (usize::MAX, None), + } + } else { + (0, None) + } + } + + #[inline] + fn forward_checked(start: Self, n: usize) -> Option { + start.checked_add(n as Self) + } + + #[inline] + fn backward_checked(start: Self, n: usize) -> Option { + start.checked_sub(n as Self) + } + } + )+ + }; +} + +#[cfg(target_pointer_width = "64")] +step_integer_impls! { + narrower than or same width as usize: [u8 i8], [u16 i16], [u32 i32], [u64 i64], [usize isize]; + wider than usize: [u128 i128]; +} + +#[cfg(target_pointer_width = "32")] +step_integer_impls! { + narrower than or same width as usize: [u8 i8], [u16 i16], [u32 i32], [usize isize]; + wider than usize: [u64 i64], [u128 i128]; +} + +#[cfg(target_pointer_width = "16")] +step_integer_impls! { + narrower than or same width as usize: [u8 i8], [u16 i16], [usize isize]; + wider than usize: [u32 i32], [u64 i64], [u128 i128]; +} + +#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] +impl Step for char { + #[inline] + fn steps_between(&start: &char, &end: &char) -> (usize, Option) { + let start = start as u32; + let end = end as u32; + if start <= end { + let count = end - start; + if start < 0xD800 && 0xE000 <= end { + if let Ok(steps) = usize::try_from(count - 0x800) { + (steps, Some(steps)) + } else { + (usize::MAX, None) + } + } else { + if let Ok(steps) = usize::try_from(count) { + (steps, Some(steps)) + } else { + (usize::MAX, None) + } + } + } else { + (0, None) + } + } + + #[inline] + fn forward_checked(start: char, count: usize) -> Option { + let start = start as u32; + let mut res = Step::forward_checked(start, count)?; + if start < 0xD800 && 0xD800 <= res { + res = Step::forward_checked(res, 0x800)?; + } + if res <= char::MAX as u32 { + // SAFETY: res is a valid unicode scalar + // (below 0x110000 and not in 0xD800..0xE000) + Some(unsafe { char::from_u32_unchecked(res) }) + } else { + None + } + } + + #[inline] + fn backward_checked(start: char, count: usize) -> Option { + let start = start as u32; + let mut res = Step::backward_checked(start, count)?; + if start >= 0xE000 && 0xE000 > res { + res = Step::backward_checked(res, 0x800)?; + } + // SAFETY: res is a valid unicode scalar + // (below 0x110000 and not in 0xD800..0xE000) + Some(unsafe { char::from_u32_unchecked(res) }) + } + + #[inline] + unsafe fn forward_unchecked(start: char, count: usize) -> char { + let start = start as u32; + // SAFETY: the caller must guarantee that this doesn't overflow + // the range of values for a char. + let mut res = unsafe { Step::forward_unchecked(start, count) }; + if start < 0xD800 && 0xD800 <= res { + // SAFETY: the caller must guarantee that this doesn't overflow + // the range of values for a char. + res = unsafe { Step::forward_unchecked(res, 0x800) }; + } + // SAFETY: because of the previous contract, this is guaranteed + // by the caller to be a valid char. + unsafe { char::from_u32_unchecked(res) } + } + + #[inline] + unsafe fn backward_unchecked(start: char, count: usize) -> char { + let start = start as u32; + // SAFETY: the caller must guarantee that this doesn't overflow + // the range of values for a char. + let mut res = unsafe { Step::backward_unchecked(start, count) }; + if start >= 0xE000 && 0xE000 > res { + // SAFETY: the caller must guarantee that this doesn't overflow + // the range of values for a char. + res = unsafe { Step::backward_unchecked(res, 0x800) }; + } + // SAFETY: because of the previous contract, this is guaranteed + // by the caller to be a valid char. + unsafe { char::from_u32_unchecked(res) } + } +} + +#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] +impl Step for AsciiChar { + #[inline] + fn steps_between(&start: &AsciiChar, &end: &AsciiChar) -> (usize, Option) { + Step::steps_between(&start.to_u8(), &end.to_u8()) + } + + #[inline] + fn forward_checked(start: AsciiChar, count: usize) -> Option { + let end = Step::forward_checked(start.to_u8(), count)?; + AsciiChar::from_u8(end) + } + + #[inline] + fn backward_checked(start: AsciiChar, count: usize) -> Option { + let end = Step::backward_checked(start.to_u8(), count)?; + + // SAFETY: Values below that of a valid ASCII character are also valid ASCII + Some(unsafe { AsciiChar::from_u8_unchecked(end) }) + } + + #[inline] + unsafe fn forward_unchecked(start: AsciiChar, count: usize) -> AsciiChar { + // SAFETY: Caller asserts that result is a valid ASCII character, + // and therefore it is a valid u8. + let end = unsafe { Step::forward_unchecked(start.to_u8(), count) }; + + // SAFETY: Caller asserts that result is a valid ASCII character. + unsafe { AsciiChar::from_u8_unchecked(end) } + } + + #[inline] + unsafe fn backward_unchecked(start: AsciiChar, count: usize) -> AsciiChar { + // SAFETY: Caller asserts that result is a valid ASCII character, + // and therefore it is a valid u8. + let end = unsafe { Step::backward_unchecked(start.to_u8(), count) }; + + // SAFETY: Caller asserts that result is a valid ASCII character. + unsafe { AsciiChar::from_u8_unchecked(end) } + } +} + +#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] +impl Step for Ipv4Addr { + #[inline] + fn steps_between(&start: &Ipv4Addr, &end: &Ipv4Addr) -> (usize, Option) { + u32::steps_between(&start.to_bits(), &end.to_bits()) + } + + #[inline] + fn forward_checked(start: Ipv4Addr, count: usize) -> Option { + u32::forward_checked(start.to_bits(), count).map(Ipv4Addr::from_bits) + } + + #[inline] + fn backward_checked(start: Ipv4Addr, count: usize) -> Option { + u32::backward_checked(start.to_bits(), count).map(Ipv4Addr::from_bits) + } + + #[inline] + unsafe fn forward_unchecked(start: Ipv4Addr, count: usize) -> Ipv4Addr { + // SAFETY: Since u32 and Ipv4Addr are losslessly convertible, + // this is as safe as the u32 version. + Ipv4Addr::from_bits(unsafe { u32::forward_unchecked(start.to_bits(), count) }) + } + + #[inline] + unsafe fn backward_unchecked(start: Ipv4Addr, count: usize) -> Ipv4Addr { + // SAFETY: Since u32 and Ipv4Addr are losslessly convertible, + // this is as safe as the u32 version. + Ipv4Addr::from_bits(unsafe { u32::backward_unchecked(start.to_bits(), count) }) + } +} + +#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] +impl Step for Ipv6Addr { + #[inline] + fn steps_between(&start: &Ipv6Addr, &end: &Ipv6Addr) -> (usize, Option) { + u128::steps_between(&start.to_bits(), &end.to_bits()) + } + + #[inline] + fn forward_checked(start: Ipv6Addr, count: usize) -> Option { + u128::forward_checked(start.to_bits(), count).map(Ipv6Addr::from_bits) + } + + #[inline] + fn backward_checked(start: Ipv6Addr, count: usize) -> Option { + u128::backward_checked(start.to_bits(), count).map(Ipv6Addr::from_bits) + } + + #[inline] + unsafe fn forward_unchecked(start: Ipv6Addr, count: usize) -> Ipv6Addr { + // SAFETY: Since u128 and Ipv6Addr are losslessly convertible, + // this is as safe as the u128 version. + Ipv6Addr::from_bits(unsafe { u128::forward_unchecked(start.to_bits(), count) }) + } + + #[inline] + unsafe fn backward_unchecked(start: Ipv6Addr, count: usize) -> Ipv6Addr { + // SAFETY: Since u128 and Ipv6Addr are losslessly convertible, + // this is as safe as the u128 version. + Ipv6Addr::from_bits(unsafe { u128::backward_unchecked(start.to_bits(), count) }) + } +} + +macro_rules! range_exact_iter_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl ExactSizeIterator for ops::Range<$t> { } + )*) +} + +/// Safety: This macro must only be used on types that are `Copy` and result in ranges +/// which have an exact `size_hint()` where the upper bound must not be `None`. +macro_rules! unsafe_range_trusted_random_access_impl { + ($($t:ty)*) => ($( + #[doc(hidden)] + #[unstable(feature = "trusted_random_access", issue = "none")] + unsafe impl TrustedRandomAccess for ops::Range<$t> {} + + #[doc(hidden)] + #[unstable(feature = "trusted_random_access", issue = "none")] + unsafe impl TrustedRandomAccessNoCoerce for ops::Range<$t> { + const MAY_HAVE_SIDE_EFFECT: bool = false; + } + )*) +} + +macro_rules! range_incl_exact_iter_impl { + ($($t:ty)*) => ($( + #[stable(feature = "inclusive_range", since = "1.26.0")] + impl ExactSizeIterator for ops::RangeInclusive<$t> { } + )*) +} + +/// Specialization implementations for `Range`. +trait RangeIteratorImpl { + type Item; + + // Iterator + fn spec_next(&mut self) -> Option; + fn spec_nth(&mut self, n: usize) -> Option; + fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZero>; + + // DoubleEndedIterator + fn spec_next_back(&mut self) -> Option; + fn spec_nth_back(&mut self, n: usize) -> Option; + fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZero>; +} + +impl RangeIteratorImpl for ops::Range { + type Item = A; + + #[inline] + default fn spec_next(&mut self) -> Option { + if self.start < self.end { + let n = + Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld"); + Some(mem::replace(&mut self.start, n)) + } else { + None + } + } + + #[inline] + default fn spec_nth(&mut self, n: usize) -> Option { + if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) { + if plus_n < self.end { + self.start = + Step::forward_checked(plus_n.clone(), 1).expect("`Step` invariants not upheld"); + return Some(plus_n); + } + } + + self.start = self.end.clone(); + None + } + + #[inline] + default fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZero> { + let steps = Step::steps_between(&self.start, &self.end); + let available = steps.1.unwrap_or(steps.0); + + let taken = available.min(n); + + self.start = + Step::forward_checked(self.start.clone(), taken).expect("`Step` invariants not upheld"); + + NonZero::new(n - taken).map_or(Ok(()), Err) + } + + #[inline] + default fn spec_next_back(&mut self) -> Option { + if self.start < self.end { + self.end = + Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld"); + Some(self.end.clone()) + } else { + None + } + } + + #[inline] + default fn spec_nth_back(&mut self, n: usize) -> Option { + if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) { + if minus_n > self.start { + self.end = + Step::backward_checked(minus_n, 1).expect("`Step` invariants not upheld"); + return Some(self.end.clone()); + } + } + + self.end = self.start.clone(); + None + } + + #[inline] + default fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + let steps = Step::steps_between(&self.start, &self.end); + let available = steps.1.unwrap_or(steps.0); + + let taken = available.min(n); + + self.end = + Step::backward_checked(self.end.clone(), taken).expect("`Step` invariants not upheld"); + + NonZero::new(n - taken).map_or(Ok(()), Err) + } +} + +impl RangeIteratorImpl for ops::Range { + #[inline] + fn spec_next(&mut self) -> Option { + if self.start < self.end { + let old = self.start; + // SAFETY: just checked precondition + self.start = unsafe { Step::forward_unchecked(old, 1) }; + Some(old) + } else { + None + } + } + + #[inline] + fn spec_nth(&mut self, n: usize) -> Option { + if let Some(plus_n) = Step::forward_checked(self.start, n) { + if plus_n < self.end { + // SAFETY: just checked precondition + self.start = unsafe { Step::forward_unchecked(plus_n, 1) }; + return Some(plus_n); + } + } + + self.start = self.end; + None + } + + #[inline] + fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZero> { + let steps = Step::steps_between(&self.start, &self.end); + let available = steps.1.unwrap_or(steps.0); + + let taken = available.min(n); + + // SAFETY: the conditions above ensure that the count is in bounds. If start <= end + // then steps_between either returns a bound to which we clamp or returns None which + // together with the initial inequality implies more than usize::MAX steps. + // Otherwise 0 is returned which always safe to use. + self.start = unsafe { Step::forward_unchecked(self.start, taken) }; + + NonZero::new(n - taken).map_or(Ok(()), Err) + } + + #[inline] + fn spec_next_back(&mut self) -> Option { + if self.start < self.end { + // SAFETY: just checked precondition + self.end = unsafe { Step::backward_unchecked(self.end, 1) }; + Some(self.end) + } else { + None + } + } + + #[inline] + fn spec_nth_back(&mut self, n: usize) -> Option { + if let Some(minus_n) = Step::backward_checked(self.end, n) { + if minus_n > self.start { + // SAFETY: just checked precondition + self.end = unsafe { Step::backward_unchecked(minus_n, 1) }; + return Some(self.end); + } + } + + self.end = self.start; + None + } + + #[inline] + fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + let steps = Step::steps_between(&self.start, &self.end); + let available = steps.1.unwrap_or(steps.0); + + let taken = available.min(n); + + // SAFETY: same as the spec_advance_by() implementation + self.end = unsafe { Step::backward_unchecked(self.end, taken) }; + + NonZero::new(n - taken).map_or(Ok(()), Err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for ops::Range { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + self.spec_next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.start < self.end { + Step::steps_between(&self.start, &self.end) + } else { + (0, Some(0)) + } + } + + #[inline] + fn count(self) -> usize { + if self.start < self.end { + Step::steps_between(&self.start, &self.end).1.expect("count overflowed usize") + } else { + 0 + } + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.spec_nth(n) + } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } + + #[inline] + fn min(mut self) -> Option + where + A: Ord, + { + self.next() + } + + #[inline] + fn max(mut self) -> Option + where + A: Ord, + { + self.next_back() + } + + #[inline] + fn is_sorted(self) -> bool { + true + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.spec_advance_by(n) + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccessNoCoerce, + { + // SAFETY: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + // Additionally Self: TrustedRandomAccess is only implemented for Copy types + // which means even repeated reads of the same index would be safe. + unsafe { Step::forward_unchecked(self.start.clone(), idx) } + } +} + +// These macros generate `ExactSizeIterator` impls for various range types. +// +// * `ExactSizeIterator::len` is required to always return an exact `usize`, +// so no range can be longer than `usize::MAX`. +// * For integer types in `Range<_>` this is the case for types narrower than or as wide as `usize`. +// For integer types in `RangeInclusive<_>` +// this is the case for types *strictly narrower* than `usize` +// since e.g. `(0..=u64::MAX).len()` would be `u64::MAX + 1`. +range_exact_iter_impl! { + usize u8 u16 + isize i8 i16 + + // These are incorrect per the reasoning above, + // but removing them would be a breaking change as they were stabilized in Rust 1.0.0. + // So e.g. `(0..66_000_u32).len()` for example will compile without error or warnings + // on 16-bit platforms, but continue to give a wrong result. + u32 + i32 +} + +unsafe_range_trusted_random_access_impl! { + usize u8 u16 + isize i8 i16 +} + +#[cfg(target_pointer_width = "32")] +unsafe_range_trusted_random_access_impl! { + u32 i32 +} + +#[cfg(target_pointer_width = "64")] +unsafe_range_trusted_random_access_impl! { + u32 i32 + u64 i64 +} + +range_incl_exact_iter_impl! { + u8 + i8 + + // These are incorrect per the reasoning above, + // but removing them would be a breaking change as they were stabilized in Rust 1.26.0. + // So e.g. `(0..=u16::MAX).len()` for example will compile without error or warnings + // on 16-bit platforms, but continue to give a wrong result. + u16 + i16 +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for ops::Range { + #[inline] + fn next_back(&mut self) -> Option { + self.spec_next_back() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.spec_nth_back(n) + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.spec_advance_back_by(n) + } +} + +// Safety: +// The following invariants for `Step::steps_between` exist: +// +// > * `steps_between(&a, &b) == (n, Some(n))` only if `a <= b` +// > * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != (n, None)`; +// > this is the case when it would require more than `usize::MAX` steps to +// > get to `b` +// > * `steps_between(&a, &b) == (0, None)` if `a > b` +// +// The first invariant is what is generally required for `TrustedLen` to be +// sound. The note addendum satisfies an additional `TrustedLen` invariant. +// +// > The upper bound must only be `None` if the actual iterator length is larger +// > than `usize::MAX` +// +// The second invariant logically follows the first so long as the `PartialOrd` +// implementation is correct; regardless it is explicitly stated. If `a < b` +// then `(0, Some(0))` is returned by `ops::Range::size_hint`. As such +// the second invariant is upheld. +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ops::Range {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for ops::Range {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for ops::RangeFrom { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + let n = Step::forward(self.start.clone(), 1); + Some(mem::replace(&mut self.start, n)) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (usize::MAX, None) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + let plus_n = Step::forward(self.start.clone(), n); + self.start = Step::forward(plus_n.clone(), 1); + Some(plus_n) + } +} + +// Safety: See above implementation for `ops::Range` +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ops::RangeFrom {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for ops::RangeFrom {} + +trait RangeInclusiveIteratorImpl { + type Item; + + // Iterator + fn spec_next(&mut self) -> Option; + fn spec_try_fold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try; + + // DoubleEndedIterator + fn spec_next_back(&mut self) -> Option; + fn spec_try_rfold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try; +} + +impl RangeInclusiveIteratorImpl for ops::RangeInclusive { + type Item = A; + + #[inline] + default fn spec_next(&mut self) -> Option { + if self.is_empty() { + return None; + } + let is_iterating = self.start < self.end; + Some(if is_iterating { + let n = + Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld"); + mem::replace(&mut self.start, n) + } else { + self.exhausted = true; + self.start.clone() + }) + } + + #[inline] + default fn spec_try_fold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, A) -> R, + R: Try, + { + if self.is_empty() { + return try { init }; + } + + let mut accum = init; + + while self.start < self.end { + let n = + Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld"); + let n = mem::replace(&mut self.start, n); + accum = f(accum, n)?; + } + + self.exhausted = true; + + if self.start == self.end { + accum = f(accum, self.start.clone())?; + } + + try { accum } + } + + #[inline] + default fn spec_next_back(&mut self) -> Option { + if self.is_empty() { + return None; + } + let is_iterating = self.start < self.end; + Some(if is_iterating { + let n = + Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld"); + mem::replace(&mut self.end, n) + } else { + self.exhausted = true; + self.end.clone() + }) + } + + #[inline] + default fn spec_try_rfold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, A) -> R, + R: Try, + { + if self.is_empty() { + return try { init }; + } + + let mut accum = init; + + while self.start < self.end { + let n = + Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld"); + let n = mem::replace(&mut self.end, n); + accum = f(accum, n)?; + } + + self.exhausted = true; + + if self.start == self.end { + accum = f(accum, self.start.clone())?; + } + + try { accum } + } +} + +impl RangeInclusiveIteratorImpl for ops::RangeInclusive { + #[inline] + fn spec_next(&mut self) -> Option { + if self.is_empty() { + return None; + } + let is_iterating = self.start < self.end; + Some(if is_iterating { + // SAFETY: just checked precondition + let n = unsafe { Step::forward_unchecked(self.start, 1) }; + mem::replace(&mut self.start, n) + } else { + self.exhausted = true; + self.start + }) + } + + #[inline] + fn spec_try_fold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, T) -> R, + R: Try, + { + if self.is_empty() { + return try { init }; + } + + let mut accum = init; + + while self.start < self.end { + // SAFETY: just checked precondition + let n = unsafe { Step::forward_unchecked(self.start, 1) }; + let n = mem::replace(&mut self.start, n); + accum = f(accum, n)?; + } + + self.exhausted = true; + + if self.start == self.end { + accum = f(accum, self.start)?; + } + + try { accum } + } + + #[inline] + fn spec_next_back(&mut self) -> Option { + if self.is_empty() { + return None; + } + let is_iterating = self.start < self.end; + Some(if is_iterating { + // SAFETY: just checked precondition + let n = unsafe { Step::backward_unchecked(self.end, 1) }; + mem::replace(&mut self.end, n) + } else { + self.exhausted = true; + self.end + }) + } + + #[inline] + fn spec_try_rfold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, T) -> R, + R: Try, + { + if self.is_empty() { + return try { init }; + } + + let mut accum = init; + + while self.start < self.end { + // SAFETY: just checked precondition + let n = unsafe { Step::backward_unchecked(self.end, 1) }; + let n = mem::replace(&mut self.end, n); + accum = f(accum, n)?; + } + + self.exhausted = true; + + if self.start == self.end { + accum = f(accum, self.start)?; + } + + try { accum } + } +} + +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl Iterator for ops::RangeInclusive { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + self.spec_next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.is_empty() { + return (0, Some(0)); + } + + let hint = Step::steps_between(&self.start, &self.end); + (hint.0.saturating_add(1), hint.1.and_then(|steps| steps.checked_add(1))) + } + + #[inline] + fn count(self) -> usize { + if self.is_empty() { + return 0; + } + + Step::steps_between(&self.start, &self.end) + .1 + .and_then(|steps| steps.checked_add(1)) + .expect("count overflowed usize") + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + if self.is_empty() { + return None; + } + + if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) { + use crate::cmp::Ordering::*; + + match plus_n.partial_cmp(&self.end) { + Some(Less) => { + self.start = Step::forward(plus_n.clone(), 1); + return Some(plus_n); + } + Some(Equal) => { + self.start = plus_n.clone(); + self.exhausted = true; + return Some(plus_n); + } + _ => {} + } + } + + self.start = self.end.clone(); + self.exhausted = true; + None + } + + #[inline] + fn try_fold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.spec_try_fold(init, f) + } + + impl_fold_via_try_fold! { fold -> try_fold } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } + + #[inline] + fn min(mut self) -> Option + where + A: Ord, + { + self.next() + } + + #[inline] + fn max(mut self) -> Option + where + A: Ord, + { + self.next_back() + } + + #[inline] + fn is_sorted(self) -> bool { + true + } +} + +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl DoubleEndedIterator for ops::RangeInclusive { + #[inline] + fn next_back(&mut self) -> Option { + self.spec_next_back() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + if self.is_empty() { + return None; + } + + if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) { + use crate::cmp::Ordering::*; + + match minus_n.partial_cmp(&self.start) { + Some(Greater) => { + self.end = Step::backward(minus_n.clone(), 1); + return Some(minus_n); + } + Some(Equal) => { + self.end = minus_n.clone(); + self.exhausted = true; + return Some(minus_n); + } + _ => {} + } + } + + self.end = self.start.clone(); + self.exhausted = true; + None + } + + #[inline] + fn try_rfold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.spec_try_rfold(init, f) + } + + impl_fold_via_try_fold! { rfold -> try_rfold } +} + +// Safety: See above implementation for `ops::Range` +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ops::RangeInclusive {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for ops::RangeInclusive {} diff --git a/CoqOfRust/core/iter/sources.rs b/CoqOfRust/core/iter/sources.rs new file mode 100644 index 000000000..c635992df --- /dev/null +++ b/CoqOfRust/core/iter/sources.rs @@ -0,0 +1,32 @@ +mod empty; +mod from_coroutine; +mod from_fn; +mod once; +mod once_with; +mod repeat; +mod repeat_n; +mod repeat_with; +mod successors; + +#[stable(feature = "iter_empty", since = "1.2.0")] +pub use self::empty::{Empty, empty}; +#[unstable( + feature = "iter_from_coroutine", + issue = "43122", + reason = "coroutines are unstable" +)] +pub use self::from_coroutine::from_coroutine; +#[stable(feature = "iter_from_fn", since = "1.34.0")] +pub use self::from_fn::{FromFn, from_fn}; +#[stable(feature = "iter_once", since = "1.2.0")] +pub use self::once::{Once, once}; +#[stable(feature = "iter_once_with", since = "1.43.0")] +pub use self::once_with::{OnceWith, once_with}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::repeat::{Repeat, repeat}; +#[stable(feature = "iter_repeat_n", since = "1.82.0")] +pub use self::repeat_n::{RepeatN, repeat_n}; +#[stable(feature = "iterator_repeat_with", since = "1.28.0")] +pub use self::repeat_with::{RepeatWith, repeat_with}; +#[stable(feature = "iter_successors", since = "1.34.0")] +pub use self::successors::{Successors, successors}; diff --git a/CoqOfRust/core/iter/sources/empty.rs b/CoqOfRust/core/iter/sources/empty.rs new file mode 100644 index 000000000..3c3accede --- /dev/null +++ b/CoqOfRust/core/iter/sources/empty.rs @@ -0,0 +1,88 @@ +use crate::iter::{FusedIterator, TrustedLen}; +use crate::{fmt, marker}; + +/// Creates an iterator that yields nothing. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::iter; +/// +/// // this could have been an iterator over i32, but alas, it's just not. +/// let mut nope = iter::empty::(); +/// +/// assert_eq!(None, nope.next()); +/// ``` +#[stable(feature = "iter_empty", since = "1.2.0")] +#[rustc_const_stable(feature = "const_iter_empty", since = "1.32.0")] +pub const fn empty() -> Empty { + Empty(marker::PhantomData) +} + +/// An iterator that yields nothing. +/// +/// This `struct` is created by the [`empty()`] function. See its documentation for more. +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "iter_empty", since = "1.2.0")] +#[rustc_diagnostic_item = "IterEmpty"] +pub struct Empty(marker::PhantomData T>); + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for Empty { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Empty").finish() + } +} + +#[stable(feature = "iter_empty", since = "1.2.0")] +impl Iterator for Empty { + type Item = T; + + fn next(&mut self) -> Option { + None + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(0)) + } +} + +#[stable(feature = "iter_empty", since = "1.2.0")] +impl DoubleEndedIterator for Empty { + fn next_back(&mut self) -> Option { + None + } +} + +#[stable(feature = "iter_empty", since = "1.2.0")] +impl ExactSizeIterator for Empty { + fn len(&self) -> usize { + 0 + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Empty {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Empty {} + +// not #[derive] because that adds a Clone bound on T, +// which isn't necessary. +#[stable(feature = "iter_empty", since = "1.2.0")] +impl Clone for Empty { + fn clone(&self) -> Empty { + Empty(marker::PhantomData) + } +} + +// not #[derive] because that adds a Default bound on T, +// which isn't necessary. +#[stable(feature = "iter_empty", since = "1.2.0")] +impl Default for Empty { + fn default() -> Empty { + Empty(marker::PhantomData) + } +} diff --git a/CoqOfRust/core/iter/sources/from_coroutine.rs b/CoqOfRust/core/iter/sources/from_coroutine.rs new file mode 100644 index 000000000..710ba504d --- /dev/null +++ b/CoqOfRust/core/iter/sources/from_coroutine.rs @@ -0,0 +1,58 @@ +use crate::fmt; +use crate::ops::{Coroutine, CoroutineState}; +use crate::pin::Pin; + +/// Creates a new iterator where each iteration calls the provided coroutine. +/// +/// Similar to [`iter::from_fn`]. +/// +/// [`iter::from_fn`]: crate::iter::from_fn +/// +/// # Examples +/// +/// ``` +/// #![feature(coroutines)] +/// #![feature(iter_from_coroutine)] +/// +/// let it = std::iter::from_coroutine(#[coroutine] || { +/// yield 1; +/// yield 2; +/// yield 3; +/// }); +/// let v: Vec<_> = it.collect(); +/// assert_eq!(v, [1, 2, 3]); +/// ``` +#[inline] +#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")] +pub fn from_coroutine + Unpin>(coroutine: G) -> FromCoroutine { + FromCoroutine(coroutine) +} + +/// An iterator over the values yielded by an underlying coroutine. +/// +/// This `struct` is created by the [`iter::from_coroutine()`] function. See its documentation for +/// more. +/// +/// [`iter::from_coroutine()`]: from_coroutine +#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")] +#[derive(Clone)] +pub struct FromCoroutine(G); + +#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")] +impl + Unpin> Iterator for FromCoroutine { + type Item = G::Yield; + + fn next(&mut self) -> Option { + match Pin::new(&mut self.0).resume(()) { + CoroutineState::Yielded(n) => Some(n), + CoroutineState::Complete(()) => None, + } + } +} + +#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")] +impl fmt::Debug for FromCoroutine { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FromCoroutine").finish() + } +} diff --git a/CoqOfRust/core/iter/sources/from_fn.rs b/CoqOfRust/core/iter/sources/from_fn.rs new file mode 100644 index 000000000..3cd383047 --- /dev/null +++ b/CoqOfRust/core/iter/sources/from_fn.rs @@ -0,0 +1,78 @@ +use crate::fmt; + +/// Creates a new iterator where each iteration calls the provided closure +/// `F: FnMut() -> Option`. +/// +/// This allows creating a custom iterator with any behavior +/// without using the more verbose syntax of creating a dedicated type +/// and implementing the [`Iterator`] trait for it. +/// +/// Note that the `FromFn` iterator doesn’t make assumptions about the behavior of the closure, +/// and therefore conservatively does not implement [`FusedIterator`], +/// or override [`Iterator::size_hint()`] from its default `(0, None)`. +/// +/// The closure can use captures and its environment to track state across iterations. Depending on +/// how the iterator is used, this may require specifying the [`move`] keyword on the closure. +/// +/// [`move`]: ../../std/keyword.move.html +/// [`FusedIterator`]: crate::iter::FusedIterator +/// +/// # Examples +/// +/// Let’s re-implement the counter iterator from [module-level documentation]: +/// +/// [module-level documentation]: crate::iter +/// +/// ``` +/// let mut count = 0; +/// let counter = std::iter::from_fn(move || { +/// // Increment our count. This is why we started at zero. +/// count += 1; +/// +/// // Check to see if we've finished counting or not. +/// if count < 6 { +/// Some(count) +/// } else { +/// None +/// } +/// }); +/// assert_eq!(counter.collect::>(), &[1, 2, 3, 4, 5]); +/// ``` +#[inline] +#[stable(feature = "iter_from_fn", since = "1.34.0")] +pub fn from_fn(f: F) -> FromFn +where + F: FnMut() -> Option, +{ + FromFn(f) +} + +/// An iterator where each iteration calls the provided closure `F: FnMut() -> Option`. +/// +/// This `struct` is created by the [`iter::from_fn()`] function. +/// See its documentation for more. +/// +/// [`iter::from_fn()`]: from_fn +#[derive(Clone)] +#[stable(feature = "iter_from_fn", since = "1.34.0")] +pub struct FromFn(F); + +#[stable(feature = "iter_from_fn", since = "1.34.0")] +impl Iterator for FromFn +where + F: FnMut() -> Option, +{ + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + (self.0)() + } +} + +#[stable(feature = "iter_from_fn", since = "1.34.0")] +impl fmt::Debug for FromFn { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FromFn").finish() + } +} diff --git a/CoqOfRust/core/iter/sources/once.rs b/CoqOfRust/core/iter/sources/once.rs new file mode 100644 index 000000000..21be4377d --- /dev/null +++ b/CoqOfRust/core/iter/sources/once.rs @@ -0,0 +1,100 @@ +use crate::iter::{FusedIterator, TrustedLen}; + +/// Creates an iterator that yields an element exactly once. +/// +/// This is commonly used to adapt a single value into a [`chain()`] of other +/// kinds of iteration. Maybe you have an iterator that covers almost +/// everything, but you need an extra special case. Maybe you have a function +/// which works on iterators, but you only need to process one value. +/// +/// [`chain()`]: Iterator::chain +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::iter; +/// +/// // one is the loneliest number +/// let mut one = iter::once(1); +/// +/// assert_eq!(Some(1), one.next()); +/// +/// // just one, that's all we get +/// assert_eq!(None, one.next()); +/// ``` +/// +/// Chaining together with another iterator. Let's say that we want to iterate +/// over each file of the `.foo` directory, but also a configuration file, +/// `.foorc`: +/// +/// ```no_run +/// use std::iter; +/// use std::fs; +/// use std::path::PathBuf; +/// +/// let dirs = fs::read_dir(".foo").unwrap(); +/// +/// // we need to convert from an iterator of DirEntry-s to an iterator of +/// // PathBufs, so we use map +/// let dirs = dirs.map(|file| file.unwrap().path()); +/// +/// // now, our iterator just for our config file +/// let config = iter::once(PathBuf::from(".foorc")); +/// +/// // chain the two iterators together into one big iterator +/// let files = dirs.chain(config); +/// +/// // this will give us all of the files in .foo as well as .foorc +/// for f in files { +/// println!("{f:?}"); +/// } +/// ``` +#[stable(feature = "iter_once", since = "1.2.0")] +pub fn once(value: T) -> Once { + Once { inner: Some(value).into_iter() } +} + +/// An iterator that yields an element exactly once. +/// +/// This `struct` is created by the [`once()`] function. See its documentation for more. +#[derive(Clone, Debug)] +#[stable(feature = "iter_once", since = "1.2.0")] +#[rustc_diagnostic_item = "IterOnce"] +pub struct Once { + inner: crate::option::IntoIter, +} + +#[stable(feature = "iter_once", since = "1.2.0")] +impl Iterator for Once { + type Item = T; + + fn next(&mut self) -> Option { + self.inner.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +#[stable(feature = "iter_once", since = "1.2.0")] +impl DoubleEndedIterator for Once { + fn next_back(&mut self) -> Option { + self.inner.next_back() + } +} + +#[stable(feature = "iter_once", since = "1.2.0")] +impl ExactSizeIterator for Once { + fn len(&self) -> usize { + self.inner.len() + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Once {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Once {} diff --git a/CoqOfRust/core/iter/sources/once_with.rs b/CoqOfRust/core/iter/sources/once_with.rs new file mode 100644 index 000000000..8b31ab2ff --- /dev/null +++ b/CoqOfRust/core/iter/sources/once_with.rs @@ -0,0 +1,121 @@ +use crate::fmt; +use crate::iter::{FusedIterator, TrustedLen}; + +/// Creates an iterator that lazily generates a value exactly once by invoking +/// the provided closure. +/// +/// This is commonly used to adapt a single value coroutine into a [`chain()`] of +/// other kinds of iteration. Maybe you have an iterator that covers almost +/// everything, but you need an extra special case. Maybe you have a function +/// which works on iterators, but you only need to process one value. +/// +/// Unlike [`once()`], this function will lazily generate the value on request. +/// +/// [`chain()`]: Iterator::chain +/// [`once()`]: crate::iter::once +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::iter; +/// +/// // one is the loneliest number +/// let mut one = iter::once_with(|| 1); +/// +/// assert_eq!(Some(1), one.next()); +/// +/// // just one, that's all we get +/// assert_eq!(None, one.next()); +/// ``` +/// +/// Chaining together with another iterator. Let's say that we want to iterate +/// over each file of the `.foo` directory, but also a configuration file, +/// `.foorc`: +/// +/// ```no_run +/// use std::iter; +/// use std::fs; +/// use std::path::PathBuf; +/// +/// let dirs = fs::read_dir(".foo").unwrap(); +/// +/// // we need to convert from an iterator of DirEntry-s to an iterator of +/// // PathBufs, so we use map +/// let dirs = dirs.map(|file| file.unwrap().path()); +/// +/// // now, our iterator just for our config file +/// let config = iter::once_with(|| PathBuf::from(".foorc")); +/// +/// // chain the two iterators together into one big iterator +/// let files = dirs.chain(config); +/// +/// // this will give us all of the files in .foo as well as .foorc +/// for f in files { +/// println!("{f:?}"); +/// } +/// ``` +#[inline] +#[stable(feature = "iter_once_with", since = "1.43.0")] +pub fn once_with A>(gen: F) -> OnceWith { + OnceWith { gen: Some(gen) } +} + +/// An iterator that yields a single element of type `A` by +/// applying the provided closure `F: FnOnce() -> A`. +/// +/// This `struct` is created by the [`once_with()`] function. +/// See its documentation for more. +#[derive(Clone)] +#[stable(feature = "iter_once_with", since = "1.43.0")] +pub struct OnceWith { + gen: Option, +} + +#[stable(feature = "iter_once_with_debug", since = "1.68.0")] +impl fmt::Debug for OnceWith { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.gen.is_some() { + f.write_str("OnceWith(Some(_))") + } else { + f.write_str("OnceWith(None)") + } + } +} + +#[stable(feature = "iter_once_with", since = "1.43.0")] +impl A> Iterator for OnceWith { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + let f = self.gen.take()?; + Some(f()) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.gen.iter().size_hint() + } +} + +#[stable(feature = "iter_once_with", since = "1.43.0")] +impl A> DoubleEndedIterator for OnceWith { + fn next_back(&mut self) -> Option { + self.next() + } +} + +#[stable(feature = "iter_once_with", since = "1.43.0")] +impl A> ExactSizeIterator for OnceWith { + fn len(&self) -> usize { + self.gen.iter().len() + } +} + +#[stable(feature = "iter_once_with", since = "1.43.0")] +impl A> FusedIterator for OnceWith {} + +#[stable(feature = "iter_once_with", since = "1.43.0")] +unsafe impl A> TrustedLen for OnceWith {} diff --git a/CoqOfRust/core/iter/sources/repeat.rs b/CoqOfRust/core/iter/sources/repeat.rs new file mode 100644 index 000000000..243f938bc --- /dev/null +++ b/CoqOfRust/core/iter/sources/repeat.rs @@ -0,0 +1,134 @@ +use crate::iter::{FusedIterator, TrustedLen}; +use crate::num::NonZero; + +/// Creates a new iterator that endlessly repeats a single element. +/// +/// The `repeat()` function repeats a single value over and over again. +/// +/// Infinite iterators like `repeat()` are often used with adapters like +/// [`Iterator::take()`], in order to make them finite. +/// +/// Use [`str::repeat()`] instead of this function if you just want to repeat +/// a char/string `n`th times. +/// +/// If the element type of the iterator you need does not implement `Clone`, +/// or if you do not want to keep the repeated element in memory, you can +/// instead use the [`repeat_with()`] function. +/// +/// [`repeat_with()`]: crate::iter::repeat_with +/// [`str::repeat()`]: ../../std/primitive.str.html#method.repeat +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::iter; +/// +/// // the number four 4ever: +/// let mut fours = iter::repeat(4); +/// +/// assert_eq!(Some(4), fours.next()); +/// assert_eq!(Some(4), fours.next()); +/// assert_eq!(Some(4), fours.next()); +/// assert_eq!(Some(4), fours.next()); +/// assert_eq!(Some(4), fours.next()); +/// +/// // yup, still four +/// assert_eq!(Some(4), fours.next()); +/// ``` +/// +/// Going finite with [`Iterator::take()`]: +/// +/// ``` +/// use std::iter; +/// +/// // that last example was too many fours. Let's only have four fours. +/// let mut four_fours = iter::repeat(4).take(4); +/// +/// assert_eq!(Some(4), four_fours.next()); +/// assert_eq!(Some(4), four_fours.next()); +/// assert_eq!(Some(4), four_fours.next()); +/// assert_eq!(Some(4), four_fours.next()); +/// +/// // ... and now we're done +/// assert_eq!(None, four_fours.next()); +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "iter_repeat")] +pub fn repeat(elt: T) -> Repeat { + Repeat { element: elt } +} + +/// An iterator that repeats an element endlessly. +/// +/// This `struct` is created by the [`repeat()`] function. See its documentation for more. +#[derive(Clone, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Repeat { + element: A, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Repeat { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + Some(self.element.clone()) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (usize::MAX, None) + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + // Advancing an infinite iterator of a single element is a no-op. + let _ = n; + Ok(()) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + let _ = n; + Some(self.element.clone()) + } + + fn last(self) -> Option { + loop {} + } + + fn count(self) -> usize { + loop {} + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Repeat { + #[inline] + fn next_back(&mut self) -> Option { + Some(self.element.clone()) + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + // Advancing an infinite iterator of a single element is a no-op. + let _ = n; + Ok(()) + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let _ = n; + Some(self.element.clone()) + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Repeat {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Repeat {} diff --git a/CoqOfRust/core/iter/sources/repeat_n.rs b/CoqOfRust/core/iter/sources/repeat_n.rs new file mode 100644 index 000000000..cc089c617 --- /dev/null +++ b/CoqOfRust/core/iter/sources/repeat_n.rs @@ -0,0 +1,230 @@ +use crate::fmt; +use crate::iter::{FusedIterator, TrustedLen, UncheckedIterator}; +use crate::mem::{self, MaybeUninit}; +use crate::num::NonZero; + +/// Creates a new iterator that repeats a single element a given number of times. +/// +/// The `repeat_n()` function repeats a single value exactly `n` times. +/// +/// This is very similar to using [`repeat()`] with [`Iterator::take()`], +/// but `repeat_n()` can return the original value, rather than always cloning. +/// +/// [`repeat()`]: crate::iter::repeat +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::iter; +/// +/// // four of the number four: +/// let mut four_fours = iter::repeat_n(4, 4); +/// +/// assert_eq!(Some(4), four_fours.next()); +/// assert_eq!(Some(4), four_fours.next()); +/// assert_eq!(Some(4), four_fours.next()); +/// assert_eq!(Some(4), four_fours.next()); +/// +/// // no more fours +/// assert_eq!(None, four_fours.next()); +/// ``` +/// +/// For non-`Copy` types, +/// +/// ``` +/// use std::iter; +/// +/// let v: Vec = Vec::with_capacity(123); +/// let mut it = iter::repeat_n(v, 5); +/// +/// for i in 0..4 { +/// // It starts by cloning things +/// let cloned = it.next().unwrap(); +/// assert_eq!(cloned.len(), 0); +/// assert_eq!(cloned.capacity(), 0); +/// } +/// +/// // ... but the last item is the original one +/// let last = it.next().unwrap(); +/// assert_eq!(last.len(), 0); +/// assert_eq!(last.capacity(), 123); +/// +/// // ... and now we're done +/// assert_eq!(None, it.next()); +/// ``` +#[inline] +#[stable(feature = "iter_repeat_n", since = "1.82.0")] +pub fn repeat_n(element: T, count: usize) -> RepeatN { + let element = if count == 0 { + // `element` gets dropped eagerly. + MaybeUninit::uninit() + } else { + MaybeUninit::new(element) + }; + + RepeatN { element, count } +} + +/// An iterator that repeats an element an exact number of times. +/// +/// This `struct` is created by the [`repeat_n()`] function. +/// See its documentation for more. +#[stable(feature = "iter_repeat_n", since = "1.82.0")] +pub struct RepeatN { + count: usize, + // Invariant: uninit iff count == 0. + element: MaybeUninit, +} + +impl RepeatN { + /// Returns the element if it hasn't been dropped already. + fn element_ref(&self) -> Option<&A> { + if self.count > 0 { + // SAFETY: The count is non-zero, so it must be initialized. + Some(unsafe { self.element.assume_init_ref() }) + } else { + None + } + } + /// If we haven't already dropped the element, return it in an option. + /// + /// Clears the count so it won't be dropped again later. + #[inline] + fn take_element(&mut self) -> Option { + if self.count > 0 { + self.count = 0; + let element = mem::replace(&mut self.element, MaybeUninit::uninit()); + // SAFETY: We just set count to zero so it won't be dropped again, + // and it used to be non-zero so it hasn't already been dropped. + unsafe { Some(element.assume_init()) } + } else { + None + } + } +} + +#[stable(feature = "iter_repeat_n", since = "1.82.0")] +impl Clone for RepeatN { + fn clone(&self) -> RepeatN { + RepeatN { + count: self.count, + element: self.element_ref().cloned().map_or_else(MaybeUninit::uninit, MaybeUninit::new), + } + } +} + +#[stable(feature = "iter_repeat_n", since = "1.82.0")] +impl fmt::Debug for RepeatN { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RepeatN") + .field("count", &self.count) + .field("element", &self.element_ref()) + .finish() + } +} + +#[stable(feature = "iter_repeat_n", since = "1.82.0")] +impl Drop for RepeatN { + fn drop(&mut self) { + self.take_element(); + } +} + +#[stable(feature = "iter_repeat_n", since = "1.82.0")] +impl Iterator for RepeatN { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + if self.count > 0 { + // SAFETY: Just checked it's not empty + unsafe { Some(self.next_unchecked()) } + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } + + #[inline] + fn advance_by(&mut self, skip: usize) -> Result<(), NonZero> { + let len = self.count; + + if skip >= len { + self.take_element(); + } + + if skip > len { + // SAFETY: we just checked that the difference is positive + Err(unsafe { NonZero::new_unchecked(skip - len) }) + } else { + self.count = len - skip; + Ok(()) + } + } + + #[inline] + fn last(mut self) -> Option { + self.take_element() + } + + #[inline] + fn count(self) -> usize { + self.len() + } +} + +#[stable(feature = "iter_repeat_n", since = "1.82.0")] +impl ExactSizeIterator for RepeatN { + fn len(&self) -> usize { + self.count + } +} + +#[stable(feature = "iter_repeat_n", since = "1.82.0")] +impl DoubleEndedIterator for RepeatN { + #[inline] + fn next_back(&mut self) -> Option { + self.next() + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.advance_by(n) + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.nth(n) + } +} + +#[stable(feature = "iter_repeat_n", since = "1.82.0")] +impl FusedIterator for RepeatN {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for RepeatN {} +#[stable(feature = "iter_repeat_n", since = "1.82.0")] +impl UncheckedIterator for RepeatN { + #[inline] + unsafe fn next_unchecked(&mut self) -> Self::Item { + // SAFETY: The caller promised the iterator isn't empty + self.count = unsafe { self.count.unchecked_sub(1) }; + if self.count == 0 { + // SAFETY: the check above ensured that the count used to be non-zero, + // so element hasn't been dropped yet, and we just lowered the count to + // zero so it won't be dropped later, and thus it's okay to take it here. + unsafe { mem::replace(&mut self.element, MaybeUninit::uninit()).assume_init() } + } else { + // SAFETY: the count is non-zero, so it must have not been dropped yet. + let element = unsafe { self.element.assume_init_ref() }; + A::clone(element) + } + } +} diff --git a/CoqOfRust/core/iter/sources/repeat_with.rs b/CoqOfRust/core/iter/sources/repeat_with.rs new file mode 100644 index 000000000..d3cd74a44 --- /dev/null +++ b/CoqOfRust/core/iter/sources/repeat_with.rs @@ -0,0 +1,122 @@ +use crate::fmt; +use crate::iter::{FusedIterator, TrustedLen}; +use crate::ops::Try; + +/// Creates a new iterator that repeats elements of type `A` endlessly by +/// applying the provided closure, the repeater, `F: FnMut() -> A`. +/// +/// The `repeat_with()` function calls the repeater over and over again. +/// +/// Infinite iterators like `repeat_with()` are often used with adapters like +/// [`Iterator::take()`], in order to make them finite. +/// +/// If the element type of the iterator you need implements [`Clone`], and +/// it is OK to keep the source element in memory, you should instead use +/// the [`repeat()`] function. +/// +/// An iterator produced by `repeat_with()` is not a [`DoubleEndedIterator`]. +/// If you need `repeat_with()` to return a [`DoubleEndedIterator`], +/// please open a GitHub issue explaining your use case. +/// +/// [`repeat()`]: crate::iter::repeat +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::iter; +/// +/// // let's assume we have some value of a type that is not `Clone` +/// // or which we don't want to have in memory just yet because it is expensive: +/// #[derive(PartialEq, Debug)] +/// struct Expensive; +/// +/// // a particular value forever: +/// let mut things = iter::repeat_with(|| Expensive); +/// +/// assert_eq!(Some(Expensive), things.next()); +/// assert_eq!(Some(Expensive), things.next()); +/// assert_eq!(Some(Expensive), things.next()); +/// assert_eq!(Some(Expensive), things.next()); +/// assert_eq!(Some(Expensive), things.next()); +/// ``` +/// +/// Using mutation and going finite: +/// +/// ```rust +/// use std::iter; +/// +/// // From the zeroth to the third power of two: +/// let mut curr = 1; +/// let mut pow2 = iter::repeat_with(|| { let tmp = curr; curr *= 2; tmp }) +/// .take(4); +/// +/// assert_eq!(Some(1), pow2.next()); +/// assert_eq!(Some(2), pow2.next()); +/// assert_eq!(Some(4), pow2.next()); +/// assert_eq!(Some(8), pow2.next()); +/// +/// // ... and now we're done +/// assert_eq!(None, pow2.next()); +/// ``` +#[inline] +#[stable(feature = "iterator_repeat_with", since = "1.28.0")] +pub fn repeat_with A>(repeater: F) -> RepeatWith { + RepeatWith { repeater } +} + +/// An iterator that repeats elements of type `A` endlessly by +/// applying the provided closure `F: FnMut() -> A`. +/// +/// This `struct` is created by the [`repeat_with()`] function. +/// See its documentation for more. +#[derive(Copy, Clone)] +#[stable(feature = "iterator_repeat_with", since = "1.28.0")] +pub struct RepeatWith { + repeater: F, +} + +#[stable(feature = "iterator_repeat_with_debug", since = "1.68.0")] +impl fmt::Debug for RepeatWith { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RepeatWith").finish_non_exhaustive() + } +} + +#[stable(feature = "iterator_repeat_with", since = "1.28.0")] +impl A> Iterator for RepeatWith { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + Some((self.repeater)()) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (usize::MAX, None) + } + + #[inline] + fn try_fold(&mut self, mut init: Acc, mut fold: Fold) -> R + where + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + // This override isn't strictly needed, but avoids the need to optimize + // away the `next`-always-returns-`Some` and emphasizes that the `?` + // is the only way to exit the loop. + + loop { + let item = (self.repeater)(); + init = fold(init, item)?; + } + } +} + +#[stable(feature = "iterator_repeat_with", since = "1.28.0")] +impl A> FusedIterator for RepeatWith {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl A> TrustedLen for RepeatWith {} diff --git a/CoqOfRust/core/iter/sources/successors.rs b/CoqOfRust/core/iter/sources/successors.rs new file mode 100644 index 000000000..36bc40350 --- /dev/null +++ b/CoqOfRust/core/iter/sources/successors.rs @@ -0,0 +1,67 @@ +use crate::fmt; +use crate::iter::FusedIterator; + +/// Creates a new iterator where each successive item is computed based on the preceding one. +/// +/// The iterator starts with the given first item (if any) +/// and calls the given `FnMut(&T) -> Option` closure to compute each item’s successor. +/// +/// ``` +/// use std::iter::successors; +/// +/// let powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10)); +/// assert_eq!(powers_of_10.collect::>(), &[1, 10, 100, 1_000, 10_000]); +/// ``` +#[stable(feature = "iter_successors", since = "1.34.0")] +pub fn successors(first: Option, succ: F) -> Successors +where + F: FnMut(&T) -> Option, +{ + // If this function returned `impl Iterator` + // it could be based on `from_fn` and not need a dedicated type. + // However having a named `Successors` type allows it to be `Clone` when `T` and `F` are. + Successors { next: first, succ } +} + +/// A new iterator where each successive item is computed based on the preceding one. +/// +/// This `struct` is created by the [`iter::successors()`] function. +/// See its documentation for more. +/// +/// [`iter::successors()`]: successors +#[derive(Clone)] +#[stable(feature = "iter_successors", since = "1.34.0")] +pub struct Successors { + next: Option, + succ: F, +} + +#[stable(feature = "iter_successors", since = "1.34.0")] +impl Iterator for Successors +where + F: FnMut(&T) -> Option, +{ + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + let item = self.next.take()?; + self.next = (self.succ)(&item); + Some(item) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.next.is_some() { (1, None) } else { (0, Some(0)) } + } +} + +#[stable(feature = "iter_successors", since = "1.34.0")] +impl FusedIterator for Successors where F: FnMut(&T) -> Option {} + +#[stable(feature = "iter_successors", since = "1.34.0")] +impl fmt::Debug for Successors { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Successors").field("next", &self.next).finish() + } +} diff --git a/CoqOfRust/core/iter/traits/accum.rs b/CoqOfRust/core/iter/traits/accum.rs new file mode 100644 index 000000000..5b7d95c2f --- /dev/null +++ b/CoqOfRust/core/iter/traits/accum.rs @@ -0,0 +1,271 @@ +use crate::iter; +use crate::num::Wrapping; + +/// Trait to represent types that can be created by summing up an iterator. +/// +/// This trait is used to implement [`Iterator::sum()`]. Types which implement +/// this trait can be generated by using the [`sum()`] method on an iterator. +/// Like [`FromIterator`], this trait should rarely be called directly. +/// +/// [`sum()`]: Iterator::sum +/// [`FromIterator`]: iter::FromIterator +#[stable(feature = "iter_arith_traits", since = "1.12.0")] +#[rustc_on_unimplemented( + message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`", + label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator`" +)] +pub trait Sum: Sized { + /// Takes an iterator and generates `Self` from the elements by "summing up" + /// the items. + #[stable(feature = "iter_arith_traits", since = "1.12.0")] + fn sum>(iter: I) -> Self; +} + +/// Trait to represent types that can be created by multiplying elements of an +/// iterator. +/// +/// This trait is used to implement [`Iterator::product()`]. Types which implement +/// this trait can be generated by using the [`product()`] method on an iterator. +/// Like [`FromIterator`], this trait should rarely be called directly. +/// +/// [`product()`]: Iterator::product +/// [`FromIterator`]: iter::FromIterator +#[stable(feature = "iter_arith_traits", since = "1.12.0")] +#[rustc_on_unimplemented( + message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator", + label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator`" +)] +pub trait Product: Sized { + /// Takes an iterator and generates `Self` from the elements by multiplying + /// the items. + #[stable(feature = "iter_arith_traits", since = "1.12.0")] + fn product>(iter: I) -> Self; +} + +macro_rules! integer_sum_product { + (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($( + #[$attr] + impl Sum for $a { + fn sum>(iter: I) -> Self { + iter.fold( + $zero, + #[rustc_inherit_overflow_checks] + |a, b| a + b, + ) + } + } + + #[$attr] + impl Product for $a { + fn product>(iter: I) -> Self { + iter.fold( + $one, + #[rustc_inherit_overflow_checks] + |a, b| a * b, + ) + } + } + + #[$attr] + impl<'a> Sum<&'a $a> for $a { + fn sum>(iter: I) -> Self { + iter.fold( + $zero, + #[rustc_inherit_overflow_checks] + |a, b| a + b, + ) + } + } + + #[$attr] + impl<'a> Product<&'a $a> for $a { + fn product>(iter: I) -> Self { + iter.fold( + $one, + #[rustc_inherit_overflow_checks] + |a, b| a * b, + ) + } + } + )*); + ($($a:ty)*) => ( + integer_sum_product!(@impls 0, 1, + #[stable(feature = "iter_arith_traits", since = "1.12.0")], + $($a)*); + integer_sum_product!(@impls Wrapping(0), Wrapping(1), + #[stable(feature = "wrapping_iter_arith", since = "1.14.0")], + $(Wrapping<$a>)*); + ); +} + +macro_rules! float_sum_product { + ($($a:ident)*) => ($( + #[stable(feature = "iter_arith_traits", since = "1.12.0")] + impl Sum for $a { + fn sum>(iter: I) -> Self { + iter.fold( + -0.0, + #[rustc_inherit_overflow_checks] + |a, b| a + b, + ) + } + } + + #[stable(feature = "iter_arith_traits", since = "1.12.0")] + impl Product for $a { + fn product>(iter: I) -> Self { + iter.fold( + 1.0, + #[rustc_inherit_overflow_checks] + |a, b| a * b, + ) + } + } + + #[stable(feature = "iter_arith_traits", since = "1.12.0")] + impl<'a> Sum<&'a $a> for $a { + fn sum>(iter: I) -> Self { + iter.fold( + -0.0, + #[rustc_inherit_overflow_checks] + |a, b| a + b, + ) + } + } + + #[stable(feature = "iter_arith_traits", since = "1.12.0")] + impl<'a> Product<&'a $a> for $a { + fn product>(iter: I) -> Self { + iter.fold( + 1.0, + #[rustc_inherit_overflow_checks] + |a, b| a * b, + ) + } + } + )*) +} + +integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } +float_sum_product! { f32 f64 } + +#[stable(feature = "iter_arith_traits_result", since = "1.16.0")] +impl Sum> for Result +where + T: Sum, +{ + /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further + /// elements are taken, and the [`Err`] is returned. Should no [`Err`] + /// occur, the sum of all elements is returned. + /// + /// # Examples + /// + /// This sums up every integer in a vector, rejecting the sum if a negative + /// element is encountered: + /// + /// ``` + /// let f = |&x: &i32| if x < 0 { Err("Negative element found") } else { Ok(x) }; + /// let v = vec![1, 2]; + /// let res: Result = v.iter().map(f).sum(); + /// assert_eq!(res, Ok(3)); + /// let v = vec![1, -2]; + /// let res: Result = v.iter().map(f).sum(); + /// assert_eq!(res, Err("Negative element found")); + /// ``` + fn sum(iter: I) -> Result + where + I: Iterator>, + { + iter::try_process(iter, |i| i.sum()) + } +} + +#[stable(feature = "iter_arith_traits_result", since = "1.16.0")] +impl Product> for Result +where + T: Product, +{ + /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further + /// elements are taken, and the [`Err`] is returned. Should no [`Err`] + /// occur, the product of all elements is returned. + /// + /// # Examples + /// + /// This multiplies each number in a vector of strings, + /// if a string could not be parsed the operation returns `Err`: + /// + /// ``` + /// let nums = vec!["5", "10", "1", "2"]; + /// let total: Result = nums.iter().map(|w| w.parse::()).product(); + /// assert_eq!(total, Ok(100)); + /// let nums = vec!["5", "10", "one", "2"]; + /// let total: Result = nums.iter().map(|w| w.parse::()).product(); + /// assert!(total.is_err()); + /// ``` + fn product(iter: I) -> Result + where + I: Iterator>, + { + iter::try_process(iter, |i| i.product()) + } +} + +#[stable(feature = "iter_arith_traits_option", since = "1.37.0")] +impl Sum> for Option +where + T: Sum, +{ + /// Takes each element in the [`Iterator`]: if it is a [`None`], no further + /// elements are taken, and the [`None`] is returned. Should no [`None`] + /// occur, the sum of all elements is returned. + /// + /// # Examples + /// + /// This sums up the position of the character 'a' in a vector of strings, + /// if a word did not have the character 'a' the operation returns `None`: + /// + /// ``` + /// let words = vec!["have", "a", "great", "day"]; + /// let total: Option = words.iter().map(|w| w.find('a')).sum(); + /// assert_eq!(total, Some(5)); + /// let words = vec!["have", "a", "good", "day"]; + /// let total: Option = words.iter().map(|w| w.find('a')).sum(); + /// assert_eq!(total, None); + /// ``` + fn sum(iter: I) -> Option + where + I: Iterator>, + { + iter::try_process(iter, |i| i.sum()) + } +} + +#[stable(feature = "iter_arith_traits_option", since = "1.37.0")] +impl Product> for Option +where + T: Product, +{ + /// Takes each element in the [`Iterator`]: if it is a [`None`], no further + /// elements are taken, and the [`None`] is returned. Should no [`None`] + /// occur, the product of all elements is returned. + /// + /// # Examples + /// + /// This multiplies each number in a vector of strings, + /// if a string could not be parsed the operation returns `None`: + /// + /// ``` + /// let nums = vec!["5", "10", "1", "2"]; + /// let total: Option = nums.iter().map(|w| w.parse::().ok()).product(); + /// assert_eq!(total, Some(100)); + /// let nums = vec!["5", "10", "one", "2"]; + /// let total: Option = nums.iter().map(|w| w.parse::().ok()).product(); + /// assert_eq!(total, None); + /// ``` + fn product(iter: I) -> Option + where + I: Iterator>, + { + iter::try_process(iter, |i| i.product()) + } +} diff --git a/CoqOfRust/core/iter/traits/collect.rs b/CoqOfRust/core/iter/traits/collect.rs new file mode 100644 index 000000000..2cf2ea58f --- /dev/null +++ b/CoqOfRust/core/iter/traits/collect.rs @@ -0,0 +1,622 @@ +use super::TrustedLen; + +/// Conversion from an [`Iterator`]. +/// +/// By implementing `FromIterator` for a type, you define how it will be +/// created from an iterator. This is common for types which describe a +/// collection of some kind. +/// +/// If you want to create a collection from the contents of an iterator, the +/// [`Iterator::collect()`] method is preferred. However, when you need to +/// specify the container type, [`FromIterator::from_iter()`] can be more +/// readable than using a turbofish (e.g. `::>()`). See the +/// [`Iterator::collect()`] documentation for more examples of its use. +/// +/// See also: [`IntoIterator`]. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let five_fives = std::iter::repeat(5).take(5); +/// +/// let v = Vec::from_iter(five_fives); +/// +/// assert_eq!(v, vec![5, 5, 5, 5, 5]); +/// ``` +/// +/// Using [`Iterator::collect()`] to implicitly use `FromIterator`: +/// +/// ``` +/// let five_fives = std::iter::repeat(5).take(5); +/// +/// let v: Vec = five_fives.collect(); +/// +/// assert_eq!(v, vec![5, 5, 5, 5, 5]); +/// ``` +/// +/// Using [`FromIterator::from_iter()`] as a more readable alternative to +/// [`Iterator::collect()`]: +/// +/// ``` +/// use std::collections::VecDeque; +/// let first = (0..10).collect::>(); +/// let second = VecDeque::from_iter(0..10); +/// +/// assert_eq!(first, second); +/// ``` +/// +/// Implementing `FromIterator` for your type: +/// +/// ``` +/// // A sample collection, that's just a wrapper over Vec +/// #[derive(Debug)] +/// struct MyCollection(Vec); +/// +/// // Let's give it some methods so we can create one and add things +/// // to it. +/// impl MyCollection { +/// fn new() -> MyCollection { +/// MyCollection(Vec::new()) +/// } +/// +/// fn add(&mut self, elem: i32) { +/// self.0.push(elem); +/// } +/// } +/// +/// // and we'll implement FromIterator +/// impl FromIterator for MyCollection { +/// fn from_iter>(iter: I) -> Self { +/// let mut c = MyCollection::new(); +/// +/// for i in iter { +/// c.add(i); +/// } +/// +/// c +/// } +/// } +/// +/// // Now we can make a new iterator... +/// let iter = (0..5).into_iter(); +/// +/// // ... and make a MyCollection out of it +/// let c = MyCollection::from_iter(iter); +/// +/// assert_eq!(c.0, vec![0, 1, 2, 3, 4]); +/// +/// // collect works too! +/// +/// let iter = (0..5).into_iter(); +/// let c: MyCollection = iter.collect(); +/// +/// assert_eq!(c.0, vec![0, 1, 2, 3, 4]); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + on( + _Self = "&[{A}]", + message = "a slice of type `{Self}` cannot be built since we need to store the elements somewhere", + label = "try explicitly collecting into a `Vec<{A}>`", + ), + on( + all(A = "{integer}", any(_Self = "&[{integral}]",)), + message = "a slice of type `{Self}` cannot be built since we need to store the elements somewhere", + label = "try explicitly collecting into a `Vec<{A}>`", + ), + on( + _Self = "[{A}]", + message = "a slice of type `{Self}` cannot be built since `{Self}` has no definite size", + label = "try explicitly collecting into a `Vec<{A}>`", + ), + on( + all(A = "{integer}", any(_Self = "[{integral}]",)), + message = "a slice of type `{Self}` cannot be built since `{Self}` has no definite size", + label = "try explicitly collecting into a `Vec<{A}>`", + ), + on( + _Self = "[{A}; _]", + message = "an array of type `{Self}` cannot be built directly from an iterator", + label = "try collecting into a `Vec<{A}>`, then using `.try_into()`", + ), + on( + all(A = "{integer}", any(_Self = "[{integral}; _]",)), + message = "an array of type `{Self}` cannot be built directly from an iterator", + label = "try collecting into a `Vec<{A}>`, then using `.try_into()`", + ), + message = "a value of type `{Self}` cannot be built from an iterator \ + over elements of type `{A}`", + label = "value of type `{Self}` cannot be built from `std::iter::Iterator`" +)] +#[rustc_diagnostic_item = "FromIterator"] +pub trait FromIterator: Sized { + /// Creates a value from an iterator. + /// + /// See the [module-level documentation] for more. + /// + /// [module-level documentation]: crate::iter + /// + /// # Examples + /// + /// ``` + /// let five_fives = std::iter::repeat(5).take(5); + /// + /// let v = Vec::from_iter(five_fives); + /// + /// assert_eq!(v, vec![5, 5, 5, 5, 5]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "from_iter_fn"] + fn from_iter>(iter: T) -> Self; +} + +/// This implementation turns an iterator of tuples into a tuple of types which implement +/// [`Default`] and [`Extend`]. +/// +/// This is similar to [`Iterator::unzip`], but is also composable with other [`FromIterator`] +/// implementations: +/// +/// ```rust +/// # fn main() -> Result<(), core::num::ParseIntError> { +/// let string = "1,2,123,4"; +/// +/// let (numbers, lengths): (Vec<_>, Vec<_>) = string +/// .split(',') +/// .map(|s| s.parse().map(|n: u32| (n, s.len()))) +/// .collect::>()?; +/// +/// assert_eq!(numbers, [1, 2, 123, 4]); +/// assert_eq!(lengths, [1, 1, 3, 1]); +/// # Ok(()) } +/// ``` +#[stable(feature = "from_iterator_for_tuple", since = "1.79.0")] +impl FromIterator<(AE, BE)> for (A, B) +where + A: Default + Extend, + B: Default + Extend, +{ + fn from_iter>(iter: I) -> Self { + let mut res = <(A, B)>::default(); + res.extend(iter); + + res + } +} + +/// Conversion into an [`Iterator`]. +/// +/// By implementing `IntoIterator` for a type, you define how it will be +/// converted to an iterator. This is common for types which describe a +/// collection of some kind. +/// +/// One benefit of implementing `IntoIterator` is that your type will [work +/// with Rust's `for` loop syntax](crate::iter#for-loops-and-intoiterator). +/// +/// See also: [`FromIterator`]. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let v = [1, 2, 3]; +/// let mut iter = v.into_iter(); +/// +/// assert_eq!(Some(1), iter.next()); +/// assert_eq!(Some(2), iter.next()); +/// assert_eq!(Some(3), iter.next()); +/// assert_eq!(None, iter.next()); +/// ``` +/// Implementing `IntoIterator` for your type: +/// +/// ``` +/// // A sample collection, that's just a wrapper over Vec +/// #[derive(Debug)] +/// struct MyCollection(Vec); +/// +/// // Let's give it some methods so we can create one and add things +/// // to it. +/// impl MyCollection { +/// fn new() -> MyCollection { +/// MyCollection(Vec::new()) +/// } +/// +/// fn add(&mut self, elem: i32) { +/// self.0.push(elem); +/// } +/// } +/// +/// // and we'll implement IntoIterator +/// impl IntoIterator for MyCollection { +/// type Item = i32; +/// type IntoIter = std::vec::IntoIter; +/// +/// fn into_iter(self) -> Self::IntoIter { +/// self.0.into_iter() +/// } +/// } +/// +/// // Now we can make a new collection... +/// let mut c = MyCollection::new(); +/// +/// // ... add some stuff to it ... +/// c.add(0); +/// c.add(1); +/// c.add(2); +/// +/// // ... and then turn it into an Iterator: +/// for (i, n) in c.into_iter().enumerate() { +/// assert_eq!(i as i32, n); +/// } +/// ``` +/// +/// It is common to use `IntoIterator` as a trait bound. This allows +/// the input collection type to change, so long as it is still an +/// iterator. Additional bounds can be specified by restricting on +/// `Item`: +/// +/// ```rust +/// fn collect_as_strings(collection: T) -> Vec +/// where +/// T: IntoIterator, +/// T::Item: std::fmt::Debug, +/// { +/// collection +/// .into_iter() +/// .map(|item| format!("{item:?}")) +/// .collect() +/// } +/// ``` +#[rustc_diagnostic_item = "IntoIterator"] +#[rustc_on_unimplemented( + on( + _Self = "core::ops::range::RangeTo", + label = "if you meant to iterate until a value, add a starting value", + note = "`..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a \ + bounded `Range`: `0..end`" + ), + on( + _Self = "core::ops::range::RangeToInclusive", + label = "if you meant to iterate until a value (including it), add a starting value", + note = "`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \ + to have a bounded `RangeInclusive`: `0..=end`" + ), + on( + _Self = "[]", + label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`" + ), + on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"), + on( + _Self = "alloc::vec::Vec", + label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`" + ), + on( + _Self = "&str", + label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`" + ), + on( + _Self = "alloc::string::String", + label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`" + ), + on( + _Self = "{integral}", + note = "if you want to iterate between `start` until a value `end`, use the exclusive range \ + syntax `start..end` or the inclusive range syntax `start..=end`" + ), + on( + _Self = "{float}", + note = "if you want to iterate between `start` until a value `end`, use the exclusive range \ + syntax `start..end` or the inclusive range syntax `start..=end`" + ), + label = "`{Self}` is not an iterator", + message = "`{Self}` is not an iterator" +)] +#[rustc_skip_during_method_dispatch(array, boxed_slice)] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait IntoIterator { + /// The type of the elements being iterated over. + #[stable(feature = "rust1", since = "1.0.0")] + type Item; + + /// Which kind of iterator are we turning this into? + #[stable(feature = "rust1", since = "1.0.0")] + type IntoIter: Iterator; + + /// Creates an iterator from a value. + /// + /// See the [module-level documentation] for more. + /// + /// [module-level documentation]: crate::iter + /// + /// # Examples + /// + /// ``` + /// let v = [1, 2, 3]; + /// let mut iter = v.into_iter(); + /// + /// assert_eq!(Some(1), iter.next()); + /// assert_eq!(Some(2), iter.next()); + /// assert_eq!(Some(3), iter.next()); + /// assert_eq!(None, iter.next()); + /// ``` + #[lang = "into_iter"] + #[stable(feature = "rust1", since = "1.0.0")] + fn into_iter(self) -> Self::IntoIter; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for I { + type Item = I::Item; + type IntoIter = I; + + #[inline] + fn into_iter(self) -> I { + self + } +} + +/// Extend a collection with the contents of an iterator. +/// +/// Iterators produce a series of values, and collections can also be thought +/// of as a series of values. The `Extend` trait bridges this gap, allowing you +/// to extend a collection by including the contents of that iterator. When +/// extending a collection with an already existing key, that entry is updated +/// or, in the case of collections that permit multiple entries with equal +/// keys, that entry is inserted. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// // You can extend a String with some chars: +/// let mut message = String::from("The first three letters are: "); +/// +/// message.extend(&['a', 'b', 'c']); +/// +/// assert_eq!("abc", &message[29..32]); +/// ``` +/// +/// Implementing `Extend`: +/// +/// ``` +/// // A sample collection, that's just a wrapper over Vec +/// #[derive(Debug)] +/// struct MyCollection(Vec); +/// +/// // Let's give it some methods so we can create one and add things +/// // to it. +/// impl MyCollection { +/// fn new() -> MyCollection { +/// MyCollection(Vec::new()) +/// } +/// +/// fn add(&mut self, elem: i32) { +/// self.0.push(elem); +/// } +/// } +/// +/// // since MyCollection has a list of i32s, we implement Extend for i32 +/// impl Extend for MyCollection { +/// +/// // This is a bit simpler with the concrete type signature: we can call +/// // extend on anything which can be turned into an Iterator which gives +/// // us i32s. Because we need i32s to put into MyCollection. +/// fn extend>(&mut self, iter: T) { +/// +/// // The implementation is very straightforward: loop through the +/// // iterator, and add() each element to ourselves. +/// for elem in iter { +/// self.add(elem); +/// } +/// } +/// } +/// +/// let mut c = MyCollection::new(); +/// +/// c.add(5); +/// c.add(6); +/// c.add(7); +/// +/// // let's extend our collection with three more numbers +/// c.extend(vec![1, 2, 3]); +/// +/// // we've added these elements onto the end +/// assert_eq!("MyCollection([5, 6, 7, 1, 2, 3])", format!("{c:?}")); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Extend { + /// Extends a collection with the contents of an iterator. + /// + /// As this is the only required method for this trait, the [trait-level] docs + /// contain more details. + /// + /// [trait-level]: Extend + /// + /// # Examples + /// + /// ``` + /// // You can extend a String with some chars: + /// let mut message = String::from("abc"); + /// + /// message.extend(['d', 'e', 'f'].iter()); + /// + /// assert_eq!("abcdef", &message); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn extend>(&mut self, iter: T); + + /// Extends a collection with exactly one element. + #[unstable(feature = "extend_one", issue = "72631")] + fn extend_one(&mut self, item: A) { + self.extend(Some(item)); + } + + /// Reserves capacity in a collection for the given number of additional elements. + /// + /// The default implementation does nothing. + #[unstable(feature = "extend_one", issue = "72631")] + fn extend_reserve(&mut self, additional: usize) { + let _ = additional; + } + + /// Extends a collection with one element, without checking there is enough capacity for it. + /// + /// # Safety + /// + /// **For callers:** This must only be called when we know the collection has enough capacity + /// to contain the new item, for example because we previously called `extend_reserve`. + /// + /// **For implementors:** For a collection to unsafely rely on this method's safety precondition (that is, + /// invoke UB if they are violated), it must implement `extend_reserve` correctly. In other words, + /// callers may assume that if they `extend_reserve`ed enough space they can call this method. + + // This method is for internal usage only. It is only on the trait because of specialization's limitations. + #[unstable(feature = "extend_one_unchecked", issue = "none")] + #[doc(hidden)] + unsafe fn extend_one_unchecked(&mut self, item: A) + where + Self: Sized, + { + self.extend_one(item); + } +} + +#[stable(feature = "extend_for_unit", since = "1.28.0")] +impl Extend<()> for () { + fn extend>(&mut self, iter: T) { + iter.into_iter().for_each(drop) + } + fn extend_one(&mut self, _item: ()) {} +} + +#[stable(feature = "extend_for_tuple", since = "1.56.0")] +impl Extend<(A, B)> for (ExtendA, ExtendB) +where + ExtendA: Extend, + ExtendB: Extend, +{ + /// Allows to `extend` a tuple of collections that also implement `Extend`. + /// + /// See also: [`Iterator::unzip`] + /// + /// # Examples + /// ``` + /// let mut tuple = (vec![0], vec![1]); + /// tuple.extend([(2, 3), (4, 5), (6, 7)]); + /// assert_eq!(tuple.0, [0, 2, 4, 6]); + /// assert_eq!(tuple.1, [1, 3, 5, 7]); + /// + /// // also allows for arbitrarily nested tuples as elements + /// let mut nested_tuple = (vec![1], (vec![2], vec![3])); + /// nested_tuple.extend([(4, (5, 6)), (7, (8, 9))]); + /// + /// let (a, (b, c)) = nested_tuple; + /// assert_eq!(a, [1, 4, 7]); + /// assert_eq!(b, [2, 5, 8]); + /// assert_eq!(c, [3, 6, 9]); + /// ``` + fn extend>(&mut self, into_iter: T) { + let (a, b) = self; + let iter = into_iter.into_iter(); + SpecTupleExtend::extend(iter, a, b); + } + + fn extend_one(&mut self, item: (A, B)) { + self.0.extend_one(item.0); + self.1.extend_one(item.1); + } + + fn extend_reserve(&mut self, additional: usize) { + self.0.extend_reserve(additional); + self.1.extend_reserve(additional); + } + + unsafe fn extend_one_unchecked(&mut self, item: (A, B)) { + // SAFETY: Those are our safety preconditions, and we correctly forward `extend_reserve`. + unsafe { + self.0.extend_one_unchecked(item.0); + self.1.extend_one_unchecked(item.1); + } + } +} + +fn default_extend_tuple( + iter: impl Iterator, + a: &mut ExtendA, + b: &mut ExtendB, +) where + ExtendA: Extend, + ExtendB: Extend, +{ + fn extend<'a, A, B>( + a: &'a mut impl Extend, + b: &'a mut impl Extend, + ) -> impl FnMut((), (A, B)) + 'a { + move |(), (t, u)| { + a.extend_one(t); + b.extend_one(u); + } + } + + let (lower_bound, _) = iter.size_hint(); + if lower_bound > 0 { + a.extend_reserve(lower_bound); + b.extend_reserve(lower_bound); + } + + iter.fold((), extend(a, b)); +} + +trait SpecTupleExtend { + fn extend(self, a: &mut A, b: &mut B); +} + +impl SpecTupleExtend for Iter +where + ExtendA: Extend, + ExtendB: Extend, + Iter: Iterator, +{ + default fn extend(self, a: &mut ExtendA, b: &mut ExtendB) { + default_extend_tuple(self, a, b); + } +} + +impl SpecTupleExtend for Iter +where + ExtendA: Extend, + ExtendB: Extend, + Iter: TrustedLen, +{ + fn extend(self, a: &mut ExtendA, b: &mut ExtendB) { + fn extend<'a, A, B>( + a: &'a mut impl Extend, + b: &'a mut impl Extend, + ) -> impl FnMut((), (A, B)) + 'a { + // SAFETY: We reserve enough space for the `size_hint`, and the iterator is `TrustedLen` + // so its `size_hint` is exact. + move |(), (t, u)| unsafe { + a.extend_one_unchecked(t); + b.extend_one_unchecked(u); + } + } + + let (lower_bound, upper_bound) = self.size_hint(); + + if upper_bound.is_none() { + // We cannot reserve more than `usize::MAX` items, and this is likely to go out of memory anyway. + default_extend_tuple(self, a, b); + return; + } + + if lower_bound > 0 { + a.extend_reserve(lower_bound); + b.extend_reserve(lower_bound); + } + + self.fold((), extend(a, b)); + } +} diff --git a/CoqOfRust/core/iter/traits/double_ended.rs b/CoqOfRust/core/iter/traits/double_ended.rs new file mode 100644 index 000000000..3b1267857 --- /dev/null +++ b/CoqOfRust/core/iter/traits/double_ended.rs @@ -0,0 +1,445 @@ +use crate::num::NonZero; +use crate::ops::{ControlFlow, Try}; + +/// An iterator able to yield elements from both ends. +/// +/// Something that implements `DoubleEndedIterator` has one extra capability +/// over something that implements [`Iterator`]: the ability to also take +/// `Item`s from the back, as well as the front. +/// +/// It is important to note that both back and forth work on the same range, +/// and do not cross: iteration is over when they meet in the middle. +/// +/// In a similar fashion to the [`Iterator`] protocol, once a +/// `DoubleEndedIterator` returns [`None`] from a [`next_back()`], calling it +/// again may or may not ever return [`Some`] again. [`next()`] and +/// [`next_back()`] are interchangeable for this purpose. +/// +/// [`next_back()`]: DoubleEndedIterator::next_back +/// [`next()`]: Iterator::next +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let numbers = vec![1, 2, 3, 4, 5, 6]; +/// +/// let mut iter = numbers.iter(); +/// +/// assert_eq!(Some(&1), iter.next()); +/// assert_eq!(Some(&6), iter.next_back()); +/// assert_eq!(Some(&5), iter.next_back()); +/// assert_eq!(Some(&2), iter.next()); +/// assert_eq!(Some(&3), iter.next()); +/// assert_eq!(Some(&4), iter.next()); +/// assert_eq!(None, iter.next()); +/// assert_eq!(None, iter.next_back()); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "DoubleEndedIterator")] +pub trait DoubleEndedIterator: Iterator { + /// Removes and returns an element from the end of the iterator. + /// + /// Returns `None` when there are no more elements. + /// + /// The [trait-level] docs contain more details. + /// + /// [trait-level]: DoubleEndedIterator + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let numbers = vec![1, 2, 3, 4, 5, 6]; + /// + /// let mut iter = numbers.iter(); + /// + /// assert_eq!(Some(&1), iter.next()); + /// assert_eq!(Some(&6), iter.next_back()); + /// assert_eq!(Some(&5), iter.next_back()); + /// assert_eq!(Some(&2), iter.next()); + /// assert_eq!(Some(&3), iter.next()); + /// assert_eq!(Some(&4), iter.next()); + /// assert_eq!(None, iter.next()); + /// assert_eq!(None, iter.next_back()); + /// ``` + /// + /// # Remarks + /// + /// The elements yielded by `DoubleEndedIterator`'s methods may differ from + /// the ones yielded by [`Iterator`]'s methods: + /// + /// ``` + /// let vec = vec![(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b')]; + /// let uniq_by_fst_comp = || { + /// let mut seen = std::collections::HashSet::new(); + /// vec.iter().copied().filter(move |x| seen.insert(x.0)) + /// }; + /// + /// assert_eq!(uniq_by_fst_comp().last(), Some((2, 'a'))); + /// assert_eq!(uniq_by_fst_comp().next_back(), Some((2, 'b'))); + /// + /// assert_eq!( + /// uniq_by_fst_comp().fold(vec![], |mut v, x| {v.push(x); v}), + /// vec![(1, 'a'), (2, 'a')] + /// ); + /// assert_eq!( + /// uniq_by_fst_comp().rfold(vec![], |mut v, x| {v.push(x); v}), + /// vec![(2, 'b'), (1, 'c')] + /// ); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn next_back(&mut self) -> Option; + + /// Advances the iterator from the back by `n` elements. + /// + /// `advance_back_by` is the reverse version of [`advance_by`]. This method will + /// eagerly skip `n` elements starting from the back by calling [`next_back`] up + /// to `n` times until [`None`] is encountered. + /// + /// `advance_back_by(n)` will return `Ok(())` if the iterator successfully advances by + /// `n` elements, or a `Err(NonZero)` with value `k` if [`None`] is encountered, where `k` + /// is remaining number of steps that could not be advanced because the iterator ran out. + /// If `self` is empty and `n` is non-zero, then this returns `Err(n)`. + /// Otherwise, `k` is always less than `n`. + /// + /// Calling `advance_back_by(0)` can do meaningful work, for example [`Flatten`] can advance its + /// outer iterator until it finds an inner iterator that is not empty, which then often + /// allows it to return a more accurate `size_hint()` than in its initial state. + /// + /// [`advance_by`]: Iterator::advance_by + /// [`Flatten`]: crate::iter::Flatten + /// [`next_back`]: DoubleEndedIterator::next_back + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_advance_by)] + /// + /// use std::num::NonZero; + /// + /// let a = [3, 4, 5, 6]; + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.advance_back_by(2), Ok(())); + /// assert_eq!(iter.next_back(), Some(&4)); + /// assert_eq!(iter.advance_back_by(0), Ok(())); + /// assert_eq!(iter.advance_back_by(100), Err(NonZero::new(99).unwrap())); // only `&3` was skipped + /// ``` + /// + /// [`Ok(())`]: Ok + /// [`Err(k)`]: Err + #[inline] + #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + for i in 0..n { + if self.next_back().is_none() { + // SAFETY: `i` is always less than `n`. + return Err(unsafe { NonZero::new_unchecked(n - i) }); + } + } + Ok(()) + } + + /// Returns the `n`th element from the end of the iterator. + /// + /// This is essentially the reversed version of [`Iterator::nth()`]. + /// Although like most indexing operations, the count starts from zero, so + /// `nth_back(0)` returns the first value from the end, `nth_back(1)` the + /// second, and so on. + /// + /// Note that all elements between the end and the returned element will be + /// consumed, including the returned element. This also means that calling + /// `nth_back(0)` multiple times on the same iterator will return different + /// elements. + /// + /// `nth_back()` will return [`None`] if `n` is greater than or equal to the + /// length of the iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// assert_eq!(a.iter().nth_back(2), Some(&1)); + /// ``` + /// + /// Calling `nth_back()` multiple times doesn't rewind the iterator: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.nth_back(1), Some(&2)); + /// assert_eq!(iter.nth_back(1), None); + /// ``` + /// + /// Returning `None` if there are less than `n + 1` elements: + /// + /// ``` + /// let a = [1, 2, 3]; + /// assert_eq!(a.iter().nth_back(10), None); + /// ``` + #[inline] + #[stable(feature = "iter_nth_back", since = "1.37.0")] + fn nth_back(&mut self, n: usize) -> Option { + if self.advance_back_by(n).is_err() { + return None; + } + self.next_back() + } + + /// This is the reverse version of [`Iterator::try_fold()`]: it takes + /// elements starting from the back of the iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = ["1", "2", "3"]; + /// let sum = a.iter() + /// .map(|&s| s.parse::()) + /// .try_rfold(0, |acc, x| x.and_then(|y| Ok(acc + y))); + /// assert_eq!(sum, Ok(6)); + /// ``` + /// + /// Short-circuiting: + /// + /// ``` + /// let a = ["1", "rust", "3"]; + /// let mut it = a.iter(); + /// let sum = it + /// .by_ref() + /// .map(|&s| s.parse::()) + /// .try_rfold(0, |acc, x| x.and_then(|y| Ok(acc + y))); + /// assert!(sum.is_err()); + /// + /// // Because it short-circuited, the remaining elements are still + /// // available through the iterator. + /// assert_eq!(it.next_back(), Some(&"1")); + /// ``` + #[inline] + #[stable(feature = "iterator_try_fold", since = "1.27.0")] + fn try_rfold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x)?; + } + try { accum } + } + + /// An iterator method that reduces the iterator's elements to a single, + /// final value, starting from the back. + /// + /// This is the reverse version of [`Iterator::fold()`]: it takes elements + /// starting from the back of the iterator. + /// + /// `rfold()` takes two arguments: an initial value, and a closure with two + /// arguments: an 'accumulator', and an element. The closure returns the value that + /// the accumulator should have for the next iteration. + /// + /// The initial value is the value the accumulator will have on the first + /// call. + /// + /// After applying this closure to every element of the iterator, `rfold()` + /// returns the accumulator. + /// + /// This operation is sometimes called 'reduce' or 'inject'. + /// + /// Folding is useful whenever you have a collection of something, and want + /// to produce a single value from it. + /// + /// Note: `rfold()` combines elements in a *right-associative* fashion. For associative + /// operators like `+`, the order the elements are combined in is not important, but for non-associative + /// operators like `-` the order will affect the final result. + /// For a *left-associative* version of `rfold()`, see [`Iterator::fold()`]. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// // the sum of all of the elements of a + /// let sum = a.iter() + /// .rfold(0, |acc, &x| acc + x); + /// + /// assert_eq!(sum, 6); + /// ``` + /// + /// This example demonstrates the right-associative nature of `rfold()`: + /// it builds a string, starting with an initial value + /// and continuing with each element from the back until the front: + /// + /// ``` + /// let numbers = [1, 2, 3, 4, 5]; + /// + /// let zero = "0".to_string(); + /// + /// let result = numbers.iter().rfold(zero, |acc, &x| { + /// format!("({x} + {acc})") + /// }); + /// + /// assert_eq!(result, "(1 + (2 + (3 + (4 + (5 + 0)))))"); + /// ``` + #[doc(alias = "foldr")] + #[inline] + #[stable(feature = "iter_rfold", since = "1.27.0")] + fn rfold(mut self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x); + } + accum + } + + /// Searches for an element of an iterator from the back that satisfies a predicate. + /// + /// `rfind()` takes a closure that returns `true` or `false`. It applies + /// this closure to each element of the iterator, starting at the end, and if any + /// of them return `true`, then `rfind()` returns [`Some(element)`]. If they all return + /// `false`, it returns [`None`]. + /// + /// `rfind()` is short-circuiting; in other words, it will stop processing + /// as soon as the closure returns `true`. + /// + /// Because `rfind()` takes a reference, and many iterators iterate over + /// references, this leads to a possibly confusing situation where the + /// argument is a double reference. You can see this effect in the + /// examples below, with `&&x`. + /// + /// [`Some(element)`]: Some + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2)); + /// + /// assert_eq!(a.iter().rfind(|&&x| x == 5), None); + /// ``` + /// + /// Stopping at the first `true`: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.rfind(|&&x| x == 2), Some(&2)); + /// + /// // we can still use `iter`, as there are more elements. + /// assert_eq!(iter.next_back(), Some(&1)); + /// ``` + #[inline] + #[stable(feature = "iter_rfind", since = "1.27.0")] + fn rfind

(&mut self, predicate: P) -> Option + where + Self: Sized, + P: FnMut(&Self::Item) -> bool, + { + #[inline] + fn check(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow { + move |(), x| { + if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) } + } + } + + self.try_rfold((), check(predicate)).break_value() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I { + fn next_back(&mut self) -> Option { + (**self).next_back() + } + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + (**self).advance_back_by(n) + } + fn nth_back(&mut self, n: usize) -> Option { + (**self).nth_back(n) + } + fn rfold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.spec_rfold(init, f) + } + fn try_rfold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.spec_try_rfold(init, f) + } +} + +/// Helper trait to specialize `rfold` and `rtry_fold` for `&mut I where I: Sized` +trait DoubleEndedIteratorRefSpec: DoubleEndedIterator { + fn spec_rfold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B; + + fn spec_try_rfold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try; +} + +impl DoubleEndedIteratorRefSpec for &mut I { + default fn spec_rfold(self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x); + } + accum + } + + default fn spec_try_rfold(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x)?; + } + try { accum } + } +} + +impl DoubleEndedIteratorRefSpec for &mut I { + impl_fold_via_try_fold! { spec_rfold -> spec_try_rfold } + + fn spec_try_rfold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + (**self).try_rfold(init, f) + } +} diff --git a/CoqOfRust/core/iter/traits/exact_size.rs b/CoqOfRust/core/iter/traits/exact_size.rs new file mode 100644 index 000000000..908830d8a --- /dev/null +++ b/CoqOfRust/core/iter/traits/exact_size.rs @@ -0,0 +1,161 @@ +/// An iterator that knows its exact length. +/// +/// Many [`Iterator`]s don't know how many times they will iterate, but some do. +/// If an iterator knows how many times it can iterate, providing access to +/// that information can be useful. For example, if you want to iterate +/// backwards, a good start is to know where the end is. +/// +/// When implementing an `ExactSizeIterator`, you must also implement +/// [`Iterator`]. When doing so, the implementation of [`Iterator::size_hint`] +/// *must* return the exact size of the iterator. +/// +/// The [`len`] method has a default implementation, so you usually shouldn't +/// implement it. However, you may be able to provide a more performant +/// implementation than the default, so overriding it in this case makes sense. +/// +/// Note that this trait is a safe trait and as such does *not* and *cannot* +/// guarantee that the returned length is correct. This means that `unsafe` +/// code **must not** rely on the correctness of [`Iterator::size_hint`]. The +/// unstable and unsafe [`TrustedLen`](super::marker::TrustedLen) trait gives +/// this additional guarantee. +/// +/// [`len`]: ExactSizeIterator::len +/// +/// # When *shouldn't* an adapter be `ExactSizeIterator`? +/// +/// If an adapter makes an iterator *longer*, then it's usually incorrect for +/// that adapter to implement `ExactSizeIterator`. The inner exact-sized +/// iterator might already be `usize::MAX`-long, and thus the length of the +/// longer adapted iterator would no longer be exactly representable in `usize`. +/// +/// This is why [`Chain`](crate::iter::Chain) isn't `ExactSizeIterator`, +/// even when `A` and `B` are both `ExactSizeIterator`. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// // a finite range knows exactly how many times it will iterate +/// let five = 0..5; +/// +/// assert_eq!(5, five.len()); +/// ``` +/// +/// In the [module-level docs], we implemented an [`Iterator`], `Counter`. +/// Let's implement `ExactSizeIterator` for it as well: +/// +/// [module-level docs]: crate::iter +/// +/// ``` +/// # struct Counter { +/// # count: usize, +/// # } +/// # impl Counter { +/// # fn new() -> Counter { +/// # Counter { count: 0 } +/// # } +/// # } +/// # impl Iterator for Counter { +/// # type Item = usize; +/// # fn next(&mut self) -> Option { +/// # self.count += 1; +/// # if self.count < 6 { +/// # Some(self.count) +/// # } else { +/// # None +/// # } +/// # } +/// # } +/// impl ExactSizeIterator for Counter { +/// // We can easily calculate the remaining number of iterations. +/// fn len(&self) -> usize { +/// 5 - self.count +/// } +/// } +/// +/// // And now we can use it! +/// +/// let mut counter = Counter::new(); +/// +/// assert_eq!(5, counter.len()); +/// let _ = counter.next(); +/// assert_eq!(4, counter.len()); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub trait ExactSizeIterator: Iterator { + /// Returns the exact remaining length of the iterator. + /// + /// The implementation ensures that the iterator will return exactly `len()` + /// more times a [`Some(T)`] value, before returning [`None`]. + /// This method has a default implementation, so you usually should not + /// implement it directly. However, if you can provide a more efficient + /// implementation, you can do so. See the [trait-level] docs for an + /// example. + /// + /// This function has the same safety guarantees as the + /// [`Iterator::size_hint`] function. + /// + /// [trait-level]: ExactSizeIterator + /// [`Some(T)`]: Some + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // a finite range knows exactly how many times it will iterate + /// let mut range = 0..5; + /// + /// assert_eq!(5, range.len()); + /// let _ = range.next(); + /// assert_eq!(4, range.len()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn len(&self) -> usize { + let (lower, upper) = self.size_hint(); + // Note: This assertion is overly defensive, but it checks the invariant + // guaranteed by the trait. If this trait were rust-internal, + // we could use debug_assert!; assert_eq! will check all Rust user + // implementations too. + assert_eq!(upper, Some(lower)); + lower + } + + /// Returns `true` if the iterator is empty. + /// + /// This method has a default implementation using + /// [`ExactSizeIterator::len()`], so you don't need to implement it yourself. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(exact_size_is_empty)] + /// + /// let mut one_element = std::iter::once(0); + /// assert!(!one_element.is_empty()); + /// + /// assert_eq!(one_element.next(), Some(0)); + /// assert!(one_element.is_empty()); + /// + /// assert_eq!(one_element.next(), None); + /// ``` + #[inline] + #[unstable(feature = "exact_size_is_empty", issue = "35428")] + fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for &mut I { + fn len(&self) -> usize { + (**self).len() + } + fn is_empty(&self) -> bool { + (**self).is_empty() + } +} diff --git a/CoqOfRust/core/iter/traits/iterator.rs b/CoqOfRust/core/iter/traits/iterator.rs new file mode 100644 index 000000000..38dfbbef3 --- /dev/null +++ b/CoqOfRust/core/iter/traits/iterator.rs @@ -0,0 +1,4099 @@ +use super::super::{ + ArrayChunks, ByRefSized, Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, FlatMap, + Flatten, Fuse, Inspect, Intersperse, IntersperseWith, Map, MapWhile, MapWindows, Peekable, + Product, Rev, Scan, Skip, SkipWhile, StepBy, Sum, Take, TakeWhile, TrustedRandomAccessNoCoerce, + Zip, try_process, +}; +use crate::array; +use crate::cmp::{self, Ordering}; +use crate::num::NonZero; +use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; + +fn _assert_is_dyn_compatible(_: &dyn Iterator) {} + +/// A trait for dealing with iterators. +/// +/// This is the main iterator trait. For more about the concept of iterators +/// generally, please see the [module-level documentation]. In particular, you +/// may want to know how to [implement `Iterator`][impl]. +/// +/// [module-level documentation]: crate::iter +/// [impl]: crate::iter#implementing-iterator +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + on( + _Self = "core::ops::range::RangeTo", + note = "you might have meant to use a bounded `Range`" + ), + on( + _Self = "core::ops::range::RangeToInclusive", + note = "you might have meant to use a bounded `RangeInclusive`" + ), + label = "`{Self}` is not an iterator", + message = "`{Self}` is not an iterator" +)] +#[doc(notable_trait)] +#[lang = "iterator"] +#[rustc_diagnostic_item = "Iterator"] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub trait Iterator { + /// The type of the elements being iterated over. + #[rustc_diagnostic_item = "IteratorItem"] + #[stable(feature = "rust1", since = "1.0.0")] + type Item; + + /// Advances the iterator and returns the next value. + /// + /// Returns [`None`] when iteration is finished. Individual iterator + /// implementations may choose to resume iteration, and so calling `next()` + /// again may or may not eventually start returning [`Some(Item)`] again at some + /// point. + /// + /// [`Some(Item)`]: Some + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter(); + /// + /// // A call to next() returns the next value... + /// assert_eq!(Some(&1), iter.next()); + /// assert_eq!(Some(&2), iter.next()); + /// assert_eq!(Some(&3), iter.next()); + /// + /// // ... and then None once it's over. + /// assert_eq!(None, iter.next()); + /// + /// // More calls may or may not return `None`. Here, they always will. + /// assert_eq!(None, iter.next()); + /// assert_eq!(None, iter.next()); + /// ``` + #[lang = "next"] + #[stable(feature = "rust1", since = "1.0.0")] + fn next(&mut self) -> Option; + + /// Advances the iterator and returns an array containing the next `N` values. + /// + /// If there are not enough elements to fill the array then `Err` is returned + /// containing an iterator over the remaining elements. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_next_chunk)] + /// + /// let mut iter = "lorem".chars(); + /// + /// assert_eq!(iter.next_chunk().unwrap(), ['l', 'o']); // N is inferred as 2 + /// assert_eq!(iter.next_chunk().unwrap(), ['r', 'e', 'm']); // N is inferred as 3 + /// assert_eq!(iter.next_chunk::<4>().unwrap_err().as_slice(), &[]); // N is explicitly 4 + /// ``` + /// + /// Split a string and get the first three items. + /// + /// ``` + /// #![feature(iter_next_chunk)] + /// + /// let quote = "not all those who wander are lost"; + /// let [first, second, third] = quote.split_whitespace().next_chunk().unwrap(); + /// assert_eq!(first, "not"); + /// assert_eq!(second, "all"); + /// assert_eq!(third, "those"); + /// ``` + #[inline] + #[unstable(feature = "iter_next_chunk", reason = "recently added", issue = "98326")] + fn next_chunk( + &mut self, + ) -> Result<[Self::Item; N], array::IntoIter> + where + Self: Sized, + { + array::iter_next_chunk(self) + } + + /// Returns the bounds on the remaining length of the iterator. + /// + /// Specifically, `size_hint()` returns a tuple where the first element + /// is the lower bound, and the second element is the upper bound. + /// + /// The second half of the tuple that is returned is an [Option]<[usize]>. + /// A [`None`] here means that either there is no known upper bound, or the + /// upper bound is larger than [`usize`]. + /// + /// # Implementation notes + /// + /// It is not enforced that an iterator implementation yields the declared + /// number of elements. A buggy iterator may yield less than the lower bound + /// or more than the upper bound of elements. + /// + /// `size_hint()` is primarily intended to be used for optimizations such as + /// reserving space for the elements of the iterator, but must not be + /// trusted to e.g., omit bounds checks in unsafe code. An incorrect + /// implementation of `size_hint()` should not lead to memory safety + /// violations. + /// + /// That said, the implementation should provide a correct estimation, + /// because otherwise it would be a violation of the trait's protocol. + /// + /// The default implementation returns (0, [None]) which is correct for any + /// iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// let mut iter = a.iter(); + /// + /// assert_eq!((3, Some(3)), iter.size_hint()); + /// let _ = iter.next(); + /// assert_eq!((2, Some(2)), iter.size_hint()); + /// ``` + /// + /// A more complex example: + /// + /// ``` + /// // The even numbers in the range of zero to nine. + /// let iter = (0..10).filter(|x| x % 2 == 0); + /// + /// // We might iterate from zero to ten times. Knowing that it's five + /// // exactly wouldn't be possible without executing filter(). + /// assert_eq!((0, Some(10)), iter.size_hint()); + /// + /// // Let's add five more numbers with chain() + /// let iter = (0..10).filter(|x| x % 2 == 0).chain(15..20); + /// + /// // now both bounds are increased by five + /// assert_eq!((5, Some(15)), iter.size_hint()); + /// ``` + /// + /// Returning `None` for an upper bound: + /// + /// ``` + /// // an infinite iterator has no upper bound + /// // and the maximum possible lower bound + /// let iter = 0..; + /// + /// assert_eq!((usize::MAX, None), iter.size_hint()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn size_hint(&self) -> (usize, Option) { + (0, None) + } + + /// Consumes the iterator, counting the number of iterations and returning it. + /// + /// This method will call [`next`] repeatedly until [`None`] is encountered, + /// returning the number of times it saw [`Some`]. Note that [`next`] has to be + /// called at least once even if the iterator does not have any elements. + /// + /// [`next`]: Iterator::next + /// + /// # Overflow Behavior + /// + /// The method does no guarding against overflows, so counting elements of + /// an iterator with more than [`usize::MAX`] elements either produces the + /// wrong result or panics. If debug assertions are enabled, a panic is + /// guaranteed. + /// + /// # Panics + /// + /// This function might panic if the iterator has more than [`usize::MAX`] + /// elements. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// assert_eq!(a.iter().count(), 3); + /// + /// let a = [1, 2, 3, 4, 5]; + /// assert_eq!(a.iter().count(), 5); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn count(self) -> usize + where + Self: Sized, + { + self.fold( + 0, + #[rustc_inherit_overflow_checks] + |count, _| count + 1, + ) + } + + /// Consumes the iterator, returning the last element. + /// + /// This method will evaluate the iterator until it returns [`None`]. While + /// doing so, it keeps track of the current element. After [`None`] is + /// returned, `last()` will then return the last element it saw. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// assert_eq!(a.iter().last(), Some(&3)); + /// + /// let a = [1, 2, 3, 4, 5]; + /// assert_eq!(a.iter().last(), Some(&5)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn last(self) -> Option + where + Self: Sized, + { + #[inline] + fn some(_: Option, x: T) -> Option { + Some(x) + } + + self.fold(None, some) + } + + /// Advances the iterator by `n` elements. + /// + /// This method will eagerly skip `n` elements by calling [`next`] up to `n` + /// times until [`None`] is encountered. + /// + /// `advance_by(n)` will return `Ok(())` if the iterator successfully advances by + /// `n` elements, or a `Err(NonZero)` with value `k` if [`None`] is encountered, + /// where `k` is remaining number of steps that could not be advanced because the iterator ran out. + /// If `self` is empty and `n` is non-zero, then this returns `Err(n)`. + /// Otherwise, `k` is always less than `n`. + /// + /// Calling `advance_by(0)` can do meaningful work, for example [`Flatten`] + /// can advance its outer iterator until it finds an inner iterator that is not empty, which + /// then often allows it to return a more accurate `size_hint()` than in its initial state. + /// + /// [`Flatten`]: crate::iter::Flatten + /// [`next`]: Iterator::next + /// + /// # Examples + /// + /// ``` + /// #![feature(iter_advance_by)] + /// + /// use std::num::NonZero; + /// + /// let a = [1, 2, 3, 4]; + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.advance_by(2), Ok(())); + /// assert_eq!(iter.next(), Some(&3)); + /// assert_eq!(iter.advance_by(0), Ok(())); + /// assert_eq!(iter.advance_by(100), Err(NonZero::new(99).unwrap())); // only `&4` was skipped + /// ``` + #[inline] + #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + for i in 0..n { + if self.next().is_none() { + // SAFETY: `i` is always less than `n`. + return Err(unsafe { NonZero::new_unchecked(n - i) }); + } + } + Ok(()) + } + + /// Returns the `n`th element of the iterator. + /// + /// Like most indexing operations, the count starts from zero, so `nth(0)` + /// returns the first value, `nth(1)` the second, and so on. + /// + /// Note that all preceding elements, as well as the returned element, will be + /// consumed from the iterator. That means that the preceding elements will be + /// discarded, and also that calling `nth(0)` multiple times on the same iterator + /// will return different elements. + /// + /// `nth()` will return [`None`] if `n` is greater than or equal to the length of the + /// iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// assert_eq!(a.iter().nth(1), Some(&2)); + /// ``` + /// + /// Calling `nth()` multiple times doesn't rewind the iterator: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.nth(1), Some(&2)); + /// assert_eq!(iter.nth(1), None); + /// ``` + /// + /// Returning `None` if there are less than `n + 1` elements: + /// + /// ``` + /// let a = [1, 2, 3]; + /// assert_eq!(a.iter().nth(10), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn nth(&mut self, n: usize) -> Option { + self.advance_by(n).ok()?; + self.next() + } + + /// Creates an iterator starting at the same point, but stepping by + /// the given amount at each iteration. + /// + /// Note 1: The first element of the iterator will always be returned, + /// regardless of the step given. + /// + /// Note 2: The time at which ignored elements are pulled is not fixed. + /// `StepBy` behaves like the sequence `self.next()`, `self.nth(step-1)`, + /// `self.nth(step-1)`, …, but is also free to behave like the sequence + /// `advance_n_and_return_first(&mut self, step)`, + /// `advance_n_and_return_first(&mut self, step)`, … + /// Which way is used may change for some iterators for performance reasons. + /// The second way will advance the iterator earlier and may consume more items. + /// + /// `advance_n_and_return_first` is the equivalent of: + /// ``` + /// fn advance_n_and_return_first(iter: &mut I, n: usize) -> Option + /// where + /// I: Iterator, + /// { + /// let next = iter.next(); + /// if n > 1 { + /// iter.nth(n - 2); + /// } + /// next + /// } + /// ``` + /// + /// # Panics + /// + /// The method will panic if the given step is `0`. + /// + /// # Examples + /// + /// ``` + /// let a = [0, 1, 2, 3, 4, 5]; + /// let mut iter = a.iter().step_by(2); + /// + /// assert_eq!(iter.next(), Some(&0)); + /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), Some(&4)); + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[stable(feature = "iterator_step_by", since = "1.28.0")] + fn step_by(self, step: usize) -> StepBy + where + Self: Sized, + { + StepBy::new(self, step) + } + + /// Takes two iterators and creates a new iterator over both in sequence. + /// + /// `chain()` will return a new iterator which will first iterate over + /// values from the first iterator and then over values from the second + /// iterator. + /// + /// In other words, it links two iterators together, in a chain. 🔗 + /// + /// [`once`] is commonly used to adapt a single value into a chain of + /// other kinds of iteration. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a1 = [1, 2, 3]; + /// let a2 = [4, 5, 6]; + /// + /// let mut iter = a1.iter().chain(a2.iter()); + /// + /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), Some(&3)); + /// assert_eq!(iter.next(), Some(&4)); + /// assert_eq!(iter.next(), Some(&5)); + /// assert_eq!(iter.next(), Some(&6)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// Since the argument to `chain()` uses [`IntoIterator`], we can pass + /// anything that can be converted into an [`Iterator`], not just an + /// [`Iterator`] itself. For example, slices (`&[T]`) implement + /// [`IntoIterator`], and so can be passed to `chain()` directly: + /// + /// ``` + /// let s1 = &[1, 2, 3]; + /// let s2 = &[4, 5, 6]; + /// + /// let mut iter = s1.iter().chain(s2); + /// + /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), Some(&3)); + /// assert_eq!(iter.next(), Some(&4)); + /// assert_eq!(iter.next(), Some(&5)); + /// assert_eq!(iter.next(), Some(&6)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// If you work with Windows API, you may wish to convert [`OsStr`] to `Vec`: + /// + /// ``` + /// #[cfg(windows)] + /// fn os_str_to_utf16(s: &std::ffi::OsStr) -> Vec { + /// use std::os::windows::ffi::OsStrExt; + /// s.encode_wide().chain(std::iter::once(0)).collect() + /// } + /// ``` + /// + /// [`once`]: crate::iter::once + /// [`OsStr`]: ../../std/ffi/struct.OsStr.html + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn chain(self, other: U) -> Chain + where + Self: Sized, + U: IntoIterator, + { + Chain::new(self, other.into_iter()) + } + + /// 'Zips up' two iterators into a single iterator of pairs. + /// + /// `zip()` returns a new iterator that will iterate over two other + /// iterators, returning a tuple where the first element comes from the + /// first iterator, and the second element comes from the second iterator. + /// + /// In other words, it zips two iterators together, into a single one. + /// + /// If either iterator returns [`None`], [`next`] from the zipped iterator + /// will return [`None`]. + /// If the zipped iterator has no more elements to return then each further attempt to advance + /// it will first try to advance the first iterator at most one time and if it still yielded an item + /// try to advance the second iterator at most one time. + /// + /// To 'undo' the result of zipping up two iterators, see [`unzip`]. + /// + /// [`unzip`]: Iterator::unzip + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a1 = [1, 2, 3]; + /// let a2 = [4, 5, 6]; + /// + /// let mut iter = a1.iter().zip(a2.iter()); + /// + /// assert_eq!(iter.next(), Some((&1, &4))); + /// assert_eq!(iter.next(), Some((&2, &5))); + /// assert_eq!(iter.next(), Some((&3, &6))); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// Since the argument to `zip()` uses [`IntoIterator`], we can pass + /// anything that can be converted into an [`Iterator`], not just an + /// [`Iterator`] itself. For example, slices (`&[T]`) implement + /// [`IntoIterator`], and so can be passed to `zip()` directly: + /// + /// ``` + /// let s1 = &[1, 2, 3]; + /// let s2 = &[4, 5, 6]; + /// + /// let mut iter = s1.iter().zip(s2); + /// + /// assert_eq!(iter.next(), Some((&1, &4))); + /// assert_eq!(iter.next(), Some((&2, &5))); + /// assert_eq!(iter.next(), Some((&3, &6))); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// `zip()` is often used to zip an infinite iterator to a finite one. + /// This works because the finite iterator will eventually return [`None`], + /// ending the zipper. Zipping with `(0..)` can look a lot like [`enumerate`]: + /// + /// ``` + /// let enumerate: Vec<_> = "foo".chars().enumerate().collect(); + /// + /// let zipper: Vec<_> = (0..).zip("foo".chars()).collect(); + /// + /// assert_eq!((0, 'f'), enumerate[0]); + /// assert_eq!((0, 'f'), zipper[0]); + /// + /// assert_eq!((1, 'o'), enumerate[1]); + /// assert_eq!((1, 'o'), zipper[1]); + /// + /// assert_eq!((2, 'o'), enumerate[2]); + /// assert_eq!((2, 'o'), zipper[2]); + /// ``` + /// + /// If both iterators have roughly equivalent syntax, it may be more readable to use [`zip`]: + /// + /// ``` + /// use std::iter::zip; + /// + /// let a = [1, 2, 3]; + /// let b = [2, 3, 4]; + /// + /// let mut zipped = zip( + /// a.into_iter().map(|x| x * 2).skip(1), + /// b.into_iter().map(|x| x * 2).skip(1), + /// ); + /// + /// assert_eq!(zipped.next(), Some((4, 6))); + /// assert_eq!(zipped.next(), Some((6, 8))); + /// assert_eq!(zipped.next(), None); + /// ``` + /// + /// compared to: + /// + /// ``` + /// # let a = [1, 2, 3]; + /// # let b = [2, 3, 4]; + /// # + /// let mut zipped = a + /// .into_iter() + /// .map(|x| x * 2) + /// .skip(1) + /// .zip(b.into_iter().map(|x| x * 2).skip(1)); + /// # + /// # assert_eq!(zipped.next(), Some((4, 6))); + /// # assert_eq!(zipped.next(), Some((6, 8))); + /// # assert_eq!(zipped.next(), None); + /// ``` + /// + /// [`enumerate`]: Iterator::enumerate + /// [`next`]: Iterator::next + /// [`zip`]: crate::iter::zip + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn zip(self, other: U) -> Zip + where + Self: Sized, + U: IntoIterator, + { + Zip::new(self, other.into_iter()) + } + + /// Creates a new iterator which places a copy of `separator` between adjacent + /// items of the original iterator. + /// + /// In case `separator` does not implement [`Clone`] or needs to be + /// computed every time, use [`intersperse_with`]. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_intersperse)] + /// + /// let mut a = [0, 1, 2].iter().intersperse(&100); + /// assert_eq!(a.next(), Some(&0)); // The first element from `a`. + /// assert_eq!(a.next(), Some(&100)); // The separator. + /// assert_eq!(a.next(), Some(&1)); // The next element from `a`. + /// assert_eq!(a.next(), Some(&100)); // The separator. + /// assert_eq!(a.next(), Some(&2)); // The last element from `a`. + /// assert_eq!(a.next(), None); // The iterator is finished. + /// ``` + /// + /// `intersperse` can be very useful to join an iterator's items using a common element: + /// ``` + /// #![feature(iter_intersperse)] + /// + /// let hello = ["Hello", "World", "!"].iter().copied().intersperse(" ").collect::(); + /// assert_eq!(hello, "Hello World !"); + /// ``` + /// + /// [`Clone`]: crate::clone::Clone + /// [`intersperse_with`]: Iterator::intersperse_with + #[inline] + #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] + fn intersperse(self, separator: Self::Item) -> Intersperse + where + Self: Sized, + Self::Item: Clone, + { + Intersperse::new(self, separator) + } + + /// Creates a new iterator which places an item generated by `separator` + /// between adjacent items of the original iterator. + /// + /// The closure will be called exactly once each time an item is placed + /// between two adjacent items from the underlying iterator; specifically, + /// the closure is not called if the underlying iterator yields less than + /// two items and after the last item is yielded. + /// + /// If the iterator's item implements [`Clone`], it may be easier to use + /// [`intersperse`]. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_intersperse)] + /// + /// #[derive(PartialEq, Debug)] + /// struct NotClone(usize); + /// + /// let v = [NotClone(0), NotClone(1), NotClone(2)]; + /// let mut it = v.into_iter().intersperse_with(|| NotClone(99)); + /// + /// assert_eq!(it.next(), Some(NotClone(0))); // The first element from `v`. + /// assert_eq!(it.next(), Some(NotClone(99))); // The separator. + /// assert_eq!(it.next(), Some(NotClone(1))); // The next element from `v`. + /// assert_eq!(it.next(), Some(NotClone(99))); // The separator. + /// assert_eq!(it.next(), Some(NotClone(2))); // The last element from `v`. + /// assert_eq!(it.next(), None); // The iterator is finished. + /// ``` + /// + /// `intersperse_with` can be used in situations where the separator needs + /// to be computed: + /// ``` + /// #![feature(iter_intersperse)] + /// + /// let src = ["Hello", "to", "all", "people", "!!"].iter().copied(); + /// + /// // The closure mutably borrows its context to generate an item. + /// let mut happy_emojis = [" ❤️ ", " 😀 "].iter().copied(); + /// let separator = || happy_emojis.next().unwrap_or(" 🦀 "); + /// + /// let result = src.intersperse_with(separator).collect::(); + /// assert_eq!(result, "Hello ❤️ to 😀 all 🦀 people 🦀 !!"); + /// ``` + /// [`Clone`]: crate::clone::Clone + /// [`intersperse`]: Iterator::intersperse + #[inline] + #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] + fn intersperse_with(self, separator: G) -> IntersperseWith + where + Self: Sized, + G: FnMut() -> Self::Item, + { + IntersperseWith::new(self, separator) + } + + /// Takes a closure and creates an iterator which calls that closure on each + /// element. + /// + /// `map()` transforms one iterator into another, by means of its argument: + /// something that implements [`FnMut`]. It produces a new iterator which + /// calls this closure on each element of the original iterator. + /// + /// If you are good at thinking in types, you can think of `map()` like this: + /// If you have an iterator that gives you elements of some type `A`, and + /// you want an iterator of some other type `B`, you can use `map()`, + /// passing a closure that takes an `A` and returns a `B`. + /// + /// `map()` is conceptually similar to a [`for`] loop. However, as `map()` is + /// lazy, it is best used when you're already working with other iterators. + /// If you're doing some sort of looping for a side effect, it's considered + /// more idiomatic to use [`for`] than `map()`. + /// + /// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter().map(|x| 2 * x); + /// + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), Some(4)); + /// assert_eq!(iter.next(), Some(6)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// If you're doing some sort of side effect, prefer [`for`] to `map()`: + /// + /// ``` + /// # #![allow(unused_must_use)] + /// // don't do this: + /// (0..5).map(|x| println!("{x}")); + /// + /// // it won't even execute, as it is lazy. Rust will warn you about this. + /// + /// // Instead, use for: + /// for x in 0..5 { + /// println!("{x}"); + /// } + /// ``` + #[rustc_diagnostic_item = "IteratorMap"] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn map(self, f: F) -> Map + where + Self: Sized, + F: FnMut(Self::Item) -> B, + { + Map::new(self, f) + } + + /// Calls a closure on each element of an iterator. + /// + /// This is equivalent to using a [`for`] loop on the iterator, although + /// `break` and `continue` are not possible from a closure. It's generally + /// more idiomatic to use a `for` loop, but `for_each` may be more legible + /// when processing items at the end of longer iterator chains. In some + /// cases `for_each` may also be faster than a loop, because it will use + /// internal iteration on adapters like `Chain`. + /// + /// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::sync::mpsc::channel; + /// + /// let (tx, rx) = channel(); + /// (0..5).map(|x| x * 2 + 1) + /// .for_each(move |x| tx.send(x).unwrap()); + /// + /// let v: Vec<_> = rx.iter().collect(); + /// assert_eq!(v, vec![1, 3, 5, 7, 9]); + /// ``` + /// + /// For such a small example, a `for` loop may be cleaner, but `for_each` + /// might be preferable to keep a functional style with longer iterators: + /// + /// ``` + /// (0..5).flat_map(|x| x * 100 .. x * 110) + /// .enumerate() + /// .filter(|&(i, x)| (i + x) % 3 == 0) + /// .for_each(|(i, x)| println!("{i}:{x}")); + /// ``` + #[inline] + #[stable(feature = "iterator_for_each", since = "1.21.0")] + fn for_each(self, f: F) + where + Self: Sized, + F: FnMut(Self::Item), + { + #[inline] + fn call(mut f: impl FnMut(T)) -> impl FnMut((), T) { + move |(), item| f(item) + } + + self.fold((), call(f)); + } + + /// Creates an iterator which uses a closure to determine if an element + /// should be yielded. + /// + /// Given an element the closure must return `true` or `false`. The returned + /// iterator will yield only the elements for which the closure returns + /// `true`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [0i32, 1, 2]; + /// + /// let mut iter = a.iter().filter(|x| x.is_positive()); + /// + /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// Because the closure passed to `filter()` takes a reference, and many + /// iterators iterate over references, this leads to a possibly confusing + /// situation, where the type of the closure is a double reference: + /// + /// ``` + /// let a = [0, 1, 2]; + /// + /// let mut iter = a.iter().filter(|x| **x > 1); // need two *s! + /// + /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// It's common to instead use destructuring on the argument to strip away + /// one: + /// + /// ``` + /// let a = [0, 1, 2]; + /// + /// let mut iter = a.iter().filter(|&x| *x > 1); // both & and * + /// + /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// or both: + /// + /// ``` + /// let a = [0, 1, 2]; + /// + /// let mut iter = a.iter().filter(|&&x| x > 1); // two &s + /// + /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// of these layers. + /// + /// Note that `iter.filter(f).next()` is equivalent to `iter.find(f)`. + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "iter_filter")] + fn filter

(self, predicate: P) -> Filter + where + Self: Sized, + P: FnMut(&Self::Item) -> bool, + { + Filter::new(self, predicate) + } + + /// Creates an iterator that both filters and maps. + /// + /// The returned iterator yields only the `value`s for which the supplied + /// closure returns `Some(value)`. + /// + /// `filter_map` can be used to make chains of [`filter`] and [`map`] more + /// concise. The example below shows how a `map().filter().map()` can be + /// shortened to a single call to `filter_map`. + /// + /// [`filter`]: Iterator::filter + /// [`map`]: Iterator::map + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = ["1", "two", "NaN", "four", "5"]; + /// + /// let mut iter = a.iter().filter_map(|s| s.parse().ok()); + /// + /// assert_eq!(iter.next(), Some(1)); + /// assert_eq!(iter.next(), Some(5)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// Here's the same example, but with [`filter`] and [`map`]: + /// + /// ``` + /// let a = ["1", "two", "NaN", "four", "5"]; + /// let mut iter = a.iter().map(|s| s.parse()).filter(|s| s.is_ok()).map(|s| s.unwrap()); + /// assert_eq!(iter.next(), Some(1)); + /// assert_eq!(iter.next(), Some(5)); + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn filter_map(self, f: F) -> FilterMap + where + Self: Sized, + F: FnMut(Self::Item) -> Option, + { + FilterMap::new(self, f) + } + + /// Creates an iterator which gives the current iteration count as well as + /// the next value. + /// + /// The iterator returned yields pairs `(i, val)`, where `i` is the + /// current index of iteration and `val` is the value returned by the + /// iterator. + /// + /// `enumerate()` keeps its count as a [`usize`]. If you want to count by a + /// different sized integer, the [`zip`] function provides similar + /// functionality. + /// + /// # Overflow Behavior + /// + /// The method does no guarding against overflows, so enumerating more than + /// [`usize::MAX`] elements either produces the wrong result or panics. If + /// debug assertions are enabled, a panic is guaranteed. + /// + /// # Panics + /// + /// The returned iterator might panic if the to-be-returned index would + /// overflow a [`usize`]. + /// + /// [`zip`]: Iterator::zip + /// + /// # Examples + /// + /// ``` + /// let a = ['a', 'b', 'c']; + /// + /// let mut iter = a.iter().enumerate(); + /// + /// assert_eq!(iter.next(), Some((0, &'a'))); + /// assert_eq!(iter.next(), Some((1, &'b'))); + /// assert_eq!(iter.next(), Some((2, &'c'))); + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "enumerate_method")] + fn enumerate(self) -> Enumerate + where + Self: Sized, + { + Enumerate::new(self) + } + + /// Creates an iterator which can use the [`peek`] and [`peek_mut`] methods + /// to look at the next element of the iterator without consuming it. See + /// their documentation for more information. + /// + /// Note that the underlying iterator is still advanced when [`peek`] or + /// [`peek_mut`] are called for the first time: In order to retrieve the + /// next element, [`next`] is called on the underlying iterator, hence any + /// side effects (i.e. anything other than fetching the next value) of + /// the [`next`] method will occur. + /// + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let xs = [1, 2, 3]; + /// + /// let mut iter = xs.iter().peekable(); + /// + /// // peek() lets us see into the future + /// assert_eq!(iter.peek(), Some(&&1)); + /// assert_eq!(iter.next(), Some(&1)); + /// + /// assert_eq!(iter.next(), Some(&2)); + /// + /// // we can peek() multiple times, the iterator won't advance + /// assert_eq!(iter.peek(), Some(&&3)); + /// assert_eq!(iter.peek(), Some(&&3)); + /// + /// assert_eq!(iter.next(), Some(&3)); + /// + /// // after the iterator is finished, so is peek() + /// assert_eq!(iter.peek(), None); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// Using [`peek_mut`] to mutate the next item without advancing the + /// iterator: + /// + /// ``` + /// let xs = [1, 2, 3]; + /// + /// let mut iter = xs.iter().peekable(); + /// + /// // `peek_mut()` lets us see into the future + /// assert_eq!(iter.peek_mut(), Some(&mut &1)); + /// assert_eq!(iter.peek_mut(), Some(&mut &1)); + /// assert_eq!(iter.next(), Some(&1)); + /// + /// if let Some(mut p) = iter.peek_mut() { + /// assert_eq!(*p, &2); + /// // put a value into the iterator + /// *p = &1000; + /// } + /// + /// // The value reappears as the iterator continues + /// assert_eq!(iter.collect::>(), vec![&1000, &3]); + /// ``` + /// [`peek`]: Peekable::peek + /// [`peek_mut`]: Peekable::peek_mut + /// [`next`]: Iterator::next + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn peekable(self) -> Peekable + where + Self: Sized, + { + Peekable::new(self) + } + + /// Creates an iterator that [`skip`]s elements based on a predicate. + /// + /// [`skip`]: Iterator::skip + /// + /// `skip_while()` takes a closure as an argument. It will call this + /// closure on each element of the iterator, and ignore elements + /// until it returns `false`. + /// + /// After `false` is returned, `skip_while()`'s job is over, and the + /// rest of the elements are yielded. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [-1i32, 0, 1]; + /// + /// let mut iter = a.iter().skip_while(|x| x.is_negative()); + /// + /// assert_eq!(iter.next(), Some(&0)); + /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// Because the closure passed to `skip_while()` takes a reference, and many + /// iterators iterate over references, this leads to a possibly confusing + /// situation, where the type of the closure argument is a double reference: + /// + /// ``` + /// let a = [-1, 0, 1]; + /// + /// let mut iter = a.iter().skip_while(|x| **x < 0); // need two *s! + /// + /// assert_eq!(iter.next(), Some(&0)); + /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// Stopping after an initial `false`: + /// + /// ``` + /// let a = [-1, 0, 1, -2]; + /// + /// let mut iter = a.iter().skip_while(|x| **x < 0); + /// + /// assert_eq!(iter.next(), Some(&0)); + /// assert_eq!(iter.next(), Some(&1)); + /// + /// // while this would have been false, since we already got a false, + /// // skip_while() isn't used any more + /// assert_eq!(iter.next(), Some(&-2)); + /// + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[doc(alias = "drop_while")] + #[stable(feature = "rust1", since = "1.0.0")] + fn skip_while

(self, predicate: P) -> SkipWhile + where + Self: Sized, + P: FnMut(&Self::Item) -> bool, + { + SkipWhile::new(self, predicate) + } + + /// Creates an iterator that yields elements based on a predicate. + /// + /// `take_while()` takes a closure as an argument. It will call this + /// closure on each element of the iterator, and yield elements + /// while it returns `true`. + /// + /// After `false` is returned, `take_while()`'s job is over, and the + /// rest of the elements are ignored. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [-1i32, 0, 1]; + /// + /// let mut iter = a.iter().take_while(|x| x.is_negative()); + /// + /// assert_eq!(iter.next(), Some(&-1)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// Because the closure passed to `take_while()` takes a reference, and many + /// iterators iterate over references, this leads to a possibly confusing + /// situation, where the type of the closure is a double reference: + /// + /// ``` + /// let a = [-1, 0, 1]; + /// + /// let mut iter = a.iter().take_while(|x| **x < 0); // need two *s! + /// + /// assert_eq!(iter.next(), Some(&-1)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// Stopping after an initial `false`: + /// + /// ``` + /// let a = [-1, 0, 1, -2]; + /// + /// let mut iter = a.iter().take_while(|x| **x < 0); + /// + /// assert_eq!(iter.next(), Some(&-1)); + /// + /// // We have more elements that are less than zero, but since we already + /// // got a false, take_while() isn't used any more + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// Because `take_while()` needs to look at the value in order to see if it + /// should be included or not, consuming iterators will see that it is + /// removed: + /// + /// ``` + /// let a = [1, 2, 3, 4]; + /// let mut iter = a.iter(); + /// + /// let result: Vec = iter.by_ref() + /// .take_while(|n| **n != 3) + /// .cloned() + /// .collect(); + /// + /// assert_eq!(result, &[1, 2]); + /// + /// let result: Vec = iter.cloned().collect(); + /// + /// assert_eq!(result, &[4]); + /// ``` + /// + /// The `3` is no longer there, because it was consumed in order to see if + /// the iteration should stop, but wasn't placed back into the iterator. + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn take_while

(self, predicate: P) -> TakeWhile + where + Self: Sized, + P: FnMut(&Self::Item) -> bool, + { + TakeWhile::new(self, predicate) + } + + /// Creates an iterator that both yields elements based on a predicate and maps. + /// + /// `map_while()` takes a closure as an argument. It will call this + /// closure on each element of the iterator, and yield elements + /// while it returns [`Some(_)`][`Some`]. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [-1i32, 4, 0, 1]; + /// + /// let mut iter = a.iter().map_while(|x| 16i32.checked_div(*x)); + /// + /// assert_eq!(iter.next(), Some(-16)); + /// assert_eq!(iter.next(), Some(4)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// Here's the same example, but with [`take_while`] and [`map`]: + /// + /// [`take_while`]: Iterator::take_while + /// [`map`]: Iterator::map + /// + /// ``` + /// let a = [-1i32, 4, 0, 1]; + /// + /// let mut iter = a.iter() + /// .map(|x| 16i32.checked_div(*x)) + /// .take_while(|x| x.is_some()) + /// .map(|x| x.unwrap()); + /// + /// assert_eq!(iter.next(), Some(-16)); + /// assert_eq!(iter.next(), Some(4)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// Stopping after an initial [`None`]: + /// + /// ``` + /// let a = [0, 1, 2, -3, 4, 5, -6]; + /// + /// let iter = a.iter().map_while(|x| u32::try_from(*x).ok()); + /// let vec = iter.collect::>(); + /// + /// // We have more elements which could fit in u32 (4, 5), but `map_while` returned `None` for `-3` + /// // (as the `predicate` returned `None`) and `collect` stops at the first `None` encountered. + /// assert_eq!(vec, vec![0, 1, 2]); + /// ``` + /// + /// Because `map_while()` needs to look at the value in order to see if it + /// should be included or not, consuming iterators will see that it is + /// removed: + /// + /// ``` + /// let a = [1, 2, -3, 4]; + /// let mut iter = a.iter(); + /// + /// let result: Vec = iter.by_ref() + /// .map_while(|n| u32::try_from(*n).ok()) + /// .collect(); + /// + /// assert_eq!(result, &[1, 2]); + /// + /// let result: Vec = iter.cloned().collect(); + /// + /// assert_eq!(result, &[4]); + /// ``` + /// + /// The `-3` is no longer there, because it was consumed in order to see if + /// the iteration should stop, but wasn't placed back into the iterator. + /// + /// Note that unlike [`take_while`] this iterator is **not** fused. + /// It is also not specified what this iterator returns after the first [`None`] is returned. + /// If you need fused iterator, use [`fuse`]. + /// + /// [`fuse`]: Iterator::fuse + #[inline] + #[stable(feature = "iter_map_while", since = "1.57.0")] + fn map_while(self, predicate: P) -> MapWhile + where + Self: Sized, + P: FnMut(Self::Item) -> Option, + { + MapWhile::new(self, predicate) + } + + /// Creates an iterator that skips the first `n` elements. + /// + /// `skip(n)` skips elements until `n` elements are skipped or the end of the + /// iterator is reached (whichever happens first). After that, all the remaining + /// elements are yielded. In particular, if the original iterator is too short, + /// then the returned iterator is empty. + /// + /// Rather than overriding this method directly, instead override the `nth` method. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter().skip(2); + /// + /// assert_eq!(iter.next(), Some(&3)); + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn skip(self, n: usize) -> Skip + where + Self: Sized, + { + Skip::new(self, n) + } + + /// Creates an iterator that yields the first `n` elements, or fewer + /// if the underlying iterator ends sooner. + /// + /// `take(n)` yields elements until `n` elements are yielded or the end of + /// the iterator is reached (whichever happens first). + /// The returned iterator is a prefix of length `n` if the original iterator + /// contains at least `n` elements, otherwise it contains all of the + /// (fewer than `n`) elements of the original iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter().take(2); + /// + /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// `take()` is often used with an infinite iterator, to make it finite: + /// + /// ``` + /// let mut iter = (0..).take(3); + /// + /// assert_eq!(iter.next(), Some(0)); + /// assert_eq!(iter.next(), Some(1)); + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// If less than `n` elements are available, + /// `take` will limit itself to the size of the underlying iterator: + /// + /// ``` + /// let v = [1, 2]; + /// let mut iter = v.into_iter().take(5); + /// assert_eq!(iter.next(), Some(1)); + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn take(self, n: usize) -> Take + where + Self: Sized, + { + Take::new(self, n) + } + + /// An iterator adapter which, like [`fold`], holds internal state, but + /// unlike [`fold`], produces a new iterator. + /// + /// [`fold`]: Iterator::fold + /// + /// `scan()` takes two arguments: an initial value which seeds the internal + /// state, and a closure with two arguments, the first being a mutable + /// reference to the internal state and the second an iterator element. + /// The closure can assign to the internal state to share state between + /// iterations. + /// + /// On iteration, the closure will be applied to each element of the + /// iterator and the return value from the closure, an [`Option`], is + /// returned by the `next` method. Thus the closure can return + /// `Some(value)` to yield `value`, or `None` to end the iteration. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3, 4]; + /// + /// let mut iter = a.iter().scan(1, |state, &x| { + /// // each iteration, we'll multiply the state by the element ... + /// *state = *state * x; + /// + /// // ... and terminate if the state exceeds 6 + /// if *state > 6 { + /// return None; + /// } + /// // ... else yield the negation of the state + /// Some(-*state) + /// }); + /// + /// assert_eq!(iter.next(), Some(-1)); + /// assert_eq!(iter.next(), Some(-2)); + /// assert_eq!(iter.next(), Some(-6)); + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn scan(self, initial_state: St, f: F) -> Scan + where + Self: Sized, + F: FnMut(&mut St, Self::Item) -> Option, + { + Scan::new(self, initial_state, f) + } + + /// Creates an iterator that works like map, but flattens nested structure. + /// + /// The [`map`] adapter is very useful, but only when the closure + /// argument produces values. If it produces an iterator instead, there's + /// an extra layer of indirection. `flat_map()` will remove this extra layer + /// on its own. + /// + /// You can think of `flat_map(f)` as the semantic equivalent + /// of [`map`]ping, and then [`flatten`]ing as in `map(f).flatten()`. + /// + /// Another way of thinking about `flat_map()`: [`map`]'s closure returns + /// one item for each element, and `flat_map()`'s closure returns an + /// iterator for each element. + /// + /// [`map`]: Iterator::map + /// [`flatten`]: Iterator::flatten + /// + /// # Examples + /// + /// ``` + /// let words = ["alpha", "beta", "gamma"]; + /// + /// // chars() returns an iterator + /// let merged: String = words.iter() + /// .flat_map(|s| s.chars()) + /// .collect(); + /// assert_eq!(merged, "alphabetagamma"); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn flat_map(self, f: F) -> FlatMap + where + Self: Sized, + U: IntoIterator, + F: FnMut(Self::Item) -> U, + { + FlatMap::new(self, f) + } + + /// Creates an iterator that flattens nested structure. + /// + /// This is useful when you have an iterator of iterators or an iterator of + /// things that can be turned into iterators and you want to remove one + /// level of indirection. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let data = vec![vec![1, 2, 3, 4], vec![5, 6]]; + /// let flattened = data.into_iter().flatten().collect::>(); + /// assert_eq!(flattened, &[1, 2, 3, 4, 5, 6]); + /// ``` + /// + /// Mapping and then flattening: + /// + /// ``` + /// let words = ["alpha", "beta", "gamma"]; + /// + /// // chars() returns an iterator + /// let merged: String = words.iter() + /// .map(|s| s.chars()) + /// .flatten() + /// .collect(); + /// assert_eq!(merged, "alphabetagamma"); + /// ``` + /// + /// You can also rewrite this in terms of [`flat_map()`], which is preferable + /// in this case since it conveys intent more clearly: + /// + /// ``` + /// let words = ["alpha", "beta", "gamma"]; + /// + /// // chars() returns an iterator + /// let merged: String = words.iter() + /// .flat_map(|s| s.chars()) + /// .collect(); + /// assert_eq!(merged, "alphabetagamma"); + /// ``` + /// + /// Flattening works on any `IntoIterator` type, including `Option` and `Result`: + /// + /// ``` + /// let options = vec![Some(123), Some(321), None, Some(231)]; + /// let flattened_options: Vec<_> = options.into_iter().flatten().collect(); + /// assert_eq!(flattened_options, vec![123, 321, 231]); + /// + /// let results = vec![Ok(123), Ok(321), Err(456), Ok(231)]; + /// let flattened_results: Vec<_> = results.into_iter().flatten().collect(); + /// assert_eq!(flattened_results, vec![123, 321, 231]); + /// ``` + /// + /// Flattening only removes one level of nesting at a time: + /// + /// ``` + /// let d3 = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]; + /// + /// let d2 = d3.iter().flatten().collect::>(); + /// assert_eq!(d2, [&[1, 2], &[3, 4], &[5, 6], &[7, 8]]); + /// + /// let d1 = d3.iter().flatten().flatten().collect::>(); + /// assert_eq!(d1, [&1, &2, &3, &4, &5, &6, &7, &8]); + /// ``` + /// + /// Here we see that `flatten()` does not perform a "deep" flatten. + /// Instead, only one level of nesting is removed. That is, if you + /// `flatten()` a three-dimensional array, the result will be + /// two-dimensional and not one-dimensional. To get a one-dimensional + /// structure, you have to `flatten()` again. + /// + /// [`flat_map()`]: Iterator::flat_map + #[inline] + #[stable(feature = "iterator_flatten", since = "1.29.0")] + fn flatten(self) -> Flatten + where + Self: Sized, + Self::Item: IntoIterator, + { + Flatten::new(self) + } + + /// Calls the given function `f` for each contiguous window of size `N` over + /// `self` and returns an iterator over the outputs of `f`. Like [`slice::windows()`], + /// the windows during mapping overlap as well. + /// + /// In the following example, the closure is called three times with the + /// arguments `&['a', 'b']`, `&['b', 'c']` and `&['c', 'd']` respectively. + /// + /// ``` + /// #![feature(iter_map_windows)] + /// + /// let strings = "abcd".chars() + /// .map_windows(|[x, y]| format!("{}+{}", x, y)) + /// .collect::>(); + /// + /// assert_eq!(strings, vec!["a+b", "b+c", "c+d"]); + /// ``` + /// + /// Note that the const parameter `N` is usually inferred by the + /// destructured argument in the closure. + /// + /// The returned iterator yields 𝑘 − `N` + 1 items (where 𝑘 is the number of + /// items yielded by `self`). If 𝑘 is less than `N`, this method yields an + /// empty iterator. + /// + /// The returned iterator implements [`FusedIterator`], because once `self` + /// returns `None`, even if it returns a `Some(T)` again in the next iterations, + /// we cannot put it into a contiguous array buffer, and thus the returned iterator + /// should be fused. + /// + /// [`slice::windows()`]: slice::windows + /// [`FusedIterator`]: crate::iter::FusedIterator + /// + /// # Panics + /// + /// Panics if `N` is zero. This check will most probably get changed to a + /// compile time error before this method gets stabilized. + /// + /// ```should_panic + /// #![feature(iter_map_windows)] + /// + /// let iter = std::iter::repeat(0).map_windows(|&[]| ()); + /// ``` + /// + /// # Examples + /// + /// Building the sums of neighboring numbers. + /// + /// ``` + /// #![feature(iter_map_windows)] + /// + /// let mut it = [1, 3, 8, 1].iter().map_windows(|&[a, b]| a + b); + /// assert_eq!(it.next(), Some(4)); // 1 + 3 + /// assert_eq!(it.next(), Some(11)); // 3 + 8 + /// assert_eq!(it.next(), Some(9)); // 8 + 1 + /// assert_eq!(it.next(), None); + /// ``` + /// + /// Since the elements in the following example implement `Copy`, we can + /// just copy the array and get an iterator over the windows. + /// + /// ``` + /// #![feature(iter_map_windows)] + /// + /// let mut it = "ferris".chars().map_windows(|w: &[_; 3]| *w); + /// assert_eq!(it.next(), Some(['f', 'e', 'r'])); + /// assert_eq!(it.next(), Some(['e', 'r', 'r'])); + /// assert_eq!(it.next(), Some(['r', 'r', 'i'])); + /// assert_eq!(it.next(), Some(['r', 'i', 's'])); + /// assert_eq!(it.next(), None); + /// ``` + /// + /// You can also use this function to check the sortedness of an iterator. + /// For the simple case, rather use [`Iterator::is_sorted`]. + /// + /// ``` + /// #![feature(iter_map_windows)] + /// + /// let mut it = [0.5, 1.0, 3.5, 3.0, 8.5, 8.5, f32::NAN].iter() + /// .map_windows(|[a, b]| a <= b); + /// + /// assert_eq!(it.next(), Some(true)); // 0.5 <= 1.0 + /// assert_eq!(it.next(), Some(true)); // 1.0 <= 3.5 + /// assert_eq!(it.next(), Some(false)); // 3.5 <= 3.0 + /// assert_eq!(it.next(), Some(true)); // 3.0 <= 8.5 + /// assert_eq!(it.next(), Some(true)); // 8.5 <= 8.5 + /// assert_eq!(it.next(), Some(false)); // 8.5 <= NAN + /// assert_eq!(it.next(), None); + /// ``` + /// + /// For non-fused iterators, they are fused after `map_windows`. + /// + /// ``` + /// #![feature(iter_map_windows)] + /// + /// #[derive(Default)] + /// struct NonFusedIterator { + /// state: i32, + /// } + /// + /// impl Iterator for NonFusedIterator { + /// type Item = i32; + /// + /// fn next(&mut self) -> Option { + /// let val = self.state; + /// self.state = self.state + 1; + /// + /// // yields `0..5` first, then only even numbers since `6..`. + /// if val < 5 || val % 2 == 0 { + /// Some(val) + /// } else { + /// None + /// } + /// } + /// } + /// + /// + /// let mut iter = NonFusedIterator::default(); + /// + /// // yields 0..5 first. + /// assert_eq!(iter.next(), Some(0)); + /// assert_eq!(iter.next(), Some(1)); + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), Some(3)); + /// assert_eq!(iter.next(), Some(4)); + /// // then we can see our iterator going back and forth + /// assert_eq!(iter.next(), None); + /// assert_eq!(iter.next(), Some(6)); + /// assert_eq!(iter.next(), None); + /// assert_eq!(iter.next(), Some(8)); + /// assert_eq!(iter.next(), None); + /// + /// // however, with `.map_windows()`, it is fused. + /// let mut iter = NonFusedIterator::default() + /// .map_windows(|arr: &[_; 2]| *arr); + /// + /// assert_eq!(iter.next(), Some([0, 1])); + /// assert_eq!(iter.next(), Some([1, 2])); + /// assert_eq!(iter.next(), Some([2, 3])); + /// assert_eq!(iter.next(), Some([3, 4])); + /// assert_eq!(iter.next(), None); + /// + /// // it will always return `None` after the first time. + /// assert_eq!(iter.next(), None); + /// assert_eq!(iter.next(), None); + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[unstable(feature = "iter_map_windows", reason = "recently added", issue = "87155")] + fn map_windows(self, f: F) -> MapWindows + where + Self: Sized, + F: FnMut(&[Self::Item; N]) -> R, + { + MapWindows::new(self, f) + } + + /// Creates an iterator which ends after the first [`None`]. + /// + /// After an iterator returns [`None`], future calls may or may not yield + /// [`Some(T)`] again. `fuse()` adapts an iterator, ensuring that after a + /// [`None`] is given, it will always return [`None`] forever. + /// + /// Note that the [`Fuse`] wrapper is a no-op on iterators that implement + /// the [`FusedIterator`] trait. `fuse()` may therefore behave incorrectly + /// if the [`FusedIterator`] trait is improperly implemented. + /// + /// [`Some(T)`]: Some + /// [`FusedIterator`]: crate::iter::FusedIterator + /// + /// # Examples + /// + /// ``` + /// // an iterator which alternates between Some and None + /// struct Alternate { + /// state: i32, + /// } + /// + /// impl Iterator for Alternate { + /// type Item = i32; + /// + /// fn next(&mut self) -> Option { + /// let val = self.state; + /// self.state = self.state + 1; + /// + /// // if it's even, Some(i32), else None + /// if val % 2 == 0 { + /// Some(val) + /// } else { + /// None + /// } + /// } + /// } + /// + /// let mut iter = Alternate { state: 0 }; + /// + /// // we can see our iterator going back and forth + /// assert_eq!(iter.next(), Some(0)); + /// assert_eq!(iter.next(), None); + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), None); + /// + /// // however, once we fuse it... + /// let mut iter = iter.fuse(); + /// + /// assert_eq!(iter.next(), Some(4)); + /// assert_eq!(iter.next(), None); + /// + /// // it will always return `None` after the first time. + /// assert_eq!(iter.next(), None); + /// assert_eq!(iter.next(), None); + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn fuse(self) -> Fuse + where + Self: Sized, + { + Fuse::new(self) + } + + /// Does something with each element of an iterator, passing the value on. + /// + /// When using iterators, you'll often chain several of them together. + /// While working on such code, you might want to check out what's + /// happening at various parts in the pipeline. To do that, insert + /// a call to `inspect()`. + /// + /// It's more common for `inspect()` to be used as a debugging tool than to + /// exist in your final code, but applications may find it useful in certain + /// situations when errors need to be logged before being discarded. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 4, 2, 3]; + /// + /// // this iterator sequence is complex. + /// let sum = a.iter() + /// .cloned() + /// .filter(|x| x % 2 == 0) + /// .fold(0, |sum, i| sum + i); + /// + /// println!("{sum}"); + /// + /// // let's add some inspect() calls to investigate what's happening + /// let sum = a.iter() + /// .cloned() + /// .inspect(|x| println!("about to filter: {x}")) + /// .filter(|x| x % 2 == 0) + /// .inspect(|x| println!("made it through filter: {x}")) + /// .fold(0, |sum, i| sum + i); + /// + /// println!("{sum}"); + /// ``` + /// + /// This will print: + /// + /// ```text + /// 6 + /// about to filter: 1 + /// about to filter: 4 + /// made it through filter: 4 + /// about to filter: 2 + /// made it through filter: 2 + /// about to filter: 3 + /// 6 + /// ``` + /// + /// Logging errors before discarding them: + /// + /// ``` + /// let lines = ["1", "2", "a"]; + /// + /// let sum: i32 = lines + /// .iter() + /// .map(|line| line.parse::()) + /// .inspect(|num| { + /// if let Err(ref e) = *num { + /// println!("Parsing error: {e}"); + /// } + /// }) + /// .filter_map(Result::ok) + /// .sum(); + /// + /// println!("Sum: {sum}"); + /// ``` + /// + /// This will print: + /// + /// ```text + /// Parsing error: invalid digit found in string + /// Sum: 3 + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn inspect(self, f: F) -> Inspect + where + Self: Sized, + F: FnMut(&Self::Item), + { + Inspect::new(self, f) + } + + /// Borrows an iterator, rather than consuming it. + /// + /// This is useful to allow applying iterator adapters while still + /// retaining ownership of the original iterator. + /// + /// # Examples + /// + /// ``` + /// let mut words = ["hello", "world", "of", "Rust"].into_iter(); + /// + /// // Take the first two words. + /// let hello_world: Vec<_> = words.by_ref().take(2).collect(); + /// assert_eq!(hello_world, vec!["hello", "world"]); + /// + /// // Collect the rest of the words. + /// // We can only do this because we used `by_ref` earlier. + /// let of_rust: Vec<_> = words.collect(); + /// assert_eq!(of_rust, vec!["of", "Rust"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn by_ref(&mut self) -> &mut Self + where + Self: Sized, + { + self + } + + /// Transforms an iterator into a collection. + /// + /// `collect()` can take anything iterable, and turn it into a relevant + /// collection. This is one of the more powerful methods in the standard + /// library, used in a variety of contexts. + /// + /// The most basic pattern in which `collect()` is used is to turn one + /// collection into another. You take a collection, call [`iter`] on it, + /// do a bunch of transformations, and then `collect()` at the end. + /// + /// `collect()` can also create instances of types that are not typical + /// collections. For example, a [`String`] can be built from [`char`]s, + /// and an iterator of [`Result`][`Result`] items can be collected + /// into `Result, E>`. See the examples below for more. + /// + /// Because `collect()` is so general, it can cause problems with type + /// inference. As such, `collect()` is one of the few times you'll see + /// the syntax affectionately known as the 'turbofish': `::<>`. This + /// helps the inference algorithm understand specifically which collection + /// you're trying to collect into. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let doubled: Vec = a.iter() + /// .map(|&x| x * 2) + /// .collect(); + /// + /// assert_eq!(vec![2, 4, 6], doubled); + /// ``` + /// + /// Note that we needed the `: Vec` on the left-hand side. This is because + /// we could collect into, for example, a [`VecDeque`] instead: + /// + /// [`VecDeque`]: ../../std/collections/struct.VecDeque.html + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let a = [1, 2, 3]; + /// + /// let doubled: VecDeque = a.iter().map(|&x| x * 2).collect(); + /// + /// assert_eq!(2, doubled[0]); + /// assert_eq!(4, doubled[1]); + /// assert_eq!(6, doubled[2]); + /// ``` + /// + /// Using the 'turbofish' instead of annotating `doubled`: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let doubled = a.iter().map(|x| x * 2).collect::>(); + /// + /// assert_eq!(vec![2, 4, 6], doubled); + /// ``` + /// + /// Because `collect()` only cares about what you're collecting into, you can + /// still use a partial type hint, `_`, with the turbofish: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let doubled = a.iter().map(|x| x * 2).collect::>(); + /// + /// assert_eq!(vec![2, 4, 6], doubled); + /// ``` + /// + /// Using `collect()` to make a [`String`]: + /// + /// ``` + /// let chars = ['g', 'd', 'k', 'k', 'n']; + /// + /// let hello: String = chars.iter() + /// .map(|&x| x as u8) + /// .map(|x| (x + 1) as char) + /// .collect(); + /// + /// assert_eq!("hello", hello); + /// ``` + /// + /// If you have a list of [`Result`][`Result`]s, you can use `collect()` to + /// see if any of them failed: + /// + /// ``` + /// let results = [Ok(1), Err("nope"), Ok(3), Err("bad")]; + /// + /// let result: Result, &str> = results.iter().cloned().collect(); + /// + /// // gives us the first error + /// assert_eq!(Err("nope"), result); + /// + /// let results = [Ok(1), Ok(3)]; + /// + /// let result: Result, &str> = results.iter().cloned().collect(); + /// + /// // gives us the list of answers + /// assert_eq!(Ok(vec![1, 3]), result); + /// ``` + /// + /// [`iter`]: Iterator::next + /// [`String`]: ../../std/string/struct.String.html + /// [`char`]: type@char + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] + #[cfg_attr(not(test), rustc_diagnostic_item = "iterator_collect_fn")] + fn collect>(self) -> B + where + Self: Sized, + { + FromIterator::from_iter(self) + } + + /// Fallibly transforms an iterator into a collection, short circuiting if + /// a failure is encountered. + /// + /// `try_collect()` is a variation of [`collect()`][`collect`] that allows fallible + /// conversions during collection. Its main use case is simplifying conversions from + /// iterators yielding [`Option`][`Option`] into `Option>`, or similarly for other [`Try`] + /// types (e.g. [`Result`]). + /// + /// Importantly, `try_collect()` doesn't require that the outer [`Try`] type also implements [`FromIterator`]; + /// only the inner type produced on `Try::Output` must implement it. Concretely, + /// this means that collecting into `ControlFlow<_, Vec>` is valid because `Vec` implements + /// [`FromIterator`], even though [`ControlFlow`] doesn't. + /// + /// Also, if a failure is encountered during `try_collect()`, the iterator is still valid and + /// may continue to be used, in which case it will continue iterating starting after the element that + /// triggered the failure. See the last example below for an example of how this works. + /// + /// # Examples + /// Successfully collecting an iterator of `Option` into `Option>`: + /// ``` + /// #![feature(iterator_try_collect)] + /// + /// let u = vec![Some(1), Some(2), Some(3)]; + /// let v = u.into_iter().try_collect::>(); + /// assert_eq!(v, Some(vec![1, 2, 3])); + /// ``` + /// + /// Failing to collect in the same way: + /// ``` + /// #![feature(iterator_try_collect)] + /// + /// let u = vec![Some(1), Some(2), None, Some(3)]; + /// let v = u.into_iter().try_collect::>(); + /// assert_eq!(v, None); + /// ``` + /// + /// A similar example, but with `Result`: + /// ``` + /// #![feature(iterator_try_collect)] + /// + /// let u: Vec> = vec![Ok(1), Ok(2), Ok(3)]; + /// let v = u.into_iter().try_collect::>(); + /// assert_eq!(v, Ok(vec![1, 2, 3])); + /// + /// let u = vec![Ok(1), Ok(2), Err(()), Ok(3)]; + /// let v = u.into_iter().try_collect::>(); + /// assert_eq!(v, Err(())); + /// ``` + /// + /// Finally, even [`ControlFlow`] works, despite the fact that it + /// doesn't implement [`FromIterator`]. Note also that the iterator can + /// continue to be used, even if a failure is encountered: + /// + /// ``` + /// #![feature(iterator_try_collect)] + /// + /// use core::ops::ControlFlow::{Break, Continue}; + /// + /// let u = [Continue(1), Continue(2), Break(3), Continue(4), Continue(5)]; + /// let mut it = u.into_iter(); + /// + /// let v = it.try_collect::>(); + /// assert_eq!(v, Break(3)); + /// + /// let v = it.try_collect::>(); + /// assert_eq!(v, Continue(vec![4, 5])); + /// ``` + /// + /// [`collect`]: Iterator::collect + #[inline] + #[unstable(feature = "iterator_try_collect", issue = "94047")] + fn try_collect(&mut self) -> ChangeOutputType + where + Self: Sized, + Self::Item: Try>, + B: FromIterator<::Output>, + { + try_process(ByRefSized(self), |i| i.collect()) + } + + /// Collects all the items from an iterator into a collection. + /// + /// This method consumes the iterator and adds all its items to the + /// passed collection. The collection is then returned, so the call chain + /// can be continued. + /// + /// This is useful when you already have a collection and want to add + /// the iterator items to it. + /// + /// This method is a convenience method to call [Extend::extend](trait.Extend.html), + /// but instead of being called on a collection, it's called on an iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_collect_into)] + /// + /// let a = [1, 2, 3]; + /// let mut vec: Vec:: = vec![0, 1]; + /// + /// a.iter().map(|&x| x * 2).collect_into(&mut vec); + /// a.iter().map(|&x| x * 10).collect_into(&mut vec); + /// + /// assert_eq!(vec, vec![0, 1, 2, 4, 6, 10, 20, 30]); + /// ``` + /// + /// `Vec` can have a manual set capacity to avoid reallocating it: + /// + /// ``` + /// #![feature(iter_collect_into)] + /// + /// let a = [1, 2, 3]; + /// let mut vec: Vec:: = Vec::with_capacity(6); + /// + /// a.iter().map(|&x| x * 2).collect_into(&mut vec); + /// a.iter().map(|&x| x * 10).collect_into(&mut vec); + /// + /// assert_eq!(6, vec.capacity()); + /// assert_eq!(vec, vec![2, 4, 6, 10, 20, 30]); + /// ``` + /// + /// The returned mutable reference can be used to continue the call chain: + /// + /// ``` + /// #![feature(iter_collect_into)] + /// + /// let a = [1, 2, 3]; + /// let mut vec: Vec:: = Vec::with_capacity(6); + /// + /// let count = a.iter().collect_into(&mut vec).iter().count(); + /// + /// assert_eq!(count, vec.len()); + /// assert_eq!(vec, vec![1, 2, 3]); + /// + /// let count = a.iter().collect_into(&mut vec).iter().count(); + /// + /// assert_eq!(count, vec.len()); + /// assert_eq!(vec, vec![1, 2, 3, 1, 2, 3]); + /// ``` + #[inline] + #[unstable(feature = "iter_collect_into", reason = "new API", issue = "94780")] + fn collect_into>(self, collection: &mut E) -> &mut E + where + Self: Sized, + { + collection.extend(self); + collection + } + + /// Consumes an iterator, creating two collections from it. + /// + /// The predicate passed to `partition()` can return `true`, or `false`. + /// `partition()` returns a pair, all of the elements for which it returned + /// `true`, and all of the elements for which it returned `false`. + /// + /// See also [`is_partitioned()`] and [`partition_in_place()`]. + /// + /// [`is_partitioned()`]: Iterator::is_partitioned + /// [`partition_in_place()`]: Iterator::partition_in_place + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let (even, odd): (Vec<_>, Vec<_>) = a + /// .into_iter() + /// .partition(|n| n % 2 == 0); + /// + /// assert_eq!(even, vec![2]); + /// assert_eq!(odd, vec![1, 3]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn partition(self, f: F) -> (B, B) + where + Self: Sized, + B: Default + Extend, + F: FnMut(&Self::Item) -> bool, + { + #[inline] + fn extend<'a, T, B: Extend>( + mut f: impl FnMut(&T) -> bool + 'a, + left: &'a mut B, + right: &'a mut B, + ) -> impl FnMut((), T) + 'a { + move |(), x| { + if f(&x) { + left.extend_one(x); + } else { + right.extend_one(x); + } + } + } + + let mut left: B = Default::default(); + let mut right: B = Default::default(); + + self.fold((), extend(f, &mut left, &mut right)); + + (left, right) + } + + /// Reorders the elements of this iterator *in-place* according to the given predicate, + /// such that all those that return `true` precede all those that return `false`. + /// Returns the number of `true` elements found. + /// + /// The relative order of partitioned items is not maintained. + /// + /// # Current implementation + /// + /// The current algorithm tries to find the first element for which the predicate evaluates + /// to false and the last element for which it evaluates to true, and repeatedly swaps them. + /// + /// Time complexity: *O*(*n*) + /// + /// See also [`is_partitioned()`] and [`partition()`]. + /// + /// [`is_partitioned()`]: Iterator::is_partitioned + /// [`partition()`]: Iterator::partition + /// + /// # Examples + /// + /// ``` + /// #![feature(iter_partition_in_place)] + /// + /// let mut a = [1, 2, 3, 4, 5, 6, 7]; + /// + /// // Partition in-place between evens and odds + /// let i = a.iter_mut().partition_in_place(|&n| n % 2 == 0); + /// + /// assert_eq!(i, 3); + /// assert!(a[..i].iter().all(|&n| n % 2 == 0)); // evens + /// assert!(a[i..].iter().all(|&n| n % 2 == 1)); // odds + /// ``` + #[unstable(feature = "iter_partition_in_place", reason = "new API", issue = "62543")] + fn partition_in_place<'a, T: 'a, P>(mut self, ref mut predicate: P) -> usize + where + Self: Sized + DoubleEndedIterator, + P: FnMut(&T) -> bool, + { + // FIXME: should we worry about the count overflowing? The only way to have more than + // `usize::MAX` mutable references is with ZSTs, which aren't useful to partition... + + // These closure "factory" functions exist to avoid genericity in `Self`. + + #[inline] + fn is_false<'a, T>( + predicate: &'a mut impl FnMut(&T) -> bool, + true_count: &'a mut usize, + ) -> impl FnMut(&&mut T) -> bool + 'a { + move |x| { + let p = predicate(&**x); + *true_count += p as usize; + !p + } + } + + #[inline] + fn is_true(predicate: &mut impl FnMut(&T) -> bool) -> impl FnMut(&&mut T) -> bool + '_ { + move |x| predicate(&**x) + } + + // Repeatedly find the first `false` and swap it with the last `true`. + let mut true_count = 0; + while let Some(head) = self.find(is_false(predicate, &mut true_count)) { + if let Some(tail) = self.rfind(is_true(predicate)) { + crate::mem::swap(head, tail); + true_count += 1; + } else { + break; + } + } + true_count + } + + /// Checks if the elements of this iterator are partitioned according to the given predicate, + /// such that all those that return `true` precede all those that return `false`. + /// + /// See also [`partition()`] and [`partition_in_place()`]. + /// + /// [`partition()`]: Iterator::partition + /// [`partition_in_place()`]: Iterator::partition_in_place + /// + /// # Examples + /// + /// ``` + /// #![feature(iter_is_partitioned)] + /// + /// assert!("Iterator".chars().is_partitioned(char::is_uppercase)); + /// assert!(!"IntoIterator".chars().is_partitioned(char::is_uppercase)); + /// ``` + #[unstable(feature = "iter_is_partitioned", reason = "new API", issue = "62544")] + fn is_partitioned

(mut self, mut predicate: P) -> bool + where + Self: Sized, + P: FnMut(Self::Item) -> bool, + { + // Either all items test `true`, or the first clause stops at `false` + // and we check that there are no more `true` items after that. + self.all(&mut predicate) || !self.any(predicate) + } + + /// An iterator method that applies a function as long as it returns + /// successfully, producing a single, final value. + /// + /// `try_fold()` takes two arguments: an initial value, and a closure with + /// two arguments: an 'accumulator', and an element. The closure either + /// returns successfully, with the value that the accumulator should have + /// for the next iteration, or it returns failure, with an error value that + /// is propagated back to the caller immediately (short-circuiting). + /// + /// The initial value is the value the accumulator will have on the first + /// call. If applying the closure succeeded against every element of the + /// iterator, `try_fold()` returns the final accumulator as success. + /// + /// Folding is useful whenever you have a collection of something, and want + /// to produce a single value from it. + /// + /// # Note to Implementors + /// + /// Several of the other (forward) methods have default implementations in + /// terms of this one, so try to implement this explicitly if it can + /// do something better than the default `for` loop implementation. + /// + /// In particular, try to have this call `try_fold()` on the internal parts + /// from which this iterator is composed. If multiple calls are needed, + /// the `?` operator may be convenient for chaining the accumulator value + /// along, but beware any invariants that need to be upheld before those + /// early returns. This is a `&mut self` method, so iteration needs to be + /// resumable after hitting an error here. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// // the checked sum of all of the elements of the array + /// let sum = a.iter().try_fold(0i8, |acc, &x| acc.checked_add(x)); + /// + /// assert_eq!(sum, Some(6)); + /// ``` + /// + /// Short-circuiting: + /// + /// ``` + /// let a = [10, 20, 30, 100, 40, 50]; + /// let mut it = a.iter(); + /// + /// // This sum overflows when adding the 100 element + /// let sum = it.try_fold(0i8, |acc, &x| acc.checked_add(x)); + /// assert_eq!(sum, None); + /// + /// // Because it short-circuited, the remaining elements are still + /// // available through the iterator. + /// assert_eq!(it.len(), 2); + /// assert_eq!(it.next(), Some(&40)); + /// ``` + /// + /// While you cannot `break` from a closure, the [`ControlFlow`] type allows + /// a similar idea: + /// + /// ``` + /// use std::ops::ControlFlow; + /// + /// let triangular = (1..30).try_fold(0_i8, |prev, x| { + /// if let Some(next) = prev.checked_add(x) { + /// ControlFlow::Continue(next) + /// } else { + /// ControlFlow::Break(prev) + /// } + /// }); + /// assert_eq!(triangular, ControlFlow::Break(120)); + /// + /// let triangular = (1..30).try_fold(0_u64, |prev, x| { + /// if let Some(next) = prev.checked_add(x) { + /// ControlFlow::Continue(next) + /// } else { + /// ControlFlow::Break(prev) + /// } + /// }); + /// assert_eq!(triangular, ControlFlow::Continue(435)); + /// ``` + #[inline] + #[stable(feature = "iterator_try_fold", since = "1.27.0")] + fn try_fold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let mut accum = init; + while let Some(x) = self.next() { + accum = f(accum, x)?; + } + try { accum } + } + + /// An iterator method that applies a fallible function to each item in the + /// iterator, stopping at the first error and returning that error. + /// + /// This can also be thought of as the fallible form of [`for_each()`] + /// or as the stateless version of [`try_fold()`]. + /// + /// [`for_each()`]: Iterator::for_each + /// [`try_fold()`]: Iterator::try_fold + /// + /// # Examples + /// + /// ``` + /// use std::fs::rename; + /// use std::io::{stdout, Write}; + /// use std::path::Path; + /// + /// let data = ["no_tea.txt", "stale_bread.json", "torrential_rain.png"]; + /// + /// let res = data.iter().try_for_each(|x| writeln!(stdout(), "{x}")); + /// assert!(res.is_ok()); + /// + /// let mut it = data.iter().cloned(); + /// let res = it.try_for_each(|x| rename(x, Path::new(x).with_extension("old"))); + /// assert!(res.is_err()); + /// // It short-circuited, so the remaining items are still in the iterator: + /// assert_eq!(it.next(), Some("stale_bread.json")); + /// ``` + /// + /// The [`ControlFlow`] type can be used with this method for the situations + /// in which you'd use `break` and `continue` in a normal loop: + /// + /// ``` + /// use std::ops::ControlFlow; + /// + /// let r = (2..100).try_for_each(|x| { + /// if 323 % x == 0 { + /// return ControlFlow::Break(x) + /// } + /// + /// ControlFlow::Continue(()) + /// }); + /// assert_eq!(r, ControlFlow::Break(17)); + /// ``` + #[inline] + #[stable(feature = "iterator_try_fold", since = "1.27.0")] + fn try_for_each(&mut self, f: F) -> R + where + Self: Sized, + F: FnMut(Self::Item) -> R, + R: Try, + { + #[inline] + fn call(mut f: impl FnMut(T) -> R) -> impl FnMut((), T) -> R { + move |(), x| f(x) + } + + self.try_fold((), call(f)) + } + + /// Folds every element into an accumulator by applying an operation, + /// returning the final result. + /// + /// `fold()` takes two arguments: an initial value, and a closure with two + /// arguments: an 'accumulator', and an element. The closure returns the value that + /// the accumulator should have for the next iteration. + /// + /// The initial value is the value the accumulator will have on the first + /// call. + /// + /// After applying this closure to every element of the iterator, `fold()` + /// returns the accumulator. + /// + /// This operation is sometimes called 'reduce' or 'inject'. + /// + /// Folding is useful whenever you have a collection of something, and want + /// to produce a single value from it. + /// + /// Note: `fold()`, and similar methods that traverse the entire iterator, + /// might not terminate for infinite iterators, even on traits for which a + /// result is determinable in finite time. + /// + /// Note: [`reduce()`] can be used to use the first element as the initial + /// value, if the accumulator type and item type is the same. + /// + /// Note: `fold()` combines elements in a *left-associative* fashion. For associative + /// operators like `+`, the order the elements are combined in is not important, but for non-associative + /// operators like `-` the order will affect the final result. + /// For a *right-associative* version of `fold()`, see [`DoubleEndedIterator::rfold()`]. + /// + /// # Note to Implementors + /// + /// Several of the other (forward) methods have default implementations in + /// terms of this one, so try to implement this explicitly if it can + /// do something better than the default `for` loop implementation. + /// + /// In particular, try to have this call `fold()` on the internal parts + /// from which this iterator is composed. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// // the sum of all of the elements of the array + /// let sum = a.iter().fold(0, |acc, x| acc + x); + /// + /// assert_eq!(sum, 6); + /// ``` + /// + /// Let's walk through each step of the iteration here: + /// + /// | element | acc | x | result | + /// |---------|-----|---|--------| + /// | | 0 | | | + /// | 1 | 0 | 1 | 1 | + /// | 2 | 1 | 2 | 3 | + /// | 3 | 3 | 3 | 6 | + /// + /// And so, our final result, `6`. + /// + /// This example demonstrates the left-associative nature of `fold()`: + /// it builds a string, starting with an initial value + /// and continuing with each element from the front until the back: + /// + /// ``` + /// let numbers = [1, 2, 3, 4, 5]; + /// + /// let zero = "0".to_string(); + /// + /// let result = numbers.iter().fold(zero, |acc, &x| { + /// format!("({acc} + {x})") + /// }); + /// + /// assert_eq!(result, "(((((0 + 1) + 2) + 3) + 4) + 5)"); + /// ``` + /// It's common for people who haven't used iterators a lot to + /// use a `for` loop with a list of things to build up a result. Those + /// can be turned into `fold()`s: + /// + /// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for + /// + /// ``` + /// let numbers = [1, 2, 3, 4, 5]; + /// + /// let mut result = 0; + /// + /// // for loop: + /// for i in &numbers { + /// result = result + i; + /// } + /// + /// // fold: + /// let result2 = numbers.iter().fold(0, |acc, &x| acc + x); + /// + /// // they're the same + /// assert_eq!(result, result2); + /// ``` + /// + /// [`reduce()`]: Iterator::reduce + #[doc(alias = "inject", alias = "foldl")] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn fold(mut self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + let mut accum = init; + while let Some(x) = self.next() { + accum = f(accum, x); + } + accum + } + + /// Reduces the elements to a single one, by repeatedly applying a reducing + /// operation. + /// + /// If the iterator is empty, returns [`None`]; otherwise, returns the + /// result of the reduction. + /// + /// The reducing function is a closure with two arguments: an 'accumulator', and an element. + /// For iterators with at least one element, this is the same as [`fold()`] + /// with the first element of the iterator as the initial accumulator value, folding + /// every subsequent element into it. + /// + /// [`fold()`]: Iterator::fold + /// + /// # Example + /// + /// ``` + /// let reduced: i32 = (1..10).reduce(|acc, e| acc + e).unwrap(); + /// assert_eq!(reduced, 45); + /// + /// // Which is equivalent to doing it with `fold`: + /// let folded: i32 = (1..10).fold(0, |acc, e| acc + e); + /// assert_eq!(reduced, folded); + /// ``` + #[inline] + #[stable(feature = "iterator_fold_self", since = "1.51.0")] + fn reduce(mut self, f: F) -> Option + where + Self: Sized, + F: FnMut(Self::Item, Self::Item) -> Self::Item, + { + let first = self.next()?; + Some(self.fold(first, f)) + } + + /// Reduces the elements to a single one by repeatedly applying a reducing operation. If the + /// closure returns a failure, the failure is propagated back to the caller immediately. + /// + /// The return type of this method depends on the return type of the closure. If the closure + /// returns `Result`, then this function will return `Result, + /// E>`. If the closure returns `Option`, then this function will return + /// `Option>`. + /// + /// When called on an empty iterator, this function will return either `Some(None)` or + /// `Ok(None)` depending on the type of the provided closure. + /// + /// For iterators with at least one element, this is essentially the same as calling + /// [`try_fold()`] with the first element of the iterator as the initial accumulator value. + /// + /// [`try_fold()`]: Iterator::try_fold + /// + /// # Examples + /// + /// Safely calculate the sum of a series of numbers: + /// + /// ``` + /// #![feature(iterator_try_reduce)] + /// + /// let numbers: Vec = vec![10, 20, 5, 23, 0]; + /// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y)); + /// assert_eq!(sum, Some(Some(58))); + /// ``` + /// + /// Determine when a reduction short circuited: + /// + /// ``` + /// #![feature(iterator_try_reduce)] + /// + /// let numbers = vec![1, 2, 3, usize::MAX, 4, 5]; + /// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y)); + /// assert_eq!(sum, None); + /// ``` + /// + /// Determine when a reduction was not performed because there are no elements: + /// + /// ``` + /// #![feature(iterator_try_reduce)] + /// + /// let numbers: Vec = Vec::new(); + /// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y)); + /// assert_eq!(sum, Some(None)); + /// ``` + /// + /// Use a [`Result`] instead of an [`Option`]: + /// + /// ``` + /// #![feature(iterator_try_reduce)] + /// + /// let numbers = vec!["1", "2", "3", "4", "5"]; + /// let max: Result, ::Err> = + /// numbers.into_iter().try_reduce(|x, y| { + /// if x.parse::()? > y.parse::()? { Ok(x) } else { Ok(y) } + /// }); + /// assert_eq!(max, Ok(Some("5"))); + /// ``` + #[inline] + #[unstable(feature = "iterator_try_reduce", reason = "new API", issue = "87053")] + fn try_reduce( + &mut self, + f: impl FnMut(Self::Item, Self::Item) -> R, + ) -> ChangeOutputType> + where + Self: Sized, + R: Try>>, + { + let first = match self.next() { + Some(i) => i, + None => return Try::from_output(None), + }; + + match self.try_fold(first, f).branch() { + ControlFlow::Break(r) => FromResidual::from_residual(r), + ControlFlow::Continue(i) => Try::from_output(Some(i)), + } + } + + /// Tests if every element of the iterator matches a predicate. + /// + /// `all()` takes a closure that returns `true` or `false`. It applies + /// this closure to each element of the iterator, and if they all return + /// `true`, then so does `all()`. If any of them return `false`, it + /// returns `false`. + /// + /// `all()` is short-circuiting; in other words, it will stop processing + /// as soon as it finds a `false`, given that no matter what else happens, + /// the result will also be `false`. + /// + /// An empty iterator returns `true`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// assert!(a.iter().all(|&x| x > 0)); + /// + /// assert!(!a.iter().all(|&x| x > 2)); + /// ``` + /// + /// Stopping at the first `false`: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter(); + /// + /// assert!(!iter.all(|&x| x != 2)); + /// + /// // we can still use `iter`, as there are more elements. + /// assert_eq!(iter.next(), Some(&3)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn all(&mut self, f: F) -> bool + where + Self: Sized, + F: FnMut(Self::Item) -> bool, + { + #[inline] + fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<()> { + move |(), x| { + if f(x) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) } + } + } + self.try_fold((), check(f)) == ControlFlow::Continue(()) + } + + /// Tests if any element of the iterator matches a predicate. + /// + /// `any()` takes a closure that returns `true` or `false`. It applies + /// this closure to each element of the iterator, and if any of them return + /// `true`, then so does `any()`. If they all return `false`, it + /// returns `false`. + /// + /// `any()` is short-circuiting; in other words, it will stop processing + /// as soon as it finds a `true`, given that no matter what else happens, + /// the result will also be `true`. + /// + /// An empty iterator returns `false`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// assert!(a.iter().any(|&x| x > 0)); + /// + /// assert!(!a.iter().any(|&x| x > 5)); + /// ``` + /// + /// Stopping at the first `true`: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter(); + /// + /// assert!(iter.any(|&x| x != 2)); + /// + /// // we can still use `iter`, as there are more elements. + /// assert_eq!(iter.next(), Some(&2)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn any(&mut self, f: F) -> bool + where + Self: Sized, + F: FnMut(Self::Item) -> bool, + { + #[inline] + fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<()> { + move |(), x| { + if f(x) { ControlFlow::Break(()) } else { ControlFlow::Continue(()) } + } + } + + self.try_fold((), check(f)) == ControlFlow::Break(()) + } + + /// Searches for an element of an iterator that satisfies a predicate. + /// + /// `find()` takes a closure that returns `true` or `false`. It applies + /// this closure to each element of the iterator, and if any of them return + /// `true`, then `find()` returns [`Some(element)`]. If they all return + /// `false`, it returns [`None`]. + /// + /// `find()` is short-circuiting; in other words, it will stop processing + /// as soon as the closure returns `true`. + /// + /// Because `find()` takes a reference, and many iterators iterate over + /// references, this leads to a possibly confusing situation where the + /// argument is a double reference. You can see this effect in the + /// examples below, with `&&x`. + /// + /// If you need the index of the element, see [`position()`]. + /// + /// [`Some(element)`]: Some + /// [`position()`]: Iterator::position + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// assert_eq!(a.iter().find(|&&x| x == 2), Some(&2)); + /// + /// assert_eq!(a.iter().find(|&&x| x == 5), None); + /// ``` + /// + /// Stopping at the first `true`: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.find(|&&x| x == 2), Some(&2)); + /// + /// // we can still use `iter`, as there are more elements. + /// assert_eq!(iter.next(), Some(&3)); + /// ``` + /// + /// Note that `iter.find(f)` is equivalent to `iter.filter(f).next()`. + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn find

(&mut self, predicate: P) -> Option + where + Self: Sized, + P: FnMut(&Self::Item) -> bool, + { + #[inline] + fn check(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow { + move |(), x| { + if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) } + } + } + + self.try_fold((), check(predicate)).break_value() + } + + /// Applies function to the elements of iterator and returns + /// the first non-none result. + /// + /// `iter.find_map(f)` is equivalent to `iter.filter_map(f).next()`. + /// + /// # Examples + /// + /// ``` + /// let a = ["lol", "NaN", "2", "5"]; + /// + /// let first_number = a.iter().find_map(|s| s.parse().ok()); + /// + /// assert_eq!(first_number, Some(2)); + /// ``` + #[inline] + #[stable(feature = "iterator_find_map", since = "1.30.0")] + fn find_map(&mut self, f: F) -> Option + where + Self: Sized, + F: FnMut(Self::Item) -> Option, + { + #[inline] + fn check(mut f: impl FnMut(T) -> Option) -> impl FnMut((), T) -> ControlFlow { + move |(), x| match f(x) { + Some(x) => ControlFlow::Break(x), + None => ControlFlow::Continue(()), + } + } + + self.try_fold((), check(f)).break_value() + } + + /// Applies function to the elements of iterator and returns + /// the first true result or the first error. + /// + /// The return type of this method depends on the return type of the closure. + /// If you return `Result` from the closure, you'll get a `Result, E>`. + /// If you return `Option` from the closure, you'll get an `Option>`. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_find)] + /// + /// let a = ["1", "2", "lol", "NaN", "5"]; + /// + /// let is_my_num = |s: &str, search: i32| -> Result { + /// Ok(s.parse::()? == search) + /// }; + /// + /// let result = a.iter().try_find(|&&s| is_my_num(s, 2)); + /// assert_eq!(result, Ok(Some(&"2"))); + /// + /// let result = a.iter().try_find(|&&s| is_my_num(s, 5)); + /// assert!(result.is_err()); + /// ``` + /// + /// This also supports other types which implement [`Try`], not just [`Result`]. + /// + /// ``` + /// #![feature(try_find)] + /// + /// use std::num::NonZero; + /// + /// let a = [3, 5, 7, 4, 9, 0, 11u32]; + /// let result = a.iter().try_find(|&&x| NonZero::new(x).map(|y| y.is_power_of_two())); + /// assert_eq!(result, Some(Some(&4))); + /// let result = a.iter().take(3).try_find(|&&x| NonZero::new(x).map(|y| y.is_power_of_two())); + /// assert_eq!(result, Some(None)); + /// let result = a.iter().rev().try_find(|&&x| NonZero::new(x).map(|y| y.is_power_of_two())); + /// assert_eq!(result, None); + /// ``` + #[inline] + #[unstable(feature = "try_find", reason = "new API", issue = "63178")] + fn try_find( + &mut self, + f: impl FnMut(&Self::Item) -> R, + ) -> ChangeOutputType> + where + Self: Sized, + R: Try>>, + { + #[inline] + fn check( + mut f: impl FnMut(&I) -> V, + ) -> impl FnMut((), I) -> ControlFlow + where + V: Try, + R: Residual>, + { + move |(), x| match f(&x).branch() { + ControlFlow::Continue(false) => ControlFlow::Continue(()), + ControlFlow::Continue(true) => ControlFlow::Break(Try::from_output(Some(x))), + ControlFlow::Break(r) => ControlFlow::Break(FromResidual::from_residual(r)), + } + } + + match self.try_fold((), check(f)) { + ControlFlow::Break(x) => x, + ControlFlow::Continue(()) => Try::from_output(None), + } + } + + /// Searches for an element in an iterator, returning its index. + /// + /// `position()` takes a closure that returns `true` or `false`. It applies + /// this closure to each element of the iterator, and if one of them + /// returns `true`, then `position()` returns [`Some(index)`]. If all of + /// them return `false`, it returns [`None`]. + /// + /// `position()` is short-circuiting; in other words, it will stop + /// processing as soon as it finds a `true`. + /// + /// # Overflow Behavior + /// + /// The method does no guarding against overflows, so if there are more + /// than [`usize::MAX`] non-matching elements, it either produces the wrong + /// result or panics. If debug assertions are enabled, a panic is + /// guaranteed. + /// + /// # Panics + /// + /// This function might panic if the iterator has more than `usize::MAX` + /// non-matching elements. + /// + /// [`Some(index)`]: Some + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// assert_eq!(a.iter().position(|&x| x == 2), Some(1)); + /// + /// assert_eq!(a.iter().position(|&x| x == 5), None); + /// ``` + /// + /// Stopping at the first `true`: + /// + /// ``` + /// let a = [1, 2, 3, 4]; + /// + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.position(|&x| x >= 2), Some(1)); + /// + /// // we can still use `iter`, as there are more elements. + /// assert_eq!(iter.next(), Some(&3)); + /// + /// // The returned index depends on iterator state + /// assert_eq!(iter.position(|&x| x == 4), Some(0)); + /// + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn position

(&mut self, predicate: P) -> Option + where + Self: Sized, + P: FnMut(Self::Item) -> bool, + { + #[inline] + fn check<'a, T>( + mut predicate: impl FnMut(T) -> bool + 'a, + acc: &'a mut usize, + ) -> impl FnMut((), T) -> ControlFlow + 'a { + #[rustc_inherit_overflow_checks] + move |_, x| { + if predicate(x) { + ControlFlow::Break(*acc) + } else { + *acc += 1; + ControlFlow::Continue(()) + } + } + } + + let mut acc = 0; + self.try_fold((), check(predicate, &mut acc)).break_value() + } + + /// Searches for an element in an iterator from the right, returning its + /// index. + /// + /// `rposition()` takes a closure that returns `true` or `false`. It applies + /// this closure to each element of the iterator, starting from the end, + /// and if one of them returns `true`, then `rposition()` returns + /// [`Some(index)`]. If all of them return `false`, it returns [`None`]. + /// + /// `rposition()` is short-circuiting; in other words, it will stop + /// processing as soon as it finds a `true`. + /// + /// [`Some(index)`]: Some + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// assert_eq!(a.iter().rposition(|&x| x == 3), Some(2)); + /// + /// assert_eq!(a.iter().rposition(|&x| x == 5), None); + /// ``` + /// + /// Stopping at the first `true`: + /// + /// ``` + /// let a = [-1, 2, 3, 4]; + /// + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.rposition(|&x| x >= 2), Some(3)); + /// + /// // we can still use `iter`, as there are more elements. + /// assert_eq!(iter.next(), Some(&-1)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn rposition

(&mut self, predicate: P) -> Option + where + P: FnMut(Self::Item) -> bool, + Self: Sized + ExactSizeIterator + DoubleEndedIterator, + { + // No need for an overflow check here, because `ExactSizeIterator` + // implies that the number of elements fits into a `usize`. + #[inline] + fn check( + mut predicate: impl FnMut(T) -> bool, + ) -> impl FnMut(usize, T) -> ControlFlow { + move |i, x| { + let i = i - 1; + if predicate(x) { ControlFlow::Break(i) } else { ControlFlow::Continue(i) } + } + } + + let n = self.len(); + self.try_rfold(n, check(predicate)).break_value() + } + + /// Returns the maximum element of an iterator. + /// + /// If several elements are equally maximum, the last element is + /// returned. If the iterator is empty, [`None`] is returned. + /// + /// Note that [`f32`]/[`f64`] doesn't implement [`Ord`] due to NaN being + /// incomparable. You can work around this by using [`Iterator::reduce`]: + /// ``` + /// assert_eq!( + /// [2.4, f32::NAN, 1.3] + /// .into_iter() + /// .reduce(f32::max) + /// .unwrap(), + /// 2.4 + /// ); + /// ``` + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// let b: Vec = Vec::new(); + /// + /// assert_eq!(a.iter().max(), Some(&3)); + /// assert_eq!(b.iter().max(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn max(self) -> Option + where + Self: Sized, + Self::Item: Ord, + { + self.max_by(Ord::cmp) + } + + /// Returns the minimum element of an iterator. + /// + /// If several elements are equally minimum, the first element is returned. + /// If the iterator is empty, [`None`] is returned. + /// + /// Note that [`f32`]/[`f64`] doesn't implement [`Ord`] due to NaN being + /// incomparable. You can work around this by using [`Iterator::reduce`]: + /// ``` + /// assert_eq!( + /// [2.4, f32::NAN, 1.3] + /// .into_iter() + /// .reduce(f32::min) + /// .unwrap(), + /// 1.3 + /// ); + /// ``` + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// let b: Vec = Vec::new(); + /// + /// assert_eq!(a.iter().min(), Some(&1)); + /// assert_eq!(b.iter().min(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn min(self) -> Option + where + Self: Sized, + Self::Item: Ord, + { + self.min_by(Ord::cmp) + } + + /// Returns the element that gives the maximum value from the + /// specified function. + /// + /// If several elements are equally maximum, the last element is + /// returned. If the iterator is empty, [`None`] is returned. + /// + /// # Examples + /// + /// ``` + /// let a = [-3_i32, 0, 1, 5, -10]; + /// assert_eq!(*a.iter().max_by_key(|x| x.abs()).unwrap(), -10); + /// ``` + #[inline] + #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] + fn max_by_key(self, f: F) -> Option + where + Self: Sized, + F: FnMut(&Self::Item) -> B, + { + #[inline] + fn key(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) { + move |x| (f(&x), x) + } + + #[inline] + fn compare((x_p, _): &(B, T), (y_p, _): &(B, T)) -> Ordering { + x_p.cmp(y_p) + } + + let (_, x) = self.map(key(f)).max_by(compare)?; + Some(x) + } + + /// Returns the element that gives the maximum value with respect to the + /// specified comparison function. + /// + /// If several elements are equally maximum, the last element is + /// returned. If the iterator is empty, [`None`] is returned. + /// + /// # Examples + /// + /// ``` + /// let a = [-3_i32, 0, 1, 5, -10]; + /// assert_eq!(*a.iter().max_by(|x, y| x.cmp(y)).unwrap(), 5); + /// ``` + #[inline] + #[stable(feature = "iter_max_by", since = "1.15.0")] + fn max_by(self, compare: F) -> Option + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, + { + #[inline] + fn fold(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(T, T) -> T { + move |x, y| cmp::max_by(x, y, &mut compare) + } + + self.reduce(fold(compare)) + } + + /// Returns the element that gives the minimum value from the + /// specified function. + /// + /// If several elements are equally minimum, the first element is + /// returned. If the iterator is empty, [`None`] is returned. + /// + /// # Examples + /// + /// ``` + /// let a = [-3_i32, 0, 1, 5, -10]; + /// assert_eq!(*a.iter().min_by_key(|x| x.abs()).unwrap(), 0); + /// ``` + #[inline] + #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] + fn min_by_key(self, f: F) -> Option + where + Self: Sized, + F: FnMut(&Self::Item) -> B, + { + #[inline] + fn key(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) { + move |x| (f(&x), x) + } + + #[inline] + fn compare((x_p, _): &(B, T), (y_p, _): &(B, T)) -> Ordering { + x_p.cmp(y_p) + } + + let (_, x) = self.map(key(f)).min_by(compare)?; + Some(x) + } + + /// Returns the element that gives the minimum value with respect to the + /// specified comparison function. + /// + /// If several elements are equally minimum, the first element is + /// returned. If the iterator is empty, [`None`] is returned. + /// + /// # Examples + /// + /// ``` + /// let a = [-3_i32, 0, 1, 5, -10]; + /// assert_eq!(*a.iter().min_by(|x, y| x.cmp(y)).unwrap(), -10); + /// ``` + #[inline] + #[stable(feature = "iter_min_by", since = "1.15.0")] + fn min_by(self, compare: F) -> Option + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, + { + #[inline] + fn fold(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(T, T) -> T { + move |x, y| cmp::min_by(x, y, &mut compare) + } + + self.reduce(fold(compare)) + } + + /// Reverses an iterator's direction. + /// + /// Usually, iterators iterate from left to right. After using `rev()`, + /// an iterator will instead iterate from right to left. + /// + /// This is only possible if the iterator has an end, so `rev()` only + /// works on [`DoubleEndedIterator`]s. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter().rev(); + /// + /// assert_eq!(iter.next(), Some(&3)); + /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), Some(&1)); + /// + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[doc(alias = "reverse")] + #[stable(feature = "rust1", since = "1.0.0")] + fn rev(self) -> Rev + where + Self: Sized + DoubleEndedIterator, + { + Rev::new(self) + } + + /// Converts an iterator of pairs into a pair of containers. + /// + /// `unzip()` consumes an entire iterator of pairs, producing two + /// collections: one from the left elements of the pairs, and one + /// from the right elements. + /// + /// This function is, in some sense, the opposite of [`zip`]. + /// + /// [`zip`]: Iterator::zip + /// + /// # Examples + /// + /// ``` + /// let a = [(1, 2), (3, 4), (5, 6)]; + /// + /// let (left, right): (Vec<_>, Vec<_>) = a.iter().cloned().unzip(); + /// + /// assert_eq!(left, [1, 3, 5]); + /// assert_eq!(right, [2, 4, 6]); + /// + /// // you can also unzip multiple nested tuples at once + /// let a = [(1, (2, 3)), (4, (5, 6))]; + /// + /// let (x, (y, z)): (Vec<_>, (Vec<_>, Vec<_>)) = a.iter().cloned().unzip(); + /// assert_eq!(x, [1, 4]); + /// assert_eq!(y, [2, 5]); + /// assert_eq!(z, [3, 6]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn unzip(self) -> (FromA, FromB) + where + FromA: Default + Extend, + FromB: Default + Extend, + Self: Sized + Iterator, + { + let mut unzipped: (FromA, FromB) = Default::default(); + unzipped.extend(self); + unzipped + } + + /// Creates an iterator which copies all of its elements. + /// + /// This is useful when you have an iterator over `&T`, but you need an + /// iterator over `T`. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let v_copied: Vec<_> = a.iter().copied().collect(); + /// + /// // copied is the same as .map(|&x| x) + /// let v_map: Vec<_> = a.iter().map(|&x| x).collect(); + /// + /// assert_eq!(v_copied, vec![1, 2, 3]); + /// assert_eq!(v_map, vec![1, 2, 3]); + /// ``` + #[stable(feature = "iter_copied", since = "1.36.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "iter_copied")] + fn copied<'a, T: 'a>(self) -> Copied + where + Self: Sized + Iterator, + T: Copy, + { + Copied::new(self) + } + + /// Creates an iterator which [`clone`]s all of its elements. + /// + /// This is useful when you have an iterator over `&T`, but you need an + /// iterator over `T`. + /// + /// There is no guarantee whatsoever about the `clone` method actually + /// being called *or* optimized away. So code should not depend on + /// either. + /// + /// [`clone`]: Clone::clone + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let v_cloned: Vec<_> = a.iter().cloned().collect(); + /// + /// // cloned is the same as .map(|&x| x), for integers + /// let v_map: Vec<_> = a.iter().map(|&x| x).collect(); + /// + /// assert_eq!(v_cloned, vec![1, 2, 3]); + /// assert_eq!(v_map, vec![1, 2, 3]); + /// ``` + /// + /// To get the best performance, try to clone late: + /// + /// ``` + /// let a = [vec![0_u8, 1, 2], vec![3, 4], vec![23]]; + /// // don't do this: + /// let slower: Vec<_> = a.iter().cloned().filter(|s| s.len() == 1).collect(); + /// assert_eq!(&[vec![23]], &slower[..]); + /// // instead call `cloned` late + /// let faster: Vec<_> = a.iter().filter(|s| s.len() == 1).cloned().collect(); + /// assert_eq!(&[vec![23]], &faster[..]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "iter_cloned")] + fn cloned<'a, T: 'a>(self) -> Cloned + where + Self: Sized + Iterator, + T: Clone, + { + Cloned::new(self) + } + + /// Repeats an iterator endlessly. + /// + /// Instead of stopping at [`None`], the iterator will instead start again, + /// from the beginning. After iterating again, it will start at the + /// beginning again. And again. And again. Forever. Note that in case the + /// original iterator is empty, the resulting iterator will also be empty. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// + /// let mut it = a.iter().cycle(); + /// + /// assert_eq!(it.next(), Some(&1)); + /// assert_eq!(it.next(), Some(&2)); + /// assert_eq!(it.next(), Some(&3)); + /// assert_eq!(it.next(), Some(&1)); + /// assert_eq!(it.next(), Some(&2)); + /// assert_eq!(it.next(), Some(&3)); + /// assert_eq!(it.next(), Some(&1)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + fn cycle(self) -> Cycle + where + Self: Sized + Clone, + { + Cycle::new(self) + } + + /// Returns an iterator over `N` elements of the iterator at a time. + /// + /// The chunks do not overlap. If `N` does not divide the length of the + /// iterator, then the last up to `N-1` elements will be omitted and can be + /// retrieved from the [`.into_remainder()`][ArrayChunks::into_remainder] + /// function of the iterator. + /// + /// # Panics + /// + /// Panics if `N` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_array_chunks)] + /// + /// let mut iter = "lorem".chars().array_chunks(); + /// assert_eq!(iter.next(), Some(['l', 'o'])); + /// assert_eq!(iter.next(), Some(['r', 'e'])); + /// assert_eq!(iter.next(), None); + /// assert_eq!(iter.into_remainder().unwrap().as_slice(), &['m']); + /// ``` + /// + /// ``` + /// #![feature(iter_array_chunks)] + /// + /// let data = [1, 1, 2, -2, 6, 0, 3, 1]; + /// // ^-----^ ^------^ + /// for [x, y, z] in data.iter().array_chunks() { + /// assert_eq!(x + y + z, 4); + /// } + /// ``` + #[track_caller] + #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] + fn array_chunks(self) -> ArrayChunks + where + Self: Sized, + { + ArrayChunks::new(self) + } + + /// Sums the elements of an iterator. + /// + /// Takes each element, adds them together, and returns the result. + /// + /// An empty iterator returns the zero value of the type. + /// + /// `sum()` can be used to sum any type implementing [`Sum`][`core::iter::Sum`], + /// including [`Option`][`Option::sum`] and [`Result`][`Result::sum`]. + /// + /// # Panics + /// + /// When calling `sum()` and a primitive integer type is being returned, this + /// method will panic if the computation overflows and debug assertions are + /// enabled. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// let sum: i32 = a.iter().sum(); + /// + /// assert_eq!(sum, 6); + /// ``` + #[stable(feature = "iter_arith", since = "1.11.0")] + fn sum(self) -> S + where + Self: Sized, + S: Sum, + { + Sum::sum(self) + } + + /// Iterates over the entire iterator, multiplying all the elements + /// + /// An empty iterator returns the one value of the type. + /// + /// `product()` can be used to multiply any type implementing [`Product`][`core::iter::Product`], + /// including [`Option`][`Option::product`] and [`Result`][`Result::product`]. + /// + /// # Panics + /// + /// When calling `product()` and a primitive integer type is being returned, + /// method will panic if the computation overflows and debug assertions are + /// enabled. + /// + /// # Examples + /// + /// ``` + /// fn factorial(n: u32) -> u32 { + /// (1..=n).product() + /// } + /// assert_eq!(factorial(0), 1); + /// assert_eq!(factorial(1), 1); + /// assert_eq!(factorial(5), 120); + /// ``` + #[stable(feature = "iter_arith", since = "1.11.0")] + fn product

(self) -> P + where + Self: Sized, + P: Product, + { + Product::product(self) + } + + /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those + /// of another. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!([1].iter().cmp([1].iter()), Ordering::Equal); + /// assert_eq!([1].iter().cmp([1, 2].iter()), Ordering::Less); + /// assert_eq!([1, 2].iter().cmp([1].iter()), Ordering::Greater); + /// ``` + #[stable(feature = "iter_order", since = "1.5.0")] + fn cmp(self, other: I) -> Ordering + where + I: IntoIterator, + Self::Item: Ord, + Self: Sized, + { + self.cmp_by(other, |x, y| x.cmp(&y)) + } + + /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those + /// of another with respect to the specified comparison function. + /// + /// # Examples + /// + /// ``` + /// #![feature(iter_order_by)] + /// + /// use std::cmp::Ordering; + /// + /// let xs = [1, 2, 3, 4]; + /// let ys = [1, 4, 9, 16]; + /// + /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| x.cmp(&y)), Ordering::Less); + /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (x * x).cmp(&y)), Ordering::Equal); + /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater); + /// ``` + #[unstable(feature = "iter_order_by", issue = "64295")] + fn cmp_by(self, other: I, cmp: F) -> Ordering + where + Self: Sized, + I: IntoIterator, + F: FnMut(Self::Item, I::Item) -> Ordering, + { + #[inline] + fn compare(mut cmp: F) -> impl FnMut(X, Y) -> ControlFlow + where + F: FnMut(X, Y) -> Ordering, + { + move |x, y| match cmp(x, y) { + Ordering::Equal => ControlFlow::Continue(()), + non_eq => ControlFlow::Break(non_eq), + } + } + + match iter_compare(self, other.into_iter(), compare(cmp)) { + ControlFlow::Continue(ord) => ord, + ControlFlow::Break(ord) => ord, + } + } + + /// [Lexicographically](Ord#lexicographical-comparison) compares the [`PartialOrd`] elements of + /// this [`Iterator`] with those of another. The comparison works like short-circuit + /// evaluation, returning a result without comparing the remaining elements. + /// As soon as an order can be determined, the evaluation stops and a result is returned. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!([1.].iter().partial_cmp([1.].iter()), Some(Ordering::Equal)); + /// assert_eq!([1.].iter().partial_cmp([1., 2.].iter()), Some(Ordering::Less)); + /// assert_eq!([1., 2.].iter().partial_cmp([1.].iter()), Some(Ordering::Greater)); + /// ``` + /// + /// For floating-point numbers, NaN does not have a total order and will result + /// in `None` when compared: + /// + /// ``` + /// assert_eq!([f64::NAN].iter().partial_cmp([1.].iter()), None); + /// ``` + /// + /// The results are determined by the order of evaluation. + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!([1.0, f64::NAN].iter().partial_cmp([2.0, f64::NAN].iter()), Some(Ordering::Less)); + /// assert_eq!([2.0, f64::NAN].iter().partial_cmp([1.0, f64::NAN].iter()), Some(Ordering::Greater)); + /// assert_eq!([f64::NAN, 1.0].iter().partial_cmp([f64::NAN, 2.0].iter()), None); + /// ``` + /// + #[stable(feature = "iter_order", since = "1.5.0")] + fn partial_cmp(self, other: I) -> Option + where + I: IntoIterator, + Self::Item: PartialOrd, + Self: Sized, + { + self.partial_cmp_by(other, |x, y| x.partial_cmp(&y)) + } + + /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those + /// of another with respect to the specified comparison function. + /// + /// # Examples + /// + /// ``` + /// #![feature(iter_order_by)] + /// + /// use std::cmp::Ordering; + /// + /// let xs = [1.0, 2.0, 3.0, 4.0]; + /// let ys = [1.0, 4.0, 9.0, 16.0]; + /// + /// assert_eq!( + /// xs.iter().partial_cmp_by(&ys, |&x, &y| x.partial_cmp(&y)), + /// Some(Ordering::Less) + /// ); + /// assert_eq!( + /// xs.iter().partial_cmp_by(&ys, |&x, &y| (x * x).partial_cmp(&y)), + /// Some(Ordering::Equal) + /// ); + /// assert_eq!( + /// xs.iter().partial_cmp_by(&ys, |&x, &y| (2.0 * x).partial_cmp(&y)), + /// Some(Ordering::Greater) + /// ); + /// ``` + #[unstable(feature = "iter_order_by", issue = "64295")] + fn partial_cmp_by(self, other: I, partial_cmp: F) -> Option + where + Self: Sized, + I: IntoIterator, + F: FnMut(Self::Item, I::Item) -> Option, + { + #[inline] + fn compare(mut partial_cmp: F) -> impl FnMut(X, Y) -> ControlFlow> + where + F: FnMut(X, Y) -> Option, + { + move |x, y| match partial_cmp(x, y) { + Some(Ordering::Equal) => ControlFlow::Continue(()), + non_eq => ControlFlow::Break(non_eq), + } + } + + match iter_compare(self, other.into_iter(), compare(partial_cmp)) { + ControlFlow::Continue(ord) => Some(ord), + ControlFlow::Break(ord) => ord, + } + } + + /// Determines if the elements of this [`Iterator`] are equal to those of + /// another. + /// + /// # Examples + /// + /// ``` + /// assert_eq!([1].iter().eq([1].iter()), true); + /// assert_eq!([1].iter().eq([1, 2].iter()), false); + /// ``` + #[stable(feature = "iter_order", since = "1.5.0")] + fn eq(self, other: I) -> bool + where + I: IntoIterator, + Self::Item: PartialEq, + Self: Sized, + { + self.eq_by(other, |x, y| x == y) + } + + /// Determines if the elements of this [`Iterator`] are equal to those of + /// another with respect to the specified equality function. + /// + /// # Examples + /// + /// ``` + /// #![feature(iter_order_by)] + /// + /// let xs = [1, 2, 3, 4]; + /// let ys = [1, 4, 9, 16]; + /// + /// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y)); + /// ``` + #[unstable(feature = "iter_order_by", issue = "64295")] + fn eq_by(self, other: I, eq: F) -> bool + where + Self: Sized, + I: IntoIterator, + F: FnMut(Self::Item, I::Item) -> bool, + { + #[inline] + fn compare(mut eq: F) -> impl FnMut(X, Y) -> ControlFlow<()> + where + F: FnMut(X, Y) -> bool, + { + move |x, y| { + if eq(x, y) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) } + } + } + + match iter_compare(self, other.into_iter(), compare(eq)) { + ControlFlow::Continue(ord) => ord == Ordering::Equal, + ControlFlow::Break(()) => false, + } + } + + /// Determines if the elements of this [`Iterator`] are not equal to those of + /// another. + /// + /// # Examples + /// + /// ``` + /// assert_eq!([1].iter().ne([1].iter()), false); + /// assert_eq!([1].iter().ne([1, 2].iter()), true); + /// ``` + #[stable(feature = "iter_order", since = "1.5.0")] + fn ne(self, other: I) -> bool + where + I: IntoIterator, + Self::Item: PartialEq, + Self: Sized, + { + !self.eq(other) + } + + /// Determines if the elements of this [`Iterator`] are [lexicographically](Ord#lexicographical-comparison) + /// less than those of another. + /// + /// # Examples + /// + /// ``` + /// assert_eq!([1].iter().lt([1].iter()), false); + /// assert_eq!([1].iter().lt([1, 2].iter()), true); + /// assert_eq!([1, 2].iter().lt([1].iter()), false); + /// assert_eq!([1, 2].iter().lt([1, 2].iter()), false); + /// ``` + #[stable(feature = "iter_order", since = "1.5.0")] + fn lt(self, other: I) -> bool + where + I: IntoIterator, + Self::Item: PartialOrd, + Self: Sized, + { + self.partial_cmp(other) == Some(Ordering::Less) + } + + /// Determines if the elements of this [`Iterator`] are [lexicographically](Ord#lexicographical-comparison) + /// less or equal to those of another. + /// + /// # Examples + /// + /// ``` + /// assert_eq!([1].iter().le([1].iter()), true); + /// assert_eq!([1].iter().le([1, 2].iter()), true); + /// assert_eq!([1, 2].iter().le([1].iter()), false); + /// assert_eq!([1, 2].iter().le([1, 2].iter()), true); + /// ``` + #[stable(feature = "iter_order", since = "1.5.0")] + fn le(self, other: I) -> bool + where + I: IntoIterator, + Self::Item: PartialOrd, + Self: Sized, + { + matches!(self.partial_cmp(other), Some(Ordering::Less | Ordering::Equal)) + } + + /// Determines if the elements of this [`Iterator`] are [lexicographically](Ord#lexicographical-comparison) + /// greater than those of another. + /// + /// # Examples + /// + /// ``` + /// assert_eq!([1].iter().gt([1].iter()), false); + /// assert_eq!([1].iter().gt([1, 2].iter()), false); + /// assert_eq!([1, 2].iter().gt([1].iter()), true); + /// assert_eq!([1, 2].iter().gt([1, 2].iter()), false); + /// ``` + #[stable(feature = "iter_order", since = "1.5.0")] + fn gt(self, other: I) -> bool + where + I: IntoIterator, + Self::Item: PartialOrd, + Self: Sized, + { + self.partial_cmp(other) == Some(Ordering::Greater) + } + + /// Determines if the elements of this [`Iterator`] are [lexicographically](Ord#lexicographical-comparison) + /// greater than or equal to those of another. + /// + /// # Examples + /// + /// ``` + /// assert_eq!([1].iter().ge([1].iter()), true); + /// assert_eq!([1].iter().ge([1, 2].iter()), false); + /// assert_eq!([1, 2].iter().ge([1].iter()), true); + /// assert_eq!([1, 2].iter().ge([1, 2].iter()), true); + /// ``` + #[stable(feature = "iter_order", since = "1.5.0")] + fn ge(self, other: I) -> bool + where + I: IntoIterator, + Self::Item: PartialOrd, + Self: Sized, + { + matches!(self.partial_cmp(other), Some(Ordering::Greater | Ordering::Equal)) + } + + /// Checks if the elements of this iterator are sorted. + /// + /// That is, for each element `a` and its following element `b`, `a <= b` must hold. If the + /// iterator yields exactly zero or one element, `true` is returned. + /// + /// Note that if `Self::Item` is only `PartialOrd`, but not `Ord`, the above definition + /// implies that this function returns `false` if any two consecutive items are not + /// comparable. + /// + /// # Examples + /// + /// ``` + /// assert!([1, 2, 2, 9].iter().is_sorted()); + /// assert!(![1, 3, 2, 4].iter().is_sorted()); + /// assert!([0].iter().is_sorted()); + /// assert!(std::iter::empty::().is_sorted()); + /// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted()); + /// ``` + #[inline] + #[stable(feature = "is_sorted", since = "1.82.0")] + fn is_sorted(self) -> bool + where + Self: Sized, + Self::Item: PartialOrd, + { + self.is_sorted_by(|a, b| a <= b) + } + + /// Checks if the elements of this iterator are sorted using the given comparator function. + /// + /// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare` + /// function to determine whether two elements are to be considered in sorted order. + /// + /// # Examples + /// + /// ``` + /// assert!([1, 2, 2, 9].iter().is_sorted_by(|a, b| a <= b)); + /// assert!(![1, 2, 2, 9].iter().is_sorted_by(|a, b| a < b)); + /// + /// assert!([0].iter().is_sorted_by(|a, b| true)); + /// assert!([0].iter().is_sorted_by(|a, b| false)); + /// + /// assert!(std::iter::empty::().is_sorted_by(|a, b| false)); + /// assert!(std::iter::empty::().is_sorted_by(|a, b| true)); + /// ``` + #[stable(feature = "is_sorted", since = "1.82.0")] + fn is_sorted_by(mut self, compare: F) -> bool + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> bool, + { + #[inline] + fn check<'a, T>( + last: &'a mut T, + mut compare: impl FnMut(&T, &T) -> bool + 'a, + ) -> impl FnMut(T) -> bool + 'a { + move |curr| { + if !compare(&last, &curr) { + return false; + } + *last = curr; + true + } + } + + let mut last = match self.next() { + Some(e) => e, + None => return true, + }; + + self.all(check(&mut last, compare)) + } + + /// Checks if the elements of this iterator are sorted using the given key extraction + /// function. + /// + /// Instead of comparing the iterator's elements directly, this function compares the keys of + /// the elements, as determined by `f`. Apart from that, it's equivalent to [`is_sorted`]; see + /// its documentation for more information. + /// + /// [`is_sorted`]: Iterator::is_sorted + /// + /// # Examples + /// + /// ``` + /// assert!(["c", "bb", "aaa"].iter().is_sorted_by_key(|s| s.len())); + /// assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs())); + /// ``` + #[inline] + #[stable(feature = "is_sorted", since = "1.82.0")] + fn is_sorted_by_key(self, f: F) -> bool + where + Self: Sized, + F: FnMut(Self::Item) -> K, + K: PartialOrd, + { + self.map(f).is_sorted() + } + + /// See [TrustedRandomAccess][super::super::TrustedRandomAccess] + // The unusual name is to avoid name collisions in method resolution + // see #76479. + #[inline] + #[doc(hidden)] + #[unstable(feature = "trusted_random_access", issue = "none")] + unsafe fn __iterator_get_unchecked(&mut self, _idx: usize) -> Self::Item + where + Self: TrustedRandomAccessNoCoerce, + { + unreachable!("Always specialized"); + } +} + +/// Compares two iterators element-wise using the given function. +/// +/// If `ControlFlow::Continue(())` is returned from the function, the comparison moves on to the next +/// elements of both iterators. Returning `ControlFlow::Break(x)` short-circuits the iteration and +/// returns `ControlFlow::Break(x)`. If one of the iterators runs out of elements, +/// `ControlFlow::Continue(ord)` is returned where `ord` is the result of comparing the lengths of +/// the iterators. +/// +/// Isolates the logic shared by ['cmp_by'](Iterator::cmp_by), +/// ['partial_cmp_by'](Iterator::partial_cmp_by), and ['eq_by'](Iterator::eq_by). +#[inline] +fn iter_compare(mut a: A, mut b: B, f: F) -> ControlFlow +where + A: Iterator, + B: Iterator, + F: FnMut(A::Item, B::Item) -> ControlFlow, +{ + #[inline] + fn compare<'a, B, X, T>( + b: &'a mut B, + mut f: impl FnMut(X, B::Item) -> ControlFlow + 'a, + ) -> impl FnMut(X) -> ControlFlow> + 'a + where + B: Iterator, + { + move |x| match b.next() { + None => ControlFlow::Break(ControlFlow::Continue(Ordering::Greater)), + Some(y) => f(x, y).map_break(ControlFlow::Break), + } + } + + match a.try_for_each(compare(&mut b, f)) { + ControlFlow::Continue(()) => ControlFlow::Continue(match b.next() { + None => Ordering::Equal, + Some(_) => Ordering::Less, + }), + ControlFlow::Break(x) => x, + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for &mut I { + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option { + (**self).next() + } + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + (**self).advance_by(n) + } + fn nth(&mut self, n: usize) -> Option { + (**self).nth(n) + } + fn fold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.spec_fold(init, f) + } + fn try_fold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.spec_try_fold(init, f) + } +} + +/// Helper trait to specialize `fold` and `try_fold` for `&mut I where I: Sized` +trait IteratorRefSpec: Iterator { + fn spec_fold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B; + + fn spec_try_fold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try; +} + +impl IteratorRefSpec for &mut I { + default fn spec_fold(self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let mut accum = init; + while let Some(x) = self.next() { + accum = f(accum, x); + } + accum + } + + default fn spec_try_fold(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let mut accum = init; + while let Some(x) = self.next() { + accum = f(accum, x)?; + } + try { accum } + } +} + +impl IteratorRefSpec for &mut I { + impl_fold_via_try_fold! { spec_fold -> spec_try_fold } + + fn spec_try_fold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + (**self).try_fold(init, f) + } +} diff --git a/CoqOfRust/core/iter/traits/marker.rs b/CoqOfRust/core/iter/traits/marker.rs new file mode 100644 index 000000000..2e756a6dd --- /dev/null +++ b/CoqOfRust/core/iter/traits/marker.rs @@ -0,0 +1,116 @@ +use crate::iter::Step; +use crate::num::NonZero; + +/// Same as FusedIterator +/// +/// # Safety +/// +/// This is used for specialization. Therefore implementations must not +/// be lifetime-dependent. +#[unstable(issue = "none", feature = "trusted_fused")] +#[doc(hidden)] +#[rustc_specialization_trait] +pub unsafe trait TrustedFused {} + +/// An iterator that always continues to yield `None` when exhausted. +/// +/// Calling next on a fused iterator that has returned `None` once is guaranteed +/// to return [`None`] again. This trait should be implemented by all iterators +/// that behave this way because it allows optimizing [`Iterator::fuse()`]. +/// +/// Note: In general, you should not use `FusedIterator` in generic bounds if +/// you need a fused iterator. Instead, you should just call [`Iterator::fuse()`] +/// on the iterator. If the iterator is already fused, the additional [`Fuse`] +/// wrapper will be a no-op with no performance penalty. +/// +/// [`Fuse`]: crate::iter::Fuse +#[stable(feature = "fused", since = "1.26.0")] +#[rustc_unsafe_specialization_marker] +// FIXME: this should be a #[marker] and have another blanket impl for T: TrustedFused +// but that ICEs iter::Fuse specializations. +#[lang = "fused_iterator"] +pub trait FusedIterator: Iterator {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for &mut I {} + +/// An iterator that reports an accurate length using size_hint. +/// +/// The iterator reports a size hint where it is either exact +/// (lower bound is equal to upper bound), or the upper bound is [`None`]. +/// The upper bound must only be [`None`] if the actual iterator length is +/// larger than [`usize::MAX`]. In that case, the lower bound must be +/// [`usize::MAX`], resulting in an [`Iterator::size_hint()`] of +/// `(usize::MAX, None)`. +/// +/// The iterator must produce exactly the number of elements it reported +/// or diverge before reaching the end. +/// +/// # When *shouldn't* an adapter be `TrustedLen`? +/// +/// If an adapter makes an iterator *shorter* by a given amount, then it's +/// usually incorrect for that adapter to implement `TrustedLen`. The inner +/// iterator might return more than `usize::MAX` items, but there's no way to +/// know what `k` elements less than that will be, since the `size_hint` from +/// the inner iterator has already saturated and lost that information. +/// +/// This is why [`Skip`](crate::iter::Skip) isn't `TrustedLen`, even when +/// `I` implements `TrustedLen`. +/// +/// # Safety +/// +/// This trait must only be implemented when the contract is upheld. Consumers +/// of this trait must inspect [`Iterator::size_hint()`]’s upper bound. +#[unstable(feature = "trusted_len", issue = "37572")] +#[rustc_unsafe_specialization_marker] +pub unsafe trait TrustedLen: Iterator {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for &mut I {} + +/// An iterator that when yielding an item will have taken at least one element +/// from its underlying [`SourceIter`]. +/// +/// Calling any method that advances the iterator, e.g. [`next()`] or [`try_fold()`], +/// guarantees that for each step at least one value of the iterator's underlying source +/// has been moved out and the result of the iterator chain could be inserted +/// in its place, assuming structural constraints of the source allow such an insertion. +/// In other words this trait indicates that an iterator pipeline can be collected in place. +/// +/// The primary use of this trait is in-place iteration. Refer to the [`vec::in_place_collect`] +/// module documentation for more information. +/// +/// [`vec::in_place_collect`]: ../../../../alloc/vec/in_place_collect/index.html +/// [`SourceIter`]: crate::iter::SourceIter +/// [`next()`]: Iterator::next +/// [`try_fold()`]: Iterator::try_fold +#[unstable(issue = "none", feature = "inplace_iteration")] +#[doc(hidden)] +#[rustc_specialization_trait] +pub unsafe trait InPlaceIterable { + /// The product of one-to-many item expansions that happen throughout the iterator pipeline. + /// E.g. [[u8; 4]; 4].iter().flatten().flatten() would have a `EXPAND_BY` of 16. + /// This is an upper bound, i.e. the transformations will produce at most this many items per + /// input. It's meant for layout calculations. + const EXPAND_BY: Option>; + /// The product of many-to-one item reductions that happen throughout the iterator pipeline. + /// E.g. [u8].iter().array_chunks::<4>().array_chunks::<4>() would have a `MERGE_BY` of 16. + /// This is a lower bound, i.e. the transformations will consume at least this many items per + /// output. + const MERGE_BY: Option>; +} + +/// A type that upholds all invariants of [`Step`]. +/// +/// The invariants of [`Step::steps_between()`] are a superset of the invariants +/// of [`TrustedLen`]. As such, [`TrustedLen`] is implemented for all range +/// types with the same generic type argument. +/// +/// # Safety +/// +/// The implementation of [`Step`] for the given type must guarantee all +/// invariants of all methods are upheld. See the [`Step`] trait's documentation +/// for details. Consumers are free to rely on the invariants in unsafe code. +#[unstable(feature = "trusted_step", issue = "85731")] +#[rustc_specialization_trait] +pub unsafe trait TrustedStep: Step + Copy {} diff --git a/CoqOfRust/core/iter/traits/mod.rs b/CoqOfRust/core/iter/traits/mod.rs new file mode 100644 index 000000000..b330e9ffe --- /dev/null +++ b/CoqOfRust/core/iter/traits/mod.rs @@ -0,0 +1,24 @@ +mod accum; +mod collect; +mod double_ended; +mod exact_size; +mod iterator; +mod marker; +mod unchecked_iterator; + +#[unstable(issue = "none", feature = "inplace_iteration")] +pub use self::marker::InPlaceIterable; +#[unstable(issue = "none", feature = "trusted_fused")] +pub use self::marker::TrustedFused; +#[unstable(feature = "trusted_step", issue = "85731")] +pub use self::marker::TrustedStep; +pub(crate) use self::unchecked_iterator::UncheckedIterator; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::{ + accum::{Product, Sum}, + collect::{Extend, FromIterator, IntoIterator}, + double_ended::DoubleEndedIterator, + exact_size::ExactSizeIterator, + iterator::Iterator, + marker::{FusedIterator, TrustedLen}, +}; diff --git a/CoqOfRust/core/iter/traits/unchecked_iterator.rs b/CoqOfRust/core/iter/traits/unchecked_iterator.rs new file mode 100644 index 000000000..ae4bfcad4 --- /dev/null +++ b/CoqOfRust/core/iter/traits/unchecked_iterator.rs @@ -0,0 +1,36 @@ +use crate::iter::TrustedLen; + +/// [`TrustedLen`] cannot have methods, so this allows augmenting it. +/// +/// It currently requires `TrustedLen` because it's unclear whether it's +/// reasonably possible to depend on the `size_hint` of anything else. +pub(crate) trait UncheckedIterator: TrustedLen { + /// Gets the next item from a non-empty iterator. + /// + /// Because there's always a value to return, that means it can return + /// the `Item` type directly, without wrapping it in an `Option`. + /// + /// # Safety + /// + /// This can only be called if `size_hint().0 != 0`, guaranteeing that + /// there's at least one item available. + /// + /// Otherwise (aka when `size_hint().1 == Some(0)`), this is UB. + /// + /// # Note to Implementers + /// + /// This has a default implementation using [`Option::unwrap_unchecked`]. + /// That's probably sufficient if your `next` *always* returns `Some`, + /// such as for infinite iterators. In more complicated situations, however, + /// sometimes there can still be `insertvalue`/`assume`/`extractvalue` + /// instructions remaining in the IR from the `Option` handling, at which + /// point you might want to implement this manually instead. + #[unstable(feature = "trusted_len_next_unchecked", issue = "37572")] + #[inline] + unsafe fn next_unchecked(&mut self) -> Self::Item { + let opt = self.next(); + // SAFETY: The caller promised that we're not empty, and + // `Self: TrustedLen` so we can actually trust the `size_hint`. + unsafe { opt.unwrap_unchecked() } + } +} diff --git a/CoqOfRust/core/lib.miri.rs b/CoqOfRust/core/lib.miri.rs new file mode 100644 index 000000000..5c1027f20 --- /dev/null +++ b/CoqOfRust/core/lib.miri.rs @@ -0,0 +1,4 @@ +//! Grep bootstrap for `MIRI_REPLACE_LIBRS_IF_NOT_TEST` to learn what this is about. +#![no_std] +extern crate core as realcore; +pub use realcore::*; diff --git a/CoqOfRust/core/lib.rs b/CoqOfRust/core/lib.rs new file mode 100644 index 000000000..fde6887c5 --- /dev/null +++ b/CoqOfRust/core/lib.rs @@ -0,0 +1,425 @@ +//! # The Rust Core Library +//! +//! The Rust Core Library is the dependency-free[^free] foundation of [The +//! Rust Standard Library](../std/index.html). It is the portable glue +//! between the language and its libraries, defining the intrinsic and +//! primitive building blocks of all Rust code. It links to no +//! upstream libraries, no system libraries, and no libc. +//! +//! [^free]: Strictly speaking, there are some symbols which are needed but +//! they aren't always necessary. +//! +//! The core library is *minimal*: it isn't even aware of heap allocation, +//! nor does it provide concurrency or I/O. These things require +//! platform integration, and this library is platform-agnostic. +//! +//! # How to use the core library +//! +//! Please note that all of these details are currently not considered stable. +//! +// FIXME: Fill me in with more detail when the interface settles +//! This library is built on the assumption of a few existing symbols: +//! +//! * `memcpy`, `memmove`, `memset`, `memcmp`, `bcmp`, `strlen` - These are core memory routines +//! which are generated by Rust codegen backends. Additionally, this library can make explicit +//! calls to `strlen`. Their signatures are the same as found in C, but there are extra +//! assumptions about their semantics: For `memcpy`, `memmove`, `memset`, `memcmp`, and `bcmp`, if +//! the `n` parameter is 0, the function is assumed to not be UB, even if the pointers are NULL or +//! dangling. (Note that making extra assumptions about these functions is common among compilers: +//! [clang](https://reviews.llvm.org/D86993) and [GCC](https://gcc.gnu.org/onlinedocs/gcc/Standards.html#C-Language) do the same.) +//! These functions are often provided by the system libc, but can also be provided by the +//! [compiler-builtins crate](https://crates.io/crates/compiler_builtins). +//! Note that the library does not guarantee that it will always make these assumptions, so Rust +//! user code directly calling the C functions should follow the C specification! The advice for +//! Rust user code is to call the functions provided by this library instead (such as +//! `ptr::copy`). +//! +//! * Panic handler - This function takes one argument, a `&panic::PanicInfo`. It is up to consumers of this core +//! library to define this panic function; it is only required to never +//! return. You should mark your implementation using `#[panic_handler]`. +//! +//! * `rust_eh_personality` - is used by the failure mechanisms of the +//! compiler. This is often mapped to GCC's personality function, but crates +//! which do not trigger a panic can be assured that this function is never +//! called. The `lang` attribute is called `eh_personality`. + +// Since core defines many fundamental lang items, all tests live in a +// separate crate, libcoretest (library/core/tests), to avoid bizarre issues. +// +// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do +// this, both the generated test artifact and the linked libtest (which +// transitively includes core) will both define the same set of lang items, +// and this will cause the E0152 "found duplicate lang item" error. See +// discussion in #50466 for details. +// +// This cfg won't affect doc tests. +#![cfg(not(test))] +// +#![stable(feature = "core", since = "1.6.0")] +#![doc( + html_playground_url = "https://play.rust-lang.org/", + issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", + test(no_crate_inject, attr(deny(warnings))), + test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) +)] +#![doc(rust_logo)] +#![doc(cfg_hide( + not(test), + no_fp_fmt_parse, + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64", + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr", + target_has_atomic_equal_alignment = "8", + target_has_atomic_equal_alignment = "16", + target_has_atomic_equal_alignment = "32", + target_has_atomic_equal_alignment = "64", + target_has_atomic_equal_alignment = "ptr", + target_has_atomic_load_store = "8", + target_has_atomic_load_store = "16", + target_has_atomic_load_store = "32", + target_has_atomic_load_store = "64", + target_has_atomic_load_store = "ptr", +))] +#![no_core] +#![rustc_coherence_is_core] +#![rustc_preserve_ub_checks] +// +// Lints: +#![deny(rust_2021_incompatible_or_patterns)] +#![deny(unsafe_op_in_unsafe_fn)] +#![deny(fuzzy_provenance_casts)] +#![warn(deprecated_in_future)] +#![warn(missing_debug_implementations)] +#![warn(missing_docs)] +#![allow(explicit_outlives_requirements)] +#![allow(incomplete_features)] +#![warn(multiple_supertrait_upcastable)] +#![allow(internal_features)] +#![deny(ffi_unwind_calls)] +// Do not check link redundancy on bootstraping phase +#![allow(rustdoc::redundant_explicit_links)] +#![warn(rustdoc::unescaped_backticks)] +// +// Library features: +// tidy-alphabetical-start +#![feature(array_ptr_get)] +#![feature(asm_experimental_arch)] +#![feature(const_eval_select)] +#![feature(const_typed_swap)] +#![feature(core_intrinsics)] +#![feature(coverage_attribute)] +#![feature(do_not_recommend)] +#![feature(internal_impls_macro)] +#![feature(ip)] +#![feature(is_ascii_octdigit)] +#![feature(lazy_get)] +#![feature(link_cfg)] +#![feature(non_null_from_ref)] +#![feature(offset_of_enum)] +#![feature(panic_internals)] +#![feature(ptr_alignment_type)] +#![feature(ptr_metadata)] +#![feature(set_ptr_value)] +#![feature(slice_as_array)] +#![feature(slice_as_chunks)] +#![feature(slice_ptr_get)] +#![feature(str_internals)] +#![feature(str_split_inclusive_remainder)] +#![feature(str_split_remainder)] +#![feature(ub_checks)] +#![feature(unchecked_neg)] +#![feature(unchecked_shifts)] +#![feature(utf16_extra)] +#![feature(variant_count)] +// tidy-alphabetical-end +// +// Language features: +// tidy-alphabetical-start +#![feature(abi_unadjusted)] +#![feature(adt_const_params)] +#![feature(allow_internal_unsafe)] +#![feature(allow_internal_unstable)] +#![feature(auto_traits)] +#![feature(cfg_sanitize)] +#![feature(cfg_target_has_atomic)] +#![feature(cfg_target_has_atomic_equal_alignment)] +#![feature(cfg_ub_checks)] +#![feature(const_precise_live_drops)] +#![feature(const_trait_impl)] +#![feature(decl_macro)] +#![feature(deprecated_suggestion)] +#![feature(doc_cfg)] +#![feature(doc_cfg_hide)] +#![feature(doc_notable_trait)] +#![feature(extern_types)] +#![feature(f128)] +#![feature(f16)] +#![feature(freeze_impls)] +#![feature(fundamental)] +#![feature(generic_arg_infer)] +#![feature(if_let_guard)] +#![feature(intra_doc_pointers)] +#![feature(intrinsics)] +#![feature(lang_items)] +#![feature(let_chains)] +#![feature(link_llvm_intrinsics)] +#![feature(macro_metavar_expr)] +#![feature(marker_trait_attr)] +#![feature(min_specialization)] +#![feature(multiple_supertrait_upcastable)] +#![feature(must_not_suspend)] +#![feature(negative_impls)] +#![feature(never_type)] +#![feature(no_core)] +#![feature(no_sanitize)] +#![feature(optimize_attribute)] +#![feature(prelude_import)] +#![feature(repr_simd)] +#![feature(rustc_allow_const_fn_unstable)] +#![feature(rustc_attrs)] +#![feature(rustdoc_internals)] +#![feature(simd_ffi)] +#![feature(staged_api)] +#![feature(stmt_expr_attributes)] +#![feature(strict_provenance_lints)] +#![feature(target_feature_11)] +#![feature(trait_alias)] +#![feature(transparent_unions)] +#![feature(try_blocks)] +#![feature(unboxed_closures)] +#![feature(unsized_fn_params)] +#![feature(with_negative_coherence)] +// tidy-alphabetical-end +// +// Target features: +// tidy-alphabetical-start +#![feature(arm_target_feature)] +#![feature(avx512_target_feature)] +#![feature(hexagon_target_feature)] +#![feature(loongarch_target_feature)] +#![feature(mips_target_feature)] +#![feature(powerpc_target_feature)] +#![feature(riscv_target_feature)] +#![feature(rtm_target_feature)] +#![feature(sha512_sm_x86)] +#![feature(sse4a_target_feature)] +#![feature(tbm_target_feature)] +#![feature(wasm_target_feature)] +#![feature(x86_amx_intrinsics)] +// tidy-alphabetical-end + +// allow using `core::` in intra-doc links +#[allow(unused_extern_crates)] +extern crate self as core; + +#[prelude_import] +#[allow(unused)] +use prelude::rust_2021::*; + +#[cfg(not(test))] // See #65860 +#[macro_use] +mod macros; + +// We don't export this through #[macro_export] for now, to avoid breakage. +// See https://github.com/rust-lang/rust/issues/82913 +#[cfg(not(test))] +#[unstable(feature = "assert_matches", issue = "82775")] +/// Unstable module containing the unstable `assert_matches` macro. +pub mod assert_matches { + #[unstable(feature = "assert_matches", issue = "82775")] + pub use crate::macros::{assert_matches, debug_assert_matches}; +} + +// We don't export this through #[macro_export] for now, to avoid breakage. +#[unstable(feature = "autodiff", issue = "124509")] +/// Unstable module containing the unstable `autodiff` macro. +pub mod autodiff { + #[unstable(feature = "autodiff", issue = "124509")] + pub use crate::macros::builtin::autodiff; +} + +#[unstable(feature = "cfg_match", issue = "115585")] +pub use crate::macros::cfg_match; + +#[macro_use] +mod internal_macros; + +#[path = "num/shells/int_macros.rs"] +#[macro_use] +mod int_macros; + +#[rustc_diagnostic_item = "i128_legacy_mod"] +#[path = "num/shells/i128.rs"] +pub mod i128; +#[rustc_diagnostic_item = "i16_legacy_mod"] +#[path = "num/shells/i16.rs"] +pub mod i16; +#[rustc_diagnostic_item = "i32_legacy_mod"] +#[path = "num/shells/i32.rs"] +pub mod i32; +#[rustc_diagnostic_item = "i64_legacy_mod"] +#[path = "num/shells/i64.rs"] +pub mod i64; +#[rustc_diagnostic_item = "i8_legacy_mod"] +#[path = "num/shells/i8.rs"] +pub mod i8; +#[rustc_diagnostic_item = "isize_legacy_mod"] +#[path = "num/shells/isize.rs"] +pub mod isize; + +#[rustc_diagnostic_item = "u128_legacy_mod"] +#[path = "num/shells/u128.rs"] +pub mod u128; +#[rustc_diagnostic_item = "u16_legacy_mod"] +#[path = "num/shells/u16.rs"] +pub mod u16; +#[rustc_diagnostic_item = "u32_legacy_mod"] +#[path = "num/shells/u32.rs"] +pub mod u32; +#[rustc_diagnostic_item = "u64_legacy_mod"] +#[path = "num/shells/u64.rs"] +pub mod u64; +#[rustc_diagnostic_item = "u8_legacy_mod"] +#[path = "num/shells/u8.rs"] +pub mod u8; +#[rustc_diagnostic_item = "usize_legacy_mod"] +#[path = "num/shells/usize.rs"] +pub mod usize; + +#[path = "num/f128.rs"] +pub mod f128; +#[path = "num/f16.rs"] +pub mod f16; +#[path = "num/f32.rs"] +pub mod f32; +#[path = "num/f64.rs"] +pub mod f64; + +#[macro_use] +pub mod num; + +/* The core prelude, not as all-encompassing as the std prelude */ + +pub mod prelude; + +/* Core modules for ownership management */ + +pub mod hint; +pub mod intrinsics; +pub mod mem; +pub mod ptr; +#[unstable(feature = "ub_checks", issue = "none")] +pub mod ub_checks; + +/* Core language traits */ + +pub mod borrow; +pub mod clone; +pub mod cmp; +pub mod convert; +pub mod default; +pub mod error; +pub mod marker; +pub mod ops; + +/* Core types and methods on primitives */ + +pub mod any; +pub mod array; +pub mod ascii; +pub mod asserting; +#[unstable(feature = "async_iterator", issue = "79024")] +pub mod async_iter; +pub mod cell; +pub mod char; +pub mod ffi; +#[unstable(feature = "core_io_borrowed_buf", issue = "117693")] +pub mod io; +pub mod iter; +pub mod net; +pub mod option; +pub mod panic; +pub mod panicking; +#[unstable(feature = "pattern_type_macro", issue = "123646")] +pub mod pat; +pub mod pin; +#[unstable(feature = "random", issue = "130703")] +pub mod random; +#[unstable(feature = "new_range_api", issue = "125687")] +pub mod range; +pub mod result; +pub mod sync; + +pub mod fmt; +pub mod hash; +pub mod slice; +pub mod str; +pub mod time; + +pub mod unicode; + +/* Async */ +pub mod future; +pub mod task; + +/* Heap memory allocator trait */ +#[allow(missing_docs)] +pub mod alloc; + +// note: does not need to be public +mod bool; +mod escape; +mod tuple; +mod unit; + +#[stable(feature = "core_primitive", since = "1.43.0")] +pub mod primitive; + +// Pull in the `core_arch` crate directly into core. The contents of +// `core_arch` are in a different repository: rust-lang/stdarch. +// +// `core_arch` depends on core, but the contents of this module are +// set up in such a way that directly pulling it here works such that the +// crate uses the this crate as its core. +#[path = "../../stdarch/crates/core_arch/src/mod.rs"] +#[allow( + missing_docs, + missing_debug_implementations, + dead_code, + unused_imports, + unsafe_op_in_unsafe_fn, + ambiguous_glob_reexports, + deprecated_in_future +)] +#[allow(rustdoc::bare_urls)] +mod core_arch; + +#[stable(feature = "simd_arch", since = "1.27.0")] +pub mod arch; + +// Pull in the `core_simd` crate directly into core. The contents of +// `core_simd` are in a different repository: rust-lang/portable-simd. +// +// `core_simd` depends on core, but the contents of this module are +// set up in such a way that directly pulling it here works such that the +// crate uses this crate as its core. +#[path = "../../portable-simd/crates/core_simd/src/mod.rs"] +#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn)] +#[allow(rustdoc::bare_urls)] +#[unstable(feature = "portable_simd", issue = "86656")] +mod core_simd; + +#[unstable(feature = "portable_simd", issue = "86656")] +pub mod simd { + #![doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")] + + #[unstable(feature = "portable_simd", issue = "86656")] + pub use crate::core_simd::simd::*; +} + +include!("primitive_docs.rs"); diff --git a/CoqOfRust/core/macros/mod.rs b/CoqOfRust/core/macros/mod.rs new file mode 100644 index 000000000..ab674b589 --- /dev/null +++ b/CoqOfRust/core/macros/mod.rs @@ -0,0 +1,1799 @@ +#[doc = include_str!("panic.md")] +#[macro_export] +#[rustc_builtin_macro(core_panic)] +#[allow_internal_unstable(edition_panic)] +#[stable(feature = "core", since = "1.6.0")] +#[rustc_diagnostic_item = "core_panic_macro"] +macro_rules! panic { + // Expands to either `$crate::panic::panic_2015` or `$crate::panic::panic_2021` + // depending on the edition of the caller. + ($($arg:tt)*) => { + /* compiler built-in */ + }; +} + +/// Asserts that two expressions are equal to each other (using [`PartialEq`]). +/// +/// Assertions are always checked in both debug and release builds, and cannot +/// be disabled. See [`debug_assert_eq!`] for assertions that are disabled in +/// release builds by default. +/// +/// [`debug_assert_eq!`]: crate::debug_assert_eq +/// +/// On panic, this macro will print the values of the expressions with their +/// debug representations. +/// +/// Like [`assert!`], this macro has a second form, where a custom +/// panic message can be provided. +/// +/// # Examples +/// +/// ``` +/// let a = 3; +/// let b = 1 + 2; +/// assert_eq!(a, b); +/// +/// assert_eq!(a, b, "we are testing addition with {} and {}", a, b); +/// ``` +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "assert_eq_macro")] +#[allow_internal_unstable(panic_internals)] +macro_rules! assert_eq { + ($left:expr, $right:expr $(,)?) => { + match (&$left, &$right) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = $crate::panicking::AssertKind::Eq; + // The reborrows below are intentional. Without them, the stack slot for the + // borrow is initialized even before the values are compared, leading to a + // noticeable slow down. + $crate::panicking::assert_failed(kind, &*left_val, &*right_val, $crate::option::Option::None); + } + } + } + }; + ($left:expr, $right:expr, $($arg:tt)+) => { + match (&$left, &$right) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = $crate::panicking::AssertKind::Eq; + // The reborrows below are intentional. Without them, the stack slot for the + // borrow is initialized even before the values are compared, leading to a + // noticeable slow down. + $crate::panicking::assert_failed(kind, &*left_val, &*right_val, $crate::option::Option::Some($crate::format_args!($($arg)+))); + } + } + } + }; +} + +/// Asserts that two expressions are not equal to each other (using [`PartialEq`]). +/// +/// Assertions are always checked in both debug and release builds, and cannot +/// be disabled. See [`debug_assert_ne!`] for assertions that are disabled in +/// release builds by default. +/// +/// [`debug_assert_ne!`]: crate::debug_assert_ne +/// +/// On panic, this macro will print the values of the expressions with their +/// debug representations. +/// +/// Like [`assert!`], this macro has a second form, where a custom +/// panic message can be provided. +/// +/// # Examples +/// +/// ``` +/// let a = 3; +/// let b = 2; +/// assert_ne!(a, b); +/// +/// assert_ne!(a, b, "we are testing that the values are not equal"); +/// ``` +#[macro_export] +#[stable(feature = "assert_ne", since = "1.13.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "assert_ne_macro")] +#[allow_internal_unstable(panic_internals)] +macro_rules! assert_ne { + ($left:expr, $right:expr $(,)?) => { + match (&$left, &$right) { + (left_val, right_val) => { + if *left_val == *right_val { + let kind = $crate::panicking::AssertKind::Ne; + // The reborrows below are intentional. Without them, the stack slot for the + // borrow is initialized even before the values are compared, leading to a + // noticeable slow down. + $crate::panicking::assert_failed(kind, &*left_val, &*right_val, $crate::option::Option::None); + } + } + } + }; + ($left:expr, $right:expr, $($arg:tt)+) => { + match (&($left), &($right)) { + (left_val, right_val) => { + if *left_val == *right_val { + let kind = $crate::panicking::AssertKind::Ne; + // The reborrows below are intentional. Without them, the stack slot for the + // borrow is initialized even before the values are compared, leading to a + // noticeable slow down. + $crate::panicking::assert_failed(kind, &*left_val, &*right_val, $crate::option::Option::Some($crate::format_args!($($arg)+))); + } + } + } + }; +} + +/// Asserts that an expression matches the provided pattern. +/// +/// This macro is generally preferable to `assert!(matches!(value, pattern))`, because it can print +/// the debug representation of the actual value shape that did not meet expectations. In contrast, +/// using [`assert!`] will only print that expectations were not met, but not why. +/// +/// The pattern syntax is exactly the same as found in a match arm and the `matches!` macro. The +/// optional if guard can be used to add additional checks that must be true for the matched value, +/// otherwise this macro will panic. +/// +/// Assertions are always checked in both debug and release builds, and cannot +/// be disabled. See [`debug_assert_matches!`] for assertions that are disabled in +/// release builds by default. +/// +/// [`debug_assert_matches!`]: crate::assert_matches::debug_assert_matches +/// +/// On panic, this macro will print the value of the expression with its debug representation. +/// +/// Like [`assert!`], this macro has a second form, where a custom panic message can be provided. +/// +/// # Examples +/// +/// ``` +/// #![feature(assert_matches)] +/// +/// use std::assert_matches::assert_matches; +/// +/// let a = Some(345); +/// let b = Some(56); +/// assert_matches!(a, Some(_)); +/// assert_matches!(b, Some(_)); +/// +/// assert_matches!(a, Some(345)); +/// assert_matches!(a, Some(345) | None); +/// +/// // assert_matches!(a, None); // panics +/// // assert_matches!(b, Some(345)); // panics +/// // assert_matches!(b, Some(345) | None); // panics +/// +/// assert_matches!(a, Some(x) if x > 100); +/// // assert_matches!(a, Some(x) if x < 100); // panics +/// ``` +#[unstable(feature = "assert_matches", issue = "82775")] +#[allow_internal_unstable(panic_internals)] +#[rustc_macro_transparency = "semitransparent"] +pub macro assert_matches { + ($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => { + match $left { + $( $pattern )|+ $( if $guard )? => {} + ref left_val => { + $crate::panicking::assert_matches_failed( + left_val, + $crate::stringify!($($pattern)|+ $(if $guard)?), + $crate::option::Option::None + ); + } + } + }, + ($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )?, $($arg:tt)+) => { + match $left { + $( $pattern )|+ $( if $guard )? => {} + ref left_val => { + $crate::panicking::assert_matches_failed( + left_val, + $crate::stringify!($($pattern)|+ $(if $guard)?), + $crate::option::Option::Some($crate::format_args!($($arg)+)) + ); + } + } + }, +} + +/// A macro for defining `#[cfg]` match-like statements. +/// +/// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of +/// `#[cfg]` cases, emitting the implementation which matches first. +/// +/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code +/// without having to rewrite each clause multiple times. +/// +/// Trailing `_` wildcard match arms are **optional** and they indicate a fallback branch when +/// all previous declarations do not evaluate to true. +/// +/// # Example +/// +/// ``` +/// #![feature(cfg_match)] +/// +/// cfg_match! { +/// cfg(unix) => { +/// fn foo() { /* unix specific functionality */ } +/// } +/// cfg(target_pointer_width = "32") => { +/// fn foo() { /* non-unix, 32-bit functionality */ } +/// } +/// _ => { +/// fn foo() { /* fallback implementation */ } +/// } +/// } +/// ``` +#[unstable(feature = "cfg_match", issue = "115585")] +#[rustc_diagnostic_item = "cfg_match"] +pub macro cfg_match { + // with a final wildcard + ( + $(cfg($initial_meta:meta) => { $($initial_tokens:tt)* })+ + _ => { $($extra_tokens:tt)* } + ) => { + cfg_match! { + @__items (); + $((($initial_meta) ($($initial_tokens)*)),)+ + (() ($($extra_tokens)*)), + } + }, + + // without a final wildcard + ( + $(cfg($extra_meta:meta) => { $($extra_tokens:tt)* })* + ) => { + cfg_match! { + @__items (); + $((($extra_meta) ($($extra_tokens)*)),)* + } + }, + + // Internal and recursive macro to emit all the items + // + // Collects all the previous cfgs in a list at the beginning, so they can be + // negated. After the semicolon is all the remaining items. + (@__items ($($_:meta,)*);) => {}, + ( + @__items ($($no:meta,)*); + (($($yes:meta)?) ($($tokens:tt)*)), + $($rest:tt,)* + ) => { + // Emit all items within one block, applying an appropriate #[cfg]. The + // #[cfg] will require all `$yes` matchers specified and must also negate + // all previous matchers. + #[cfg(all( + $($yes,)? + not(any($($no),*)) + ))] + cfg_match! { @__identity $($tokens)* } + + // Recurse to emit all other items in `$rest`, and when we do so add all + // our `$yes` matchers to the list of `$no` matchers as future emissions + // will have to negate everything we just matched as well. + cfg_match! { + @__items ($($no,)* $($yes,)?); + $($rest,)* + } + }, + + // Internal macro to make __apply work out right for different match types, + // because of how macros match/expand stuff. + (@__identity $($tokens:tt)*) => { + $($tokens)* + } +} + +/// Asserts that a boolean expression is `true` at runtime. +/// +/// This will invoke the [`panic!`] macro if the provided expression cannot be +/// evaluated to `true` at runtime. +/// +/// Like [`assert!`], this macro also has a second version, where a custom panic +/// message can be provided. +/// +/// # Uses +/// +/// Unlike [`assert!`], `debug_assert!` statements are only enabled in non +/// optimized builds by default. An optimized build will not execute +/// `debug_assert!` statements unless `-C debug-assertions` is passed to the +/// compiler. This makes `debug_assert!` useful for checks that are too +/// expensive to be present in a release build but may be helpful during +/// development. The result of expanding `debug_assert!` is always type checked. +/// +/// An unchecked assertion allows a program in an inconsistent state to keep +/// running, which might have unexpected consequences but does not introduce +/// unsafety as long as this only happens in safe code. The performance cost +/// of assertions, however, is not measurable in general. Replacing [`assert!`] +/// with `debug_assert!` is thus only encouraged after thorough profiling, and +/// more importantly, only in safe code! +/// +/// # Examples +/// +/// ``` +/// // the panic message for these assertions is the stringified value of the +/// // expression given. +/// debug_assert!(true); +/// +/// fn some_expensive_computation() -> bool { true } // a very simple function +/// debug_assert!(some_expensive_computation()); +/// +/// // assert with a custom message +/// let x = true; +/// debug_assert!(x, "x wasn't true!"); +/// +/// let a = 3; let b = 27; +/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b); +/// ``` +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "debug_assert_macro"] +#[allow_internal_unstable(edition_panic)] +macro_rules! debug_assert { + ($($arg:tt)*) => { + if $crate::cfg!(debug_assertions) { + $crate::assert!($($arg)*); + } + }; +} + +/// Asserts that two expressions are equal to each other. +/// +/// On panic, this macro will print the values of the expressions with their +/// debug representations. +/// +/// Unlike [`assert_eq!`], `debug_assert_eq!` statements are only enabled in non +/// optimized builds by default. An optimized build will not execute +/// `debug_assert_eq!` statements unless `-C debug-assertions` is passed to the +/// compiler. This makes `debug_assert_eq!` useful for checks that are too +/// expensive to be present in a release build but may be helpful during +/// development. The result of expanding `debug_assert_eq!` is always type checked. +/// +/// # Examples +/// +/// ``` +/// let a = 3; +/// let b = 1 + 2; +/// debug_assert_eq!(a, b); +/// ``` +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "debug_assert_eq_macro")] +macro_rules! debug_assert_eq { + ($($arg:tt)*) => { + if $crate::cfg!(debug_assertions) { + $crate::assert_eq!($($arg)*); + } + }; +} + +/// Asserts that two expressions are not equal to each other. +/// +/// On panic, this macro will print the values of the expressions with their +/// debug representations. +/// +/// Unlike [`assert_ne!`], `debug_assert_ne!` statements are only enabled in non +/// optimized builds by default. An optimized build will not execute +/// `debug_assert_ne!` statements unless `-C debug-assertions` is passed to the +/// compiler. This makes `debug_assert_ne!` useful for checks that are too +/// expensive to be present in a release build but may be helpful during +/// development. The result of expanding `debug_assert_ne!` is always type checked. +/// +/// # Examples +/// +/// ``` +/// let a = 3; +/// let b = 2; +/// debug_assert_ne!(a, b); +/// ``` +#[macro_export] +#[stable(feature = "assert_ne", since = "1.13.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "debug_assert_ne_macro")] +macro_rules! debug_assert_ne { + ($($arg:tt)*) => { + if $crate::cfg!(debug_assertions) { + $crate::assert_ne!($($arg)*); + } + }; +} + +/// Asserts that an expression matches the provided pattern. +/// +/// This macro is generally preferable to `debug_assert!(matches!(value, pattern))`, because it can +/// print the debug representation of the actual value shape that did not meet expectations. In +/// contrast, using [`debug_assert!`] will only print that expectations were not met, but not why. +/// +/// The pattern syntax is exactly the same as found in a match arm and the `matches!` macro. The +/// optional if guard can be used to add additional checks that must be true for the matched value, +/// otherwise this macro will panic. +/// +/// On panic, this macro will print the value of the expression with its debug representation. +/// +/// Like [`assert!`], this macro has a second form, where a custom panic message can be provided. +/// +/// Unlike [`assert_matches!`], `debug_assert_matches!` statements are only enabled in non optimized +/// builds by default. An optimized build will not execute `debug_assert_matches!` statements unless +/// `-C debug-assertions` is passed to the compiler. This makes `debug_assert_matches!` useful for +/// checks that are too expensive to be present in a release build but may be helpful during +/// development. The result of expanding `debug_assert_matches!` is always type checked. +/// +/// # Examples +/// +/// ``` +/// #![feature(assert_matches)] +/// +/// use std::assert_matches::debug_assert_matches; +/// +/// let a = Some(345); +/// let b = Some(56); +/// debug_assert_matches!(a, Some(_)); +/// debug_assert_matches!(b, Some(_)); +/// +/// debug_assert_matches!(a, Some(345)); +/// debug_assert_matches!(a, Some(345) | None); +/// +/// // debug_assert_matches!(a, None); // panics +/// // debug_assert_matches!(b, Some(345)); // panics +/// // debug_assert_matches!(b, Some(345) | None); // panics +/// +/// debug_assert_matches!(a, Some(x) if x > 100); +/// // debug_assert_matches!(a, Some(x) if x < 100); // panics +/// ``` +#[unstable(feature = "assert_matches", issue = "82775")] +#[allow_internal_unstable(assert_matches)] +#[rustc_macro_transparency = "semitransparent"] +pub macro debug_assert_matches($($arg:tt)*) { + if $crate::cfg!(debug_assertions) { + $crate::assert_matches::assert_matches!($($arg)*); + } +} + +/// Returns whether the given expression matches the provided pattern. +/// +/// The pattern syntax is exactly the same as found in a match arm. The optional if guard can be +/// used to add additional checks that must be true for the matched value, otherwise this macro will +/// return `false`. +/// +/// When testing that a value matches a pattern, it's generally preferable to use +/// [`assert_matches!`] as it will print the debug representation of the value if the assertion +/// fails. +/// +/// # Examples +/// +/// ``` +/// let foo = 'f'; +/// assert!(matches!(foo, 'A'..='Z' | 'a'..='z')); +/// +/// let bar = Some(4); +/// assert!(matches!(bar, Some(x) if x > 2)); +/// ``` +#[macro_export] +#[stable(feature = "matches_macro", since = "1.42.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "matches_macro")] +macro_rules! matches { + ($expression:expr, $pattern:pat $(if $guard:expr)? $(,)?) => { + match $expression { + $pattern $(if $guard)? => true, + _ => false + } + }; +} + +/// Unwraps a result or propagates its error. +/// +/// The [`?` operator][propagating-errors] was added to replace `try!` +/// and should be used instead. Furthermore, `try` is a reserved word +/// in Rust 2018, so if you must use it, you will need to use the +/// [raw-identifier syntax][ris]: `r#try`. +/// +/// [propagating-errors]: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator +/// [ris]: https://doc.rust-lang.org/nightly/rust-by-example/compatibility/raw_identifiers.html +/// +/// `try!` matches the given [`Result`]. In case of the `Ok` variant, the +/// expression has the value of the wrapped value. +/// +/// In case of the `Err` variant, it retrieves the inner error. `try!` then +/// performs conversion using `From`. This provides automatic conversion +/// between specialized errors and more general ones. The resulting +/// error is then immediately returned. +/// +/// Because of the early return, `try!` can only be used in functions that +/// return [`Result`]. +/// +/// # Examples +/// +/// ``` +/// use std::io; +/// use std::fs::File; +/// use std::io::prelude::*; +/// +/// enum MyError { +/// FileWriteError +/// } +/// +/// impl From for MyError { +/// fn from(e: io::Error) -> MyError { +/// MyError::FileWriteError +/// } +/// } +/// +/// // The preferred method of quick returning Errors +/// fn write_to_file_question() -> Result<(), MyError> { +/// let mut file = File::create("my_best_friends.txt")?; +/// file.write_all(b"This is a list of my best friends.")?; +/// Ok(()) +/// } +/// +/// // The previous method of quick returning Errors +/// fn write_to_file_using_try() -> Result<(), MyError> { +/// let mut file = r#try!(File::create("my_best_friends.txt")); +/// r#try!(file.write_all(b"This is a list of my best friends.")); +/// Ok(()) +/// } +/// +/// // This is equivalent to: +/// fn write_to_file_using_match() -> Result<(), MyError> { +/// let mut file = r#try!(File::create("my_best_friends.txt")); +/// match file.write_all(b"This is a list of my best friends.") { +/// Ok(v) => v, +/// Err(e) => return Err(From::from(e)), +/// } +/// Ok(()) +/// } +/// ``` +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.39.0", note = "use the `?` operator instead")] +#[doc(alias = "?")] +macro_rules! r#try { + ($expr:expr $(,)?) => { + match $expr { + $crate::result::Result::Ok(val) => val, + $crate::result::Result::Err(err) => { + return $crate::result::Result::Err($crate::convert::From::from(err)); + } + } + }; +} + +/// Writes formatted data into a buffer. +/// +/// This macro accepts a 'writer', a format string, and a list of arguments. Arguments will be +/// formatted according to the specified format string and the result will be passed to the writer. +/// The writer may be any value with a `write_fmt` method; generally this comes from an +/// implementation of either the [`fmt::Write`] or the [`io::Write`] trait. The macro +/// returns whatever the `write_fmt` method returns; commonly a [`fmt::Result`], or an +/// [`io::Result`]. +/// +/// See [`std::fmt`] for more information on the format string syntax. +/// +/// [`std::fmt`]: ../std/fmt/index.html +/// [`fmt::Write`]: crate::fmt::Write +/// [`io::Write`]: ../std/io/trait.Write.html +/// [`fmt::Result`]: crate::fmt::Result +/// [`io::Result`]: ../std/io/type.Result.html +/// +/// # Examples +/// +/// ``` +/// use std::io::Write; +/// +/// fn main() -> std::io::Result<()> { +/// let mut w = Vec::new(); +/// write!(&mut w, "test")?; +/// write!(&mut w, "formatted {}", "arguments")?; +/// +/// assert_eq!(w, b"testformatted arguments"); +/// Ok(()) +/// } +/// ``` +/// +/// A module can import both `std::fmt::Write` and `std::io::Write` and call `write!` on objects +/// implementing either, as objects do not typically implement both. However, the module must +/// avoid conflict between the trait names, such as by importing them as `_` or otherwise renaming +/// them: +/// +/// ``` +/// use std::fmt::Write as _; +/// use std::io::Write as _; +/// +/// fn main() -> Result<(), Box> { +/// let mut s = String::new(); +/// let mut v = Vec::new(); +/// +/// write!(&mut s, "{} {}", "abc", 123)?; // uses fmt::Write::write_fmt +/// write!(&mut v, "s = {:?}", s)?; // uses io::Write::write_fmt +/// assert_eq!(v, b"s = \"abc 123\""); +/// Ok(()) +/// } +/// ``` +/// +/// If you also need the trait names themselves, such as to implement one or both on your types, +/// import the containing module and then name them with a prefix: +/// +/// ``` +/// # #![allow(unused_imports)] +/// use std::fmt::{self, Write as _}; +/// use std::io::{self, Write as _}; +/// +/// struct Example; +/// +/// impl fmt::Write for Example { +/// fn write_str(&mut self, _s: &str) -> core::fmt::Result { +/// unimplemented!(); +/// } +/// } +/// ``` +/// +/// Note: This macro can be used in `no_std` setups as well. +/// In a `no_std` setup you are responsible for the implementation details of the components. +/// +/// ```no_run +/// use core::fmt::Write; +/// +/// struct Example; +/// +/// impl Write for Example { +/// fn write_str(&mut self, _s: &str) -> core::fmt::Result { +/// unimplemented!(); +/// } +/// } +/// +/// let mut m = Example{}; +/// write!(&mut m, "Hello World").expect("Not written"); +/// ``` +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "write_macro")] +macro_rules! write { + ($dst:expr, $($arg:tt)*) => { + $dst.write_fmt($crate::format_args!($($arg)*)) + }; +} + +/// Writes formatted data into a buffer, with a newline appended. +/// +/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone +/// (no additional CARRIAGE RETURN (`\r`/`U+000D`). +/// +/// For more information, see [`write!`]. For information on the format string syntax, see +/// [`std::fmt`]. +/// +/// [`std::fmt`]: ../std/fmt/index.html +/// +/// # Examples +/// +/// ``` +/// use std::io::{Write, Result}; +/// +/// fn main() -> Result<()> { +/// let mut w = Vec::new(); +/// writeln!(&mut w)?; +/// writeln!(&mut w, "test")?; +/// writeln!(&mut w, "formatted {}", "arguments")?; +/// +/// assert_eq!(&w[..], "\ntest\nformatted arguments\n".as_bytes()); +/// Ok(()) +/// } +/// ``` +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "writeln_macro")] +#[allow_internal_unstable(format_args_nl)] +macro_rules! writeln { + ($dst:expr $(,)?) => { + $crate::write!($dst, "\n") + }; + ($dst:expr, $($arg:tt)*) => { + $dst.write_fmt($crate::format_args_nl!($($arg)*)) + }; +} + +/// Indicates unreachable code. +/// +/// This is useful any time that the compiler can't determine that some code is unreachable. For +/// example: +/// +/// * Match arms with guard conditions. +/// * Loops that dynamically terminate. +/// * Iterators that dynamically terminate. +/// +/// If the determination that the code is unreachable proves incorrect, the +/// program immediately terminates with a [`panic!`]. +/// +/// The unsafe counterpart of this macro is the [`unreachable_unchecked`] function, which +/// will cause undefined behavior if the code is reached. +/// +/// [`unreachable_unchecked`]: crate::hint::unreachable_unchecked +/// +/// # Panics +/// +/// This will always [`panic!`] because `unreachable!` is just a shorthand for `panic!` with a +/// fixed, specific message. +/// +/// Like `panic!`, this macro has a second form for displaying custom values. +/// +/// # Examples +/// +/// Match arms: +/// +/// ``` +/// # #[allow(dead_code)] +/// fn foo(x: Option) { +/// match x { +/// Some(n) if n >= 0 => println!("Some(Non-negative)"), +/// Some(n) if n < 0 => println!("Some(Negative)"), +/// Some(_) => unreachable!(), // compile error if commented out +/// None => println!("None") +/// } +/// } +/// ``` +/// +/// Iterators: +/// +/// ``` +/// # #[allow(dead_code)] +/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3 +/// for i in 0.. { +/// if 3*i < i { panic!("u32 overflow"); } +/// if x < 3*i { return i-1; } +/// } +/// unreachable!("The loop should always return"); +/// } +/// ``` +#[macro_export] +#[rustc_builtin_macro(unreachable)] +#[allow_internal_unstable(edition_panic)] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "unreachable_macro")] +macro_rules! unreachable { + // Expands to either `$crate::panic::unreachable_2015` or `$crate::panic::unreachable_2021` + // depending on the edition of the caller. + ($($arg:tt)*) => { + /* compiler built-in */ + }; +} + +/// Indicates unimplemented code by panicking with a message of "not implemented". +/// +/// This allows your code to type-check, which is useful if you are prototyping or +/// implementing a trait that requires multiple methods which you don't plan to use all of. +/// +/// The difference between `unimplemented!` and [`todo!`] is that while `todo!` +/// conveys an intent of implementing the functionality later and the message is "not yet +/// implemented", `unimplemented!` makes no such claims. Its message is "not implemented". +/// +/// Also, some IDEs will mark `todo!`s. +/// +/// # Panics +/// +/// This will always [`panic!`] because `unimplemented!` is just a shorthand for `panic!` with a +/// fixed, specific message. +/// +/// Like `panic!`, this macro has a second form for displaying custom values. +/// +/// [`todo!`]: crate::todo +/// +/// # Examples +/// +/// Say we have a trait `Foo`: +/// +/// ``` +/// trait Foo { +/// fn bar(&self) -> u8; +/// fn baz(&self); +/// fn qux(&self) -> Result; +/// } +/// ``` +/// +/// We want to implement `Foo` for 'MyStruct', but for some reason it only makes sense +/// to implement the `bar()` function. `baz()` and `qux()` will still need to be defined +/// in our implementation of `Foo`, but we can use `unimplemented!` in their definitions +/// to allow our code to compile. +/// +/// We still want to have our program stop running if the unimplemented methods are +/// reached. +/// +/// ``` +/// # trait Foo { +/// # fn bar(&self) -> u8; +/// # fn baz(&self); +/// # fn qux(&self) -> Result; +/// # } +/// struct MyStruct; +/// +/// impl Foo for MyStruct { +/// fn bar(&self) -> u8 { +/// 1 + 1 +/// } +/// +/// fn baz(&self) { +/// // It makes no sense to `baz` a `MyStruct`, so we have no logic here +/// // at all. +/// // This will display "thread 'main' panicked at 'not implemented'". +/// unimplemented!(); +/// } +/// +/// fn qux(&self) -> Result { +/// // We have some logic here, +/// // We can add a message to unimplemented! to display our omission. +/// // This will display: +/// // "thread 'main' panicked at 'not implemented: MyStruct isn't quxable'". +/// unimplemented!("MyStruct isn't quxable"); +/// } +/// } +/// +/// fn main() { +/// let s = MyStruct; +/// s.bar(); +/// } +/// ``` +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "unimplemented_macro")] +#[allow_internal_unstable(panic_internals)] +macro_rules! unimplemented { + () => { + $crate::panicking::panic("not implemented") + }; + ($($arg:tt)+) => { + $crate::panic!("not implemented: {}", $crate::format_args!($($arg)+)) + }; +} + +/// Indicates unfinished code. +/// +/// This can be useful if you are prototyping and just +/// want a placeholder to let your code pass type analysis. +/// +/// The difference between [`unimplemented!`] and `todo!` is that while `todo!` conveys +/// an intent of implementing the functionality later and the message is "not yet +/// implemented", `unimplemented!` makes no such claims. Its message is "not implemented". +/// +/// Also, some IDEs will mark `todo!`s. +/// +/// # Panics +/// +/// This will always [`panic!`] because `todo!` is just a shorthand for `panic!` with a +/// fixed, specific message. +/// +/// Like `panic!`, this macro has a second form for displaying custom values. +/// +/// # Examples +/// +/// Here's an example of some in-progress code. We have a trait `Foo`: +/// +/// ``` +/// trait Foo { +/// fn bar(&self) -> u8; +/// fn baz(&self); +/// fn qux(&self) -> Result; +/// } +/// ``` +/// +/// We want to implement `Foo` on one of our types, but we also want to work on +/// just `bar()` first. In order for our code to compile, we need to implement +/// `baz()` and `qux()`, so we can use `todo!`: +/// +/// ``` +/// # trait Foo { +/// # fn bar(&self) -> u8; +/// # fn baz(&self); +/// # fn qux(&self) -> Result; +/// # } +/// struct MyStruct; +/// +/// impl Foo for MyStruct { +/// fn bar(&self) -> u8 { +/// 1 + 1 +/// } +/// +/// fn baz(&self) { +/// // Let's not worry about implementing baz() for now +/// todo!(); +/// } +/// +/// fn qux(&self) -> Result { +/// // We can add a message to todo! to display our omission. +/// // This will display: +/// // "thread 'main' panicked at 'not yet implemented: MyStruct is not yet quxable'". +/// todo!("MyStruct is not yet quxable"); +/// } +/// } +/// +/// fn main() { +/// let s = MyStruct; +/// s.bar(); +/// +/// // We aren't even using baz() or qux(), so this is fine. +/// } +/// ``` +#[macro_export] +#[stable(feature = "todo_macro", since = "1.40.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "todo_macro")] +#[allow_internal_unstable(panic_internals)] +macro_rules! todo { + () => { + $crate::panicking::panic("not yet implemented") + }; + ($($arg:tt)+) => { + $crate::panic!("not yet implemented: {}", $crate::format_args!($($arg)+)) + }; +} + +/// Definitions of built-in macros. +/// +/// Most of the macro properties (stability, visibility, etc.) are taken from the source code here, +/// with exception of expansion functions transforming macro inputs into outputs, +/// those functions are provided by the compiler. +pub(crate) mod builtin { + + /// Causes compilation to fail with the given error message when encountered. + /// + /// This macro should be used when a crate uses a conditional compilation strategy to provide + /// better error messages for erroneous conditions. It's the compiler-level form of [`panic!`], + /// but emits an error during *compilation* rather than at *runtime*. + /// + /// # Examples + /// + /// Two such examples are macros and `#[cfg]` environments. + /// + /// Emit a better compiler error if a macro is passed invalid values. Without the final branch, + /// the compiler would still emit an error, but the error's message would not mention the two + /// valid values. + /// + /// ```compile_fail + /// macro_rules! give_me_foo_or_bar { + /// (foo) => {}; + /// (bar) => {}; + /// ($x:ident) => { + /// compile_error!("This macro only accepts `foo` or `bar`"); + /// } + /// } + /// + /// give_me_foo_or_bar!(neither); + /// // ^ will fail at compile time with message "This macro only accepts `foo` or `bar`" + /// ``` + /// + /// Emit a compiler error if one of a number of features isn't available. + /// + /// ```compile_fail + /// #[cfg(not(any(feature = "foo", feature = "bar")))] + /// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate."); + /// ``` + #[stable(feature = "compile_error_macro", since = "1.20.0")] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! compile_error { + ($msg:expr $(,)?) => {{ /* compiler built-in */ }}; + } + + /// Constructs parameters for the other string-formatting macros. + /// + /// This macro functions by taking a formatting string literal containing + /// `{}` for each additional argument passed. `format_args!` prepares the + /// additional parameters to ensure the output can be interpreted as a string + /// and canonicalizes the arguments into a single type. Any value that implements + /// the [`Display`] trait can be passed to `format_args!`, as can any + /// [`Debug`] implementation be passed to a `{:?}` within the formatting string. + /// + /// This macro produces a value of type [`fmt::Arguments`]. This value can be + /// passed to the macros within [`std::fmt`] for performing useful redirection. + /// All other formatting macros ([`format!`], [`write!`], [`println!`], etc) are + /// proxied through this one. `format_args!`, unlike its derived macros, avoids + /// heap allocations. + /// + /// You can use the [`fmt::Arguments`] value that `format_args!` returns + /// in `Debug` and `Display` contexts as seen below. The example also shows + /// that `Debug` and `Display` format to the same thing: the interpolated + /// format string in `format_args!`. + /// + /// ```rust + /// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); + /// let display = format!("{}", format_args!("{} foo {:?}", 1, 2)); + /// assert_eq!("1 foo 2", display); + /// assert_eq!(display, debug); + /// ``` + /// + /// See [the formatting documentation in `std::fmt`](../std/fmt/index.html) + /// for details of the macro argument syntax, and further information. + /// + /// [`Display`]: crate::fmt::Display + /// [`Debug`]: crate::fmt::Debug + /// [`fmt::Arguments`]: crate::fmt::Arguments + /// [`std::fmt`]: ../std/fmt/index.html + /// [`format!`]: ../std/macro.format.html + /// [`println!`]: ../std/macro.println.html + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// let s = fmt::format(format_args!("hello {}", "world")); + /// assert_eq!(s, format!("hello {}", "world")); + /// ``` + /// + /// # Lifetime limitation + /// + /// Except when no formatting arguments are used, + /// the produced `fmt::Arguments` value borrows temporary values, + /// which means it can only be used within the same expression + /// and cannot be stored for later use. + /// This is a known limitation, see [#92698](https://github.com/rust-lang/rust/issues/92698). + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "format_args_macro")] + #[allow_internal_unsafe] + #[allow_internal_unstable(fmt_internals)] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! format_args { + ($fmt:expr) => {{ /* compiler built-in */ }}; + ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }}; + } + + /// Same as [`format_args`], but can be used in some const contexts. + /// + /// This macro is used by the panic macros for the `const_panic` feature. + /// + /// This macro will be removed once `format_args` is allowed in const contexts. + #[unstable(feature = "const_format_args", issue = "none")] + #[allow_internal_unstable(fmt_internals, const_fmt_arguments_new)] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! const_format_args { + ($fmt:expr) => {{ /* compiler built-in */ }}; + ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }}; + } + + /// Same as [`format_args`], but adds a newline in the end. + #[unstable( + feature = "format_args_nl", + issue = "none", + reason = "`format_args_nl` is only for internal \ + language use and is subject to change" + )] + #[allow_internal_unstable(fmt_internals)] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! format_args_nl { + ($fmt:expr) => {{ /* compiler built-in */ }}; + ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }}; + } + + /// Inspects an environment variable at compile time. + /// + /// This macro will expand to the value of the named environment variable at + /// compile time, yielding an expression of type `&'static str`. Use + /// [`std::env::var`] instead if you want to read the value at runtime. + /// + /// [`std::env::var`]: ../std/env/fn.var.html + /// + /// If the environment variable is not defined, then a compilation error + /// will be emitted. To not emit a compile error, use the [`option_env!`] + /// macro instead. A compilation error will also be emitted if the + /// environment variable is not a valid Unicode string. + /// + /// # Examples + /// + /// ``` + /// let path: &'static str = env!("PATH"); + /// println!("the $PATH variable at the time of compiling was: {path}"); + /// ``` + /// + /// You can customize the error message by passing a string as the second + /// parameter: + /// + /// ```compile_fail + /// let doc: &'static str = env!("documentation", "what's that?!"); + /// ``` + /// + /// If the `documentation` environment variable is not defined, you'll get + /// the following error: + /// + /// ```text + /// error: what's that?! + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + #[macro_export] + #[rustc_diagnostic_item = "env_macro"] // useful for external lints + macro_rules! env { + ($name:expr $(,)?) => {{ /* compiler built-in */ }}; + ($name:expr, $error_msg:expr $(,)?) => {{ /* compiler built-in */ }}; + } + + /// Optionally inspects an environment variable at compile time. + /// + /// If the named environment variable is present at compile time, this will + /// expand into an expression of type `Option<&'static str>` whose value is + /// `Some` of the value of the environment variable (a compilation error + /// will be emitted if the environment variable is not a valid Unicode + /// string). If the environment variable is not present, then this will + /// expand to `None`. See [`Option`][Option] for more information on this + /// type. Use [`std::env::var`] instead if you want to read the value at + /// runtime. + /// + /// [`std::env::var`]: ../std/env/fn.var.html + /// + /// A compile time error is only emitted when using this macro if the + /// environment variable exists and is not a valid Unicode string. To also + /// emit a compile error if the environment variable is not present, use the + /// [`env!`] macro instead. + /// + /// # Examples + /// + /// ``` + /// let key: Option<&'static str> = option_env!("SECRET_KEY"); + /// println!("the secret key might be: {key:?}"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + #[macro_export] + #[rustc_diagnostic_item = "option_env_macro"] // useful for external lints + macro_rules! option_env { + ($name:expr $(,)?) => {{ /* compiler built-in */ }}; + } + + /// Concatenates identifiers into one identifier. + /// + /// This macro takes any number of comma-separated identifiers, and + /// concatenates them all into one, yielding an expression which is a new + /// identifier. Note that hygiene makes it such that this macro cannot + /// capture local variables. Also, as a general rule, macros are only + /// allowed in item, statement or expression position. That means while + /// you may use this macro for referring to existing variables, functions or + /// modules etc, you cannot define a new one with it. + /// + /// # Examples + /// + /// ``` + /// #![feature(concat_idents)] + /// + /// # fn main() { + /// fn foobar() -> u32 { 23 } + /// + /// let f = concat_idents!(foo, bar); + /// println!("{}", f()); + /// + /// // fn concat_idents!(new, fun, name) { } // not usable in this way! + /// # } + /// ``` + #[unstable( + feature = "concat_idents", + issue = "29599", + reason = "`concat_idents` is not stable enough for use and is subject to change" + )] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! concat_idents { + ($($e:ident),+ $(,)?) => {{ /* compiler built-in */ }}; + } + + /// Concatenates literals into a byte slice. + /// + /// This macro takes any number of comma-separated literals, and concatenates them all into + /// one, yielding an expression of type `&[u8; _]`, which represents all of the literals + /// concatenated left-to-right. The literals passed can be any combination of: + /// + /// - byte literals (`b'r'`) + /// - byte strings (`b"Rust"`) + /// - arrays of bytes/numbers (`[b'A', 66, b'C']`) + /// + /// # Examples + /// + /// ``` + /// #![feature(concat_bytes)] + /// + /// # fn main() { + /// let s: &[u8; 6] = concat_bytes!(b'A', b"BC", [68, b'E', 70]); + /// assert_eq!(s, b"ABCDEF"); + /// # } + /// ``` + #[unstable(feature = "concat_bytes", issue = "87555")] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! concat_bytes { + ($($e:literal),+ $(,)?) => {{ /* compiler built-in */ }}; + } + + /// Concatenates literals into a static string slice. + /// + /// This macro takes any number of comma-separated literals, yielding an + /// expression of type `&'static str` which represents all of the literals + /// concatenated left-to-right. + /// + /// Integer and floating point literals are [stringified](core::stringify) in order to be + /// concatenated. + /// + /// # Examples + /// + /// ``` + /// let s = concat!("test", 10, 'b', true); + /// assert_eq!(s, "test10btrue"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! concat { + ($($e:expr),* $(,)?) => {{ /* compiler built-in */ }}; + } + + /// Expands to the line number on which it was invoked. + /// + /// With [`column!`] and [`file!`], these macros provide debugging information for + /// developers about the location within the source. + /// + /// The expanded expression has type `u32` and is 1-based, so the first line + /// in each file evaluates to 1, the second to 2, etc. This is consistent + /// with error messages by common compilers or popular editors. + /// The returned line is *not necessarily* the line of the `line!` invocation itself, + /// but rather the first macro invocation leading up to the invocation + /// of the `line!` macro. + /// + /// # Examples + /// + /// ``` + /// let current_line = line!(); + /// println!("defined on line: {current_line}"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! line { + () => { + /* compiler built-in */ + }; + } + + /// Expands to the column number at which it was invoked. + /// + /// With [`line!`] and [`file!`], these macros provide debugging information for + /// developers about the location within the source. + /// + /// The expanded expression has type `u32` and is 1-based, so the first column + /// in each line evaluates to 1, the second to 2, etc. This is consistent + /// with error messages by common compilers or popular editors. + /// The returned column is *not necessarily* the line of the `column!` invocation itself, + /// but rather the first macro invocation leading up to the invocation + /// of the `column!` macro. + /// + /// # Examples + /// + /// ``` + /// let current_col = column!(); + /// println!("defined on column: {current_col}"); + /// ``` + /// + /// `column!` counts Unicode code points, not bytes or graphemes. As a result, the first two + /// invocations return the same value, but the third does not. + /// + /// ``` + /// let a = ("foobar", column!()).1; + /// let b = ("人之初性本善", column!()).1; + /// let c = ("f̅o̅o̅b̅a̅r̅", column!()).1; // Uses combining overline (U+0305) + /// + /// assert_eq!(a, b); + /// assert_ne!(b, c); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! column { + () => { + /* compiler built-in */ + }; + } + + /// Expands to the file name in which it was invoked. + /// + /// With [`line!`] and [`column!`], these macros provide debugging information for + /// developers about the location within the source. + /// + /// The expanded expression has type `&'static str`, and the returned file + /// is not the invocation of the `file!` macro itself, but rather the + /// first macro invocation leading up to the invocation of the `file!` + /// macro. + /// + /// # Examples + /// + /// ``` + /// let this_file = file!(); + /// println!("defined in file: {this_file}"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! file { + () => { + /* compiler built-in */ + }; + } + + /// Stringifies its arguments. + /// + /// This macro will yield an expression of type `&'static str` which is the + /// stringification of all the tokens passed to the macro. No restrictions + /// are placed on the syntax of the macro invocation itself. + /// + /// Note that the expanded results of the input tokens may change in the + /// future. You should be careful if you rely on the output. + /// + /// # Examples + /// + /// ``` + /// let one_plus_one = stringify!(1 + 1); + /// assert_eq!(one_plus_one, "1 + 1"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! stringify { + ($($t:tt)*) => { + /* compiler built-in */ + }; + } + + /// Includes a UTF-8 encoded file as a string. + /// + /// The file is located relative to the current file (similarly to how + /// modules are found). The provided path is interpreted in a platform-specific + /// way at compile time. So, for instance, an invocation with a Windows path + /// containing backslashes `\` would not compile correctly on Unix. + /// + /// This macro will yield an expression of type `&'static str` which is the + /// contents of the file. + /// + /// # Examples + /// + /// Assume there are two files in the same directory with the following + /// contents: + /// + /// File 'spanish.in': + /// + /// ```text + /// adiós + /// ``` + /// + /// File 'main.rs': + /// + /// ```ignore (cannot-doctest-external-file-dependency) + /// fn main() { + /// let my_str = include_str!("spanish.in"); + /// assert_eq!(my_str, "adiós\n"); + /// print!("{my_str}"); + /// } + /// ``` + /// + /// Compiling 'main.rs' and running the resulting binary will print "adiós". + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + #[macro_export] + #[cfg_attr(not(test), rustc_diagnostic_item = "include_str_macro")] + macro_rules! include_str { + ($file:expr $(,)?) => {{ /* compiler built-in */ }}; + } + + /// Includes a file as a reference to a byte array. + /// + /// The file is located relative to the current file (similarly to how + /// modules are found). The provided path is interpreted in a platform-specific + /// way at compile time. So, for instance, an invocation with a Windows path + /// containing backslashes `\` would not compile correctly on Unix. + /// + /// This macro will yield an expression of type `&'static [u8; N]` which is + /// the contents of the file. + /// + /// # Examples + /// + /// Assume there are two files in the same directory with the following + /// contents: + /// + /// File 'spanish.in': + /// + /// ```text + /// adiós + /// ``` + /// + /// File 'main.rs': + /// + /// ```ignore (cannot-doctest-external-file-dependency) + /// fn main() { + /// let bytes = include_bytes!("spanish.in"); + /// assert_eq!(bytes, b"adi\xc3\xb3s\n"); + /// print!("{}", String::from_utf8_lossy(bytes)); + /// } + /// ``` + /// + /// Compiling 'main.rs' and running the resulting binary will print "adiós". + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + #[macro_export] + #[cfg_attr(not(test), rustc_diagnostic_item = "include_bytes_macro")] + macro_rules! include_bytes { + ($file:expr $(,)?) => {{ /* compiler built-in */ }}; + } + + /// Expands to a string that represents the current module path. + /// + /// The current module path can be thought of as the hierarchy of modules + /// leading back up to the crate root. The first component of the path + /// returned is the name of the crate currently being compiled. + /// + /// # Examples + /// + /// ``` + /// mod test { + /// pub fn foo() { + /// assert!(module_path!().ends_with("test")); + /// } + /// } + /// + /// test::foo(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! module_path { + () => { + /* compiler built-in */ + }; + } + + /// Evaluates boolean combinations of configuration flags at compile-time. + /// + /// In addition to the `#[cfg]` attribute, this macro is provided to allow + /// boolean expression evaluation of configuration flags. This frequently + /// leads to less duplicated code. + /// + /// The syntax given to this macro is the same syntax as the [`cfg`] + /// attribute. + /// + /// `cfg!`, unlike `#[cfg]`, does not remove any code and only evaluates to true or false. For + /// example, all blocks in an if/else expression need to be valid when `cfg!` is used for + /// the condition, regardless of what `cfg!` is evaluating. + /// + /// [`cfg`]: ../reference/conditional-compilation.html#the-cfg-attribute + /// + /// # Examples + /// + /// ``` + /// let my_directory = if cfg!(windows) { + /// "windows-specific-directory" + /// } else { + /// "unix-directory" + /// }; + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! cfg { + ($($cfg:tt)*) => { + /* compiler built-in */ + }; + } + + /// Parses a file as an expression or an item according to the context. + /// + /// **Warning**: For multi-file Rust projects, the `include!` macro is probably not what you + /// are looking for. Usually, multi-file Rust projects use + /// [modules](https://doc.rust-lang.org/reference/items/modules.html). Multi-file projects and + /// modules are explained in the Rust-by-Example book + /// [here](https://doc.rust-lang.org/rust-by-example/mod/split.html) and the module system is + /// explained in the Rust Book + /// [here](https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html). + /// + /// The included file is placed in the surrounding code + /// [unhygienically](https://doc.rust-lang.org/reference/macros-by-example.html#hygiene). If + /// the included file is parsed as an expression and variables or functions share names across + /// both files, it could result in variables or functions being different from what the + /// included file expected. + /// + /// The included file is located relative to the current file (similarly to how modules are + /// found). The provided path is interpreted in a platform-specific way at compile time. So, + /// for instance, an invocation with a Windows path containing backslashes `\` would not + /// compile correctly on Unix. + /// + /// # Uses + /// + /// The `include!` macro is primarily used for two purposes. It is used to include + /// documentation that is written in a separate file and it is used to include [build artifacts + /// usually as a result from the `build.rs` + /// script](https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script). + /// + /// When using the `include` macro to include stretches of documentation, remember that the + /// included file still needs to be a valid Rust syntax. It is also possible to + /// use the [`include_str`] macro as `#![doc = include_str!("...")]` (at the module level) or + /// `#[doc = include_str!("...")]` (at the item level) to include documentation from a plain + /// text or markdown file. + /// + /// # Examples + /// + /// Assume there are two files in the same directory with the following contents: + /// + /// File 'monkeys.in': + /// + /// ```ignore (only-for-syntax-highlight) + /// ['🙈', '🙊', '🙉'] + /// .iter() + /// .cycle() + /// .take(6) + /// .collect::() + /// ``` + /// + /// File 'main.rs': + /// + /// ```ignore (cannot-doctest-external-file-dependency) + /// fn main() { + /// let my_string = include!("monkeys.in"); + /// assert_eq!("🙈🙊🙉🙈🙊🙉", my_string); + /// println!("{my_string}"); + /// } + /// ``` + /// + /// Compiling 'main.rs' and running the resulting binary will print + /// "🙈🙊🙉🙈🙊🙉". + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + #[macro_export] + #[rustc_diagnostic_item = "include_macro"] // useful for external lints + macro_rules! include { + ($file:expr $(,)?) => {{ /* compiler built-in */ }}; + } + + /// Automatic Differentiation macro which allows generating a new function to compute + /// the derivative of a given function. It may only be applied to a function. + /// The expected usage syntax is + /// `#[autodiff(NAME, MODE, INPUT_ACTIVITIES, OUTPUT_ACTIVITY)]` + /// where: + /// NAME is a string that represents a valid function name. + /// MODE is any of Forward, Reverse, ForwardFirst, ReverseFirst. + /// INPUT_ACTIVITIES consists of one valid activity for each input parameter. + /// OUTPUT_ACTIVITY must not be set if we implicitely return nothing (or explicitely return + /// `-> ()`). Otherwise it must be set to one of the allowed activities. + #[unstable(feature = "autodiff", issue = "124509")] + #[allow_internal_unstable(rustc_attrs)] + #[rustc_builtin_macro] + pub macro autodiff($item:item) { + /* compiler built-in */ + } + + /// Asserts that a boolean expression is `true` at runtime. + /// + /// This will invoke the [`panic!`] macro if the provided expression cannot be + /// evaluated to `true` at runtime. + /// + /// # Uses + /// + /// Assertions are always checked in both debug and release builds, and cannot + /// be disabled. See [`debug_assert!`] for assertions that are not enabled in + /// release builds by default. + /// + /// Unsafe code may rely on `assert!` to enforce run-time invariants that, if + /// violated could lead to unsafety. + /// + /// Other use-cases of `assert!` include testing and enforcing run-time + /// invariants in safe code (whose violation cannot result in unsafety). + /// + /// # Custom Messages + /// + /// This macro has a second form, where a custom panic message can + /// be provided with or without arguments for formatting. See [`std::fmt`] + /// for syntax for this form. Expressions used as format arguments will only + /// be evaluated if the assertion fails. + /// + /// [`std::fmt`]: ../std/fmt/index.html + /// + /// # Examples + /// + /// ``` + /// // the panic message for these assertions is the stringified value of the + /// // expression given. + /// assert!(true); + /// + /// fn some_computation() -> bool { true } // a very simple function + /// + /// assert!(some_computation()); + /// + /// // assert with a custom message + /// let x = true; + /// assert!(x, "x wasn't true!"); + /// + /// let a = 3; let b = 27; + /// assert!(a + b == 30, "a = {}, b = {}", a, b); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + #[macro_export] + #[rustc_diagnostic_item = "assert_macro"] + #[allow_internal_unstable( + core_intrinsics, + panic_internals, + edition_panic, + generic_assert_internals + )] + macro_rules! assert { + ($cond:expr $(,)?) => {{ /* compiler built-in */ }}; + ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }}; + } + + /// Prints passed tokens into the standard output. + #[unstable( + feature = "log_syntax", + issue = "29598", + reason = "`log_syntax!` is not stable enough for use and is subject to change" + )] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! log_syntax { + ($($arg:tt)*) => { + /* compiler built-in */ + }; + } + + /// Enables or disables tracing functionality used for debugging other macros. + #[unstable( + feature = "trace_macros", + issue = "29598", + reason = "`trace_macros` is not stable enough for use and is subject to change" + )] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! trace_macros { + (true) => {{ /* compiler built-in */ }}; + (false) => {{ /* compiler built-in */ }}; + } + + /// Attribute macro used to apply derive macros. + /// + /// See [the reference] for more info. + /// + /// [the reference]: ../../../reference/attributes/derive.html + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + pub macro derive($item:item) { + /* compiler built-in */ + } + + /// Attribute macro used to apply derive macros for implementing traits + /// in a const context. + /// + /// See [the reference] for more info. + /// + /// [the reference]: ../../../reference/attributes/derive.html + #[unstable(feature = "derive_const", issue = "none")] + #[rustc_builtin_macro] + pub macro derive_const($item:item) { + /* compiler built-in */ + } + + /// Attribute macro applied to a function to turn it into a unit test. + /// + /// See [the reference] for more info. + /// + /// [the reference]: ../../../reference/attributes/testing.html#the-test-attribute + #[stable(feature = "rust1", since = "1.0.0")] + #[allow_internal_unstable(test, rustc_attrs, coverage_attribute)] + #[rustc_builtin_macro] + pub macro test($item:item) { + /* compiler built-in */ + } + + /// Attribute macro applied to a function to turn it into a benchmark test. + #[unstable( + feature = "test", + issue = "50297", + soft, + reason = "`bench` is a part of custom test frameworks which are unstable" + )] + #[allow_internal_unstable(test, rustc_attrs, coverage_attribute)] + #[rustc_builtin_macro] + pub macro bench($item:item) { + /* compiler built-in */ + } + + /// An implementation detail of the `#[test]` and `#[bench]` macros. + #[unstable( + feature = "custom_test_frameworks", + issue = "50297", + reason = "custom test frameworks are an unstable feature" + )] + #[allow_internal_unstable(test, rustc_attrs)] + #[rustc_builtin_macro] + pub macro test_case($item:item) { + /* compiler built-in */ + } + + /// Attribute macro applied to a static to register it as a global allocator. + /// + /// See also [`std::alloc::GlobalAlloc`](../../../std/alloc/trait.GlobalAlloc.html). + #[stable(feature = "global_allocator", since = "1.28.0")] + #[allow_internal_unstable(rustc_attrs)] + #[rustc_builtin_macro] + pub macro global_allocator($item:item) { + /* compiler built-in */ + } + + /// Attribute macro applied to a function to register it as a handler for allocation failure. + /// + /// See also [`std::alloc::handle_alloc_error`](../../../std/alloc/fn.handle_alloc_error.html). + #[unstable(feature = "alloc_error_handler", issue = "51540")] + #[allow_internal_unstable(rustc_attrs)] + #[rustc_builtin_macro] + pub macro alloc_error_handler($item:item) { + /* compiler built-in */ + } + + /// Keeps the item it's applied to if the passed path is accessible, and removes it otherwise. + #[unstable( + feature = "cfg_accessible", + issue = "64797", + reason = "`cfg_accessible` is not fully implemented" + )] + #[rustc_builtin_macro] + pub macro cfg_accessible($item:item) { + /* compiler built-in */ + } + + /// Expands all `#[cfg]` and `#[cfg_attr]` attributes in the code fragment it's applied to. + #[unstable( + feature = "cfg_eval", + issue = "82679", + reason = "`cfg_eval` is a recently implemented feature" + )] + #[rustc_builtin_macro] + pub macro cfg_eval($($tt:tt)*) { + /* compiler built-in */ + } + + /// Unstable placeholder for type ascription. + #[allow_internal_unstable(builtin_syntax)] + #[unstable( + feature = "type_ascription", + issue = "23416", + reason = "placeholder syntax for type ascription" + )] + #[rustfmt::skip] + pub macro type_ascribe($expr:expr, $ty:ty) { + builtin # type_ascribe($expr, $ty) + } + + /// Unstable placeholder for deref patterns. + #[allow_internal_unstable(builtin_syntax)] + #[unstable( + feature = "deref_patterns", + issue = "87121", + reason = "placeholder syntax for deref patterns" + )] + pub macro deref($pat:pat) { + builtin # deref($pat) + } + + /// Derive macro for `rustc-serialize`. Should not be used in new code. + #[rustc_builtin_macro] + #[unstable( + feature = "rustc_encodable_decodable", + issue = "none", + soft, + reason = "derive macro for `rustc-serialize`; should not be used in new code" + )] + #[deprecated(since = "1.52.0", note = "rustc-serialize is deprecated and no longer supported")] + #[doc(hidden)] // While technically stable, using it is unstable, and deprecated. Hide it. + pub macro RustcDecodable($item:item) { + /* compiler built-in */ + } + + /// Derive macro for `rustc-serialize`. Should not be used in new code. + #[rustc_builtin_macro] + #[unstable( + feature = "rustc_encodable_decodable", + issue = "none", + soft, + reason = "derive macro for `rustc-serialize`; should not be used in new code" + )] + #[deprecated(since = "1.52.0", note = "rustc-serialize is deprecated and no longer supported")] + #[doc(hidden)] // While technically stable, using it is unstable, and deprecated. Hide it. + pub macro RustcEncodable($item:item) { + /* compiler built-in */ + } +} diff --git a/CoqOfRust/core/marker.rs b/CoqOfRust/core/marker.rs new file mode 100644 index 000000000..1620b9495 --- /dev/null +++ b/CoqOfRust/core/marker.rs @@ -0,0 +1,1085 @@ +//! Primitive traits and types representing basic properties of types. +//! +//! Rust types can be classified in various useful ways according to +//! their intrinsic properties. These classifications are represented +//! as traits. + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::cell::UnsafeCell; +use crate::cmp; +use crate::fmt::Debug; +use crate::hash::{Hash, Hasher}; + +/// Implements a given marker trait for multiple types at the same time. +/// +/// The basic syntax looks like this: +/// ```ignore private macro +/// marker_impls! { MarkerTrait for u8, i8 } +/// ``` +/// You can also implement `unsafe` traits +/// ```ignore private macro +/// marker_impls! { unsafe MarkerTrait for u8, i8 } +/// ``` +/// Add attributes to all impls: +/// ```ignore private macro +/// marker_impls! { +/// #[allow(lint)] +/// #[unstable(feature = "marker_trait", issue = "none")] +/// MarkerTrait for u8, i8 +/// } +/// ``` +/// And use generics: +/// ```ignore private macro +/// marker_impls! { +/// MarkerTrait for +/// u8, i8, +/// {T: ?Sized} *const T, +/// {T: ?Sized} *mut T, +/// {T: MarkerTrait} PhantomData, +/// u32, +/// } +/// ``` +#[unstable(feature = "internal_impls_macro", issue = "none")] +// Allow implementations of `UnsizedConstParamTy` even though std cannot use that feature. +#[allow_internal_unstable(unsized_const_params)] +macro marker_impls { + ( $(#[$($meta:tt)*])* $Trait:ident for $({$($bounds:tt)*})? $T:ty $(, $($rest:tt)*)? ) => { + $(#[$($meta)*])* impl< $($($bounds)*)? > $Trait for $T {} + marker_impls! { $(#[$($meta)*])* $Trait for $($($rest)*)? } + }, + ( $(#[$($meta:tt)*])* $Trait:ident for ) => {}, + + ( $(#[$($meta:tt)*])* unsafe $Trait:ident for $({$($bounds:tt)*})? $T:ty $(, $($rest:tt)*)? ) => { + $(#[$($meta)*])* unsafe impl< $($($bounds)*)? > $Trait for $T {} + marker_impls! { $(#[$($meta)*])* unsafe $Trait for $($($rest)*)? } + }, + ( $(#[$($meta:tt)*])* unsafe $Trait:ident for ) => {}, +} + +/// Types that can be transferred across thread boundaries. +/// +/// This trait is automatically implemented when the compiler determines it's +/// appropriate. +/// +/// An example of a non-`Send` type is the reference-counting pointer +/// [`rc::Rc`][`Rc`]. If two threads attempt to clone [`Rc`]s that point to the same +/// reference-counted value, they might try to update the reference count at the +/// same time, which is [undefined behavior][ub] because [`Rc`] doesn't use atomic +/// operations. Its cousin [`sync::Arc`][arc] does use atomic operations (incurring +/// some overhead) and thus is `Send`. +/// +/// See [the Nomicon](../../nomicon/send-and-sync.html) and the [`Sync`] trait for more details. +/// +/// [`Rc`]: ../../std/rc/struct.Rc.html +/// [arc]: ../../std/sync/struct.Arc.html +/// [ub]: ../../reference/behavior-considered-undefined.html +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Send")] +#[diagnostic::on_unimplemented( + message = "`{Self}` cannot be sent between threads safely", + label = "`{Self}` cannot be sent between threads safely" +)] +pub unsafe auto trait Send { + // empty. +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl !Send for *const T {} +#[stable(feature = "rust1", since = "1.0.0")] +impl !Send for *mut T {} + +// Most instances arise automatically, but this instance is needed to link up `T: Sync` with +// `&T: Send` (and it also removes the unsound default instance `T Send` -> `&T: Send` that would +// otherwise exist). +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for &T {} + +/// Types with a constant size known at compile time. +/// +/// All type parameters have an implicit bound of `Sized`. The special syntax +/// `?Sized` can be used to remove this bound if it's not appropriate. +/// +/// ``` +/// # #![allow(dead_code)] +/// struct Foo(T); +/// struct Bar(T); +/// +/// // struct FooUse(Foo<[i32]>); // error: Sized is not implemented for [i32] +/// struct BarUse(Bar<[i32]>); // OK +/// ``` +/// +/// The one exception is the implicit `Self` type of a trait. A trait does not +/// have an implicit `Sized` bound as this is incompatible with [trait object]s +/// where, by definition, the trait needs to work with all possible implementors, +/// and thus could be any size. +/// +/// Although Rust will let you bind `Sized` to a trait, you won't +/// be able to use it to form a trait object later: +/// +/// ``` +/// # #![allow(unused_variables)] +/// trait Foo { } +/// trait Bar: Sized { } +/// +/// struct Impl; +/// impl Foo for Impl { } +/// impl Bar for Impl { } +/// +/// let x: &dyn Foo = &Impl; // OK +/// // let y: &dyn Bar = &Impl; // error: the trait `Bar` cannot +/// // be made into an object +/// ``` +/// +/// [trait object]: ../../book/ch17-02-trait-objects.html +#[doc(alias = "?", alias = "?Sized")] +#[stable(feature = "rust1", since = "1.0.0")] +#[lang = "sized"] +#[diagnostic::on_unimplemented( + message = "the size for values of type `{Self}` cannot be known at compilation time", + label = "doesn't have a size known at compile-time" +)] +#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable +#[rustc_specialization_trait] +#[rustc_deny_explicit_impl(implement_via_object = false)] +#[rustc_coinductive] +pub trait Sized { + // Empty. +} + +/// Types that can be "unsized" to a dynamically-sized type. +/// +/// For example, the sized array type `[i8; 2]` implements `Unsize<[i8]>` and +/// `Unsize`. +/// +/// All implementations of `Unsize` are provided automatically by the compiler. +/// Those implementations are: +/// +/// - Arrays `[T; N]` implement `Unsize<[T]>`. +/// - A type implements `Unsize` if all of these conditions are met: +/// - The type implements `Trait`. +/// - `Trait` is dyn-compatible[^1]. +/// - The type is sized. +/// - The type outlives `'a`. +/// - Structs `Foo<..., T1, ..., Tn, ...>` implement `Unsize>` +/// where any number of (type and const) parameters may be changed if all of these conditions +/// are met: +/// - Only the last field of `Foo` has a type involving the parameters `T1`, ..., `Tn`. +/// - All other parameters of the struct are equal. +/// - `Field: Unsize>`, where `Field<...>` stands for the actual +/// type of the struct's last field. +/// +/// `Unsize` is used along with [`ops::CoerceUnsized`] to allow +/// "user-defined" containers such as [`Rc`] to contain dynamically-sized +/// types. See the [DST coercion RFC][RFC982] and [the nomicon entry on coercion][nomicon-coerce] +/// for more details. +/// +/// [`ops::CoerceUnsized`]: crate::ops::CoerceUnsized +/// [`Rc`]: ../../std/rc/struct.Rc.html +/// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md +/// [nomicon-coerce]: ../../nomicon/coercions.html +/// [^1]: Formerly known as *object safe*. +#[unstable(feature = "unsize", issue = "18598")] +#[lang = "unsize"] +#[rustc_deny_explicit_impl(implement_via_object = false)] +pub trait Unsize { + // Empty. +} + +/// Required trait for constants used in pattern matches. +/// +/// Any type that derives `PartialEq` automatically implements this trait, +/// *regardless* of whether its type-parameters implement `PartialEq`. +/// +/// If a `const` item contains some type that does not implement this trait, +/// then that type either (1.) does not implement `PartialEq` (which means the +/// constant will not provide that comparison method, which code generation +/// assumes is available), or (2.) it implements *its own* version of +/// `PartialEq` (which we assume does not conform to a structural-equality +/// comparison). +/// +/// In either of the two scenarios above, we reject usage of such a constant in +/// a pattern match. +/// +/// See also the [structural match RFC][RFC1445], and [issue 63438] which +/// motivated migrating from an attribute-based design to this trait. +/// +/// [RFC1445]: https://github.com/rust-lang/rfcs/blob/master/text/1445-restrict-constants-in-patterns.md +/// [issue 63438]: https://github.com/rust-lang/rust/issues/63438 +#[unstable(feature = "structural_match", issue = "31434")] +#[diagnostic::on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")] +#[lang = "structural_peq"] +pub trait StructuralPartialEq { + // Empty. +} + +marker_impls! { + #[unstable(feature = "structural_match", issue = "31434")] + StructuralPartialEq for + usize, u8, u16, u32, u64, u128, + isize, i8, i16, i32, i64, i128, + bool, + char, + str /* Technically requires `[u8]: StructuralPartialEq` */, + (), + {T, const N: usize} [T; N], + {T} [T], + {T: ?Sized} &T, +} + +/// Types whose values can be duplicated simply by copying bits. +/// +/// By default, variable bindings have 'move semantics.' In other +/// words: +/// +/// ``` +/// #[derive(Debug)] +/// struct Foo; +/// +/// let x = Foo; +/// +/// let y = x; +/// +/// // `x` has moved into `y`, and so cannot be used +/// +/// // println!("{x:?}"); // error: use of moved value +/// ``` +/// +/// However, if a type implements `Copy`, it instead has 'copy semantics': +/// +/// ``` +/// // We can derive a `Copy` implementation. `Clone` is also required, as it's +/// // a supertrait of `Copy`. +/// #[derive(Debug, Copy, Clone)] +/// struct Foo; +/// +/// let x = Foo; +/// +/// let y = x; +/// +/// // `y` is a copy of `x` +/// +/// println!("{x:?}"); // A-OK! +/// ``` +/// +/// It's important to note that in these two examples, the only difference is whether you +/// are allowed to access `x` after the assignment. Under the hood, both a copy and a move +/// can result in bits being copied in memory, although this is sometimes optimized away. +/// +/// ## How can I implement `Copy`? +/// +/// There are two ways to implement `Copy` on your type. The simplest is to use `derive`: +/// +/// ``` +/// #[derive(Copy, Clone)] +/// struct MyStruct; +/// ``` +/// +/// You can also implement `Copy` and `Clone` manually: +/// +/// ``` +/// struct MyStruct; +/// +/// impl Copy for MyStruct { } +/// +/// impl Clone for MyStruct { +/// fn clone(&self) -> MyStruct { +/// *self +/// } +/// } +/// ``` +/// +/// There is a small difference between the two. The `derive` strategy will also place a `Copy` +/// bound on type parameters: +/// +/// ``` +/// #[derive(Clone)] +/// struct MyStruct(T); +/// +/// impl Copy for MyStruct { } +/// ``` +/// +/// This isn't always desired. For example, shared references (`&T`) can be copied regardless of +/// whether `T` is `Copy`. Likewise, a generic struct containing markers such as [`PhantomData`] +/// could potentially be duplicated with a bit-wise copy. +/// +/// ## What's the difference between `Copy` and `Clone`? +/// +/// Copies happen implicitly, for example as part of an assignment `y = x`. The behavior of +/// `Copy` is not overloadable; it is always a simple bit-wise copy. +/// +/// Cloning is an explicit action, `x.clone()`. The implementation of [`Clone`] can +/// provide any type-specific behavior necessary to duplicate values safely. For example, +/// the implementation of [`Clone`] for [`String`] needs to copy the pointed-to string +/// buffer in the heap. A simple bitwise copy of [`String`] values would merely copy the +/// pointer, leading to a double free down the line. For this reason, [`String`] is [`Clone`] +/// but not `Copy`. +/// +/// [`Clone`] is a supertrait of `Copy`, so everything which is `Copy` must also implement +/// [`Clone`]. If a type is `Copy` then its [`Clone`] implementation only needs to return `*self` +/// (see the example above). +/// +/// ## When can my type be `Copy`? +/// +/// A type can implement `Copy` if all of its components implement `Copy`. For example, this +/// struct can be `Copy`: +/// +/// ``` +/// # #[allow(dead_code)] +/// #[derive(Copy, Clone)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// ``` +/// +/// A struct can be `Copy`, and [`i32`] is `Copy`, therefore `Point` is eligible to be `Copy`. +/// By contrast, consider +/// +/// ``` +/// # #![allow(dead_code)] +/// # struct Point; +/// struct PointList { +/// points: Vec, +/// } +/// ``` +/// +/// The struct `PointList` cannot implement `Copy`, because [`Vec`] is not `Copy`. If we +/// attempt to derive a `Copy` implementation, we'll get an error: +/// +/// ```text +/// the trait `Copy` cannot be implemented for this type; field `points` does not implement `Copy` +/// ``` +/// +/// Shared references (`&T`) are also `Copy`, so a type can be `Copy`, even when it holds +/// shared references of types `T` that are *not* `Copy`. Consider the following struct, +/// which can implement `Copy`, because it only holds a *shared reference* to our non-`Copy` +/// type `PointList` from above: +/// +/// ``` +/// # #![allow(dead_code)] +/// # struct PointList; +/// #[derive(Copy, Clone)] +/// struct PointListWrapper<'a> { +/// point_list_ref: &'a PointList, +/// } +/// ``` +/// +/// ## When *can't* my type be `Copy`? +/// +/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased +/// mutable reference. Copying [`String`] would duplicate responsibility for managing the +/// [`String`]'s buffer, leading to a double free. +/// +/// Generalizing the latter case, any type implementing [`Drop`] can't be `Copy`, because it's +/// managing some resource besides its own [`size_of::`] bytes. +/// +/// If you try to implement `Copy` on a struct or enum containing non-`Copy` data, you will get +/// the error [E0204]. +/// +/// [E0204]: ../../error_codes/E0204.html +/// +/// ## When *should* my type be `Copy`? +/// +/// Generally speaking, if your type _can_ implement `Copy`, it should. Keep in mind, though, +/// that implementing `Copy` is part of the public API of your type. If the type might become +/// non-`Copy` in the future, it could be prudent to omit the `Copy` implementation now, to +/// avoid a breaking API change. +/// +/// ## Additional implementors +/// +/// In addition to the [implementors listed below][impls], +/// the following types also implement `Copy`: +/// +/// * Function item types (i.e., the distinct types defined for each function) +/// * Function pointer types (e.g., `fn() -> i32`) +/// * Closure types, if they capture no value from the environment +/// or if all such captured values implement `Copy` themselves. +/// Note that variables captured by shared reference always implement `Copy` +/// (even if the referent doesn't), +/// while variables captured by mutable reference never implement `Copy`. +/// +/// [`Vec`]: ../../std/vec/struct.Vec.html +/// [`String`]: ../../std/string/struct.String.html +/// [`size_of::`]: crate::mem::size_of +/// [impls]: #implementors +#[stable(feature = "rust1", since = "1.0.0")] +#[lang = "copy"] +// FIXME(matthewjasper) This allows copying a type that doesn't implement +// `Copy` because of unsatisfied lifetime bounds (copying `A<'_>` when only +// `A<'static>: Copy` and `A<'_>: Clone`). +// We have this attribute here for now only because there are quite a few +// existing specializations on `Copy` that already exist in the standard +// library, and there's no way to safely have this behavior right now. +#[rustc_unsafe_specialization_marker] +#[rustc_diagnostic_item = "Copy"] +pub trait Copy: Clone { + // Empty. +} + +/// Derive macro generating an impl of the trait `Copy`. +#[rustc_builtin_macro] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics, derive_clone_copy)] +pub macro Copy($item:item) { + /* compiler built-in */ +} + +// Implementations of `Copy` for primitive types. +// +// Implementations that cannot be described in Rust +// are implemented in `traits::SelectionContext::copy_clone_conditions()` +// in `rustc_trait_selection`. +marker_impls! { + #[stable(feature = "rust1", since = "1.0.0")] + Copy for + usize, u8, u16, u32, u64, u128, + isize, i8, i16, i32, i64, i128, + f16, f32, f64, f128, + bool, char, + {T: ?Sized} *const T, + {T: ?Sized} *mut T, + +} + +#[unstable(feature = "never_type", issue = "35121")] +impl Copy for ! {} + +/// Shared references can be copied, but mutable references *cannot*! +#[stable(feature = "rust1", since = "1.0.0")] +impl Copy for &T {} + +/// Types for which it is safe to share references between threads. +/// +/// This trait is automatically implemented when the compiler determines +/// it's appropriate. +/// +/// The precise definition is: a type `T` is [`Sync`] if and only if `&T` is +/// [`Send`]. In other words, if there is no possibility of +/// [undefined behavior][ub] (including data races) when passing +/// `&T` references between threads. +/// +/// As one would expect, primitive types like [`u8`] and [`f64`] +/// are all [`Sync`], and so are simple aggregate types containing them, +/// like tuples, structs and enums. More examples of basic [`Sync`] +/// types include "immutable" types like `&T`, and those with simple +/// inherited mutability, such as [`Box`][box], [`Vec`][vec] and +/// most other collection types. (Generic parameters need to be [`Sync`] +/// for their container to be [`Sync`].) +/// +/// A somewhat surprising consequence of the definition is that `&mut T` +/// is `Sync` (if `T` is `Sync`) even though it seems like that might +/// provide unsynchronized mutation. The trick is that a mutable +/// reference behind a shared reference (that is, `& &mut T`) +/// becomes read-only, as if it were a `& &T`. Hence there is no risk +/// of a data race. +/// +/// A shorter overview of how [`Sync`] and [`Send`] relate to referencing: +/// * `&T` is [`Send`] if and only if `T` is [`Sync`] +/// * `&mut T` is [`Send`] if and only if `T` is [`Send`] +/// * `&T` and `&mut T` are [`Sync`] if and only if `T` is [`Sync`] +/// +/// Types that are not `Sync` are those that have "interior +/// mutability" in a non-thread-safe form, such as [`Cell`][cell] +/// and [`RefCell`][refcell]. These types allow for mutation of +/// their contents even through an immutable, shared reference. For +/// example the `set` method on [`Cell`][cell] takes `&self`, so it requires +/// only a shared reference [`&Cell`][cell]. The method performs no +/// synchronization, thus [`Cell`][cell] cannot be `Sync`. +/// +/// Another example of a non-`Sync` type is the reference-counting +/// pointer [`Rc`][rc]. Given any reference [`&Rc`][rc], you can clone +/// a new [`Rc`][rc], modifying the reference counts in a non-atomic way. +/// +/// For cases when one does need thread-safe interior mutability, +/// Rust provides [atomic data types], as well as explicit locking via +/// [`sync::Mutex`][mutex] and [`sync::RwLock`][rwlock]. These types +/// ensure that any mutation cannot cause data races, hence the types +/// are `Sync`. Likewise, [`sync::Arc`][arc] provides a thread-safe +/// analogue of [`Rc`][rc]. +/// +/// Any types with interior mutability must also use the +/// [`cell::UnsafeCell`][unsafecell] wrapper around the value(s) which +/// can be mutated through a shared reference. Failing to doing this is +/// [undefined behavior][ub]. For example, [`transmute`][transmute]-ing +/// from `&T` to `&mut T` is invalid. +/// +/// See [the Nomicon][nomicon-send-and-sync] for more details about `Sync`. +/// +/// [box]: ../../std/boxed/struct.Box.html +/// [vec]: ../../std/vec/struct.Vec.html +/// [cell]: crate::cell::Cell +/// [refcell]: crate::cell::RefCell +/// [rc]: ../../std/rc/struct.Rc.html +/// [arc]: ../../std/sync/struct.Arc.html +/// [atomic data types]: crate::sync::atomic +/// [mutex]: ../../std/sync/struct.Mutex.html +/// [rwlock]: ../../std/sync/struct.RwLock.html +/// [unsafecell]: crate::cell::UnsafeCell +/// [ub]: ../../reference/behavior-considered-undefined.html +/// [transmute]: crate::mem::transmute +/// [nomicon-send-and-sync]: ../../nomicon/send-and-sync.html +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Sync")] +#[lang = "sync"] +#[rustc_on_unimplemented( + on( + _Self = "core::cell::once::OnceCell", + note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::OnceLock` instead" + ), + on( + _Self = "core::cell::Cell", + note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU8` instead", + ), + on( + _Self = "core::cell::Cell", + note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU16` instead", + ), + on( + _Self = "core::cell::Cell", + note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU32` instead", + ), + on( + _Self = "core::cell::Cell", + note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU64` instead", + ), + on( + _Self = "core::cell::Cell", + note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicUsize` instead", + ), + on( + _Self = "core::cell::Cell", + note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI8` instead", + ), + on( + _Self = "core::cell::Cell", + note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI16` instead", + ), + on( + _Self = "core::cell::Cell", + note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead", + ), + on( + _Self = "core::cell::Cell", + note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI64` instead", + ), + on( + _Self = "core::cell::Cell", + note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicIsize` instead", + ), + on( + _Self = "core::cell::Cell", + note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicBool` instead", + ), + on( + all( + _Self = "core::cell::Cell", + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell") + ), + note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock`", + ), + on( + _Self = "core::cell::RefCell", + note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead", + ), + message = "`{Self}` cannot be shared between threads safely", + label = "`{Self}` cannot be shared between threads safely" +)] +pub unsafe auto trait Sync { + // FIXME(estebank): once support to add notes in `rustc_on_unimplemented` + // lands in beta, and it has been extended to check whether a closure is + // anywhere in the requirement chain, extend it as such (#48534): + // ``` + // on( + // closure, + // note="`{Self}` cannot be shared safely, consider marking the closure `move`" + // ), + // ``` + + // Empty +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl !Sync for *const T {} +#[stable(feature = "rust1", since = "1.0.0")] +impl !Sync for *mut T {} + +/// Zero-sized type used to mark things that "act like" they own a `T`. +/// +/// Adding a `PhantomData` field to your type tells the compiler that your +/// type acts as though it stores a value of type `T`, even though it doesn't +/// really. This information is used when computing certain safety properties. +/// +/// For a more in-depth explanation of how to use `PhantomData`, please see +/// [the Nomicon](../../nomicon/phantom-data.html). +/// +/// # A ghastly note 👻👻👻 +/// +/// Though they both have scary names, `PhantomData` and 'phantom types' are +/// related, but not identical. A phantom type parameter is simply a type +/// parameter which is never used. In Rust, this often causes the compiler to +/// complain, and the solution is to add a "dummy" use by way of `PhantomData`. +/// +/// # Examples +/// +/// ## Unused lifetime parameters +/// +/// Perhaps the most common use case for `PhantomData` is a struct that has an +/// unused lifetime parameter, typically as part of some unsafe code. For +/// example, here is a struct `Slice` that has two pointers of type `*const T`, +/// presumably pointing into an array somewhere: +/// +/// ```compile_fail,E0392 +/// struct Slice<'a, T> { +/// start: *const T, +/// end: *const T, +/// } +/// ``` +/// +/// The intention is that the underlying data is only valid for the +/// lifetime `'a`, so `Slice` should not outlive `'a`. However, this +/// intent is not expressed in the code, since there are no uses of +/// the lifetime `'a` and hence it is not clear what data it applies +/// to. We can correct this by telling the compiler to act *as if* the +/// `Slice` struct contained a reference `&'a T`: +/// +/// ``` +/// use std::marker::PhantomData; +/// +/// # #[allow(dead_code)] +/// struct Slice<'a, T> { +/// start: *const T, +/// end: *const T, +/// phantom: PhantomData<&'a T>, +/// } +/// ``` +/// +/// This also in turn infers the lifetime bound `T: 'a`, indicating +/// that any references in `T` are valid over the lifetime `'a`. +/// +/// When initializing a `Slice` you simply provide the value +/// `PhantomData` for the field `phantom`: +/// +/// ``` +/// # #![allow(dead_code)] +/// # use std::marker::PhantomData; +/// # struct Slice<'a, T> { +/// # start: *const T, +/// # end: *const T, +/// # phantom: PhantomData<&'a T>, +/// # } +/// fn borrow_vec(vec: &Vec) -> Slice<'_, T> { +/// let ptr = vec.as_ptr(); +/// Slice { +/// start: ptr, +/// end: unsafe { ptr.add(vec.len()) }, +/// phantom: PhantomData, +/// } +/// } +/// ``` +/// +/// ## Unused type parameters +/// +/// It sometimes happens that you have unused type parameters which +/// indicate what type of data a struct is "tied" to, even though that +/// data is not actually found in the struct itself. Here is an +/// example where this arises with [FFI]. The foreign interface uses +/// handles of type `*mut ()` to refer to Rust values of different +/// types. We track the Rust type using a phantom type parameter on +/// the struct `ExternalResource` which wraps a handle. +/// +/// [FFI]: ../../book/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code +/// +/// ``` +/// # #![allow(dead_code)] +/// # trait ResType { } +/// # struct ParamType; +/// # mod foreign_lib { +/// # pub fn new(_: usize) -> *mut () { 42 as *mut () } +/// # pub fn do_stuff(_: *mut (), _: usize) {} +/// # } +/// # fn convert_params(_: ParamType) -> usize { 42 } +/// use std::marker::PhantomData; +/// use std::mem; +/// +/// struct ExternalResource { +/// resource_handle: *mut (), +/// resource_type: PhantomData, +/// } +/// +/// impl ExternalResource { +/// fn new() -> Self { +/// let size_of_res = mem::size_of::(); +/// Self { +/// resource_handle: foreign_lib::new(size_of_res), +/// resource_type: PhantomData, +/// } +/// } +/// +/// fn do_stuff(&self, param: ParamType) { +/// let foreign_params = convert_params(param); +/// foreign_lib::do_stuff(self.resource_handle, foreign_params); +/// } +/// } +/// ``` +/// +/// ## Ownership and the drop check +/// +/// The exact interaction of `PhantomData` with drop check **may change in the future**. +/// +/// Currently, adding a field of type `PhantomData` indicates that your type *owns* data of type +/// `T` in very rare circumstances. This in turn has effects on the Rust compiler's [drop check] +/// analysis. For the exact rules, see the [drop check] documentation. +/// +/// ## Layout +/// +/// For all `T`, the following are guaranteed: +/// * `size_of::>() == 0` +/// * `align_of::>() == 1` +/// +/// [drop check]: Drop#drop-check +#[lang = "phantom_data"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct PhantomData; + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for PhantomData { + #[inline] + fn hash(&self, _: &mut H) {} +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl cmp::PartialEq for PhantomData { + fn eq(&self, _other: &PhantomData) -> bool { + true + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl cmp::Eq for PhantomData {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl cmp::PartialOrd for PhantomData { + fn partial_cmp(&self, _other: &PhantomData) -> Option { + Option::Some(cmp::Ordering::Equal) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl cmp::Ord for PhantomData { + fn cmp(&self, _other: &PhantomData) -> cmp::Ordering { + cmp::Ordering::Equal + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Copy for PhantomData {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for PhantomData { + fn clone(&self) -> Self { + Self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for PhantomData { + fn default() -> Self { + Self + } +} + +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralPartialEq for PhantomData {} + +/// Compiler-internal trait used to indicate the type of enum discriminants. +/// +/// This trait is automatically implemented for every type and does not add any +/// guarantees to [`mem::Discriminant`]. It is **undefined behavior** to transmute +/// between `DiscriminantKind::Discriminant` and `mem::Discriminant`. +/// +/// [`mem::Discriminant`]: crate::mem::Discriminant +#[unstable( + feature = "discriminant_kind", + issue = "none", + reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead" +)] +#[lang = "discriminant_kind"] +#[rustc_deny_explicit_impl(implement_via_object = false)] +pub trait DiscriminantKind { + /// The type of the discriminant, which must satisfy the trait + /// bounds required by `mem::Discriminant`. + #[lang = "discriminant_type"] + type Discriminant: Clone + Copy + Debug + Eq + PartialEq + Hash + Send + Sync + Unpin; +} + +/// Used to determine whether a type contains +/// any `UnsafeCell` internally, but not through an indirection. +/// This affects, for example, whether a `static` of that type is +/// placed in read-only static memory or writable static memory. +/// This can be used to declare that a constant with a generic type +/// will not contain interior mutability, and subsequently allow +/// placing the constant behind references. +/// +/// # Safety +/// +/// This trait is a core part of the language, it is just expressed as a trait in libcore for +/// convenience. Do *not* implement it for other types. +// FIXME: Eventually this trait should become `#[rustc_deny_explicit_impl]`. +// That requires porting the impls below to native internal impls. +#[lang = "freeze"] +#[unstable(feature = "freeze", issue = "121675")] +pub unsafe auto trait Freeze {} + +#[unstable(feature = "freeze", issue = "121675")] +impl !Freeze for UnsafeCell {} +marker_impls! { + #[unstable(feature = "freeze", issue = "121675")] + unsafe Freeze for + {T: ?Sized} PhantomData, + {T: ?Sized} *const T, + {T: ?Sized} *mut T, + {T: ?Sized} &T, + {T: ?Sized} &mut T, +} + +/// Types that do not require any pinning guarantees. +/// +/// For information on what "pinning" is, see the [`pin` module] documentation. +/// +/// Implementing the `Unpin` trait for `T` expresses the fact that `T` is pinning-agnostic: +/// it shall not expose nor rely on any pinning guarantees. This, in turn, means that a +/// `Pin`-wrapped pointer to such a type can feature a *fully unrestricted* API. +/// In other words, if `T: Unpin`, a value of type `T` will *not* be bound by the invariants +/// which pinning otherwise offers, even when "pinned" by a [`Pin`] pointing at it. +/// When a value of type `T` is pointed at by a [`Pin`], [`Pin`] will not restrict access +/// to the pointee value like it normally would, thus allowing the user to do anything that they +/// normally could with a non-[`Pin`]-wrapped `Ptr` to that value. +/// +/// The idea of this trait is to alleviate the reduced ergonomics of APIs that require the use +/// of [`Pin`] for soundness for some types, but which also want to be used by other types that +/// don't care about pinning. The prime example of such an API is [`Future::poll`]. There are many +/// [`Future`] types that don't care about pinning. These futures can implement `Unpin` and +/// therefore get around the pinning related restrictions in the API, while still allowing the +/// subset of [`Future`]s which *do* require pinning to be implemented soundly. +/// +/// For more discussion on the consequences of [`Unpin`] within the wider scope of the pinning +/// system, see the [section about `Unpin`] in the [`pin` module]. +/// +/// `Unpin` has no consequence at all for non-pinned data. In particular, [`mem::replace`] happily +/// moves `!Unpin` data, which would be immovable when pinned ([`mem::replace`] works for any +/// `&mut T`, not just when `T: Unpin`). +/// +/// *However*, you cannot use [`mem::replace`] on `!Unpin` data which is *pinned* by being wrapped +/// inside a [`Pin`] pointing at it. This is because you cannot (safely) use a +/// [`Pin`] to get a `&mut T` to its pointee value, which you would need to call +/// [`mem::replace`], and *that* is what makes this system work. +/// +/// So this, for example, can only be done on types implementing `Unpin`: +/// +/// ```rust +/// # #![allow(unused_must_use)] +/// use std::mem; +/// use std::pin::Pin; +/// +/// let mut string = "this".to_string(); +/// let mut pinned_string = Pin::new(&mut string); +/// +/// // We need a mutable reference to call `mem::replace`. +/// // We can obtain such a reference by (implicitly) invoking `Pin::deref_mut`, +/// // but that is only possible because `String` implements `Unpin`. +/// mem::replace(&mut *pinned_string, "other".to_string()); +/// ``` +/// +/// This trait is automatically implemented for almost every type. The compiler is free +/// to take the conservative stance of marking types as [`Unpin`] so long as all of the types that +/// compose its fields are also [`Unpin`]. This is because if a type implements [`Unpin`], then it +/// is unsound for that type's implementation to rely on pinning-related guarantees for soundness, +/// *even* when viewed through a "pinning" pointer! It is the responsibility of the implementor of +/// a type that relies upon pinning for soundness to ensure that type is *not* marked as [`Unpin`] +/// by adding [`PhantomPinned`] field. For more details, see the [`pin` module] docs. +/// +/// [`mem::replace`]: crate::mem::replace "mem replace" +/// [`Future`]: crate::future::Future "Future" +/// [`Future::poll`]: crate::future::Future::poll "Future poll" +/// [`Pin`]: crate::pin::Pin "Pin" +/// [`Pin`]: crate::pin::Pin "Pin" +/// [`pin` module]: crate::pin "pin module" +/// [section about `Unpin`]: crate::pin#unpin "pin module docs about unpin" +/// [`unsafe`]: ../../std/keyword.unsafe.html "keyword unsafe" +#[stable(feature = "pin", since = "1.33.0")] +#[diagnostic::on_unimplemented( + note = "consider using the `pin!` macro\nconsider using `Box::pin` if you need to access the pinned value outside of the current scope", + message = "`{Self}` cannot be unpinned" +)] +#[lang = "unpin"] +pub auto trait Unpin {} + +/// A marker type which does not implement `Unpin`. +/// +/// If a type contains a `PhantomPinned`, it will not implement `Unpin` by default. +#[stable(feature = "pin", since = "1.33.0")] +#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct PhantomPinned; + +#[stable(feature = "pin", since = "1.33.0")] +impl !Unpin for PhantomPinned {} + +marker_impls! { + #[stable(feature = "pin", since = "1.33.0")] + Unpin for + {T: ?Sized} &T, + {T: ?Sized} &mut T, +} + +marker_impls! { + #[stable(feature = "pin_raw", since = "1.38.0")] + Unpin for + {T: ?Sized} *const T, + {T: ?Sized} *mut T, +} + +/// A marker for types that can be dropped. +/// +/// This should be used for `~const` bounds, +/// as non-const bounds will always hold for every type. +#[unstable(feature = "const_destruct", issue = "133214")] +#[lang = "destruct"] +#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] +#[rustc_deny_explicit_impl(implement_via_object = false)] +#[cfg_attr(not(bootstrap), const_trait)] +pub trait Destruct {} + +/// A marker for tuple types. +/// +/// The implementation of this trait is built-in and cannot be implemented +/// for any user type. +#[unstable(feature = "tuple_trait", issue = "none")] +#[lang = "tuple_trait"] +#[diagnostic::on_unimplemented(message = "`{Self}` is not a tuple")] +#[rustc_deny_explicit_impl(implement_via_object = false)] +pub trait Tuple {} + +/// A marker for pointer-like types. +/// +/// All types that have the same size and alignment as a `usize` or +/// `*const ()` automatically implement this trait. +#[unstable(feature = "pointer_like_trait", issue = "none")] +#[lang = "pointer_like"] +#[diagnostic::on_unimplemented( + message = "`{Self}` needs to have the same ABI as a pointer", + label = "`{Self}` needs to be a pointer-like type" +)] +pub trait PointerLike {} + +#[cfg(not(bootstrap))] +marker_impls! { + #[unstable(feature = "pointer_like_trait", issue = "none")] + PointerLike for + usize, + {T} &T, + {T} &mut T, + {T} *const T, + {T} *mut T, + {T: PointerLike} crate::pin::Pin, +} + +/// A marker for types which can be used as types of `const` generic parameters. +/// +/// These types must have a proper equivalence relation (`Eq`) and it must be automatically +/// derived (`StructuralPartialEq`). There's a hard-coded check in the compiler ensuring +/// that all fields are also `ConstParamTy`, which implies that recursively, all fields +/// are `StructuralPartialEq`. +#[lang = "const_param_ty"] +#[unstable(feature = "unsized_const_params", issue = "95174")] +#[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] +#[allow(multiple_supertrait_upcastable)] +// We name this differently than the derive macro so that the `adt_const_params` can +// be used independently of `unsized_const_params` without requiring a full path +// to the derive macro every time it is used. This should be renamed on stabilization. +pub trait ConstParamTy_: UnsizedConstParamTy + StructuralPartialEq + Eq {} + +/// Derive macro generating an impl of the trait `ConstParamTy`. +#[rustc_builtin_macro] +#[allow_internal_unstable(unsized_const_params)] +#[unstable(feature = "adt_const_params", issue = "95174")] +pub macro ConstParamTy($item:item) { + /* compiler built-in */ +} + +#[lang = "unsized_const_param_ty"] +#[unstable(feature = "unsized_const_params", issue = "95174")] +#[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] +/// A marker for types which can be used as types of `const` generic parameters. +/// +/// Equivalent to [`ConstParamTy_`] except that this is used by +/// the `unsized_const_params` to allow for fake unstable impls. +pub trait UnsizedConstParamTy: StructuralPartialEq + Eq {} + +/// Derive macro generating an impl of the trait `ConstParamTy`. +#[rustc_builtin_macro] +#[allow_internal_unstable(unsized_const_params)] +#[unstable(feature = "unsized_const_params", issue = "95174")] +pub macro UnsizedConstParamTy($item:item) { + /* compiler built-in */ +} + +// FIXME(adt_const_params): handle `ty::FnDef`/`ty::Closure` +marker_impls! { + #[unstable(feature = "adt_const_params", issue = "95174")] + ConstParamTy_ for + usize, u8, u16, u32, u64, u128, + isize, i8, i16, i32, i64, i128, + bool, + char, + (), + {T: ConstParamTy_, const N: usize} [T; N], +} + +marker_impls! { + #[unstable(feature = "unsized_const_params", issue = "95174")] + UnsizedConstParamTy for + usize, u8, u16, u32, u64, u128, + isize, i8, i16, i32, i64, i128, + bool, + char, + (), + {T: UnsizedConstParamTy, const N: usize} [T; N], + + str, + {T: UnsizedConstParamTy} [T], + {T: UnsizedConstParamTy + ?Sized} &T, +} + +/// A common trait implemented by all function pointers. +#[unstable( + feature = "fn_ptr_trait", + issue = "none", + reason = "internal trait for implementing various traits for all function pointers" +)] +#[lang = "fn_ptr_trait"] +#[rustc_deny_explicit_impl(implement_via_object = false)] +pub trait FnPtr: Copy + Clone { + /// Returns the address of the function pointer. + #[lang = "fn_ptr_addr"] + fn addr(self) -> *const (); +} + +/// Derive macro generating impls of traits related to smart pointers. +#[rustc_builtin_macro(CoercePointee, attributes(pointee))] +#[allow_internal_unstable(dispatch_from_dyn, coerce_unsized, unsize)] +#[unstable(feature = "derive_coerce_pointee", issue = "123430")] +#[cfg(not(bootstrap))] +pub macro CoercePointee($item:item) { + /* compiler built-in */ +} diff --git a/CoqOfRust/core/mem/manually_drop.rs b/CoqOfRust/core/mem/manually_drop.rs new file mode 100644 index 000000000..7d519384e --- /dev/null +++ b/CoqOfRust/core/mem/manually_drop.rs @@ -0,0 +1,278 @@ +use crate::ops::{Deref, DerefMut, DerefPure}; +use crate::ptr; + +/// A wrapper to inhibit the compiler from automatically calling `T`’s +/// destructor. This wrapper is 0-cost. +/// +/// `ManuallyDrop` is guaranteed to have the same layout and bit validity as +/// `T`, and is subject to the same layout optimizations as `T`. As a +/// consequence, it has *no effect* on the assumptions that the compiler makes +/// about its contents. For example, initializing a `ManuallyDrop<&mut T>` with +/// [`mem::zeroed`] is undefined behavior. If you need to handle uninitialized +/// data, use [`MaybeUninit`] instead. +/// +/// Note that accessing the value inside a `ManuallyDrop` is safe. This means +/// that a `ManuallyDrop` whose content has been dropped must not be exposed +/// through a public safe API. Correspondingly, `ManuallyDrop::drop` is unsafe. +/// +/// # `ManuallyDrop` and drop order +/// +/// Rust has a well-defined [drop order] of values. To make sure that fields or +/// locals are dropped in a specific order, reorder the declarations such that +/// the implicit drop order is the correct one. +/// +/// It is possible to use `ManuallyDrop` to control the drop order, but this +/// requires unsafe code and is hard to do correctly in the presence of +/// unwinding. +/// +/// For example, if you want to make sure that a specific field is dropped after +/// the others, make it the last field of a struct: +/// +/// ``` +/// struct Context; +/// +/// struct Widget { +/// children: Vec, +/// // `context` will be dropped after `children`. +/// // Rust guarantees that fields are dropped in the order of declaration. +/// context: Context, +/// } +/// ``` +/// +/// # Interaction with `Box` +/// +/// Currently, if you have a `ManuallyDrop`, where the type `T` is a `Box` or +/// contains a `Box` inside, then dropping the `T` followed by moving the +/// `ManuallyDrop` is [considered to be undefined +/// behavior](https://github.com/rust-lang/unsafe-code-guidelines/issues/245). +/// That is, the following code causes undefined behavior: +/// +/// ```no_run +/// use std::mem::ManuallyDrop; +/// +/// let mut x = ManuallyDrop::new(Box::new(42)); +/// unsafe { +/// ManuallyDrop::drop(&mut x); +/// } +/// let y = x; // Undefined behavior! +/// ``` +/// +/// This is [likely to change in the +/// future](https://rust-lang.github.io/rfcs/3336-maybe-dangling.html). In the +/// meantime, consider using [`MaybeUninit`] instead. +/// +/// # Safety hazards when storing `ManuallyDrop` in a struct or an enum. +/// +/// Special care is needed when all of the conditions below are met: +/// * A struct or enum contains a `ManuallyDrop`. +/// * The `ManuallyDrop` is not inside a `union`. +/// * The struct or enum is part of public API, or is stored in a struct or an +/// enum that is part of public API. +/// * There is code that drops the contents of the `ManuallyDrop` field, and +/// this code is outside the struct or enum's `Drop` implementation. +/// +/// In particular, the following hazards may occur: +/// +/// #### Storing generic types +/// +/// If the `ManuallyDrop` contains a client-supplied generic type, the client +/// might provide a `Box` as that type. This would cause undefined behavior when +/// the struct or enum is later moved, as mentioned in the previous section. For +/// example, the following code causes undefined behavior: +/// +/// ```no_run +/// use std::mem::ManuallyDrop; +/// +/// pub struct BadOption { +/// // Invariant: Has been dropped iff `is_some` is false. +/// value: ManuallyDrop, +/// is_some: bool, +/// } +/// impl BadOption { +/// pub fn new(value: T) -> Self { +/// Self { value: ManuallyDrop::new(value), is_some: true } +/// } +/// pub fn change_to_none(&mut self) { +/// if self.is_some { +/// self.is_some = false; +/// unsafe { +/// // SAFETY: `value` hasn't been dropped yet, as per the invariant +/// // (This is actually unsound!) +/// ManuallyDrop::drop(&mut self.value); +/// } +/// } +/// } +/// } +/// +/// // In another crate: +/// +/// let mut option = BadOption::new(Box::new(42)); +/// option.change_to_none(); +/// let option2 = option; // Undefined behavior! +/// ``` +/// +/// #### Deriving traits +/// +/// Deriving `Debug`, `Clone`, `PartialEq`, `PartialOrd`, `Ord`, or `Hash` on +/// the struct or enum could be unsound, since the derived implementations of +/// these traits would access the `ManuallyDrop` field. For example, the +/// following code causes undefined behavior: +/// +/// ```no_run +/// use std::mem::ManuallyDrop; +/// +/// // This derive is unsound in combination with the `ManuallyDrop::drop` call. +/// #[derive(Debug)] +/// pub struct Foo { +/// value: ManuallyDrop, +/// } +/// impl Foo { +/// pub fn new() -> Self { +/// let mut temp = Self { +/// value: ManuallyDrop::new(String::from("Unsafe rust is hard.")) +/// }; +/// unsafe { +/// // SAFETY: `value` hasn't been dropped yet. +/// ManuallyDrop::drop(&mut temp.value); +/// } +/// temp +/// } +/// } +/// +/// // In another crate: +/// +/// let foo = Foo::new(); +/// println!("{:?}", foo); // Undefined behavior! +/// ``` +/// +/// [drop order]: https://doc.rust-lang.org/reference/destructors.html +/// [`mem::zeroed`]: crate::mem::zeroed +/// [`MaybeUninit`]: crate::mem::MaybeUninit +/// [`MaybeUninit`]: crate::mem::MaybeUninit +#[stable(feature = "manually_drop", since = "1.20.0")] +#[lang = "manually_drop"] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] +#[rustc_pub_transparent] +pub struct ManuallyDrop { + value: T, +} + +impl ManuallyDrop { + /// Wrap a value to be manually dropped. + /// + /// # Examples + /// + /// ```rust + /// use std::mem::ManuallyDrop; + /// let mut x = ManuallyDrop::new(String::from("Hello World!")); + /// x.truncate(5); // You can still safely operate on the value + /// assert_eq!(*x, "Hello"); + /// // But `Drop` will not be run here + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # let _ = ManuallyDrop::into_inner(x); + /// ``` + #[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"] + #[stable(feature = "manually_drop", since = "1.20.0")] + #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")] + #[inline(always)] + pub const fn new(value: T) -> ManuallyDrop { + ManuallyDrop { value } + } + + /// Extracts the value from the `ManuallyDrop` container. + /// + /// This allows the value to be dropped again. + /// + /// # Examples + /// + /// ```rust + /// use std::mem::ManuallyDrop; + /// let x = ManuallyDrop::new(Box::new(())); + /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`. + /// ``` + #[stable(feature = "manually_drop", since = "1.20.0")] + #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")] + #[inline(always)] + pub const fn into_inner(slot: ManuallyDrop) -> T { + slot.value + } + + /// Takes the value from the `ManuallyDrop` container out. + /// + /// This method is primarily intended for moving out values in drop. + /// Instead of using [`ManuallyDrop::drop`] to manually drop the value, + /// you can use this method to take the value and use it however desired. + /// + /// Whenever possible, it is preferable to use [`into_inner`][`ManuallyDrop::into_inner`] + /// instead, which prevents duplicating the content of the `ManuallyDrop`. + /// + /// # Safety + /// + /// This function semantically moves out the contained value without preventing further usage, + /// leaving the state of this container unchanged. + /// It is your responsibility to ensure that this `ManuallyDrop` is not used again. + /// + #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"] + #[stable(feature = "manually_drop_take", since = "1.42.0")] + #[inline] + pub unsafe fn take(slot: &mut ManuallyDrop) -> T { + // SAFETY: we are reading from a reference, which is guaranteed + // to be valid for reads. + unsafe { ptr::read(&slot.value) } + } +} + +impl ManuallyDrop { + /// Manually drops the contained value. + /// + /// This is exactly equivalent to calling [`ptr::drop_in_place`] with a + /// pointer to the contained value. As such, unless the contained value is a + /// packed struct, the destructor will be called in-place without moving the + /// value, and thus can be used to safely drop [pinned] data. + /// + /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead. + /// + /// # Safety + /// + /// This function runs the destructor of the contained value. Other than changes made by + /// the destructor itself, the memory is left unchanged, and so as far as the compiler is + /// concerned still holds a bit-pattern which is valid for the type `T`. + /// + /// However, this "zombie" value should not be exposed to safe code, and this function + /// should not be called more than once. To use a value after it's been dropped, or drop + /// a value multiple times, can cause Undefined Behavior (depending on what `drop` does). + /// This is normally prevented by the type system, but users of `ManuallyDrop` must + /// uphold those guarantees without assistance from the compiler. + /// + /// [pinned]: crate::pin + #[stable(feature = "manually_drop", since = "1.20.0")] + #[inline] + pub unsafe fn drop(slot: &mut ManuallyDrop) { + // SAFETY: we are dropping the value pointed to by a mutable reference + // which is guaranteed to be valid for writes. + // It is up to the caller to make sure that `slot` isn't dropped again. + unsafe { ptr::drop_in_place(&mut slot.value) } + } +} + +#[stable(feature = "manually_drop", since = "1.20.0")] +impl Deref for ManuallyDrop { + type Target = T; + #[inline(always)] + fn deref(&self) -> &T { + &self.value + } +} + +#[stable(feature = "manually_drop", since = "1.20.0")] +impl DerefMut for ManuallyDrop { + #[inline(always)] + fn deref_mut(&mut self) -> &mut T { + &mut self.value + } +} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for ManuallyDrop {} diff --git a/CoqOfRust/core/mem/maybe_uninit.rs b/CoqOfRust/core/mem/maybe_uninit.rs new file mode 100644 index 000000000..9b3d69020 --- /dev/null +++ b/CoqOfRust/core/mem/maybe_uninit.rs @@ -0,0 +1,1491 @@ +use crate::any::type_name; +use crate::mem::{self, ManuallyDrop}; +use crate::{fmt, intrinsics, ptr, slice}; + +/// A wrapper type to construct uninitialized instances of `T`. +/// +/// # Initialization invariant +/// +/// The compiler, in general, assumes that a variable is properly initialized +/// according to the requirements of the variable's type. For example, a variable of +/// reference type must be aligned and non-null. This is an invariant that must +/// *always* be upheld, even in unsafe code. As a consequence, zero-initializing a +/// variable of reference type causes instantaneous [undefined behavior][ub], +/// no matter whether that reference ever gets used to access memory: +/// +/// ```rust,no_run +/// # #![allow(invalid_value)] +/// use std::mem::{self, MaybeUninit}; +/// +/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! ⚠️ +/// // The equivalent code with `MaybeUninit<&i32>`: +/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior! ⚠️ +/// ``` +/// +/// This is exploited by the compiler for various optimizations, such as eliding +/// run-time checks and optimizing `enum` layout. +/// +/// Similarly, entirely uninitialized memory may have any content, while a `bool` must +/// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior: +/// +/// ```rust,no_run +/// # #![allow(invalid_value)] +/// use std::mem::{self, MaybeUninit}; +/// +/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️ +/// // The equivalent code with `MaybeUninit`: +/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️ +/// ``` +/// +/// Moreover, uninitialized memory is special in that it does not have a fixed value ("fixed" +/// meaning "it won't change without being written to"). Reading the same uninitialized byte +/// multiple times can give different results. This makes it undefined behavior to have +/// uninitialized data in a variable even if that variable has an integer type, which otherwise can +/// hold any *fixed* bit pattern: +/// +/// ```rust,no_run +/// # #![allow(invalid_value)] +/// use std::mem::{self, MaybeUninit}; +/// +/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️ +/// // The equivalent code with `MaybeUninit`: +/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️ +/// ``` +/// On top of that, remember that most types have additional invariants beyond merely +/// being considered initialized at the type level. For example, a `1`-initialized [`Vec`] +/// is considered initialized (under the current implementation; this does not constitute +/// a stable guarantee) because the only requirement the compiler knows about it +/// is that the data pointer must be non-null. Creating such a `Vec` does not cause +/// *immediate* undefined behavior, but will cause undefined behavior with most +/// safe operations (including dropping it). +/// +/// [`Vec`]: ../../std/vec/struct.Vec.html +/// +/// # Examples +/// +/// `MaybeUninit` serves to enable unsafe code to deal with uninitialized data. +/// It is a signal to the compiler indicating that the data here might *not* +/// be initialized: +/// +/// ```rust +/// use std::mem::MaybeUninit; +/// +/// // Create an explicitly uninitialized reference. The compiler knows that data inside +/// // a `MaybeUninit` may be invalid, and hence this is not UB: +/// let mut x = MaybeUninit::<&i32>::uninit(); +/// // Set it to a valid value. +/// x.write(&0); +/// // Extract the initialized data -- this is only allowed *after* properly +/// // initializing `x`! +/// let x = unsafe { x.assume_init() }; +/// ``` +/// +/// The compiler then knows to not make any incorrect assumptions or optimizations on this code. +/// +/// You can think of `MaybeUninit` as being a bit like `Option` but without +/// any of the run-time tracking and without any of the safety checks. +/// +/// ## out-pointers +/// +/// You can use `MaybeUninit` to implement "out-pointers": instead of returning data +/// from a function, pass it a pointer to some (uninitialized) memory to put the +/// result into. This can be useful when it is important for the caller to control +/// how the memory the result is stored in gets allocated, and you want to avoid +/// unnecessary moves. +/// +/// ``` +/// use std::mem::MaybeUninit; +/// +/// unsafe fn make_vec(out: *mut Vec) { +/// // `write` does not drop the old contents, which is important. +/// out.write(vec![1, 2, 3]); +/// } +/// +/// let mut v = MaybeUninit::uninit(); +/// unsafe { make_vec(v.as_mut_ptr()); } +/// // Now we know `v` is initialized! This also makes sure the vector gets +/// // properly dropped. +/// let v = unsafe { v.assume_init() }; +/// assert_eq!(&v, &[1, 2, 3]); +/// ``` +/// +/// ## Initializing an array element-by-element +/// +/// `MaybeUninit` can be used to initialize a large array element-by-element: +/// +/// ``` +/// use std::mem::{self, MaybeUninit}; +/// +/// let data = { +/// // Create an uninitialized array of `MaybeUninit`. +/// let mut data: [MaybeUninit>; 1000] = [const { MaybeUninit::uninit() }; 1000]; +/// +/// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop, +/// // we have a memory leak, but there is no memory safety issue. +/// for elem in &mut data[..] { +/// elem.write(vec![42]); +/// } +/// +/// // Everything is initialized. Transmute the array to the +/// // initialized type. +/// unsafe { mem::transmute::<_, [Vec; 1000]>(data) } +/// }; +/// +/// assert_eq!(&data[0], &[42]); +/// ``` +/// +/// You can also work with partially initialized arrays, which could +/// be found in low-level datastructures. +/// +/// ``` +/// use std::mem::MaybeUninit; +/// +/// // Create an uninitialized array of `MaybeUninit`. +/// let mut data: [MaybeUninit; 1000] = [const { MaybeUninit::uninit() }; 1000]; +/// // Count the number of elements we have assigned. +/// let mut data_len: usize = 0; +/// +/// for elem in &mut data[0..500] { +/// elem.write(String::from("hello")); +/// data_len += 1; +/// } +/// +/// // For each item in the array, drop if we allocated it. +/// for elem in &mut data[0..data_len] { +/// unsafe { elem.assume_init_drop(); } +/// } +/// ``` +/// +/// ## Initializing a struct field-by-field +/// +/// You can use `MaybeUninit`, and the [`std::ptr::addr_of_mut`] macro, to initialize structs field by field: +/// +/// ```rust +/// use std::mem::MaybeUninit; +/// use std::ptr::addr_of_mut; +/// +/// #[derive(Debug, PartialEq)] +/// pub struct Foo { +/// name: String, +/// list: Vec, +/// } +/// +/// let foo = { +/// let mut uninit: MaybeUninit = MaybeUninit::uninit(); +/// let ptr = uninit.as_mut_ptr(); +/// +/// // Initializing the `name` field +/// // Using `write` instead of assignment via `=` to not call `drop` on the +/// // old, uninitialized value. +/// unsafe { addr_of_mut!((*ptr).name).write("Bob".to_string()); } +/// +/// // Initializing the `list` field +/// // If there is a panic here, then the `String` in the `name` field leaks. +/// unsafe { addr_of_mut!((*ptr).list).write(vec![0, 1, 2]); } +/// +/// // All the fields are initialized, so we call `assume_init` to get an initialized Foo. +/// unsafe { uninit.assume_init() } +/// }; +/// +/// assert_eq!( +/// foo, +/// Foo { +/// name: "Bob".to_string(), +/// list: vec![0, 1, 2] +/// } +/// ); +/// ``` +/// [`std::ptr::addr_of_mut`]: crate::ptr::addr_of_mut +/// [ub]: ../../reference/behavior-considered-undefined.html +/// +/// # Layout +/// +/// `MaybeUninit` is guaranteed to have the same size, alignment, and ABI as `T`: +/// +/// ```rust +/// use std::mem::{MaybeUninit, size_of, align_of}; +/// assert_eq!(size_of::>(), size_of::()); +/// assert_eq!(align_of::>(), align_of::()); +/// ``` +/// +/// However remember that a type *containing* a `MaybeUninit` is not necessarily the same +/// layout; Rust does not in general guarantee that the fields of a `Foo` have the same order as +/// a `Foo` even if `T` and `U` have the same size and alignment. Furthermore because any bit +/// value is valid for a `MaybeUninit` the compiler can't apply non-zero/niche-filling +/// optimizations, potentially resulting in a larger size: +/// +/// ```rust +/// # use std::mem::{MaybeUninit, size_of}; +/// assert_eq!(size_of::>(), 1); +/// assert_eq!(size_of::>>(), 2); +/// ``` +/// +/// If `T` is FFI-safe, then so is `MaybeUninit`. +/// +/// While `MaybeUninit` is `#[repr(transparent)]` (indicating it guarantees the same size, +/// alignment, and ABI as `T`), this does *not* change any of the previous caveats. `Option` and +/// `Option>` may still have different sizes, and types containing a field of type +/// `T` may be laid out (and sized) differently than if that field were `MaybeUninit`. +/// `MaybeUninit` is a union type, and `#[repr(transparent)]` on unions is unstable (see [the +/// tracking issue](https://github.com/rust-lang/rust/issues/60405)). Over time, the exact +/// guarantees of `#[repr(transparent)]` on unions may evolve, and `MaybeUninit` may or may not +/// remain `#[repr(transparent)]`. That said, `MaybeUninit` will *always* guarantee that it has +/// the same size, alignment, and ABI as `T`; it's just that the way `MaybeUninit` implements that +/// guarantee may evolve. +#[stable(feature = "maybe_uninit", since = "1.36.0")] +// Lang item so we can wrap other types in it. This is useful for coroutines. +#[lang = "maybe_uninit"] +#[derive(Copy)] +#[repr(transparent)] +#[rustc_pub_transparent] +pub union MaybeUninit { + uninit: (), + value: ManuallyDrop, +} + +#[stable(feature = "maybe_uninit", since = "1.36.0")] +impl Clone for MaybeUninit { + #[inline(always)] + fn clone(&self) -> Self { + // Not calling `T::clone()`, we cannot know if we are initialized enough for that. + *self + } +} + +#[stable(feature = "maybe_uninit_debug", since = "1.41.0")] +impl fmt::Debug for MaybeUninit { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // NB: there is no `.pad_fmt` so we can't use a simpler `format_args!("MaybeUninit<{..}>"). + // This needs to be adjusted if `MaybeUninit` moves modules. + let full_name = type_name::(); + let short_name = full_name.split_once("mem::maybe_uninit::").unwrap().1; + f.pad(short_name) + } +} + +impl MaybeUninit { + /// Creates a new `MaybeUninit` initialized with the given value. + /// It is safe to call [`assume_init`] on the return value of this function. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + /// + /// # Example + /// + /// ``` + /// use std::mem::MaybeUninit; + /// + /// let v: MaybeUninit> = MaybeUninit::new(vec![42]); + /// # // Prevent leaks for Miri + /// # unsafe { let _ = MaybeUninit::assume_init(v); } + /// ``` + /// + /// [`assume_init`]: MaybeUninit::assume_init + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] + #[must_use = "use `forget` to avoid running Drop code"] + #[inline(always)] + pub const fn new(val: T) -> MaybeUninit { + MaybeUninit { value: ManuallyDrop::new(val) } + } + + /// Creates a new `MaybeUninit` in an uninitialized state. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + /// + /// See the [type-level documentation][MaybeUninit] for some examples. + /// + /// # Example + /// + /// ``` + /// use std::mem::MaybeUninit; + /// + /// let v: MaybeUninit = MaybeUninit::uninit(); + /// ``` + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] + #[must_use] + #[inline(always)] + #[rustc_diagnostic_item = "maybe_uninit_uninit"] + pub const fn uninit() -> MaybeUninit { + MaybeUninit { uninit: () } + } + + /// Creates a new array of `MaybeUninit` items, in an uninitialized state. + /// + /// Note: in a future Rust version this method may become unnecessary + /// when Rust allows + /// [inline const expressions](https://github.com/rust-lang/rust/issues/76001). + /// The example below could then use `let mut buf = [const { MaybeUninit::::uninit() }; 32];`. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(maybe_uninit_uninit_array, maybe_uninit_slice)] + /// + /// use std::mem::MaybeUninit; + /// + /// extern "C" { + /// fn read_into_buffer(ptr: *mut u8, max_len: usize) -> usize; + /// } + /// + /// /// Returns a (possibly smaller) slice of data that was actually read + /// fn read(buf: &mut [MaybeUninit]) -> &[u8] { + /// unsafe { + /// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len()); + /// MaybeUninit::slice_assume_init_ref(&buf[..len]) + /// } + /// } + /// + /// let mut buf: [MaybeUninit; 32] = MaybeUninit::uninit_array(); + /// let data = read(&mut buf); + /// ``` + #[unstable(feature = "maybe_uninit_uninit_array", issue = "96097")] + #[must_use] + #[inline(always)] + pub const fn uninit_array() -> [Self; N] { + [const { MaybeUninit::uninit() }; N] + } + + /// Creates a new `MaybeUninit` in an uninitialized state, with the memory being + /// filled with `0` bytes. It depends on `T` whether that already makes for + /// proper initialization. For example, `MaybeUninit::zeroed()` is initialized, + /// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not + /// be null. + /// + /// Note that if `T` has padding bytes, those bytes are *not* preserved when the + /// `MaybeUninit` value is returned from this function, so those bytes will *not* be zeroed. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + /// + /// # Example + /// + /// Correct usage of this function: initializing a struct with zero, where all + /// fields of the struct can hold the bit-pattern 0 as a valid value. + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let x = MaybeUninit::<(u8, bool)>::zeroed(); + /// let x = unsafe { x.assume_init() }; + /// assert_eq!(x, (0, false)); + /// ``` + /// + /// This can be used in const contexts, such as to indicate the end of static arrays for + /// plugin registration. + /// + /// *Incorrect* usage of this function: calling `x.zeroed().assume_init()` + /// when `0` is not a valid bit-pattern for the type: + /// + /// ```rust,no_run + /// use std::mem::MaybeUninit; + /// + /// enum NotZero { One = 1, Two = 2 } + /// + /// let x = MaybeUninit::<(u8, NotZero)>::zeroed(); + /// let x = unsafe { x.assume_init() }; + /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. + /// // This is undefined behavior. ⚠️ + /// ``` + #[inline] + #[must_use] + #[rustc_diagnostic_item = "maybe_uninit_zeroed"] + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_zeroed", since = "1.75.0")] + pub const fn zeroed() -> MaybeUninit { + let mut u = MaybeUninit::::uninit(); + // SAFETY: `u.as_mut_ptr()` points to allocated memory. + unsafe { u.as_mut_ptr().write_bytes(0u8, 1) }; + u + } + + /// Sets the value of the `MaybeUninit`. + /// + /// This overwrites any previous value without dropping it, so be careful + /// not to use this twice unless you want to skip running the destructor. + /// For your convenience, this also returns a mutable reference to the + /// (now safely initialized) contents of `self`. + /// + /// As the content is stored inside a `MaybeUninit`, the destructor is not + /// run for the inner data if the MaybeUninit leaves scope without a call to + /// [`assume_init`], [`assume_init_drop`], or similar. Code that receives + /// the mutable reference returned by this function needs to keep this in + /// mind. The safety model of Rust regards leaks as safe, but they are + /// usually still undesirable. This being said, the mutable reference + /// behaves like any other mutable reference would, so assigning a new value + /// to it will drop the old content. + /// + /// [`assume_init`]: Self::assume_init + /// [`assume_init_drop`]: Self::assume_init_drop + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::>::uninit(); + /// + /// { + /// let hello = x.write((&b"Hello, world!").to_vec()); + /// // Setting hello does not leak prior allocations, but drops them + /// *hello = (&b"Hello").to_vec(); + /// hello[0] = 'h' as u8; + /// } + /// // x is initialized now: + /// let s = unsafe { x.assume_init() }; + /// assert_eq!(b"hello", s.as_slice()); + /// ``` + /// + /// This usage of the method causes a leak: + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::::uninit(); + /// + /// x.write("Hello".to_string()); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # unsafe { MaybeUninit::assume_init_drop(&mut x); } + /// // This leaks the contained string: + /// x.write("hello".to_string()); + /// // x is initialized now: + /// let s = unsafe { x.assume_init() }; + /// ``` + /// + /// This method can be used to avoid unsafe in some cases. The example below + /// shows a part of an implementation of a fixed sized arena that lends out + /// pinned references. + /// With `write`, we can avoid the need to write through a raw pointer: + /// + /// ```rust + /// use core::pin::Pin; + /// use core::mem::MaybeUninit; + /// + /// struct PinArena { + /// memory: Box<[MaybeUninit]>, + /// len: usize, + /// } + /// + /// impl PinArena { + /// pub fn capacity(&self) -> usize { + /// self.memory.len() + /// } + /// pub fn push(&mut self, val: T) -> Pin<&mut T> { + /// if self.len >= self.capacity() { + /// panic!("Attempted to push to a full pin arena!"); + /// } + /// let ref_ = self.memory[self.len].write(val); + /// self.len += 1; + /// unsafe { Pin::new_unchecked(ref_) } + /// } + /// } + /// ``` + #[inline(always)] + #[stable(feature = "maybe_uninit_write", since = "1.55.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_write", since = "CURRENT_RUSTC_VERSION")] + pub const fn write(&mut self, val: T) -> &mut T { + *self = MaybeUninit::new(val); + // SAFETY: We just initialized this value. + unsafe { self.assume_init_mut() } + } + + /// Gets a pointer to the contained value. Reading from this pointer or turning it + /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. + /// Writing to memory that this pointer (non-transitively) points to is undefined behavior + /// (except inside an `UnsafeCell`). + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::>::uninit(); + /// x.write(vec![0, 1, 2]); + /// // Create a reference into the `MaybeUninit`. This is okay because we initialized it. + /// let x_vec = unsafe { &*x.as_ptr() }; + /// assert_eq!(x_vec.len(), 3); + /// # // Prevent leaks for Miri + /// # unsafe { MaybeUninit::assume_init_drop(&mut x); } + /// ``` + /// + /// *Incorrect* usage of this method: + /// + /// ```rust,no_run + /// use std::mem::MaybeUninit; + /// + /// let x = MaybeUninit::>::uninit(); + /// let x_vec = unsafe { &*x.as_ptr() }; + /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ + /// ``` + /// + /// (Notice that the rules around references to uninitialized data are not finalized yet, but + /// until they are, it is advisable to avoid them.) + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_as_ptr", since = "1.59.0")] + #[rustc_as_ptr] + #[inline(always)] + pub const fn as_ptr(&self) -> *const T { + // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. + self as *const _ as *const T + } + + /// Gets a mutable pointer to the contained value. Reading from this pointer or turning it + /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::>::uninit(); + /// x.write(vec![0, 1, 2]); + /// // Create a reference into the `MaybeUninit>`. + /// // This is okay because we initialized it. + /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; + /// x_vec.push(3); + /// assert_eq!(x_vec.len(), 4); + /// # // Prevent leaks for Miri + /// # unsafe { MaybeUninit::assume_init_drop(&mut x); } + /// ``` + /// + /// *Incorrect* usage of this method: + /// + /// ```rust,no_run + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::>::uninit(); + /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; + /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ + /// ``` + /// + /// (Notice that the rules around references to uninitialized data are not finalized yet, but + /// until they are, it is advisable to avoid them.) + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_as_mut_ptr", since = "1.83.0")] + #[rustc_as_ptr] + #[inline(always)] + pub const fn as_mut_ptr(&mut self) -> *mut T { + // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. + self as *mut _ as *mut T + } + + /// Extracts the value from the `MaybeUninit` container. This is a great way + /// to ensure that the data will get dropped, because the resulting `T` is + /// subject to the usual drop handling. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized + /// state. Calling this when the content is not yet fully initialized causes immediate undefined + /// behavior. The [type-level documentation][inv] contains more information about + /// this initialization invariant. + /// + /// [inv]: #initialization-invariant + /// + /// On top of that, remember that most types have additional invariants beyond merely + /// being considered initialized at the type level. For example, a `1`-initialized [`Vec`] + /// is considered initialized (under the current implementation; this does not constitute + /// a stable guarantee) because the only requirement the compiler knows about it + /// is that the data pointer must be non-null. Creating such a `Vec` does not cause + /// *immediate* undefined behavior, but will cause undefined behavior with most + /// safe operations (including dropping it). + /// + /// [`Vec`]: ../../std/vec/struct.Vec.html + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::::uninit(); + /// x.write(true); + /// let x_init = unsafe { x.assume_init() }; + /// assert_eq!(x_init, true); + /// ``` + /// + /// *Incorrect* usage of this method: + /// + /// ```rust,no_run + /// use std::mem::MaybeUninit; + /// + /// let x = MaybeUninit::>::uninit(); + /// let x_init = unsafe { x.assume_init() }; + /// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️ + /// ``` + #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_assume_init_by_value", since = "1.59.0")] + #[inline(always)] + #[rustc_diagnostic_item = "assume_init"] + #[track_caller] + pub const unsafe fn assume_init(self) -> T { + // SAFETY: the caller must guarantee that `self` is initialized. + // This also means that `self` must be a `value` variant. + unsafe { + intrinsics::assert_inhabited::(); + ManuallyDrop::into_inner(self.value) + } + } + + /// Reads the value from the `MaybeUninit` container. The resulting `T` is subject + /// to the usual drop handling. + /// + /// Whenever possible, it is preferable to use [`assume_init`] instead, which + /// prevents duplicating the content of the `MaybeUninit`. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized + /// state. Calling this when the content is not yet fully initialized causes undefined + /// behavior. The [type-level documentation][inv] contains more information about + /// this initialization invariant. + /// + /// Moreover, similar to the [`ptr::read`] function, this function creates a + /// bitwise copy of the contents, regardless whether the contained type + /// implements the [`Copy`] trait or not. When using multiple copies of the + /// data (by calling `assume_init_read` multiple times, or first calling + /// `assume_init_read` and then [`assume_init`]), it is your responsibility + /// to ensure that data may indeed be duplicated. + /// + /// [inv]: #initialization-invariant + /// [`assume_init`]: MaybeUninit::assume_init + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::::uninit(); + /// x.write(13); + /// let x1 = unsafe { x.assume_init_read() }; + /// // `u32` is `Copy`, so we may read multiple times. + /// let x2 = unsafe { x.assume_init_read() }; + /// assert_eq!(x1, x2); + /// + /// let mut x = MaybeUninit::>>::uninit(); + /// x.write(None); + /// let x1 = unsafe { x.assume_init_read() }; + /// // Duplicating a `None` value is okay, so we may read multiple times. + /// let x2 = unsafe { x.assume_init_read() }; + /// assert_eq!(x1, x2); + /// ``` + /// + /// *Incorrect* usage of this method: + /// + /// ```rust,no_run + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::>>::uninit(); + /// x.write(Some(vec![0, 1, 2])); + /// let x1 = unsafe { x.assume_init_read() }; + /// let x2 = unsafe { x.assume_init_read() }; + /// // We now created two copies of the same vector, leading to a double-free ⚠️ when + /// // they both get dropped! + /// ``` + #[stable(feature = "maybe_uninit_extra", since = "1.60.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_assume_init_read", since = "1.75.0")] + #[inline(always)] + #[track_caller] + pub const unsafe fn assume_init_read(&self) -> T { + // SAFETY: the caller must guarantee that `self` is initialized. + // Reading from `self.as_ptr()` is safe since `self` should be initialized. + unsafe { + intrinsics::assert_inhabited::(); + self.as_ptr().read() + } + } + + /// Drops the contained value in place. + /// + /// If you have ownership of the `MaybeUninit`, you can also use + /// [`assume_init`] as an alternative. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` really is + /// in an initialized state. Calling this when the content is not yet fully + /// initialized causes undefined behavior. + /// + /// On top of that, all additional invariants of the type `T` must be + /// satisfied, as the `Drop` implementation of `T` (or its members) may + /// rely on this. For example, setting a [`Vec`] to an invalid but + /// non-null address makes it initialized (under the current implementation; + /// this does not constitute a stable guarantee), because the only + /// requirement the compiler knows about it is that the data pointer must be + /// non-null. Dropping such a `Vec` however will cause undefined + /// behavior. + /// + /// [`assume_init`]: MaybeUninit::assume_init + /// [`Vec`]: ../../std/vec/struct.Vec.html + #[stable(feature = "maybe_uninit_extra", since = "1.60.0")] + pub unsafe fn assume_init_drop(&mut self) { + // SAFETY: the caller must guarantee that `self` is initialized and + // satisfies all invariants of `T`. + // Dropping the value in place is safe if that is the case. + unsafe { ptr::drop_in_place(self.as_mut_ptr()) } + } + + /// Gets a shared reference to the contained value. + /// + /// This can be useful when we want to access a `MaybeUninit` that has been + /// initialized but don't have ownership of the `MaybeUninit` (preventing the use + /// of `.assume_init()`). + /// + /// # Safety + /// + /// Calling this when the content is not yet fully initialized causes undefined + /// behavior: it is up to the caller to guarantee that the `MaybeUninit` really + /// is in an initialized state. + /// + /// # Examples + /// + /// ### Correct usage of this method: + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::>::uninit(); + /// # let mut x_mu = x; + /// # let mut x = &mut x_mu; + /// // Initialize `x`: + /// x.write(vec![1, 2, 3]); + /// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to + /// // create a shared reference to it: + /// let x: &Vec = unsafe { + /// // SAFETY: `x` has been initialized. + /// x.assume_init_ref() + /// }; + /// assert_eq!(x, &vec![1, 2, 3]); + /// # // Prevent leaks for Miri + /// # unsafe { MaybeUninit::assume_init_drop(&mut x_mu); } + /// ``` + /// + /// ### *Incorrect* usages of this method: + /// + /// ```rust,no_run + /// use std::mem::MaybeUninit; + /// + /// let x = MaybeUninit::>::uninit(); + /// let x_vec: &Vec = unsafe { x.assume_init_ref() }; + /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ + /// ``` + /// + /// ```rust,no_run + /// use std::{cell::Cell, mem::MaybeUninit}; + /// + /// let b = MaybeUninit::>::uninit(); + /// // Initialize the `MaybeUninit` using `Cell::set`: + /// unsafe { + /// b.assume_init_ref().set(true); + /// // ^^^^^^^^^^^^^^^ + /// // Reference to an uninitialized `Cell`: UB! + /// } + /// ``` + #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_assume_init_ref", since = "1.59.0")] + #[inline(always)] + pub const unsafe fn assume_init_ref(&self) -> &T { + // SAFETY: the caller must guarantee that `self` is initialized. + // This also means that `self` must be a `value` variant. + unsafe { + intrinsics::assert_inhabited::(); + &*self.as_ptr() + } + } + + /// Gets a mutable (unique) reference to the contained value. + /// + /// This can be useful when we want to access a `MaybeUninit` that has been + /// initialized but don't have ownership of the `MaybeUninit` (preventing the use + /// of `.assume_init()`). + /// + /// # Safety + /// + /// Calling this when the content is not yet fully initialized causes undefined + /// behavior: it is up to the caller to guarantee that the `MaybeUninit` really + /// is in an initialized state. For instance, `.assume_init_mut()` cannot be used to + /// initialize a `MaybeUninit`. + /// + /// # Examples + /// + /// ### Correct usage of this method: + /// + /// ```rust + /// # #![allow(unexpected_cfgs)] + /// use std::mem::MaybeUninit; + /// + /// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 1024]) { *buf = [0; 1024] } + /// # #[cfg(FALSE)] + /// extern "C" { + /// /// Initializes *all* the bytes of the input buffer. + /// fn initialize_buffer(buf: *mut [u8; 1024]); + /// } + /// + /// let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); + /// + /// // Initialize `buf`: + /// unsafe { initialize_buffer(buf.as_mut_ptr()); } + /// // Now we know that `buf` has been initialized, so we could `.assume_init()` it. + /// // However, using `.assume_init()` may trigger a `memcpy` of the 1024 bytes. + /// // To assert our buffer has been initialized without copying it, we upgrade + /// // the `&mut MaybeUninit<[u8; 1024]>` to a `&mut [u8; 1024]`: + /// let buf: &mut [u8; 1024] = unsafe { + /// // SAFETY: `buf` has been initialized. + /// buf.assume_init_mut() + /// }; + /// + /// // Now we can use `buf` as a normal slice: + /// buf.sort_unstable(); + /// assert!( + /// buf.windows(2).all(|pair| pair[0] <= pair[1]), + /// "buffer is sorted", + /// ); + /// ``` + /// + /// ### *Incorrect* usages of this method: + /// + /// You cannot use `.assume_init_mut()` to initialize a value: + /// + /// ```rust,no_run + /// use std::mem::MaybeUninit; + /// + /// let mut b = MaybeUninit::::uninit(); + /// unsafe { + /// *b.assume_init_mut() = true; + /// // We have created a (mutable) reference to an uninitialized `bool`! + /// // This is undefined behavior. ⚠️ + /// } + /// ``` + /// + /// For instance, you cannot [`Read`] into an uninitialized buffer: + /// + /// [`Read`]: ../../std/io/trait.Read.html + /// + /// ```rust,no_run + /// use std::{io, mem::MaybeUninit}; + /// + /// fn read_chunk (reader: &'_ mut dyn io::Read) -> io::Result<[u8; 64]> + /// { + /// let mut buffer = MaybeUninit::<[u8; 64]>::uninit(); + /// reader.read_exact(unsafe { buffer.assume_init_mut() })?; + /// // ^^^^^^^^^^^^^^^^^^^^^^^^ + /// // (mutable) reference to uninitialized memory! + /// // This is undefined behavior. + /// Ok(unsafe { buffer.assume_init() }) + /// } + /// ``` + /// + /// Nor can you use direct field access to do field-by-field gradual initialization: + /// + /// ```rust,no_run + /// use std::{mem::MaybeUninit, ptr}; + /// + /// struct Foo { + /// a: u32, + /// b: u8, + /// } + /// + /// let foo: Foo = unsafe { + /// let mut foo = MaybeUninit::::uninit(); + /// ptr::write(&mut foo.assume_init_mut().a as *mut u32, 1337); + /// // ^^^^^^^^^^^^^^^^^^^^^ + /// // (mutable) reference to uninitialized memory! + /// // This is undefined behavior. + /// ptr::write(&mut foo.assume_init_mut().b as *mut u8, 42); + /// // ^^^^^^^^^^^^^^^^^^^^^ + /// // (mutable) reference to uninitialized memory! + /// // This is undefined behavior. + /// foo.assume_init() + /// }; + /// ``` + #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.84.0")] + #[inline(always)] + pub const unsafe fn assume_init_mut(&mut self) -> &mut T { + // SAFETY: the caller must guarantee that `self` is initialized. + // This also means that `self` must be a `value` variant. + unsafe { + intrinsics::assert_inhabited::(); + &mut *self.as_mut_ptr() + } + } + + /// Extracts the values from an array of `MaybeUninit` containers. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that all elements of the array are + /// in an initialized state. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_array_assume_init)] + /// use std::mem::MaybeUninit; + /// + /// let mut array: [MaybeUninit; 3] = [MaybeUninit::uninit(); 3]; + /// array[0].write(0); + /// array[1].write(1); + /// array[2].write(2); + /// + /// // SAFETY: Now safe as we initialised all elements + /// let array = unsafe { + /// MaybeUninit::array_assume_init(array) + /// }; + /// + /// assert_eq!(array, [0, 1, 2]); + /// ``` + #[unstable(feature = "maybe_uninit_array_assume_init", issue = "96097")] + #[inline(always)] + #[track_caller] + pub const unsafe fn array_assume_init(array: [Self; N]) -> [T; N] { + // SAFETY: + // * The caller guarantees that all elements of the array are initialized + // * `MaybeUninit` and T are guaranteed to have the same layout + // * `MaybeUninit` does not drop, so there are no double-frees + // And thus the conversion is safe + unsafe { + intrinsics::assert_inhabited::<[T; N]>(); + intrinsics::transmute_unchecked(array) + } + } + + /// Assuming all the elements are initialized, get a slice to them. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` elements + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized causes undefined behavior. + /// + /// See [`assume_init_ref`] for more details and examples. + /// + /// [`assume_init_ref`]: MaybeUninit::assume_init_ref + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] + #[inline(always)] + pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] { + // SAFETY: casting `slice` to a `*const [T]` is safe since the caller guarantees that + // `slice` is initialized, and `MaybeUninit` is guaranteed to have the same layout as `T`. + // The pointer obtained is valid since it refers to memory owned by `slice` which is a + // reference and thus guaranteed to be valid for reads. + unsafe { &*(slice as *const [Self] as *const [T]) } + } + + /// Assuming all the elements are initialized, get a mutable slice to them. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` elements + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized causes undefined behavior. + /// + /// See [`assume_init_mut`] for more details and examples. + /// + /// [`assume_init_mut`]: MaybeUninit::assume_init_mut + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] + #[inline(always)] + pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] { + // SAFETY: similar to safety notes for `slice_get_ref`, but we have a + // mutable reference which is also guaranteed to be valid for writes. + unsafe { &mut *(slice as *mut [Self] as *mut [T]) } + } + + /// Gets a pointer to the first element of the array. + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] + #[inline(always)] + pub const fn slice_as_ptr(this: &[MaybeUninit]) -> *const T { + this.as_ptr() as *const T + } + + /// Gets a mutable pointer to the first element of the array. + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] + #[inline(always)] + pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit]) -> *mut T { + this.as_mut_ptr() as *mut T + } + + /// Copies the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`. + /// + /// If `T` does not implement `Copy`, use [`clone_from_slice`] + /// + /// This is similar to [`slice::copy_from_slice`]. + /// + /// # Panics + /// + /// This function will panic if the two slices have different lengths. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_write_slice)] + /// use std::mem::MaybeUninit; + /// + /// let mut dst = [MaybeUninit::uninit(); 32]; + /// let src = [0; 32]; + /// + /// let init = MaybeUninit::copy_from_slice(&mut dst, &src); + /// + /// assert_eq!(init, src); + /// ``` + /// + /// ``` + /// #![feature(maybe_uninit_write_slice)] + /// use std::mem::MaybeUninit; + /// + /// let mut vec = Vec::with_capacity(32); + /// let src = [0; 16]; + /// + /// MaybeUninit::copy_from_slice(&mut vec.spare_capacity_mut()[..src.len()], &src); + /// + /// // SAFETY: we have just copied all the elements of len into the spare capacity + /// // the first src.len() elements of the vec are valid now. + /// unsafe { + /// vec.set_len(src.len()); + /// } + /// + /// assert_eq!(vec, src); + /// ``` + /// + /// [`clone_from_slice`]: MaybeUninit::clone_from_slice + #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")] + pub fn copy_from_slice<'a>(this: &'a mut [MaybeUninit], src: &[T]) -> &'a mut [T] + where + T: Copy, + { + // SAFETY: &[T] and &[MaybeUninit] have the same layout + let uninit_src: &[MaybeUninit] = unsafe { super::transmute(src) }; + + this.copy_from_slice(uninit_src); + + // SAFETY: Valid elements have just been copied into `this` so it is initialized + unsafe { MaybeUninit::slice_assume_init_mut(this) } + } + + /// Clones the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`. + /// Any already initialized elements will not be dropped. + /// + /// If `T` implements `Copy`, use [`copy_from_slice`] + /// + /// This is similar to [`slice::clone_from_slice`] but does not drop existing elements. + /// + /// # Panics + /// + /// This function will panic if the two slices have different lengths, or if the implementation of `Clone` panics. + /// + /// If there is a panic, the already cloned elements will be dropped. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_write_slice)] + /// use std::mem::MaybeUninit; + /// + /// let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()]; + /// let src = ["wibbly".to_string(), "wobbly".to_string(), "timey".to_string(), "wimey".to_string(), "stuff".to_string()]; + /// + /// let init = MaybeUninit::clone_from_slice(&mut dst, &src); + /// + /// assert_eq!(init, src); + /// # // Prevent leaks for Miri + /// # unsafe { std::ptr::drop_in_place(init); } + /// ``` + /// + /// ``` + /// #![feature(maybe_uninit_write_slice)] + /// use std::mem::MaybeUninit; + /// + /// let mut vec = Vec::with_capacity(32); + /// let src = ["rust", "is", "a", "pretty", "cool", "language"]; + /// + /// MaybeUninit::clone_from_slice(&mut vec.spare_capacity_mut()[..src.len()], &src); + /// + /// // SAFETY: we have just cloned all the elements of len into the spare capacity + /// // the first src.len() elements of the vec are valid now. + /// unsafe { + /// vec.set_len(src.len()); + /// } + /// + /// assert_eq!(vec, src); + /// ``` + /// + /// [`copy_from_slice`]: MaybeUninit::copy_from_slice + #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")] + pub fn clone_from_slice<'a>(this: &'a mut [MaybeUninit], src: &[T]) -> &'a mut [T] + where + T: Clone, + { + // unlike copy_from_slice this does not call clone_from_slice on the slice + // this is because `MaybeUninit` does not implement Clone. + + assert_eq!(this.len(), src.len(), "destination and source slices have different lengths"); + // NOTE: We need to explicitly slice them to the same length + // for bounds checking to be elided, and the optimizer will + // generate memcpy for simple cases (for example T = u8). + let len = this.len(); + let src = &src[..len]; + + // guard is needed b/c panic might happen during a clone + let mut guard = Guard { slice: this, initialized: 0 }; + + for i in 0..len { + guard.slice[i].write(src[i].clone()); + guard.initialized += 1; + } + + super::forget(guard); + + // SAFETY: Valid elements have just been written into `this` so it is initialized + unsafe { MaybeUninit::slice_assume_init_mut(this) } + } + + /// Fills `this` with elements by cloning `value`, returning a mutable reference to the now + /// initialized contents of `this`. + /// Any previously initialized elements will not be dropped. + /// + /// This is similar to [`slice::fill`]. + /// + /// # Panics + /// + /// This function will panic if any call to `Clone` panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// Fill an uninit vec with 1. + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = vec![MaybeUninit::uninit(); 10]; + /// let initialized = MaybeUninit::fill(buf.as_mut_slice(), 1); + /// assert_eq!(initialized, &mut [1; 10]); + /// ``` + #[doc(alias = "memset")] + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn fill<'a>(this: &'a mut [MaybeUninit], value: T) -> &'a mut [T] + where + T: Clone, + { + SpecFill::spec_fill(this, value); + // SAFETY: Valid elements have just been filled into `this` so it is initialized + unsafe { MaybeUninit::slice_assume_init_mut(this) } + } + + /// Fills `this` with elements returned by calling a closure repeatedly. + /// + /// This method uses a closure to create new values. If you'd rather `Clone` a given value, use + /// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can + /// pass [`Default::default`] as the argument. + /// + /// # Panics + /// + /// This function will panic if any call to the provided closure panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// Fill an uninit vec with the default value. + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = vec![MaybeUninit::::uninit(); 10]; + /// let initialized = MaybeUninit::fill_with(buf.as_mut_slice(), Default::default); + /// assert_eq!(initialized, &mut [0; 10]); + /// ``` + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn fill_with<'a, F>(this: &'a mut [MaybeUninit], mut f: F) -> &'a mut [T] + where + F: FnMut() -> T, + { + let mut guard = Guard { slice: this, initialized: 0 }; + + for element in guard.slice.iter_mut() { + element.write(f()); + guard.initialized += 1; + } + + super::forget(guard); + + // SAFETY: Valid elements have just been written into `this` so it is initialized + unsafe { MaybeUninit::slice_assume_init_mut(this) } + } + + /// Fills `this` with elements yielded by an iterator until either all elements have been + /// initialized or the iterator is empty. + /// + /// Returns two slices. The first slice contains the initialized portion of the original slice. + /// The second slice is the still-uninitialized remainder of the original slice. + /// + /// # Panics + /// + /// This function panics if the iterator's `next` function panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// Fill an uninit vec with a cycling iterator. + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = vec![MaybeUninit::uninit(); 5]; + /// + /// let iter = [1, 2, 3].into_iter().cycle(); + /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter); + /// + /// assert_eq!(initialized, &mut [1, 2, 3, 1, 2]); + /// assert_eq!(0, remainder.len()); + /// ``` + /// + /// Fill an uninit vec, but not completely. + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = vec![MaybeUninit::uninit(); 5]; + /// let iter = [1, 2]; + /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter); + /// + /// assert_eq!(initialized, &mut [1, 2]); + /// assert_eq!(remainder.len(), 3); + /// ``` + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn fill_from<'a, I>( + this: &'a mut [MaybeUninit], + it: I, + ) -> (&'a mut [T], &'a mut [MaybeUninit]) + where + I: IntoIterator, + { + let iter = it.into_iter(); + let mut guard = Guard { slice: this, initialized: 0 }; + + for (element, val) in guard.slice.iter_mut().zip(iter) { + element.write(val); + guard.initialized += 1; + } + + let initialized_len = guard.initialized; + super::forget(guard); + + // SAFETY: guard.initialized <= this.len() + let (initted, remainder) = unsafe { this.split_at_mut_unchecked(initialized_len) }; + + // SAFETY: Valid elements have just been written into `init`, so that portion + // of `this` is initialized. + (unsafe { MaybeUninit::slice_assume_init_mut(initted) }, remainder) + } + + /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. + /// + /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still + /// contain padding bytes which are left uninitialized. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_as_bytes, maybe_uninit_slice)] + /// use std::mem::MaybeUninit; + /// + /// let val = 0x12345678_i32; + /// let uninit = MaybeUninit::new(val); + /// let uninit_bytes = uninit.as_bytes(); + /// let bytes = unsafe { MaybeUninit::slice_assume_init_ref(uninit_bytes) }; + /// assert_eq!(bytes, val.to_ne_bytes()); + /// ``` + #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] + pub fn as_bytes(&self) -> &[MaybeUninit] { + // SAFETY: MaybeUninit is always valid, even for padding bytes + unsafe { + slice::from_raw_parts(self.as_ptr() as *const MaybeUninit, mem::size_of::()) + } + } + + /// Returns the contents of this `MaybeUninit` as a mutable slice of potentially uninitialized + /// bytes. + /// + /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still + /// contain padding bytes which are left uninitialized. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_as_bytes)] + /// use std::mem::MaybeUninit; + /// + /// let val = 0x12345678_i32; + /// let mut uninit = MaybeUninit::new(val); + /// let uninit_bytes = uninit.as_bytes_mut(); + /// if cfg!(target_endian = "little") { + /// uninit_bytes[0].write(0xcd); + /// } else { + /// uninit_bytes[3].write(0xcd); + /// } + /// let val2 = unsafe { uninit.assume_init() }; + /// assert_eq!(val2, 0x123456cd); + /// ``` + #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] + pub fn as_bytes_mut(&mut self) -> &mut [MaybeUninit] { + // SAFETY: MaybeUninit is always valid, even for padding bytes + unsafe { + slice::from_raw_parts_mut( + self.as_mut_ptr() as *mut MaybeUninit, + mem::size_of::(), + ) + } + } + + /// Returns the contents of this slice of `MaybeUninit` as a slice of potentially uninitialized + /// bytes. + /// + /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still + /// contain padding bytes which are left uninitialized. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_as_bytes, maybe_uninit_write_slice, maybe_uninit_slice)] + /// use std::mem::MaybeUninit; + /// + /// let uninit = [MaybeUninit::new(0x1234u16), MaybeUninit::new(0x5678u16)]; + /// let uninit_bytes = MaybeUninit::slice_as_bytes(&uninit); + /// let bytes = unsafe { MaybeUninit::slice_assume_init_ref(&uninit_bytes) }; + /// let val1 = u16::from_ne_bytes(bytes[0..2].try_into().unwrap()); + /// let val2 = u16::from_ne_bytes(bytes[2..4].try_into().unwrap()); + /// assert_eq!(&[val1, val2], &[0x1234u16, 0x5678u16]); + /// ``` + #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] + pub fn slice_as_bytes(this: &[MaybeUninit]) -> &[MaybeUninit] { + let bytes = mem::size_of_val(this); + // SAFETY: MaybeUninit is always valid, even for padding bytes + unsafe { slice::from_raw_parts(this.as_ptr() as *const MaybeUninit, bytes) } + } + + /// Returns the contents of this mutable slice of `MaybeUninit` as a mutable slice of + /// potentially uninitialized bytes. + /// + /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still + /// contain padding bytes which are left uninitialized. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_as_bytes, maybe_uninit_write_slice, maybe_uninit_slice)] + /// use std::mem::MaybeUninit; + /// + /// let mut uninit = [MaybeUninit::::uninit(), MaybeUninit::::uninit()]; + /// let uninit_bytes = MaybeUninit::slice_as_bytes_mut(&mut uninit); + /// MaybeUninit::copy_from_slice(uninit_bytes, &[0x12, 0x34, 0x56, 0x78]); + /// let vals = unsafe { MaybeUninit::slice_assume_init_ref(&uninit) }; + /// if cfg!(target_endian = "little") { + /// assert_eq!(vals, &[0x3412u16, 0x7856u16]); + /// } else { + /// assert_eq!(vals, &[0x1234u16, 0x5678u16]); + /// } + /// ``` + #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] + pub fn slice_as_bytes_mut(this: &mut [MaybeUninit]) -> &mut [MaybeUninit] { + let bytes = mem::size_of_val(this); + // SAFETY: MaybeUninit is always valid, even for padding bytes + unsafe { slice::from_raw_parts_mut(this.as_mut_ptr() as *mut MaybeUninit, bytes) } + } +} + +impl MaybeUninit<[T; N]> { + /// Transposes a `MaybeUninit<[T; N]>` into a `[MaybeUninit; N]`. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_uninit_array_transpose)] + /// # use std::mem::MaybeUninit; + /// + /// let data: [MaybeUninit; 1000] = MaybeUninit::uninit().transpose(); + /// ``` + #[unstable(feature = "maybe_uninit_uninit_array_transpose", issue = "96097")] + #[inline] + pub const fn transpose(self) -> [MaybeUninit; N] { + // SAFETY: T and MaybeUninit have the same layout + unsafe { intrinsics::transmute_unchecked(self) } + } +} + +impl [MaybeUninit; N] { + /// Transposes a `[MaybeUninit; N]` into a `MaybeUninit<[T; N]>`. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_uninit_array_transpose)] + /// # use std::mem::MaybeUninit; + /// + /// let data = [MaybeUninit::::uninit(); 1000]; + /// let data: MaybeUninit<[u8; 1000]> = data.transpose(); + /// ``` + #[unstable(feature = "maybe_uninit_uninit_array_transpose", issue = "96097")] + #[inline] + pub const fn transpose(self) -> MaybeUninit<[T; N]> { + // SAFETY: T and MaybeUninit have the same layout + unsafe { intrinsics::transmute_unchecked(self) } + } +} + +struct Guard<'a, T> { + slice: &'a mut [MaybeUninit], + initialized: usize, +} + +impl<'a, T> Drop for Guard<'a, T> { + fn drop(&mut self) { + let initialized_part = &mut self.slice[..self.initialized]; + // SAFETY: this raw sub-slice will contain only initialized objects. + unsafe { + crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(initialized_part)); + } + } +} + +trait SpecFill { + fn spec_fill(&mut self, value: T); +} + +impl SpecFill for [MaybeUninit] { + default fn spec_fill(&mut self, value: T) { + let mut guard = Guard { slice: self, initialized: 0 }; + + if let Some((last, elems)) = guard.slice.split_last_mut() { + for el in elems { + el.write(value.clone()); + guard.initialized += 1; + } + + last.write(value); + } + super::forget(guard); + } +} + +impl SpecFill for [MaybeUninit] { + fn spec_fill(&mut self, value: T) { + self.fill(MaybeUninit::new(value)); + } +} diff --git a/CoqOfRust/core/mem/mod.rs b/CoqOfRust/core/mem/mod.rs new file mode 100644 index 000000000..78ad68807 --- /dev/null +++ b/CoqOfRust/core/mem/mod.rs @@ -0,0 +1,1365 @@ +//! Basic functions for dealing with memory. +//! +//! This module contains functions for querying the size and alignment of +//! types, initializing and manipulating memory. + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::alloc::Layout; +use crate::marker::DiscriminantKind; +use crate::{clone, cmp, fmt, hash, intrinsics, ptr}; + +mod manually_drop; +#[stable(feature = "manually_drop", since = "1.20.0")] +pub use manually_drop::ManuallyDrop; + +mod maybe_uninit; +#[stable(feature = "maybe_uninit", since = "1.36.0")] +pub use maybe_uninit::MaybeUninit; + +mod transmutability; +#[unstable(feature = "transmutability", issue = "99571")] +pub use transmutability::{Assume, TransmuteFrom}; + +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(inline)] +pub use crate::intrinsics::transmute; + +/// Takes ownership and "forgets" about the value **without running its destructor**. +/// +/// Any resources the value manages, such as heap memory or a file handle, will linger +/// forever in an unreachable state. However, it does not guarantee that pointers +/// to this memory will remain valid. +/// +/// * If you want to leak memory, see [`Box::leak`]. +/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`]. +/// * If you want to dispose of a value properly, running its destructor, see +/// [`mem::drop`]. +/// +/// # Safety +/// +/// `forget` is not marked as `unsafe`, because Rust's safety guarantees +/// do not include a guarantee that destructors will always run. For example, +/// a program can create a reference cycle using [`Rc`][rc], or call +/// [`process::exit`][exit] to exit without running destructors. Thus, allowing +/// `mem::forget` from safe code does not fundamentally change Rust's safety +/// guarantees. +/// +/// That said, leaking resources such as memory or I/O objects is usually undesirable. +/// The need comes up in some specialized use cases for FFI or unsafe code, but even +/// then, [`ManuallyDrop`] is typically preferred. +/// +/// Because forgetting a value is allowed, any `unsafe` code you write must +/// allow for this possibility. You cannot return a value and expect that the +/// caller will necessarily run the value's destructor. +/// +/// [rc]: ../../std/rc/struct.Rc.html +/// [exit]: ../../std/process/fn.exit.html +/// +/// # Examples +/// +/// The canonical safe use of `mem::forget` is to circumvent a value's destructor +/// implemented by the `Drop` trait. For example, this will leak a `File`, i.e. reclaim +/// the space taken by the variable but never close the underlying system resource: +/// +/// ```no_run +/// use std::mem; +/// use std::fs::File; +/// +/// let file = File::open("foo.txt").unwrap(); +/// mem::forget(file); +/// ``` +/// +/// This is useful when the ownership of the underlying resource was previously +/// transferred to code outside of Rust, for example by transmitting the raw +/// file descriptor to C code. +/// +/// # Relationship with `ManuallyDrop` +/// +/// While `mem::forget` can also be used to transfer *memory* ownership, doing so is error-prone. +/// [`ManuallyDrop`] should be used instead. Consider, for example, this code: +/// +/// ``` +/// use std::mem; +/// +/// let mut v = vec![65, 122]; +/// // Build a `String` using the contents of `v` +/// let s = unsafe { String::from_raw_parts(v.as_mut_ptr(), v.len(), v.capacity()) }; +/// // leak `v` because its memory is now managed by `s` +/// mem::forget(v); // ERROR - v is invalid and must not be passed to a function +/// assert_eq!(s, "Az"); +/// // `s` is implicitly dropped and its memory deallocated. +/// ``` +/// +/// There are two issues with the above example: +/// +/// * If more code were added between the construction of `String` and the invocation of +/// `mem::forget()`, a panic within it would cause a double free because the same memory +/// is handled by both `v` and `s`. +/// * After calling `v.as_mut_ptr()` and transmitting the ownership of the data to `s`, +/// the `v` value is invalid. Even when a value is just moved to `mem::forget` (which won't +/// inspect it), some types have strict requirements on their values that +/// make them invalid when dangling or no longer owned. Using invalid values in any +/// way, including passing them to or returning them from functions, constitutes +/// undefined behavior and may break the assumptions made by the compiler. +/// +/// Switching to `ManuallyDrop` avoids both issues: +/// +/// ``` +/// use std::mem::ManuallyDrop; +/// +/// let v = vec![65, 122]; +/// // Before we disassemble `v` into its raw parts, make sure it +/// // does not get dropped! +/// let mut v = ManuallyDrop::new(v); +/// // Now disassemble `v`. These operations cannot panic, so there cannot be a leak. +/// let (ptr, len, cap) = (v.as_mut_ptr(), v.len(), v.capacity()); +/// // Finally, build a `String`. +/// let s = unsafe { String::from_raw_parts(ptr, len, cap) }; +/// assert_eq!(s, "Az"); +/// // `s` is implicitly dropped and its memory deallocated. +/// ``` +/// +/// `ManuallyDrop` robustly prevents double-free because we disable `v`'s destructor +/// before doing anything else. `mem::forget()` doesn't allow this because it consumes its +/// argument, forcing us to call it only after extracting anything we need from `v`. Even +/// if a panic were introduced between construction of `ManuallyDrop` and building the +/// string (which cannot happen in the code as shown), it would result in a leak and not a +/// double free. In other words, `ManuallyDrop` errs on the side of leaking instead of +/// erring on the side of (double-)dropping. +/// +/// Also, `ManuallyDrop` prevents us from having to "touch" `v` after transferring the +/// ownership to `s` — the final step of interacting with `v` to dispose of it without +/// running its destructor is entirely avoided. +/// +/// [`Box`]: ../../std/boxed/struct.Box.html +/// [`Box::leak`]: ../../std/boxed/struct.Box.html#method.leak +/// [`Box::into_raw`]: ../../std/boxed/struct.Box.html#method.into_raw +/// [`mem::drop`]: drop +/// [ub]: ../../reference/behavior-considered-undefined.html +#[inline] +#[rustc_const_stable(feature = "const_forget", since = "1.46.0")] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_forget")] +pub const fn forget(t: T) { + let _ = ManuallyDrop::new(t); +} + +/// Like [`forget`], but also accepts unsized values. +/// +/// This function is just a shim intended to be removed when the `unsized_locals` feature gets +/// stabilized. +#[inline] +#[unstable(feature = "forget_unsized", issue = "none")] +pub fn forget_unsized(t: T) { + intrinsics::forget(t) +} + +/// Returns the size of a type in bytes. +/// +/// More specifically, this is the offset in bytes between successive elements +/// in an array with that item type including alignment padding. Thus, for any +/// type `T` and length `n`, `[T; n]` has a size of `n * size_of::()`. +/// +/// In general, the size of a type is not stable across compilations, but +/// specific types such as primitives are. +/// +/// The following table gives the size for primitives. +/// +/// Type | `size_of::()` +/// ---- | --------------- +/// () | 0 +/// bool | 1 +/// u8 | 1 +/// u16 | 2 +/// u32 | 4 +/// u64 | 8 +/// u128 | 16 +/// i8 | 1 +/// i16 | 2 +/// i32 | 4 +/// i64 | 8 +/// i128 | 16 +/// f32 | 4 +/// f64 | 8 +/// char | 4 +/// +/// Furthermore, `usize` and `isize` have the same size. +/// +/// The types [`*const T`], `&T`, [`Box`], [`Option<&T>`], and `Option>` all have +/// the same size. If `T` is `Sized`, all of those types have the same size as `usize`. +/// +/// The mutability of a pointer does not change its size. As such, `&T` and `&mut T` +/// have the same size. Likewise for `*const T` and `*mut T`. +/// +/// # Size of `#[repr(C)]` items +/// +/// The `C` representation for items has a defined layout. With this layout, +/// the size of items is also stable as long as all fields have a stable size. +/// +/// ## Size of Structs +/// +/// For `struct`s, the size is determined by the following algorithm. +/// +/// For each field in the struct ordered by declaration order: +/// +/// 1. Add the size of the field. +/// 2. Round up the current size to the nearest multiple of the next field's [alignment]. +/// +/// Finally, round the size of the struct to the nearest multiple of its [alignment]. +/// The alignment of the struct is usually the largest alignment of all its +/// fields; this can be changed with the use of `repr(align(N))`. +/// +/// Unlike `C`, zero sized structs are not rounded up to one byte in size. +/// +/// ## Size of Enums +/// +/// Enums that carry no data other than the discriminant have the same size as C enums +/// on the platform they are compiled for. +/// +/// ## Size of Unions +/// +/// The size of a union is the size of its largest field. +/// +/// Unlike `C`, zero sized unions are not rounded up to one byte in size. +/// +/// # Examples +/// +/// ``` +/// use std::mem; +/// +/// // Some primitives +/// assert_eq!(4, mem::size_of::()); +/// assert_eq!(8, mem::size_of::()); +/// assert_eq!(0, mem::size_of::<()>()); +/// +/// // Some arrays +/// assert_eq!(8, mem::size_of::<[i32; 2]>()); +/// assert_eq!(12, mem::size_of::<[i32; 3]>()); +/// assert_eq!(0, mem::size_of::<[i32; 0]>()); +/// +/// +/// // Pointer size equality +/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<*const i32>()); +/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::>()); +/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::>()); +/// assert_eq!(mem::size_of::>(), mem::size_of::>>()); +/// ``` +/// +/// Using `#[repr(C)]`. +/// +/// ``` +/// use std::mem; +/// +/// #[repr(C)] +/// struct FieldStruct { +/// first: u8, +/// second: u16, +/// third: u8 +/// } +/// +/// // The size of the first field is 1, so add 1 to the size. Size is 1. +/// // The alignment of the second field is 2, so add 1 to the size for padding. Size is 2. +/// // The size of the second field is 2, so add 2 to the size. Size is 4. +/// // The alignment of the third field is 1, so add 0 to the size for padding. Size is 4. +/// // The size of the third field is 1, so add 1 to the size. Size is 5. +/// // Finally, the alignment of the struct is 2 (because the largest alignment amongst its +/// // fields is 2), so add 1 to the size for padding. Size is 6. +/// assert_eq!(6, mem::size_of::()); +/// +/// #[repr(C)] +/// struct TupleStruct(u8, u16, u8); +/// +/// // Tuple structs follow the same rules. +/// assert_eq!(6, mem::size_of::()); +/// +/// // Note that reordering the fields can lower the size. We can remove both padding bytes +/// // by putting `third` before `second`. +/// #[repr(C)] +/// struct FieldStructOptimized { +/// first: u8, +/// third: u8, +/// second: u16 +/// } +/// +/// assert_eq!(4, mem::size_of::()); +/// +/// // Union size is the size of the largest field. +/// #[repr(C)] +/// union ExampleUnion { +/// smaller: u8, +/// larger: u16 +/// } +/// +/// assert_eq!(2, mem::size_of::()); +/// ``` +/// +/// [alignment]: align_of +/// [`*const T`]: primitive@pointer +/// [`Box`]: ../../std/boxed/struct.Box.html +/// [`Option<&T>`]: crate::option::Option +/// +#[inline(always)] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_promotable] +#[rustc_const_stable(feature = "const_mem_size_of", since = "1.24.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of")] +pub const fn size_of() -> usize { + intrinsics::size_of::() +} + +/// Returns the size of the pointed-to value in bytes. +/// +/// This is usually the same as [`size_of::()`]. However, when `T` *has* no +/// statically-known size, e.g., a slice [`[T]`][slice] or a [trait object], +/// then `size_of_val` can be used to get the dynamically-known size. +/// +/// [trait object]: ../../book/ch17-02-trait-objects.html +/// +/// # Examples +/// +/// ``` +/// use std::mem; +/// +/// assert_eq!(4, mem::size_of_val(&5i32)); +/// +/// let x: [u8; 13] = [0; 13]; +/// let y: &[u8] = &x; +/// assert_eq!(13, mem::size_of_val(y)); +/// ``` +/// +/// [`size_of::()`]: size_of +#[inline] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_size_of_val", since = "CURRENT_RUSTC_VERSION")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of_val")] +pub const fn size_of_val(val: &T) -> usize { + // SAFETY: `val` is a reference, so it's a valid raw pointer + unsafe { intrinsics::size_of_val(val) } +} + +/// Returns the size of the pointed-to value in bytes. +/// +/// This is usually the same as [`size_of::()`]. However, when `T` *has* no +/// statically-known size, e.g., a slice [`[T]`][slice] or a [trait object], +/// then `size_of_val_raw` can be used to get the dynamically-known size. +/// +/// # Safety +/// +/// This function is only safe to call if the following conditions hold: +/// +/// - If `T` is `Sized`, this function is always safe to call. +/// - If the unsized tail of `T` is: +/// - a [slice], then the length of the slice tail must be an initialized +/// integer, and the size of the *entire value* +/// (dynamic tail length + statically sized prefix) must fit in `isize`. +/// For the special case where the dynamic tail length is 0, this function +/// is safe to call. +// NOTE: the reason this is safe is that if an overflow were to occur already with size 0, +// then we would stop compilation as even the "statically known" part of the type would +// already be too big (or the call may be in dead code and optimized away, but then it +// doesn't matter). +/// - a [trait object], then the vtable part of the pointer must point +/// to a valid vtable acquired by an unsizing coercion, and the size +/// of the *entire value* (dynamic tail length + statically sized prefix) +/// must fit in `isize`. +/// - an (unstable) [extern type], then this function is always safe to +/// call, but may panic or otherwise return the wrong value, as the +/// extern type's layout is not known. This is the same behavior as +/// [`size_of_val`] on a reference to a type with an extern type tail. +/// - otherwise, it is conservatively not allowed to call this function. +/// +/// [`size_of::()`]: size_of +/// [trait object]: ../../book/ch17-02-trait-objects.html +/// [extern type]: ../../unstable-book/language-features/extern-types.html +/// +/// # Examples +/// +/// ``` +/// #![feature(layout_for_ptr)] +/// use std::mem; +/// +/// assert_eq!(4, mem::size_of_val(&5i32)); +/// +/// let x: [u8; 13] = [0; 13]; +/// let y: &[u8] = &x; +/// assert_eq!(13, unsafe { mem::size_of_val_raw(y) }); +/// ``` +#[inline] +#[must_use] +#[unstable(feature = "layout_for_ptr", issue = "69835")] +pub const unsafe fn size_of_val_raw(val: *const T) -> usize { + // SAFETY: the caller must provide a valid raw pointer + unsafe { intrinsics::size_of_val(val) } +} + +/// Returns the [ABI]-required minimum alignment of a type in bytes. +/// +/// Every reference to a value of the type `T` must be a multiple of this number. +/// +/// This is the alignment used for struct fields. It may be smaller than the preferred alignment. +/// +/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface +/// +/// # Examples +/// +/// ``` +/// # #![allow(deprecated)] +/// use std::mem; +/// +/// assert_eq!(4, mem::min_align_of::()); +/// ``` +#[inline] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(note = "use `align_of` instead", since = "1.2.0", suggestion = "align_of")] +pub fn min_align_of() -> usize { + intrinsics::min_align_of::() +} + +/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to in +/// bytes. +/// +/// Every reference to a value of the type `T` must be a multiple of this number. +/// +/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface +/// +/// # Examples +/// +/// ``` +/// # #![allow(deprecated)] +/// use std::mem; +/// +/// assert_eq!(4, mem::min_align_of_val(&5i32)); +/// ``` +#[inline] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(note = "use `align_of_val` instead", since = "1.2.0", suggestion = "align_of_val")] +pub fn min_align_of_val(val: &T) -> usize { + // SAFETY: val is a reference, so it's a valid raw pointer + unsafe { intrinsics::min_align_of_val(val) } +} + +/// Returns the [ABI]-required minimum alignment of a type in bytes. +/// +/// Every reference to a value of the type `T` must be a multiple of this number. +/// +/// This is the alignment used for struct fields. It may be smaller than the preferred alignment. +/// +/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface +/// +/// # Examples +/// +/// ``` +/// use std::mem; +/// +/// assert_eq!(4, mem::align_of::()); +/// ``` +#[inline(always)] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_promotable] +#[rustc_const_stable(feature = "const_align_of", since = "1.24.0")] +pub const fn align_of() -> usize { + intrinsics::min_align_of::() +} + +/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to in +/// bytes. +/// +/// Every reference to a value of the type `T` must be a multiple of this number. +/// +/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface +/// +/// # Examples +/// +/// ``` +/// use std::mem; +/// +/// assert_eq!(4, mem::align_of_val(&5i32)); +/// ``` +#[inline] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_align_of_val", since = "CURRENT_RUSTC_VERSION")] +#[allow(deprecated)] +pub const fn align_of_val(val: &T) -> usize { + // SAFETY: val is a reference, so it's a valid raw pointer + unsafe { intrinsics::min_align_of_val(val) } +} + +/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to in +/// bytes. +/// +/// Every reference to a value of the type `T` must be a multiple of this number. +/// +/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface +/// +/// # Safety +/// +/// This function is only safe to call if the following conditions hold: +/// +/// - If `T` is `Sized`, this function is always safe to call. +/// - If the unsized tail of `T` is: +/// - a [slice], then the length of the slice tail must be an initialized +/// integer, and the size of the *entire value* +/// (dynamic tail length + statically sized prefix) must fit in `isize`. +/// For the special case where the dynamic tail length is 0, this function +/// is safe to call. +/// - a [trait object], then the vtable part of the pointer must point +/// to a valid vtable acquired by an unsizing coercion, and the size +/// of the *entire value* (dynamic tail length + statically sized prefix) +/// must fit in `isize`. +/// - an (unstable) [extern type], then this function is always safe to +/// call, but may panic or otherwise return the wrong value, as the +/// extern type's layout is not known. This is the same behavior as +/// [`align_of_val`] on a reference to a type with an extern type tail. +/// - otherwise, it is conservatively not allowed to call this function. +/// +/// [trait object]: ../../book/ch17-02-trait-objects.html +/// [extern type]: ../../unstable-book/language-features/extern-types.html +/// +/// # Examples +/// +/// ``` +/// #![feature(layout_for_ptr)] +/// use std::mem; +/// +/// assert_eq!(4, unsafe { mem::align_of_val_raw(&5i32) }); +/// ``` +#[inline] +#[must_use] +#[unstable(feature = "layout_for_ptr", issue = "69835")] +pub const unsafe fn align_of_val_raw(val: *const T) -> usize { + // SAFETY: the caller must provide a valid raw pointer + unsafe { intrinsics::min_align_of_val(val) } +} + +/// Returns `true` if dropping values of type `T` matters. +/// +/// This is purely an optimization hint, and may be implemented conservatively: +/// it may return `true` for types that don't actually need to be dropped. +/// As such always returning `true` would be a valid implementation of +/// this function. However if this function actually returns `false`, then you +/// can be certain dropping `T` has no side effect. +/// +/// Low level implementations of things like collections, which need to manually +/// drop their data, should use this function to avoid unnecessarily +/// trying to drop all their contents when they are destroyed. This might not +/// make a difference in release builds (where a loop that has no side-effects +/// is easily detected and eliminated), but is often a big win for debug builds. +/// +/// Note that [`drop_in_place`] already performs this check, so if your workload +/// can be reduced to some small number of [`drop_in_place`] calls, using this is +/// unnecessary. In particular note that you can [`drop_in_place`] a slice, and that +/// will do a single needs_drop check for all the values. +/// +/// Types like Vec therefore just `drop_in_place(&mut self[..])` without using +/// `needs_drop` explicitly. Types like [`HashMap`], on the other hand, have to drop +/// values one at a time and should use this API. +/// +/// [`drop_in_place`]: crate::ptr::drop_in_place +/// [`HashMap`]: ../../std/collections/struct.HashMap.html +/// +/// # Examples +/// +/// Here's an example of how a collection might make use of `needs_drop`: +/// +/// ``` +/// use std::{mem, ptr}; +/// +/// pub struct MyCollection { +/// # data: [T; 1], +/// /* ... */ +/// } +/// # impl MyCollection { +/// # fn iter_mut(&mut self) -> &mut [T] { &mut self.data } +/// # fn free_buffer(&mut self) {} +/// # } +/// +/// impl Drop for MyCollection { +/// fn drop(&mut self) { +/// unsafe { +/// // drop the data +/// if mem::needs_drop::() { +/// for x in self.iter_mut() { +/// ptr::drop_in_place(x); +/// } +/// } +/// self.free_buffer(); +/// } +/// } +/// } +/// ``` +#[inline] +#[must_use] +#[stable(feature = "needs_drop", since = "1.21.0")] +#[rustc_const_stable(feature = "const_mem_needs_drop", since = "1.36.0")] +#[rustc_diagnostic_item = "needs_drop"] +pub const fn needs_drop() -> bool { + intrinsics::needs_drop::() +} + +/// Returns the value of type `T` represented by the all-zero byte-pattern. +/// +/// This means that, for example, the padding byte in `(u8, u16)` is not +/// necessarily zeroed. +/// +/// There is no guarantee that an all-zero byte-pattern represents a valid value +/// of some type `T`. For example, the all-zero byte-pattern is not a valid value +/// for reference types (`&T`, `&mut T`) and function pointers. Using `zeroed` +/// on such types causes immediate [undefined behavior][ub] because [the Rust +/// compiler assumes][inv] that there always is a valid value in a variable it +/// considers initialized. +/// +/// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed]. +/// It is useful for FFI sometimes, but should generally be avoided. +/// +/// [zeroed]: MaybeUninit::zeroed +/// [ub]: ../../reference/behavior-considered-undefined.html +/// [inv]: MaybeUninit#initialization-invariant +/// +/// # Examples +/// +/// Correct usage of this function: initializing an integer with zero. +/// +/// ``` +/// use std::mem; +/// +/// let x: i32 = unsafe { mem::zeroed() }; +/// assert_eq!(0, x); +/// ``` +/// +/// *Incorrect* usage of this function: initializing a reference with zero. +/// +/// ```rust,no_run +/// # #![allow(invalid_value)] +/// use std::mem; +/// +/// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior! +/// let _y: fn() = unsafe { mem::zeroed() }; // And again! +/// ``` +#[inline(always)] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated_in_future)] +#[allow(deprecated)] +#[rustc_diagnostic_item = "mem_zeroed"] +#[track_caller] +#[rustc_const_stable(feature = "const_mem_zeroed", since = "1.75.0")] +pub const unsafe fn zeroed() -> T { + // SAFETY: the caller must guarantee that an all-zero value is valid for `T`. + unsafe { + intrinsics::assert_zero_valid::(); + MaybeUninit::zeroed().assume_init() + } +} + +/// Bypasses Rust's normal memory-initialization checks by pretending to +/// produce a value of type `T`, while doing nothing at all. +/// +/// **This function is deprecated.** Use [`MaybeUninit`] instead. +/// It also might be slower than using `MaybeUninit` due to mitigations that were put in place to +/// limit the potential harm caused by incorrect use of this function in legacy code. +/// +/// The reason for deprecation is that the function basically cannot be used +/// correctly: it has the same effect as [`MaybeUninit::uninit().assume_init()`][uninit]. +/// As the [`assume_init` documentation][assume_init] explains, +/// [the Rust compiler assumes][inv] that values are properly initialized. +/// +/// Truly uninitialized memory like what gets returned here +/// is special in that the compiler knows that it does not have a fixed value. +/// This makes it undefined behavior to have uninitialized data in a variable even +/// if that variable has an integer type. +/// +/// Therefore, it is immediate undefined behavior to call this function on nearly all types, +/// including integer types and arrays of integer types, and even if the result is unused. +/// +/// [uninit]: MaybeUninit::uninit +/// [assume_init]: MaybeUninit::assume_init +/// [inv]: MaybeUninit#initialization-invariant +#[inline(always)] +#[must_use] +#[deprecated(since = "1.39.0", note = "use `mem::MaybeUninit` instead")] +#[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated_in_future)] +#[allow(deprecated)] +#[rustc_diagnostic_item = "mem_uninitialized"] +#[track_caller] +pub unsafe fn uninitialized() -> T { + // SAFETY: the caller must guarantee that an uninitialized value is valid for `T`. + unsafe { + intrinsics::assert_mem_uninitialized_valid::(); + let mut val = MaybeUninit::::uninit(); + + // Fill memory with 0x01, as an imperfect mitigation for old code that uses this function on + // bool, nonnull, and noundef types. But don't do this if we actively want to detect UB. + if !cfg!(any(miri, sanitize = "memory")) { + val.as_mut_ptr().write_bytes(0x01, 1); + } + + val.assume_init() + } +} + +/// Swaps the values at two mutable locations, without deinitializing either one. +/// +/// * If you want to swap with a default or dummy value, see [`take`]. +/// * If you want to swap with a passed value, returning the old value, see [`replace`]. +/// +/// # Examples +/// +/// ``` +/// use std::mem; +/// +/// let mut x = 5; +/// let mut y = 42; +/// +/// mem::swap(&mut x, &mut y); +/// +/// assert_eq!(42, x); +/// assert_eq!(5, y); +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_swap", issue = "83163")] +#[rustc_diagnostic_item = "mem_swap"] +pub const fn swap(x: &mut T, y: &mut T) { + // SAFETY: `&mut` guarantees these are typed readable and writable + // as well as non-overlapping. + unsafe { intrinsics::typed_swap(x, y) } +} + +/// Replaces `dest` with the default value of `T`, returning the previous `dest` value. +/// +/// * If you want to replace the values of two variables, see [`swap`]. +/// * If you want to replace with a passed value instead of the default value, see [`replace`]. +/// +/// # Examples +/// +/// A simple example: +/// +/// ``` +/// use std::mem; +/// +/// let mut v: Vec = vec![1, 2]; +/// +/// let old_v = mem::take(&mut v); +/// assert_eq!(vec![1, 2], old_v); +/// assert!(v.is_empty()); +/// ``` +/// +/// `take` allows taking ownership of a struct field by replacing it with an "empty" value. +/// Without `take` you can run into issues like these: +/// +/// ```compile_fail,E0507 +/// struct Buffer { buf: Vec } +/// +/// impl Buffer { +/// fn get_and_reset(&mut self) -> Vec { +/// // error: cannot move out of dereference of `&mut`-pointer +/// let buf = self.buf; +/// self.buf = Vec::new(); +/// buf +/// } +/// } +/// ``` +/// +/// Note that `T` does not necessarily implement [`Clone`], so it can't even clone and reset +/// `self.buf`. But `take` can be used to disassociate the original value of `self.buf` from +/// `self`, allowing it to be returned: +/// +/// ``` +/// use std::mem; +/// +/// # struct Buffer { buf: Vec } +/// impl Buffer { +/// fn get_and_reset(&mut self) -> Vec { +/// mem::take(&mut self.buf) +/// } +/// } +/// +/// let mut buffer = Buffer { buf: vec![0, 1] }; +/// assert_eq!(buffer.buf.len(), 2); +/// +/// assert_eq!(buffer.get_and_reset(), vec![0, 1]); +/// assert_eq!(buffer.buf.len(), 0); +/// ``` +#[inline] +#[stable(feature = "mem_take", since = "1.40.0")] +pub fn take(dest: &mut T) -> T { + replace(dest, T::default()) +} + +/// Moves `src` into the referenced `dest`, returning the previous `dest` value. +/// +/// Neither value is dropped. +/// +/// * If you want to replace the values of two variables, see [`swap`]. +/// * If you want to replace with a default value, see [`take`]. +/// +/// # Examples +/// +/// A simple example: +/// +/// ``` +/// use std::mem; +/// +/// let mut v: Vec = vec![1, 2]; +/// +/// let old_v = mem::replace(&mut v, vec![3, 4, 5]); +/// assert_eq!(vec![1, 2], old_v); +/// assert_eq!(vec![3, 4, 5], v); +/// ``` +/// +/// `replace` allows consumption of a struct field by replacing it with another value. +/// Without `replace` you can run into issues like these: +/// +/// ```compile_fail,E0507 +/// struct Buffer { buf: Vec } +/// +/// impl Buffer { +/// fn replace_index(&mut self, i: usize, v: T) -> T { +/// // error: cannot move out of dereference of `&mut`-pointer +/// let t = self.buf[i]; +/// self.buf[i] = v; +/// t +/// } +/// } +/// ``` +/// +/// Note that `T` does not necessarily implement [`Clone`], so we can't even clone `self.buf[i]` to +/// avoid the move. But `replace` can be used to disassociate the original value at that index from +/// `self`, allowing it to be returned: +/// +/// ``` +/// # #![allow(dead_code)] +/// use std::mem; +/// +/// # struct Buffer { buf: Vec } +/// impl Buffer { +/// fn replace_index(&mut self, i: usize, v: T) -> T { +/// mem::replace(&mut self.buf[i], v) +/// } +/// } +/// +/// let mut buffer = Buffer { buf: vec![0, 1] }; +/// assert_eq!(buffer.buf[0], 0); +/// +/// assert_eq!(buffer.replace_index(0, 2), 0); +/// assert_eq!(buffer.buf[0], 2); +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "if you don't need the old value, you can just assign the new value directly"] +#[rustc_const_stable(feature = "const_replace", since = "1.83.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")] +pub const fn replace(dest: &mut T, src: T) -> T { + // It may be tempting to use `swap` to avoid `unsafe` here. Don't! + // The compiler optimizes the implementation below to two `memcpy`s + // while `swap` would require at least three. See PR#83022 for details. + + // SAFETY: We read from `dest` but directly write `src` into it afterwards, + // such that the old value is not duplicated. Nothing is dropped and + // nothing here can panic. + unsafe { + let result = ptr::read(dest); + ptr::write(dest, src); + result + } +} + +/// Disposes of a value. +/// +/// This does so by calling the argument's implementation of [`Drop`][drop]. +/// +/// This effectively does nothing for types which implement `Copy`, e.g. +/// integers. Such values are copied and _then_ moved into the function, so the +/// value persists after this function call. +/// +/// This function is not magic; it is literally defined as +/// +/// ``` +/// pub fn drop(_x: T) {} +/// ``` +/// +/// Because `_x` is moved into the function, it is automatically dropped before +/// the function returns. +/// +/// [drop]: Drop +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let v = vec![1, 2, 3]; +/// +/// drop(v); // explicitly drop the vector +/// ``` +/// +/// Since [`RefCell`] enforces the borrow rules at runtime, `drop` can +/// release a [`RefCell`] borrow: +/// +/// ``` +/// use std::cell::RefCell; +/// +/// let x = RefCell::new(1); +/// +/// let mut mutable_borrow = x.borrow_mut(); +/// *mutable_borrow = 1; +/// +/// drop(mutable_borrow); // relinquish the mutable borrow on this slot +/// +/// let borrow = x.borrow(); +/// println!("{}", *borrow); +/// ``` +/// +/// Integers and other types implementing [`Copy`] are unaffected by `drop`. +/// +/// ``` +/// # #![allow(dropping_copy_types)] +/// #[derive(Copy, Clone)] +/// struct Foo(u8); +/// +/// let x = 1; +/// let y = Foo(2); +/// drop(x); // a copy of `x` is moved and dropped +/// drop(y); // a copy of `y` is moved and dropped +/// +/// println!("x: {}, y: {}", x, y.0); // still available +/// ``` +/// +/// [`RefCell`]: crate::cell::RefCell +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_drop")] +pub fn drop(_x: T) {} + +/// Bitwise-copies a value. +/// +/// This function is not magic; it is literally defined as +/// ``` +/// pub fn copy(x: &T) -> T { *x } +/// ``` +/// +/// It is useful when you want to pass a function pointer to a combinator, rather than defining a new closure. +/// +/// Example: +/// ``` +/// #![feature(mem_copy_fn)] +/// use core::mem::copy; +/// let result_from_ffi_function: Result<(), &i32> = Err(&1); +/// let result_copied: Result<(), i32> = result_from_ffi_function.map_err(copy); +/// ``` +#[inline] +#[unstable(feature = "mem_copy_fn", issue = "98262")] +pub const fn copy(x: &T) -> T { + *x +} + +/// Interprets `src` as having type `&Dst`, and then reads `src` without moving +/// the contained value. +/// +/// This function will unsafely assume the pointer `src` is valid for [`size_of::`][size_of] +/// bytes by transmuting `&Src` to `&Dst` and then reading the `&Dst` (except that this is done +/// in a way that is correct even when `&Dst` has stricter alignment requirements than `&Src`). +/// It will also unsafely create a copy of the contained value instead of moving out of `src`. +/// +/// It is not a compile-time error if `Src` and `Dst` have different sizes, but it +/// is highly encouraged to only invoke this function where `Src` and `Dst` have the +/// same size. This function triggers [undefined behavior][ub] if `Dst` is larger than +/// `Src`. +/// +/// [ub]: ../../reference/behavior-considered-undefined.html +/// +/// # Examples +/// +/// ``` +/// use std::mem; +/// +/// #[repr(packed)] +/// struct Foo { +/// bar: u8, +/// } +/// +/// let foo_array = [10u8]; +/// +/// unsafe { +/// // Copy the data from 'foo_array' and treat it as a 'Foo' +/// let mut foo_struct: Foo = mem::transmute_copy(&foo_array); +/// assert_eq!(foo_struct.bar, 10); +/// +/// // Modify the copied data +/// foo_struct.bar = 20; +/// assert_eq!(foo_struct.bar, 20); +/// } +/// +/// // The contents of 'foo_array' should not have changed +/// assert_eq!(foo_array, [10]); +/// ``` +#[inline] +#[must_use] +#[track_caller] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_transmute_copy", since = "1.74.0")] +pub const unsafe fn transmute_copy(src: &Src) -> Dst { + assert!( + size_of::() >= size_of::(), + "cannot transmute_copy if Dst is larger than Src" + ); + + // If Dst has a higher alignment requirement, src might not be suitably aligned. + if align_of::() > align_of::() { + // SAFETY: `src` is a reference which is guaranteed to be valid for reads. + // The caller must guarantee that the actual transmutation is safe. + unsafe { ptr::read_unaligned(src as *const Src as *const Dst) } + } else { + // SAFETY: `src` is a reference which is guaranteed to be valid for reads. + // We just checked that `src as *const Dst` was properly aligned. + // The caller must guarantee that the actual transmutation is safe. + unsafe { ptr::read(src as *const Src as *const Dst) } + } +} + +/// Opaque type representing the discriminant of an enum. +/// +/// See the [`discriminant`] function in this module for more information. +#[stable(feature = "discriminant_value", since = "1.21.0")] +pub struct Discriminant(::Discriminant); + +// N.B. These trait implementations cannot be derived because we don't want any bounds on T. + +#[stable(feature = "discriminant_value", since = "1.21.0")] +impl Copy for Discriminant {} + +#[stable(feature = "discriminant_value", since = "1.21.0")] +impl clone::Clone for Discriminant { + fn clone(&self) -> Self { + *self + } +} + +#[stable(feature = "discriminant_value", since = "1.21.0")] +impl cmp::PartialEq for Discriminant { + fn eq(&self, rhs: &Self) -> bool { + self.0 == rhs.0 + } +} + +#[stable(feature = "discriminant_value", since = "1.21.0")] +impl cmp::Eq for Discriminant {} + +#[stable(feature = "discriminant_value", since = "1.21.0")] +impl hash::Hash for Discriminant { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + +#[stable(feature = "discriminant_value", since = "1.21.0")] +impl fmt::Debug for Discriminant { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("Discriminant").field(&self.0).finish() + } +} + +/// Returns a value uniquely identifying the enum variant in `v`. +/// +/// If `T` is not an enum, calling this function will not result in undefined behavior, but the +/// return value is unspecified. +/// +/// # Stability +/// +/// The discriminant of an enum variant may change if the enum definition changes. A discriminant +/// of some variant will not change between compilations with the same compiler. See the [Reference] +/// for more information. +/// +/// [Reference]: ../../reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations +/// +/// The value of a [`Discriminant`] is independent of any *free lifetimes* in `T`. As such, +/// reading or writing a `Discriminant>` as a `Discriminant>` (whether via +/// [`transmute`] or otherwise) is always sound. Note that this is **not** true for other kinds +/// of generic parameters and for higher-ranked lifetimes; `Discriminant>` and +/// `Discriminant>` as well as `Discriminant Trait<'a>>>` and +/// `Discriminant>>` may be incompatible. +/// +/// # Examples +/// +/// This can be used to compare enums that carry data, while disregarding +/// the actual data: +/// +/// ``` +/// use std::mem; +/// +/// enum Foo { A(&'static str), B(i32), C(i32) } +/// +/// assert_eq!(mem::discriminant(&Foo::A("bar")), mem::discriminant(&Foo::A("baz"))); +/// assert_eq!(mem::discriminant(&Foo::B(1)), mem::discriminant(&Foo::B(2))); +/// assert_ne!(mem::discriminant(&Foo::B(3)), mem::discriminant(&Foo::C(3))); +/// ``` +/// +/// ## Accessing the numeric value of the discriminant +/// +/// Note that it is *undefined behavior* to [`transmute`] from [`Discriminant`] to a primitive! +/// +/// If an enum has only unit variants, then the numeric value of the discriminant can be accessed +/// with an [`as`] cast: +/// +/// ``` +/// enum Enum { +/// Foo, +/// Bar, +/// Baz, +/// } +/// +/// assert_eq!(0, Enum::Foo as isize); +/// assert_eq!(1, Enum::Bar as isize); +/// assert_eq!(2, Enum::Baz as isize); +/// ``` +/// +/// If an enum has opted-in to having a [primitive representation] for its discriminant, +/// then it's possible to use pointers to read the memory location storing the discriminant. +/// That **cannot** be done for enums using the [default representation], however, as it's +/// undefined what layout the discriminant has and where it's stored — it might not even be +/// stored at all! +/// +/// [`as`]: ../../std/keyword.as.html +/// [primitive representation]: ../../reference/type-layout.html#primitive-representations +/// [default representation]: ../../reference/type-layout.html#the-default-representation +/// ``` +/// #[repr(u8)] +/// enum Enum { +/// Unit, +/// Tuple(bool), +/// Struct { a: bool }, +/// } +/// +/// impl Enum { +/// fn discriminant(&self) -> u8 { +/// // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a `repr(C)` `union` +/// // between `repr(C)` structs, each of which has the `u8` discriminant as its first +/// // field, so we can read the discriminant without offsetting the pointer. +/// unsafe { *<*const _>::from(self).cast::() } +/// } +/// } +/// +/// let unit_like = Enum::Unit; +/// let tuple_like = Enum::Tuple(true); +/// let struct_like = Enum::Struct { a: false }; +/// assert_eq!(0, unit_like.discriminant()); +/// assert_eq!(1, tuple_like.discriminant()); +/// assert_eq!(2, struct_like.discriminant()); +/// +/// // ⚠️ This is undefined behavior. Don't do this. ⚠️ +/// // assert_eq!(0, unsafe { std::mem::transmute::<_, u8>(std::mem::discriminant(&unit_like)) }); +/// ``` +#[stable(feature = "discriminant_value", since = "1.21.0")] +#[rustc_const_stable(feature = "const_discriminant", since = "1.75.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_discriminant")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub const fn discriminant(v: &T) -> Discriminant { + Discriminant(intrinsics::discriminant_value(v)) +} + +/// Returns the number of variants in the enum type `T`. +/// +/// If `T` is not an enum, calling this function will not result in undefined behavior, but the +/// return value is unspecified. Equally, if `T` is an enum with more variants than `usize::MAX` +/// the return value is unspecified. Uninhabited variants will be counted. +/// +/// Note that an enum may be expanded with additional variants in the future +/// as a non-breaking change, for example if it is marked `#[non_exhaustive]`, +/// which will change the result of this function. +/// +/// # Examples +/// +/// ``` +/// # #![feature(never_type)] +/// # #![feature(variant_count)] +/// +/// use std::mem; +/// +/// enum Void {} +/// enum Foo { A(&'static str), B(i32), C(i32) } +/// +/// assert_eq!(mem::variant_count::(), 0); +/// assert_eq!(mem::variant_count::(), 3); +/// +/// assert_eq!(mem::variant_count::>(), 2); +/// assert_eq!(mem::variant_count::>(), 2); +/// ``` +#[inline(always)] +#[must_use] +#[unstable(feature = "variant_count", issue = "73662")] +#[rustc_const_unstable(feature = "variant_count", issue = "73662")] +#[rustc_diagnostic_item = "mem_variant_count"] +pub const fn variant_count() -> usize { + intrinsics::variant_count::() +} + +/// Provides associated constants for various useful properties of types, +/// to give them a canonical form in our code and make them easier to read. +/// +/// This is here only to simplify all the ZST checks we need in the library. +/// It's not on a stabilization track right now. +#[doc(hidden)] +#[unstable(feature = "sized_type_properties", issue = "none")] +pub trait SizedTypeProperties: Sized { + /// `true` if this type requires no storage. + /// `false` if its [size](size_of) is greater than zero. + /// + /// # Examples + /// + /// ``` + /// #![feature(sized_type_properties)] + /// use core::mem::SizedTypeProperties; + /// + /// fn do_something_with() { + /// if T::IS_ZST { + /// // ... special approach ... + /// } else { + /// // ... the normal thing ... + /// } + /// } + /// + /// struct MyUnit; + /// assert!(MyUnit::IS_ZST); + /// + /// // For negative checks, consider using UFCS to emphasize the negation + /// assert!(!::IS_ZST); + /// // As it can sometimes hide in the type otherwise + /// assert!(!String::IS_ZST); + /// ``` + #[doc(hidden)] + #[unstable(feature = "sized_type_properties", issue = "none")] + const IS_ZST: bool = size_of::() == 0; + + #[doc(hidden)] + #[unstable(feature = "sized_type_properties", issue = "none")] + const LAYOUT: Layout = Layout::new::(); +} +#[doc(hidden)] +#[unstable(feature = "sized_type_properties", issue = "none")] +impl SizedTypeProperties for T {} + +/// Expands to the offset in bytes of a field from the beginning of the given type. +/// +/// Structs, enums, unions and tuples are supported. +/// +/// Nested field accesses may be used, but not array indexes. +/// +/// If the nightly-only feature `offset_of_enum` is enabled, +/// variants may be traversed as if they were fields. +/// Variants themselves do not have an offset. +/// +/// Visibility is respected - all types and fields must be visible to the call site: +/// +/// ``` +/// mod nested { +/// #[repr(C)] +/// pub struct Struct { +/// private: u8, +/// } +/// } +/// +/// // assert_eq!(mem::offset_of!(nested::Struct, private), 0); +/// // ^^^ error[E0616]: field `private` of struct `Struct` is private +/// ``` +/// +/// Only [`Sized`] fields are supported, but the container may be unsized: +/// ``` +/// # use core::mem; +/// #[repr(C)] +/// pub struct Struct { +/// a: u8, +/// b: [u8], +/// } +/// +/// assert_eq!(mem::offset_of!(Struct, a), 0); // OK +/// // assert_eq!(mem::offset_of!(Struct, b), 1); +/// // ^^^ error[E0277]: doesn't have a size known at compile-time +/// ``` +/// +/// Note that type layout is, in general, [subject to change and +/// platform-specific](https://doc.rust-lang.org/reference/type-layout.html). If +/// layout stability is required, consider using an [explicit `repr` attribute]. +/// +/// Rust guarantees that the offset of a given field within a given type will not +/// change over the lifetime of the program. However, two different compilations of +/// the same program may result in different layouts. Also, even within a single +/// program execution, no guarantees are made about types which are *similar* but +/// not *identical*, e.g.: +/// +/// ``` +/// struct Wrapper(T, U); +/// +/// type A = Wrapper; +/// type B = Wrapper; +/// +/// // Not necessarily identical even though `u8` and `i8` have the same layout! +/// // assert_eq!(mem::offset_of!(A, 1), mem::offset_of!(B, 1)); +/// +/// #[repr(transparent)] +/// struct U8(u8); +/// +/// type C = Wrapper; +/// +/// // Not necessarily identical even though `u8` and `U8` have the same layout! +/// // assert_eq!(mem::offset_of!(A, 1), mem::offset_of!(C, 1)); +/// +/// struct Empty(core::marker::PhantomData); +/// +/// // Not necessarily identical even though `PhantomData` always has the same layout! +/// // assert_eq!(mem::offset_of!(Empty, 0), mem::offset_of!(Empty, 0)); +/// ``` +/// +/// [explicit `repr` attribute]: https://doc.rust-lang.org/reference/type-layout.html#representations +/// +/// # Examples +/// +/// ``` +/// #![feature(offset_of_enum)] +/// +/// use std::mem; +/// #[repr(C)] +/// struct FieldStruct { +/// first: u8, +/// second: u16, +/// third: u8 +/// } +/// +/// assert_eq!(mem::offset_of!(FieldStruct, first), 0); +/// assert_eq!(mem::offset_of!(FieldStruct, second), 2); +/// assert_eq!(mem::offset_of!(FieldStruct, third), 4); +/// +/// #[repr(C)] +/// struct NestedA { +/// b: NestedB +/// } +/// +/// #[repr(C)] +/// struct NestedB(u8); +/// +/// assert_eq!(mem::offset_of!(NestedA, b.0), 0); +/// +/// #[repr(u8)] +/// enum Enum { +/// A(u8, u16), +/// B { one: u8, two: u16 }, +/// } +/// +/// assert_eq!(mem::offset_of!(Enum, A.0), 1); +/// assert_eq!(mem::offset_of!(Enum, B.two), 2); +/// +/// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0); +/// ``` +#[stable(feature = "offset_of", since = "1.77.0")] +#[allow_internal_unstable(builtin_syntax)] +pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { + // The `{}` is for better error messages + {builtin # offset_of($Container, $($fields)+)} +} diff --git a/CoqOfRust/core/mem/transmutability.rs b/CoqOfRust/core/mem/transmutability.rs new file mode 100644 index 000000000..7fa3c3343 --- /dev/null +++ b/CoqOfRust/core/mem/transmutability.rs @@ -0,0 +1,428 @@ +use crate::marker::{ConstParamTy_, UnsizedConstParamTy}; + +/// Marks that `Src` is transmutable into `Self`. +/// +/// # Implementation +/// +/// This trait cannot be implemented explicitly. It is implemented on-the-fly by +/// the compiler for all types `Src` and `Self` such that, given a set of safety +/// obligations on the programmer (see [`Assume`]), the compiler has proved that +/// the bits of a value of type `Src` can be soundly reinterpreted as a `Self`. +/// +/// # Safety +/// +/// If `Dst: TransmuteFrom`, the compiler guarantees that +/// `Src` is soundly *union-transmutable* into a value of type `Dst`, provided +/// that the programmer has guaranteed that the given [`ASSUMPTIONS`](Assume) +/// are satisfied. +/// +/// A union-transmute is any bit-reinterpretation conversion in the form of: +/// +/// ```rust +/// pub unsafe fn transmute_via_union(src: Src) -> Dst { +/// use core::mem::ManuallyDrop; +/// +/// #[repr(C)] +/// union Transmute { +/// src: ManuallyDrop, +/// dst: ManuallyDrop, +/// } +/// +/// let transmute = Transmute { +/// src: ManuallyDrop::new(src), +/// }; +/// +/// let dst = transmute.dst; +/// +/// ManuallyDrop::into_inner(dst) +/// } +/// ``` +/// +/// Note that this construction is more permissive than +/// [`mem::transmute_copy`](super::transmute_copy); union-transmutes permit +/// conversions that extend the bits of `Src` with trailing padding to fill +/// trailing uninitialized bytes of `Self`; e.g.: +/// +/// ```rust +/// #![feature(transmutability)] +/// +/// use core::mem::{Assume, TransmuteFrom}; +/// +/// let src = 42u8; // size = 1 +/// +/// #[repr(C, align(2))] +/// struct Dst(u8); // size = 2 +// +/// let _ = unsafe { +/// >::transmute(src) +/// }; +/// ``` +/// +/// # Caveats +/// +/// ## Portability +/// +/// Implementations of this trait do not provide any guarantee of portability +/// across toolchains, targets or compilations. This trait may be implemented +/// for certain combinations of `Src`, `Self` and `ASSUME` on some toolchains, +/// targets or compilations, but not others. For example, if the layouts of +/// `Src` or `Self` are non-deterministic, the presence or absence of an +/// implementation of this trait may also be non-deterministic. Even if `Src` +/// and `Self` have deterministic layouts (e.g., they are `repr(C)` structs), +/// Rust does not specify the alignments of its primitive integer types, and +/// layouts that involve these types may vary across toolchains, targets or +/// compilations. +/// +/// ## Stability +/// +/// Implementations of this trait do not provide any guarantee of SemVer +/// stability across the crate versions that define the `Src` and `Self` types. +/// If SemVer stability is crucial to your application, you must consult the +/// documentation of `Src` and `Self`s' defining crates. Note that the presence +/// of `repr(C)`, alone, does not carry a safety invariant of SemVer stability. +/// Furthermore, stability does not imply portability. For example, the size of +/// `usize` is stable, but not portable. +#[unstable(feature = "transmutability", issue = "99571")] +#[lang = "transmute_trait"] +#[rustc_deny_explicit_impl(implement_via_object = false)] +#[rustc_coinductive] +pub unsafe trait TransmuteFrom +where + Src: ?Sized, +{ + /// Transmutes a `Src` value into a `Self`. + /// + /// # Safety + /// + /// The safety obligations of the caller depend on the value of `ASSUME`: + /// - If [`ASSUME.alignment`](Assume::alignment), the caller must guarantee + /// that the addresses of references in the returned `Self` satisfy the + /// alignment requirements of their referent types. + /// - If [`ASSUME.lifetimes`](Assume::lifetimes), the caller must guarantee + /// that references in the returned `Self` will not outlive their + /// referents. + /// - If [`ASSUME.safety`](Assume::safety), the returned value might not + /// satisfy the library safety invariants of `Self`, and the caller must + /// guarantee that undefined behavior does not arise from uses of the + /// returned value. + /// - If [`ASSUME.validity`](Assume::validity), the caller must guarantee + /// that `src` is a bit-valid instance of `Self`. + /// + /// When satisfying the above obligations (if any), the caller must *not* + /// assume that this trait provides any inherent guarantee of layout + /// [portability](#portability) or [stability](#stability). + unsafe fn transmute(src: Src) -> Self + where + Src: Sized, + Self: Sized, + { + use super::ManuallyDrop; + + #[repr(C)] + union Transmute { + src: ManuallyDrop, + dst: ManuallyDrop, + } + + let transmute = Transmute { src: ManuallyDrop::new(src) }; + + // SAFETY: It is safe to reinterpret the bits of `src` as a value of + // type `Self`, because, by combination of invariant on this trait and + // contract on the caller, `src` has been proven to satisfy both the + // language and library invariants of `Self`. For all invariants not + // `ASSUME`'d by the caller, the safety obligation is supplied by the + // compiler. Conversely, for all invariants `ASSUME`'d by the caller, + // the safety obligation is supplied by contract on the caller. + let dst = unsafe { transmute.dst }; + + ManuallyDrop::into_inner(dst) + } +} + +/// Configurable proof assumptions of [`TransmuteFrom`]. +/// +/// When `false`, the respective proof obligation belongs to the compiler. When +/// `true`, the onus of the safety proof belongs to the programmer. +#[unstable(feature = "transmutability", issue = "99571")] +#[lang = "transmute_opts"] +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct Assume { + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that might violate the alignment requirements of references; e.g.: + /// + /// ```compile_fail,E0277 + /// #![feature(transmutability)] + /// use core::mem::{align_of, TransmuteFrom}; + /// + /// assert_eq!(align_of::<[u8; 2]>(), 1); + /// assert_eq!(align_of::(), 2); + /// + /// let src: &[u8; 2] = &[0xFF, 0xFF]; + /// + /// // SAFETY: No safety obligations. + /// let dst: &u16 = unsafe { + /// <_ as TransmuteFrom<_>>::transmute(src) + /// }; + /// ``` + /// + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured + /// that references in the transmuted value satisfy the alignment + /// requirements of their referent types; e.g.: + /// + /// ```rust + /// #![feature(pointer_is_aligned_to, transmutability)] + /// use core::mem::{align_of, Assume, TransmuteFrom}; + /// + /// let src: &[u8; 2] = &[0xFF, 0xFF]; + /// + /// let maybe_dst: Option<&u16> = if <*const _>::is_aligned_to(src, align_of::()) { + /// // SAFETY: We have checked above that the address of `src` satisfies the + /// // alignment requirements of `u16`. + /// Some(unsafe { + /// <_ as TransmuteFrom<_, { Assume::ALIGNMENT }>>::transmute(src) + /// }) + /// } else { + /// None + /// }; + /// + /// assert!(matches!(maybe_dst, Some(&u16::MAX) | None)); + /// ``` + pub alignment: bool, + + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that extend the lifetimes of references. + /// + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured that + /// references in the transmuted value do not outlive their referents. + pub lifetimes: bool, + + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that might violate the library safety invariants of the destination + /// type; e.g.: + /// + /// ```compile_fail,E0277 + /// #![feature(transmutability)] + /// use core::mem::TransmuteFrom; + /// + /// let src: u8 = 3; + /// + /// struct EvenU8 { + /// // SAFETY: `val` must be an even number. + /// val: u8, + /// } + /// + /// // SAFETY: No safety obligations. + /// let dst: EvenU8 = unsafe { + /// <_ as TransmuteFrom<_>>::transmute(src) + /// }; + /// ``` + /// + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured + /// that undefined behavior does not arise from using the transmuted value; + /// e.g.: + /// + /// ```rust + /// #![feature(transmutability)] + /// use core::mem::{Assume, TransmuteFrom}; + /// + /// let src: u8 = 42; + /// + /// struct EvenU8 { + /// // SAFETY: `val` must be an even number. + /// val: u8, + /// } + /// + /// let maybe_dst: Option = if src % 2 == 0 { + /// // SAFETY: We have checked above that the value of `src` is even. + /// Some(unsafe { + /// <_ as TransmuteFrom<_, { Assume::SAFETY }>>::transmute(src) + /// }) + /// } else { + /// None + /// }; + /// + /// assert!(matches!(maybe_dst, Some(EvenU8 { val: 42 }))); + /// ``` + pub safety: bool, + + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that might violate the language-level bit-validity invariant of the + /// destination type; e.g.: + /// + /// ```compile_fail,E0277 + /// #![feature(transmutability)] + /// use core::mem::TransmuteFrom; + /// + /// let src: u8 = 3; + /// + /// // SAFETY: No safety obligations. + /// let dst: bool = unsafe { + /// <_ as TransmuteFrom<_>>::transmute(src) + /// }; + /// ``` + /// + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured + /// that the value being transmuted is a bit-valid instance of the + /// transmuted value; e.g.: + /// + /// ```rust + /// #![feature(transmutability)] + /// use core::mem::{Assume, TransmuteFrom}; + /// + /// let src: u8 = 1; + /// + /// let maybe_dst: Option = if src == 0 || src == 1 { + /// // SAFETY: We have checked above that the value of `src` is a bit-valid + /// // instance of `bool`. + /// Some(unsafe { + /// <_ as TransmuteFrom<_, { Assume::VALIDITY }>>::transmute(src) + /// }) + /// } else { + /// None + /// }; + /// + /// assert_eq!(maybe_dst, Some(true)); + /// ``` + pub validity: bool, +} + +#[unstable(feature = "transmutability", issue = "99571")] +impl ConstParamTy_ for Assume {} +#[unstable(feature = "transmutability", issue = "99571")] +impl UnsizedConstParamTy for Assume {} + +impl Assume { + /// With this, [`TransmuteFrom`] does not assume you have ensured any safety + /// obligations are met, and relies only upon its own analysis to (dis)prove + /// transmutability. + #[unstable(feature = "transmutability", issue = "99571")] + pub const NOTHING: Self = + Self { alignment: false, lifetimes: false, safety: false, validity: false }; + + /// With this, [`TransmuteFrom`] assumes only that you have ensured that + /// references in the transmuted value satisfy the alignment requirements of + /// their referent types. See [`Assume::alignment`] for examples. + #[unstable(feature = "transmutability", issue = "99571")] + pub const ALIGNMENT: Self = Self { alignment: true, ..Self::NOTHING }; + + /// With this, [`TransmuteFrom`] assumes only that you have ensured that + /// references in the transmuted value do not outlive their referents. See + /// [`Assume::lifetimes`] for examples. + #[unstable(feature = "transmutability", issue = "99571")] + pub const LIFETIMES: Self = Self { lifetimes: true, ..Self::NOTHING }; + + /// With this, [`TransmuteFrom`] assumes only that you have ensured that + /// undefined behavior does not arise from using the transmuted value. See + /// [`Assume::safety`] for examples. + #[unstable(feature = "transmutability", issue = "99571")] + pub const SAFETY: Self = Self { safety: true, ..Self::NOTHING }; + + /// With this, [`TransmuteFrom`] assumes only that you have ensured that the + /// value being transmuted is a bit-valid instance of the transmuted value. + /// See [`Assume::validity`] for examples. + #[unstable(feature = "transmutability", issue = "99571")] + pub const VALIDITY: Self = Self { validity: true, ..Self::NOTHING }; + + /// Combine the assumptions of `self` and `other_assumptions`. + /// + /// This is especially useful for extending [`Assume`] in generic contexts; + /// e.g.: + /// + /// ```rust + /// #![feature( + /// adt_const_params, + /// generic_const_exprs, + /// pointer_is_aligned_to, + /// transmutability, + /// )] + /// #![allow(incomplete_features)] + /// use core::mem::{align_of, Assume, TransmuteFrom}; + /// + /// /// Attempts to transmute `src` to `&Dst`. + /// /// + /// /// Returns `None` if `src` violates the alignment requirements of `&Dst`. + /// /// + /// /// # Safety + /// /// + /// /// The caller guarantees that the obligations required by `ASSUME`, except + /// /// alignment, are satisfied. + /// unsafe fn try_transmute_ref<'a, Src, Dst, const ASSUME: Assume>(src: &'a Src) -> Option<&'a Dst> + /// where + /// &'a Dst: TransmuteFrom<&'a Src, { ASSUME.and(Assume::ALIGNMENT) }>, + /// { + /// if <*const _>::is_aligned_to(src, align_of::()) { + /// // SAFETY: By the above dynamic check, we have ensured that the address + /// // of `src` satisfies the alignment requirements of `&Dst`. By contract + /// // on the caller, the safety obligations required by `ASSUME` have also + /// // been satisfied. + /// Some(unsafe { + /// <_ as TransmuteFrom<_, { ASSUME.and(Assume::ALIGNMENT) }>>::transmute(src) + /// }) + /// } else { + /// None + /// } + /// } + /// + /// let src: &[u8; 2] = &[0xFF, 0xFF]; + /// + /// // SAFETY: No safety obligations. + /// let maybe_dst: Option<&u16> = unsafe { + /// try_transmute_ref::<_, _, { Assume::NOTHING }>(src) + /// }; + ///``` + #[unstable(feature = "transmutability", issue = "99571")] + pub const fn and(self, other_assumptions: Self) -> Self { + Self { + alignment: self.alignment || other_assumptions.alignment, + lifetimes: self.lifetimes || other_assumptions.lifetimes, + safety: self.safety || other_assumptions.safety, + validity: self.validity || other_assumptions.validity, + } + } + + /// Remove `other_assumptions` the obligations of `self`; e.g.: + /// + /// ```rust + /// #![feature(transmutability)] + /// use core::mem::Assume; + /// + /// let assumptions = Assume::ALIGNMENT.and(Assume::SAFETY); + /// let to_be_removed = Assume::SAFETY.and(Assume::VALIDITY); + /// + /// assert_eq!( + /// assumptions.but_not(to_be_removed), + /// Assume::ALIGNMENT, + /// ); + /// ``` + #[unstable(feature = "transmutability", issue = "99571")] + pub const fn but_not(self, other_assumptions: Self) -> Self { + Self { + alignment: self.alignment && !other_assumptions.alignment, + lifetimes: self.lifetimes && !other_assumptions.lifetimes, + safety: self.safety && !other_assumptions.safety, + validity: self.validity && !other_assumptions.validity, + } + } +} + +// FIXME(jswrenn): This const op is not actually usable. Why? +// https://github.com/rust-lang/rust/pull/100726#issuecomment-1219928926 +#[unstable(feature = "transmutability", issue = "99571")] +impl core::ops::Add for Assume { + type Output = Assume; + + fn add(self, other_assumptions: Assume) -> Assume { + self.and(other_assumptions) + } +} + +// FIXME(jswrenn): This const op is not actually usable. Why? +// https://github.com/rust-lang/rust/pull/100726#issuecomment-1219928926 +#[unstable(feature = "transmutability", issue = "99571")] +impl core::ops::Sub for Assume { + type Output = Assume; + + fn sub(self, other_assumptions: Assume) -> Assume { + self.but_not(other_assumptions) + } +} diff --git a/CoqOfRust/core/net/display_buffer.rs b/CoqOfRust/core/net/display_buffer.rs new file mode 100644 index 000000000..bab84a973 --- /dev/null +++ b/CoqOfRust/core/net/display_buffer.rs @@ -0,0 +1,39 @@ +use crate::mem::MaybeUninit; +use crate::{fmt, str}; + +/// Used for slow path in `Display` implementations when alignment is required. +pub struct DisplayBuffer { + buf: [MaybeUninit; SIZE], + len: usize, +} + +impl DisplayBuffer { + #[inline] + pub const fn new() -> Self { + Self { buf: [MaybeUninit::uninit(); SIZE], len: 0 } + } + + #[inline] + pub fn as_str(&self) -> &str { + // SAFETY: `buf` is only written to by the `fmt::Write::write_str` implementation + // which writes a valid UTF-8 string to `buf` and correctly sets `len`. + unsafe { + let s = MaybeUninit::slice_assume_init_ref(&self.buf[..self.len]); + str::from_utf8_unchecked(s) + } + } +} + +impl fmt::Write for DisplayBuffer { + fn write_str(&mut self, s: &str) -> fmt::Result { + let bytes = s.as_bytes(); + + if let Some(buf) = self.buf.get_mut(self.len..(self.len + bytes.len())) { + MaybeUninit::copy_from_slice(buf, bytes); + self.len += bytes.len(); + Ok(()) + } else { + Err(fmt::Error) + } + } +} diff --git a/CoqOfRust/core/net/ip_addr.rs b/CoqOfRust/core/net/ip_addr.rs new file mode 100644 index 000000000..82f11f0ea --- /dev/null +++ b/CoqOfRust/core/net/ip_addr.rs @@ -0,0 +1,2399 @@ +use super::display_buffer::DisplayBuffer; +use crate::cmp::Ordering; +use crate::fmt::{self, Write}; +use crate::hash::{Hash, Hasher}; +use crate::iter; +use crate::mem::transmute; +use crate::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not}; + +/// An IP address, either IPv4 or IPv6. +/// +/// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their +/// respective documentation for more details. +/// +/// # Examples +/// +/// ``` +/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +/// +/// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); +/// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); +/// +/// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4)); +/// assert_eq!("::1".parse(), Ok(localhost_v6)); +/// +/// assert_eq!(localhost_v4.is_ipv6(), false); +/// assert_eq!(localhost_v4.is_ipv4(), true); +/// ``` +#[cfg_attr(not(test), rustc_diagnostic_item = "IpAddr")] +#[stable(feature = "ip_addr", since = "1.7.0")] +#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] +pub enum IpAddr { + /// An IPv4 address. + #[stable(feature = "ip_addr", since = "1.7.0")] + V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr), + /// An IPv6 address. + #[stable(feature = "ip_addr", since = "1.7.0")] + V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr), +} + +/// An IPv4 address. +/// +/// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791]. +/// They are usually represented as four octets. +/// +/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses. +/// +/// [IETF RFC 791]: https://tools.ietf.org/html/rfc791 +/// +/// # Textual representation +/// +/// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal +/// notation, divided by `.` (this is called "dot-decimal notation"). +/// Notably, octal numbers (which are indicated with a leading `0`) and hexadecimal numbers (which +/// are indicated with a leading `0x`) are not allowed per [IETF RFC 6943]. +/// +/// [IETF RFC 6943]: https://tools.ietf.org/html/rfc6943#section-3.1.1 +/// [`FromStr`]: crate::str::FromStr +/// +/// # Examples +/// +/// ``` +/// use std::net::Ipv4Addr; +/// +/// let localhost = Ipv4Addr::new(127, 0, 0, 1); +/// assert_eq!("127.0.0.1".parse(), Ok(localhost)); +/// assert_eq!(localhost.is_loopback(), true); +/// assert!("012.004.002.000".parse::().is_err()); // all octets are in octal +/// assert!("0000000.0.0.0".parse::().is_err()); // first octet is a zero in octal +/// assert!("0xcb.0x0.0x71.0x00".parse::().is_err()); // all octets are in hex +/// ``` +#[derive(Copy, Clone, PartialEq, Eq)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Ipv4Addr { + octets: [u8; 4], +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Ipv4Addr { + fn hash(&self, state: &mut H) { + // Hashers are often more efficient at hashing a fixed-width integer + // than a bytestring, so convert before hashing. We don't use to_bits() + // here as that may involve a byteswap which is unnecessary. + u32::from_ne_bytes(self.octets).hash(state); + } +} + +/// An IPv6 address. +/// +/// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291]. +/// They are usually represented as eight 16-bit segments. +/// +/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 +/// +/// # Embedding IPv4 Addresses +/// +/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses. +/// +/// To assist in the transition from IPv4 to IPv6 two types of IPv6 addresses that embed an IPv4 address were defined: +/// IPv4-compatible and IPv4-mapped addresses. Of these IPv4-compatible addresses have been officially deprecated. +/// +/// Both types of addresses are not assigned any special meaning by this implementation, +/// other than what the relevant standards prescribe. This means that an address like `::ffff:127.0.0.1`, +/// while representing an IPv4 loopback address, is not itself an IPv6 loopback address; only `::1` is. +/// To handle these so called "IPv4-in-IPv6" addresses, they have to first be converted to their canonical IPv4 address. +/// +/// ### IPv4-Compatible IPv6 Addresses +/// +/// IPv4-compatible IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.1], and have been officially deprecated. +/// The RFC describes the format of an "IPv4-Compatible IPv6 address" as follows: +/// +/// ```text +/// | 80 bits | 16 | 32 bits | +/// +--------------------------------------+--------------------------+ +/// |0000..............................0000|0000| IPv4 address | +/// +--------------------------------------+----+---------------------+ +/// ``` +/// So `::a.b.c.d` would be an IPv4-compatible IPv6 address representing the IPv4 address `a.b.c.d`. +/// +/// To convert from an IPv4 address to an IPv4-compatible IPv6 address, use [`Ipv4Addr::to_ipv6_compatible`]. +/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-compatible IPv6 address to the canonical IPv4 address. +/// +/// [IETF RFC 4291 Section 2.5.5.1]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.1 +/// +/// ### IPv4-Mapped IPv6 Addresses +/// +/// IPv4-mapped IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.2]. +/// The RFC describes the format of an "IPv4-Mapped IPv6 address" as follows: +/// +/// ```text +/// | 80 bits | 16 | 32 bits | +/// +--------------------------------------+--------------------------+ +/// |0000..............................0000|FFFF| IPv4 address | +/// +--------------------------------------+----+---------------------+ +/// ``` +/// So `::ffff:a.b.c.d` would be an IPv4-mapped IPv6 address representing the IPv4 address `a.b.c.d`. +/// +/// To convert from an IPv4 address to an IPv4-mapped IPv6 address, use [`Ipv4Addr::to_ipv6_mapped`]. +/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-mapped IPv6 address to the canonical IPv4 address. +/// Note that this will also convert the IPv6 loopback address `::1` to `0.0.0.1`. Use +/// [`Ipv6Addr::to_ipv4_mapped`] to avoid this. +/// +/// [IETF RFC 4291 Section 2.5.5.2]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2 +/// +/// # Textual representation +/// +/// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent +/// an IPv6 address in text, but in general, each segments is written in hexadecimal +/// notation, and segments are separated by `:`. For more information, see +/// [IETF RFC 5952]. +/// +/// [`FromStr`]: crate::str::FromStr +/// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952 +/// +/// # Examples +/// +/// ``` +/// use std::net::Ipv6Addr; +/// +/// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); +/// assert_eq!("::1".parse(), Ok(localhost)); +/// assert_eq!(localhost.is_loopback(), true); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Ipv6Addr { + octets: [u8; 16], +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Ipv6Addr { + fn hash(&self, state: &mut H) { + // Hashers are often more efficient at hashing a fixed-width integer + // than a bytestring, so convert before hashing. We don't use to_bits() + // here as that may involve unnecessary byteswaps. + u128::from_ne_bytes(self.octets).hash(state); + } +} + +/// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2]. +/// +/// # Stability Guarantees +/// +/// Not all possible values for a multicast scope have been assigned. +/// Future RFCs may introduce new scopes, which will be added as variants to this enum; +/// because of this the enum is marked as `#[non_exhaustive]`. +/// +/// # Examples +/// ``` +/// #![feature(ip)] +/// +/// use std::net::Ipv6Addr; +/// use std::net::Ipv6MulticastScope::*; +/// +/// // An IPv6 multicast address with global scope (`ff0e::`). +/// let address = Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0); +/// +/// // Will print "Global scope". +/// match address.multicast_scope() { +/// Some(InterfaceLocal) => println!("Interface-Local scope"), +/// Some(LinkLocal) => println!("Link-Local scope"), +/// Some(RealmLocal) => println!("Realm-Local scope"), +/// Some(AdminLocal) => println!("Admin-Local scope"), +/// Some(SiteLocal) => println!("Site-Local scope"), +/// Some(OrganizationLocal) => println!("Organization-Local scope"), +/// Some(Global) => println!("Global scope"), +/// Some(_) => println!("Unknown scope"), +/// None => println!("Not a multicast address!") +/// } +/// +/// ``` +/// +/// [IPv6 multicast address]: Ipv6Addr +/// [IETF RFC 7346 section 2]: https://tools.ietf.org/html/rfc7346#section-2 +#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)] +#[unstable(feature = "ip", issue = "27709")] +#[non_exhaustive] +pub enum Ipv6MulticastScope { + /// Interface-Local scope. + InterfaceLocal, + /// Link-Local scope. + LinkLocal, + /// Realm-Local scope. + RealmLocal, + /// Admin-Local scope. + AdminLocal, + /// Site-Local scope. + SiteLocal, + /// Organization-Local scope. + OrganizationLocal, + /// Global scope. + Global, +} + +impl IpAddr { + /// Returns [`true`] for the special 'unspecified' address. + /// + /// See the documentation for [`Ipv4Addr::is_unspecified()`] and + /// [`Ipv6Addr::is_unspecified()`] for more details. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(feature = "ip_shared", since = "1.12.0")] + #[must_use] + #[inline] + pub const fn is_unspecified(&self) -> bool { + match self { + IpAddr::V4(ip) => ip.is_unspecified(), + IpAddr::V6(ip) => ip.is_unspecified(), + } + } + + /// Returns [`true`] if this is a loopback address. + /// + /// See the documentation for [`Ipv4Addr::is_loopback()`] and + /// [`Ipv6Addr::is_loopback()`] for more details. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(feature = "ip_shared", since = "1.12.0")] + #[must_use] + #[inline] + pub const fn is_loopback(&self) -> bool { + match self { + IpAddr::V4(ip) => ip.is_loopback(), + IpAddr::V6(ip) => ip.is_loopback(), + } + } + + /// Returns [`true`] if the address appears to be globally routable. + /// + /// See the documentation for [`Ipv4Addr::is_global()`] and + /// [`Ipv6Addr::is_global()`] for more details. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true); + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_global(&self) -> bool { + match self { + IpAddr::V4(ip) => ip.is_global(), + IpAddr::V6(ip) => ip.is_global(), + } + } + + /// Returns [`true`] if this is a multicast address. + /// + /// See the documentation for [`Ipv4Addr::is_multicast()`] and + /// [`Ipv6Addr::is_multicast()`] for more details. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(feature = "ip_shared", since = "1.12.0")] + #[must_use] + #[inline] + pub const fn is_multicast(&self) -> bool { + match self { + IpAddr::V4(ip) => ip.is_multicast(), + IpAddr::V6(ip) => ip.is_multicast(), + } + } + + /// Returns [`true`] if this address is in a range designated for documentation. + /// + /// See the documentation for [`Ipv4Addr::is_documentation()`] and + /// [`Ipv6Addr::is_documentation()`] for more details. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true); + /// assert_eq!( + /// IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_documentation(), + /// true + /// ); + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_documentation(&self) -> bool { + match self { + IpAddr::V4(ip) => ip.is_documentation(), + IpAddr::V6(ip) => ip.is_documentation(), + } + } + + /// Returns [`true`] if this address is in a range designated for benchmarking. + /// + /// See the documentation for [`Ipv4Addr::is_benchmarking()`] and + /// [`Ipv6Addr::is_benchmarking()`] for more details. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(198, 19, 255, 255)).is_benchmarking(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0)).is_benchmarking(), true); + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_benchmarking(&self) -> bool { + match self { + IpAddr::V4(ip) => ip.is_benchmarking(), + IpAddr::V6(ip) => ip.is_benchmarking(), + } + } + + /// Returns [`true`] if this address is an [`IPv4` address], and [`false`] + /// otherwise. + /// + /// [`IPv4` address]: IpAddr::V4 + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(feature = "ipaddr_checker", since = "1.16.0")] + #[must_use] + #[inline] + pub const fn is_ipv4(&self) -> bool { + matches!(self, IpAddr::V4(_)) + } + + /// Returns [`true`] if this address is an [`IPv6` address], and [`false`] + /// otherwise. + /// + /// [`IPv6` address]: IpAddr::V6 + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(feature = "ipaddr_checker", since = "1.16.0")] + #[must_use] + #[inline] + pub const fn is_ipv6(&self) -> bool { + matches!(self, IpAddr::V6(_)) + } + + /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6 + /// address, otherwise returns `self` as-is. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// let localhost_v4 = Ipv4Addr::new(127, 0, 0, 1); + /// + /// assert_eq!(IpAddr::V4(localhost_v4).to_canonical(), localhost_v4); + /// assert_eq!(IpAddr::V6(localhost_v4.to_ipv6_mapped()).to_canonical(), localhost_v4); + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).to_canonical().is_loopback(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).is_loopback(), false); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).to_canonical().is_loopback(), true); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "ip_to_canonical", since = "1.75.0")] + #[rustc_const_stable(feature = "ip_to_canonical", since = "1.75.0")] + pub const fn to_canonical(&self) -> IpAddr { + match self { + IpAddr::V4(_) => *self, + IpAddr::V6(v6) => v6.to_canonical(), + } + } +} + +impl Ipv4Addr { + /// Creates a new IPv4 address from four eight-bit octets. + /// + /// The result will represent the IP address `a`.`b`.`c`.`d`. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::new(127, 0, 0, 1); + /// ``` + #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + #[inline] + pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { + Ipv4Addr { octets: [a, b, c, d] } + } + + /// The size of an IPv4 address in bits. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::BITS, 32); + /// ``` + #[stable(feature = "ip_bits", since = "1.80.0")] + pub const BITS: u32 = 32; + + /// Converts an IPv4 address into a `u32` representation using native byte order. + /// + /// Although IPv4 addresses are big-endian, the `u32` value will use the target platform's + /// native byte order. That is, the `u32` value is an integer representation of the IPv4 + /// address and not an integer interpretation of the IPv4 address's big-endian bitstring. This + /// means that the `u32` value masked with `0xffffff00` will set the last octet in the address + /// to 0, regardless of the target platform's endianness. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78); + /// assert_eq!(0x12345678, addr.to_bits()); + /// ``` + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78); + /// let addr_bits = addr.to_bits() & 0xffffff00; + /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x00), Ipv4Addr::from_bits(addr_bits)); + /// + /// ``` + #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")] + #[stable(feature = "ip_bits", since = "1.80.0")] + #[must_use] + #[inline] + pub const fn to_bits(self) -> u32 { + u32::from_be_bytes(self.octets) + } + + /// Converts a native byte order `u32` into an IPv4 address. + /// + /// See [`Ipv4Addr::to_bits`] for an explanation on endianness. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::from(0x12345678); + /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr); + /// ``` + #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")] + #[stable(feature = "ip_bits", since = "1.80.0")] + #[must_use] + #[inline] + pub const fn from_bits(bits: u32) -> Ipv4Addr { + Ipv4Addr { octets: bits.to_be_bytes() } + } + + /// An IPv4 address with the address pointing to localhost: `127.0.0.1` + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::LOCALHOST; + /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1)); + /// ``` + #[stable(feature = "ip_constructors", since = "1.30.0")] + pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1); + + /// An IPv4 address representing an unspecified address: `0.0.0.0` + /// + /// This corresponds to the constant `INADDR_ANY` in other languages. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::UNSPECIFIED; + /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0)); + /// ``` + #[doc(alias = "INADDR_ANY")] + #[stable(feature = "ip_constructors", since = "1.30.0")] + pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0); + + /// An IPv4 address representing the broadcast address: `255.255.255.255`. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::BROADCAST; + /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255)); + /// ``` + #[stable(feature = "ip_constructors", since = "1.30.0")] + pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255); + + /// Returns the four eight-bit integers that make up this address. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::new(127, 0, 0, 1); + /// assert_eq!(addr.octets(), [127, 0, 0, 1]); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + #[inline] + pub const fn octets(&self) -> [u8; 4] { + self.octets + } + + /// Creates an `Ipv4Addr` from a four element byte array. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip_from)] + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::from_octets([13u8, 12u8, 11u8, 10u8]); + /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr); + /// ``` + #[unstable(feature = "ip_from", issue = "131360")] + #[must_use] + #[inline] + pub const fn from_octets(octets: [u8; 4]) -> Ipv4Addr { + Ipv4Addr { octets } + } + + /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`). + /// + /// This property is defined in _UNIX Network Programming, Second Edition_, + /// W. Richard Stevens, p. 891; see also [ip7]. + /// + /// [ip7]: https://man7.org/linux/man-pages/man7/ip.7.html + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true); + /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false); + /// ``` + #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] + #[stable(feature = "ip_shared", since = "1.12.0")] + #[must_use] + #[inline] + pub const fn is_unspecified(&self) -> bool { + u32::from_be_bytes(self.octets) == 0 + } + + /// Returns [`true`] if this is a loopback address (`127.0.0.0/8`). + /// + /// This property is defined by [IETF RFC 1122]. + /// + /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true); + /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] + #[inline] + pub const fn is_loopback(&self) -> bool { + self.octets()[0] == 127 + } + + /// Returns [`true`] if this is a private address. + /// + /// The private address ranges are defined in [IETF RFC 1918] and include: + /// + /// - `10.0.0.0/8` + /// - `172.16.0.0/12` + /// - `192.168.0.0/16` + /// + /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true); + /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true); + /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true); + /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true); + /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false); + /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true); + /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] + #[inline] + pub const fn is_private(&self) -> bool { + match self.octets() { + [10, ..] => true, + [172, b, ..] if b >= 16 && b <= 31 => true, + [192, 168, ..] => true, + _ => false, + } + } + + /// Returns [`true`] if the address is link-local (`169.254.0.0/16`). + /// + /// This property is defined by [IETF RFC 3927]. + /// + /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true); + /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true); + /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] + #[inline] + pub const fn is_link_local(&self) -> bool { + matches!(self.octets(), [169, 254, ..]) + } + + /// Returns [`true`] if the address appears to be globally reachable + /// as specified by the [IANA IPv4 Special-Purpose Address Registry]. + /// + /// Whether or not an address is practically reachable will depend on your + /// network configuration. Most IPv4 addresses are globally reachable, unless + /// they are specifically defined as *not* globally reachable. + /// + /// Non-exhaustive list of notable addresses that are not globally reachable: + /// + /// - The [unspecified address] ([`is_unspecified`](Ipv4Addr::is_unspecified)) + /// - Addresses reserved for private use ([`is_private`](Ipv4Addr::is_private)) + /// - Addresses in the shared address space ([`is_shared`](Ipv4Addr::is_shared)) + /// - Loopback addresses ([`is_loopback`](Ipv4Addr::is_loopback)) + /// - Link-local addresses ([`is_link_local`](Ipv4Addr::is_link_local)) + /// - Addresses reserved for documentation ([`is_documentation`](Ipv4Addr::is_documentation)) + /// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv4Addr::is_benchmarking)) + /// - Reserved addresses ([`is_reserved`](Ipv4Addr::is_reserved)) + /// - The [broadcast address] ([`is_broadcast`](Ipv4Addr::is_broadcast)) + /// + /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv4 Special-Purpose Address Registry]. + /// + /// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml + /// [unspecified address]: Ipv4Addr::UNSPECIFIED + /// [broadcast address]: Ipv4Addr::BROADCAST + + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv4Addr; + /// + /// // Most IPv4 addresses are globally reachable: + /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true); + /// + /// // However some addresses have been assigned a special meaning + /// // that makes them not globally reachable. Some examples are: + /// + /// // The unspecified address (`0.0.0.0`) + /// assert_eq!(Ipv4Addr::UNSPECIFIED.is_global(), false); + /// + /// // Addresses reserved for private use (`10.0.0.0/8`, `172.16.0.0/12`, 192.168.0.0/16) + /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false); + /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false); + /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false); + /// + /// // Addresses in the shared address space (`100.64.0.0/10`) + /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false); + /// + /// // The loopback addresses (`127.0.0.0/8`) + /// assert_eq!(Ipv4Addr::LOCALHOST.is_global(), false); + /// + /// // Link-local addresses (`169.254.0.0/16`) + /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false); + /// + /// // Addresses reserved for documentation (`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`) + /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false); + /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false); + /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false); + /// + /// // Addresses reserved for benchmarking (`198.18.0.0/15`) + /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false); + /// + /// // Reserved addresses (`240.0.0.0/4`) + /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false); + /// + /// // The broadcast address (`255.255.255.255`) + /// assert_eq!(Ipv4Addr::BROADCAST.is_global(), false); + /// + /// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry. + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_global(&self) -> bool { + !(self.octets()[0] == 0 // "This network" + || self.is_private() + || self.is_shared() + || self.is_loopback() + || self.is_link_local() + // addresses reserved for future protocols (`192.0.0.0/24`) + // .9 and .10 are documented as globally reachable so they're excluded + || ( + self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0 + && self.octets()[3] != 9 && self.octets()[3] != 10 + ) + || self.is_documentation() + || self.is_benchmarking() + || self.is_reserved() + || self.is_broadcast()) + } + + /// Returns [`true`] if this address is part of the Shared Address Space defined in + /// [IETF RFC 6598] (`100.64.0.0/10`). + /// + /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598 + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true); + /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true); + /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false); + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_shared(&self) -> bool { + self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000) + } + + /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for + /// network devices benchmarking. + /// + /// This range is defined in [IETF RFC 2544] as `192.18.0.0` through + /// `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`. + /// + /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544 + /// [errata 423]: https://www.rfc-editor.org/errata/eid423 + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false); + /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true); + /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true); + /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false); + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_benchmarking(&self) -> bool { + self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18 + } + + /// Returns [`true`] if this address is reserved by IANA for future use. + /// + /// [IETF RFC 1112] defines the block of reserved addresses as `240.0.0.0/4`. + /// This range normally includes the broadcast address `255.255.255.255`, but + /// this implementation explicitly excludes it, since it is obviously not + /// reserved for future use. + /// + /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112 + /// + /// # Warning + /// + /// As IANA assigns new addresses, this method will be + /// updated. This may result in non-reserved addresses being + /// treated as reserved in code that relies on an outdated version + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true); + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true); + /// + /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false); + /// // The broadcast address is not considered as reserved for future use by this implementation + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false); + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_reserved(&self) -> bool { + self.octets()[0] & 240 == 240 && !self.is_broadcast() + } + + /// Returns [`true`] if this is a multicast address (`224.0.0.0/4`). + /// + /// Multicast addresses have a most significant octet between `224` and `239`, + /// and is defined by [IETF RFC 5771]. + /// + /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true); + /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true); + /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] + #[inline] + pub const fn is_multicast(&self) -> bool { + self.octets()[0] >= 224 && self.octets()[0] <= 239 + } + + /// Returns [`true`] if this is a broadcast address (`255.255.255.255`). + /// + /// A broadcast address has all octets set to `255` as defined in [IETF RFC 919]. + /// + /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true); + /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] + #[inline] + pub const fn is_broadcast(&self) -> bool { + u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets()) + } + + /// Returns [`true`] if this address is in a range designated for documentation. + /// + /// This is defined in [IETF RFC 5737]: + /// + /// - `192.0.2.0/24` (TEST-NET-1) + /// - `198.51.100.0/24` (TEST-NET-2) + /// - `203.0.113.0/24` (TEST-NET-3) + /// + /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true); + /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true); + /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true); + /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] + #[inline] + pub const fn is_documentation(&self) -> bool { + matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _]) + } + + /// Converts this address to an [IPv4-compatible] [`IPv6` address]. + /// + /// `a.b.c.d` becomes `::a.b.c.d` + /// + /// Note that IPv4-compatible addresses have been officially deprecated. + /// If you don't explicitly need an IPv4-compatible address for legacy reasons, consider using `to_ipv6_mapped` instead. + /// + /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses + /// [`IPv6` address]: Ipv6Addr + /// + /// # Examples + /// + /// ``` + /// use std::net::{Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!( + /// Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(), + /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x2ff) + /// ); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_ipv6_compatible(&self) -> Ipv6Addr { + let [a, b, c, d] = self.octets(); + Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] } + } + + /// Converts this address to an [IPv4-mapped] [`IPv6` address]. + /// + /// `a.b.c.d` becomes `::ffff:a.b.c.d` + /// + /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses + /// [`IPv6` address]: Ipv6Addr + /// + /// # Examples + /// + /// ``` + /// use std::net::{Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(), + /// Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff)); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_ipv6_mapped(&self) -> Ipv6Addr { + let [a, b, c, d] = self.octets(); + Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] } + } +} + +#[stable(feature = "ip_addr", since = "1.7.0")] +impl fmt::Display for IpAddr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + IpAddr::V4(ip) => ip.fmt(fmt), + IpAddr::V6(ip) => ip.fmt(fmt), + } + } +} + +#[stable(feature = "ip_addr", since = "1.7.0")] +impl fmt::Debug for IpAddr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + +#[stable(feature = "ip_from_ip", since = "1.16.0")] +impl From for IpAddr { + /// Copies this address to a new `IpAddr::V4`. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr}; + /// + /// let addr = Ipv4Addr::new(127, 0, 0, 1); + /// + /// assert_eq!( + /// IpAddr::V4(addr), + /// IpAddr::from(addr) + /// ) + /// ``` + #[inline] + fn from(ipv4: Ipv4Addr) -> IpAddr { + IpAddr::V4(ipv4) + } +} + +#[stable(feature = "ip_from_ip", since = "1.16.0")] +impl From for IpAddr { + /// Copies this address to a new `IpAddr::V6`. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv6Addr}; + /// + /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); + /// + /// assert_eq!( + /// IpAddr::V6(addr), + /// IpAddr::from(addr) + /// ); + /// ``` + #[inline] + fn from(ipv6: Ipv6Addr) -> IpAddr { + IpAddr::V6(ipv6) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Ipv4Addr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let octets = self.octets(); + + // If there are no alignment requirements, write the IP address directly to `f`. + // Otherwise, write it to a local buffer and then use `f.pad`. + if fmt.precision().is_none() && fmt.width().is_none() { + write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]) + } else { + const LONGEST_IPV4_ADDR: &str = "255.255.255.255"; + + let mut buf = DisplayBuffer::<{ LONGEST_IPV4_ADDR.len() }>::new(); + // Buffer is long enough for the longest possible IPv4 address, so this should never fail. + write!(buf, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap(); + + fmt.pad(buf.as_str()) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Ipv4Addr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + +#[stable(feature = "ip_cmp", since = "1.16.0")] +impl PartialEq for IpAddr { + #[inline] + fn eq(&self, other: &Ipv4Addr) -> bool { + match self { + IpAddr::V4(v4) => v4 == other, + IpAddr::V6(_) => false, + } + } +} + +#[stable(feature = "ip_cmp", since = "1.16.0")] +impl PartialEq for Ipv4Addr { + #[inline] + fn eq(&self, other: &IpAddr) -> bool { + match other { + IpAddr::V4(v4) => self == v4, + IpAddr::V6(_) => false, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Ipv4Addr { + #[inline] + fn partial_cmp(&self, other: &Ipv4Addr) -> Option { + Some(self.cmp(other)) + } +} + +#[stable(feature = "ip_cmp", since = "1.16.0")] +impl PartialOrd for IpAddr { + #[inline] + fn partial_cmp(&self, other: &Ipv4Addr) -> Option { + match self { + IpAddr::V4(v4) => v4.partial_cmp(other), + IpAddr::V6(_) => Some(Ordering::Greater), + } + } +} + +#[stable(feature = "ip_cmp", since = "1.16.0")] +impl PartialOrd for Ipv4Addr { + #[inline] + fn partial_cmp(&self, other: &IpAddr) -> Option { + match other { + IpAddr::V4(v4) => self.partial_cmp(v4), + IpAddr::V6(_) => Some(Ordering::Less), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Ipv4Addr { + #[inline] + fn cmp(&self, other: &Ipv4Addr) -> Ordering { + self.octets.cmp(&other.octets) + } +} + +#[stable(feature = "ip_u32", since = "1.1.0")] +impl From for u32 { + /// Uses [`Ipv4Addr::to_bits`] to convert an IPv4 address to a host byte order `u32`. + #[inline] + fn from(ip: Ipv4Addr) -> u32 { + ip.to_bits() + } +} + +#[stable(feature = "ip_u32", since = "1.1.0")] +impl From for Ipv4Addr { + /// Uses [`Ipv4Addr::from_bits`] to convert a host byte order `u32` into an IPv4 address. + #[inline] + fn from(ip: u32) -> Ipv4Addr { + Ipv4Addr::from_bits(ip) + } +} + +#[stable(feature = "from_slice_v4", since = "1.9.0")] +impl From<[u8; 4]> for Ipv4Addr { + /// Creates an `Ipv4Addr` from a four element byte array. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]); + /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr); + /// ``` + #[inline] + fn from(octets: [u8; 4]) -> Ipv4Addr { + Ipv4Addr { octets } + } +} + +#[stable(feature = "ip_from_slice", since = "1.17.0")] +impl From<[u8; 4]> for IpAddr { + /// Creates an `IpAddr::V4` from a four element byte array. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr}; + /// + /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]); + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr); + /// ``` + #[inline] + fn from(octets: [u8; 4]) -> IpAddr { + IpAddr::V4(Ipv4Addr::from(octets)) + } +} + +impl Ipv6Addr { + /// Creates a new IPv6 address from eight 16-bit segments. + /// + /// The result will represent the IP address `a:b:c:d:e:f:g:h`. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); + /// ``` + #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + #[inline] + pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { + let addr16 = [ + a.to_be(), + b.to_be(), + c.to_be(), + d.to_be(), + e.to_be(), + f.to_be(), + g.to_be(), + h.to_be(), + ]; + Ipv6Addr { + // All elements in `addr16` are big endian. + // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`. + octets: unsafe { transmute::<_, [u8; 16]>(addr16) }, + } + } + + /// The size of an IPv6 address in bits. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::BITS, 128); + /// ``` + #[stable(feature = "ip_bits", since = "1.80.0")] + pub const BITS: u32 = 128; + + /// Converts an IPv6 address into a `u128` representation using native byte order. + /// + /// Although IPv6 addresses are big-endian, the `u128` value will use the target platform's + /// native byte order. That is, the `u128` value is an integer representation of the IPv6 + /// address and not an integer interpretation of the IPv6 address's big-endian bitstring. This + /// means that the `u128` value masked with `0xffffffffffffffffffffffffffff0000_u128` will set + /// the last segment in the address to 0, regardless of the target platform's endianness. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::new( + /// 0x1020, 0x3040, 0x5060, 0x7080, + /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D, + /// ); + /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr)); + /// ``` + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::new( + /// 0x1020, 0x3040, 0x5060, 0x7080, + /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D, + /// ); + /// let addr_bits = addr.to_bits() & 0xffffffffffffffffffffffffffff0000_u128; + /// assert_eq!( + /// Ipv6Addr::new( + /// 0x1020, 0x3040, 0x5060, 0x7080, + /// 0x90A0, 0xB0C0, 0xD0E0, 0x0000, + /// ), + /// Ipv6Addr::from_bits(addr_bits)); + /// + /// ``` + #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")] + #[stable(feature = "ip_bits", since = "1.80.0")] + #[must_use] + #[inline] + pub const fn to_bits(self) -> u128 { + u128::from_be_bytes(self.octets) + } + + /// Converts a native byte order `u128` into an IPv6 address. + /// + /// See [`Ipv6Addr::to_bits`] for an explanation on endianness. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128); + /// assert_eq!( + /// Ipv6Addr::new( + /// 0x1020, 0x3040, 0x5060, 0x7080, + /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D, + /// ), + /// addr); + /// ``` + #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")] + #[stable(feature = "ip_bits", since = "1.80.0")] + #[must_use] + #[inline] + pub const fn from_bits(bits: u128) -> Ipv6Addr { + Ipv6Addr { octets: bits.to_be_bytes() } + } + + /// An IPv6 address representing localhost: `::1`. + /// + /// This corresponds to constant `IN6ADDR_LOOPBACK_INIT` or `in6addr_loopback` in other + /// languages. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::LOCALHOST; + /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); + /// ``` + #[doc(alias = "IN6ADDR_LOOPBACK_INIT")] + #[doc(alias = "in6addr_loopback")] + #[stable(feature = "ip_constructors", since = "1.30.0")] + pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); + + /// An IPv6 address representing the unspecified address: `::`. + /// + /// This corresponds to constant `IN6ADDR_ANY_INIT` or `in6addr_any` in other languages. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::UNSPECIFIED; + /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); + /// ``` + #[doc(alias = "IN6ADDR_ANY_INIT")] + #[doc(alias = "in6addr_any")] + #[stable(feature = "ip_constructors", since = "1.30.0")] + pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0); + + /// Returns the eight 16-bit segments that make up this address. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(), + /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + #[inline] + pub const fn segments(&self) -> [u16; 8] { + // All elements in `self.octets` must be big endian. + // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`. + let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.octets) }; + // We want native endian u16 + [ + u16::from_be(a), + u16::from_be(b), + u16::from_be(c), + u16::from_be(d), + u16::from_be(e), + u16::from_be(f), + u16::from_be(g), + u16::from_be(h), + ] + } + + /// Creates an `Ipv6Addr` from an eight element 16-bit array. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip_from)] + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::from_segments([ + /// 0x20du16, 0x20cu16, 0x20bu16, 0x20au16, + /// 0x209u16, 0x208u16, 0x207u16, 0x206u16, + /// ]); + /// assert_eq!( + /// Ipv6Addr::new( + /// 0x20d, 0x20c, 0x20b, 0x20a, + /// 0x209, 0x208, 0x207, 0x206, + /// ), + /// addr + /// ); + /// ``` + #[unstable(feature = "ip_from", issue = "131360")] + #[must_use] + #[inline] + pub const fn from_segments(segments: [u16; 8]) -> Ipv6Addr { + let [a, b, c, d, e, f, g, h] = segments; + Ipv6Addr::new(a, b, c, d, e, f, g, h) + } + + /// Returns [`true`] for the special 'unspecified' address (`::`). + /// + /// This property is defined in [IETF RFC 4291]. + /// + /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] + #[inline] + pub const fn is_unspecified(&self) -> bool { + u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets()) + } + + /// Returns [`true`] if this is the [loopback address] (`::1`), + /// as defined in [IETF RFC 4291 section 2.5.3]. + /// + /// Contrary to IPv4, in IPv6 there is only one loopback address. + /// + /// [loopback address]: Ipv6Addr::LOCALHOST + /// [IETF RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] + #[inline] + pub const fn is_loopback(&self) -> bool { + u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets()) + } + + /// Returns [`true`] if the address appears to be globally reachable + /// as specified by the [IANA IPv6 Special-Purpose Address Registry]. + /// + /// Whether or not an address is practically reachable will depend on your + /// network configuration. Most IPv6 addresses are globally reachable, unless + /// they are specifically defined as *not* globally reachable. + /// + /// Non-exhaustive list of notable addresses that are not globally reachable: + /// - The [unspecified address] ([`is_unspecified`](Ipv6Addr::is_unspecified)) + /// - The [loopback address] ([`is_loopback`](Ipv6Addr::is_loopback)) + /// - IPv4-mapped addresses + /// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv6Addr::is_benchmarking)) + /// - Addresses reserved for documentation ([`is_documentation`](Ipv6Addr::is_documentation)) + /// - Unique local addresses ([`is_unique_local`](Ipv6Addr::is_unique_local)) + /// - Unicast addresses with link-local scope ([`is_unicast_link_local`](Ipv6Addr::is_unicast_link_local)) + /// + /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv6 Special-Purpose Address Registry]. + /// + /// Note that an address having global scope is not the same as being globally reachable, + /// and there is no direct relation between the two concepts: There exist addresses with global scope + /// that are not globally reachable (for example unique local addresses), + /// and addresses that are globally reachable without having global scope + /// (multicast addresses with non-global scope). + /// + /// [IANA IPv6 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml + /// [unspecified address]: Ipv6Addr::UNSPECIFIED + /// [loopback address]: Ipv6Addr::LOCALHOST + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// // Most IPv6 addresses are globally reachable: + /// assert_eq!(Ipv6Addr::new(0x26, 0, 0x1c9, 0, 0, 0xafc8, 0x10, 0x1).is_global(), true); + /// + /// // However some addresses have been assigned a special meaning + /// // that makes them not globally reachable. Some examples are: + /// + /// // The unspecified address (`::`) + /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_global(), false); + /// + /// // The loopback address (`::1`) + /// assert_eq!(Ipv6Addr::LOCALHOST.is_global(), false); + /// + /// // IPv4-mapped addresses (`::ffff:0:0/96`) + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), false); + /// + /// // Addresses reserved for benchmarking (`2001:2::/48`) + /// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false); + /// + /// // Addresses reserved for documentation (`2001:db8::/32`) + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false); + /// + /// // Unique local addresses (`fc00::/7`) + /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false); + /// + /// // Unicast addresses with link-local scope (`fe80::/10`) + /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 1).is_global(), false); + /// + /// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry. + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_global(&self) -> bool { + !(self.is_unspecified() + || self.is_loopback() + // IPv4-mapped Address (`::ffff:0:0/96`) + || matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _]) + // IPv4-IPv6 Translat. (`64:ff9b:1::/48`) + || matches!(self.segments(), [0x64, 0xff9b, 1, _, _, _, _, _]) + // Discard-Only Address Block (`100::/64`) + || matches!(self.segments(), [0x100, 0, 0, 0, _, _, _, _]) + // IETF Protocol Assignments (`2001::/23`) + || (matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200) + && !( + // Port Control Protocol Anycast (`2001:1::1`) + u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001 + // Traversal Using Relays around NAT Anycast (`2001:1::2`) + || u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002 + // AMT (`2001:3::/32`) + || matches!(self.segments(), [0x2001, 3, _, _, _, _, _, _]) + // AS112-v6 (`2001:4:112::/48`) + || matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _]) + // ORCHIDv2 (`2001:20::/28`) + // Drone Remote ID Protocol Entity Tags (DETs) Prefix (`2001:30::/28`)` + || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x3F) + )) + // 6to4 (`2002::/16`) – it's not explicitly documented as globally reachable, + // IANA says N/A. + || matches!(self.segments(), [0x2002, _, _, _, _, _, _, _]) + || self.is_documentation() + || self.is_unique_local() + || self.is_unicast_link_local()) + } + + /// Returns [`true`] if this is a unique local address (`fc00::/7`). + /// + /// This property is defined in [IETF RFC 4193]. + /// + /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false); + /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); + /// ``` + #[must_use] + #[inline] + #[stable(feature = "ipv6_is_unique_local", since = "1.84.0")] + #[rustc_const_stable(feature = "ipv6_is_unique_local", since = "1.84.0")] + pub const fn is_unique_local(&self) -> bool { + (self.segments()[0] & 0xfe00) == 0xfc00 + } + + /// Returns [`true`] if this is a unicast address, as defined by [IETF RFC 4291]. + /// Any address that is not a [multicast address] (`ff00::/8`) is unicast. + /// + /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 + /// [multicast address]: Ipv6Addr::is_multicast + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// // The unspecified and loopback addresses are unicast. + /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_unicast(), true); + /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast(), true); + /// + /// // Any address that is not a multicast address (`ff00::/8`) is unicast. + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true); + /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false); + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_unicast(&self) -> bool { + !self.is_multicast() + } + + /// Returns `true` if the address is a unicast address with link-local scope, + /// as defined in [RFC 4291]. + /// + /// A unicast address has link-local scope if it has the prefix `fe80::/10`, as per [RFC 4291 section 2.4]. + /// Note that this encompasses more addresses than those defined in [RFC 4291 section 2.5.6], + /// which describes "Link-Local IPv6 Unicast Addresses" as having the following stricter format: + /// + /// ```text + /// | 10 bits | 54 bits | 64 bits | + /// +----------+-------------------------+----------------------------+ + /// |1111111010| 0 | interface ID | + /// +----------+-------------------------+----------------------------+ + /// ``` + /// So while currently the only addresses with link-local scope an application will encounter are all in `fe80::/64`, + /// this might change in the future with the publication of new standards. More addresses in `fe80::/10` could be allocated, + /// and those addresses will have link-local scope. + /// + /// Also note that while [RFC 4291 section 2.5.3] mentions about the [loopback address] (`::1`) that "it is treated as having Link-Local scope", + /// this does not mean that the loopback address actually has link-local scope and this method will return `false` on it. + /// + /// [RFC 4291]: https://tools.ietf.org/html/rfc4291 + /// [RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4 + /// [RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3 + /// [RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6 + /// [loopback address]: Ipv6Addr::LOCALHOST + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// // The loopback address (`::1`) does not actually have link-local scope. + /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast_link_local(), false); + /// + /// // Only addresses in `fe80::/10` have link-local scope. + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), false); + /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); + /// + /// // Addresses outside the stricter `fe80::/64` also have link-local scope. + /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0).is_unicast_link_local(), true); + /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); + /// ``` + #[must_use] + #[inline] + #[stable(feature = "ipv6_is_unique_local", since = "1.84.0")] + #[rustc_const_stable(feature = "ipv6_is_unique_local", since = "1.84.0")] + pub const fn is_unicast_link_local(&self) -> bool { + (self.segments()[0] & 0xffc0) == 0xfe80 + } + + /// Returns [`true`] if this is an address reserved for documentation + /// (`2001:db8::/32`). + /// + /// This property is defined in [IETF RFC 3849]. + /// + /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849 + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false); + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_documentation(&self) -> bool { + (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) + } + + /// Returns [`true`] if this is an address reserved for benchmarking (`2001:2::/48`). + /// + /// This property is defined in [IETF RFC 5180], where it is mistakenly specified as covering the range `2001:0200::/48`. + /// This is corrected in [IETF RFC Errata 1752] to `2001:0002::/48`. + /// + /// [IETF RFC 5180]: https://tools.ietf.org/html/rfc5180 + /// [IETF RFC Errata 1752]: https://www.rfc-editor.org/errata_search.php?eid=1752 + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc613, 0x0).is_benchmarking(), false); + /// assert_eq!(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0).is_benchmarking(), true); + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_benchmarking(&self) -> bool { + (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && (self.segments()[2] == 0) + } + + /// Returns [`true`] if the address is a globally routable unicast address. + /// + /// The following return false: + /// + /// - the loopback address + /// - the link-local addresses + /// - unique local addresses + /// - the unspecified address + /// - the address range reserved for documentation + /// + /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7] + /// + /// ```no_rust + /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer + /// be supported in new implementations (i.e., new implementations must treat this prefix as + /// Global Unicast). + /// ``` + /// + /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7 + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true); + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_unicast_global(&self) -> bool { + self.is_unicast() + && !self.is_loopback() + && !self.is_unicast_link_local() + && !self.is_unique_local() + && !self.is_unspecified() + && !self.is_documentation() + && !self.is_benchmarking() + } + + /// Returns the address's multicast scope if the address is multicast. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::{Ipv6Addr, Ipv6MulticastScope}; + /// + /// assert_eq!( + /// Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(), + /// Some(Ipv6MulticastScope::Global) + /// ); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn multicast_scope(&self) -> Option { + if self.is_multicast() { + match self.segments()[0] & 0x000f { + 1 => Some(Ipv6MulticastScope::InterfaceLocal), + 2 => Some(Ipv6MulticastScope::LinkLocal), + 3 => Some(Ipv6MulticastScope::RealmLocal), + 4 => Some(Ipv6MulticastScope::AdminLocal), + 5 => Some(Ipv6MulticastScope::SiteLocal), + 8 => Some(Ipv6MulticastScope::OrganizationLocal), + 14 => Some(Ipv6MulticastScope::Global), + _ => None, + } + } else { + None + } + } + + /// Returns [`true`] if this is a multicast address (`ff00::/8`). + /// + /// This property is defined by [IETF RFC 4291]. + /// + /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] + #[inline] + pub const fn is_multicast(&self) -> bool { + (self.segments()[0] & 0xff00) == 0xff00 + } + + /// Returns [`true`] if the address is an IPv4-mapped address (`::ffff:0:0/96`). + /// + /// IPv4-mapped addresses can be converted to their canonical IPv4 address with + /// [`to_ipv4_mapped`](Ipv6Addr::to_ipv4_mapped). + /// + /// # Examples + /// ``` + /// #![feature(ip)] + /// + /// use std::net::{Ipv4Addr, Ipv6Addr}; + /// + /// let ipv4_mapped = Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(); + /// assert_eq!(ipv4_mapped.is_ipv4_mapped(), true); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff).is_ipv4_mapped(), true); + /// + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_ipv4_mapped(), false); + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_ipv4_mapped(&self) -> bool { + matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _]) + } + + /// Converts this address to an [`IPv4` address] if it's an [IPv4-mapped] address, + /// as defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`]. + /// + /// `::ffff:a.b.c.d` becomes `a.b.c.d`. + /// All addresses *not* starting with `::ffff` will return `None`. + /// + /// [`IPv4` address]: Ipv4Addr + /// [IPv4-mapped]: Ipv6Addr + /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2 + /// + /// # Examples + /// + /// ``` + /// use std::net::{Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(), + /// Some(Ipv4Addr::new(192, 10, 2, 255))); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0")] + #[rustc_const_stable(feature = "const_ipv6_to_ipv4_mapped", since = "1.75.0")] + pub const fn to_ipv4_mapped(&self) -> Option { + match self.octets() { + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => { + Some(Ipv4Addr::new(a, b, c, d)) + } + _ => None, + } + } + + /// Converts this address to an [`IPv4` address] if it is either + /// an [IPv4-compatible] address as defined in [IETF RFC 4291 section 2.5.5.1], + /// or an [IPv4-mapped] address as defined in [IETF RFC 4291 section 2.5.5.2], + /// otherwise returns [`None`]. + /// + /// Note that this will return an [`IPv4` address] for the IPv6 loopback address `::1`. Use + /// [`Ipv6Addr::to_ipv4_mapped`] to avoid this. + /// + /// `::a.b.c.d` and `::ffff:a.b.c.d` become `a.b.c.d`. `::1` becomes `0.0.0.1`. + /// All addresses *not* starting with either all zeroes or `::ffff` will return `None`. + /// + /// [`IPv4` address]: Ipv4Addr + /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses + /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses + /// [IETF RFC 4291 section 2.5.5.1]: https://tools.ietf.org/html/rfc4291#section-2.5.5.1 + /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2 + /// + /// # Examples + /// + /// ``` + /// use std::net::{Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(), + /// Some(Ipv4Addr::new(192, 10, 2, 255))); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(), + /// Some(Ipv4Addr::new(0, 0, 0, 1))); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_ipv4(&self) -> Option { + if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() { + let [a, b] = ab.to_be_bytes(); + let [c, d] = cd.to_be_bytes(); + Some(Ipv4Addr::new(a, b, c, d)) + } else { + None + } + } + + /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped address, + /// otherwise returns self wrapped in an `IpAddr::V6`. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).to_canonical().is_loopback(), true); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "ip_to_canonical", since = "1.75.0")] + #[rustc_const_stable(feature = "ip_to_canonical", since = "1.75.0")] + pub const fn to_canonical(&self) -> IpAddr { + if let Some(mapped) = self.to_ipv4_mapped() { + return IpAddr::V4(mapped); + } + IpAddr::V6(*self) + } + + /// Returns the sixteen eight-bit integers the IPv6 address consists of. + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(), + /// [0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + /// ``` + #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] + #[stable(feature = "ipv6_to_octets", since = "1.12.0")] + #[must_use] + #[inline] + pub const fn octets(&self) -> [u8; 16] { + self.octets + } + + /// Creates an `Ipv6Addr` from a sixteen element byte array. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip_from)] + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::from_octets([ + /// 0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8, + /// 0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8, + /// ]); + /// assert_eq!( + /// Ipv6Addr::new( + /// 0x1918, 0x1716, 0x1514, 0x1312, + /// 0x1110, 0x0f0e, 0x0d0c, 0x0b0a, + /// ), + /// addr + /// ); + /// ``` + #[unstable(feature = "ip_from", issue = "131360")] + #[must_use] + #[inline] + pub const fn from_octets(octets: [u8; 16]) -> Ipv6Addr { + Ipv6Addr { octets } + } +} + +/// Writes an Ipv6Addr, conforming to the canonical style described by +/// [RFC 5952](https://tools.ietf.org/html/rfc5952). +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Ipv6Addr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // If there are no alignment requirements, write the IP address directly to `f`. + // Otherwise, write it to a local buffer and then use `f.pad`. + if f.precision().is_none() && f.width().is_none() { + let segments = self.segments(); + + if let Some(ipv4) = self.to_ipv4_mapped() { + write!(f, "::ffff:{}", ipv4) + } else { + #[derive(Copy, Clone, Default)] + struct Span { + start: usize, + len: usize, + } + + // Find the inner 0 span + let zeroes = { + let mut longest = Span::default(); + let mut current = Span::default(); + + for (i, &segment) in segments.iter().enumerate() { + if segment == 0 { + if current.len == 0 { + current.start = i; + } + + current.len += 1; + + if current.len > longest.len { + longest = current; + } + } else { + current = Span::default(); + } + } + + longest + }; + + /// Writes a colon-separated part of the address. + #[inline] + fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result { + if let Some((first, tail)) = chunk.split_first() { + write!(f, "{:x}", first)?; + for segment in tail { + f.write_char(':')?; + write!(f, "{:x}", segment)?; + } + } + Ok(()) + } + + if zeroes.len > 1 { + fmt_subslice(f, &segments[..zeroes.start])?; + f.write_str("::")?; + fmt_subslice(f, &segments[zeroes.start + zeroes.len..]) + } else { + fmt_subslice(f, &segments) + } + } + } else { + const LONGEST_IPV6_ADDR: &str = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; + + let mut buf = DisplayBuffer::<{ LONGEST_IPV6_ADDR.len() }>::new(); + // Buffer is long enough for the longest possible IPv6 address, so this should never fail. + write!(buf, "{}", self).unwrap(); + + f.pad(buf.as_str()) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Ipv6Addr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + +#[stable(feature = "ip_cmp", since = "1.16.0")] +impl PartialEq for Ipv6Addr { + #[inline] + fn eq(&self, other: &IpAddr) -> bool { + match other { + IpAddr::V4(_) => false, + IpAddr::V6(v6) => self == v6, + } + } +} + +#[stable(feature = "ip_cmp", since = "1.16.0")] +impl PartialEq for IpAddr { + #[inline] + fn eq(&self, other: &Ipv6Addr) -> bool { + match self { + IpAddr::V4(_) => false, + IpAddr::V6(v6) => v6 == other, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Ipv6Addr { + #[inline] + fn partial_cmp(&self, other: &Ipv6Addr) -> Option { + Some(self.cmp(other)) + } +} + +#[stable(feature = "ip_cmp", since = "1.16.0")] +impl PartialOrd for IpAddr { + #[inline] + fn partial_cmp(&self, other: &Ipv6Addr) -> Option { + match self { + IpAddr::V4(_) => Some(Ordering::Less), + IpAddr::V6(v6) => v6.partial_cmp(other), + } + } +} + +#[stable(feature = "ip_cmp", since = "1.16.0")] +impl PartialOrd for Ipv6Addr { + #[inline] + fn partial_cmp(&self, other: &IpAddr) -> Option { + match other { + IpAddr::V4(_) => Some(Ordering::Greater), + IpAddr::V6(v6) => self.partial_cmp(v6), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Ipv6Addr { + #[inline] + fn cmp(&self, other: &Ipv6Addr) -> Ordering { + self.segments().cmp(&other.segments()) + } +} + +#[stable(feature = "i128", since = "1.26.0")] +impl From for u128 { + /// Uses [`Ipv6Addr::to_bits`] to convert an IPv6 address to a host byte order `u128`. + #[inline] + fn from(ip: Ipv6Addr) -> u128 { + ip.to_bits() + } +} +#[stable(feature = "i128", since = "1.26.0")] +impl From for Ipv6Addr { + /// Uses [`Ipv6Addr::from_bits`] to convert a host byte order `u128` to an IPv6 address. + #[inline] + fn from(ip: u128) -> Ipv6Addr { + Ipv6Addr::from_bits(ip) + } +} + +#[stable(feature = "ipv6_from_octets", since = "1.9.0")] +impl From<[u8; 16]> for Ipv6Addr { + /// Creates an `Ipv6Addr` from a sixteen element byte array. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::from([ + /// 0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8, + /// 0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8, + /// ]); + /// assert_eq!( + /// Ipv6Addr::new( + /// 0x1918, 0x1716, 0x1514, 0x1312, + /// 0x1110, 0x0f0e, 0x0d0c, 0x0b0a, + /// ), + /// addr + /// ); + /// ``` + #[inline] + fn from(octets: [u8; 16]) -> Ipv6Addr { + Ipv6Addr { octets } + } +} + +#[stable(feature = "ipv6_from_segments", since = "1.16.0")] +impl From<[u16; 8]> for Ipv6Addr { + /// Creates an `Ipv6Addr` from an eight element 16-bit array. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::from([ + /// 0x20du16, 0x20cu16, 0x20bu16, 0x20au16, + /// 0x209u16, 0x208u16, 0x207u16, 0x206u16, + /// ]); + /// assert_eq!( + /// Ipv6Addr::new( + /// 0x20d, 0x20c, 0x20b, 0x20a, + /// 0x209, 0x208, 0x207, 0x206, + /// ), + /// addr + /// ); + /// ``` + #[inline] + fn from(segments: [u16; 8]) -> Ipv6Addr { + let [a, b, c, d, e, f, g, h] = segments; + Ipv6Addr::new(a, b, c, d, e, f, g, h) + } +} + +#[stable(feature = "ip_from_slice", since = "1.17.0")] +impl From<[u8; 16]> for IpAddr { + /// Creates an `IpAddr::V6` from a sixteen element byte array. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv6Addr}; + /// + /// let addr = IpAddr::from([ + /// 0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8, + /// 0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8, + /// ]); + /// assert_eq!( + /// IpAddr::V6(Ipv6Addr::new( + /// 0x1918, 0x1716, 0x1514, 0x1312, + /// 0x1110, 0x0f0e, 0x0d0c, 0x0b0a, + /// )), + /// addr + /// ); + /// ``` + #[inline] + fn from(octets: [u8; 16]) -> IpAddr { + IpAddr::V6(Ipv6Addr::from(octets)) + } +} + +#[stable(feature = "ip_from_slice", since = "1.17.0")] +impl From<[u16; 8]> for IpAddr { + /// Creates an `IpAddr::V6` from an eight element 16-bit array. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv6Addr}; + /// + /// let addr = IpAddr::from([ + /// 0x20du16, 0x20cu16, 0x20bu16, 0x20au16, + /// 0x209u16, 0x208u16, 0x207u16, 0x206u16, + /// ]); + /// assert_eq!( + /// IpAddr::V6(Ipv6Addr::new( + /// 0x20d, 0x20c, 0x20b, 0x20a, + /// 0x209, 0x208, 0x207, 0x206, + /// )), + /// addr + /// ); + /// ``` + #[inline] + fn from(segments: [u16; 8]) -> IpAddr { + IpAddr::V6(Ipv6Addr::from(segments)) + } +} + +#[stable(feature = "ip_bitops", since = "1.75.0")] +impl Not for Ipv4Addr { + type Output = Ipv4Addr; + + #[inline] + fn not(mut self) -> Ipv4Addr { + for octet in &mut self.octets { + *octet = !*octet; + } + self + } +} + +#[stable(feature = "ip_bitops", since = "1.75.0")] +impl Not for &'_ Ipv4Addr { + type Output = Ipv4Addr; + + #[inline] + fn not(self) -> Ipv4Addr { + !*self + } +} + +#[stable(feature = "ip_bitops", since = "1.75.0")] +impl Not for Ipv6Addr { + type Output = Ipv6Addr; + + #[inline] + fn not(mut self) -> Ipv6Addr { + for octet in &mut self.octets { + *octet = !*octet; + } + self + } +} + +#[stable(feature = "ip_bitops", since = "1.75.0")] +impl Not for &'_ Ipv6Addr { + type Output = Ipv6Addr; + + #[inline] + fn not(self) -> Ipv6Addr { + !*self + } +} + +macro_rules! bitop_impls { + ($( + $(#[$attr:meta])* + impl ($BitOp:ident, $BitOpAssign:ident) for $ty:ty = ($bitop:ident, $bitop_assign:ident); + )*) => { + $( + $(#[$attr])* + impl $BitOpAssign for $ty { + fn $bitop_assign(&mut self, rhs: $ty) { + for (lhs, rhs) in iter::zip(&mut self.octets, rhs.octets) { + lhs.$bitop_assign(rhs); + } + } + } + + $(#[$attr])* + impl $BitOpAssign<&'_ $ty> for $ty { + fn $bitop_assign(&mut self, rhs: &'_ $ty) { + self.$bitop_assign(*rhs); + } + } + + $(#[$attr])* + impl $BitOp for $ty { + type Output = $ty; + + #[inline] + fn $bitop(mut self, rhs: $ty) -> $ty { + self.$bitop_assign(rhs); + self + } + } + + $(#[$attr])* + impl $BitOp<&'_ $ty> for $ty { + type Output = $ty; + + #[inline] + fn $bitop(mut self, rhs: &'_ $ty) -> $ty { + self.$bitop_assign(*rhs); + self + } + } + + $(#[$attr])* + impl $BitOp<$ty> for &'_ $ty { + type Output = $ty; + + #[inline] + fn $bitop(self, rhs: $ty) -> $ty { + let mut lhs = *self; + lhs.$bitop_assign(rhs); + lhs + } + } + + $(#[$attr])* + impl $BitOp<&'_ $ty> for &'_ $ty { + type Output = $ty; + + #[inline] + fn $bitop(self, rhs: &'_ $ty) -> $ty { + let mut lhs = *self; + lhs.$bitop_assign(*rhs); + lhs + } + } + )* + }; +} + +bitop_impls! { + #[stable(feature = "ip_bitops", since = "1.75.0")] + impl (BitAnd, BitAndAssign) for Ipv4Addr = (bitand, bitand_assign); + #[stable(feature = "ip_bitops", since = "1.75.0")] + impl (BitOr, BitOrAssign) for Ipv4Addr = (bitor, bitor_assign); + + #[stable(feature = "ip_bitops", since = "1.75.0")] + impl (BitAnd, BitAndAssign) for Ipv6Addr = (bitand, bitand_assign); + #[stable(feature = "ip_bitops", since = "1.75.0")] + impl (BitOr, BitOrAssign) for Ipv6Addr = (bitor, bitor_assign); +} diff --git a/CoqOfRust/core/net/mod.rs b/CoqOfRust/core/net/mod.rs new file mode 100644 index 000000000..0786165fe --- /dev/null +++ b/CoqOfRust/core/net/mod.rs @@ -0,0 +1,24 @@ +//! Networking primitives for IP communication. +//! +//! This module provides types for IP and socket addresses. +//! +//! # Organization +//! +//! * [`IpAddr`] represents IP addresses of either IPv4 or IPv6; [`Ipv4Addr`] and +//! [`Ipv6Addr`] are respectively IPv4 and IPv6 addresses +//! * [`SocketAddr`] represents socket addresses of either IPv4 or IPv6; [`SocketAddrV4`] +//! and [`SocketAddrV6`] are respectively IPv4 and IPv6 socket addresses + +#![stable(feature = "ip_in_core", since = "1.77.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::parser::AddrParseError; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::socket_addr::{SocketAddr, SocketAddrV4, SocketAddrV6}; + +mod display_buffer; +mod ip_addr; +mod parser; +mod socket_addr; diff --git a/CoqOfRust/core/net/parser.rs b/CoqOfRust/core/net/parser.rs new file mode 100644 index 000000000..73230f6ee --- /dev/null +++ b/CoqOfRust/core/net/parser.rs @@ -0,0 +1,519 @@ +//! A private parser implementation of IPv4, IPv6, and socket addresses. +//! +//! This module is "publicly exported" through the `FromStr` implementations +//! below. + +use crate::error::Error; +use crate::fmt; +use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; +use crate::str::FromStr; + +trait ReadNumberHelper: Sized { + const ZERO: Self; + fn checked_mul(&self, other: u32) -> Option; + fn checked_add(&self, other: u32) -> Option; +} + +macro_rules! impl_helper { + ($($t:ty)*) => ($(impl ReadNumberHelper for $t { + const ZERO: Self = 0; + #[inline] + fn checked_mul(&self, other: u32) -> Option { + Self::checked_mul(*self, other.try_into().ok()?) + } + #[inline] + fn checked_add(&self, other: u32) -> Option { + Self::checked_add(*self, other.try_into().ok()?) + } + })*) +} + +impl_helper! { u8 u16 u32 } + +struct Parser<'a> { + // Parsing as ASCII, so can use byte array. + state: &'a [u8], +} + +impl<'a> Parser<'a> { + fn new(input: &'a [u8]) -> Parser<'a> { + Parser { state: input } + } + + /// Run a parser, and restore the pre-parse state if it fails. + fn read_atomically(&mut self, inner: F) -> Option + where + F: FnOnce(&mut Parser<'_>) -> Option, + { + let state = self.state; + let result = inner(self); + if result.is_none() { + self.state = state; + } + result + } + + /// Run a parser, but fail if the entire input wasn't consumed. + /// Doesn't run atomically. + fn parse_with(&mut self, inner: F, kind: AddrKind) -> Result + where + F: FnOnce(&mut Parser<'_>) -> Option, + { + let result = inner(self); + if self.state.is_empty() { result } else { None }.ok_or(AddrParseError(kind)) + } + + /// Peek the next character from the input + fn peek_char(&self) -> Option { + self.state.first().map(|&b| char::from(b)) + } + + /// Reads the next character from the input + fn read_char(&mut self) -> Option { + self.state.split_first().map(|(&b, tail)| { + self.state = tail; + char::from(b) + }) + } + + #[must_use] + /// Reads the next character from the input if it matches the target. + fn read_given_char(&mut self, target: char) -> Option<()> { + self.read_atomically(|p| { + p.read_char().and_then(|c| if c == target { Some(()) } else { None }) + }) + } + + /// Helper for reading separators in an indexed loop. Reads the separator + /// character iff index > 0, then runs the parser. When used in a loop, + /// the separator character will only be read on index > 0 (see + /// read_ipv4_addr for an example) + fn read_separator(&mut self, sep: char, index: usize, inner: F) -> Option + where + F: FnOnce(&mut Parser<'_>) -> Option, + { + self.read_atomically(move |p| { + if index > 0 { + p.read_given_char(sep)?; + } + inner(p) + }) + } + + // Read a number off the front of the input in the given radix, stopping + // at the first non-digit character or eof. Fails if the number has more + // digits than max_digits or if there is no number. + // + // INVARIANT: `max_digits` must be less than the number of digits that `u32` + // can represent. + fn read_number>( + &mut self, + radix: u32, + max_digits: Option, + allow_zero_prefix: bool, + ) -> Option { + self.read_atomically(move |p| { + let mut digit_count = 0; + let has_leading_zero = p.peek_char() == Some('0'); + + // If max_digits.is_some(), then we are parsing a `u8` or `u16` and + // don't need to use checked arithmetic since it fits within a `u32`. + let result = if let Some(max_digits) = max_digits { + // u32::MAX = 4_294_967_295u32, which is 10 digits long. + // `max_digits` must be less than 10 to not overflow a `u32`. + debug_assert!(max_digits < 10); + + let mut result = 0_u32; + while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) { + result *= radix; + result += digit; + digit_count += 1; + + if digit_count > max_digits { + return None; + } + } + + result.try_into().ok() + } else { + let mut result = T::ZERO; + + while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) { + result = result.checked_mul(radix)?; + result = result.checked_add(digit)?; + digit_count += 1; + } + + Some(result) + }; + + if digit_count == 0 { + None + } else if !allow_zero_prefix && has_leading_zero && digit_count > 1 { + None + } else { + result + } + }) + } + + /// Reads an IPv4 address. + fn read_ipv4_addr(&mut self) -> Option { + self.read_atomically(|p| { + let mut groups = [0; 4]; + + for (i, slot) in groups.iter_mut().enumerate() { + *slot = p.read_separator('.', i, |p| { + // Disallow octal number in IP string. + // https://tools.ietf.org/html/rfc6943#section-3.1.1 + p.read_number(10, Some(3), false) + })?; + } + + Some(groups.into()) + }) + } + + /// Reads an IPv6 address. + fn read_ipv6_addr(&mut self) -> Option { + /// Read a chunk of an IPv6 address into `groups`. Returns the number + /// of groups read, along with a bool indicating if an embedded + /// trailing IPv4 address was read. Specifically, read a series of + /// colon-separated IPv6 groups (0x0000 - 0xFFFF), with an optional + /// trailing embedded IPv4 address. + fn read_groups(p: &mut Parser<'_>, groups: &mut [u16]) -> (usize, bool) { + let limit = groups.len(); + + for (i, slot) in groups.iter_mut().enumerate() { + // Try to read a trailing embedded IPv4 address. There must be + // at least two groups left. + if i < limit - 1 { + let ipv4 = p.read_separator(':', i, |p| p.read_ipv4_addr()); + + if let Some(v4_addr) = ipv4 { + let [one, two, three, four] = v4_addr.octets(); + groups[i + 0] = u16::from_be_bytes([one, two]); + groups[i + 1] = u16::from_be_bytes([three, four]); + return (i + 2, true); + } + } + + let group = p.read_separator(':', i, |p| p.read_number(16, Some(4), true)); + + match group { + Some(g) => *slot = g, + None => return (i, false), + } + } + (groups.len(), false) + } + + self.read_atomically(|p| { + // Read the front part of the address; either the whole thing, or up + // to the first :: + let mut head = [0; 8]; + let (head_size, head_ipv4) = read_groups(p, &mut head); + + if head_size == 8 { + return Some(head.into()); + } + + // IPv4 part is not allowed before `::` + if head_ipv4 { + return None; + } + + // Read `::` if previous code parsed less than 8 groups. + // `::` indicates one or more groups of 16 bits of zeros. + p.read_given_char(':')?; + p.read_given_char(':')?; + + // Read the back part of the address. The :: must contain at least one + // set of zeroes, so our max length is 7. + let mut tail = [0; 7]; + let limit = 8 - (head_size + 1); + let (tail_size, _) = read_groups(p, &mut tail[..limit]); + + // Concat the head and tail of the IP address + head[(8 - tail_size)..8].copy_from_slice(&tail[..tail_size]); + + Some(head.into()) + }) + } + + /// Reads an IP address, either IPv4 or IPv6. + fn read_ip_addr(&mut self) -> Option { + self.read_ipv4_addr().map(IpAddr::V4).or_else(move || self.read_ipv6_addr().map(IpAddr::V6)) + } + + /// Reads a `:` followed by a port in base 10. + fn read_port(&mut self) -> Option { + self.read_atomically(|p| { + p.read_given_char(':')?; + p.read_number(10, None, true) + }) + } + + /// Reads a `%` followed by a scope ID in base 10. + fn read_scope_id(&mut self) -> Option { + self.read_atomically(|p| { + p.read_given_char('%')?; + p.read_number(10, None, true) + }) + } + + /// Reads an IPv4 address with a port. + fn read_socket_addr_v4(&mut self) -> Option { + self.read_atomically(|p| { + let ip = p.read_ipv4_addr()?; + let port = p.read_port()?; + Some(SocketAddrV4::new(ip, port)) + }) + } + + /// Reads an IPv6 address with a port. + fn read_socket_addr_v6(&mut self) -> Option { + self.read_atomically(|p| { + p.read_given_char('[')?; + let ip = p.read_ipv6_addr()?; + let scope_id = p.read_scope_id().unwrap_or(0); + p.read_given_char(']')?; + + let port = p.read_port()?; + Some(SocketAddrV6::new(ip, port, 0, scope_id)) + }) + } + + /// Reads an IP address with a port. + fn read_socket_addr(&mut self) -> Option { + self.read_socket_addr_v4() + .map(SocketAddr::V4) + .or_else(|| self.read_socket_addr_v6().map(SocketAddr::V6)) + } +} + +impl IpAddr { + /// Parse an IP address from a slice of bytes. + /// + /// ``` + /// #![feature(addr_parse_ascii)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); + /// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); + /// + /// assert_eq!(IpAddr::parse_ascii(b"127.0.0.1"), Ok(localhost_v4)); + /// assert_eq!(IpAddr::parse_ascii(b"::1"), Ok(localhost_v6)); + /// ``` + #[unstable(feature = "addr_parse_ascii", issue = "101035")] + pub fn parse_ascii(b: &[u8]) -> Result { + Parser::new(b).parse_with(|p| p.read_ip_addr(), AddrKind::Ip) + } +} + +#[stable(feature = "ip_addr", since = "1.7.0")] +impl FromStr for IpAddr { + type Err = AddrParseError; + fn from_str(s: &str) -> Result { + Self::parse_ascii(s.as_bytes()) + } +} + +impl Ipv4Addr { + /// Parse an IPv4 address from a slice of bytes. + /// + /// ``` + /// #![feature(addr_parse_ascii)] + /// + /// use std::net::Ipv4Addr; + /// + /// let localhost = Ipv4Addr::new(127, 0, 0, 1); + /// + /// assert_eq!(Ipv4Addr::parse_ascii(b"127.0.0.1"), Ok(localhost)); + /// ``` + #[unstable(feature = "addr_parse_ascii", issue = "101035")] + pub fn parse_ascii(b: &[u8]) -> Result { + // don't try to parse if too long + if b.len() > 15 { + Err(AddrParseError(AddrKind::Ipv4)) + } else { + Parser::new(b).parse_with(|p| p.read_ipv4_addr(), AddrKind::Ipv4) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromStr for Ipv4Addr { + type Err = AddrParseError; + fn from_str(s: &str) -> Result { + Self::parse_ascii(s.as_bytes()) + } +} + +impl Ipv6Addr { + /// Parse an IPv6 address from a slice of bytes. + /// + /// ``` + /// #![feature(addr_parse_ascii)] + /// + /// use std::net::Ipv6Addr; + /// + /// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); + /// + /// assert_eq!(Ipv6Addr::parse_ascii(b"::1"), Ok(localhost)); + /// ``` + #[unstable(feature = "addr_parse_ascii", issue = "101035")] + pub fn parse_ascii(b: &[u8]) -> Result { + Parser::new(b).parse_with(|p| p.read_ipv6_addr(), AddrKind::Ipv6) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromStr for Ipv6Addr { + type Err = AddrParseError; + fn from_str(s: &str) -> Result { + Self::parse_ascii(s.as_bytes()) + } +} + +impl SocketAddrV4 { + /// Parse an IPv4 socket address from a slice of bytes. + /// + /// ``` + /// #![feature(addr_parse_ascii)] + /// + /// use std::net::{Ipv4Addr, SocketAddrV4}; + /// + /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); + /// + /// assert_eq!(SocketAddrV4::parse_ascii(b"127.0.0.1:8080"), Ok(socket)); + /// ``` + #[unstable(feature = "addr_parse_ascii", issue = "101035")] + pub fn parse_ascii(b: &[u8]) -> Result { + Parser::new(b).parse_with(|p| p.read_socket_addr_v4(), AddrKind::SocketV4) + } +} + +#[stable(feature = "socket_addr_from_str", since = "1.5.0")] +impl FromStr for SocketAddrV4 { + type Err = AddrParseError; + fn from_str(s: &str) -> Result { + Self::parse_ascii(s.as_bytes()) + } +} + +impl SocketAddrV6 { + /// Parse an IPv6 socket address from a slice of bytes. + /// + /// ``` + /// #![feature(addr_parse_ascii)] + /// + /// use std::net::{Ipv6Addr, SocketAddrV6}; + /// + /// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0); + /// + /// assert_eq!(SocketAddrV6::parse_ascii(b"[2001:db8::1]:8080"), Ok(socket)); + /// ``` + #[unstable(feature = "addr_parse_ascii", issue = "101035")] + pub fn parse_ascii(b: &[u8]) -> Result { + Parser::new(b).parse_with(|p| p.read_socket_addr_v6(), AddrKind::SocketV6) + } +} + +#[stable(feature = "socket_addr_from_str", since = "1.5.0")] +impl FromStr for SocketAddrV6 { + type Err = AddrParseError; + fn from_str(s: &str) -> Result { + Self::parse_ascii(s.as_bytes()) + } +} + +impl SocketAddr { + /// Parse a socket address from a slice of bytes. + /// + /// ``` + /// #![feature(addr_parse_ascii)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; + /// + /// let socket_v4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// let socket_v6 = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8080); + /// + /// assert_eq!(SocketAddr::parse_ascii(b"127.0.0.1:8080"), Ok(socket_v4)); + /// assert_eq!(SocketAddr::parse_ascii(b"[::1]:8080"), Ok(socket_v6)); + /// ``` + #[unstable(feature = "addr_parse_ascii", issue = "101035")] + pub fn parse_ascii(b: &[u8]) -> Result { + Parser::new(b).parse_with(|p| p.read_socket_addr(), AddrKind::Socket) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromStr for SocketAddr { + type Err = AddrParseError; + fn from_str(s: &str) -> Result { + Self::parse_ascii(s.as_bytes()) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum AddrKind { + Ip, + Ipv4, + Ipv6, + Socket, + SocketV4, + SocketV6, +} + +/// An error which can be returned when parsing an IP address or a socket address. +/// +/// This error is used as the error type for the [`FromStr`] implementation for +/// [`IpAddr`], [`Ipv4Addr`], [`Ipv6Addr`], [`SocketAddr`], [`SocketAddrV4`], and +/// [`SocketAddrV6`]. +/// +/// # Potential causes +/// +/// `AddrParseError` may be thrown because the provided string does not parse as the given type, +/// often because it includes information only handled by a different address type. +/// +/// ```should_panic +/// use std::net::IpAddr; +/// let _foo: IpAddr = "127.0.0.1:8080".parse().expect("Cannot handle the socket port"); +/// ``` +/// +/// [`IpAddr`] doesn't handle the port. Use [`SocketAddr`] instead. +/// +/// ``` +/// use std::net::SocketAddr; +/// +/// // No problem, the `panic!` message has disappeared. +/// let _foo: SocketAddr = "127.0.0.1:8080".parse().expect("unreachable panic"); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct AddrParseError(AddrKind); + +#[stable(feature = "addr_parse_error_error", since = "1.4.0")] +impl fmt::Display for AddrParseError { + #[allow(deprecated, deprecated_in_future)] + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.write_str(self.description()) + } +} + +#[stable(feature = "addr_parse_error_error", since = "1.4.0")] +impl Error for AddrParseError { + #[allow(deprecated)] + fn description(&self) -> &str { + match self.0 { + AddrKind::Ip => "invalid IP address syntax", + AddrKind::Ipv4 => "invalid IPv4 address syntax", + AddrKind::Ipv6 => "invalid IPv6 address syntax", + AddrKind::Socket => "invalid socket address syntax", + AddrKind::SocketV4 => "invalid IPv4 socket address syntax", + AddrKind::SocketV6 => "invalid IPv6 socket address syntax", + } + } +} diff --git a/CoqOfRust/core/net/socket_addr.rs b/CoqOfRust/core/net/socket_addr.rs new file mode 100644 index 000000000..9204797e6 --- /dev/null +++ b/CoqOfRust/core/net/socket_addr.rs @@ -0,0 +1,690 @@ +use super::display_buffer::DisplayBuffer; +use crate::fmt::{self, Write}; +use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + +/// An internet socket address, either IPv4 or IPv6. +/// +/// Internet socket addresses consist of an [IP address], a 16-bit port number, as well +/// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and +/// [`SocketAddrV6`]'s respective documentation for more details. +/// +/// The size of a `SocketAddr` instance may vary depending on the target operating +/// system. +/// +/// [IP address]: IpAddr +/// +/// # Examples +/// +/// ``` +/// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +/// +/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); +/// +/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket)); +/// assert_eq!(socket.port(), 8080); +/// assert_eq!(socket.is_ipv4(), true); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[stable(feature = "rust1", since = "1.0.0")] +pub enum SocketAddr { + /// An IPv4 socket address. + #[stable(feature = "rust1", since = "1.0.0")] + V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4), + /// An IPv6 socket address. + #[stable(feature = "rust1", since = "1.0.0")] + V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6), +} + +/// An IPv4 socket address. +/// +/// IPv4 socket addresses consist of an [`IPv4` address] and a 16-bit port number, as +/// stated in [IETF RFC 793]. +/// +/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. +/// +/// The size of a `SocketAddrV4` struct may vary depending on the target operating +/// system. Do not assume that this type has the same memory layout as the underlying +/// system representation. +/// +/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793 +/// [`IPv4` address]: Ipv4Addr +/// +/// # Textual representation +/// +/// `SocketAddrV4` provides a [`FromStr`](crate::str::FromStr) implementation. +/// It accepts an IPv4 address in its [textual representation], followed by a +/// single `:`, followed by the port encoded as a decimal integer. Other +/// formats are not accepted. +/// +/// [textual representation]: Ipv4Addr#textual-representation +/// +/// # Examples +/// +/// ``` +/// use std::net::{Ipv4Addr, SocketAddrV4}; +/// +/// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); +/// +/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket)); +/// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); +/// assert_eq!(socket.port(), 8080); +/// ``` +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct SocketAddrV4 { + ip: Ipv4Addr, + port: u16, +} + +/// An IPv6 socket address. +/// +/// IPv6 socket addresses consist of an [`IPv6` address], a 16-bit port number, as well +/// as fields containing the traffic class, the flow label, and a scope identifier +/// (see [IETF RFC 2553, Section 3.3] for more details). +/// +/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. +/// +/// The size of a `SocketAddrV6` struct may vary depending on the target operating +/// system. Do not assume that this type has the same memory layout as the underlying +/// system representation. +/// +/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 +/// [`IPv6` address]: Ipv6Addr +/// +/// # Textual representation +/// +/// `SocketAddrV6` provides a [`FromStr`](crate::str::FromStr) implementation, +/// based on the bracketed format recommended by [IETF RFC 5952], +/// with scope identifiers based on those specified in [IETF RFC 4007]. +/// +/// It accepts addresses consisting of the following elements, in order: +/// - A left square bracket (`[`) +/// - The [textual representation] of an IPv6 address +/// - _Optionally_, a percent sign (`%`) followed by the scope identifier +/// encoded as a decimal integer +/// - A right square bracket (`]`) +/// - A colon (`:`) +/// - The port, encoded as a decimal integer. +/// +/// For example, the string `[2001:db8::413]:443` represents a `SocketAddrV6` +/// with the address `2001:db8::413` and port `443`. The string +/// `[2001:db8::413%612]:443` represents the same address and port, with a +/// scope identifier of `612`. +/// +/// Other formats are not accepted. +/// +/// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952#section-6 +/// [IETF RFC 4007]: https://tools.ietf.org/html/rfc4007#section-11 +/// [textual representation]: Ipv6Addr#textual-representation +/// +/// # Examples +/// +/// ``` +/// use std::net::{Ipv6Addr, SocketAddrV6}; +/// +/// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0); +/// +/// assert_eq!("[2001:db8::1]:8080".parse(), Ok(socket)); +/// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); +/// assert_eq!(socket.port(), 8080); +/// +/// let mut with_scope = socket.clone(); +/// with_scope.set_scope_id(3); +/// assert_eq!("[2001:db8::1%3]:8080".parse(), Ok(with_scope)); +/// ``` +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct SocketAddrV6 { + ip: Ipv6Addr, + port: u16, + flowinfo: u32, + scope_id: u32, +} + +impl SocketAddr { + /// Creates a new socket address from an [IP address] and a port number. + /// + /// [IP address]: IpAddr + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); + /// assert_eq!(socket.port(), 8080); + /// ``` + #[stable(feature = "ip_addr", since = "1.7.0")] + #[must_use] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + pub const fn new(ip: IpAddr, port: u16) -> SocketAddr { + match ip { + IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)), + IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)), + } + } + + /// Returns the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); + /// ``` + #[must_use] + #[stable(feature = "ip_addr", since = "1.7.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + pub const fn ip(&self) -> IpAddr { + match *self { + SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()), + SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()), + } + } + + /// Changes the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); + /// ``` + #[inline] + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")] + pub const fn set_ip(&mut self, new_ip: IpAddr) { + // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away. + match (self, new_ip) { + (&mut SocketAddr::V4(ref mut a), IpAddr::V4(new_ip)) => a.set_ip(new_ip), + (&mut SocketAddr::V6(ref mut a), IpAddr::V6(new_ip)) => a.set_ip(new_ip), + (self_, new_ip) => *self_ = Self::new(new_ip, self_.port()), + } + } + + /// Returns the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.port(), 8080); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + pub const fn port(&self) -> u16 { + match *self { + SocketAddr::V4(ref a) => a.port(), + SocketAddr::V6(ref a) => a.port(), + } + } + + /// Changes the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// socket.set_port(1025); + /// assert_eq!(socket.port(), 1025); + /// ``` + #[inline] + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")] + pub const fn set_port(&mut self, new_port: u16) { + match *self { + SocketAddr::V4(ref mut a) => a.set_port(new_port), + SocketAddr::V6(ref mut a) => a.set_port(new_port), + } + } + + /// Returns [`true`] if the [IP address] in this `SocketAddr` is an + /// [`IPv4` address], and [`false`] otherwise. + /// + /// [IP address]: IpAddr + /// [`IPv4` address]: IpAddr::V4 + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.is_ipv4(), true); + /// assert_eq!(socket.is_ipv6(), false); + /// ``` + #[must_use] + #[stable(feature = "sockaddr_checker", since = "1.16.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + pub const fn is_ipv4(&self) -> bool { + matches!(*self, SocketAddr::V4(_)) + } + + /// Returns [`true`] if the [IP address] in this `SocketAddr` is an + /// [`IPv6` address], and [`false`] otherwise. + /// + /// [IP address]: IpAddr + /// [`IPv6` address]: IpAddr::V6 + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv6Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080); + /// assert_eq!(socket.is_ipv4(), false); + /// assert_eq!(socket.is_ipv6(), true); + /// ``` + #[must_use] + #[stable(feature = "sockaddr_checker", since = "1.16.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + pub const fn is_ipv6(&self) -> bool { + matches!(*self, SocketAddr::V6(_)) + } +} + +impl SocketAddrV4 { + /// Creates a new socket address from an [`IPv4` address] and a port number. + /// + /// [`IPv4` address]: Ipv4Addr + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV4, Ipv4Addr}; + /// + /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + pub const fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 { + SocketAddrV4 { ip, port } + } + + /// Returns the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV4, Ipv4Addr}; + /// + /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); + /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + pub const fn ip(&self) -> &Ipv4Addr { + &self.ip + } + + /// Changes the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV4, Ipv4Addr}; + /// + /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); + /// socket.set_ip(Ipv4Addr::new(192, 168, 0, 1)); + /// assert_eq!(socket.ip(), &Ipv4Addr::new(192, 168, 0, 1)); + /// ``` + #[inline] + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")] + pub const fn set_ip(&mut self, new_ip: Ipv4Addr) { + self.ip = new_ip; + } + + /// Returns the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV4, Ipv4Addr}; + /// + /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); + /// assert_eq!(socket.port(), 8080); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + pub const fn port(&self) -> u16 { + self.port + } + + /// Changes the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV4, Ipv4Addr}; + /// + /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); + /// socket.set_port(4242); + /// assert_eq!(socket.port(), 4242); + /// ``` + #[inline] + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")] + pub const fn set_port(&mut self, new_port: u16) { + self.port = new_port; + } +} + +impl SocketAddrV6 { + /// Creates a new socket address from an [`IPv6` address], a 16-bit port number, + /// and the `flowinfo` and `scope_id` fields. + /// + /// For more information on the meaning and layout of the `flowinfo` and `scope_id` + /// parameters, see [IETF RFC 2553, Section 3.3]. + /// + /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 + /// [`IPv6` address]: Ipv6Addr + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 { + SocketAddrV6 { ip, port, flowinfo, scope_id } + } + + /// Returns the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); + /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + pub const fn ip(&self) -> &Ipv6Addr { + &self.ip + } + + /// Changes the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); + /// socket.set_ip(Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0)); + /// assert_eq!(socket.ip(), &Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0)); + /// ``` + #[inline] + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")] + pub const fn set_ip(&mut self, new_ip: Ipv6Addr) { + self.ip = new_ip; + } + + /// Returns the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); + /// assert_eq!(socket.port(), 8080); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + pub const fn port(&self) -> u16 { + self.port + } + + /// Changes the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); + /// socket.set_port(4242); + /// assert_eq!(socket.port(), 4242); + /// ``` + #[inline] + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")] + pub const fn set_port(&mut self, new_port: u16) { + self.port = new_port; + } + + /// Returns the flow information associated with this address. + /// + /// This information corresponds to the `sin6_flowinfo` field in C's `netinet/in.h`, + /// as specified in [IETF RFC 2553, Section 3.3]. + /// It combines information about the flow label and the traffic class as specified + /// in [IETF RFC 2460], respectively [Section 6] and [Section 7]. + /// + /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 + /// [IETF RFC 2460]: https://tools.ietf.org/html/rfc2460 + /// [Section 6]: https://tools.ietf.org/html/rfc2460#section-6 + /// [Section 7]: https://tools.ietf.org/html/rfc2460#section-7 + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0); + /// assert_eq!(socket.flowinfo(), 10); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + pub const fn flowinfo(&self) -> u32 { + self.flowinfo + } + + /// Changes the flow information associated with this socket address. + /// + /// See [`SocketAddrV6::flowinfo`]'s documentation for more details. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0); + /// socket.set_flowinfo(56); + /// assert_eq!(socket.flowinfo(), 56); + /// ``` + #[inline] + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")] + pub const fn set_flowinfo(&mut self, new_flowinfo: u32) { + self.flowinfo = new_flowinfo; + } + + /// Returns the scope ID associated with this address. + /// + /// This information corresponds to the `sin6_scope_id` field in C's `netinet/in.h`, + /// as specified in [IETF RFC 2553, Section 3.3]. + /// + /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78); + /// assert_eq!(socket.scope_id(), 78); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + pub const fn scope_id(&self) -> u32 { + self.scope_id + } + + /// Changes the scope ID associated with this socket address. + /// + /// See [`SocketAddrV6::scope_id`]'s documentation for more details. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78); + /// socket.set_scope_id(42); + /// assert_eq!(socket.scope_id(), 42); + /// ``` + #[inline] + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_sockaddr_setters", issue = "131714")] + pub const fn set_scope_id(&mut self, new_scope_id: u32) { + self.scope_id = new_scope_id; + } +} + +#[stable(feature = "ip_from_ip", since = "1.16.0")] +impl From for SocketAddr { + /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`]. + #[inline] + fn from(sock4: SocketAddrV4) -> SocketAddr { + SocketAddr::V4(sock4) + } +} + +#[stable(feature = "ip_from_ip", since = "1.16.0")] +impl From for SocketAddr { + /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`]. + #[inline] + fn from(sock6: SocketAddrV6) -> SocketAddr { + SocketAddr::V6(sock6) + } +} + +#[stable(feature = "addr_from_into_ip", since = "1.17.0")] +impl> From<(I, u16)> for SocketAddr { + /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`]. + /// + /// This conversion creates a [`SocketAddr::V4`] for an [`IpAddr::V4`] + /// and creates a [`SocketAddr::V6`] for an [`IpAddr::V6`]. + /// + /// `u16` is treated as port of the newly created [`SocketAddr`]. + fn from(pieces: (I, u16)) -> SocketAddr { + SocketAddr::new(pieces.0.into(), pieces.1) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + SocketAddr::V4(ref a) => a.fmt(f), + SocketAddr::V6(ref a) => a.fmt(f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for SocketAddr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddrV4 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // If there are no alignment requirements, write the socket address directly to `f`. + // Otherwise, write it to a local buffer and then use `f.pad`. + if f.precision().is_none() && f.width().is_none() { + write!(f, "{}:{}", self.ip(), self.port()) + } else { + const LONGEST_IPV4_SOCKET_ADDR: &str = "255.255.255.255:65535"; + + let mut buf = DisplayBuffer::<{ LONGEST_IPV4_SOCKET_ADDR.len() }>::new(); + // Buffer is long enough for the longest possible IPv4 socket address, so this should never fail. + write!(buf, "{}:{}", self.ip(), self.port()).unwrap(); + + f.pad(buf.as_str()) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for SocketAddrV4 { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddrV6 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // If there are no alignment requirements, write the socket address directly to `f`. + // Otherwise, write it to a local buffer and then use `f.pad`. + if f.precision().is_none() && f.width().is_none() { + match self.scope_id() { + 0 => write!(f, "[{}]:{}", self.ip(), self.port()), + scope_id => write!(f, "[{}%{}]:{}", self.ip(), scope_id, self.port()), + } + } else { + const LONGEST_IPV6_SOCKET_ADDR: &str = + "[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%4294967295]:65535"; + + let mut buf = DisplayBuffer::<{ LONGEST_IPV6_SOCKET_ADDR.len() }>::new(); + match self.scope_id() { + 0 => write!(buf, "[{}]:{}", self.ip(), self.port()), + scope_id => write!(buf, "[{}%{}]:{}", self.ip(), scope_id, self.port()), + } + // Buffer is long enough for the longest possible IPv6 socket address, so this should never fail. + .unwrap(); + + f.pad(buf.as_str()) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for SocketAddrV6 { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} diff --git a/CoqOfRust/core/num/bignum.rs b/CoqOfRust/core/num/bignum.rs new file mode 100644 index 000000000..2a47c89e2 --- /dev/null +++ b/CoqOfRust/core/num/bignum.rs @@ -0,0 +1,432 @@ +//! Custom arbitrary-precision number (bignum) implementation. +//! +//! This is designed to avoid the heap allocation at expense of stack memory. +//! The most used bignum type, `Big32x40`, is limited by 32 × 40 = 1,280 bits +//! and will take at most 160 bytes of stack memory. This is more than enough +//! for round-tripping all possible finite `f64` values. +//! +//! In principle it is possible to have multiple bignum types for different +//! inputs, but we don't do so to avoid the code bloat. Each bignum is still +//! tracked for the actual usages, so it normally doesn't matter. + +// This module is only for dec2flt and flt2dec, and only public because of coretests. +// It is not intended to ever be stabilized. +#![doc(hidden)] +#![unstable( + feature = "core_private_bignum", + reason = "internal routines only exposed for testing", + issue = "none" +)] +#![macro_use] + +/// Arithmetic operations required by bignums. +pub trait FullOps: Sized { + /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + other2 + carry`, + /// where `W` is the number of bits in `Self`. + fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /* carry */, Self); + + /// Returns `(quo, rem)` such that `borrow * 2^W + self = quo * other + rem` + /// and `0 <= rem < other`, where `W` is the number of bits in `Self`. + fn full_div_rem(self, other: Self, borrow: Self) + -> (Self /* quotient */, Self /* remainder */); +} + +macro_rules! impl_full_ops { + ($($ty:ty: add($addfn:path), mul/div($bigty:ident);)*) => ( + $( + impl FullOps for $ty { + fn full_mul_add(self, other: $ty, other2: $ty, carry: $ty) -> ($ty, $ty) { + // This cannot overflow; + // the output is between `0` and `2^nbits * (2^nbits - 1)`. + let v = (self as $bigty) * (other as $bigty) + (other2 as $bigty) + + (carry as $bigty); + ((v >> <$ty>::BITS) as $ty, v as $ty) + } + + fn full_div_rem(self, other: $ty, borrow: $ty) -> ($ty, $ty) { + debug_assert!(borrow < other); + // This cannot overflow; the output is between `0` and `other * (2^nbits - 1)`. + let lhs = ((borrow as $bigty) << <$ty>::BITS) | (self as $bigty); + let rhs = other as $bigty; + ((lhs / rhs) as $ty, (lhs % rhs) as $ty) + } + } + )* + ) +} + +impl_full_ops! { + u8: add(intrinsics::u8_add_with_overflow), mul/div(u16); + u16: add(intrinsics::u16_add_with_overflow), mul/div(u32); + u32: add(intrinsics::u32_add_with_overflow), mul/div(u64); + // See RFC #521 for enabling this. + // u64: add(intrinsics::u64_add_with_overflow), mul/div(u128); +} + +/// Table of powers of 5 representable in digits. Specifically, the largest {u8, u16, u32} value +/// that's a power of five, plus the corresponding exponent. Used in `mul_pow5`. +const SMALL_POW5: [(u64, usize); 3] = [(125, 3), (15625, 6), (1_220_703_125, 13)]; + +macro_rules! define_bignum { + ($name:ident: type=$ty:ty, n=$n:expr) => { + /// Stack-allocated arbitrary-precision (up to certain limit) integer. + /// + /// This is backed by a fixed-size array of given type ("digit"). + /// While the array is not very large (normally some hundred bytes), + /// copying it recklessly may result in the performance hit. + /// Thus this is intentionally not `Copy`. + /// + /// All operations available to bignums panic in the case of overflows. + /// The caller is responsible to use large enough bignum types. + pub struct $name { + /// One plus the offset to the maximum "digit" in use. + /// This does not decrease, so be aware of the computation order. + /// `base[size..]` should be zero. + size: usize, + /// Digits. `[a, b, c, ...]` represents `a + b*2^W + c*2^(2W) + ...` + /// where `W` is the number of bits in the digit type. + base: [$ty; $n], + } + + impl $name { + /// Makes a bignum from one digit. + pub fn from_small(v: $ty) -> $name { + let mut base = [0; $n]; + base[0] = v; + $name { size: 1, base } + } + + /// Makes a bignum from `u64` value. + pub fn from_u64(mut v: u64) -> $name { + let mut base = [0; $n]; + let mut sz = 0; + while v > 0 { + base[sz] = v as $ty; + v >>= <$ty>::BITS; + sz += 1; + } + $name { size: sz, base } + } + + /// Returns the internal digits as a slice `[a, b, c, ...]` such that the numeric + /// value is `a + b * 2^W + c * 2^(2W) + ...` where `W` is the number of bits in + /// the digit type. + pub fn digits(&self) -> &[$ty] { + &self.base[..self.size] + } + + /// Returns the `i`-th bit where bit 0 is the least significant one. + /// In other words, the bit with weight `2^i`. + pub fn get_bit(&self, i: usize) -> u8 { + let digitbits = <$ty>::BITS as usize; + let d = i / digitbits; + let b = i % digitbits; + ((self.base[d] >> b) & 1) as u8 + } + + /// Returns `true` if the bignum is zero. + pub fn is_zero(&self) -> bool { + self.digits().iter().all(|&v| v == 0) + } + + /// Returns the number of bits necessary to represent this value. Note that zero + /// is considered to need 0 bits. + pub fn bit_length(&self) -> usize { + let digitbits = <$ty>::BITS as usize; + let digits = self.digits(); + // Find the most significant non-zero digit. + let msd = digits.iter().rposition(|&x| x != 0); + match msd { + Some(msd) => msd * digitbits + digits[msd].ilog2() as usize + 1, + // There are no non-zero digits, i.e., the number is zero. + _ => 0, + } + } + + /// Adds `other` to itself and returns its own mutable reference. + pub fn add<'a>(&'a mut self, other: &$name) -> &'a mut $name { + use crate::{cmp, iter}; + + let mut sz = cmp::max(self.size, other.size); + let mut carry = false; + for (a, b) in iter::zip(&mut self.base[..sz], &other.base[..sz]) { + let (v, c) = (*a).carrying_add(*b, carry); + *a = v; + carry = c; + } + if carry { + self.base[sz] = 1; + sz += 1; + } + self.size = sz; + self + } + + pub fn add_small(&mut self, other: $ty) -> &mut $name { + let (v, mut carry) = self.base[0].carrying_add(other, false); + self.base[0] = v; + let mut i = 1; + while carry { + let (v, c) = self.base[i].carrying_add(0, carry); + self.base[i] = v; + carry = c; + i += 1; + } + if i > self.size { + self.size = i; + } + self + } + + /// Subtracts `other` from itself and returns its own mutable reference. + pub fn sub<'a>(&'a mut self, other: &$name) -> &'a mut $name { + use crate::{cmp, iter}; + + let sz = cmp::max(self.size, other.size); + let mut noborrow = true; + for (a, b) in iter::zip(&mut self.base[..sz], &other.base[..sz]) { + let (v, c) = (*a).carrying_add(!*b, noborrow); + *a = v; + noborrow = c; + } + assert!(noborrow); + self.size = sz; + self + } + + /// Multiplies itself by a digit-sized `other` and returns its own + /// mutable reference. + pub fn mul_small(&mut self, other: $ty) -> &mut $name { + let mut sz = self.size; + let mut carry = 0; + for a in &mut self.base[..sz] { + let (v, c) = (*a).carrying_mul(other, carry); + *a = v; + carry = c; + } + if carry > 0 { + self.base[sz] = carry; + sz += 1; + } + self.size = sz; + self + } + + /// Multiplies itself by `2^bits` and returns its own mutable reference. + pub fn mul_pow2(&mut self, bits: usize) -> &mut $name { + let digitbits = <$ty>::BITS as usize; + let digits = bits / digitbits; + let bits = bits % digitbits; + + assert!(digits < $n); + debug_assert!(self.base[$n - digits..].iter().all(|&v| v == 0)); + debug_assert!(bits == 0 || (self.base[$n - digits - 1] >> (digitbits - bits)) == 0); + + // shift by `digits * digitbits` bits + for i in (0..self.size).rev() { + self.base[i + digits] = self.base[i]; + } + for i in 0..digits { + self.base[i] = 0; + } + + // shift by `bits` bits + let mut sz = self.size + digits; + if bits > 0 { + let last = sz; + let overflow = self.base[last - 1] >> (digitbits - bits); + if overflow > 0 { + self.base[last] = overflow; + sz += 1; + } + for i in (digits + 1..last).rev() { + self.base[i] = + (self.base[i] << bits) | (self.base[i - 1] >> (digitbits - bits)); + } + self.base[digits] <<= bits; + // self.base[..digits] is zero, no need to shift + } + + self.size = sz; + self + } + + /// Multiplies itself by `5^e` and returns its own mutable reference. + pub fn mul_pow5(&mut self, mut e: usize) -> &mut $name { + use crate::mem; + use crate::num::bignum::SMALL_POW5; + + // There are exactly n trailing zeros on 2^n, and the only relevant digit sizes + // are consecutive powers of two, so this is well suited index for the table. + let table_index = mem::size_of::<$ty>().trailing_zeros() as usize; + let (small_power, small_e) = SMALL_POW5[table_index]; + let small_power = small_power as $ty; + + // Multiply with the largest single-digit power as long as possible ... + while e >= small_e { + self.mul_small(small_power); + e -= small_e; + } + + // ... then finish off the remainder. + let mut rest_power = 1; + for _ in 0..e { + rest_power *= 5; + } + self.mul_small(rest_power); + + self + } + + /// Multiplies itself by a number described by `other[0] + other[1] * 2^W + + /// other[2] * 2^(2W) + ...` (where `W` is the number of bits in the digit type) + /// and returns its own mutable reference. + pub fn mul_digits<'a>(&'a mut self, other: &[$ty]) -> &'a mut $name { + // the internal routine. works best when aa.len() <= bb.len(). + fn mul_inner(ret: &mut [$ty; $n], aa: &[$ty], bb: &[$ty]) -> usize { + use crate::num::bignum::FullOps; + + let mut retsz = 0; + for (i, &a) in aa.iter().enumerate() { + if a == 0 { + continue; + } + let mut sz = bb.len(); + let mut carry = 0; + for (j, &b) in bb.iter().enumerate() { + let (c, v) = a.full_mul_add(b, ret[i + j], carry); + ret[i + j] = v; + carry = c; + } + if carry > 0 { + ret[i + sz] = carry; + sz += 1; + } + if retsz < i + sz { + retsz = i + sz; + } + } + retsz + } + + let mut ret = [0; $n]; + let retsz = if self.size < other.len() { + mul_inner(&mut ret, &self.digits(), other) + } else { + mul_inner(&mut ret, other, &self.digits()) + }; + self.base = ret; + self.size = retsz; + self + } + + /// Divides itself by a digit-sized `other` and returns its own + /// mutable reference *and* the remainder. + pub fn div_rem_small(&mut self, other: $ty) -> (&mut $name, $ty) { + use crate::num::bignum::FullOps; + + assert!(other > 0); + + let sz = self.size; + let mut borrow = 0; + for a in self.base[..sz].iter_mut().rev() { + let (q, r) = (*a).full_div_rem(other, borrow); + *a = q; + borrow = r; + } + (self, borrow) + } + + /// Divide self by another bignum, overwriting `q` with the quotient and `r` with the + /// remainder. + pub fn div_rem(&self, d: &$name, q: &mut $name, r: &mut $name) { + // Stupid slow base-2 long division taken from + // https://en.wikipedia.org/wiki/Division_algorithm + // FIXME use a greater base ($ty) for the long division. + assert!(!d.is_zero()); + let digitbits = <$ty>::BITS as usize; + for digit in &mut q.base[..] { + *digit = 0; + } + for digit in &mut r.base[..] { + *digit = 0; + } + r.size = d.size; + q.size = 1; + let mut q_is_zero = true; + let end = self.bit_length(); + for i in (0..end).rev() { + r.mul_pow2(1); + r.base[0] |= self.get_bit(i) as $ty; + if &*r >= d { + r.sub(d); + // Set bit `i` of q to 1. + let digit_idx = i / digitbits; + let bit_idx = i % digitbits; + if q_is_zero { + q.size = digit_idx + 1; + q_is_zero = false; + } + q.base[digit_idx] |= 1 << bit_idx; + } + } + debug_assert!(q.base[q.size..].iter().all(|&d| d == 0)); + debug_assert!(r.base[r.size..].iter().all(|&d| d == 0)); + } + } + + impl crate::cmp::PartialEq for $name { + fn eq(&self, other: &$name) -> bool { + self.base[..] == other.base[..] + } + } + + impl crate::cmp::Eq for $name {} + + impl crate::cmp::PartialOrd for $name { + fn partial_cmp(&self, other: &$name) -> crate::option::Option { + crate::option::Option::Some(self.cmp(other)) + } + } + + impl crate::cmp::Ord for $name { + fn cmp(&self, other: &$name) -> crate::cmp::Ordering { + use crate::cmp::max; + let sz = max(self.size, other.size); + let lhs = self.base[..sz].iter().cloned().rev(); + let rhs = other.base[..sz].iter().cloned().rev(); + lhs.cmp(rhs) + } + } + + impl crate::clone::Clone for $name { + fn clone(&self) -> Self { + Self { size: self.size, base: self.base } + } + } + + impl crate::fmt::Debug for $name { + fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result { + let sz = if self.size < 1 { 1 } else { self.size }; + let digitlen = <$ty>::BITS as usize / 4; + + write!(f, "{:#x}", self.base[sz - 1])?; + for &v in self.base[..sz - 1].iter().rev() { + write!(f, "_{:01$x}", v, digitlen)?; + } + crate::result::Result::Ok(()) + } + } + }; +} + +/// The digit type for `Big32x40`. +pub type Digit32 = u32; + +define_bignum!(Big32x40: type=Digit32, n=40); + +// this one is used for testing only. +#[doc(hidden)] +pub mod tests { + define_bignum!(Big8x3: type=u8, n=3); +} diff --git a/CoqOfRust/core/num/dec2flt/common.rs b/CoqOfRust/core/num/dec2flt/common.rs new file mode 100644 index 000000000..4dadf406a --- /dev/null +++ b/CoqOfRust/core/num/dec2flt/common.rs @@ -0,0 +1,79 @@ +//! Common utilities, for internal use only. + +/// Helper methods to process immutable bytes. +pub(crate) trait ByteSlice { + /// Reads 8 bytes as a 64-bit integer in little-endian order. + fn read_u64(&self) -> u64; + + /// Writes a 64-bit integer as 8 bytes in little-endian order. + fn write_u64(&mut self, value: u64); + + /// Calculate the offset of a slice from another. + fn offset_from(&self, other: &Self) -> isize; + + /// Iteratively parse and consume digits from bytes. + /// Returns the same bytes with consumed digits being + /// elided. + fn parse_digits(&self, func: impl FnMut(u8)) -> &Self; +} + +impl ByteSlice for [u8] { + #[inline(always)] // inlining this is crucial to remove bound checks + fn read_u64(&self) -> u64 { + let mut tmp = [0; 8]; + tmp.copy_from_slice(&self[..8]); + u64::from_le_bytes(tmp) + } + + #[inline(always)] // inlining this is crucial to remove bound checks + fn write_u64(&mut self, value: u64) { + self[..8].copy_from_slice(&value.to_le_bytes()) + } + + #[inline] + fn offset_from(&self, other: &Self) -> isize { + other.len() as isize - self.len() as isize + } + + #[inline] + fn parse_digits(&self, mut func: impl FnMut(u8)) -> &Self { + let mut s = self; + + while let Some((c, s_next)) = s.split_first() { + let c = c.wrapping_sub(b'0'); + if c < 10 { + func(c); + s = s_next; + } else { + break; + } + } + + s + } +} + +/// Determine if 8 bytes are all decimal digits. +/// This does not care about the order in which the bytes were loaded. +pub(crate) fn is_8digits(v: u64) -> bool { + let a = v.wrapping_add(0x4646_4646_4646_4646); + let b = v.wrapping_sub(0x3030_3030_3030_3030); + (a | b) & 0x8080_8080_8080_8080 == 0 +} + +/// A custom 64-bit floating point type, representing `f * 2^e`. +/// e is biased, so it be directly shifted into the exponent bits. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)] +pub struct BiasedFp { + /// The significant digits. + pub f: u64, + /// The biased, binary exponent. + pub e: i32, +} + +impl BiasedFp { + #[inline] + pub const fn zero_pow2(e: i32) -> Self { + Self { f: 0, e } + } +} diff --git a/CoqOfRust/core/num/dec2flt/decimal.rs b/CoqOfRust/core/num/dec2flt/decimal.rs new file mode 100644 index 000000000..be9c0eccd --- /dev/null +++ b/CoqOfRust/core/num/dec2flt/decimal.rs @@ -0,0 +1,358 @@ +//! Arbitrary-precision decimal class for fallback algorithms. +//! +//! This is only used if the fast-path (native floats) and +//! the Eisel-Lemire algorithm are unable to unambiguously +//! determine the float. +//! +//! The technique used is "Simple Decimal Conversion", developed +//! by Nigel Tao and Ken Thompson. A detailed description of the +//! algorithm can be found in "ParseNumberF64 by Simple Decimal Conversion", +//! available online: . + +use crate::num::dec2flt::common::{ByteSlice, is_8digits}; + +#[derive(Clone)] +pub struct Decimal { + /// The number of significant digits in the decimal. + pub num_digits: usize, + /// The offset of the decimal point in the significant digits. + pub decimal_point: i32, + /// If the number of significant digits stored in the decimal is truncated. + pub truncated: bool, + /// Buffer of the raw digits, in the range [0, 9]. + pub digits: [u8; Self::MAX_DIGITS], +} + +impl Default for Decimal { + fn default() -> Self { + Self { num_digits: 0, decimal_point: 0, truncated: false, digits: [0; Self::MAX_DIGITS] } + } +} + +impl Decimal { + /// The maximum number of digits required to unambiguously round a float. + /// + /// For a double-precision IEEE 754 float, this required 767 digits, + /// so we store the max digits + 1. + /// + /// We can exactly represent a float in radix `b` from radix 2 if + /// `b` is divisible by 2. This function calculates the exact number of + /// digits required to exactly represent that float. + /// + /// According to the "Handbook of Floating Point Arithmetic", + /// for IEEE754, with emin being the min exponent, p2 being the + /// precision, and b being the radix, the number of digits follows as: + /// + /// `−emin + p2 + ⌊(emin + 1) log(2, b) − log(1 − 2^(−p2), b)⌋` + /// + /// For f32, this follows as: + /// emin = -126 + /// p2 = 24 + /// + /// For f64, this follows as: + /// emin = -1022 + /// p2 = 53 + /// + /// In Python: + /// `-emin + p2 + math.floor((emin+ 1)*math.log(2, b)-math.log(1-2**(-p2), b))` + pub const MAX_DIGITS: usize = 768; + /// The max digits that can be exactly represented in a 64-bit integer. + pub const MAX_DIGITS_WITHOUT_OVERFLOW: usize = 19; + pub const DECIMAL_POINT_RANGE: i32 = 2047; + + /// Append a digit to the buffer. + pub fn try_add_digit(&mut self, digit: u8) { + if self.num_digits < Self::MAX_DIGITS { + self.digits[self.num_digits] = digit; + } + self.num_digits += 1; + } + + /// Trim trailing zeros from the buffer. + pub fn trim(&mut self) { + // All of the following calls to `Decimal::trim` can't panic because: + // + // 1. `parse_decimal` sets `num_digits` to a max of `Decimal::MAX_DIGITS`. + // 2. `right_shift` sets `num_digits` to `write_index`, which is bounded by `num_digits`. + // 3. `left_shift` `num_digits` to a max of `Decimal::MAX_DIGITS`. + // + // Trim is only called in `right_shift` and `left_shift`. + debug_assert!(self.num_digits <= Self::MAX_DIGITS); + while self.num_digits != 0 && self.digits[self.num_digits - 1] == 0 { + self.num_digits -= 1; + } + } + + pub fn round(&self) -> u64 { + if self.num_digits == 0 || self.decimal_point < 0 { + return 0; + } else if self.decimal_point > 18 { + return 0xFFFF_FFFF_FFFF_FFFF_u64; + } + let dp = self.decimal_point as usize; + let mut n = 0_u64; + for i in 0..dp { + n *= 10; + if i < self.num_digits { + n += self.digits[i] as u64; + } + } + let mut round_up = false; + if dp < self.num_digits { + round_up = self.digits[dp] >= 5; + if self.digits[dp] == 5 && dp + 1 == self.num_digits { + round_up = self.truncated || ((dp != 0) && (1 & self.digits[dp - 1] != 0)) + } + } + if round_up { + n += 1; + } + n + } + + /// Computes decimal * 2^shift. + pub fn left_shift(&mut self, shift: usize) { + if self.num_digits == 0 { + return; + } + let num_new_digits = number_of_digits_decimal_left_shift(self, shift); + let mut read_index = self.num_digits; + let mut write_index = self.num_digits + num_new_digits; + let mut n = 0_u64; + while read_index != 0 { + read_index -= 1; + write_index -= 1; + n += (self.digits[read_index] as u64) << shift; + let quotient = n / 10; + let remainder = n - (10 * quotient); + if write_index < Self::MAX_DIGITS { + self.digits[write_index] = remainder as u8; + } else if remainder > 0 { + self.truncated = true; + } + n = quotient; + } + while n > 0 { + write_index -= 1; + let quotient = n / 10; + let remainder = n - (10 * quotient); + if write_index < Self::MAX_DIGITS { + self.digits[write_index] = remainder as u8; + } else if remainder > 0 { + self.truncated = true; + } + n = quotient; + } + self.num_digits += num_new_digits; + if self.num_digits > Self::MAX_DIGITS { + self.num_digits = Self::MAX_DIGITS; + } + self.decimal_point += num_new_digits as i32; + self.trim(); + } + + /// Computes decimal * 2^-shift. + pub fn right_shift(&mut self, shift: usize) { + let mut read_index = 0; + let mut write_index = 0; + let mut n = 0_u64; + while (n >> shift) == 0 { + if read_index < self.num_digits { + n = (10 * n) + self.digits[read_index] as u64; + read_index += 1; + } else if n == 0 { + return; + } else { + while (n >> shift) == 0 { + n *= 10; + read_index += 1; + } + break; + } + } + self.decimal_point -= read_index as i32 - 1; + if self.decimal_point < -Self::DECIMAL_POINT_RANGE { + // `self = Self::Default()`, but without the overhead of clearing `digits`. + self.num_digits = 0; + self.decimal_point = 0; + self.truncated = false; + return; + } + let mask = (1_u64 << shift) - 1; + while read_index < self.num_digits { + let new_digit = (n >> shift) as u8; + n = (10 * (n & mask)) + self.digits[read_index] as u64; + read_index += 1; + self.digits[write_index] = new_digit; + write_index += 1; + } + while n > 0 { + let new_digit = (n >> shift) as u8; + n = 10 * (n & mask); + if write_index < Self::MAX_DIGITS { + self.digits[write_index] = new_digit; + write_index += 1; + } else if new_digit > 0 { + self.truncated = true; + } + } + self.num_digits = write_index; + self.trim(); + } +} + +/// Parse a big integer representation of the float as a decimal. +pub fn parse_decimal(mut s: &[u8]) -> Decimal { + let mut d = Decimal::default(); + let start = s; + + while let Some((&b'0', s_next)) = s.split_first() { + s = s_next; + } + + s = s.parse_digits(|digit| d.try_add_digit(digit)); + + if let Some((b'.', s_next)) = s.split_first() { + s = s_next; + let first = s; + // Skip leading zeros. + if d.num_digits == 0 { + while let Some((&b'0', s_next)) = s.split_first() { + s = s_next; + } + } + while s.len() >= 8 && d.num_digits + 8 < Decimal::MAX_DIGITS { + let v = s.read_u64(); + if !is_8digits(v) { + break; + } + d.digits[d.num_digits..].write_u64(v - 0x3030_3030_3030_3030); + d.num_digits += 8; + s = &s[8..]; + } + s = s.parse_digits(|digit| d.try_add_digit(digit)); + d.decimal_point = s.len() as i32 - first.len() as i32; + } + if d.num_digits != 0 { + // Ignore the trailing zeros if there are any + let mut n_trailing_zeros = 0; + for &c in start[..(start.len() - s.len())].iter().rev() { + if c == b'0' { + n_trailing_zeros += 1; + } else if c != b'.' { + break; + } + } + d.decimal_point += n_trailing_zeros as i32; + d.num_digits -= n_trailing_zeros; + d.decimal_point += d.num_digits as i32; + if d.num_digits > Decimal::MAX_DIGITS { + d.truncated = true; + d.num_digits = Decimal::MAX_DIGITS; + } + } + if let Some((&ch, s_next)) = s.split_first() { + if ch == b'e' || ch == b'E' { + s = s_next; + let mut neg_exp = false; + if let Some((&ch, s_next)) = s.split_first() { + neg_exp = ch == b'-'; + if ch == b'-' || ch == b'+' { + s = s_next; + } + } + let mut exp_num = 0_i32; + + s.parse_digits(|digit| { + if exp_num < 0x10000 { + exp_num = 10 * exp_num + digit as i32; + } + }); + + d.decimal_point += if neg_exp { -exp_num } else { exp_num }; + } + } + for i in d.num_digits..Decimal::MAX_DIGITS_WITHOUT_OVERFLOW { + d.digits[i] = 0; + } + d +} + +fn number_of_digits_decimal_left_shift(d: &Decimal, mut shift: usize) -> usize { + #[rustfmt::skip] + const TABLE: [u16; 65] = [ + 0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817, 0x181D, 0x2024, + 0x202B, 0x2033, 0x203C, 0x2846, 0x2850, 0x285B, 0x3067, 0x3073, 0x3080, 0x388E, 0x389C, + 0x38AB, 0x38BB, 0x40CC, 0x40DD, 0x40EF, 0x4902, 0x4915, 0x4929, 0x513E, 0x5153, 0x5169, + 0x5180, 0x5998, 0x59B0, 0x59C9, 0x61E3, 0x61FD, 0x6218, 0x6A34, 0x6A50, 0x6A6D, 0x6A8B, + 0x72AA, 0x72C9, 0x72E9, 0x7B0A, 0x7B2B, 0x7B4D, 0x8370, 0x8393, 0x83B7, 0x83DC, 0x8C02, + 0x8C28, 0x8C4F, 0x9477, 0x949F, 0x94C8, 0x9CF2, 0x051C, 0x051C, 0x051C, 0x051C, + ]; + #[rustfmt::skip] + const TABLE_POW5: [u8; 0x051C] = [ + 5, 2, 5, 1, 2, 5, 6, 2, 5, 3, 1, 2, 5, 1, 5, 6, 2, 5, 7, 8, 1, 2, 5, 3, 9, 0, 6, 2, 5, 1, + 9, 5, 3, 1, 2, 5, 9, 7, 6, 5, 6, 2, 5, 4, 8, 8, 2, 8, 1, 2, 5, 2, 4, 4, 1, 4, 0, 6, 2, 5, + 1, 2, 2, 0, 7, 0, 3, 1, 2, 5, 6, 1, 0, 3, 5, 1, 5, 6, 2, 5, 3, 0, 5, 1, 7, 5, 7, 8, 1, 2, + 5, 1, 5, 2, 5, 8, 7, 8, 9, 0, 6, 2, 5, 7, 6, 2, 9, 3, 9, 4, 5, 3, 1, 2, 5, 3, 8, 1, 4, 6, + 9, 7, 2, 6, 5, 6, 2, 5, 1, 9, 0, 7, 3, 4, 8, 6, 3, 2, 8, 1, 2, 5, 9, 5, 3, 6, 7, 4, 3, 1, + 6, 4, 0, 6, 2, 5, 4, 7, 6, 8, 3, 7, 1, 5, 8, 2, 0, 3, 1, 2, 5, 2, 3, 8, 4, 1, 8, 5, 7, 9, + 1, 0, 1, 5, 6, 2, 5, 1, 1, 9, 2, 0, 9, 2, 8, 9, 5, 5, 0, 7, 8, 1, 2, 5, 5, 9, 6, 0, 4, 6, + 4, 4, 7, 7, 5, 3, 9, 0, 6, 2, 5, 2, 9, 8, 0, 2, 3, 2, 2, 3, 8, 7, 6, 9, 5, 3, 1, 2, 5, 1, + 4, 9, 0, 1, 1, 6, 1, 1, 9, 3, 8, 4, 7, 6, 5, 6, 2, 5, 7, 4, 5, 0, 5, 8, 0, 5, 9, 6, 9, 2, + 3, 8, 2, 8, 1, 2, 5, 3, 7, 2, 5, 2, 9, 0, 2, 9, 8, 4, 6, 1, 9, 1, 4, 0, 6, 2, 5, 1, 8, 6, + 2, 6, 4, 5, 1, 4, 9, 2, 3, 0, 9, 5, 7, 0, 3, 1, 2, 5, 9, 3, 1, 3, 2, 2, 5, 7, 4, 6, 1, 5, + 4, 7, 8, 5, 1, 5, 6, 2, 5, 4, 6, 5, 6, 6, 1, 2, 8, 7, 3, 0, 7, 7, 3, 9, 2, 5, 7, 8, 1, 2, + 5, 2, 3, 2, 8, 3, 0, 6, 4, 3, 6, 5, 3, 8, 6, 9, 6, 2, 8, 9, 0, 6, 2, 5, 1, 1, 6, 4, 1, 5, + 3, 2, 1, 8, 2, 6, 9, 3, 4, 8, 1, 4, 4, 5, 3, 1, 2, 5, 5, 8, 2, 0, 7, 6, 6, 0, 9, 1, 3, 4, + 6, 7, 4, 0, 7, 2, 2, 6, 5, 6, 2, 5, 2, 9, 1, 0, 3, 8, 3, 0, 4, 5, 6, 7, 3, 3, 7, 0, 3, 6, + 1, 3, 2, 8, 1, 2, 5, 1, 4, 5, 5, 1, 9, 1, 5, 2, 2, 8, 3, 6, 6, 8, 5, 1, 8, 0, 6, 6, 4, 0, + 6, 2, 5, 7, 2, 7, 5, 9, 5, 7, 6, 1, 4, 1, 8, 3, 4, 2, 5, 9, 0, 3, 3, 2, 0, 3, 1, 2, 5, 3, + 6, 3, 7, 9, 7, 8, 8, 0, 7, 0, 9, 1, 7, 1, 2, 9, 5, 1, 6, 6, 0, 1, 5, 6, 2, 5, 1, 8, 1, 8, + 9, 8, 9, 4, 0, 3, 5, 4, 5, 8, 5, 6, 4, 7, 5, 8, 3, 0, 0, 7, 8, 1, 2, 5, 9, 0, 9, 4, 9, 4, + 7, 0, 1, 7, 7, 2, 9, 2, 8, 2, 3, 7, 9, 1, 5, 0, 3, 9, 0, 6, 2, 5, 4, 5, 4, 7, 4, 7, 3, 5, + 0, 8, 8, 6, 4, 6, 4, 1, 1, 8, 9, 5, 7, 5, 1, 9, 5, 3, 1, 2, 5, 2, 2, 7, 3, 7, 3, 6, 7, 5, + 4, 4, 3, 2, 3, 2, 0, 5, 9, 4, 7, 8, 7, 5, 9, 7, 6, 5, 6, 2, 5, 1, 1, 3, 6, 8, 6, 8, 3, 7, + 7, 2, 1, 6, 1, 6, 0, 2, 9, 7, 3, 9, 3, 7, 9, 8, 8, 2, 8, 1, 2, 5, 5, 6, 8, 4, 3, 4, 1, 8, + 8, 6, 0, 8, 0, 8, 0, 1, 4, 8, 6, 9, 6, 8, 9, 9, 4, 1, 4, 0, 6, 2, 5, 2, 8, 4, 2, 1, 7, 0, + 9, 4, 3, 0, 4, 0, 4, 0, 0, 7, 4, 3, 4, 8, 4, 4, 9, 7, 0, 7, 0, 3, 1, 2, 5, 1, 4, 2, 1, 0, + 8, 5, 4, 7, 1, 5, 2, 0, 2, 0, 0, 3, 7, 1, 7, 4, 2, 2, 4, 8, 5, 3, 5, 1, 5, 6, 2, 5, 7, 1, + 0, 5, 4, 2, 7, 3, 5, 7, 6, 0, 1, 0, 0, 1, 8, 5, 8, 7, 1, 1, 2, 4, 2, 6, 7, 5, 7, 8, 1, 2, + 5, 3, 5, 5, 2, 7, 1, 3, 6, 7, 8, 8, 0, 0, 5, 0, 0, 9, 2, 9, 3, 5, 5, 6, 2, 1, 3, 3, 7, 8, + 9, 0, 6, 2, 5, 1, 7, 7, 6, 3, 5, 6, 8, 3, 9, 4, 0, 0, 2, 5, 0, 4, 6, 4, 6, 7, 7, 8, 1, 0, + 6, 6, 8, 9, 4, 5, 3, 1, 2, 5, 8, 8, 8, 1, 7, 8, 4, 1, 9, 7, 0, 0, 1, 2, 5, 2, 3, 2, 3, 3, + 8, 9, 0, 5, 3, 3, 4, 4, 7, 2, 6, 5, 6, 2, 5, 4, 4, 4, 0, 8, 9, 2, 0, 9, 8, 5, 0, 0, 6, 2, + 6, 1, 6, 1, 6, 9, 4, 5, 2, 6, 6, 7, 2, 3, 6, 3, 2, 8, 1, 2, 5, 2, 2, 2, 0, 4, 4, 6, 0, 4, + 9, 2, 5, 0, 3, 1, 3, 0, 8, 0, 8, 4, 7, 2, 6, 3, 3, 3, 6, 1, 8, 1, 6, 4, 0, 6, 2, 5, 1, 1, + 1, 0, 2, 2, 3, 0, 2, 4, 6, 2, 5, 1, 5, 6, 5, 4, 0, 4, 2, 3, 6, 3, 1, 6, 6, 8, 0, 9, 0, 8, + 2, 0, 3, 1, 2, 5, 5, 5, 5, 1, 1, 1, 5, 1, 2, 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5, + 8, 3, 4, 0, 4, 5, 4, 1, 0, 1, 5, 6, 2, 5, 2, 7, 7, 5, 5, 5, 7, 5, 6, 1, 5, 6, 2, 8, 9, 1, + 3, 5, 1, 0, 5, 9, 0, 7, 9, 1, 7, 0, 2, 2, 7, 0, 5, 0, 7, 8, 1, 2, 5, 1, 3, 8, 7, 7, 7, 8, + 7, 8, 0, 7, 8, 1, 4, 4, 5, 6, 7, 5, 5, 2, 9, 5, 3, 9, 5, 8, 5, 1, 1, 3, 5, 2, 5, 3, 9, 0, + 6, 2, 5, 6, 9, 3, 8, 8, 9, 3, 9, 0, 3, 9, 0, 7, 2, 2, 8, 3, 7, 7, 6, 4, 7, 6, 9, 7, 9, 2, + 5, 5, 6, 7, 6, 2, 6, 9, 5, 3, 1, 2, 5, 3, 4, 6, 9, 4, 4, 6, 9, 5, 1, 9, 5, 3, 6, 1, 4, 1, + 8, 8, 8, 2, 3, 8, 4, 8, 9, 6, 2, 7, 8, 3, 8, 1, 3, 4, 7, 6, 5, 6, 2, 5, 1, 7, 3, 4, 7, 2, + 3, 4, 7, 5, 9, 7, 6, 8, 0, 7, 0, 9, 4, 4, 1, 1, 9, 2, 4, 4, 8, 1, 3, 9, 1, 9, 0, 6, 7, 3, + 8, 2, 8, 1, 2, 5, 8, 6, 7, 3, 6, 1, 7, 3, 7, 9, 8, 8, 4, 0, 3, 5, 4, 7, 2, 0, 5, 9, 6, 2, + 2, 4, 0, 6, 9, 5, 9, 5, 3, 3, 6, 9, 1, 4, 0, 6, 2, 5, + ]; + + shift &= 63; + let x_a = TABLE[shift]; + let x_b = TABLE[shift + 1]; + let num_new_digits = (x_a >> 11) as _; + let pow5_a = (0x7FF & x_a) as usize; + let pow5_b = (0x7FF & x_b) as usize; + let pow5 = &TABLE_POW5[pow5_a..]; + for (i, &p5) in pow5.iter().enumerate().take(pow5_b - pow5_a) { + if i >= d.num_digits { + return num_new_digits - 1; + } else if d.digits[i] == p5 { + continue; + } else if d.digits[i] < p5 { + return num_new_digits - 1; + } else { + return num_new_digits; + } + } + num_new_digits +} diff --git a/CoqOfRust/core/num/dec2flt/float.rs b/CoqOfRust/core/num/dec2flt/float.rs new file mode 100644 index 000000000..da57aa9a5 --- /dev/null +++ b/CoqOfRust/core/num/dec2flt/float.rs @@ -0,0 +1,211 @@ +//! Helper trait for generic float types. + +use crate::fmt::{Debug, LowerExp}; +use crate::num::FpCategory; +use crate::ops::{Add, Div, Mul, Neg}; + +/// A helper trait to avoid duplicating basically all the conversion code for `f32` and `f64`. +/// +/// See the parent module's doc comment for why this is necessary. +/// +/// Should **never ever** be implemented for other types or be used outside the dec2flt module. +#[doc(hidden)] +pub trait RawFloat: + Sized + + Div + + Neg + + Mul + + Add + + LowerExp + + PartialEq + + PartialOrd + + Default + + Clone + + Copy + + Debug +{ + const INFINITY: Self; + const NEG_INFINITY: Self; + const NAN: Self; + const NEG_NAN: Self; + + /// The number of bits in the significand, *excluding* the hidden bit. + const MANTISSA_EXPLICIT_BITS: usize; + + // Round-to-even only happens for negative values of q + // when q ≥ −4 in the 64-bit case and when q ≥ −17 in + // the 32-bitcase. + // + // When q ≥ 0,we have that 5^q ≤ 2m+1. In the 64-bit case,we + // have 5^q ≤ 2m+1 ≤ 2^54 or q ≤ 23. In the 32-bit case,we have + // 5^q ≤ 2m+1 ≤ 2^25 or q ≤ 10. + // + // When q < 0, we have w ≥ (2m+1)×5^−q. We must have that w < 2^64 + // so (2m+1)×5^−q < 2^64. We have that 2m+1 > 2^53 (64-bit case) + // or 2m+1 > 2^24 (32-bit case). Hence,we must have 2^53×5^−q < 2^64 + // (64-bit) and 2^24×5^−q < 2^64 (32-bit). Hence we have 5^−q < 2^11 + // or q ≥ −4 (64-bit case) and 5^−q < 2^40 or q ≥ −17 (32-bitcase). + // + // Thus we have that we only need to round ties to even when + // we have that q ∈ [−4,23](in the 64-bit case) or q∈[−17,10] + // (in the 32-bit case). In both cases,the power of five(5^|q|) + // fits in a 64-bit word. + const MIN_EXPONENT_ROUND_TO_EVEN: i32; + const MAX_EXPONENT_ROUND_TO_EVEN: i32; + + // Minimum exponent that for a fast path case, or `-⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋` + const MIN_EXPONENT_FAST_PATH: i64; + + // Maximum exponent that for a fast path case, or `⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋` + const MAX_EXPONENT_FAST_PATH: i64; + + // Maximum exponent that can be represented for a disguised-fast path case. + // This is `MAX_EXPONENT_FAST_PATH + ⌊(MANTISSA_EXPLICIT_BITS+1)/log2(10)⌋` + const MAX_EXPONENT_DISGUISED_FAST_PATH: i64; + + // Minimum exponent value `-(1 << (EXP_BITS - 1)) + 1`. + const MINIMUM_EXPONENT: i32; + + // Largest exponent value `(1 << EXP_BITS) - 1`. + const INFINITE_POWER: i32; + + // Index (in bits) of the sign. + const SIGN_INDEX: usize; + + // Smallest decimal exponent for a non-zero value. + const SMALLEST_POWER_OF_TEN: i32; + + // Largest decimal exponent for a non-infinite value. + const LARGEST_POWER_OF_TEN: i32; + + // Maximum mantissa for the fast-path (`1 << 53` for f64). + const MAX_MANTISSA_FAST_PATH: u64 = 2_u64 << Self::MANTISSA_EXPLICIT_BITS; + + /// Converts integer into float through an as cast. + /// This is only called in the fast-path algorithm, and therefore + /// will not lose precision, since the value will always have + /// only if the value is <= Self::MAX_MANTISSA_FAST_PATH. + fn from_u64(v: u64) -> Self; + + /// Performs a raw transmutation from an integer. + fn from_u64_bits(v: u64) -> Self; + + /// Gets a small power-of-ten for fast-path multiplication. + fn pow10_fast_path(exponent: usize) -> Self; + + /// Returns the category that this number falls into. + fn classify(self) -> FpCategory; + + /// Returns the mantissa, exponent and sign as integers. + fn integer_decode(self) -> (u64, i16, i8); +} + +impl RawFloat for f32 { + const INFINITY: Self = f32::INFINITY; + const NEG_INFINITY: Self = f32::NEG_INFINITY; + const NAN: Self = f32::NAN; + const NEG_NAN: Self = -f32::NAN; + + const MANTISSA_EXPLICIT_BITS: usize = 23; + const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -17; + const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 10; + const MIN_EXPONENT_FAST_PATH: i64 = -10; // assuming FLT_EVAL_METHOD = 0 + const MAX_EXPONENT_FAST_PATH: i64 = 10; + const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 = 17; + const MINIMUM_EXPONENT: i32 = -127; + const INFINITE_POWER: i32 = 0xFF; + const SIGN_INDEX: usize = 31; + const SMALLEST_POWER_OF_TEN: i32 = -65; + const LARGEST_POWER_OF_TEN: i32 = 38; + + #[inline] + fn from_u64(v: u64) -> Self { + debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH); + v as _ + } + + #[inline] + fn from_u64_bits(v: u64) -> Self { + f32::from_bits((v & 0xFFFFFFFF) as u32) + } + + fn pow10_fast_path(exponent: usize) -> Self { + #[allow(clippy::use_self)] + const TABLE: [f32; 16] = + [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.]; + TABLE[exponent & 15] + } + + /// Returns the mantissa, exponent and sign as integers. + fn integer_decode(self) -> (u64, i16, i8) { + let bits = self.to_bits(); + let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 }; + let mut exponent: i16 = ((bits >> 23) & 0xff) as i16; + let mantissa = + if exponent == 0 { (bits & 0x7fffff) << 1 } else { (bits & 0x7fffff) | 0x800000 }; + // Exponent bias + mantissa shift + exponent -= 127 + 23; + (mantissa as u64, exponent, sign) + } + + fn classify(self) -> FpCategory { + self.classify() + } +} + +impl RawFloat for f64 { + const INFINITY: Self = f64::INFINITY; + const NEG_INFINITY: Self = f64::NEG_INFINITY; + const NAN: Self = f64::NAN; + const NEG_NAN: Self = -f64::NAN; + + const MANTISSA_EXPLICIT_BITS: usize = 52; + const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -4; + const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 23; + const MIN_EXPONENT_FAST_PATH: i64 = -22; // assuming FLT_EVAL_METHOD = 0 + const MAX_EXPONENT_FAST_PATH: i64 = 22; + const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 = 37; + const MINIMUM_EXPONENT: i32 = -1023; + const INFINITE_POWER: i32 = 0x7FF; + const SIGN_INDEX: usize = 63; + const SMALLEST_POWER_OF_TEN: i32 = -342; + const LARGEST_POWER_OF_TEN: i32 = 308; + + #[inline] + fn from_u64(v: u64) -> Self { + debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH); + v as _ + } + + #[inline] + fn from_u64_bits(v: u64) -> Self { + f64::from_bits(v) + } + + fn pow10_fast_path(exponent: usize) -> Self { + const TABLE: [f64; 32] = [ + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, + 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 0., 0., 0., 0., 0., 0., 0., 0., 0., + ]; + TABLE[exponent & 31] + } + + /// Returns the mantissa, exponent and sign as integers. + fn integer_decode(self) -> (u64, i16, i8) { + let bits = self.to_bits(); + let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 }; + let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16; + let mantissa = if exponent == 0 { + (bits & 0xfffffffffffff) << 1 + } else { + (bits & 0xfffffffffffff) | 0x10000000000000 + }; + // Exponent bias + mantissa shift + exponent -= 1023 + 52; + (mantissa, exponent, sign) + } + + fn classify(self) -> FpCategory { + self.classify() + } +} diff --git a/CoqOfRust/core/num/dec2flt/fpu.rs b/CoqOfRust/core/num/dec2flt/fpu.rs new file mode 100644 index 000000000..8d62684f8 --- /dev/null +++ b/CoqOfRust/core/num/dec2flt/fpu.rs @@ -0,0 +1,101 @@ +//! Platform-specific, assembly instructions to avoid +//! intermediate rounding on architectures with FPUs. + +pub use fpu_precision::set_precision; + +// On x86, the x87 FPU is used for float operations if the SSE/SSE2 extensions are not available. +// The x87 FPU operates with 80 bits of precision by default, which means that operations will +// round to 80 bits causing double rounding to happen when values are eventually represented as +// 32/64 bit float values. To overcome this, the FPU control word can be set so that the +// computations are performed in the desired precision. +// +// Note that normally, it is Undefined Behavior to alter the FPU control word while Rust code runs. +// The compiler assumes that the control word is always in its default state. However, in this +// particular case the semantics with the altered control word are actually *more faithful* +// to Rust semantics than the default -- arguably it is all the code that runs *outside* of the scope +// of a `set_precision` guard that is wrong. +// In other words, we are only using this to work around . +// Sometimes killing UB with UB actually works... +// (If this is used to set 32bit precision, there is still a risk that the compiler moves some 64bit +// operation into the scope of the `set_precision` guard. So it's not like this is totally sound. +// But it's not really any less sound than the default state of 80bit precision...) +#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))] +mod fpu_precision { + use core::arch::asm; + use core::mem::size_of; + + /// A structure used to preserve the original value of the FPU control word, so that it can be + /// restored when the structure is dropped. + /// + /// The x87 FPU is a 16-bits register whose fields are as follows: + /// + /// | 12-15 | 10-11 | 8-9 | 6-7 | 5 | 4 | 3 | 2 | 1 | 0 | + /// |------:|------:|----:|----:|---:|---:|---:|---:|---:|---:| + /// | | RC | PC | | PM | UM | OM | ZM | DM | IM | + /// + /// The documentation for all of the fields is available in the IA-32 Architectures Software + /// Developer's Manual (Volume 1). + /// + /// The only field which is relevant for the following code is PC, Precision Control. This + /// field determines the precision of the operations performed by the FPU. It can be set to: + /// - 0b00, single precision i.e., 32-bits + /// - 0b10, double precision i.e., 64-bits + /// - 0b11, double extended precision i.e., 80-bits (default state) + /// The 0b01 value is reserved and should not be used. + 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 word ptr [{}]", + in(reg) &cw, + options(nostack), + ) + } + } + + /// Sets the precision field of the FPU to `T` and returns a `FPUControlWord`. + pub fn set_precision() -> FPUControlWord { + let mut cw = 0_u16; + + // Compute the value for the Precision Control field that is appropriate for `T`. + let cw_precision = match size_of::() { + 4 => 0x0000, // 32 bits + 8 => 0x0200, // 64 bits + _ => 0x0300, // default, 80 bits + }; + + // 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 word ptr [{}]", + in(reg) &mut cw, + options(nostack), + ) + } + + // Set the control word to the desired precision. This is achieved by masking away the old + // precision (bits 8 and 9, 0x300) and replacing it with the precision flag computed above. + set_cw((cw & 0xFCFF) | cw_precision); + + FPUControlWord(cw) + } + + impl Drop for FPUControlWord { + fn drop(&mut self) { + set_cw(self.0) + } + } +} + +// In most architectures, floating point operations have an explicit bit size, therefore the +// precision of the computation is determined on a per-operation basis. +#[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))] +mod fpu_precision { + pub fn set_precision() {} +} diff --git a/CoqOfRust/core/num/dec2flt/lemire.rs b/CoqOfRust/core/num/dec2flt/lemire.rs new file mode 100644 index 000000000..01642e1b1 --- /dev/null +++ b/CoqOfRust/core/num/dec2flt/lemire.rs @@ -0,0 +1,168 @@ +//! Implementation of the Eisel-Lemire algorithm. + +use crate::num::dec2flt::common::BiasedFp; +use crate::num::dec2flt::float::RawFloat; +use crate::num::dec2flt::table::{ + LARGEST_POWER_OF_FIVE, POWER_OF_FIVE_128, SMALLEST_POWER_OF_FIVE, +}; + +/// Compute w * 10^q using an extended-precision float representation. +/// +/// Fast conversion of a the significant digits and decimal exponent +/// a float to an extended representation with a binary float. This +/// algorithm will accurately parse the vast majority of cases, +/// and uses a 128-bit representation (with a fallback 192-bit +/// representation). +/// +/// This algorithm scales the exponent by the decimal exponent +/// using pre-computed powers-of-5, and calculates if the +/// representation can be unambiguously rounded to the nearest +/// machine float. Near-halfway cases are not handled here, +/// and are represented by a negative, biased binary exponent. +/// +/// The algorithm is described in detail in "Daniel Lemire, Number Parsing +/// at a Gigabyte per Second" in section 5, "Fast Algorithm", and +/// section 6, "Exact Numbers And Ties", available online: +/// . +pub fn compute_float(q: i64, mut w: u64) -> BiasedFp { + let fp_zero = BiasedFp::zero_pow2(0); + let fp_inf = BiasedFp::zero_pow2(F::INFINITE_POWER); + let fp_error = BiasedFp::zero_pow2(-1); + + // Short-circuit if the value can only be a literal 0 or infinity. + if w == 0 || q < F::SMALLEST_POWER_OF_TEN as i64 { + return fp_zero; + } else if q > F::LARGEST_POWER_OF_TEN as i64 { + return fp_inf; + } + // Normalize our significant digits, so the most-significant bit is set. + let lz = w.leading_zeros(); + w <<= lz; + let (lo, hi) = compute_product_approx(q, w, F::MANTISSA_EXPLICIT_BITS + 3); + if lo == 0xFFFF_FFFF_FFFF_FFFF { + // If we have failed to approximate w x 5^-q with our 128-bit value. + // Since the addition of 1 could lead to an overflow which could then + // round up over the half-way point, this can lead to improper rounding + // of a float. + // + // However, this can only occur if q ∈ [-27, 55]. The upper bound of q + // is 55 because 5^55 < 2^128, however, this can only happen if 5^q > 2^64, + // since otherwise the product can be represented in 64-bits, producing + // an exact result. For negative exponents, rounding-to-even can + // only occur if 5^-q < 2^64. + // + // For detailed explanations of rounding for negative exponents, see + // . For detailed + // explanations of rounding for positive exponents, see + // . + let inside_safe_exponent = (q >= -27) && (q <= 55); + if !inside_safe_exponent { + return fp_error; + } + } + let upperbit = (hi >> 63) as i32; + let mut mantissa = hi >> (upperbit + 64 - F::MANTISSA_EXPLICIT_BITS as i32 - 3); + let mut power2 = power(q as i32) + upperbit - lz as i32 - F::MINIMUM_EXPONENT; + if power2 <= 0 { + if -power2 + 1 >= 64 { + // Have more than 64 bits below the minimum exponent, must be 0. + return fp_zero; + } + // Have a subnormal value. + mantissa >>= -power2 + 1; + mantissa += mantissa & 1; + mantissa >>= 1; + power2 = (mantissa >= (1_u64 << F::MANTISSA_EXPLICIT_BITS)) as i32; + return BiasedFp { f: mantissa, e: power2 }; + } + // Need to handle rounding ties. Normally, we need to round up, + // but if we fall right in between and we have an even basis, we + // need to round down. + // + // This will only occur if: + // 1. The lower 64 bits of the 128-bit representation is 0. + // IE, 5^q fits in single 64-bit word. + // 2. The least-significant bit prior to truncated mantissa is odd. + // 3. All the bits truncated when shifting to mantissa bits + 1 are 0. + // + // Or, we may fall between two floats: we are exactly halfway. + if lo <= 1 + && q >= F::MIN_EXPONENT_ROUND_TO_EVEN as i64 + && q <= F::MAX_EXPONENT_ROUND_TO_EVEN as i64 + && mantissa & 3 == 1 + && (mantissa << (upperbit + 64 - F::MANTISSA_EXPLICIT_BITS as i32 - 3)) == hi + { + // Zero the lowest bit, so we don't round up. + mantissa &= !1_u64; + } + // Round-to-even, then shift the significant digits into place. + mantissa += mantissa & 1; + mantissa >>= 1; + if mantissa >= (2_u64 << F::MANTISSA_EXPLICIT_BITS) { + // Rounding up overflowed, so the carry bit is set. Set the + // mantissa to 1 (only the implicit, hidden bit is set) and + // increase the exponent. + mantissa = 1_u64 << F::MANTISSA_EXPLICIT_BITS; + power2 += 1; + } + // Zero out the hidden bit. + mantissa &= !(1_u64 << F::MANTISSA_EXPLICIT_BITS); + if power2 >= F::INFINITE_POWER { + // Exponent is above largest normal value, must be infinite. + return fp_inf; + } + BiasedFp { f: mantissa, e: power2 } +} + +/// Calculate a base 2 exponent from a decimal exponent. +/// This uses a pre-computed integer approximation for +/// log2(10), where 217706 / 2^16 is accurate for the +/// entire range of non-finite decimal exponents. +#[inline] +fn power(q: i32) -> i32 { + (q.wrapping_mul(152_170 + 65536) >> 16) + 63 +} + +#[inline] +fn full_multiplication(a: u64, b: u64) -> (u64, u64) { + let r = (a as u128) * (b as u128); + (r as u64, (r >> 64) as u64) +} + +// This will compute or rather approximate w * 5**q and return a pair of 64-bit words +// approximating the result, with the "high" part corresponding to the most significant +// bits and the low part corresponding to the least significant bits. +fn compute_product_approx(q: i64, w: u64, precision: usize) -> (u64, u64) { + debug_assert!(q >= SMALLEST_POWER_OF_FIVE as i64); + debug_assert!(q <= LARGEST_POWER_OF_FIVE as i64); + debug_assert!(precision <= 64); + + let mask = if precision < 64 { + 0xFFFF_FFFF_FFFF_FFFF_u64 >> precision + } else { + 0xFFFF_FFFF_FFFF_FFFF_u64 + }; + + // 5^q < 2^64, then the multiplication always provides an exact value. + // That means whenever we need to round ties to even, we always have + // an exact value. + let index = (q - SMALLEST_POWER_OF_FIVE as i64) as usize; + let (lo5, hi5) = POWER_OF_FIVE_128[index]; + // Only need one multiplication as long as there is 1 zero but + // in the explicit mantissa bits, +1 for the hidden bit, +1 to + // determine the rounding direction, +1 for if the computed + // product has a leading zero. + let (mut first_lo, mut first_hi) = full_multiplication(w, lo5); + if first_hi & mask == mask { + // Need to do a second multiplication to get better precision + // for the lower product. This will always be exact + // where q is < 55, since 5^55 < 2^128. If this wraps, + // then we need to round up the hi product. + let (_, second_hi) = full_multiplication(w, hi5); + first_lo = first_lo.wrapping_add(second_hi); + if second_hi > first_lo { + first_hi += 1; + } + } + (first_lo, first_hi) +} diff --git a/CoqOfRust/core/num/dec2flt/mod.rs b/CoqOfRust/core/num/dec2flt/mod.rs new file mode 100644 index 000000000..6dca74068 --- /dev/null +++ b/CoqOfRust/core/num/dec2flt/mod.rs @@ -0,0 +1,277 @@ +//! Converting decimal strings into IEEE 754 binary floating point numbers. +//! +//! # Problem statement +//! +//! We are given a decimal string such as `12.34e56`. This string consists of integral (`12`), +//! fractional (`34`), and exponent (`56`) parts. All parts are optional and interpreted as zero +//! when missing. +//! +//! We seek the IEEE 754 floating point number that is closest to the exact value of the decimal +//! string. It is well-known that many decimal strings do not have terminating representations in +//! base two, so we round to 0.5 units in the last place (in other words, as well as possible). +//! Ties, decimal values exactly half-way between two consecutive floats, are resolved with the +//! half-to-even strategy, also known as banker's rounding. +//! +//! Needless to say, this is quite hard, both in terms of implementation complexity and in terms +//! of CPU cycles taken. +//! +//! # Implementation +//! +//! First, we ignore signs. Or rather, we remove it at the very beginning of the conversion +//! process and re-apply it at the very end. This is correct in all edge cases since IEEE +//! floats are symmetric around zero, negating one simply flips the first bit. +//! +//! Then we remove the decimal point by adjusting the exponent: Conceptually, `12.34e56` turns +//! into `1234e54`, which we describe with a positive integer `f = 1234` and an integer `e = 54`. +//! The `(f, e)` representation is used by almost all code past the parsing stage. +//! +//! We then try a long chain of progressively more general and expensive special cases using +//! machine-sized integers and small, fixed-sized floating point numbers (first `f32`/`f64`, then +//! a type with 64 bit significand). The extended-precision algorithm +//! uses the Eisel-Lemire algorithm, which uses a 128-bit (or 192-bit) +//! representation that can accurately and quickly compute the vast majority +//! of floats. When all these fail, we bite the bullet and resort to using +//! a large-decimal representation, shifting the digits into range, calculating +//! the upper significant bits and exactly round to the nearest representation. +//! +//! Another aspect that needs attention is the ``RawFloat`` trait by which almost all functions +//! are parametrized. One might think that it's enough to parse to `f64` and cast the result to +//! `f32`. Unfortunately this is not the world we live in, and this has nothing to do with using +//! base two or half-to-even rounding. +//! +//! Consider for example two types `d2` and `d4` representing a decimal type with two decimal +//! digits and four decimal digits each and take "0.01499" as input. Let's use half-up rounding. +//! Going directly to two decimal digits gives `0.01`, but if we round to four digits first, +//! we get `0.0150`, which is then rounded up to `0.02`. The same principle applies to other +//! operations as well, if you want 0.5 ULP accuracy you need to do *everything* in full precision +//! and round *exactly once, at the end*, by considering all truncated bits at once. +//! +//! Primarily, this module and its children implement the algorithms described in: +//! "Number Parsing at a Gigabyte per Second", available online: +//! . +//! +//! # Other +//! +//! The conversion should *never* panic. There are assertions and explicit panics in the code, +//! but they should never be triggered and only serve as internal sanity checks. Any panics should +//! be considered a bug. +//! +//! There are unit tests but they are woefully inadequate at ensuring correctness, they only cover +//! a small percentage of possible errors. Far more extensive tests are located in the directory +//! `src/etc/test-float-parse` as a Rust program. +//! +//! A note on integer overflow: Many parts of this file perform arithmetic with the decimal +//! exponent `e`. Primarily, we shift the decimal point around: Before the first decimal digit, +//! after the last decimal digit, and so on. This could overflow if done carelessly. We rely on +//! the parsing submodule to only hand out sufficiently small exponents, where "sufficient" means +//! "such that the exponent +/- the number of decimal digits fits into a 64 bit integer". +//! Larger exponents are accepted, but we don't do arithmetic with them, they are immediately +//! turned into {positive,negative} {zero,infinity}. + +#![doc(hidden)] +#![unstable( + feature = "dec2flt", + reason = "internal routines only exposed for testing", + issue = "none" +)] + +use self::common::BiasedFp; +use self::float::RawFloat; +use self::lemire::compute_float; +use self::parse::{parse_inf_nan, parse_number}; +use self::slow::parse_long_mantissa; +use crate::error::Error; +use crate::fmt; +use crate::str::FromStr; + +mod common; +mod decimal; +mod fpu; +mod slow; +mod table; +// float is used in flt2dec, and all are used in unit tests. +pub mod float; +pub mod lemire; +pub mod number; +pub mod parse; + +macro_rules! from_str_float_impl { + ($t:ty) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl FromStr for $t { + type Err = ParseFloatError; + + /// Converts a string in base 10 to a float. + /// Accepts an optional decimal exponent. + /// + /// This function accepts strings such as + /// + /// * '3.14' + /// * '-3.14' + /// * '2.5E10', or equivalently, '2.5e10' + /// * '2.5E-10' + /// * '5.' + /// * '.5', or, equivalently, '0.5' + /// * 'inf', '-inf', '+infinity', 'NaN' + /// + /// Note that alphabetical characters are not case-sensitive. + /// + /// Leading and trailing whitespace represent an error. + /// + /// # Grammar + /// + /// All strings that adhere to the following [EBNF] grammar when + /// lowercased will result in an [`Ok`] being returned: + /// + /// ```txt + /// Float ::= Sign? ( 'inf' | 'infinity' | 'nan' | Number ) + /// Number ::= ( Digit+ | + /// Digit+ '.' Digit* | + /// Digit* '.' Digit+ ) Exp? + /// Exp ::= 'e' Sign? Digit+ + /// Sign ::= [+-] + /// Digit ::= [0-9] + /// ``` + /// + /// [EBNF]: https://www.w3.org/TR/REC-xml/#sec-notation + /// + /// # Arguments + /// + /// * src - A string + /// + /// # Return value + /// + /// `Err(ParseFloatError)` if the string did not represent a valid + /// number. Otherwise, `Ok(n)` where `n` is the closest + /// representable floating-point number to the number represented + /// by `src` (following the same rules for rounding as for the + /// results of primitive operations). + // We add the `#[inline(never)]` attribute, since its content will + // be filled with that of `dec2flt`, which has #[inline(always)]. + // Since `dec2flt` is generic, a normal inline attribute on this function + // with `dec2flt` having no attributes results in heavily repeated + // generation of `dec2flt`, despite the fact only a maximum of 2 + // possible instances can ever exist. Adding #[inline(never)] avoids this. + #[inline(never)] + fn from_str(src: &str) -> Result { + dec2flt(src) + } + } + }; +} +from_str_float_impl!(f32); +from_str_float_impl!(f64); + +/// An error which can be returned when parsing a float. +/// +/// This error is used as the error type for the [`FromStr`] implementation +/// for [`f32`] and [`f64`]. +/// +/// # Example +/// +/// ``` +/// use std::str::FromStr; +/// +/// if let Err(e) = f64::from_str("a.12") { +/// println!("Failed conversion to f64: {e}"); +/// } +/// ``` +#[derive(Debug, Clone, PartialEq, Eq)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct ParseFloatError { + kind: FloatErrorKind, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum FloatErrorKind { + Empty, + Invalid, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for ParseFloatError { + #[allow(deprecated)] + fn description(&self) -> &str { + match self.kind { + FloatErrorKind::Empty => "cannot parse float from empty string", + FloatErrorKind::Invalid => "invalid float literal", + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for ParseFloatError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + #[allow(deprecated)] + self.description().fmt(f) + } +} + +#[inline] +pub(super) fn pfe_empty() -> ParseFloatError { + ParseFloatError { kind: FloatErrorKind::Empty } +} + +// Used in unit tests, keep public. +// This is much better than making FloatErrorKind and ParseFloatError::kind public. +#[inline] +pub fn pfe_invalid() -> ParseFloatError { + ParseFloatError { kind: FloatErrorKind::Invalid } +} + +/// Converts a `BiasedFp` to the closest machine float type. +fn biased_fp_to_float(x: BiasedFp) -> T { + let mut word = x.f; + word |= (x.e as u64) << T::MANTISSA_EXPLICIT_BITS; + T::from_u64_bits(word) +} + +/// Converts a decimal string into a floating point number. +#[inline(always)] // Will be inlined into a function with `#[inline(never)]`, see above +pub fn dec2flt(s: &str) -> Result { + let mut s = s.as_bytes(); + let c = if let Some(&c) = s.first() { + c + } else { + return Err(pfe_empty()); + }; + let negative = c == b'-'; + if c == b'-' || c == b'+' { + s = &s[1..]; + } + if s.is_empty() { + return Err(pfe_invalid()); + } + + let mut num = match parse_number(s) { + Some(r) => r, + None if let Some(value) = parse_inf_nan(s, negative) => return Ok(value), + None => return Err(pfe_invalid()), + }; + num.negative = negative; + if !cfg!(feature = "optimize_for_size") { + if let Some(value) = num.try_fast_path::() { + return Ok(value); + } + } + + // If significant digits were truncated, then we can have rounding error + // only if `mantissa + 1` produces a different result. We also avoid + // redundantly using the Eisel-Lemire algorithm if it was unable to + // correctly round on the first pass. + let mut fp = compute_float::(num.exponent, num.mantissa); + if num.many_digits && fp.e >= 0 && fp != compute_float::(num.exponent, num.mantissa + 1) { + fp.e = -1; + } + // Unable to correctly round the float using the Eisel-Lemire algorithm. + // Fallback to a slower, but always correct algorithm. + if fp.e < 0 { + fp = parse_long_mantissa::(s); + } + + let mut float = biased_fp_to_float::(fp); + if num.negative { + float = -float; + } + Ok(float) +} diff --git a/CoqOfRust/core/num/dec2flt/number.rs b/CoqOfRust/core/num/dec2flt/number.rs new file mode 100644 index 000000000..253899156 --- /dev/null +++ b/CoqOfRust/core/num/dec2flt/number.rs @@ -0,0 +1,88 @@ +//! Representation of a float as the significant digits and exponent. + +use crate::num::dec2flt::float::RawFloat; +use crate::num::dec2flt::fpu::set_precision; + +#[rustfmt::skip] +const INT_POW10: [u64; 16] = [ + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000, + 100000000000, + 1000000000000, + 10000000000000, + 100000000000000, + 1000000000000000, +]; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct Number { + pub exponent: i64, + pub mantissa: u64, + pub negative: bool, + pub many_digits: bool, +} + +impl Number { + /// Detect if the float can be accurately reconstructed from native floats. + #[inline] + fn is_fast_path(&self) -> bool { + F::MIN_EXPONENT_FAST_PATH <= self.exponent + && self.exponent <= F::MAX_EXPONENT_DISGUISED_FAST_PATH + && self.mantissa <= F::MAX_MANTISSA_FAST_PATH + && !self.many_digits + } + + /// The fast path algorithm using machine-sized integers and floats. + /// + /// This is extracted into a separate function so that it can be attempted before constructing + /// a Decimal. This only works if both the mantissa and the exponent + /// can be exactly represented as a machine float, since IEE-754 guarantees + /// no rounding will occur. + /// + /// There is an exception: disguised fast-path cases, where we can shift + /// powers-of-10 from the exponent to the significant digits. + pub fn try_fast_path(&self) -> Option { + // Here we need to work around . + // The fast path crucially depends on arithmetic being rounded to the correct number of bits + // without any intermediate rounding. On x86 (without SSE or SSE2) this requires the precision + // of the x87 FPU stack to be changed so that it directly rounds to 64/32 bit. + // The `set_precision` function takes care of setting the precision on architectures which + // require setting it by changing the global state (like the control word of the x87 FPU). + let _cw = set_precision::(); + + if self.is_fast_path::() { + let mut value = if self.exponent <= F::MAX_EXPONENT_FAST_PATH { + // normal fast path + let value = F::from_u64(self.mantissa); + if self.exponent < 0 { + value / F::pow10_fast_path((-self.exponent) as _) + } else { + value * F::pow10_fast_path(self.exponent as _) + } + } else { + // disguised fast path + let shift = self.exponent - F::MAX_EXPONENT_FAST_PATH; + let mantissa = self.mantissa.checked_mul(INT_POW10[shift as usize])?; + if mantissa > F::MAX_MANTISSA_FAST_PATH { + return None; + } + F::from_u64(mantissa) * F::pow10_fast_path(F::MAX_EXPONENT_FAST_PATH as _) + }; + if self.negative { + value = -value; + } + Some(value) + } else { + None + } + } +} diff --git a/CoqOfRust/core/num/dec2flt/parse.rs b/CoqOfRust/core/num/dec2flt/parse.rs new file mode 100644 index 000000000..06ee8e95f --- /dev/null +++ b/CoqOfRust/core/num/dec2flt/parse.rs @@ -0,0 +1,241 @@ +//! Functions to parse floating-point numbers. + +use crate::num::dec2flt::common::{ByteSlice, is_8digits}; +use crate::num::dec2flt::float::RawFloat; +use crate::num::dec2flt::number::Number; + +const MIN_19DIGIT_INT: u64 = 100_0000_0000_0000_0000; + +/// Parse 8 digits, loaded as bytes in little-endian order. +/// +/// This uses the trick where every digit is in [0x030, 0x39], +/// and therefore can be parsed in 3 multiplications, much +/// faster than the normal 8. +/// +/// This is based off the algorithm described in "Fast numeric string to +/// int", available here: . +fn parse_8digits(mut v: u64) -> u64 { + const MASK: u64 = 0x0000_00FF_0000_00FF; + const MUL1: u64 = 0x000F_4240_0000_0064; + const MUL2: u64 = 0x0000_2710_0000_0001; + v -= 0x3030_3030_3030_3030; + v = (v * 10) + (v >> 8); // will not overflow, fits in 63 bits + let v1 = (v & MASK).wrapping_mul(MUL1); + let v2 = ((v >> 16) & MASK).wrapping_mul(MUL2); + ((v1.wrapping_add(v2) >> 32) as u32) as u64 +} + +/// Parse digits until a non-digit character is found. +fn try_parse_digits(mut s: &[u8], mut x: u64) -> (&[u8], u64) { + // may cause overflows, to be handled later + + while s.len() >= 8 { + let num = s.read_u64(); + if is_8digits(num) { + x = x.wrapping_mul(1_0000_0000).wrapping_add(parse_8digits(num)); + s = &s[8..]; + } else { + break; + } + } + + s = s.parse_digits(|digit| { + x = x.wrapping_mul(10).wrapping_add(digit as _); + }); + + (s, x) +} + +/// Parse up to 19 digits (the max that can be stored in a 64-bit integer). +fn try_parse_19digits(s_ref: &mut &[u8], x: &mut u64) { + let mut s = *s_ref; + + while *x < MIN_19DIGIT_INT { + if let Some((c, s_next)) = s.split_first() { + let digit = c.wrapping_sub(b'0'); + + if digit < 10 { + *x = (*x * 10) + digit as u64; // no overflows here + s = s_next; + } else { + break; + } + } else { + break; + } + } + + *s_ref = s; +} + +/// Parse the scientific notation component of a float. +fn parse_scientific(s_ref: &mut &[u8]) -> Option { + let mut exponent = 0i64; + let mut negative = false; + + let mut s = *s_ref; + + if let Some((&c, s_next)) = s.split_first() { + negative = c == b'-'; + if c == b'-' || c == b'+' { + s = s_next; + } + } + + if matches!(s.first(), Some(&x) if x.is_ascii_digit()) { + *s_ref = s.parse_digits(|digit| { + // no overflows here, saturate well before overflow + if exponent < 0x10000 { + exponent = 10 * exponent + digit as i64; + } + }); + if negative { Some(-exponent) } else { Some(exponent) } + } else { + *s_ref = s; + None + } +} + +/// Parse a partial, non-special floating point number. +/// +/// This creates a representation of the float as the +/// significant digits and the decimal exponent. +fn parse_partial_number(mut s: &[u8]) -> Option<(Number, usize)> { + debug_assert!(!s.is_empty()); + + // parse initial digits before dot + let mut mantissa = 0_u64; + let start = s; + let tmp = try_parse_digits(s, mantissa); + s = tmp.0; + mantissa = tmp.1; + let mut n_digits = s.offset_from(start); + + // handle dot with the following digits + let mut n_after_dot = 0; + let mut exponent = 0_i64; + let int_end = s; + + if let Some((&b'.', s_next)) = s.split_first() { + s = s_next; + let before = s; + let tmp = try_parse_digits(s, mantissa); + s = tmp.0; + mantissa = tmp.1; + n_after_dot = s.offset_from(before); + exponent = -n_after_dot as i64; + } + + n_digits += n_after_dot; + if n_digits == 0 { + return None; + } + + // handle scientific format + let mut exp_number = 0_i64; + if let Some((&c, s_next)) = s.split_first() { + if c == b'e' || c == b'E' { + s = s_next; + // If None, we have no trailing digits after exponent, or an invalid float. + exp_number = parse_scientific(&mut s)?; + exponent += exp_number; + } + } + + let len = s.offset_from(start) as _; + + // handle uncommon case with many digits + if n_digits <= 19 { + return Some((Number { exponent, mantissa, negative: false, many_digits: false }, len)); + } + + n_digits -= 19; + let mut many_digits = false; + let mut p = start; + while let Some((&c, p_next)) = p.split_first() { + if c == b'.' || c == b'0' { + n_digits -= c.saturating_sub(b'0' - 1) as isize; + p = p_next; + } else { + break; + } + } + if n_digits > 0 { + // at this point we have more than 19 significant digits, let's try again + many_digits = true; + mantissa = 0; + let mut s = start; + try_parse_19digits(&mut s, &mut mantissa); + exponent = if mantissa >= MIN_19DIGIT_INT { + // big int + int_end.offset_from(s) + } else { + s = &s[1..]; + let before = s; + try_parse_19digits(&mut s, &mut mantissa); + -s.offset_from(before) + } as i64; + // add back the explicit part + exponent += exp_number; + } + + Some((Number { exponent, mantissa, negative: false, many_digits }, len)) +} + +/// Try to parse a non-special floating point number, +/// as well as two slices with integer and fractional parts +/// and the parsed exponent. +pub fn parse_number(s: &[u8]) -> Option { + if let Some((float, rest)) = parse_partial_number(s) { + if rest == s.len() { + return Some(float); + } + } + None +} + +/// Try to parse a special, non-finite float. +pub(crate) fn parse_inf_nan(s: &[u8], negative: bool) -> Option { + // Since a valid string has at most the length 8, we can load + // all relevant characters into a u64 and work from there. + // This also generates much better code. + + let mut register; + let len: usize; + + // All valid strings are either of length 8 or 3. + if s.len() == 8 { + register = s.read_u64(); + len = 8; + } else if s.len() == 3 { + let a = s[0] as u64; + let b = s[1] as u64; + let c = s[2] as u64; + register = (c << 16) | (b << 8) | a; + len = 3; + } else { + return None; + } + + // Clear out the bits which turn ASCII uppercase characters into + // lowercase characters. The resulting string is all uppercase. + // What happens to other characters is irrelevant. + register &= 0xDFDFDFDFDFDFDFDF; + + // u64 values corresponding to relevant cases + const INF_3: u64 = 0x464E49; // "INF" + const INF_8: u64 = 0x5954494E49464E49; // "INFINITY" + const NAN: u64 = 0x4E414E; // "NAN" + + // Match register value to constant to parse string. + // Also match on the string length to catch edge cases + // like "inf\0\0\0\0\0". + let float = match (register, len) { + (INF_3, 3) => F::INFINITY, + (INF_8, 8) => F::INFINITY, + (NAN, 3) => F::NAN, + _ => return None, + }; + + if negative { Some(-float) } else { Some(float) } +} diff --git a/CoqOfRust/core/num/dec2flt/slow.rs b/CoqOfRust/core/num/dec2flt/slow.rs new file mode 100644 index 000000000..85d4b1328 --- /dev/null +++ b/CoqOfRust/core/num/dec2flt/slow.rs @@ -0,0 +1,109 @@ +//! Slow, fallback algorithm for cases the Eisel-Lemire algorithm cannot round. + +use crate::num::dec2flt::common::BiasedFp; +use crate::num::dec2flt::decimal::{Decimal, parse_decimal}; +use crate::num::dec2flt::float::RawFloat; + +/// Parse the significant digits and biased, binary exponent of a float. +/// +/// This is a fallback algorithm that uses a big-integer representation +/// of the float, and therefore is considerably slower than faster +/// approximations. However, it will always determine how to round +/// the significant digits to the nearest machine float, allowing +/// use to handle near half-way cases. +/// +/// Near half-way cases are halfway between two consecutive machine floats. +/// For example, the float `16777217.0` has a bitwise representation of +/// `100000000000000000000000 1`. Rounding to a single-precision float, +/// the trailing `1` is truncated. Using round-nearest, tie-even, any +/// value above `16777217.0` must be rounded up to `16777218.0`, while +/// any value before or equal to `16777217.0` must be rounded down +/// to `16777216.0`. These near-halfway conversions therefore may require +/// a large number of digits to unambiguously determine how to round. +/// +/// The algorithms described here are based on "Processing Long Numbers Quickly", +/// available here: . +pub(crate) fn parse_long_mantissa(s: &[u8]) -> BiasedFp { + const MAX_SHIFT: usize = 60; + const NUM_POWERS: usize = 19; + const POWERS: [u8; 19] = + [0, 3, 6, 9, 13, 16, 19, 23, 26, 29, 33, 36, 39, 43, 46, 49, 53, 56, 59]; + + let get_shift = |n| { + if n < NUM_POWERS { POWERS[n] as usize } else { MAX_SHIFT } + }; + + let fp_zero = BiasedFp::zero_pow2(0); + let fp_inf = BiasedFp::zero_pow2(F::INFINITE_POWER); + + let mut d = parse_decimal(s); + + // Short-circuit if the value can only be a literal 0 or infinity. + if d.num_digits == 0 || d.decimal_point < -324 { + return fp_zero; + } else if d.decimal_point >= 310 { + return fp_inf; + } + let mut exp2 = 0_i32; + // Shift right toward (1/2 ... 1]. + while d.decimal_point > 0 { + let n = d.decimal_point as usize; + let shift = get_shift(n); + d.right_shift(shift); + if d.decimal_point < -Decimal::DECIMAL_POINT_RANGE { + return fp_zero; + } + exp2 += shift as i32; + } + // Shift left toward (1/2 ... 1]. + while d.decimal_point <= 0 { + let shift = if d.decimal_point == 0 { + match d.digits[0] { + digit if digit >= 5 => break, + 0 | 1 => 2, + _ => 1, + } + } else { + get_shift((-d.decimal_point) as _) + }; + d.left_shift(shift); + if d.decimal_point > Decimal::DECIMAL_POINT_RANGE { + return fp_inf; + } + exp2 -= shift as i32; + } + // We are now in the range [1/2 ... 1] but the binary format uses [1 ... 2]. + exp2 -= 1; + while (F::MINIMUM_EXPONENT + 1) > exp2 { + let mut n = ((F::MINIMUM_EXPONENT + 1) - exp2) as usize; + if n > MAX_SHIFT { + n = MAX_SHIFT; + } + d.right_shift(n); + exp2 += n as i32; + } + if (exp2 - F::MINIMUM_EXPONENT) >= F::INFINITE_POWER { + return fp_inf; + } + // Shift the decimal to the hidden bit, and then round the value + // to get the high mantissa+1 bits. + d.left_shift(F::MANTISSA_EXPLICIT_BITS + 1); + let mut mantissa = d.round(); + if mantissa >= (1_u64 << (F::MANTISSA_EXPLICIT_BITS + 1)) { + // Rounding up overflowed to the carry bit, need to + // shift back to the hidden bit. + d.right_shift(1); + exp2 += 1; + mantissa = d.round(); + if (exp2 - F::MINIMUM_EXPONENT) >= F::INFINITE_POWER { + return fp_inf; + } + } + let mut power2 = exp2 - F::MINIMUM_EXPONENT; + if mantissa < (1_u64 << F::MANTISSA_EXPLICIT_BITS) { + power2 -= 1; + } + // Zero out all the bits above the explicit mantissa bits. + mantissa &= (1_u64 << F::MANTISSA_EXPLICIT_BITS) - 1; + BiasedFp { f: mantissa, e: power2 } +} diff --git a/CoqOfRust/core/num/dec2flt/table.rs b/CoqOfRust/core/num/dec2flt/table.rs new file mode 100644 index 000000000..4856074a6 --- /dev/null +++ b/CoqOfRust/core/num/dec2flt/table.rs @@ -0,0 +1,670 @@ +//! Pre-computed tables powers-of-5 for extended-precision representations. +//! +//! These tables enable fast scaling of the significant digits +//! of a float to the decimal exponent, with minimal rounding +//! errors, in a 128 or 192-bit representation. +//! +//! DO NOT MODIFY: Generated by `src/etc/dec2flt_table.py` + +pub const SMALLEST_POWER_OF_FIVE: i32 = -342; +pub const LARGEST_POWER_OF_FIVE: i32 = 308; +pub const N_POWERS_OF_FIVE: usize = (LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize; + +// Use static to avoid long compile times: Rust compiler errors +// can have the entire table compiled multiple times, and then +// emit code multiple times, even if it's stripped out in +// the final binary. +#[rustfmt::skip] +pub static POWER_OF_FIVE_128: [(u64, u64); N_POWERS_OF_FIVE] = [ + (0xeef453d6923bd65a, 0x113faa2906a13b3f), // 5^-342 + (0x9558b4661b6565f8, 0x4ac7ca59a424c507), // 5^-341 + (0xbaaee17fa23ebf76, 0x5d79bcf00d2df649), // 5^-340 + (0xe95a99df8ace6f53, 0xf4d82c2c107973dc), // 5^-339 + (0x91d8a02bb6c10594, 0x79071b9b8a4be869), // 5^-338 + (0xb64ec836a47146f9, 0x9748e2826cdee284), // 5^-337 + (0xe3e27a444d8d98b7, 0xfd1b1b2308169b25), // 5^-336 + (0x8e6d8c6ab0787f72, 0xfe30f0f5e50e20f7), // 5^-335 + (0xb208ef855c969f4f, 0xbdbd2d335e51a935), // 5^-334 + (0xde8b2b66b3bc4723, 0xad2c788035e61382), // 5^-333 + (0x8b16fb203055ac76, 0x4c3bcb5021afcc31), // 5^-332 + (0xaddcb9e83c6b1793, 0xdf4abe242a1bbf3d), // 5^-331 + (0xd953e8624b85dd78, 0xd71d6dad34a2af0d), // 5^-330 + (0x87d4713d6f33aa6b, 0x8672648c40e5ad68), // 5^-329 + (0xa9c98d8ccb009506, 0x680efdaf511f18c2), // 5^-328 + (0xd43bf0effdc0ba48, 0x212bd1b2566def2), // 5^-327 + (0x84a57695fe98746d, 0x14bb630f7604b57), // 5^-326 + (0xa5ced43b7e3e9188, 0x419ea3bd35385e2d), // 5^-325 + (0xcf42894a5dce35ea, 0x52064cac828675b9), // 5^-324 + (0x818995ce7aa0e1b2, 0x7343efebd1940993), // 5^-323 + (0xa1ebfb4219491a1f, 0x1014ebe6c5f90bf8), // 5^-322 + (0xca66fa129f9b60a6, 0xd41a26e077774ef6), // 5^-321 + (0xfd00b897478238d0, 0x8920b098955522b4), // 5^-320 + (0x9e20735e8cb16382, 0x55b46e5f5d5535b0), // 5^-319 + (0xc5a890362fddbc62, 0xeb2189f734aa831d), // 5^-318 + (0xf712b443bbd52b7b, 0xa5e9ec7501d523e4), // 5^-317 + (0x9a6bb0aa55653b2d, 0x47b233c92125366e), // 5^-316 + (0xc1069cd4eabe89f8, 0x999ec0bb696e840a), // 5^-315 + (0xf148440a256e2c76, 0xc00670ea43ca250d), // 5^-314 + (0x96cd2a865764dbca, 0x380406926a5e5728), // 5^-313 + (0xbc807527ed3e12bc, 0xc605083704f5ecf2), // 5^-312 + (0xeba09271e88d976b, 0xf7864a44c633682e), // 5^-311 + (0x93445b8731587ea3, 0x7ab3ee6afbe0211d), // 5^-310 + (0xb8157268fdae9e4c, 0x5960ea05bad82964), // 5^-309 + (0xe61acf033d1a45df, 0x6fb92487298e33bd), // 5^-308 + (0x8fd0c16206306bab, 0xa5d3b6d479f8e056), // 5^-307 + (0xb3c4f1ba87bc8696, 0x8f48a4899877186c), // 5^-306 + (0xe0b62e2929aba83c, 0x331acdabfe94de87), // 5^-305 + (0x8c71dcd9ba0b4925, 0x9ff0c08b7f1d0b14), // 5^-304 + (0xaf8e5410288e1b6f, 0x7ecf0ae5ee44dd9), // 5^-303 + (0xdb71e91432b1a24a, 0xc9e82cd9f69d6150), // 5^-302 + (0x892731ac9faf056e, 0xbe311c083a225cd2), // 5^-301 + (0xab70fe17c79ac6ca, 0x6dbd630a48aaf406), // 5^-300 + (0xd64d3d9db981787d, 0x92cbbccdad5b108), // 5^-299 + (0x85f0468293f0eb4e, 0x25bbf56008c58ea5), // 5^-298 + (0xa76c582338ed2621, 0xaf2af2b80af6f24e), // 5^-297 + (0xd1476e2c07286faa, 0x1af5af660db4aee1), // 5^-296 + (0x82cca4db847945ca, 0x50d98d9fc890ed4d), // 5^-295 + (0xa37fce126597973c, 0xe50ff107bab528a0), // 5^-294 + (0xcc5fc196fefd7d0c, 0x1e53ed49a96272c8), // 5^-293 + (0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7a), // 5^-292 + (0x9faacf3df73609b1, 0x77b191618c54e9ac), // 5^-291 + (0xc795830d75038c1d, 0xd59df5b9ef6a2417), // 5^-290 + (0xf97ae3d0d2446f25, 0x4b0573286b44ad1d), // 5^-289 + (0x9becce62836ac577, 0x4ee367f9430aec32), // 5^-288 + (0xc2e801fb244576d5, 0x229c41f793cda73f), // 5^-287 + (0xf3a20279ed56d48a, 0x6b43527578c1110f), // 5^-286 + (0x9845418c345644d6, 0x830a13896b78aaa9), // 5^-285 + (0xbe5691ef416bd60c, 0x23cc986bc656d553), // 5^-284 + (0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa8), // 5^-283 + (0x94b3a202eb1c3f39, 0x7bf7d71432f3d6a9), // 5^-282 + (0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc53), // 5^-281 + (0xe858ad248f5c22c9, 0xd1b3400f8f9cff68), // 5^-280 + (0x91376c36d99995be, 0x23100809b9c21fa1), // 5^-279 + (0xb58547448ffffb2d, 0xabd40a0c2832a78a), // 5^-278 + (0xe2e69915b3fff9f9, 0x16c90c8f323f516c), // 5^-277 + (0x8dd01fad907ffc3b, 0xae3da7d97f6792e3), // 5^-276 + (0xb1442798f49ffb4a, 0x99cd11cfdf41779c), // 5^-275 + (0xdd95317f31c7fa1d, 0x40405643d711d583), // 5^-274 + (0x8a7d3eef7f1cfc52, 0x482835ea666b2572), // 5^-273 + (0xad1c8eab5ee43b66, 0xda3243650005eecf), // 5^-272 + (0xd863b256369d4a40, 0x90bed43e40076a82), // 5^-271 + (0x873e4f75e2224e68, 0x5a7744a6e804a291), // 5^-270 + (0xa90de3535aaae202, 0x711515d0a205cb36), // 5^-269 + (0xd3515c2831559a83, 0xd5a5b44ca873e03), // 5^-268 + (0x8412d9991ed58091, 0xe858790afe9486c2), // 5^-267 + (0xa5178fff668ae0b6, 0x626e974dbe39a872), // 5^-266 + (0xce5d73ff402d98e3, 0xfb0a3d212dc8128f), // 5^-265 + (0x80fa687f881c7f8e, 0x7ce66634bc9d0b99), // 5^-264 + (0xa139029f6a239f72, 0x1c1fffc1ebc44e80), // 5^-263 + (0xc987434744ac874e, 0xa327ffb266b56220), // 5^-262 + (0xfbe9141915d7a922, 0x4bf1ff9f0062baa8), // 5^-261 + (0x9d71ac8fada6c9b5, 0x6f773fc3603db4a9), // 5^-260 + (0xc4ce17b399107c22, 0xcb550fb4384d21d3), // 5^-259 + (0xf6019da07f549b2b, 0x7e2a53a146606a48), // 5^-258 + (0x99c102844f94e0fb, 0x2eda7444cbfc426d), // 5^-257 + (0xc0314325637a1939, 0xfa911155fefb5308), // 5^-256 + (0xf03d93eebc589f88, 0x793555ab7eba27ca), // 5^-255 + (0x96267c7535b763b5, 0x4bc1558b2f3458de), // 5^-254 + (0xbbb01b9283253ca2, 0x9eb1aaedfb016f16), // 5^-253 + (0xea9c227723ee8bcb, 0x465e15a979c1cadc), // 5^-252 + (0x92a1958a7675175f, 0xbfacd89ec191ec9), // 5^-251 + (0xb749faed14125d36, 0xcef980ec671f667b), // 5^-250 + (0xe51c79a85916f484, 0x82b7e12780e7401a), // 5^-249 + (0x8f31cc0937ae58d2, 0xd1b2ecb8b0908810), // 5^-248 + (0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa15), // 5^-247 + (0xdfbdcece67006ac9, 0x67a791e093e1d49a), // 5^-246 + (0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e0), // 5^-245 + (0xaecc49914078536d, 0x58fae9f773886e18), // 5^-244 + (0xda7f5bf590966848, 0xaf39a475506a899e), // 5^-243 + (0x888f99797a5e012d, 0x6d8406c952429603), // 5^-242 + (0xaab37fd7d8f58178, 0xc8e5087ba6d33b83), // 5^-241 + (0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a64), // 5^-240 + (0x855c3be0a17fcd26, 0x5cf2eea09a55067f), // 5^-239 + (0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481e), // 5^-238 + (0xd0601d8efc57b08b, 0xf13b94daf124da26), // 5^-237 + (0x823c12795db6ce57, 0x76c53d08d6b70858), // 5^-236 + (0xa2cb1717b52481ed, 0x54768c4b0c64ca6e), // 5^-235 + (0xcb7ddcdda26da268, 0xa9942f5dcf7dfd09), // 5^-234 + (0xfe5d54150b090b02, 0xd3f93b35435d7c4c), // 5^-233 + (0x9efa548d26e5a6e1, 0xc47bc5014a1a6daf), // 5^-232 + (0xc6b8e9b0709f109a, 0x359ab6419ca1091b), // 5^-231 + (0xf867241c8cc6d4c0, 0xc30163d203c94b62), // 5^-230 + (0x9b407691d7fc44f8, 0x79e0de63425dcf1d), // 5^-229 + (0xc21094364dfb5636, 0x985915fc12f542e4), // 5^-228 + (0xf294b943e17a2bc4, 0x3e6f5b7b17b2939d), // 5^-227 + (0x979cf3ca6cec5b5a, 0xa705992ceecf9c42), // 5^-226 + (0xbd8430bd08277231, 0x50c6ff782a838353), // 5^-225 + (0xece53cec4a314ebd, 0xa4f8bf5635246428), // 5^-224 + (0x940f4613ae5ed136, 0x871b7795e136be99), // 5^-223 + (0xb913179899f68584, 0x28e2557b59846e3f), // 5^-222 + (0xe757dd7ec07426e5, 0x331aeada2fe589cf), // 5^-221 + (0x9096ea6f3848984f, 0x3ff0d2c85def7621), // 5^-220 + (0xb4bca50b065abe63, 0xfed077a756b53a9), // 5^-219 + (0xe1ebce4dc7f16dfb, 0xd3e8495912c62894), // 5^-218 + (0x8d3360f09cf6e4bd, 0x64712dd7abbbd95c), // 5^-217 + (0xb080392cc4349dec, 0xbd8d794d96aacfb3), // 5^-216 + (0xdca04777f541c567, 0xecf0d7a0fc5583a0), // 5^-215 + (0x89e42caaf9491b60, 0xf41686c49db57244), // 5^-214 + (0xac5d37d5b79b6239, 0x311c2875c522ced5), // 5^-213 + (0xd77485cb25823ac7, 0x7d633293366b828b), // 5^-212 + (0x86a8d39ef77164bc, 0xae5dff9c02033197), // 5^-211 + (0xa8530886b54dbdeb, 0xd9f57f830283fdfc), // 5^-210 + (0xd267caa862a12d66, 0xd072df63c324fd7b), // 5^-209 + (0x8380dea93da4bc60, 0x4247cb9e59f71e6d), // 5^-208 + (0xa46116538d0deb78, 0x52d9be85f074e608), // 5^-207 + (0xcd795be870516656, 0x67902e276c921f8b), // 5^-206 + (0x806bd9714632dff6, 0xba1cd8a3db53b6), // 5^-205 + (0xa086cfcd97bf97f3, 0x80e8a40eccd228a4), // 5^-204 + (0xc8a883c0fdaf7df0, 0x6122cd128006b2cd), // 5^-203 + (0xfad2a4b13d1b5d6c, 0x796b805720085f81), // 5^-202 + (0x9cc3a6eec6311a63, 0xcbe3303674053bb0), // 5^-201 + (0xc3f490aa77bd60fc, 0xbedbfc4411068a9c), // 5^-200 + (0xf4f1b4d515acb93b, 0xee92fb5515482d44), // 5^-199 + (0x991711052d8bf3c5, 0x751bdd152d4d1c4a), // 5^-198 + (0xbf5cd54678eef0b6, 0xd262d45a78a0635d), // 5^-197 + (0xef340a98172aace4, 0x86fb897116c87c34), // 5^-196 + (0x9580869f0e7aac0e, 0xd45d35e6ae3d4da0), // 5^-195 + (0xbae0a846d2195712, 0x8974836059cca109), // 5^-194 + (0xe998d258869facd7, 0x2bd1a438703fc94b), // 5^-193 + (0x91ff83775423cc06, 0x7b6306a34627ddcf), // 5^-192 + (0xb67f6455292cbf08, 0x1a3bc84c17b1d542), // 5^-191 + (0xe41f3d6a7377eeca, 0x20caba5f1d9e4a93), // 5^-190 + (0x8e938662882af53e, 0x547eb47b7282ee9c), // 5^-189 + (0xb23867fb2a35b28d, 0xe99e619a4f23aa43), // 5^-188 + (0xdec681f9f4c31f31, 0x6405fa00e2ec94d4), // 5^-187 + (0x8b3c113c38f9f37e, 0xde83bc408dd3dd04), // 5^-186 + (0xae0b158b4738705e, 0x9624ab50b148d445), // 5^-185 + (0xd98ddaee19068c76, 0x3badd624dd9b0957), // 5^-184 + (0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d6), // 5^-183 + (0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4c), // 5^-182 + (0xd47487cc8470652b, 0x7647c3200069671f), // 5^-181 + (0x84c8d4dfd2c63f3b, 0x29ecd9f40041e073), // 5^-180 + (0xa5fb0a17c777cf09, 0xf468107100525890), // 5^-179 + (0xcf79cc9db955c2cc, 0x7182148d4066eeb4), // 5^-178 + (0x81ac1fe293d599bf, 0xc6f14cd848405530), // 5^-177 + (0xa21727db38cb002f, 0xb8ada00e5a506a7c), // 5^-176 + (0xca9cf1d206fdc03b, 0xa6d90811f0e4851c), // 5^-175 + (0xfd442e4688bd304a, 0x908f4a166d1da663), // 5^-174 + (0x9e4a9cec15763e2e, 0x9a598e4e043287fe), // 5^-173 + (0xc5dd44271ad3cdba, 0x40eff1e1853f29fd), // 5^-172 + (0xf7549530e188c128, 0xd12bee59e68ef47c), // 5^-171 + (0x9a94dd3e8cf578b9, 0x82bb74f8301958ce), // 5^-170 + (0xc13a148e3032d6e7, 0xe36a52363c1faf01), // 5^-169 + (0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac1), // 5^-168 + (0x96f5600f15a7b7e5, 0x29ab103a5ef8c0b9), // 5^-167 + (0xbcb2b812db11a5de, 0x7415d448f6b6f0e7), // 5^-166 + (0xebdf661791d60f56, 0x111b495b3464ad21), // 5^-165 + (0x936b9fcebb25c995, 0xcab10dd900beec34), // 5^-164 + (0xb84687c269ef3bfb, 0x3d5d514f40eea742), // 5^-163 + (0xe65829b3046b0afa, 0xcb4a5a3112a5112), // 5^-162 + (0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ab), // 5^-161 + (0xb3f4e093db73a093, 0x59ed216765690f56), // 5^-160 + (0xe0f218b8d25088b8, 0x306869c13ec3532c), // 5^-159 + (0x8c974f7383725573, 0x1e414218c73a13fb), // 5^-158 + (0xafbd2350644eeacf, 0xe5d1929ef90898fa), // 5^-157 + (0xdbac6c247d62a583, 0xdf45f746b74abf39), // 5^-156 + (0x894bc396ce5da772, 0x6b8bba8c328eb783), // 5^-155 + (0xab9eb47c81f5114f, 0x66ea92f3f326564), // 5^-154 + (0xd686619ba27255a2, 0xc80a537b0efefebd), // 5^-153 + (0x8613fd0145877585, 0xbd06742ce95f5f36), // 5^-152 + (0xa798fc4196e952e7, 0x2c48113823b73704), // 5^-151 + (0xd17f3b51fca3a7a0, 0xf75a15862ca504c5), // 5^-150 + (0x82ef85133de648c4, 0x9a984d73dbe722fb), // 5^-149 + (0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebba), // 5^-148 + (0xcc963fee10b7d1b3, 0x318df905079926a8), // 5^-147 + (0xffbbcfe994e5c61f, 0xfdf17746497f7052), // 5^-146 + (0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa633), // 5^-145 + (0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc0), // 5^-144 + (0xf9bd690a1b68637b, 0x3dfdce7aa3c673b0), // 5^-143 + (0x9c1661a651213e2d, 0x6bea10ca65c084e), // 5^-142 + (0xc31bfa0fe5698db8, 0x486e494fcff30a62), // 5^-141 + (0xf3e2f893dec3f126, 0x5a89dba3c3efccfa), // 5^-140 + (0x986ddb5c6b3a76b7, 0xf89629465a75e01c), // 5^-139 + (0xbe89523386091465, 0xf6bbb397f1135823), // 5^-138 + (0xee2ba6c0678b597f, 0x746aa07ded582e2c), // 5^-137 + (0x94db483840b717ef, 0xa8c2a44eb4571cdc), // 5^-136 + (0xba121a4650e4ddeb, 0x92f34d62616ce413), // 5^-135 + (0xe896a0d7e51e1566, 0x77b020baf9c81d17), // 5^-134 + (0x915e2486ef32cd60, 0xace1474dc1d122e), // 5^-133 + (0xb5b5ada8aaff80b8, 0xd819992132456ba), // 5^-132 + (0xe3231912d5bf60e6, 0x10e1fff697ed6c69), // 5^-131 + (0x8df5efabc5979c8f, 0xca8d3ffa1ef463c1), // 5^-130 + (0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb2), // 5^-129 + (0xddd0467c64bce4a0, 0xac7cb3f6d05ddbde), // 5^-128 + (0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96b), // 5^-127 + (0xad4ab7112eb3929d, 0x86c16c98d2c953c6), // 5^-126 + (0xd89d64d57a607744, 0xe871c7bf077ba8b7), // 5^-125 + (0x87625f056c7c4a8b, 0x11471cd764ad4972), // 5^-124 + (0xa93af6c6c79b5d2d, 0xd598e40d3dd89bcf), // 5^-123 + (0xd389b47879823479, 0x4aff1d108d4ec2c3), // 5^-122 + (0x843610cb4bf160cb, 0xcedf722a585139ba), // 5^-121 + (0xa54394fe1eedb8fe, 0xc2974eb4ee658828), // 5^-120 + (0xce947a3da6a9273e, 0x733d226229feea32), // 5^-119 + (0x811ccc668829b887, 0x806357d5a3f525f), // 5^-118 + (0xa163ff802a3426a8, 0xca07c2dcb0cf26f7), // 5^-117 + (0xc9bcff6034c13052, 0xfc89b393dd02f0b5), // 5^-116 + (0xfc2c3f3841f17c67, 0xbbac2078d443ace2), // 5^-115 + (0x9d9ba7832936edc0, 0xd54b944b84aa4c0d), // 5^-114 + (0xc5029163f384a931, 0xa9e795e65d4df11), // 5^-113 + (0xf64335bcf065d37d, 0x4d4617b5ff4a16d5), // 5^-112 + (0x99ea0196163fa42e, 0x504bced1bf8e4e45), // 5^-111 + (0xc06481fb9bcf8d39, 0xe45ec2862f71e1d6), // 5^-110 + (0xf07da27a82c37088, 0x5d767327bb4e5a4c), // 5^-109 + (0x964e858c91ba2655, 0x3a6a07f8d510f86f), // 5^-108 + (0xbbe226efb628afea, 0x890489f70a55368b), // 5^-107 + (0xeadab0aba3b2dbe5, 0x2b45ac74ccea842e), // 5^-106 + (0x92c8ae6b464fc96f, 0x3b0b8bc90012929d), // 5^-105 + (0xb77ada0617e3bbcb, 0x9ce6ebb40173744), // 5^-104 + (0xe55990879ddcaabd, 0xcc420a6a101d0515), // 5^-103 + (0x8f57fa54c2a9eab6, 0x9fa946824a12232d), // 5^-102 + (0xb32df8e9f3546564, 0x47939822dc96abf9), // 5^-101 + (0xdff9772470297ebd, 0x59787e2b93bc56f7), // 5^-100 + (0x8bfbea76c619ef36, 0x57eb4edb3c55b65a), // 5^-99 + (0xaefae51477a06b03, 0xede622920b6b23f1), // 5^-98 + (0xdab99e59958885c4, 0xe95fab368e45eced), // 5^-97 + (0x88b402f7fd75539b, 0x11dbcb0218ebb414), // 5^-96 + (0xaae103b5fcd2a881, 0xd652bdc29f26a119), // 5^-95 + (0xd59944a37c0752a2, 0x4be76d3346f0495f), // 5^-94 + (0x857fcae62d8493a5, 0x6f70a4400c562ddb), // 5^-93 + (0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb952), // 5^-92 + (0xd097ad07a71f26b2, 0x7e2000a41346a7a7), // 5^-91 + (0x825ecc24c873782f, 0x8ed400668c0c28c8), // 5^-90 + (0xa2f67f2dfa90563b, 0x728900802f0f32fa), // 5^-89 + (0xcbb41ef979346bca, 0x4f2b40a03ad2ffb9), // 5^-88 + (0xfea126b7d78186bc, 0xe2f610c84987bfa8), // 5^-87 + (0x9f24b832e6b0f436, 0xdd9ca7d2df4d7c9), // 5^-86 + (0xc6ede63fa05d3143, 0x91503d1c79720dbb), // 5^-85 + (0xf8a95fcf88747d94, 0x75a44c6397ce912a), // 5^-84 + (0x9b69dbe1b548ce7c, 0xc986afbe3ee11aba), // 5^-83 + (0xc24452da229b021b, 0xfbe85badce996168), // 5^-82 + (0xf2d56790ab41c2a2, 0xfae27299423fb9c3), // 5^-81 + (0x97c560ba6b0919a5, 0xdccd879fc967d41a), // 5^-80 + (0xbdb6b8e905cb600f, 0x5400e987bbc1c920), // 5^-79 + (0xed246723473e3813, 0x290123e9aab23b68), // 5^-78 + (0x9436c0760c86e30b, 0xf9a0b6720aaf6521), // 5^-77 + (0xb94470938fa89bce, 0xf808e40e8d5b3e69), // 5^-76 + (0xe7958cb87392c2c2, 0xb60b1d1230b20e04), // 5^-75 + (0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c2), // 5^-74 + (0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af3), // 5^-73 + (0xe2280b6c20dd5232, 0x25c6da63c38de1b0), // 5^-72 + (0x8d590723948a535f, 0x579c487e5a38ad0e), // 5^-71 + (0xb0af48ec79ace837, 0x2d835a9df0c6d851), // 5^-70 + (0xdcdb1b2798182244, 0xf8e431456cf88e65), // 5^-69 + (0x8a08f0f8bf0f156b, 0x1b8e9ecb641b58ff), // 5^-68 + (0xac8b2d36eed2dac5, 0xe272467e3d222f3f), // 5^-67 + (0xd7adf884aa879177, 0x5b0ed81dcc6abb0f), // 5^-66 + (0x86ccbb52ea94baea, 0x98e947129fc2b4e9), // 5^-65 + (0xa87fea27a539e9a5, 0x3f2398d747b36224), // 5^-64 + (0xd29fe4b18e88640e, 0x8eec7f0d19a03aad), // 5^-63 + (0x83a3eeeef9153e89, 0x1953cf68300424ac), // 5^-62 + (0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd7), // 5^-61 + (0xcdb02555653131b6, 0x3792f412cb06794d), // 5^-60 + (0x808e17555f3ebf11, 0xe2bbd88bbee40bd0), // 5^-59 + (0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec4), // 5^-58 + (0xc8de047564d20a8b, 0xf245825a5a445275), // 5^-57 + (0xfb158592be068d2e, 0xeed6e2f0f0d56712), // 5^-56 + (0x9ced737bb6c4183d, 0x55464dd69685606b), // 5^-55 + (0xc428d05aa4751e4c, 0xaa97e14c3c26b886), // 5^-54 + (0xf53304714d9265df, 0xd53dd99f4b3066a8), // 5^-53 + (0x993fe2c6d07b7fab, 0xe546a8038efe4029), // 5^-52 + (0xbf8fdb78849a5f96, 0xde98520472bdd033), // 5^-51 + (0xef73d256a5c0f77c, 0x963e66858f6d4440), // 5^-50 + (0x95a8637627989aad, 0xdde7001379a44aa8), // 5^-49 + (0xbb127c53b17ec159, 0x5560c018580d5d52), // 5^-48 + (0xe9d71b689dde71af, 0xaab8f01e6e10b4a6), // 5^-47 + (0x9226712162ab070d, 0xcab3961304ca70e8), // 5^-46 + (0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d22), // 5^-45 + (0xe45c10c42a2b3b05, 0x8cb89a7db77c506a), // 5^-44 + (0x8eb98a7a9a5b04e3, 0x77f3608e92adb242), // 5^-43 + (0xb267ed1940f1c61c, 0x55f038b237591ed3), // 5^-42 + (0xdf01e85f912e37a3, 0x6b6c46dec52f6688), // 5^-41 + (0x8b61313bbabce2c6, 0x2323ac4b3b3da015), // 5^-40 + (0xae397d8aa96c1b77, 0xabec975e0a0d081a), // 5^-39 + (0xd9c7dced53c72255, 0x96e7bd358c904a21), // 5^-38 + (0x881cea14545c7575, 0x7e50d64177da2e54), // 5^-37 + (0xaa242499697392d2, 0xdde50bd1d5d0b9e9), // 5^-36 + (0xd4ad2dbfc3d07787, 0x955e4ec64b44e864), // 5^-35 + (0x84ec3c97da624ab4, 0xbd5af13bef0b113e), // 5^-34 + (0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58e), // 5^-33 + (0xcfb11ead453994ba, 0x67de18eda5814af2), // 5^-32 + (0x81ceb32c4b43fcf4, 0x80eacf948770ced7), // 5^-31 + (0xa2425ff75e14fc31, 0xa1258379a94d028d), // 5^-30 + (0xcad2f7f5359a3b3e, 0x96ee45813a04330), // 5^-29 + (0xfd87b5f28300ca0d, 0x8bca9d6e188853fc), // 5^-28 + (0x9e74d1b791e07e48, 0x775ea264cf55347e), // 5^-27 + (0xc612062576589dda, 0x95364afe032a819e), // 5^-26 + (0xf79687aed3eec551, 0x3a83ddbd83f52205), // 5^-25 + (0x9abe14cd44753b52, 0xc4926a9672793543), // 5^-24 + (0xc16d9a0095928a27, 0x75b7053c0f178294), // 5^-23 + (0xf1c90080baf72cb1, 0x5324c68b12dd6339), // 5^-22 + (0x971da05074da7bee, 0xd3f6fc16ebca5e04), // 5^-21 + (0xbce5086492111aea, 0x88f4bb1ca6bcf585), // 5^-20 + (0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6), // 5^-19 + (0x9392ee8e921d5d07, 0x3aff322e62439fd0), // 5^-18 + (0xb877aa3236a4b449, 0x9befeb9fad487c3), // 5^-17 + (0xe69594bec44de15b, 0x4c2ebe687989a9b4), // 5^-16 + (0x901d7cf73ab0acd9, 0xf9d37014bf60a11), // 5^-15 + (0xb424dc35095cd80f, 0x538484c19ef38c95), // 5^-14 + (0xe12e13424bb40e13, 0x2865a5f206b06fba), // 5^-13 + (0x8cbccc096f5088cb, 0xf93f87b7442e45d4), // 5^-12 + (0xafebff0bcb24aafe, 0xf78f69a51539d749), // 5^-11 + (0xdbe6fecebdedd5be, 0xb573440e5a884d1c), // 5^-10 + (0x89705f4136b4a597, 0x31680a88f8953031), // 5^-9 + (0xabcc77118461cefc, 0xfdc20d2b36ba7c3e), // 5^-8 + (0xd6bf94d5e57a42bc, 0x3d32907604691b4d), // 5^-7 + (0x8637bd05af6c69b5, 0xa63f9a49c2c1b110), // 5^-6 + (0xa7c5ac471b478423, 0xfcf80dc33721d54), // 5^-5 + (0xd1b71758e219652b, 0xd3c36113404ea4a9), // 5^-4 + (0x83126e978d4fdf3b, 0x645a1cac083126ea), // 5^-3 + (0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4), // 5^-2 + (0xcccccccccccccccc, 0xcccccccccccccccd), // 5^-1 + (0x8000000000000000, 0x0), // 5^0 + (0xa000000000000000, 0x0), // 5^1 + (0xc800000000000000, 0x0), // 5^2 + (0xfa00000000000000, 0x0), // 5^3 + (0x9c40000000000000, 0x0), // 5^4 + (0xc350000000000000, 0x0), // 5^5 + (0xf424000000000000, 0x0), // 5^6 + (0x9896800000000000, 0x0), // 5^7 + (0xbebc200000000000, 0x0), // 5^8 + (0xee6b280000000000, 0x0), // 5^9 + (0x9502f90000000000, 0x0), // 5^10 + (0xba43b74000000000, 0x0), // 5^11 + (0xe8d4a51000000000, 0x0), // 5^12 + (0x9184e72a00000000, 0x0), // 5^13 + (0xb5e620f480000000, 0x0), // 5^14 + (0xe35fa931a0000000, 0x0), // 5^15 + (0x8e1bc9bf04000000, 0x0), // 5^16 + (0xb1a2bc2ec5000000, 0x0), // 5^17 + (0xde0b6b3a76400000, 0x0), // 5^18 + (0x8ac7230489e80000, 0x0), // 5^19 + (0xad78ebc5ac620000, 0x0), // 5^20 + (0xd8d726b7177a8000, 0x0), // 5^21 + (0x878678326eac9000, 0x0), // 5^22 + (0xa968163f0a57b400, 0x0), // 5^23 + (0xd3c21bcecceda100, 0x0), // 5^24 + (0x84595161401484a0, 0x0), // 5^25 + (0xa56fa5b99019a5c8, 0x0), // 5^26 + (0xcecb8f27f4200f3a, 0x0), // 5^27 + (0x813f3978f8940984, 0x4000000000000000), // 5^28 + (0xa18f07d736b90be5, 0x5000000000000000), // 5^29 + (0xc9f2c9cd04674ede, 0xa400000000000000), // 5^30 + (0xfc6f7c4045812296, 0x4d00000000000000), // 5^31 + (0x9dc5ada82b70b59d, 0xf020000000000000), // 5^32 + (0xc5371912364ce305, 0x6c28000000000000), // 5^33 + (0xf684df56c3e01bc6, 0xc732000000000000), // 5^34 + (0x9a130b963a6c115c, 0x3c7f400000000000), // 5^35 + (0xc097ce7bc90715b3, 0x4b9f100000000000), // 5^36 + (0xf0bdc21abb48db20, 0x1e86d40000000000), // 5^37 + (0x96769950b50d88f4, 0x1314448000000000), // 5^38 + (0xbc143fa4e250eb31, 0x17d955a000000000), // 5^39 + (0xeb194f8e1ae525fd, 0x5dcfab0800000000), // 5^40 + (0x92efd1b8d0cf37be, 0x5aa1cae500000000), // 5^41 + (0xb7abc627050305ad, 0xf14a3d9e40000000), // 5^42 + (0xe596b7b0c643c719, 0x6d9ccd05d0000000), // 5^43 + (0x8f7e32ce7bea5c6f, 0xe4820023a2000000), // 5^44 + (0xb35dbf821ae4f38b, 0xdda2802c8a800000), // 5^45 + (0xe0352f62a19e306e, 0xd50b2037ad200000), // 5^46 + (0x8c213d9da502de45, 0x4526f422cc340000), // 5^47 + (0xaf298d050e4395d6, 0x9670b12b7f410000), // 5^48 + (0xdaf3f04651d47b4c, 0x3c0cdd765f114000), // 5^49 + (0x88d8762bf324cd0f, 0xa5880a69fb6ac800), // 5^50 + (0xab0e93b6efee0053, 0x8eea0d047a457a00), // 5^51 + (0xd5d238a4abe98068, 0x72a4904598d6d880), // 5^52 + (0x85a36366eb71f041, 0x47a6da2b7f864750), // 5^53 + (0xa70c3c40a64e6c51, 0x999090b65f67d924), // 5^54 + (0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d), // 5^55 + (0x82818f1281ed449f, 0xbff8f10e7a8921a4), // 5^56 + (0xa321f2d7226895c7, 0xaff72d52192b6a0d), // 5^57 + (0xcbea6f8ceb02bb39, 0x9bf4f8a69f764490), // 5^58 + (0xfee50b7025c36a08, 0x2f236d04753d5b4), // 5^59 + (0x9f4f2726179a2245, 0x1d762422c946590), // 5^60 + (0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef5), // 5^61 + (0xf8ebad2b84e0d58b, 0xd2e0898765a7deb2), // 5^62 + (0x9b934c3b330c8577, 0x63cc55f49f88eb2f), // 5^63 + (0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fb), // 5^64 + (0xf316271c7fc3908a, 0x8bef464e3945ef7a), // 5^65 + (0x97edd871cfda3a56, 0x97758bf0e3cbb5ac), // 5^66 + (0xbde94e8e43d0c8ec, 0x3d52eeed1cbea317), // 5^67 + (0xed63a231d4c4fb27, 0x4ca7aaa863ee4bdd), // 5^68 + (0x945e455f24fb1cf8, 0x8fe8caa93e74ef6a), // 5^69 + (0xb975d6b6ee39e436, 0xb3e2fd538e122b44), // 5^70 + (0xe7d34c64a9c85d44, 0x60dbbca87196b616), // 5^71 + (0x90e40fbeea1d3a4a, 0xbc8955e946fe31cd), // 5^72 + (0xb51d13aea4a488dd, 0x6babab6398bdbe41), // 5^73 + (0xe264589a4dcdab14, 0xc696963c7eed2dd1), // 5^74 + (0x8d7eb76070a08aec, 0xfc1e1de5cf543ca2), // 5^75 + (0xb0de65388cc8ada8, 0x3b25a55f43294bcb), // 5^76 + (0xdd15fe86affad912, 0x49ef0eb713f39ebe), // 5^77 + (0x8a2dbf142dfcc7ab, 0x6e3569326c784337), // 5^78 + (0xacb92ed9397bf996, 0x49c2c37f07965404), // 5^79 + (0xd7e77a8f87daf7fb, 0xdc33745ec97be906), // 5^80 + (0x86f0ac99b4e8dafd, 0x69a028bb3ded71a3), // 5^81 + (0xa8acd7c0222311bc, 0xc40832ea0d68ce0c), // 5^82 + (0xd2d80db02aabd62b, 0xf50a3fa490c30190), // 5^83 + (0x83c7088e1aab65db, 0x792667c6da79e0fa), // 5^84 + (0xa4b8cab1a1563f52, 0x577001b891185938), // 5^85 + (0xcde6fd5e09abcf26, 0xed4c0226b55e6f86), // 5^86 + (0x80b05e5ac60b6178, 0x544f8158315b05b4), // 5^87 + (0xa0dc75f1778e39d6, 0x696361ae3db1c721), // 5^88 + (0xc913936dd571c84c, 0x3bc3a19cd1e38e9), // 5^89 + (0xfb5878494ace3a5f, 0x4ab48a04065c723), // 5^90 + (0x9d174b2dcec0e47b, 0x62eb0d64283f9c76), // 5^91 + (0xc45d1df942711d9a, 0x3ba5d0bd324f8394), // 5^92 + (0xf5746577930d6500, 0xca8f44ec7ee36479), // 5^93 + (0x9968bf6abbe85f20, 0x7e998b13cf4e1ecb), // 5^94 + (0xbfc2ef456ae276e8, 0x9e3fedd8c321a67e), // 5^95 + (0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101e), // 5^96 + (0x95d04aee3b80ece5, 0xbba1f1d158724a12), // 5^97 + (0xbb445da9ca61281f, 0x2a8a6e45ae8edc97), // 5^98 + (0xea1575143cf97226, 0xf52d09d71a3293bd), // 5^99 + (0x924d692ca61be758, 0x593c2626705f9c56), // 5^100 + (0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836c), // 5^101 + (0xe498f455c38b997a, 0xb6dfb9c0f956447), // 5^102 + (0x8edf98b59a373fec, 0x4724bd4189bd5eac), // 5^103 + (0xb2977ee300c50fe7, 0x58edec91ec2cb657), // 5^104 + (0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ed), // 5^105 + (0x8b865b215899f46c, 0xbd79e0d20082ee74), // 5^106 + (0xae67f1e9aec07187, 0xecd8590680a3aa11), // 5^107 + (0xda01ee641a708de9, 0xe80e6f4820cc9495), // 5^108 + (0x884134fe908658b2, 0x3109058d147fdcdd), // 5^109 + (0xaa51823e34a7eede, 0xbd4b46f0599fd415), // 5^110 + (0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91a), // 5^111 + (0x850fadc09923329e, 0x3e2cf6bc604ddb0), // 5^112 + (0xa6539930bf6bff45, 0x84db8346b786151c), // 5^113 + (0xcfe87f7cef46ff16, 0xe612641865679a63), // 5^114 + (0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07e), // 5^115 + (0xa26da3999aef7749, 0xe3be5e330f38f09d), // 5^116 + (0xcb090c8001ab551c, 0x5cadf5bfd3072cc5), // 5^117 + (0xfdcb4fa002162a63, 0x73d9732fc7c8f7f6), // 5^118 + (0x9e9f11c4014dda7e, 0x2867e7fddcdd9afa), // 5^119 + (0xc646d63501a1511d, 0xb281e1fd541501b8), // 5^120 + (0xf7d88bc24209a565, 0x1f225a7ca91a4226), // 5^121 + (0x9ae757596946075f, 0x3375788de9b06958), // 5^122 + (0xc1a12d2fc3978937, 0x52d6b1641c83ae), // 5^123 + (0xf209787bb47d6b84, 0xc0678c5dbd23a49a), // 5^124 + (0x9745eb4d50ce6332, 0xf840b7ba963646e0), // 5^125 + (0xbd176620a501fbff, 0xb650e5a93bc3d898), // 5^126 + (0xec5d3fa8ce427aff, 0xa3e51f138ab4cebe), // 5^127 + (0x93ba47c980e98cdf, 0xc66f336c36b10137), // 5^128 + (0xb8a8d9bbe123f017, 0xb80b0047445d4184), // 5^129 + (0xe6d3102ad96cec1d, 0xa60dc059157491e5), // 5^130 + (0x9043ea1ac7e41392, 0x87c89837ad68db2f), // 5^131 + (0xb454e4a179dd1877, 0x29babe4598c311fb), // 5^132 + (0xe16a1dc9d8545e94, 0xf4296dd6fef3d67a), // 5^133 + (0x8ce2529e2734bb1d, 0x1899e4a65f58660c), // 5^134 + (0xb01ae745b101e9e4, 0x5ec05dcff72e7f8f), // 5^135 + (0xdc21a1171d42645d, 0x76707543f4fa1f73), // 5^136 + (0x899504ae72497eba, 0x6a06494a791c53a8), // 5^137 + (0xabfa45da0edbde69, 0x487db9d17636892), // 5^138 + (0xd6f8d7509292d603, 0x45a9d2845d3c42b6), // 5^139 + (0x865b86925b9bc5c2, 0xb8a2392ba45a9b2), // 5^140 + (0xa7f26836f282b732, 0x8e6cac7768d7141e), // 5^141 + (0xd1ef0244af2364ff, 0x3207d795430cd926), // 5^142 + (0x8335616aed761f1f, 0x7f44e6bd49e807b8), // 5^143 + (0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a6), // 5^144 + (0xcd036837130890a1, 0x36dba887c37a8c0f), // 5^145 + (0x802221226be55a64, 0xc2494954da2c9789), // 5^146 + (0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6c), // 5^147 + (0xc83553c5c8965d3d, 0x6f92829494e5acc7), // 5^148 + (0xfa42a8b73abbf48c, 0xcb772339ba1f17f9), // 5^149 + (0x9c69a97284b578d7, 0xff2a760414536efb), // 5^150 + (0xc38413cf25e2d70d, 0xfef5138519684aba), // 5^151 + (0xf46518c2ef5b8cd1, 0x7eb258665fc25d69), // 5^152 + (0x98bf2f79d5993802, 0xef2f773ffbd97a61), // 5^153 + (0xbeeefb584aff8603, 0xaafb550ffacfd8fa), // 5^154 + (0xeeaaba2e5dbf6784, 0x95ba2a53f983cf38), // 5^155 + (0x952ab45cfa97a0b2, 0xdd945a747bf26183), // 5^156 + (0xba756174393d88df, 0x94f971119aeef9e4), // 5^157 + (0xe912b9d1478ceb17, 0x7a37cd5601aab85d), // 5^158 + (0x91abb422ccb812ee, 0xac62e055c10ab33a), // 5^159 + (0xb616a12b7fe617aa, 0x577b986b314d6009), // 5^160 + (0xe39c49765fdf9d94, 0xed5a7e85fda0b80b), // 5^161 + (0x8e41ade9fbebc27d, 0x14588f13be847307), // 5^162 + (0xb1d219647ae6b31c, 0x596eb2d8ae258fc8), // 5^163 + (0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bb), // 5^164 + (0x8aec23d680043bee, 0x25de7bb9480d5854), // 5^165 + (0xada72ccc20054ae9, 0xaf561aa79a10ae6a), // 5^166 + (0xd910f7ff28069da4, 0x1b2ba1518094da04), // 5^167 + (0x87aa9aff79042286, 0x90fb44d2f05d0842), // 5^168 + (0xa99541bf57452b28, 0x353a1607ac744a53), // 5^169 + (0xd3fa922f2d1675f2, 0x42889b8997915ce8), // 5^170 + (0x847c9b5d7c2e09b7, 0x69956135febada11), // 5^171 + (0xa59bc234db398c25, 0x43fab9837e699095), // 5^172 + (0xcf02b2c21207ef2e, 0x94f967e45e03f4bb), // 5^173 + (0x8161afb94b44f57d, 0x1d1be0eebac278f5), // 5^174 + (0xa1ba1ba79e1632dc, 0x6462d92a69731732), // 5^175 + (0xca28a291859bbf93, 0x7d7b8f7503cfdcfe), // 5^176 + (0xfcb2cb35e702af78, 0x5cda735244c3d43e), // 5^177 + (0x9defbf01b061adab, 0x3a0888136afa64a7), // 5^178 + (0xc56baec21c7a1916, 0x88aaa1845b8fdd0), // 5^179 + (0xf6c69a72a3989f5b, 0x8aad549e57273d45), // 5^180 + (0x9a3c2087a63f6399, 0x36ac54e2f678864b), // 5^181 + (0xc0cb28a98fcf3c7f, 0x84576a1bb416a7dd), // 5^182 + (0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d5), // 5^183 + (0x969eb7c47859e743, 0x9f644ae5a4b1b325), // 5^184 + (0xbc4665b596706114, 0x873d5d9f0dde1fee), // 5^185 + (0xeb57ff22fc0c7959, 0xa90cb506d155a7ea), // 5^186 + (0x9316ff75dd87cbd8, 0x9a7f12442d588f2), // 5^187 + (0xb7dcbf5354e9bece, 0xc11ed6d538aeb2f), // 5^188 + (0xe5d3ef282a242e81, 0x8f1668c8a86da5fa), // 5^189 + (0x8fa475791a569d10, 0xf96e017d694487bc), // 5^190 + (0xb38d92d760ec4455, 0x37c981dcc395a9ac), // 5^191 + (0xe070f78d3927556a, 0x85bbe253f47b1417), // 5^192 + (0x8c469ab843b89562, 0x93956d7478ccec8e), // 5^193 + (0xaf58416654a6babb, 0x387ac8d1970027b2), // 5^194 + (0xdb2e51bfe9d0696a, 0x6997b05fcc0319e), // 5^195 + (0x88fcf317f22241e2, 0x441fece3bdf81f03), // 5^196 + (0xab3c2fddeeaad25a, 0xd527e81cad7626c3), // 5^197 + (0xd60b3bd56a5586f1, 0x8a71e223d8d3b074), // 5^198 + (0x85c7056562757456, 0xf6872d5667844e49), // 5^199 + (0xa738c6bebb12d16c, 0xb428f8ac016561db), // 5^200 + (0xd106f86e69d785c7, 0xe13336d701beba52), // 5^201 + (0x82a45b450226b39c, 0xecc0024661173473), // 5^202 + (0xa34d721642b06084, 0x27f002d7f95d0190), // 5^203 + (0xcc20ce9bd35c78a5, 0x31ec038df7b441f4), // 5^204 + (0xff290242c83396ce, 0x7e67047175a15271), // 5^205 + (0x9f79a169bd203e41, 0xf0062c6e984d386), // 5^206 + (0xc75809c42c684dd1, 0x52c07b78a3e60868), // 5^207 + (0xf92e0c3537826145, 0xa7709a56ccdf8a82), // 5^208 + (0x9bbcc7a142b17ccb, 0x88a66076400bb691), // 5^209 + (0xc2abf989935ddbfe, 0x6acff893d00ea435), // 5^210 + (0xf356f7ebf83552fe, 0x583f6b8c4124d43), // 5^211 + (0x98165af37b2153de, 0xc3727a337a8b704a), // 5^212 + (0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5c), // 5^213 + (0xeda2ee1c7064130c, 0x1162def06f79df73), // 5^214 + (0x9485d4d1c63e8be7, 0x8addcb5645ac2ba8), // 5^215 + (0xb9a74a0637ce2ee1, 0x6d953e2bd7173692), // 5^216 + (0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0437), // 5^217 + (0x910ab1d4db9914a0, 0x1d9c9892400a22a2), // 5^218 + (0xb54d5e4a127f59c8, 0x2503beb6d00cab4b), // 5^219 + (0xe2a0b5dc971f303a, 0x2e44ae64840fd61d), // 5^220 + (0x8da471a9de737e24, 0x5ceaecfed289e5d2), // 5^221 + (0xb10d8e1456105dad, 0x7425a83e872c5f47), // 5^222 + (0xdd50f1996b947518, 0xd12f124e28f77719), // 5^223 + (0x8a5296ffe33cc92f, 0x82bd6b70d99aaa6f), // 5^224 + (0xace73cbfdc0bfb7b, 0x636cc64d1001550b), // 5^225 + (0xd8210befd30efa5a, 0x3c47f7e05401aa4e), // 5^226 + (0x8714a775e3e95c78, 0x65acfaec34810a71), // 5^227 + (0xa8d9d1535ce3b396, 0x7f1839a741a14d0d), // 5^228 + (0xd31045a8341ca07c, 0x1ede48111209a050), // 5^229 + (0x83ea2b892091e44d, 0x934aed0aab460432), // 5^230 + (0xa4e4b66b68b65d60, 0xf81da84d5617853f), // 5^231 + (0xce1de40642e3f4b9, 0x36251260ab9d668e), // 5^232 + (0x80d2ae83e9ce78f3, 0xc1d72b7c6b426019), // 5^233 + (0xa1075a24e4421730, 0xb24cf65b8612f81f), // 5^234 + (0xc94930ae1d529cfc, 0xdee033f26797b627), // 5^235 + (0xfb9b7cd9a4a7443c, 0x169840ef017da3b1), // 5^236 + (0x9d412e0806e88aa5, 0x8e1f289560ee864e), // 5^237 + (0xc491798a08a2ad4e, 0xf1a6f2bab92a27e2), // 5^238 + (0xf5b5d7ec8acb58a2, 0xae10af696774b1db), // 5^239 + (0x9991a6f3d6bf1765, 0xacca6da1e0a8ef29), // 5^240 + (0xbff610b0cc6edd3f, 0x17fd090a58d32af3), // 5^241 + (0xeff394dcff8a948e, 0xddfc4b4cef07f5b0), // 5^242 + (0x95f83d0a1fb69cd9, 0x4abdaf101564f98e), // 5^243 + (0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f1), // 5^244 + (0xea53df5fd18d5513, 0x84c86189216dc5ed), // 5^245 + (0x92746b9be2f8552c, 0x32fd3cf5b4e49bb4), // 5^246 + (0xb7118682dbb66a77, 0x3fbc8c33221dc2a1), // 5^247 + (0xe4d5e82392a40515, 0xfabaf3feaa5334a), // 5^248 + (0x8f05b1163ba6832d, 0x29cb4d87f2a7400e), // 5^249 + (0xb2c71d5bca9023f8, 0x743e20e9ef511012), // 5^250 + (0xdf78e4b2bd342cf6, 0x914da9246b255416), // 5^251 + (0x8bab8eefb6409c1a, 0x1ad089b6c2f7548e), // 5^252 + (0xae9672aba3d0c320, 0xa184ac2473b529b1), // 5^253 + (0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741e), // 5^254 + (0x8865899617fb1871, 0x7e2fa67c7a658892), // 5^255 + (0xaa7eebfb9df9de8d, 0xddbb901b98feeab7), // 5^256 + (0xd51ea6fa85785631, 0x552a74227f3ea565), // 5^257 + (0x8533285c936b35de, 0xd53a88958f87275f), // 5^258 + (0xa67ff273b8460356, 0x8a892abaf368f137), // 5^259 + (0xd01fef10a657842c, 0x2d2b7569b0432d85), // 5^260 + (0x8213f56a67f6b29b, 0x9c3b29620e29fc73), // 5^261 + (0xa298f2c501f45f42, 0x8349f3ba91b47b8f), // 5^262 + (0xcb3f2f7642717713, 0x241c70a936219a73), // 5^263 + (0xfe0efb53d30dd4d7, 0xed238cd383aa0110), // 5^264 + (0x9ec95d1463e8a506, 0xf4363804324a40aa), // 5^265 + (0xc67bb4597ce2ce48, 0xb143c6053edcd0d5), // 5^266 + (0xf81aa16fdc1b81da, 0xdd94b7868e94050a), // 5^267 + (0x9b10a4e5e9913128, 0xca7cf2b4191c8326), // 5^268 + (0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f0), // 5^269 + (0xf24a01a73cf2dccf, 0xbc633b39673c8cec), // 5^270 + (0x976e41088617ca01, 0xd5be0503e085d813), // 5^271 + (0xbd49d14aa79dbc82, 0x4b2d8644d8a74e18), // 5^272 + (0xec9c459d51852ba2, 0xddf8e7d60ed1219e), // 5^273 + (0x93e1ab8252f33b45, 0xcabb90e5c942b503), // 5^274 + (0xb8da1662e7b00a17, 0x3d6a751f3b936243), // 5^275 + (0xe7109bfba19c0c9d, 0xcc512670a783ad4), // 5^276 + (0x906a617d450187e2, 0x27fb2b80668b24c5), // 5^277 + (0xb484f9dc9641e9da, 0xb1f9f660802dedf6), // 5^278 + (0xe1a63853bbd26451, 0x5e7873f8a0396973), // 5^279 + (0x8d07e33455637eb2, 0xdb0b487b6423e1e8), // 5^280 + (0xb049dc016abc5e5f, 0x91ce1a9a3d2cda62), // 5^281 + (0xdc5c5301c56b75f7, 0x7641a140cc7810fb), // 5^282 + (0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9d), // 5^283 + (0xac2820d9623bf429, 0x546345fa9fbdcd44), // 5^284 + (0xd732290fbacaf133, 0xa97c177947ad4095), // 5^285 + (0x867f59a9d4bed6c0, 0x49ed8eabcccc485d), // 5^286 + (0xa81f301449ee8c70, 0x5c68f256bfff5a74), // 5^287 + (0xd226fc195c6a2f8c, 0x73832eec6fff3111), // 5^288 + (0x83585d8fd9c25db7, 0xc831fd53c5ff7eab), // 5^289 + (0xa42e74f3d032f525, 0xba3e7ca8b77f5e55), // 5^290 + (0xcd3a1230c43fb26f, 0x28ce1bd2e55f35eb), // 5^291 + (0x80444b5e7aa7cf85, 0x7980d163cf5b81b3), // 5^292 + (0xa0555e361951c366, 0xd7e105bcc332621f), // 5^293 + (0xc86ab5c39fa63440, 0x8dd9472bf3fefaa7), // 5^294 + (0xfa856334878fc150, 0xb14f98f6f0feb951), // 5^295 + (0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d3), // 5^296 + (0xc3b8358109e84f07, 0xa862f80ec4700c8), // 5^297 + (0xf4a642e14c6262c8, 0xcd27bb612758c0fa), // 5^298 + (0x98e7e9cccfbd7dbd, 0x8038d51cb897789c), // 5^299 + (0xbf21e44003acdd2c, 0xe0470a63e6bd56c3), // 5^300 + (0xeeea5d5004981478, 0x1858ccfce06cac74), // 5^301 + (0x95527a5202df0ccb, 0xf37801e0c43ebc8), // 5^302 + (0xbaa718e68396cffd, 0xd30560258f54e6ba), // 5^303 + (0xe950df20247c83fd, 0x47c6b82ef32a2069), // 5^304 + (0x91d28b7416cdd27e, 0x4cdc331d57fa5441), // 5^305 + (0xb6472e511c81471d, 0xe0133fe4adf8e952), // 5^306 + (0xe3d8f9e563a198e5, 0x58180fddd97723a6), // 5^307 + (0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648), // 5^308 +]; diff --git a/CoqOfRust/core/num/diy_float.rs b/CoqOfRust/core/num/diy_float.rs new file mode 100644 index 000000000..ce7f6475d --- /dev/null +++ b/CoqOfRust/core/num/diy_float.rs @@ -0,0 +1,81 @@ +//! Extended precision "soft float", for internal use only. + +// This module is only for dec2flt and flt2dec, and only public because of coretests. +// It is not intended to ever be stabilized. +#![doc(hidden)] +#![unstable( + feature = "core_private_diy_float", + reason = "internal routines only exposed for testing", + issue = "none" +)] + +/// A custom 64-bit floating point type, representing `f * 2^e`. +#[derive(Copy, Clone, Debug)] +#[doc(hidden)] +pub struct Fp { + /// The integer mantissa. + pub f: u64, + /// The exponent in base 2. + pub e: i16, +} + +impl Fp { + /// Returns a correctly rounded product of itself and `other`. + pub fn mul(&self, other: &Fp) -> Fp { + const MASK: u64 = 0xffffffff; + let a = self.f >> 32; + let b = self.f & MASK; + let c = other.f >> 32; + let d = other.f & MASK; + let ac = a * c; + let bc = b * c; + let ad = a * d; + let bd = b * d; + let tmp = (bd >> 32) + (ad & MASK) + (bc & MASK) + (1 << 31) /* round */; + let f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32); + let e = self.e + other.e + 64; + Fp { f, e } + } + + /// Normalizes itself so that the resulting mantissa is at least `2^63`. + pub fn normalize(&self) -> Fp { + let mut f = self.f; + let mut e = self.e; + if f >> (64 - 32) == 0 { + f <<= 32; + e -= 32; + } + if f >> (64 - 16) == 0 { + f <<= 16; + e -= 16; + } + if f >> (64 - 8) == 0 { + f <<= 8; + e -= 8; + } + if f >> (64 - 4) == 0 { + f <<= 4; + e -= 4; + } + if f >> (64 - 2) == 0 { + f <<= 2; + e -= 2; + } + if f >> (64 - 1) == 0 { + f <<= 1; + e -= 1; + } + debug_assert!(f >= (1 << 63)); + Fp { f, e } + } + + /// Normalizes itself to have the shared exponent. + /// It can only decrease the exponent (and thus increase the mantissa). + pub fn normalize_to(&self, e: i16) -> Fp { + let edelta = self.e - e; + assert!(edelta >= 0); + let edelta = edelta as usize; + assert_eq!(self.f << edelta >> edelta, self.f); + Fp { f: self.f << edelta, e } + } +} diff --git a/CoqOfRust/core/num/error.rs b/CoqOfRust/core/num/error.rs new file mode 100644 index 000000000..6ef2fdd14 --- /dev/null +++ b/CoqOfRust/core/num/error.rs @@ -0,0 +1,143 @@ +//! Error types for conversion to integral types. + +use crate::convert::Infallible; +use crate::error::Error; +use crate::fmt; + +/// The error type returned when a checked integral type conversion fails. +#[stable(feature = "try_from", since = "1.34.0")] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct TryFromIntError(pub(crate) ()); + +#[stable(feature = "try_from", since = "1.34.0")] +impl fmt::Display for TryFromIntError { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + #[allow(deprecated)] + self.description().fmt(fmt) + } +} + +#[stable(feature = "try_from", since = "1.34.0")] +impl Error for TryFromIntError { + #[allow(deprecated)] + fn description(&self) -> &str { + "out of range integral type conversion attempted" + } +} + +#[stable(feature = "try_from", since = "1.34.0")] +impl From for TryFromIntError { + fn from(x: Infallible) -> TryFromIntError { + match x {} + } +} + +#[unstable(feature = "never_type", issue = "35121")] +impl From for TryFromIntError { + #[inline] + fn from(never: !) -> TryFromIntError { + // Match rather than coerce to make sure that code like + // `From for TryFromIntError` above will keep working + // when `Infallible` becomes an alias to `!`. + match never {} + } +} + +/// An error which can be returned when parsing an integer. +/// +/// This error is used as the error type for the `from_str_radix()` functions +/// on the primitive integer types, such as [`i8::from_str_radix`]. +/// +/// # Potential causes +/// +/// Among other causes, `ParseIntError` can be thrown because of leading or trailing whitespace +/// in the string e.g., when it is obtained from the standard input. +/// Using the [`str::trim()`] method ensures that no whitespace remains before parsing. +/// +/// # Example +/// +/// ``` +/// if let Err(e) = i32::from_str_radix("a12", 10) { +/// println!("Failed conversion to i32: {e}"); +/// } +/// ``` +#[derive(Debug, Clone, PartialEq, Eq)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct ParseIntError { + pub(super) kind: IntErrorKind, +} + +/// Enum to store the various types of errors that can cause parsing an integer to fail. +/// +/// # Example +/// +/// ``` +/// # fn main() { +/// if let Err(e) = i32::from_str_radix("a12", 10) { +/// println!("Failed conversion to i32: {:?}", e.kind()); +/// } +/// # } +/// ``` +#[stable(feature = "int_error_matching", since = "1.55.0")] +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum IntErrorKind { + /// Value being parsed is empty. + /// + /// This variant will be constructed when parsing an empty string. + #[stable(feature = "int_error_matching", since = "1.55.0")] + Empty, + /// Contains an invalid digit in its context. + /// + /// Among other causes, this variant will be constructed when parsing a string that + /// contains a non-ASCII char. + /// + /// This variant is also constructed when a `+` or `-` is misplaced within a string + /// either on its own or in the middle of a number. + #[stable(feature = "int_error_matching", since = "1.55.0")] + InvalidDigit, + /// Integer is too large to store in target integer type. + #[stable(feature = "int_error_matching", since = "1.55.0")] + PosOverflow, + /// Integer is too small to store in target integer type. + #[stable(feature = "int_error_matching", since = "1.55.0")] + NegOverflow, + /// Value was Zero + /// + /// This variant will be emitted when the parsing string has a value of zero, which + /// would be illegal for non-zero types. + #[stable(feature = "int_error_matching", since = "1.55.0")] + Zero, +} + +impl ParseIntError { + /// Outputs the detailed cause of parsing an integer failing. + #[must_use] + #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")] + #[stable(feature = "int_error_matching", since = "1.55.0")] + pub const fn kind(&self) -> &IntErrorKind { + &self.kind + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for ParseIntError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + #[allow(deprecated)] + self.description().fmt(f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for ParseIntError { + #[allow(deprecated)] + fn description(&self) -> &str { + match self.kind { + IntErrorKind::Empty => "cannot parse integer from empty string", + IntErrorKind::InvalidDigit => "invalid digit found in string", + IntErrorKind::PosOverflow => "number too large to fit in target type", + IntErrorKind::NegOverflow => "number too small to fit in target type", + IntErrorKind::Zero => "number would be zero for non-zero type", + } + } +} diff --git a/CoqOfRust/core/num/f128.rs b/CoqOfRust/core/num/f128.rs new file mode 100644 index 000000000..4ebeaf046 --- /dev/null +++ b/CoqOfRust/core/num/f128.rs @@ -0,0 +1,1364 @@ +//! Constants for the `f128` quadruple-precision floating point type. +//! +//! *[See also the `f128` primitive type][f128].* +//! +//! Mathematically significant numbers are provided in the `consts` sub-module. +//! +//! For the constants defined directly in this module +//! (as distinct from those defined in the `consts` sub-module), +//! new code should instead use the associated constants +//! defined directly on the `f128` type. + +#![unstable(feature = "f128", issue = "116909")] + +use crate::convert::FloatToInt; +#[cfg(not(test))] +use crate::intrinsics; +use crate::mem; +use crate::num::FpCategory; +use crate::panic::const_assert; + +/// Basic mathematical constants. +#[unstable(feature = "f128", issue = "116909")] +pub mod consts { + // FIXME: replace with mathematical constants from cmath. + + /// Archimedes' constant (π) + #[unstable(feature = "f128", issue = "116909")] + pub const PI: f128 = 3.14159265358979323846264338327950288419716939937510582097494_f128; + + /// The full circle constant (τ) + /// + /// Equal to 2π. + #[unstable(feature = "f128", issue = "116909")] + pub const TAU: f128 = 6.28318530717958647692528676655900576839433879875021164194989_f128; + + /// The golden ratio (φ) + #[unstable(feature = "f128", issue = "116909")] + // Also, #[unstable(feature = "more_float_constants", issue = "103883")] + pub const PHI: f128 = 1.61803398874989484820458683436563811772030917980576286213545_f128; + + /// The Euler-Mascheroni constant (γ) + #[unstable(feature = "f128", issue = "116909")] + // Also, #[unstable(feature = "more_float_constants", issue = "103883")] + pub const EGAMMA: f128 = 0.577215664901532860606512090082402431042159335939923598805767_f128; + + /// π/2 + #[unstable(feature = "f128", issue = "116909")] + pub const FRAC_PI_2: f128 = 1.57079632679489661923132169163975144209858469968755291048747_f128; + + /// π/3 + #[unstable(feature = "f128", issue = "116909")] + pub const FRAC_PI_3: f128 = 1.04719755119659774615421446109316762806572313312503527365831_f128; + + /// π/4 + #[unstable(feature = "f128", issue = "116909")] + pub const FRAC_PI_4: f128 = 0.785398163397448309615660845819875721049292349843776455243736_f128; + + /// π/6 + #[unstable(feature = "f128", issue = "116909")] + pub const FRAC_PI_6: f128 = 0.523598775598298873077107230546583814032861566562517636829157_f128; + + /// π/8 + #[unstable(feature = "f128", issue = "116909")] + pub const FRAC_PI_8: f128 = 0.392699081698724154807830422909937860524646174921888227621868_f128; + + /// 1/π + #[unstable(feature = "f128", issue = "116909")] + pub const FRAC_1_PI: f128 = 0.318309886183790671537767526745028724068919291480912897495335_f128; + + /// 1/sqrt(π) + #[unstable(feature = "f128", issue = "116909")] + // Also, #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_PI: f128 = + 0.564189583547756286948079451560772585844050629328998856844086_f128; + + /// 1/sqrt(2π) + #[doc(alias = "FRAC_1_SQRT_TAU")] + #[unstable(feature = "f128", issue = "116909")] + // Also, #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_2PI: f128 = + 0.398942280401432677939946059934381868475858631164934657665926_f128; + + /// 2/π + #[unstable(feature = "f128", issue = "116909")] + pub const FRAC_2_PI: f128 = 0.636619772367581343075535053490057448137838582961825794990669_f128; + + /// 2/sqrt(π) + #[unstable(feature = "f128", issue = "116909")] + pub const FRAC_2_SQRT_PI: f128 = + 1.12837916709551257389615890312154517168810125865799771368817_f128; + + /// sqrt(2) + #[unstable(feature = "f128", issue = "116909")] + pub const SQRT_2: f128 = 1.41421356237309504880168872420969807856967187537694807317668_f128; + + /// 1/sqrt(2) + #[unstable(feature = "f128", issue = "116909")] + pub const FRAC_1_SQRT_2: f128 = + 0.707106781186547524400844362104849039284835937688474036588340_f128; + + /// sqrt(3) + #[unstable(feature = "f128", issue = "116909")] + // Also, #[unstable(feature = "more_float_constants", issue = "103883")] + pub const SQRT_3: f128 = 1.73205080756887729352744634150587236694280525381038062805581_f128; + + /// 1/sqrt(3) + #[unstable(feature = "f128", issue = "116909")] + // Also, #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_3: f128 = + 0.577350269189625764509148780501957455647601751270126876018602_f128; + + /// Euler's number (e) + #[unstable(feature = "f128", issue = "116909")] + pub const E: f128 = 2.71828182845904523536028747135266249775724709369995957496697_f128; + + /// log2(10) + #[unstable(feature = "f128", issue = "116909")] + pub const LOG2_10: f128 = 3.32192809488736234787031942948939017586483139302458061205476_f128; + + /// log2(e) + #[unstable(feature = "f128", issue = "116909")] + pub const LOG2_E: f128 = 1.44269504088896340735992468100189213742664595415298593413545_f128; + + /// log10(2) + #[unstable(feature = "f128", issue = "116909")] + pub const LOG10_2: f128 = 0.301029995663981195213738894724493026768189881462108541310427_f128; + + /// log10(e) + #[unstable(feature = "f128", issue = "116909")] + pub const LOG10_E: f128 = 0.434294481903251827651128918916605082294397005803666566114454_f128; + + /// ln(2) + #[unstable(feature = "f128", issue = "116909")] + pub const LN_2: f128 = 0.693147180559945309417232121458176568075500134360255254120680_f128; + + /// ln(10) + #[unstable(feature = "f128", issue = "116909")] + pub const LN_10: f128 = 2.30258509299404568401799145468436420760110148862877297603333_f128; +} + +#[cfg(not(test))] +impl f128 { + // FIXME(f16_f128): almost all methods in this `impl` are missing examples and a const + // implementation. Add these once we can run code on all platforms and have f16/f128 in CTFE. + + /// The radix or base of the internal representation of `f128`. + #[unstable(feature = "f128", issue = "116909")] + pub const RADIX: u32 = 2; + + /// Number of significant digits in base 2. + #[unstable(feature = "f128", issue = "116909")] + pub const MANTISSA_DIGITS: u32 = 113; + + /// Approximate number of significant digits in base 10. + /// + /// This is the maximum x such that any decimal number with x + /// significant digits can be converted to `f128` and back without loss. + /// + /// Equal to floor(log10 2[`MANTISSA_DIGITS`] − 1). + /// + /// [`MANTISSA_DIGITS`]: f128::MANTISSA_DIGITS + #[unstable(feature = "f128", issue = "116909")] + pub const DIGITS: u32 = 33; + + /// [Machine epsilon] value for `f128`. + /// + /// This is the difference between `1.0` and the next larger representable number. + /// + /// Equal to 21 − [`MANTISSA_DIGITS`]. + /// + /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon + /// [`MANTISSA_DIGITS`]: f128::MANTISSA_DIGITS + #[unstable(feature = "f128", issue = "116909")] + pub const EPSILON: f128 = 1.92592994438723585305597794258492732e-34_f128; + + /// Smallest finite `f128` value. + /// + /// Equal to −[`MAX`]. + /// + /// [`MAX`]: f128::MAX + #[unstable(feature = "f128", issue = "116909")] + pub const MIN: f128 = -1.18973149535723176508575932662800702e+4932_f128; + /// Smallest positive normal `f128` value. + /// + /// Equal to 2[`MIN_EXP`] − 1. + /// + /// [`MIN_EXP`]: f128::MIN_EXP + #[unstable(feature = "f128", issue = "116909")] + pub const MIN_POSITIVE: f128 = 3.36210314311209350626267781732175260e-4932_f128; + /// Largest finite `f128` value. + /// + /// Equal to + /// (1 − 2−[`MANTISSA_DIGITS`]) 2[`MAX_EXP`]. + /// + /// [`MANTISSA_DIGITS`]: f128::MANTISSA_DIGITS + /// [`MAX_EXP`]: f128::MAX_EXP + #[unstable(feature = "f128", issue = "116909")] + pub const MAX: f128 = 1.18973149535723176508575932662800702e+4932_f128; + + /// One greater than the minimum possible normal power of 2 exponent. + /// + /// If x = `MIN_EXP`, then normal numbers + /// ≥ 0.5 × 2x. + #[unstable(feature = "f128", issue = "116909")] + pub const MIN_EXP: i32 = -16_381; + /// Maximum possible power of 2 exponent. + /// + /// If x = `MAX_EXP`, then normal numbers + /// < 1 × 2x. + #[unstable(feature = "f128", issue = "116909")] + pub const MAX_EXP: i32 = 16_384; + + /// Minimum x for which 10x is normal. + /// + /// Equal to ceil(log10 [`MIN_POSITIVE`]). + /// + /// [`MIN_POSITIVE`]: f128::MIN_POSITIVE + #[unstable(feature = "f128", issue = "116909")] + pub const MIN_10_EXP: i32 = -4_931; + /// Maximum x for which 10x is normal. + /// + /// Equal to floor(log10 [`MAX`]). + /// + /// [`MAX`]: f128::MAX + #[unstable(feature = "f128", issue = "116909")] + pub const MAX_10_EXP: i32 = 4_932; + + /// Not a Number (NaN). + /// + /// Note that IEEE 754 doesn't define just a single NaN value; + /// a plethora of bit patterns are considered to be NaN. + /// Furthermore, the standard makes a difference + /// between a "signaling" and a "quiet" NaN, + /// and allows inspecting its "payload" (the unspecified bits in the bit pattern). + /// This constant isn't guaranteed to equal to any specific NaN bitpattern, + /// and the stability of its representation over Rust versions + /// and target platforms isn't guaranteed. + #[allow(clippy::eq_op)] + #[rustc_diagnostic_item = "f128_nan"] + #[unstable(feature = "f128", issue = "116909")] + pub const NAN: f128 = 0.0_f128 / 0.0_f128; + + /// Infinity (∞). + #[unstable(feature = "f128", issue = "116909")] + pub const INFINITY: f128 = 1.0_f128 / 0.0_f128; + + /// Negative infinity (−∞). + #[unstable(feature = "f128", issue = "116909")] + pub const NEG_INFINITY: f128 = -1.0_f128 / 0.0_f128; + + /// Sign bit + pub(crate) const SIGN_MASK: u128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; + + /// Exponent mask + pub(crate) const EXP_MASK: u128 = 0x7fff_0000_0000_0000_0000_0000_0000_0000; + + /// Mantissa mask + pub(crate) const MAN_MASK: u128 = 0x0000_ffff_ffff_ffff_ffff_ffff_ffff_ffff; + + /// Minimum representable positive value (min subnormal) + const TINY_BITS: u128 = 0x1; + + /// Minimum representable negative value (min negative subnormal) + const NEG_TINY_BITS: u128 = Self::TINY_BITS | Self::SIGN_MASK; + + /// Returns `true` if this value is NaN. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `unordtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let nan = f128::NAN; + /// let f = 7.0_f128; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :) + pub const fn is_nan(self) -> bool { + self != self + } + + /// Returns `true` if this value is positive infinity or negative infinity, and + /// `false` otherwise. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let f = 7.0f128; + /// let inf = f128::INFINITY; + /// let neg_inf = f128::NEG_INFINITY; + /// let nan = f128::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + pub const fn is_infinite(self) -> bool { + (self == f128::INFINITY) | (self == f128::NEG_INFINITY) + } + + /// Returns `true` if this number is neither infinite nor NaN. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `lttf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let f = 7.0f128; + /// let inf: f128 = f128::INFINITY; + /// let neg_inf: f128 = f128::NEG_INFINITY; + /// let nan: f128 = f128::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] + pub const fn is_finite(self) -> bool { + // There's no need to handle NaN separately: if self is NaN, + // the comparison is not true, exactly as desired. + self.abs() < Self::INFINITY + } + + /// Returns `true` if the number is [subnormal]. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let min = f128::MIN_POSITIVE; // 3.362103143e-4932f128 + /// let max = f128::MAX; + /// let lower_than_min = 1.0e-4960_f128; + /// let zero = 0.0_f128; + /// + /// assert!(!min.is_subnormal()); + /// assert!(!max.is_subnormal()); + /// + /// assert!(!zero.is_subnormal()); + /// assert!(!f128::NAN.is_subnormal()); + /// assert!(!f128::INFINITY.is_subnormal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(lower_than_min.is_subnormal()); + /// # } + /// ``` + /// + /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + pub const fn is_subnormal(self) -> bool { + matches!(self.classify(), FpCategory::Subnormal) + } + + /// Returns `true` if the number is neither zero, infinite, [subnormal], or NaN. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let min = f128::MIN_POSITIVE; // 3.362103143e-4932f128 + /// let max = f128::MAX; + /// let lower_than_min = 1.0e-4960_f128; + /// let zero = 0.0_f128; + /// + /// assert!(min.is_normal()); + /// assert!(max.is_normal()); + /// + /// assert!(!zero.is_normal()); + /// assert!(!f128::NAN.is_normal()); + /// assert!(!f128::INFINITY.is_normal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(!lower_than_min.is_normal()); + /// # } + /// ``` + /// + /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + pub const fn is_normal(self) -> bool { + matches!(self.classify(), FpCategory::Normal) + } + + /// Returns the floating point category of the number. If only one property + /// is going to be tested, it is generally faster to use the specific + /// predicate instead. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// use std::num::FpCategory; + /// + /// let num = 12.4_f128; + /// let inf = f128::INFINITY; + /// + /// assert_eq!(num.classify(), FpCategory::Normal); + /// assert_eq!(inf.classify(), FpCategory::Infinite); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + pub const fn classify(self) -> FpCategory { + let bits = self.to_bits(); + match (bits & Self::MAN_MASK, bits & Self::EXP_MASK) { + (0, Self::EXP_MASK) => FpCategory::Infinite, + (_, Self::EXP_MASK) => FpCategory::Nan, + (0, 0) => FpCategory::Zero, + (_, 0) => FpCategory::Subnormal, + _ => FpCategory::Normal, + } + } + + /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with + /// positive sign bit and positive infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_positive` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). + /// + /// ``` + /// #![feature(f128)] + /// + /// let f = 7.0_f128; + /// let g = -7.0_f128; + /// + /// assert!(f.is_sign_positive()); + /// assert!(!g.is_sign_positive()); + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + pub const fn is_sign_positive(self) -> bool { + !self.is_sign_negative() + } + + /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with + /// negative sign bit and negative infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_negative` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). + /// + /// ``` + /// #![feature(f128)] + /// + /// let f = 7.0_f128; + /// let g = -7.0_f128; + /// + /// assert!(!f.is_sign_negative()); + /// assert!(g.is_sign_negative()); + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + pub const fn is_sign_negative(self) -> bool { + // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus + // applies to zeros and NaNs as well. + // SAFETY: This is just transmuting to get the sign bit, it's fine. + (self.to_bits() & (1 << 127)) != 0 + } + + /// Returns the least number greater than `self`. + /// + /// Let `TINY` be the smallest representable positive `f128`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`NEG_INFINITY`], this returns [`MIN`]; + /// - if `self` is `-TINY`, this returns -0.0; + /// - if `self` is -0.0 or +0.0, this returns `TINY`; + /// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`]; + /// - otherwise the unique least value greater than `self` is returned. + /// + /// The identity `x.next_up() == -(-x).next_down()` holds for all non-NaN `x`. When `x` + /// is finite `x == x.next_up().next_down()` also holds. + /// + /// ```rust + /// #![feature(f128)] + /// #![feature(float_next_up_down)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// // f128::EPSILON is the difference between 1.0 and the next number up. + /// assert_eq!(1.0f128.next_up(), 1.0 + f128::EPSILON); + /// // But not for most numbers. + /// assert!(0.1f128.next_up() < 0.1 + f128::EPSILON); + /// assert_eq!(4611686018427387904f128.next_up(), 4611686018427387904.000000000000001); + /// # } + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[inline] + #[unstable(feature = "f128", issue = "116909")] + // #[unstable(feature = "float_next_up_down", issue = "91399")] + pub const fn next_up(self) -> Self { + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. + let bits = self.to_bits(); + if self.is_nan() || bits == Self::INFINITY.to_bits() { + return self; + } + + let abs = bits & !Self::SIGN_MASK; + let next_bits = if abs == 0 { + Self::TINY_BITS + } else if bits == abs { + bits + 1 + } else { + bits - 1 + }; + Self::from_bits(next_bits) + } + + /// Returns the greatest number less than `self`. + /// + /// Let `TINY` be the smallest representable positive `f128`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`INFINITY`], this returns [`MAX`]; + /// - if `self` is `TINY`, this returns 0.0; + /// - if `self` is -0.0 or +0.0, this returns `-TINY`; + /// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`]; + /// - otherwise the unique greatest value less than `self` is returned. + /// + /// The identity `x.next_down() == -(-x).next_up()` holds for all non-NaN `x`. When `x` + /// is finite `x == x.next_down().next_up()` also holds. + /// + /// ```rust + /// #![feature(f128)] + /// #![feature(float_next_up_down)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let x = 1.0f128; + /// // Clamp value into range [0, 1). + /// let clamped = x.clamp(0.0, 1.0f128.next_down()); + /// assert!(clamped < 1.0); + /// assert_eq!(clamped.next_up(), 1.0); + /// # } + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[inline] + #[unstable(feature = "f128", issue = "116909")] + // #[unstable(feature = "float_next_up_down", issue = "91399")] + pub const fn next_down(self) -> Self { + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. + let bits = self.to_bits(); + if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() { + return self; + } + + let abs = bits & !Self::SIGN_MASK; + let next_bits = if abs == 0 { + Self::NEG_TINY_BITS + } else if bits == abs { + bits - 1 + } else { + bits + 1 + }; + Self::from_bits(next_bits) + } + + /// Takes the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let x = 2.0_f128; + /// let abs_difference = (x.recip() - (1.0 / x)).abs(); + /// + /// assert!(abs_difference <= f128::EPSILON); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn recip(self) -> Self { + 1.0 / self + } + + /// Converts radians to degrees. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let angle = std::f128::consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// assert!(abs_difference <= f128::EPSILON); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn to_degrees(self) -> Self { + // Use a literal for better precision. + const PIS_IN_180: f128 = 57.2957795130823208767981548141051703324054724665643215491602_f128; + self * PIS_IN_180 + } + + /// Converts degrees to radians. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let angle = 180.0f128; + /// + /// let abs_difference = (angle.to_radians() - std::f128::consts::PI).abs(); + /// + /// assert!(abs_difference <= 1e-30); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn to_radians(self) -> f128 { + // Use a literal for better precision. + const RADS_PER_DEG: f128 = + 0.0174532925199432957692369076848861271344287188854172545609719_f128; + self * RADS_PER_DEG + } + + /// Returns the maximum of the two numbers, ignoring NaN. + /// + /// If one of the arguments is NaN, then the other argument is returned. + /// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs; + /// this function handles all NaNs the same way and avoids maxNum's problems with associativity. + /// This also matches the behavior of libm’s fmax. + /// + /// ``` + /// #![feature(f128)] + /// # // Using aarch64 because `reliable_f128_math` is needed + /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] { + /// + /// let x = 1.0f128; + /// let y = 2.0f128; + /// + /// assert_eq!(x.max(y), y); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the comparison, without modifying either input"] + pub const fn max(self, other: f128) -> f128 { + intrinsics::maxnumf128(self, other) + } + + /// Returns the minimum of the two numbers, ignoring NaN. + /// + /// If one of the arguments is NaN, then the other argument is returned. + /// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs; + /// this function handles all NaNs the same way and avoids minNum's problems with associativity. + /// This also matches the behavior of libm’s fmin. + /// + /// ``` + /// #![feature(f128)] + /// # // Using aarch64 because `reliable_f128_math` is needed + /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] { + /// + /// let x = 1.0f128; + /// let y = 2.0f128; + /// + /// assert_eq!(x.min(y), x); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the comparison, without modifying either input"] + pub const fn min(self, other: f128) -> f128 { + intrinsics::minnumf128(self, other) + } + + /// Returns the maximum of the two numbers, propagating NaN. + /// + /// This returns NaN when *either* argument is NaN, as opposed to + /// [`f128::max`] which only returns NaN when *both* arguments are NaN. + /// + /// ``` + /// #![feature(f128)] + /// #![feature(float_minimum_maximum)] + /// # // Using aarch64 because `reliable_f128_math` is needed + /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] { + /// + /// let x = 1.0f128; + /// let y = 2.0f128; + /// + /// assert_eq!(x.maximum(y), y); + /// assert!(x.maximum(f128::NAN).is_nan()); + /// # } + /// ``` + /// + /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater + /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. + /// Note that this follows the semantics specified in IEEE 754-2019. + /// + /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. + #[inline] + #[unstable(feature = "f128", issue = "116909")] + // #[unstable(feature = "float_minimum_maximum", issue = "91079")] + #[must_use = "this returns the result of the comparison, without modifying either input"] + pub const fn maximum(self, other: f128) -> f128 { + if self > other { + self + } else if other > self { + other + } else if self == other { + if self.is_sign_positive() && other.is_sign_negative() { self } else { other } + } else { + self + other + } + } + + /// Returns the minimum of the two numbers, propagating NaN. + /// + /// This returns NaN when *either* argument is NaN, as opposed to + /// [`f128::min`] which only returns NaN when *both* arguments are NaN. + /// + /// ``` + /// #![feature(f128)] + /// #![feature(float_minimum_maximum)] + /// # // Using aarch64 because `reliable_f128_math` is needed + /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] { + /// + /// let x = 1.0f128; + /// let y = 2.0f128; + /// + /// assert_eq!(x.minimum(y), x); + /// assert!(x.minimum(f128::NAN).is_nan()); + /// # } + /// ``` + /// + /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser + /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. + /// Note that this follows the semantics specified in IEEE 754-2019. + /// + /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. + #[inline] + #[unstable(feature = "f128", issue = "116909")] + // #[unstable(feature = "float_minimum_maximum", issue = "91079")] + #[must_use = "this returns the result of the comparison, without modifying either input"] + pub const fn minimum(self, other: f128) -> f128 { + if self < other { + self + } else if other < self { + other + } else if self == other { + if self.is_sign_negative() && other.is_sign_positive() { self } else { other } + } else { + // At least one input is NaN. Use `+` to perform NaN propagation and quieting. + self + other + } + } + + /// Calculates the middle point of `self` and `rhs`. + /// + /// This returns NaN when *either* argument is NaN or if a combination of + /// +inf and -inf is provided as arguments. + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// # // Using aarch64 because `reliable_f128_math` is needed + /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] { + /// + /// assert_eq!(1f128.midpoint(4.0), 2.5); + /// assert_eq!((-5.5f128).midpoint(8.0), 1.25); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] + pub const fn midpoint(self, other: f128) -> f128 { + const LO: f128 = f128::MIN_POSITIVE * 2.; + const HI: f128 = f128::MAX / 2.; + + let (a, b) = (self, other); + let abs_a = a.abs(); + let abs_b = b.abs(); + + if abs_a <= HI && abs_b <= HI { + // Overflow is impossible + (a + b) / 2. + } else if abs_a < LO { + // Not safe to halve `a` (would underflow) + a + (b / 2.) + } else if abs_b < LO { + // Not safe to halve `b` (would underflow) + (a / 2.) + b + } else { + // Safe to halve `a` and `b` + (a / 2.) + (b / 2.) + } + } + + /// Rounds toward zero and converts to any primitive integer type, + /// assuming that the value is finite and fits in that type. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `float*itf` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let value = 4.6_f128; + /// let rounded = unsafe { value.to_int_unchecked::() }; + /// assert_eq!(rounded, 4); + /// + /// let value = -128.9_f128; + /// let rounded = unsafe { value.to_int_unchecked::() }; + /// assert_eq!(rounded, i8::MIN); + /// # } + /// ``` + /// + /// # Safety + /// + /// The value must: + /// + /// * Not be `NaN` + /// * Not be infinite + /// * Be representable in the return type `Int`, after truncating off its fractional part + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub unsafe fn to_int_unchecked(self) -> Int + where + Self: FloatToInt, + { + // SAFETY: the caller must uphold the safety contract for + // `FloatToInt::to_int_unchecked`. + unsafe { FloatToInt::::to_int_unchecked(self) } + } + + /// Raw transmutation to `u128`. + /// + /// This is currently identical to `transmute::(self)` on all platforms. + /// + /// See [`from_bits`](#method.from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// ``` + /// #![feature(f128)] + /// + /// # // FIXME(f16_f128): enable this once const casting works + /// # // assert_ne!((1f128).to_bits(), 1f128 as u128); // to_bits() is not casting! + /// assert_eq!((12.5f128).to_bits(), 0x40029000000000000000000000000000); + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn to_bits(self) -> u128 { + // SAFETY: `u128` is a plain old datatype so we can always transmute to it. + unsafe { mem::transmute(self) } + } + + /// Raw transmutation from `u128`. + /// + /// This is currently identical to `transmute::(v)` on all platforms. + /// It turns out this is incredibly portable, for two reasons: + /// + /// * Floats and Ints have the same endianness on all supported platforms. + /// * IEEE 754 very precisely specifies the bit layout of floats. + /// + /// However there is one caveat: prior to the 2008 version of IEEE 754, how + /// to interpret the NaN signaling bit wasn't actually specified. Most platforms + /// (notably x86 and ARM) picked the interpretation that was ultimately + /// standardized in 2008, but some didn't (notably MIPS). As a result, all + /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa. + /// + /// Rather than trying to preserve signaling-ness cross-platform, this + /// implementation favors preserving the exact bits. This means that + /// any payloads encoded in NaNs will be preserved even if the result of + /// this method is sent over the network from an x86 machine to a MIPS one. + /// + /// If the results of this method are only manipulated by the same + /// architecture that produced them, then there is no portability concern. + /// + /// If the input isn't NaN, then there is no portability concern. + /// + /// If you don't care about signalingness (very likely), then there is no + /// portability concern. + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let v = f128::from_bits(0x40029000000000000000000000000000); + /// assert_eq!(v, 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + pub const fn from_bits(v: u128) -> Self { + // It turns out the safety issues with sNaN were overblown! Hooray! + // SAFETY: `u128` is a plain old datatype so we can always transmute from it. + unsafe { mem::transmute(v) } + } + + /// Returns the memory representation of this floating point number as a byte array in + /// big-endian (network) byte order. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// + /// let bytes = 12.5f128.to_be_bytes(); + /// assert_eq!( + /// bytes, + /// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + /// ); + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn to_be_bytes(self) -> [u8; 16] { + self.to_bits().to_be_bytes() + } + + /// Returns the memory representation of this floating point number as a byte array in + /// little-endian byte order. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// + /// let bytes = 12.5f128.to_le_bytes(); + /// assert_eq!( + /// bytes, + /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x02, 0x40] + /// ); + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn to_le_bytes(self) -> [u8; 16] { + self.to_bits().to_le_bytes() + } + + /// Returns the memory representation of this floating point number as a byte array in + /// native byte order. + /// + /// As the target platform's native endianness is used, portable code + /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. + /// + /// [`to_be_bytes`]: f128::to_be_bytes + /// [`to_le_bytes`]: f128::to_le_bytes + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// + /// let bytes = 12.5f128.to_ne_bytes(); + /// assert_eq!( + /// bytes, + /// if cfg!(target_endian = "big") { + /// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + /// } else { + /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x02, 0x40] + /// } + /// ); + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn to_ne_bytes(self) -> [u8; 16] { + self.to_bits().to_ne_bytes() + } + + /// Creates a floating point value from its representation as a byte array in big endian. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let value = f128::from_be_bytes( + /// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + /// ); + /// assert_eq!(value, 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + pub const fn from_be_bytes(bytes: [u8; 16]) -> Self { + Self::from_bits(u128::from_be_bytes(bytes)) + } + + /// Creates a floating point value from its representation as a byte array in little endian. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let value = f128::from_le_bytes( + /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x02, 0x40] + /// ); + /// assert_eq!(value, 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + pub const fn from_le_bytes(bytes: [u8; 16]) -> Self { + Self::from_bits(u128::from_le_bytes(bytes)) + } + + /// Creates a floating point value from its representation as a byte array in native endian. + /// + /// As the target platform's native endianness is used, portable code + /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as + /// appropriate instead. + /// + /// [`from_be_bytes`]: f128::from_be_bytes + /// [`from_le_bytes`]: f128::from_le_bytes + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let value = f128::from_ne_bytes(if cfg!(target_endian = "big") { + /// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + /// } else { + /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x02, 0x40] + /// }); + /// assert_eq!(value, 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + pub const fn from_ne_bytes(bytes: [u8; 16]) -> Self { + Self::from_bits(u128::from_ne_bytes(bytes)) + } + + /// Returns the ordering between `self` and `other`. + /// + /// Unlike the standard partial comparison between floating point numbers, + /// this comparison always produces an ordering in accordance to + /// the `totalOrder` predicate as defined in the IEEE 754 (2008 revision) + /// floating point standard. The values are ordered in the following sequence: + /// + /// - negative quiet NaN + /// - negative signaling NaN + /// - negative infinity + /// - negative numbers + /// - negative subnormal numbers + /// - negative zero + /// - positive zero + /// - positive subnormal numbers + /// - positive numbers + /// - positive infinity + /// - positive signaling NaN + /// - positive quiet NaN. + /// + /// The ordering established by this function does not always agree with the + /// [`PartialOrd`] and [`PartialEq`] implementations of `f128`. For example, + /// they consider negative and positive zero equal, while `total_cmp` + /// doesn't. + /// + /// The interpretation of the signaling NaN bit follows the definition in + /// the IEEE 754 standard, which may not match the interpretation by some of + /// the older, non-conformant (e.g. MIPS) hardware implementations. + /// + /// # Example + /// + /// ``` + /// #![feature(f128)] + /// + /// struct GoodBoy { + /// name: &'static str, + /// weight: f128, + /// } + /// + /// let mut bois = vec![ + /// GoodBoy { name: "Pucci", weight: 0.1 }, + /// GoodBoy { name: "Woofer", weight: 99.0 }, + /// GoodBoy { name: "Yapper", weight: 10.0 }, + /// GoodBoy { name: "Chonk", weight: f128::INFINITY }, + /// GoodBoy { name: "Abs. Unit", weight: f128::NAN }, + /// GoodBoy { name: "Floaty", weight: -5.0 }, + /// ]; + /// + /// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight)); + /// + /// // `f128::NAN` could be positive or negative, which will affect the sort order. + /// if f128::NAN.is_sign_negative() { + /// bois.into_iter().map(|b| b.weight) + /// .zip([f128::NAN, -5.0, 0.1, 10.0, 99.0, f128::INFINITY].iter()) + /// .for_each(|(a, b)| assert_eq!(a.to_bits(), b.to_bits())) + /// } else { + /// bois.into_iter().map(|b| b.weight) + /// .zip([-5.0, 0.1, 10.0, 99.0, f128::INFINITY, f128::NAN].iter()) + /// .for_each(|(a, b)| assert_eq!(a.to_bits(), b.to_bits())) + /// } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { + let mut left = self.to_bits() as i128; + let mut right = other.to_bits() as i128; + + // In case of negatives, flip all the bits except the sign + // to achieve a similar layout as two's complement integers + // + // Why does this work? IEEE 754 floats consist of three fields: + // Sign bit, exponent and mantissa. The set of exponent and mantissa + // fields as a whole have the property that their bitwise order is + // equal to the numeric magnitude where the magnitude is defined. + // The magnitude is not normally defined on NaN values, but + // IEEE 754 totalOrder defines the NaN values also to follow the + // bitwise order. This leads to order explained in the doc comment. + // However, the representation of magnitude is the same for negative + // and positive numbers – only the sign bit is different. + // To easily compare the floats as signed integers, we need to + // flip the exponent and mantissa bits in case of negative numbers. + // We effectively convert the numbers to "two's complement" form. + // + // To do the flipping, we construct a mask and XOR against it. + // We branchlessly calculate an "all-ones except for the sign bit" + // mask from negative-signed values: right shifting sign-extends + // the integer, so we "fill" the mask with sign bits, and then + // convert to unsigned to push one more zero bit. + // On positive values, the mask is all zeros, so it's a no-op. + left ^= (((left >> 127) as u128) >> 1) as i128; + right ^= (((right >> 127) as u128) >> 1) as i128; + + left.cmp(&right) + } + + /// Restrict a value to a certain interval unless it is NaN. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// Note that this function returns NaN if the initial value was NaN as + /// well. + /// + /// # Panics + /// + /// Panics if `min > max`, `min` is NaN, or `max` is NaN. + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `{eq,gt,unord}tf` are available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// assert!((-3.0f128).clamp(-2.0, 1.0) == -2.0); + /// assert!((0.0f128).clamp(-2.0, 1.0) == 0.0); + /// assert!((2.0f128).clamp(-2.0, 1.0) == 1.0); + /// assert!((f128::NAN).clamp(-2.0, 1.0).is_nan()); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub const fn clamp(mut self, min: f128, max: f128) -> f128 { + const_assert!( + min <= max, + "min > max, or either was NaN", + "min > max, or either was NaN. min = {min:?}, max = {max:?}", + min: f128, + max: f128, + ); + + if self < min { + self = min; + } + if self > max { + self = max; + } + self + } + + /// Computes the absolute value of `self`. + /// + /// This function always returns the precise result. + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let x = 3.5_f128; + /// let y = -3.5_f128; + /// + /// assert_eq!(x.abs(), x); + /// assert_eq!(y.abs(), -y); + /// + /// assert!(f128::NAN.abs().is_nan()); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub const fn abs(self) -> Self { + // FIXME(f16_f128): replace with `intrinsics::fabsf128` when available + // We don't do this now because LLVM has lowering bugs for f128 math. + Self::from_bits(self.to_bits() & !(1 << 127)) + } + + /// Returns a number that represents the sign of `self`. + /// + /// - `1.0` if the number is positive, `+0.0` or `INFINITY` + /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` + /// - NaN if the number is NaN + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let f = 3.5_f128; + /// + /// assert_eq!(f.signum(), 1.0); + /// assert_eq!(f128::NEG_INFINITY.signum(), -1.0); + /// + /// assert!(f128::NAN.signum().is_nan()); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub const fn signum(self) -> f128 { + if self.is_nan() { Self::NAN } else { 1.0_f128.copysign(self) } + } + + /// Returns a number composed of the magnitude of `self` and the sign of + /// `sign`. + /// + /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. + /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let f = 3.5_f128; + /// + /// assert_eq!(f.copysign(0.42), 3.5_f128); + /// assert_eq!(f.copysign(-0.42), -3.5_f128); + /// assert_eq!((-f).copysign(0.42), 3.5_f128); + /// assert_eq!((-f).copysign(-0.42), -3.5_f128); + /// + /// assert!(f128::NAN.copysign(1.0).is_nan()); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub const fn copysign(self, sign: f128) -> f128 { + // SAFETY: this is actually a safe intrinsic + unsafe { intrinsics::copysignf128(self, sign) } + } +} diff --git a/CoqOfRust/core/num/f16.rs b/CoqOfRust/core/num/f16.rs new file mode 100644 index 000000000..c82f0d7cd --- /dev/null +++ b/CoqOfRust/core/num/f16.rs @@ -0,0 +1,1340 @@ +//! Constants for the `f16` half-precision floating point type. +//! +//! *[See also the `f16` primitive type][f16].* +//! +//! Mathematically significant numbers are provided in the `consts` sub-module. +//! +//! For the constants defined directly in this module +//! (as distinct from those defined in the `consts` sub-module), +//! new code should instead use the associated constants +//! defined directly on the `f16` type. + +#![unstable(feature = "f16", issue = "116909")] + +use crate::convert::FloatToInt; +#[cfg(not(test))] +use crate::intrinsics; +use crate::mem; +use crate::num::FpCategory; +use crate::panic::const_assert; + +/// Basic mathematical constants. +#[unstable(feature = "f16", issue = "116909")] +pub mod consts { + // FIXME: replace with mathematical constants from cmath. + + /// Archimedes' constant (π) + #[unstable(feature = "f16", issue = "116909")] + pub const PI: f16 = 3.14159265358979323846264338327950288_f16; + + /// The full circle constant (τ) + /// + /// Equal to 2π. + #[unstable(feature = "f16", issue = "116909")] + pub const TAU: f16 = 6.28318530717958647692528676655900577_f16; + + /// The golden ratio (φ) + #[unstable(feature = "f16", issue = "116909")] + // Also, #[unstable(feature = "more_float_constants", issue = "103883")] + pub const PHI: f16 = 1.618033988749894848204586834365638118_f16; + + /// The Euler-Mascheroni constant (γ) + #[unstable(feature = "f16", issue = "116909")] + // Also, #[unstable(feature = "more_float_constants", issue = "103883")] + pub const EGAMMA: f16 = 0.577215664901532860606512090082402431_f16; + + /// π/2 + #[unstable(feature = "f16", issue = "116909")] + pub const FRAC_PI_2: f16 = 1.57079632679489661923132169163975144_f16; + + /// π/3 + #[unstable(feature = "f16", issue = "116909")] + pub const FRAC_PI_3: f16 = 1.04719755119659774615421446109316763_f16; + + /// π/4 + #[unstable(feature = "f16", issue = "116909")] + pub const FRAC_PI_4: f16 = 0.785398163397448309615660845819875721_f16; + + /// π/6 + #[unstable(feature = "f16", issue = "116909")] + pub const FRAC_PI_6: f16 = 0.52359877559829887307710723054658381_f16; + + /// π/8 + #[unstable(feature = "f16", issue = "116909")] + pub const FRAC_PI_8: f16 = 0.39269908169872415480783042290993786_f16; + + /// 1/π + #[unstable(feature = "f16", issue = "116909")] + pub const FRAC_1_PI: f16 = 0.318309886183790671537767526745028724_f16; + + /// 1/sqrt(π) + #[unstable(feature = "f16", issue = "116909")] + // Also, #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_PI: f16 = 0.564189583547756286948079451560772586_f16; + + /// 1/sqrt(2π) + #[doc(alias = "FRAC_1_SQRT_TAU")] + #[unstable(feature = "f16", issue = "116909")] + // Also, #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_2PI: f16 = 0.398942280401432677939946059934381868_f16; + + /// 2/π + #[unstable(feature = "f16", issue = "116909")] + pub const FRAC_2_PI: f16 = 0.636619772367581343075535053490057448_f16; + + /// 2/sqrt(π) + #[unstable(feature = "f16", issue = "116909")] + pub const FRAC_2_SQRT_PI: f16 = 1.12837916709551257389615890312154517_f16; + + /// sqrt(2) + #[unstable(feature = "f16", issue = "116909")] + pub const SQRT_2: f16 = 1.41421356237309504880168872420969808_f16; + + /// 1/sqrt(2) + #[unstable(feature = "f16", issue = "116909")] + pub const FRAC_1_SQRT_2: f16 = 0.707106781186547524400844362104849039_f16; + + /// sqrt(3) + #[unstable(feature = "f16", issue = "116909")] + // Also, #[unstable(feature = "more_float_constants", issue = "103883")] + pub const SQRT_3: f16 = 1.732050807568877293527446341505872367_f16; + + /// 1/sqrt(3) + #[unstable(feature = "f16", issue = "116909")] + // Also, #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_3: f16 = 0.577350269189625764509148780501957456_f16; + + /// Euler's number (e) + #[unstable(feature = "f16", issue = "116909")] + pub const E: f16 = 2.71828182845904523536028747135266250_f16; + + /// log2(10) + #[unstable(feature = "f16", issue = "116909")] + pub const LOG2_10: f16 = 3.32192809488736234787031942948939018_f16; + + /// log2(e) + #[unstable(feature = "f16", issue = "116909")] + pub const LOG2_E: f16 = 1.44269504088896340735992468100189214_f16; + + /// log10(2) + #[unstable(feature = "f16", issue = "116909")] + pub const LOG10_2: f16 = 0.301029995663981195213738894724493027_f16; + + /// log10(e) + #[unstable(feature = "f16", issue = "116909")] + pub const LOG10_E: f16 = 0.434294481903251827651128918916605082_f16; + + /// ln(2) + #[unstable(feature = "f16", issue = "116909")] + pub const LN_2: f16 = 0.693147180559945309417232121458176568_f16; + + /// ln(10) + #[unstable(feature = "f16", issue = "116909")] + pub const LN_10: f16 = 2.30258509299404568401799145468436421_f16; +} + +#[cfg(not(test))] +impl f16 { + // FIXME(f16_f128): almost all methods in this `impl` are missing examples and a const + // implementation. Add these once we can run code on all platforms and have f16/f128 in CTFE. + + /// The radix or base of the internal representation of `f16`. + #[unstable(feature = "f16", issue = "116909")] + pub const RADIX: u32 = 2; + + /// Number of significant digits in base 2. + #[unstable(feature = "f16", issue = "116909")] + pub const MANTISSA_DIGITS: u32 = 11; + + /// Approximate number of significant digits in base 10. + /// + /// This is the maximum x such that any decimal number with x + /// significant digits can be converted to `f16` and back without loss. + /// + /// Equal to floor(log10 2[`MANTISSA_DIGITS`] − 1). + /// + /// [`MANTISSA_DIGITS`]: f16::MANTISSA_DIGITS + #[unstable(feature = "f16", issue = "116909")] + pub const DIGITS: u32 = 3; + + /// [Machine epsilon] value for `f16`. + /// + /// This is the difference between `1.0` and the next larger representable number. + /// + /// Equal to 21 − [`MANTISSA_DIGITS`]. + /// + /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon + /// [`MANTISSA_DIGITS`]: f16::MANTISSA_DIGITS + #[unstable(feature = "f16", issue = "116909")] + pub const EPSILON: f16 = 9.7656e-4_f16; + + /// Smallest finite `f16` value. + /// + /// Equal to −[`MAX`]. + /// + /// [`MAX`]: f16::MAX + #[unstable(feature = "f16", issue = "116909")] + pub const MIN: f16 = -6.5504e+4_f16; + /// Smallest positive normal `f16` value. + /// + /// Equal to 2[`MIN_EXP`] − 1. + /// + /// [`MIN_EXP`]: f16::MIN_EXP + #[unstable(feature = "f16", issue = "116909")] + pub const MIN_POSITIVE: f16 = 6.1035e-5_f16; + /// Largest finite `f16` value. + /// + /// Equal to + /// (1 − 2−[`MANTISSA_DIGITS`]) 2[`MAX_EXP`]. + /// + /// [`MANTISSA_DIGITS`]: f16::MANTISSA_DIGITS + /// [`MAX_EXP`]: f16::MAX_EXP + #[unstable(feature = "f16", issue = "116909")] + pub const MAX: f16 = 6.5504e+4_f16; + + /// One greater than the minimum possible normal power of 2 exponent. + /// + /// If x = `MIN_EXP`, then normal numbers + /// ≥ 0.5 × 2x. + #[unstable(feature = "f16", issue = "116909")] + pub const MIN_EXP: i32 = -13; + /// Maximum possible power of 2 exponent. + /// + /// If x = `MAX_EXP`, then normal numbers + /// < 1 × 2x. + #[unstable(feature = "f16", issue = "116909")] + pub const MAX_EXP: i32 = 16; + + /// Minimum x for which 10x is normal. + /// + /// Equal to ceil(log10 [`MIN_POSITIVE`]). + /// + /// [`MIN_POSITIVE`]: f16::MIN_POSITIVE + #[unstable(feature = "f16", issue = "116909")] + pub const MIN_10_EXP: i32 = -4; + /// Maximum x for which 10x is normal. + /// + /// Equal to floor(log10 [`MAX`]). + /// + /// [`MAX`]: f16::MAX + #[unstable(feature = "f16", issue = "116909")] + pub const MAX_10_EXP: i32 = 4; + + /// Not a Number (NaN). + /// + /// Note that IEEE 754 doesn't define just a single NaN value; + /// a plethora of bit patterns are considered to be NaN. + /// Furthermore, the standard makes a difference + /// between a "signaling" and a "quiet" NaN, + /// and allows inspecting its "payload" (the unspecified bits in the bit pattern). + /// This constant isn't guaranteed to equal to any specific NaN bitpattern, + /// and the stability of its representation over Rust versions + /// and target platforms isn't guaranteed. + #[allow(clippy::eq_op)] + #[rustc_diagnostic_item = "f16_nan"] + #[unstable(feature = "f16", issue = "116909")] + pub const NAN: f16 = 0.0_f16 / 0.0_f16; + + /// Infinity (∞). + #[unstable(feature = "f16", issue = "116909")] + pub const INFINITY: f16 = 1.0_f16 / 0.0_f16; + + /// Negative infinity (−∞). + #[unstable(feature = "f16", issue = "116909")] + pub const NEG_INFINITY: f16 = -1.0_f16 / 0.0_f16; + + /// Sign bit + pub(crate) const SIGN_MASK: u16 = 0x8000; + + /// Exponent mask + pub(crate) const EXP_MASK: u16 = 0x7c00; + + /// Mantissa mask + pub(crate) const MAN_MASK: u16 = 0x03ff; + + /// Minimum representable positive value (min subnormal) + const TINY_BITS: u16 = 0x1; + + /// Minimum representable negative value (min negative subnormal) + const NEG_TINY_BITS: u16 = Self::TINY_BITS | Self::SIGN_MASK; + + /// Returns `true` if this value is NaN. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let nan = f16::NAN; + /// let f = 7.0_f16; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :) + pub const fn is_nan(self) -> bool { + self != self + } + + /// Returns `true` if this value is positive infinity or negative infinity, and + /// `false` otherwise. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let f = 7.0f16; + /// let inf = f16::INFINITY; + /// let neg_inf = f16::NEG_INFINITY; + /// let nan = f16::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + pub const fn is_infinite(self) -> bool { + (self == f16::INFINITY) | (self == f16::NEG_INFINITY) + } + + /// Returns `true` if this number is neither infinite nor NaN. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let f = 7.0f16; + /// let inf: f16 = f16::INFINITY; + /// let neg_inf: f16 = f16::NEG_INFINITY; + /// let nan: f16 = f16::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] + pub const fn is_finite(self) -> bool { + // There's no need to handle NaN separately: if self is NaN, + // the comparison is not true, exactly as desired. + self.abs() < Self::INFINITY + } + + /// Returns `true` if the number is [subnormal]. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let min = f16::MIN_POSITIVE; // 6.1035e-5 + /// let max = f16::MAX; + /// let lower_than_min = 1.0e-7_f16; + /// let zero = 0.0_f16; + /// + /// assert!(!min.is_subnormal()); + /// assert!(!max.is_subnormal()); + /// + /// assert!(!zero.is_subnormal()); + /// assert!(!f16::NAN.is_subnormal()); + /// assert!(!f16::INFINITY.is_subnormal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(lower_than_min.is_subnormal()); + /// # } + /// ``` + /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + pub const fn is_subnormal(self) -> bool { + matches!(self.classify(), FpCategory::Subnormal) + } + + /// Returns `true` if the number is neither zero, infinite, [subnormal], or NaN. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let min = f16::MIN_POSITIVE; // 6.1035e-5 + /// let max = f16::MAX; + /// let lower_than_min = 1.0e-7_f16; + /// let zero = 0.0_f16; + /// + /// assert!(min.is_normal()); + /// assert!(max.is_normal()); + /// + /// assert!(!zero.is_normal()); + /// assert!(!f16::NAN.is_normal()); + /// assert!(!f16::INFINITY.is_normal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(!lower_than_min.is_normal()); + /// # } + /// ``` + /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + pub const fn is_normal(self) -> bool { + matches!(self.classify(), FpCategory::Normal) + } + + /// Returns the floating point category of the number. If only one property + /// is going to be tested, it is generally faster to use the specific + /// predicate instead. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// use std::num::FpCategory; + /// + /// let num = 12.4_f16; + /// let inf = f16::INFINITY; + /// + /// assert_eq!(num.classify(), FpCategory::Normal); + /// assert_eq!(inf.classify(), FpCategory::Infinite); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + pub const fn classify(self) -> FpCategory { + let b = self.to_bits(); + match (b & Self::MAN_MASK, b & Self::EXP_MASK) { + (0, Self::EXP_MASK) => FpCategory::Infinite, + (_, Self::EXP_MASK) => FpCategory::Nan, + (0, 0) => FpCategory::Zero, + (_, 0) => FpCategory::Subnormal, + _ => FpCategory::Normal, + } + } + + /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with + /// positive sign bit and positive infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_positive` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). + /// + /// ``` + /// #![feature(f16)] + /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let f = 7.0_f16; + /// let g = -7.0_f16; + /// + /// assert!(f.is_sign_positive()); + /// assert!(!g.is_sign_positive()); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + pub const fn is_sign_positive(self) -> bool { + !self.is_sign_negative() + } + + /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with + /// negative sign bit and negative infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_negative` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). + /// + /// ``` + /// #![feature(f16)] + /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let f = 7.0_f16; + /// let g = -7.0_f16; + /// + /// assert!(!f.is_sign_negative()); + /// assert!(g.is_sign_negative()); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + pub const fn is_sign_negative(self) -> bool { + // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus + // applies to zeros and NaNs as well. + // SAFETY: This is just transmuting to get the sign bit, it's fine. + (self.to_bits() & (1 << 15)) != 0 + } + + /// Returns the least number greater than `self`. + /// + /// Let `TINY` be the smallest representable positive `f16`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`NEG_INFINITY`], this returns [`MIN`]; + /// - if `self` is `-TINY`, this returns -0.0; + /// - if `self` is -0.0 or +0.0, this returns `TINY`; + /// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`]; + /// - otherwise the unique least value greater than `self` is returned. + /// + /// The identity `x.next_up() == -(-x).next_down()` holds for all non-NaN `x`. When `x` + /// is finite `x == x.next_up().next_down()` also holds. + /// + /// ```rust + /// #![feature(f16)] + /// #![feature(float_next_up_down)] + /// # // FIXME(f16_f128): ABI issues on MSVC + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// // f16::EPSILON is the difference between 1.0 and the next number up. + /// assert_eq!(1.0f16.next_up(), 1.0 + f16::EPSILON); + /// // But not for most numbers. + /// assert!(0.1f16.next_up() < 0.1 + f16::EPSILON); + /// assert_eq!(4356f16.next_up(), 4360.0); + /// # } + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[inline] + #[unstable(feature = "f16", issue = "116909")] + // #[unstable(feature = "float_next_up_down", issue = "91399")] + pub const fn next_up(self) -> Self { + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. + let bits = self.to_bits(); + if self.is_nan() || bits == Self::INFINITY.to_bits() { + return self; + } + + let abs = bits & !Self::SIGN_MASK; + let next_bits = if abs == 0 { + Self::TINY_BITS + } else if bits == abs { + bits + 1 + } else { + bits - 1 + }; + Self::from_bits(next_bits) + } + + /// Returns the greatest number less than `self`. + /// + /// Let `TINY` be the smallest representable positive `f16`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`INFINITY`], this returns [`MAX`]; + /// - if `self` is `TINY`, this returns 0.0; + /// - if `self` is -0.0 or +0.0, this returns `-TINY`; + /// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`]; + /// - otherwise the unique greatest value less than `self` is returned. + /// + /// The identity `x.next_down() == -(-x).next_up()` holds for all non-NaN `x`. When `x` + /// is finite `x == x.next_down().next_up()` also holds. + /// + /// ```rust + /// #![feature(f16)] + /// #![feature(float_next_up_down)] + /// # // FIXME(f16_f128): ABI issues on MSVC + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let x = 1.0f16; + /// // Clamp value into range [0, 1). + /// let clamped = x.clamp(0.0, 1.0f16.next_down()); + /// assert!(clamped < 1.0); + /// assert_eq!(clamped.next_up(), 1.0); + /// # } + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[inline] + #[unstable(feature = "f16", issue = "116909")] + // #[unstable(feature = "float_next_up_down", issue = "91399")] + pub const fn next_down(self) -> Self { + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. + let bits = self.to_bits(); + if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() { + return self; + } + + let abs = bits & !Self::SIGN_MASK; + let next_bits = if abs == 0 { + Self::NEG_TINY_BITS + } else if bits == abs { + bits - 1 + } else { + bits + 1 + }; + Self::from_bits(next_bits) + } + + /// Takes the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// #![feature(f16)] + /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let x = 2.0_f16; + /// let abs_difference = (x.recip() - (1.0 / x)).abs(); + /// + /// assert!(abs_difference <= f16::EPSILON); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn recip(self) -> Self { + 1.0 / self + } + + /// Converts radians to degrees. + /// + /// ``` + /// #![feature(f16)] + /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let angle = std::f16::consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// assert!(abs_difference <= 0.5); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn to_degrees(self) -> Self { + // Use a literal for better precision. + const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16; + self * PIS_IN_180 + } + + /// Converts degrees to radians. + /// + /// ``` + /// #![feature(f16)] + /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let angle = 180.0f16; + /// + /// let abs_difference = (angle.to_radians() - std::f16::consts::PI).abs(); + /// + /// assert!(abs_difference <= 0.01); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn to_radians(self) -> f16 { + // Use a literal for better precision. + const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16; + self * RADS_PER_DEG + } + + /// Returns the maximum of the two numbers, ignoring NaN. + /// + /// If one of the arguments is NaN, then the other argument is returned. + /// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs; + /// this function handles all NaNs the same way and avoids maxNum's problems with associativity. + /// This also matches the behavior of libm’s fmax. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// + /// let x = 1.0f16; + /// let y = 2.0f16; + /// + /// assert_eq!(x.max(y), y); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the comparison, without modifying either input"] + pub const fn max(self, other: f16) -> f16 { + intrinsics::maxnumf16(self, other) + } + + /// Returns the minimum of the two numbers, ignoring NaN. + /// + /// If one of the arguments is NaN, then the other argument is returned. + /// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs; + /// this function handles all NaNs the same way and avoids minNum's problems with associativity. + /// This also matches the behavior of libm’s fmin. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// + /// let x = 1.0f16; + /// let y = 2.0f16; + /// + /// assert_eq!(x.min(y), x); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the comparison, without modifying either input"] + pub const fn min(self, other: f16) -> f16 { + intrinsics::minnumf16(self, other) + } + + /// Returns the maximum of the two numbers, propagating NaN. + /// + /// This returns NaN when *either* argument is NaN, as opposed to + /// [`f16::max`] which only returns NaN when *both* arguments are NaN. + /// + /// ``` + /// #![feature(f16)] + /// #![feature(float_minimum_maximum)] + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// + /// let x = 1.0f16; + /// let y = 2.0f16; + /// + /// assert_eq!(x.maximum(y), y); + /// assert!(x.maximum(f16::NAN).is_nan()); + /// # } + /// ``` + /// + /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater + /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. + /// Note that this follows the semantics specified in IEEE 754-2019. + /// + /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. + #[inline] + #[unstable(feature = "f16", issue = "116909")] + // #[unstable(feature = "float_minimum_maximum", issue = "91079")] + #[must_use = "this returns the result of the comparison, without modifying either input"] + pub const fn maximum(self, other: f16) -> f16 { + if self > other { + self + } else if other > self { + other + } else if self == other { + if self.is_sign_positive() && other.is_sign_negative() { self } else { other } + } else { + self + other + } + } + + /// Returns the minimum of the two numbers, propagating NaN. + /// + /// This returns NaN when *either* argument is NaN, as opposed to + /// [`f16::min`] which only returns NaN when *both* arguments are NaN. + /// + /// ``` + /// #![feature(f16)] + /// #![feature(float_minimum_maximum)] + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// + /// let x = 1.0f16; + /// let y = 2.0f16; + /// + /// assert_eq!(x.minimum(y), x); + /// assert!(x.minimum(f16::NAN).is_nan()); + /// # } + /// ``` + /// + /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser + /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. + /// Note that this follows the semantics specified in IEEE 754-2019. + /// + /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. + #[inline] + #[unstable(feature = "f16", issue = "116909")] + // #[unstable(feature = "float_minimum_maximum", issue = "91079")] + #[must_use = "this returns the result of the comparison, without modifying either input"] + pub const fn minimum(self, other: f16) -> f16 { + if self < other { + self + } else if other < self { + other + } else if self == other { + if self.is_sign_negative() && other.is_sign_positive() { self } else { other } + } else { + // At least one input is NaN. Use `+` to perform NaN propagation and quieting. + self + other + } + } + + /// Calculates the middle point of `self` and `rhs`. + /// + /// This returns NaN when *either* argument is NaN or if a combination of + /// +inf and -inf is provided as arguments. + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// + /// assert_eq!(1f16.midpoint(4.0), 2.5); + /// assert_eq!((-5.5f16).midpoint(8.0), 1.25); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] + pub const fn midpoint(self, other: f16) -> f16 { + const LO: f16 = f16::MIN_POSITIVE * 2.; + const HI: f16 = f16::MAX / 2.; + + let (a, b) = (self, other); + let abs_a = a.abs(); + let abs_b = b.abs(); + + if abs_a <= HI && abs_b <= HI { + // Overflow is impossible + (a + b) / 2. + } else if abs_a < LO { + // Not safe to halve `a` (would underflow) + a + (b / 2.) + } else if abs_b < LO { + // Not safe to halve `b` (would underflow) + (a / 2.) + b + } else { + // Safe to halve `a` and `b` + (a / 2.) + (b / 2.) + } + } + + /// Rounds toward zero and converts to any primitive integer type, + /// assuming that the value is finite and fits in that type. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let value = 4.6_f16; + /// let rounded = unsafe { value.to_int_unchecked::() }; + /// assert_eq!(rounded, 4); + /// + /// let value = -128.9_f16; + /// let rounded = unsafe { value.to_int_unchecked::() }; + /// assert_eq!(rounded, i8::MIN); + /// # } + /// ``` + /// + /// # Safety + /// + /// The value must: + /// + /// * Not be `NaN` + /// * Not be infinite + /// * Be representable in the return type `Int`, after truncating off its fractional part + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub unsafe fn to_int_unchecked(self) -> Int + where + Self: FloatToInt, + { + // SAFETY: the caller must uphold the safety contract for + // `FloatToInt::to_int_unchecked`. + unsafe { FloatToInt::::to_int_unchecked(self) } + } + + /// Raw transmutation to `u16`. + /// + /// This is currently identical to `transmute::(self)` on all platforms. + /// + /// See [`from_bits`](#method.from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// # // FIXME(f16_f128): enable this once const casting works + /// # // assert_ne!((1f16).to_bits(), 1f16 as u128); // to_bits() is not casting! + /// assert_eq!((12.5f16).to_bits(), 0x4a40); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn to_bits(self) -> u16 { + // SAFETY: `u16` is a plain old datatype so we can always transmute to it. + unsafe { mem::transmute(self) } + } + + /// Raw transmutation from `u16`. + /// + /// This is currently identical to `transmute::(v)` on all platforms. + /// It turns out this is incredibly portable, for two reasons: + /// + /// * Floats and Ints have the same endianness on all supported platforms. + /// * IEEE 754 very precisely specifies the bit layout of floats. + /// + /// However there is one caveat: prior to the 2008 version of IEEE 754, how + /// to interpret the NaN signaling bit wasn't actually specified. Most platforms + /// (notably x86 and ARM) picked the interpretation that was ultimately + /// standardized in 2008, but some didn't (notably MIPS). As a result, all + /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa. + /// + /// Rather than trying to preserve signaling-ness cross-platform, this + /// implementation favors preserving the exact bits. This means that + /// any payloads encoded in NaNs will be preserved even if the result of + /// this method is sent over the network from an x86 machine to a MIPS one. + /// + /// If the results of this method are only manipulated by the same + /// architecture that produced them, then there is no portability concern. + /// + /// If the input isn't NaN, then there is no portability concern. + /// + /// If you don't care about signalingness (very likely), then there is no + /// portability concern. + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let v = f16::from_bits(0x4a40); + /// assert_eq!(v, 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + pub const fn from_bits(v: u16) -> Self { + // It turns out the safety issues with sNaN were overblown! Hooray! + // SAFETY: `u16` is a plain old datatype so we can always transmute from it. + unsafe { mem::transmute(v) } + } + + /// Returns the memory representation of this floating point number as a byte array in + /// big-endian (network) byte order. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let bytes = 12.5f16.to_be_bytes(); + /// assert_eq!(bytes, [0x4a, 0x40]); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn to_be_bytes(self) -> [u8; 2] { + self.to_bits().to_be_bytes() + } + + /// Returns the memory representation of this floating point number as a byte array in + /// little-endian byte order. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let bytes = 12.5f16.to_le_bytes(); + /// assert_eq!(bytes, [0x40, 0x4a]); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn to_le_bytes(self) -> [u8; 2] { + self.to_bits().to_le_bytes() + } + + /// Returns the memory representation of this floating point number as a byte array in + /// native byte order. + /// + /// As the target platform's native endianness is used, portable code + /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. + /// + /// [`to_be_bytes`]: f16::to_be_bytes + /// [`to_le_bytes`]: f16::to_le_bytes + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let bytes = 12.5f16.to_ne_bytes(); + /// assert_eq!( + /// bytes, + /// if cfg!(target_endian = "big") { + /// [0x4a, 0x40] + /// } else { + /// [0x40, 0x4a] + /// } + /// ); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn to_ne_bytes(self) -> [u8; 2] { + self.to_bits().to_ne_bytes() + } + + /// Creates a floating point value from its representation as a byte array in big endian. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let value = f16::from_be_bytes([0x4a, 0x40]); + /// assert_eq!(value, 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + pub const fn from_be_bytes(bytes: [u8; 2]) -> Self { + Self::from_bits(u16::from_be_bytes(bytes)) + } + + /// Creates a floating point value from its representation as a byte array in little endian. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let value = f16::from_le_bytes([0x40, 0x4a]); + /// assert_eq!(value, 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + pub const fn from_le_bytes(bytes: [u8; 2]) -> Self { + Self::from_bits(u16::from_le_bytes(bytes)) + } + + /// Creates a floating point value from its representation as a byte array in native endian. + /// + /// As the target platform's native endianness is used, portable code + /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as + /// appropriate instead. + /// + /// [`from_be_bytes`]: f16::from_be_bytes + /// [`from_le_bytes`]: f16::from_le_bytes + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let value = f16::from_ne_bytes(if cfg!(target_endian = "big") { + /// [0x4a, 0x40] + /// } else { + /// [0x40, 0x4a] + /// }); + /// assert_eq!(value, 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + pub const fn from_ne_bytes(bytes: [u8; 2]) -> Self { + Self::from_bits(u16::from_ne_bytes(bytes)) + } + + /// Returns the ordering between `self` and `other`. + /// + /// Unlike the standard partial comparison between floating point numbers, + /// this comparison always produces an ordering in accordance to + /// the `totalOrder` predicate as defined in the IEEE 754 (2008 revision) + /// floating point standard. The values are ordered in the following sequence: + /// + /// - negative quiet NaN + /// - negative signaling NaN + /// - negative infinity + /// - negative numbers + /// - negative subnormal numbers + /// - negative zero + /// - positive zero + /// - positive subnormal numbers + /// - positive numbers + /// - positive infinity + /// - positive signaling NaN + /// - positive quiet NaN. + /// + /// The ordering established by this function does not always agree with the + /// [`PartialOrd`] and [`PartialEq`] implementations of `f16`. For example, + /// they consider negative and positive zero equal, while `total_cmp` + /// doesn't. + /// + /// The interpretation of the signaling NaN bit follows the definition in + /// the IEEE 754 standard, which may not match the interpretation by some of + /// the older, non-conformant (e.g. MIPS) hardware implementations. + /// + /// # Example + /// + /// ``` + /// #![feature(f16)] + /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// struct GoodBoy { + /// name: &'static str, + /// weight: f16, + /// } + /// + /// let mut bois = vec![ + /// GoodBoy { name: "Pucci", weight: 0.1 }, + /// GoodBoy { name: "Woofer", weight: 99.0 }, + /// GoodBoy { name: "Yapper", weight: 10.0 }, + /// GoodBoy { name: "Chonk", weight: f16::INFINITY }, + /// GoodBoy { name: "Abs. Unit", weight: f16::NAN }, + /// GoodBoy { name: "Floaty", weight: -5.0 }, + /// ]; + /// + /// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight)); + /// + /// // `f16::NAN` could be positive or negative, which will affect the sort order. + /// if f16::NAN.is_sign_negative() { + /// bois.into_iter().map(|b| b.weight) + /// .zip([f16::NAN, -5.0, 0.1, 10.0, 99.0, f16::INFINITY].iter()) + /// .for_each(|(a, b)| assert_eq!(a.to_bits(), b.to_bits())) + /// } else { + /// bois.into_iter().map(|b| b.weight) + /// .zip([-5.0, 0.1, 10.0, 99.0, f16::INFINITY, f16::NAN].iter()) + /// .for_each(|(a, b)| assert_eq!(a.to_bits(), b.to_bits())) + /// } + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { + let mut left = self.to_bits() as i16; + let mut right = other.to_bits() as i16; + + // In case of negatives, flip all the bits except the sign + // to achieve a similar layout as two's complement integers + // + // Why does this work? IEEE 754 floats consist of three fields: + // Sign bit, exponent and mantissa. The set of exponent and mantissa + // fields as a whole have the property that their bitwise order is + // equal to the numeric magnitude where the magnitude is defined. + // The magnitude is not normally defined on NaN values, but + // IEEE 754 totalOrder defines the NaN values also to follow the + // bitwise order. This leads to order explained in the doc comment. + // However, the representation of magnitude is the same for negative + // and positive numbers – only the sign bit is different. + // To easily compare the floats as signed integers, we need to + // flip the exponent and mantissa bits in case of negative numbers. + // We effectively convert the numbers to "two's complement" form. + // + // To do the flipping, we construct a mask and XOR against it. + // We branchlessly calculate an "all-ones except for the sign bit" + // mask from negative-signed values: right shifting sign-extends + // the integer, so we "fill" the mask with sign bits, and then + // convert to unsigned to push one more zero bit. + // On positive values, the mask is all zeros, so it's a no-op. + left ^= (((left >> 15) as u16) >> 1) as i16; + right ^= (((right >> 15) as u16) >> 1) as i16; + + left.cmp(&right) + } + + /// Restrict a value to a certain interval unless it is NaN. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// Note that this function returns NaN if the initial value was NaN as + /// well. + /// + /// # Panics + /// + /// Panics if `min > max`, `min` is NaN, or `max` is NaN. + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// assert!((-3.0f16).clamp(-2.0, 1.0) == -2.0); + /// assert!((0.0f16).clamp(-2.0, 1.0) == 0.0); + /// assert!((2.0f16).clamp(-2.0, 1.0) == 1.0); + /// assert!((f16::NAN).clamp(-2.0, 1.0).is_nan()); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub const fn clamp(mut self, min: f16, max: f16) -> f16 { + const_assert!( + min <= max, + "min > max, or either was NaN", + "min > max, or either was NaN. min = {min:?}, max = {max:?}", + min: f16, + max: f16, + ); + + if self < min { + self = min; + } + if self > max { + self = max; + } + self + } + + /// Computes the absolute value of `self`. + /// + /// This function always returns the precise result. + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let x = 3.5_f16; + /// let y = -3.5_f16; + /// + /// assert_eq!(x.abs(), x); + /// assert_eq!(y.abs(), -y); + /// + /// assert!(f16::NAN.abs().is_nan()); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub const fn abs(self) -> Self { + // FIXME(f16_f128): replace with `intrinsics::fabsf16` when available + Self::from_bits(self.to_bits() & !(1 << 15)) + } + + /// Returns a number that represents the sign of `self`. + /// + /// - `1.0` if the number is positive, `+0.0` or `INFINITY` + /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` + /// - NaN if the number is NaN + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let f = 3.5_f16; + /// + /// assert_eq!(f.signum(), 1.0); + /// assert_eq!(f16::NEG_INFINITY.signum(), -1.0); + /// + /// assert!(f16::NAN.signum().is_nan()); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub const fn signum(self) -> f16 { + if self.is_nan() { Self::NAN } else { 1.0_f16.copysign(self) } + } + + /// Returns a number composed of the magnitude of `self` and the sign of + /// `sign`. + /// + /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. + /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let f = 3.5_f16; + /// + /// assert_eq!(f.copysign(0.42), 3.5_f16); + /// assert_eq!(f.copysign(-0.42), -3.5_f16); + /// assert_eq!((-f).copysign(0.42), 3.5_f16); + /// assert_eq!((-f).copysign(-0.42), -3.5_f16); + /// + /// assert!(f16::NAN.copysign(1.0).is_nan()); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub const fn copysign(self, sign: f16) -> f16 { + // SAFETY: this is actually a safe intrinsic + unsafe { intrinsics::copysignf16(self, sign) } + } +} diff --git a/CoqOfRust/core/num/f32.rs b/CoqOfRust/core/num/f32.rs new file mode 100644 index 000000000..4c0d95f95 --- /dev/null +++ b/CoqOfRust/core/num/f32.rs @@ -0,0 +1,1501 @@ +//! Constants for the `f32` single-precision floating point type. +//! +//! *[See also the `f32` primitive type][f32].* +//! +//! Mathematically significant numbers are provided in the `consts` sub-module. +//! +//! For the constants defined directly in this module +//! (as distinct from those defined in the `consts` sub-module), +//! new code should instead use the associated constants +//! defined directly on the `f32` type. + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::convert::FloatToInt; +#[cfg(not(test))] +use crate::intrinsics; +use crate::mem; +use crate::num::FpCategory; +use crate::panic::const_assert; + +/// The radix or base of the internal representation of `f32`. +/// Use [`f32::RADIX`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let r = std::f32::RADIX; +/// +/// // intended way +/// let r = f32::RADIX; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `RADIX` associated constant on `f32`")] +#[rustc_diagnostic_item = "f32_legacy_const_radix"] +pub const RADIX: u32 = f32::RADIX; + +/// Number of significant digits in base 2. +/// Use [`f32::MANTISSA_DIGITS`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let d = std::f32::MANTISSA_DIGITS; +/// +/// // intended way +/// let d = f32::MANTISSA_DIGITS; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated( + since = "TBD", + note = "replaced by the `MANTISSA_DIGITS` associated constant on `f32`" +)] +#[rustc_diagnostic_item = "f32_legacy_const_mantissa_dig"] +pub const MANTISSA_DIGITS: u32 = f32::MANTISSA_DIGITS; + +/// Approximate number of significant digits in base 10. +/// Use [`f32::DIGITS`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let d = std::f32::DIGITS; +/// +/// // intended way +/// let d = f32::DIGITS; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `DIGITS` associated constant on `f32`")] +#[rustc_diagnostic_item = "f32_legacy_const_digits"] +pub const DIGITS: u32 = f32::DIGITS; + +/// [Machine epsilon] value for `f32`. +/// Use [`f32::EPSILON`] instead. +/// +/// This is the difference between `1.0` and the next larger representable number. +/// +/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let e = std::f32::EPSILON; +/// +/// // intended way +/// let e = f32::EPSILON; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `EPSILON` associated constant on `f32`")] +#[rustc_diagnostic_item = "f32_legacy_const_epsilon"] +pub const EPSILON: f32 = f32::EPSILON; + +/// Smallest finite `f32` value. +/// Use [`f32::MIN`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let min = std::f32::MIN; +/// +/// // intended way +/// let min = f32::MIN; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `MIN` associated constant on `f32`")] +#[rustc_diagnostic_item = "f32_legacy_const_min"] +pub const MIN: f32 = f32::MIN; + +/// Smallest positive normal `f32` value. +/// Use [`f32::MIN_POSITIVE`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let min = std::f32::MIN_POSITIVE; +/// +/// // intended way +/// let min = f32::MIN_POSITIVE; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `MIN_POSITIVE` associated constant on `f32`")] +#[rustc_diagnostic_item = "f32_legacy_const_min_positive"] +pub const MIN_POSITIVE: f32 = f32::MIN_POSITIVE; + +/// Largest finite `f32` value. +/// Use [`f32::MAX`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let max = std::f32::MAX; +/// +/// // intended way +/// let max = f32::MAX; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `MAX` associated constant on `f32`")] +#[rustc_diagnostic_item = "f32_legacy_const_max"] +pub const MAX: f32 = f32::MAX; + +/// One greater than the minimum possible normal power of 2 exponent. +/// Use [`f32::MIN_EXP`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let min = std::f32::MIN_EXP; +/// +/// // intended way +/// let min = f32::MIN_EXP; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `MIN_EXP` associated constant on `f32`")] +#[rustc_diagnostic_item = "f32_legacy_const_min_exp"] +pub const MIN_EXP: i32 = f32::MIN_EXP; + +/// Maximum possible power of 2 exponent. +/// Use [`f32::MAX_EXP`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let max = std::f32::MAX_EXP; +/// +/// // intended way +/// let max = f32::MAX_EXP; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `MAX_EXP` associated constant on `f32`")] +#[rustc_diagnostic_item = "f32_legacy_const_max_exp"] +pub const MAX_EXP: i32 = f32::MAX_EXP; + +/// Minimum possible normal power of 10 exponent. +/// Use [`f32::MIN_10_EXP`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let min = std::f32::MIN_10_EXP; +/// +/// // intended way +/// let min = f32::MIN_10_EXP; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `MIN_10_EXP` associated constant on `f32`")] +#[rustc_diagnostic_item = "f32_legacy_const_min_10_exp"] +pub const MIN_10_EXP: i32 = f32::MIN_10_EXP; + +/// Maximum possible power of 10 exponent. +/// Use [`f32::MAX_10_EXP`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let max = std::f32::MAX_10_EXP; +/// +/// // intended way +/// let max = f32::MAX_10_EXP; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `MAX_10_EXP` associated constant on `f32`")] +#[rustc_diagnostic_item = "f32_legacy_const_max_10_exp"] +pub const MAX_10_EXP: i32 = f32::MAX_10_EXP; + +/// Not a Number (NaN). +/// Use [`f32::NAN`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let nan = std::f32::NAN; +/// +/// // intended way +/// let nan = f32::NAN; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `NAN` associated constant on `f32`")] +#[rustc_diagnostic_item = "f32_legacy_const_nan"] +pub const NAN: f32 = f32::NAN; + +/// Infinity (∞). +/// Use [`f32::INFINITY`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let inf = std::f32::INFINITY; +/// +/// // intended way +/// let inf = f32::INFINITY; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `INFINITY` associated constant on `f32`")] +#[rustc_diagnostic_item = "f32_legacy_const_infinity"] +pub const INFINITY: f32 = f32::INFINITY; + +/// Negative infinity (−∞). +/// Use [`f32::NEG_INFINITY`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let ninf = std::f32::NEG_INFINITY; +/// +/// // intended way +/// let ninf = f32::NEG_INFINITY; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `NEG_INFINITY` associated constant on `f32`")] +#[rustc_diagnostic_item = "f32_legacy_const_neg_infinity"] +pub const NEG_INFINITY: f32 = f32::NEG_INFINITY; + +/// Basic mathematical constants. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod consts { + // FIXME: replace with mathematical constants from cmath. + + /// Archimedes' constant (π) + #[stable(feature = "rust1", since = "1.0.0")] + pub const PI: f32 = 3.14159265358979323846264338327950288_f32; + + /// The full circle constant (τ) + /// + /// Equal to 2π. + #[stable(feature = "tau_constant", since = "1.47.0")] + pub const TAU: f32 = 6.28318530717958647692528676655900577_f32; + + /// The golden ratio (φ) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const PHI: f32 = 1.618033988749894848204586834365638118_f32; + + /// The Euler-Mascheroni constant (γ) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const EGAMMA: f32 = 0.577215664901532860606512090082402431_f32; + + /// π/2 + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32; + + /// π/3 + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_PI_3: f32 = 1.04719755119659774615421446109316763_f32; + + /// π/4 + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_PI_4: f32 = 0.785398163397448309615660845819875721_f32; + + /// π/6 + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_PI_6: f32 = 0.52359877559829887307710723054658381_f32; + + /// π/8 + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_PI_8: f32 = 0.39269908169872415480783042290993786_f32; + + /// 1/π + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32; + + /// 1/sqrt(π) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_PI: f32 = 0.564189583547756286948079451560772586_f32; + + /// 1/sqrt(2π) + #[doc(alias = "FRAC_1_SQRT_TAU")] + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_2PI: f32 = 0.398942280401432677939946059934381868_f32; + + /// 2/π + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32; + + /// 2/sqrt(π) + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_2_SQRT_PI: f32 = 1.12837916709551257389615890312154517_f32; + + /// sqrt(2) + #[stable(feature = "rust1", since = "1.0.0")] + pub const SQRT_2: f32 = 1.41421356237309504880168872420969808_f32; + + /// 1/sqrt(2) + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_1_SQRT_2: f32 = 0.707106781186547524400844362104849039_f32; + + /// sqrt(3) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const SQRT_3: f32 = 1.732050807568877293527446341505872367_f32; + + /// 1/sqrt(3) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_3: f32 = 0.577350269189625764509148780501957456_f32; + + /// Euler's number (e) + #[stable(feature = "rust1", since = "1.0.0")] + pub const E: f32 = 2.71828182845904523536028747135266250_f32; + + /// log2(e) + #[stable(feature = "rust1", since = "1.0.0")] + pub const LOG2_E: f32 = 1.44269504088896340735992468100189214_f32; + + /// log2(10) + #[stable(feature = "extra_log_consts", since = "1.43.0")] + pub const LOG2_10: f32 = 3.32192809488736234787031942948939018_f32; + + /// log10(e) + #[stable(feature = "rust1", since = "1.0.0")] + pub const LOG10_E: f32 = 0.434294481903251827651128918916605082_f32; + + /// log10(2) + #[stable(feature = "extra_log_consts", since = "1.43.0")] + pub const LOG10_2: f32 = 0.301029995663981195213738894724493027_f32; + + /// ln(2) + #[stable(feature = "rust1", since = "1.0.0")] + pub const LN_2: f32 = 0.693147180559945309417232121458176568_f32; + + /// ln(10) + #[stable(feature = "rust1", since = "1.0.0")] + pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32; +} + +#[cfg(not(test))] +impl f32 { + /// The radix or base of the internal representation of `f32`. + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const RADIX: u32 = 2; + + /// Number of significant digits in base 2. + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MANTISSA_DIGITS: u32 = 24; + + /// Approximate number of significant digits in base 10. + /// + /// This is the maximum x such that any decimal number with x + /// significant digits can be converted to `f32` and back without loss. + /// + /// Equal to floor(log10 2[`MANTISSA_DIGITS`] − 1). + /// + /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const DIGITS: u32 = 6; + + /// [Machine epsilon] value for `f32`. + /// + /// This is the difference between `1.0` and the next larger representable number. + /// + /// Equal to 21 − [`MANTISSA_DIGITS`]. + /// + /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon + /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "f32_epsilon")] + pub const EPSILON: f32 = 1.19209290e-07_f32; + + /// Smallest finite `f32` value. + /// + /// Equal to −[`MAX`]. + /// + /// [`MAX`]: f32::MAX + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MIN: f32 = -3.40282347e+38_f32; + /// Smallest positive normal `f32` value. + /// + /// Equal to 2[`MIN_EXP`] − 1. + /// + /// [`MIN_EXP`]: f32::MIN_EXP + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MIN_POSITIVE: f32 = 1.17549435e-38_f32; + /// Largest finite `f32` value. + /// + /// Equal to + /// (1 − 2−[`MANTISSA_DIGITS`]) 2[`MAX_EXP`]. + /// + /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS + /// [`MAX_EXP`]: f32::MAX_EXP + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MAX: f32 = 3.40282347e+38_f32; + + /// One greater than the minimum possible normal power of 2 exponent. + /// + /// If x = `MIN_EXP`, then normal numbers + /// ≥ 0.5 × 2x. + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MIN_EXP: i32 = -125; + /// Maximum possible power of 2 exponent. + /// + /// If x = `MAX_EXP`, then normal numbers + /// < 1 × 2x. + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MAX_EXP: i32 = 128; + + /// Minimum x for which 10x is normal. + /// + /// Equal to ceil(log10 [`MIN_POSITIVE`]). + /// + /// [`MIN_POSITIVE`]: f32::MIN_POSITIVE + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MIN_10_EXP: i32 = -37; + /// Maximum x for which 10x is normal. + /// + /// Equal to floor(log10 [`MAX`]). + /// + /// [`MAX`]: f32::MAX + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MAX_10_EXP: i32 = 38; + + /// Not a Number (NaN). + /// + /// Note that IEEE 754 doesn't define just a single NaN value; + /// a plethora of bit patterns are considered to be NaN. + /// Furthermore, the standard makes a difference + /// between a "signaling" and a "quiet" NaN, + /// and allows inspecting its "payload" (the unspecified bits in the bit pattern). + /// This constant isn't guaranteed to equal to any specific NaN bitpattern, + /// and the stability of its representation over Rust versions + /// and target platforms isn't guaranteed. + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + #[rustc_diagnostic_item = "f32_nan"] + #[allow(clippy::eq_op)] + pub const NAN: f32 = 0.0_f32 / 0.0_f32; + /// Infinity (∞). + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const INFINITY: f32 = 1.0_f32 / 0.0_f32; + /// Negative infinity (−∞). + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32; + + /// Sign bit + const SIGN_MASK: u32 = 0x8000_0000; + + /// Exponent mask + const EXP_MASK: u32 = 0x7f80_0000; + + /// Mantissa mask + const MAN_MASK: u32 = 0x007f_ffff; + + /// Minimum representable positive value (min subnormal) + const TINY_BITS: u32 = 0x1; + + /// Minimum representable negative value (min negative subnormal) + const NEG_TINY_BITS: u32 = Self::TINY_BITS | Self::SIGN_MASK; + + /// Returns `true` if this value is NaN. + /// + /// ``` + /// let nan = f32::NAN; + /// let f = 7.0_f32; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + #[inline] + #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :) + pub const fn is_nan(self) -> bool { + self != self + } + + /// Returns `true` if this value is positive infinity or negative infinity, and + /// `false` otherwise. + /// + /// ``` + /// let f = 7.0f32; + /// let inf = f32::INFINITY; + /// let neg_inf = f32::NEG_INFINITY; + /// let nan = f32::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + #[inline] + pub const fn is_infinite(self) -> bool { + // Getting clever with transmutation can result in incorrect answers on some FPUs + // FIXME: alter the Rust <-> Rust calling convention to prevent this problem. + // See https://github.com/rust-lang/rust/issues/72327 + (self == f32::INFINITY) | (self == f32::NEG_INFINITY) + } + + /// Returns `true` if this number is neither infinite nor NaN. + /// + /// ``` + /// let f = 7.0f32; + /// let inf = f32::INFINITY; + /// let neg_inf = f32::NEG_INFINITY; + /// let nan = f32::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + #[inline] + pub const fn is_finite(self) -> bool { + // There's no need to handle NaN separately: if self is NaN, + // the comparison is not true, exactly as desired. + self.abs() < Self::INFINITY + } + + /// Returns `true` if the number is [subnormal]. + /// + /// ``` + /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32 + /// let max = f32::MAX; + /// let lower_than_min = 1.0e-40_f32; + /// let zero = 0.0_f32; + /// + /// assert!(!min.is_subnormal()); + /// assert!(!max.is_subnormal()); + /// + /// assert!(!zero.is_subnormal()); + /// assert!(!f32::NAN.is_subnormal()); + /// assert!(!f32::INFINITY.is_subnormal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(lower_than_min.is_subnormal()); + /// ``` + /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number + #[must_use] + #[stable(feature = "is_subnormal", since = "1.53.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + #[inline] + pub const fn is_subnormal(self) -> bool { + matches!(self.classify(), FpCategory::Subnormal) + } + + /// Returns `true` if the number is neither zero, infinite, + /// [subnormal], or NaN. + /// + /// ``` + /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32 + /// let max = f32::MAX; + /// let lower_than_min = 1.0e-40_f32; + /// let zero = 0.0_f32; + /// + /// assert!(min.is_normal()); + /// assert!(max.is_normal()); + /// + /// assert!(!zero.is_normal()); + /// assert!(!f32::NAN.is_normal()); + /// assert!(!f32::INFINITY.is_normal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(!lower_than_min.is_normal()); + /// ``` + /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + #[inline] + pub const fn is_normal(self) -> bool { + matches!(self.classify(), FpCategory::Normal) + } + + /// Returns the floating point category of the number. If only one property + /// is going to be tested, it is generally faster to use the specific + /// predicate instead. + /// + /// ``` + /// use std::num::FpCategory; + /// + /// let num = 12.4_f32; + /// let inf = f32::INFINITY; + /// + /// assert_eq!(num.classify(), FpCategory::Normal); + /// assert_eq!(inf.classify(), FpCategory::Infinite); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + pub const fn classify(self) -> FpCategory { + // We used to have complicated logic here that avoids the simple bit-based tests to work + // around buggy codegen for x87 targets (see + // https://github.com/rust-lang/rust/issues/114479). However, some LLVM versions later, none + // of our tests is able to find any difference between the complicated and the naive + // version, so now we are back to the naive version. + let b = self.to_bits(); + match (b & Self::MAN_MASK, b & Self::EXP_MASK) { + (0, Self::EXP_MASK) => FpCategory::Infinite, + (_, Self::EXP_MASK) => FpCategory::Nan, + (0, 0) => FpCategory::Zero, + (_, 0) => FpCategory::Subnormal, + _ => FpCategory::Normal, + } + } + + /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with + /// positive sign bit and positive infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_positive` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). + /// + /// ``` + /// let f = 7.0_f32; + /// let g = -7.0_f32; + /// + /// assert!(f.is_sign_positive()); + /// assert!(!g.is_sign_positive()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + #[inline] + pub const fn is_sign_positive(self) -> bool { + !self.is_sign_negative() + } + + /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with + /// negative sign bit and negative infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_negative` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). + /// + /// ``` + /// let f = 7.0f32; + /// let g = -7.0f32; + /// + /// assert!(!f.is_sign_negative()); + /// assert!(g.is_sign_negative()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + #[inline] + pub const fn is_sign_negative(self) -> bool { + // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus + // applies to zeros and NaNs as well. + // SAFETY: This is just transmuting to get the sign bit, it's fine. + unsafe { mem::transmute::(self) & 0x8000_0000 != 0 } + } + + /// Returns the least number greater than `self`. + /// + /// Let `TINY` be the smallest representable positive `f32`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`NEG_INFINITY`], this returns [`MIN`]; + /// - if `self` is `-TINY`, this returns -0.0; + /// - if `self` is -0.0 or +0.0, this returns `TINY`; + /// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`]; + /// - otherwise the unique least value greater than `self` is returned. + /// + /// The identity `x.next_up() == -(-x).next_down()` holds for all non-NaN `x`. When `x` + /// is finite `x == x.next_up().next_down()` also holds. + /// + /// ```rust + /// #![feature(float_next_up_down)] + /// // f32::EPSILON is the difference between 1.0 and the next number up. + /// assert_eq!(1.0f32.next_up(), 1.0 + f32::EPSILON); + /// // But not for most numbers. + /// assert!(0.1f32.next_up() < 0.1 + f32::EPSILON); + /// assert_eq!(16777216f32.next_up(), 16777218.0); + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[inline] + #[unstable(feature = "float_next_up_down", issue = "91399")] + pub const fn next_up(self) -> Self { + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. + let bits = self.to_bits(); + if self.is_nan() || bits == Self::INFINITY.to_bits() { + return self; + } + + let abs = bits & !Self::SIGN_MASK; + let next_bits = if abs == 0 { + Self::TINY_BITS + } else if bits == abs { + bits + 1 + } else { + bits - 1 + }; + Self::from_bits(next_bits) + } + + /// Returns the greatest number less than `self`. + /// + /// Let `TINY` be the smallest representable positive `f32`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`INFINITY`], this returns [`MAX`]; + /// - if `self` is `TINY`, this returns 0.0; + /// - if `self` is -0.0 or +0.0, this returns `-TINY`; + /// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`]; + /// - otherwise the unique greatest value less than `self` is returned. + /// + /// The identity `x.next_down() == -(-x).next_up()` holds for all non-NaN `x`. When `x` + /// is finite `x == x.next_down().next_up()` also holds. + /// + /// ```rust + /// #![feature(float_next_up_down)] + /// let x = 1.0f32; + /// // Clamp value into range [0, 1). + /// let clamped = x.clamp(0.0, 1.0f32.next_down()); + /// assert!(clamped < 1.0); + /// assert_eq!(clamped.next_up(), 1.0); + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[inline] + #[unstable(feature = "float_next_up_down", issue = "91399")] + pub const fn next_down(self) -> Self { + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. + let bits = self.to_bits(); + if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() { + return self; + } + + let abs = bits & !Self::SIGN_MASK; + let next_bits = if abs == 0 { + Self::NEG_TINY_BITS + } else if bits == abs { + bits - 1 + } else { + bits + 1 + }; + Self::from_bits(next_bits) + } + + /// Takes the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// let x = 2.0_f32; + /// let abs_difference = (x.recip() - (1.0 / x)).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[must_use = "this returns the result of the operation, without modifying the original"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn recip(self) -> f32 { + 1.0 / self + } + + /// Converts radians to degrees. + /// + /// ``` + /// let angle = std::f32::consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// # #[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))] + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn to_degrees(self) -> f32 { + // Use a constant for better precision. + const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32; + self * PIS_IN_180 + } + + /// Converts degrees to radians. + /// + /// ``` + /// let angle = 180.0f32; + /// + /// let abs_difference = (angle.to_radians() - std::f32::consts::PI).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn to_radians(self) -> f32 { + const RADS_PER_DEG: f32 = consts::PI / 180.0; + self * RADS_PER_DEG + } + + /// Returns the maximum of the two numbers, ignoring NaN. + /// + /// If one of the arguments is NaN, then the other argument is returned. + /// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs; + /// this function handles all NaNs the same way and avoids maxNum's problems with associativity. + /// This also matches the behavior of libm’s fmax. + /// + /// ``` + /// let x = 1.0f32; + /// let y = 2.0f32; + /// + /// assert_eq!(x.max(y), y); + /// ``` + #[must_use = "this returns the result of the comparison, without modifying either input"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn max(self, other: f32) -> f32 { + intrinsics::maxnumf32(self, other) + } + + /// Returns the minimum of the two numbers, ignoring NaN. + /// + /// If one of the arguments is NaN, then the other argument is returned. + /// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs; + /// this function handles all NaNs the same way and avoids minNum's problems with associativity. + /// This also matches the behavior of libm’s fmin. + /// + /// ``` + /// let x = 1.0f32; + /// let y = 2.0f32; + /// + /// assert_eq!(x.min(y), x); + /// ``` + #[must_use = "this returns the result of the comparison, without modifying either input"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn min(self, other: f32) -> f32 { + intrinsics::minnumf32(self, other) + } + + /// Returns the maximum of the two numbers, propagating NaN. + /// + /// This returns NaN when *either* argument is NaN, as opposed to + /// [`f32::max`] which only returns NaN when *both* arguments are NaN. + /// + /// ``` + /// #![feature(float_minimum_maximum)] + /// let x = 1.0f32; + /// let y = 2.0f32; + /// + /// assert_eq!(x.maximum(y), y); + /// assert!(x.maximum(f32::NAN).is_nan()); + /// ``` + /// + /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater + /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. + /// Note that this follows the semantics specified in IEEE 754-2019. + /// + /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. + #[must_use = "this returns the result of the comparison, without modifying either input"] + #[unstable(feature = "float_minimum_maximum", issue = "91079")] + #[inline] + pub const fn maximum(self, other: f32) -> f32 { + if self > other { + self + } else if other > self { + other + } else if self == other { + if self.is_sign_positive() && other.is_sign_negative() { self } else { other } + } else { + self + other + } + } + + /// Returns the minimum of the two numbers, propagating NaN. + /// + /// This returns NaN when *either* argument is NaN, as opposed to + /// [`f32::min`] which only returns NaN when *both* arguments are NaN. + /// + /// ``` + /// #![feature(float_minimum_maximum)] + /// let x = 1.0f32; + /// let y = 2.0f32; + /// + /// assert_eq!(x.minimum(y), x); + /// assert!(x.minimum(f32::NAN).is_nan()); + /// ``` + /// + /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser + /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. + /// Note that this follows the semantics specified in IEEE 754-2019. + /// + /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. + #[must_use = "this returns the result of the comparison, without modifying either input"] + #[unstable(feature = "float_minimum_maximum", issue = "91079")] + #[inline] + pub const fn minimum(self, other: f32) -> f32 { + if self < other { + self + } else if other < self { + other + } else if self == other { + if self.is_sign_negative() && other.is_sign_positive() { self } else { other } + } else { + // At least one input is NaN. Use `+` to perform NaN propagation and quieting. + self + other + } + } + + /// Calculates the middle point of `self` and `rhs`. + /// + /// This returns NaN when *either* argument is NaN or if a combination of + /// +inf and -inf is provided as arguments. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1f32.midpoint(4.0), 2.5); + /// assert_eq!((-5.5f32).midpoint(8.0), 1.25); + /// ``` + #[inline] + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + pub const fn midpoint(self, other: f32) -> f32 { + cfg_if! { + // Allow faster implementation that have known good 64-bit float + // implementations. Falling back to the branchy code on targets that don't + // have 64-bit hardware floats or buggy implementations. + // https://github.com/rust-lang/rust/pull/121062#issuecomment-2123408114 + if #[cfg(any( + target_arch = "x86_64", + target_arch = "aarch64", + all(any(target_arch = "riscv32", target_arch = "riscv64"), target_feature = "d"), + all(target_arch = "arm", target_feature = "vfp2"), + target_arch = "wasm32", + target_arch = "wasm64", + ))] { + ((self as f64 + other as f64) / 2.0) as f32 + } else { + const LO: f32 = f32::MIN_POSITIVE * 2.; + const HI: f32 = f32::MAX / 2.; + + let (a, b) = (self, other); + let abs_a = a.abs(); + let abs_b = b.abs(); + + if abs_a <= HI && abs_b <= HI { + // Overflow is impossible + (a + b) / 2. + } else if abs_a < LO { + // Not safe to halve `a` (would underflow) + a + (b / 2.) + } else if abs_b < LO { + // Not safe to halve `b` (would underflow) + (a / 2.) + b + } else { + // Safe to halve `a` and `b` + (a / 2.) + (b / 2.) + } + } + } + } + + /// Rounds toward zero and converts to any primitive integer type, + /// assuming that the value is finite and fits in that type. + /// + /// ``` + /// let value = 4.6_f32; + /// let rounded = unsafe { value.to_int_unchecked::() }; + /// assert_eq!(rounded, 4); + /// + /// let value = -128.9_f32; + /// let rounded = unsafe { value.to_int_unchecked::() }; + /// assert_eq!(rounded, i8::MIN); + /// ``` + /// + /// # Safety + /// + /// The value must: + /// + /// * Not be `NaN` + /// * Not be infinite + /// * Be representable in the return type `Int`, after truncating off its fractional part + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "float_approx_unchecked_to", since = "1.44.0")] + #[inline] + pub unsafe fn to_int_unchecked(self) -> Int + where + Self: FloatToInt, + { + // SAFETY: the caller must uphold the safety contract for + // `FloatToInt::to_int_unchecked`. + unsafe { FloatToInt::::to_int_unchecked(self) } + } + + /// Raw transmutation to `u32`. + /// + /// This is currently identical to `transmute::(self)` on all platforms. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// # Examples + /// + /// ``` + /// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting! + /// assert_eq!((12.5f32).to_bits(), 0x41480000); + /// + /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "float_bits_conv", since = "1.20.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[inline] + pub const fn to_bits(self) -> u32 { + // SAFETY: `u32` is a plain old datatype so we can always transmute to it. + unsafe { mem::transmute(self) } + } + + /// Raw transmutation from `u32`. + /// + /// This is currently identical to `transmute::(v)` on all platforms. + /// It turns out this is incredibly portable, for two reasons: + /// + /// * Floats and Ints have the same endianness on all supported platforms. + /// * IEEE 754 very precisely specifies the bit layout of floats. + /// + /// However there is one caveat: prior to the 2008 version of IEEE 754, how + /// to interpret the NaN signaling bit wasn't actually specified. Most platforms + /// (notably x86 and ARM) picked the interpretation that was ultimately + /// standardized in 2008, but some didn't (notably MIPS). As a result, all + /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa. + /// + /// Rather than trying to preserve signaling-ness cross-platform, this + /// implementation favors preserving the exact bits. This means that + /// any payloads encoded in NaNs will be preserved even if the result of + /// this method is sent over the network from an x86 machine to a MIPS one. + /// + /// If the results of this method are only manipulated by the same + /// architecture that produced them, then there is no portability concern. + /// + /// If the input isn't NaN, then there is no portability concern. + /// + /// If you don't care about signalingness (very likely), then there is no + /// portability concern. + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// # Examples + /// + /// ``` + /// let v = f32::from_bits(0x41480000); + /// assert_eq!(v, 12.5); + /// ``` + #[stable(feature = "float_bits_conv", since = "1.20.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[must_use] + #[inline] + pub const fn from_bits(v: u32) -> Self { + // It turns out the safety issues with sNaN were overblown! Hooray! + // SAFETY: `u32` is a plain old datatype so we can always transmute from it. + unsafe { mem::transmute(v) } + } + + /// Returns the memory representation of this floating point number as a byte array in + /// big-endian (network) byte order. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// let bytes = 12.5f32.to_be_bytes(); + /// assert_eq!(bytes, [0x41, 0x48, 0x00, 0x00]); + /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[inline] + pub const fn to_be_bytes(self) -> [u8; 4] { + self.to_bits().to_be_bytes() + } + + /// Returns the memory representation of this floating point number as a byte array in + /// little-endian byte order. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// let bytes = 12.5f32.to_le_bytes(); + /// assert_eq!(bytes, [0x00, 0x00, 0x48, 0x41]); + /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[inline] + pub const fn to_le_bytes(self) -> [u8; 4] { + self.to_bits().to_le_bytes() + } + + /// Returns the memory representation of this floating point number as a byte array in + /// native byte order. + /// + /// As the target platform's native endianness is used, portable code + /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. + /// + /// [`to_be_bytes`]: f32::to_be_bytes + /// [`to_le_bytes`]: f32::to_le_bytes + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// let bytes = 12.5f32.to_ne_bytes(); + /// assert_eq!( + /// bytes, + /// if cfg!(target_endian = "big") { + /// [0x41, 0x48, 0x00, 0x00] + /// } else { + /// [0x00, 0x00, 0x48, 0x41] + /// } + /// ); + /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[inline] + pub const fn to_ne_bytes(self) -> [u8; 4] { + self.to_bits().to_ne_bytes() + } + + /// Creates a floating point value from its representation as a byte array in big endian. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// let value = f32::from_be_bytes([0x41, 0x48, 0x00, 0x00]); + /// assert_eq!(value, 12.5); + /// ``` + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[must_use] + #[inline] + pub const fn from_be_bytes(bytes: [u8; 4]) -> Self { + Self::from_bits(u32::from_be_bytes(bytes)) + } + + /// Creates a floating point value from its representation as a byte array in little endian. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// let value = f32::from_le_bytes([0x00, 0x00, 0x48, 0x41]); + /// assert_eq!(value, 12.5); + /// ``` + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[must_use] + #[inline] + pub const fn from_le_bytes(bytes: [u8; 4]) -> Self { + Self::from_bits(u32::from_le_bytes(bytes)) + } + + /// Creates a floating point value from its representation as a byte array in native endian. + /// + /// As the target platform's native endianness is used, portable code + /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as + /// appropriate instead. + /// + /// [`from_be_bytes`]: f32::from_be_bytes + /// [`from_le_bytes`]: f32::from_le_bytes + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// let value = f32::from_ne_bytes(if cfg!(target_endian = "big") { + /// [0x41, 0x48, 0x00, 0x00] + /// } else { + /// [0x00, 0x00, 0x48, 0x41] + /// }); + /// assert_eq!(value, 12.5); + /// ``` + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[must_use] + #[inline] + pub const fn from_ne_bytes(bytes: [u8; 4]) -> Self { + Self::from_bits(u32::from_ne_bytes(bytes)) + } + + /// Returns the ordering between `self` and `other`. + /// + /// Unlike the standard partial comparison between floating point numbers, + /// this comparison always produces an ordering in accordance to + /// the `totalOrder` predicate as defined in the IEEE 754 (2008 revision) + /// floating point standard. The values are ordered in the following sequence: + /// + /// - negative quiet NaN + /// - negative signaling NaN + /// - negative infinity + /// - negative numbers + /// - negative subnormal numbers + /// - negative zero + /// - positive zero + /// - positive subnormal numbers + /// - positive numbers + /// - positive infinity + /// - positive signaling NaN + /// - positive quiet NaN. + /// + /// The ordering established by this function does not always agree with the + /// [`PartialOrd`] and [`PartialEq`] implementations of `f32`. For example, + /// they consider negative and positive zero equal, while `total_cmp` + /// doesn't. + /// + /// The interpretation of the signaling NaN bit follows the definition in + /// the IEEE 754 standard, which may not match the interpretation by some of + /// the older, non-conformant (e.g. MIPS) hardware implementations. + /// + /// # Example + /// + /// ``` + /// struct GoodBoy { + /// name: String, + /// weight: f32, + /// } + /// + /// let mut bois = vec![ + /// GoodBoy { name: "Pucci".to_owned(), weight: 0.1 }, + /// GoodBoy { name: "Woofer".to_owned(), weight: 99.0 }, + /// GoodBoy { name: "Yapper".to_owned(), weight: 10.0 }, + /// GoodBoy { name: "Chonk".to_owned(), weight: f32::INFINITY }, + /// GoodBoy { name: "Abs. Unit".to_owned(), weight: f32::NAN }, + /// GoodBoy { name: "Floaty".to_owned(), weight: -5.0 }, + /// ]; + /// + /// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight)); + /// + /// // `f32::NAN` could be positive or negative, which will affect the sort order. + /// if f32::NAN.is_sign_negative() { + /// assert!(bois.into_iter().map(|b| b.weight) + /// .zip([f32::NAN, -5.0, 0.1, 10.0, 99.0, f32::INFINITY].iter()) + /// .all(|(a, b)| a.to_bits() == b.to_bits())) + /// } else { + /// assert!(bois.into_iter().map(|b| b.weight) + /// .zip([-5.0, 0.1, 10.0, 99.0, f32::INFINITY, f32::NAN].iter()) + /// .all(|(a, b)| a.to_bits() == b.to_bits())) + /// } + /// ``` + #[stable(feature = "total_cmp", since = "1.62.0")] + #[must_use] + #[inline] + pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { + let mut left = self.to_bits() as i32; + let mut right = other.to_bits() as i32; + + // In case of negatives, flip all the bits except the sign + // to achieve a similar layout as two's complement integers + // + // Why does this work? IEEE 754 floats consist of three fields: + // Sign bit, exponent and mantissa. The set of exponent and mantissa + // fields as a whole have the property that their bitwise order is + // equal to the numeric magnitude where the magnitude is defined. + // The magnitude is not normally defined on NaN values, but + // IEEE 754 totalOrder defines the NaN values also to follow the + // bitwise order. This leads to order explained in the doc comment. + // However, the representation of magnitude is the same for negative + // and positive numbers – only the sign bit is different. + // To easily compare the floats as signed integers, we need to + // flip the exponent and mantissa bits in case of negative numbers. + // We effectively convert the numbers to "two's complement" form. + // + // To do the flipping, we construct a mask and XOR against it. + // We branchlessly calculate an "all-ones except for the sign bit" + // mask from negative-signed values: right shifting sign-extends + // the integer, so we "fill" the mask with sign bits, and then + // convert to unsigned to push one more zero bit. + // On positive values, the mask is all zeros, so it's a no-op. + left ^= (((left >> 31) as u32) >> 1) as i32; + right ^= (((right >> 31) as u32) >> 1) as i32; + + left.cmp(&right) + } + + /// Restrict a value to a certain interval unless it is NaN. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// Note that this function returns NaN if the initial value was NaN as + /// well. + /// + /// # Panics + /// + /// Panics if `min > max`, `min` is NaN, or `max` is NaN. + /// + /// # Examples + /// + /// ``` + /// assert!((-3.0f32).clamp(-2.0, 1.0) == -2.0); + /// assert!((0.0f32).clamp(-2.0, 1.0) == 0.0); + /// assert!((2.0f32).clamp(-2.0, 1.0) == 1.0); + /// assert!((f32::NAN).clamp(-2.0, 1.0).is_nan()); + /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] + #[stable(feature = "clamp", since = "1.50.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn clamp(mut self, min: f32, max: f32) -> f32 { + const_assert!( + min <= max, + "min > max, or either was NaN", + "min > max, or either was NaN. min = {min:?}, max = {max:?}", + min: f32, + max: f32, + ); + + if self < min { + self = min; + } + if self > max { + self = max; + } + self + } + + /// Computes the absolute value of `self`. + /// + /// This function always returns the precise result. + /// + /// # Examples + /// + /// ``` + /// let x = 3.5_f32; + /// let y = -3.5_f32; + /// + /// assert_eq!(x.abs(), x); + /// assert_eq!(y.abs(), -y); + /// + /// assert!(f32::NAN.abs().is_nan()); + /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn abs(self) -> f32 { + // SAFETY: this is actually a safe intrinsic + unsafe { intrinsics::fabsf32(self) } + } + + /// Returns a number that represents the sign of `self`. + /// + /// - `1.0` if the number is positive, `+0.0` or `INFINITY` + /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` + /// - NaN if the number is NaN + /// + /// # Examples + /// + /// ``` + /// let f = 3.5_f32; + /// + /// assert_eq!(f.signum(), 1.0); + /// assert_eq!(f32::NEG_INFINITY.signum(), -1.0); + /// + /// assert!(f32::NAN.signum().is_nan()); + /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn signum(self) -> f32 { + if self.is_nan() { Self::NAN } else { 1.0_f32.copysign(self) } + } + + /// Returns a number composed of the magnitude of `self` and the sign of + /// `sign`. + /// + /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. + /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. + /// + /// # Examples + /// + /// ``` + /// let f = 3.5_f32; + /// + /// assert_eq!(f.copysign(0.42), 3.5_f32); + /// assert_eq!(f.copysign(-0.42), -3.5_f32); + /// assert_eq!((-f).copysign(0.42), 3.5_f32); + /// assert_eq!((-f).copysign(-0.42), -3.5_f32); + /// + /// assert!(f32::NAN.copysign(1.0).is_nan()); + /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] + #[inline] + #[stable(feature = "copysign", since = "1.35.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + pub const fn copysign(self, sign: f32) -> f32 { + // SAFETY: this is actually a safe intrinsic + unsafe { intrinsics::copysignf32(self, sign) } + } +} diff --git a/CoqOfRust/core/num/f64.rs b/CoqOfRust/core/num/f64.rs new file mode 100644 index 000000000..77ca56df0 --- /dev/null +++ b/CoqOfRust/core/num/f64.rs @@ -0,0 +1,1501 @@ +//! Constants for the `f64` double-precision floating point type. +//! +//! *[See also the `f64` primitive type][f64].* +//! +//! Mathematically significant numbers are provided in the `consts` sub-module. +//! +//! For the constants defined directly in this module +//! (as distinct from those defined in the `consts` sub-module), +//! new code should instead use the associated constants +//! defined directly on the `f64` type. + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::convert::FloatToInt; +#[cfg(not(test))] +use crate::intrinsics; +use crate::mem; +use crate::num::FpCategory; +use crate::panic::const_assert; + +/// The radix or base of the internal representation of `f64`. +/// Use [`f64::RADIX`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let r = std::f64::RADIX; +/// +/// // intended way +/// let r = f64::RADIX; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `RADIX` associated constant on `f64`")] +#[rustc_diagnostic_item = "f64_legacy_const_radix"] +pub const RADIX: u32 = f64::RADIX; + +/// Number of significant digits in base 2. +/// Use [`f64::MANTISSA_DIGITS`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let d = std::f64::MANTISSA_DIGITS; +/// +/// // intended way +/// let d = f64::MANTISSA_DIGITS; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated( + since = "TBD", + note = "replaced by the `MANTISSA_DIGITS` associated constant on `f64`" +)] +#[rustc_diagnostic_item = "f64_legacy_const_mantissa_dig"] +pub const MANTISSA_DIGITS: u32 = f64::MANTISSA_DIGITS; + +/// Approximate number of significant digits in base 10. +/// Use [`f64::DIGITS`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let d = std::f64::DIGITS; +/// +/// // intended way +/// let d = f64::DIGITS; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `DIGITS` associated constant on `f64`")] +#[rustc_diagnostic_item = "f64_legacy_const_digits"] +pub const DIGITS: u32 = f64::DIGITS; + +/// [Machine epsilon] value for `f64`. +/// Use [`f64::EPSILON`] instead. +/// +/// This is the difference between `1.0` and the next larger representable number. +/// +/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let e = std::f64::EPSILON; +/// +/// // intended way +/// let e = f64::EPSILON; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `EPSILON` associated constant on `f64`")] +#[rustc_diagnostic_item = "f64_legacy_const_epsilon"] +pub const EPSILON: f64 = f64::EPSILON; + +/// Smallest finite `f64` value. +/// Use [`f64::MIN`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let min = std::f64::MIN; +/// +/// // intended way +/// let min = f64::MIN; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `MIN` associated constant on `f64`")] +#[rustc_diagnostic_item = "f64_legacy_const_min"] +pub const MIN: f64 = f64::MIN; + +/// Smallest positive normal `f64` value. +/// Use [`f64::MIN_POSITIVE`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let min = std::f64::MIN_POSITIVE; +/// +/// // intended way +/// let min = f64::MIN_POSITIVE; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `MIN_POSITIVE` associated constant on `f64`")] +#[rustc_diagnostic_item = "f64_legacy_const_min_positive"] +pub const MIN_POSITIVE: f64 = f64::MIN_POSITIVE; + +/// Largest finite `f64` value. +/// Use [`f64::MAX`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let max = std::f64::MAX; +/// +/// // intended way +/// let max = f64::MAX; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `MAX` associated constant on `f64`")] +#[rustc_diagnostic_item = "f64_legacy_const_max"] +pub const MAX: f64 = f64::MAX; + +/// One greater than the minimum possible normal power of 2 exponent. +/// Use [`f64::MIN_EXP`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let min = std::f64::MIN_EXP; +/// +/// // intended way +/// let min = f64::MIN_EXP; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `MIN_EXP` associated constant on `f64`")] +#[rustc_diagnostic_item = "f64_legacy_const_min_exp"] +pub const MIN_EXP: i32 = f64::MIN_EXP; + +/// Maximum possible power of 2 exponent. +/// Use [`f64::MAX_EXP`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let max = std::f64::MAX_EXP; +/// +/// // intended way +/// let max = f64::MAX_EXP; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `MAX_EXP` associated constant on `f64`")] +#[rustc_diagnostic_item = "f64_legacy_const_max_exp"] +pub const MAX_EXP: i32 = f64::MAX_EXP; + +/// Minimum possible normal power of 10 exponent. +/// Use [`f64::MIN_10_EXP`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let min = std::f64::MIN_10_EXP; +/// +/// // intended way +/// let min = f64::MIN_10_EXP; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `MIN_10_EXP` associated constant on `f64`")] +#[rustc_diagnostic_item = "f64_legacy_const_min_10_exp"] +pub const MIN_10_EXP: i32 = f64::MIN_10_EXP; + +/// Maximum possible power of 10 exponent. +/// Use [`f64::MAX_10_EXP`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let max = std::f64::MAX_10_EXP; +/// +/// // intended way +/// let max = f64::MAX_10_EXP; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `MAX_10_EXP` associated constant on `f64`")] +#[rustc_diagnostic_item = "f64_legacy_const_max_10_exp"] +pub const MAX_10_EXP: i32 = f64::MAX_10_EXP; + +/// Not a Number (NaN). +/// Use [`f64::NAN`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let nan = std::f64::NAN; +/// +/// // intended way +/// let nan = f64::NAN; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `NAN` associated constant on `f64`")] +#[rustc_diagnostic_item = "f64_legacy_const_nan"] +pub const NAN: f64 = f64::NAN; + +/// Infinity (∞). +/// Use [`f64::INFINITY`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let inf = std::f64::INFINITY; +/// +/// // intended way +/// let inf = f64::INFINITY; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `INFINITY` associated constant on `f64`")] +#[rustc_diagnostic_item = "f64_legacy_const_infinity"] +pub const INFINITY: f64 = f64::INFINITY; + +/// Negative infinity (−∞). +/// Use [`f64::NEG_INFINITY`] instead. +/// +/// # Examples +/// +/// ```rust +/// // deprecated way +/// # #[allow(deprecated, deprecated_in_future)] +/// let ninf = std::f64::NEG_INFINITY; +/// +/// // intended way +/// let ninf = f64::NEG_INFINITY; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "TBD", note = "replaced by the `NEG_INFINITY` associated constant on `f64`")] +#[rustc_diagnostic_item = "f64_legacy_const_neg_infinity"] +pub const NEG_INFINITY: f64 = f64::NEG_INFINITY; + +/// Basic mathematical constants. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod consts { + // FIXME: replace with mathematical constants from cmath. + + /// Archimedes' constant (π) + #[stable(feature = "rust1", since = "1.0.0")] + pub const PI: f64 = 3.14159265358979323846264338327950288_f64; + + /// The full circle constant (τ) + /// + /// Equal to 2π. + #[stable(feature = "tau_constant", since = "1.47.0")] + pub const TAU: f64 = 6.28318530717958647692528676655900577_f64; + + /// The golden ratio (φ) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const PHI: f64 = 1.618033988749894848204586834365638118_f64; + + /// The Euler-Mascheroni constant (γ) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const EGAMMA: f64 = 0.577215664901532860606512090082402431_f64; + + /// π/2 + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_PI_2: f64 = 1.57079632679489661923132169163975144_f64; + + /// π/3 + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_PI_3: f64 = 1.04719755119659774615421446109316763_f64; + + /// π/4 + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_PI_4: f64 = 0.785398163397448309615660845819875721_f64; + + /// π/6 + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_PI_6: f64 = 0.52359877559829887307710723054658381_f64; + + /// π/8 + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_PI_8: f64 = 0.39269908169872415480783042290993786_f64; + + /// 1/π + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_1_PI: f64 = 0.318309886183790671537767526745028724_f64; + + /// 1/sqrt(π) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_PI: f64 = 0.564189583547756286948079451560772586_f64; + + /// 1/sqrt(2π) + #[doc(alias = "FRAC_1_SQRT_TAU")] + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_2PI: f64 = 0.398942280401432677939946059934381868_f64; + + /// 2/π + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_2_PI: f64 = 0.636619772367581343075535053490057448_f64; + + /// 2/sqrt(π) + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_2_SQRT_PI: f64 = 1.12837916709551257389615890312154517_f64; + + /// sqrt(2) + #[stable(feature = "rust1", since = "1.0.0")] + pub const SQRT_2: f64 = 1.41421356237309504880168872420969808_f64; + + /// 1/sqrt(2) + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_1_SQRT_2: f64 = 0.707106781186547524400844362104849039_f64; + + /// sqrt(3) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const SQRT_3: f64 = 1.732050807568877293527446341505872367_f64; + + /// 1/sqrt(3) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_3: f64 = 0.577350269189625764509148780501957456_f64; + + /// Euler's number (e) + #[stable(feature = "rust1", since = "1.0.0")] + pub const E: f64 = 2.71828182845904523536028747135266250_f64; + + /// log2(10) + #[stable(feature = "extra_log_consts", since = "1.43.0")] + pub const LOG2_10: f64 = 3.32192809488736234787031942948939018_f64; + + /// log2(e) + #[stable(feature = "rust1", since = "1.0.0")] + pub const LOG2_E: f64 = 1.44269504088896340735992468100189214_f64; + + /// log10(2) + #[stable(feature = "extra_log_consts", since = "1.43.0")] + pub const LOG10_2: f64 = 0.301029995663981195213738894724493027_f64; + + /// log10(e) + #[stable(feature = "rust1", since = "1.0.0")] + pub const LOG10_E: f64 = 0.434294481903251827651128918916605082_f64; + + /// ln(2) + #[stable(feature = "rust1", since = "1.0.0")] + pub const LN_2: f64 = 0.693147180559945309417232121458176568_f64; + + /// ln(10) + #[stable(feature = "rust1", since = "1.0.0")] + pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64; +} + +#[cfg(not(test))] +impl f64 { + /// The radix or base of the internal representation of `f64`. + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const RADIX: u32 = 2; + + /// Number of significant digits in base 2. + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MANTISSA_DIGITS: u32 = 53; + /// Approximate number of significant digits in base 10. + /// + /// This is the maximum x such that any decimal number with x + /// significant digits can be converted to `f64` and back without loss. + /// + /// Equal to floor(log10 2[`MANTISSA_DIGITS`] − 1). + /// + /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const DIGITS: u32 = 15; + + /// [Machine epsilon] value for `f64`. + /// + /// This is the difference between `1.0` and the next larger representable number. + /// + /// Equal to 21 − [`MANTISSA_DIGITS`]. + /// + /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon + /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "f64_epsilon")] + pub const EPSILON: f64 = 2.2204460492503131e-16_f64; + + /// Smallest finite `f64` value. + /// + /// Equal to −[`MAX`]. + /// + /// [`MAX`]: f64::MAX + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MIN: f64 = -1.7976931348623157e+308_f64; + /// Smallest positive normal `f64` value. + /// + /// Equal to 2[`MIN_EXP`] − 1. + /// + /// [`MIN_EXP`]: f64::MIN_EXP + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MIN_POSITIVE: f64 = 2.2250738585072014e-308_f64; + /// Largest finite `f64` value. + /// + /// Equal to + /// (1 − 2−[`MANTISSA_DIGITS`]) 2[`MAX_EXP`]. + /// + /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS + /// [`MAX_EXP`]: f64::MAX_EXP + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MAX: f64 = 1.7976931348623157e+308_f64; + + /// One greater than the minimum possible normal power of 2 exponent. + /// + /// If x = `MIN_EXP`, then normal numbers + /// ≥ 0.5 × 2x. + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MIN_EXP: i32 = -1021; + /// Maximum possible power of 2 exponent. + /// + /// If x = `MAX_EXP`, then normal numbers + /// < 1 × 2x. + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MAX_EXP: i32 = 1024; + + /// Minimum x for which 10x is normal. + /// + /// Equal to ceil(log10 [`MIN_POSITIVE`]). + /// + /// [`MIN_POSITIVE`]: f64::MIN_POSITIVE + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MIN_10_EXP: i32 = -307; + /// Maximum x for which 10x is normal. + /// + /// Equal to floor(log10 [`MAX`]). + /// + /// [`MAX`]: f64::MAX + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MAX_10_EXP: i32 = 308; + + /// Not a Number (NaN). + /// + /// Note that IEEE 754 doesn't define just a single NaN value; + /// a plethora of bit patterns are considered to be NaN. + /// Furthermore, the standard makes a difference + /// between a "signaling" and a "quiet" NaN, + /// and allows inspecting its "payload" (the unspecified bits in the bit pattern). + /// This constant isn't guaranteed to equal to any specific NaN bitpattern, + /// and the stability of its representation over Rust versions + /// and target platforms isn't guaranteed. + #[rustc_diagnostic_item = "f64_nan"] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + #[allow(clippy::eq_op)] + pub const NAN: f64 = 0.0_f64 / 0.0_f64; + /// Infinity (∞). + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const INFINITY: f64 = 1.0_f64 / 0.0_f64; + /// Negative infinity (−∞). + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64; + + /// Sign bit + const SIGN_MASK: u64 = 0x8000_0000_0000_0000; + + /// Exponent mask + const EXP_MASK: u64 = 0x7ff0_0000_0000_0000; + + /// Mantissa mask + const MAN_MASK: u64 = 0x000f_ffff_ffff_ffff; + + /// Minimum representable positive value (min subnormal) + const TINY_BITS: u64 = 0x1; + + /// Minimum representable negative value (min negative subnormal) + const NEG_TINY_BITS: u64 = Self::TINY_BITS | Self::SIGN_MASK; + + /// Returns `true` if this value is NaN. + /// + /// ``` + /// let nan = f64::NAN; + /// let f = 7.0_f64; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + #[inline] + #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :) + pub const fn is_nan(self) -> bool { + self != self + } + + /// Returns `true` if this value is positive infinity or negative infinity, and + /// `false` otherwise. + /// + /// ``` + /// let f = 7.0f64; + /// let inf = f64::INFINITY; + /// let neg_inf = f64::NEG_INFINITY; + /// let nan = f64::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + #[inline] + pub const fn is_infinite(self) -> bool { + // Getting clever with transmutation can result in incorrect answers on some FPUs + // FIXME: alter the Rust <-> Rust calling convention to prevent this problem. + // See https://github.com/rust-lang/rust/issues/72327 + (self == f64::INFINITY) | (self == f64::NEG_INFINITY) + } + + /// Returns `true` if this number is neither infinite nor NaN. + /// + /// ``` + /// let f = 7.0f64; + /// let inf: f64 = f64::INFINITY; + /// let neg_inf: f64 = f64::NEG_INFINITY; + /// let nan: f64 = f64::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + #[inline] + pub const fn is_finite(self) -> bool { + // There's no need to handle NaN separately: if self is NaN, + // the comparison is not true, exactly as desired. + self.abs() < Self::INFINITY + } + + /// Returns `true` if the number is [subnormal]. + /// + /// ``` + /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308_f64 + /// let max = f64::MAX; + /// let lower_than_min = 1.0e-308_f64; + /// let zero = 0.0_f64; + /// + /// assert!(!min.is_subnormal()); + /// assert!(!max.is_subnormal()); + /// + /// assert!(!zero.is_subnormal()); + /// assert!(!f64::NAN.is_subnormal()); + /// assert!(!f64::INFINITY.is_subnormal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(lower_than_min.is_subnormal()); + /// ``` + /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number + #[must_use] + #[stable(feature = "is_subnormal", since = "1.53.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + #[inline] + pub const fn is_subnormal(self) -> bool { + matches!(self.classify(), FpCategory::Subnormal) + } + + /// Returns `true` if the number is neither zero, infinite, + /// [subnormal], or NaN. + /// + /// ``` + /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64 + /// let max = f64::MAX; + /// let lower_than_min = 1.0e-308_f64; + /// let zero = 0.0f64; + /// + /// assert!(min.is_normal()); + /// assert!(max.is_normal()); + /// + /// assert!(!zero.is_normal()); + /// assert!(!f64::NAN.is_normal()); + /// assert!(!f64::INFINITY.is_normal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(!lower_than_min.is_normal()); + /// ``` + /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + #[inline] + pub const fn is_normal(self) -> bool { + matches!(self.classify(), FpCategory::Normal) + } + + /// Returns the floating point category of the number. If only one property + /// is going to be tested, it is generally faster to use the specific + /// predicate instead. + /// + /// ``` + /// use std::num::FpCategory; + /// + /// let num = 12.4_f64; + /// let inf = f64::INFINITY; + /// + /// assert_eq!(num.classify(), FpCategory::Normal); + /// assert_eq!(inf.classify(), FpCategory::Infinite); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + pub const fn classify(self) -> FpCategory { + // We used to have complicated logic here that avoids the simple bit-based tests to work + // around buggy codegen for x87 targets (see + // https://github.com/rust-lang/rust/issues/114479). However, some LLVM versions later, none + // of our tests is able to find any difference between the complicated and the naive + // version, so now we are back to the naive version. + let b = self.to_bits(); + match (b & Self::MAN_MASK, b & Self::EXP_MASK) { + (0, Self::EXP_MASK) => FpCategory::Infinite, + (_, Self::EXP_MASK) => FpCategory::Nan, + (0, 0) => FpCategory::Zero, + (_, 0) => FpCategory::Subnormal, + _ => FpCategory::Normal, + } + } + + /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with + /// positive sign bit and positive infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_positive` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). + /// + /// ``` + /// let f = 7.0_f64; + /// let g = -7.0_f64; + /// + /// assert!(f.is_sign_positive()); + /// assert!(!g.is_sign_positive()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + #[inline] + pub const fn is_sign_positive(self) -> bool { + !self.is_sign_negative() + } + + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "renamed to is_sign_positive")] + #[inline] + #[doc(hidden)] + pub fn is_positive(self) -> bool { + self.is_sign_positive() + } + + /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with + /// negative sign bit and negative infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_negative` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). + /// + /// ``` + /// let f = 7.0_f64; + /// let g = -7.0_f64; + /// + /// assert!(!f.is_sign_negative()); + /// assert!(g.is_sign_negative()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] + #[inline] + pub const fn is_sign_negative(self) -> bool { + // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus + // applies to zeros and NaNs as well. + // SAFETY: This is just transmuting to get the sign bit, it's fine. + unsafe { mem::transmute::(self) & Self::SIGN_MASK != 0 } + } + + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "renamed to is_sign_negative")] + #[inline] + #[doc(hidden)] + pub fn is_negative(self) -> bool { + self.is_sign_negative() + } + + /// Returns the least number greater than `self`. + /// + /// Let `TINY` be the smallest representable positive `f64`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`NEG_INFINITY`], this returns [`MIN`]; + /// - if `self` is `-TINY`, this returns -0.0; + /// - if `self` is -0.0 or +0.0, this returns `TINY`; + /// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`]; + /// - otherwise the unique least value greater than `self` is returned. + /// + /// The identity `x.next_up() == -(-x).next_down()` holds for all non-NaN `x`. When `x` + /// is finite `x == x.next_up().next_down()` also holds. + /// + /// ```rust + /// #![feature(float_next_up_down)] + /// // f64::EPSILON is the difference between 1.0 and the next number up. + /// assert_eq!(1.0f64.next_up(), 1.0 + f64::EPSILON); + /// // But not for most numbers. + /// assert!(0.1f64.next_up() < 0.1 + f64::EPSILON); + /// assert_eq!(9007199254740992f64.next_up(), 9007199254740994.0); + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[inline] + #[unstable(feature = "float_next_up_down", issue = "91399")] + pub const fn next_up(self) -> Self { + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. + let bits = self.to_bits(); + if self.is_nan() || bits == Self::INFINITY.to_bits() { + return self; + } + + let abs = bits & !Self::SIGN_MASK; + let next_bits = if abs == 0 { + Self::TINY_BITS + } else if bits == abs { + bits + 1 + } else { + bits - 1 + }; + Self::from_bits(next_bits) + } + + /// Returns the greatest number less than `self`. + /// + /// Let `TINY` be the smallest representable positive `f64`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`INFINITY`], this returns [`MAX`]; + /// - if `self` is `TINY`, this returns 0.0; + /// - if `self` is -0.0 or +0.0, this returns `-TINY`; + /// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`]; + /// - otherwise the unique greatest value less than `self` is returned. + /// + /// The identity `x.next_down() == -(-x).next_up()` holds for all non-NaN `x`. When `x` + /// is finite `x == x.next_down().next_up()` also holds. + /// + /// ```rust + /// #![feature(float_next_up_down)] + /// let x = 1.0f64; + /// // Clamp value into range [0, 1). + /// let clamped = x.clamp(0.0, 1.0f64.next_down()); + /// assert!(clamped < 1.0); + /// assert_eq!(clamped.next_up(), 1.0); + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[inline] + #[unstable(feature = "float_next_up_down", issue = "91399")] + pub const fn next_down(self) -> Self { + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. + let bits = self.to_bits(); + if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() { + return self; + } + + let abs = bits & !Self::SIGN_MASK; + let next_bits = if abs == 0 { + Self::NEG_TINY_BITS + } else if bits == abs { + bits - 1 + } else { + bits + 1 + }; + Self::from_bits(next_bits) + } + + /// Takes the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// let x = 2.0_f64; + /// let abs_difference = (x.recip() - (1.0 / x)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[must_use = "this returns the result of the operation, without modifying the original"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn recip(self) -> f64 { + 1.0 / self + } + + /// Converts radians to degrees. + /// + /// ``` + /// let angle = std::f64::consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn to_degrees(self) -> f64 { + // The division here is correctly rounded with respect to the true + // value of 180/π. (This differs from f32, where a constant must be + // used to ensure a correctly rounded result.) + self * (180.0f64 / consts::PI) + } + + /// Converts degrees to radians. + /// + /// ``` + /// let angle = 180.0_f64; + /// + /// let abs_difference = (angle.to_radians() - std::f64::consts::PI).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn to_radians(self) -> f64 { + const RADS_PER_DEG: f64 = consts::PI / 180.0; + self * RADS_PER_DEG + } + + /// Returns the maximum of the two numbers, ignoring NaN. + /// + /// If one of the arguments is NaN, then the other argument is returned. + /// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs; + /// this function handles all NaNs the same way and avoids maxNum's problems with associativity. + /// This also matches the behavior of libm’s fmax. + /// + /// ``` + /// let x = 1.0_f64; + /// let y = 2.0_f64; + /// + /// assert_eq!(x.max(y), y); + /// ``` + #[must_use = "this returns the result of the comparison, without modifying either input"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn max(self, other: f64) -> f64 { + intrinsics::maxnumf64(self, other) + } + + /// Returns the minimum of the two numbers, ignoring NaN. + /// + /// If one of the arguments is NaN, then the other argument is returned. + /// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs; + /// this function handles all NaNs the same way and avoids minNum's problems with associativity. + /// This also matches the behavior of libm’s fmin. + /// + /// ``` + /// let x = 1.0_f64; + /// let y = 2.0_f64; + /// + /// assert_eq!(x.min(y), x); + /// ``` + #[must_use = "this returns the result of the comparison, without modifying either input"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn min(self, other: f64) -> f64 { + intrinsics::minnumf64(self, other) + } + + /// Returns the maximum of the two numbers, propagating NaN. + /// + /// This returns NaN when *either* argument is NaN, as opposed to + /// [`f64::max`] which only returns NaN when *both* arguments are NaN. + /// + /// ``` + /// #![feature(float_minimum_maximum)] + /// let x = 1.0_f64; + /// let y = 2.0_f64; + /// + /// assert_eq!(x.maximum(y), y); + /// assert!(x.maximum(f64::NAN).is_nan()); + /// ``` + /// + /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater + /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. + /// Note that this follows the semantics specified in IEEE 754-2019. + /// + /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. + #[must_use = "this returns the result of the comparison, without modifying either input"] + #[unstable(feature = "float_minimum_maximum", issue = "91079")] + #[inline] + pub const fn maximum(self, other: f64) -> f64 { + if self > other { + self + } else if other > self { + other + } else if self == other { + if self.is_sign_positive() && other.is_sign_negative() { self } else { other } + } else { + self + other + } + } + + /// Returns the minimum of the two numbers, propagating NaN. + /// + /// This returns NaN when *either* argument is NaN, as opposed to + /// [`f64::min`] which only returns NaN when *both* arguments are NaN. + /// + /// ``` + /// #![feature(float_minimum_maximum)] + /// let x = 1.0_f64; + /// let y = 2.0_f64; + /// + /// assert_eq!(x.minimum(y), x); + /// assert!(x.minimum(f64::NAN).is_nan()); + /// ``` + /// + /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser + /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. + /// Note that this follows the semantics specified in IEEE 754-2019. + /// + /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. + #[must_use = "this returns the result of the comparison, without modifying either input"] + #[unstable(feature = "float_minimum_maximum", issue = "91079")] + #[inline] + pub const fn minimum(self, other: f64) -> f64 { + if self < other { + self + } else if other < self { + other + } else if self == other { + if self.is_sign_negative() && other.is_sign_positive() { self } else { other } + } else { + // At least one input is NaN. Use `+` to perform NaN propagation and quieting. + self + other + } + } + + /// Calculates the middle point of `self` and `rhs`. + /// + /// This returns NaN when *either* argument is NaN or if a combination of + /// +inf and -inf is provided as arguments. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1f64.midpoint(4.0), 2.5); + /// assert_eq!((-5.5f64).midpoint(8.0), 1.25); + /// ``` + #[inline] + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + pub const fn midpoint(self, other: f64) -> f64 { + const LO: f64 = f64::MIN_POSITIVE * 2.; + const HI: f64 = f64::MAX / 2.; + + let (a, b) = (self, other); + let abs_a = a.abs(); + let abs_b = b.abs(); + + if abs_a <= HI && abs_b <= HI { + // Overflow is impossible + (a + b) / 2. + } else if abs_a < LO { + // Not safe to halve `a` (would underflow) + a + (b / 2.) + } else if abs_b < LO { + // Not safe to halve `b` (would underflow) + (a / 2.) + b + } else { + // Safe to halve `a` and `b` + (a / 2.) + (b / 2.) + } + } + + /// Rounds toward zero and converts to any primitive integer type, + /// assuming that the value is finite and fits in that type. + /// + /// ``` + /// let value = 4.6_f64; + /// let rounded = unsafe { value.to_int_unchecked::() }; + /// assert_eq!(rounded, 4); + /// + /// let value = -128.9_f64; + /// let rounded = unsafe { value.to_int_unchecked::() }; + /// assert_eq!(rounded, i8::MIN); + /// ``` + /// + /// # Safety + /// + /// The value must: + /// + /// * Not be `NaN` + /// * Not be infinite + /// * Be representable in the return type `Int`, after truncating off its fractional part + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "float_approx_unchecked_to", since = "1.44.0")] + #[inline] + pub unsafe fn to_int_unchecked(self) -> Int + where + Self: FloatToInt, + { + // SAFETY: the caller must uphold the safety contract for + // `FloatToInt::to_int_unchecked`. + unsafe { FloatToInt::::to_int_unchecked(self) } + } + + /// Raw transmutation to `u64`. + /// + /// This is currently identical to `transmute::(self)` on all platforms. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// # Examples + /// + /// ``` + /// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting! + /// assert_eq!((12.5f64).to_bits(), 0x4029000000000000); + /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "float_bits_conv", since = "1.20.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[inline] + pub const fn to_bits(self) -> u64 { + // SAFETY: `u64` is a plain old datatype so we can always transmute to it. + unsafe { mem::transmute(self) } + } + + /// Raw transmutation from `u64`. + /// + /// This is currently identical to `transmute::(v)` on all platforms. + /// It turns out this is incredibly portable, for two reasons: + /// + /// * Floats and Ints have the same endianness on all supported platforms. + /// * IEEE 754 very precisely specifies the bit layout of floats. + /// + /// However there is one caveat: prior to the 2008 version of IEEE 754, how + /// to interpret the NaN signaling bit wasn't actually specified. Most platforms + /// (notably x86 and ARM) picked the interpretation that was ultimately + /// standardized in 2008, but some didn't (notably MIPS). As a result, all + /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa. + /// + /// Rather than trying to preserve signaling-ness cross-platform, this + /// implementation favors preserving the exact bits. This means that + /// any payloads encoded in NaNs will be preserved even if the result of + /// this method is sent over the network from an x86 machine to a MIPS one. + /// + /// If the results of this method are only manipulated by the same + /// architecture that produced them, then there is no portability concern. + /// + /// If the input isn't NaN, then there is no portability concern. + /// + /// If you don't care about signaling-ness (very likely), then there is no + /// portability concern. + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// # Examples + /// + /// ``` + /// let v = f64::from_bits(0x4029000000000000); + /// assert_eq!(v, 12.5); + /// ``` + #[stable(feature = "float_bits_conv", since = "1.20.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[must_use] + #[inline] + pub const fn from_bits(v: u64) -> Self { + // It turns out the safety issues with sNaN were overblown! Hooray! + // SAFETY: `u64` is a plain old datatype so we can always transmute from it. + unsafe { mem::transmute(v) } + } + + /// Returns the memory representation of this floating point number as a byte array in + /// big-endian (network) byte order. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// let bytes = 12.5f64.to_be_bytes(); + /// assert_eq!(bytes, [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[inline] + pub const fn to_be_bytes(self) -> [u8; 8] { + self.to_bits().to_be_bytes() + } + + /// Returns the memory representation of this floating point number as a byte array in + /// little-endian byte order. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// let bytes = 12.5f64.to_le_bytes(); + /// assert_eq!(bytes, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]); + /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[inline] + pub const fn to_le_bytes(self) -> [u8; 8] { + self.to_bits().to_le_bytes() + } + + /// Returns the memory representation of this floating point number as a byte array in + /// native byte order. + /// + /// As the target platform's native endianness is used, portable code + /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. + /// + /// [`to_be_bytes`]: f64::to_be_bytes + /// [`to_le_bytes`]: f64::to_le_bytes + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// let bytes = 12.5f64.to_ne_bytes(); + /// assert_eq!( + /// bytes, + /// if cfg!(target_endian = "big") { + /// [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + /// } else { + /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40] + /// } + /// ); + /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[inline] + pub const fn to_ne_bytes(self) -> [u8; 8] { + self.to_bits().to_ne_bytes() + } + + /// Creates a floating point value from its representation as a byte array in big endian. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// let value = f64::from_be_bytes([0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + /// assert_eq!(value, 12.5); + /// ``` + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[must_use] + #[inline] + pub const fn from_be_bytes(bytes: [u8; 8]) -> Self { + Self::from_bits(u64::from_be_bytes(bytes)) + } + + /// Creates a floating point value from its representation as a byte array in little endian. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// let value = f64::from_le_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]); + /// assert_eq!(value, 12.5); + /// ``` + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[must_use] + #[inline] + pub const fn from_le_bytes(bytes: [u8; 8]) -> Self { + Self::from_bits(u64::from_le_bytes(bytes)) + } + + /// Creates a floating point value from its representation as a byte array in native endian. + /// + /// As the target platform's native endianness is used, portable code + /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as + /// appropriate instead. + /// + /// [`from_be_bytes`]: f64::from_be_bytes + /// [`from_le_bytes`]: f64::from_le_bytes + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// let value = f64::from_ne_bytes(if cfg!(target_endian = "big") { + /// [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + /// } else { + /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40] + /// }); + /// assert_eq!(value, 12.5); + /// ``` + #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] + #[must_use] + #[inline] + pub const fn from_ne_bytes(bytes: [u8; 8]) -> Self { + Self::from_bits(u64::from_ne_bytes(bytes)) + } + + /// Returns the ordering between `self` and `other`. + /// + /// Unlike the standard partial comparison between floating point numbers, + /// this comparison always produces an ordering in accordance to + /// the `totalOrder` predicate as defined in the IEEE 754 (2008 revision) + /// floating point standard. The values are ordered in the following sequence: + /// + /// - negative quiet NaN + /// - negative signaling NaN + /// - negative infinity + /// - negative numbers + /// - negative subnormal numbers + /// - negative zero + /// - positive zero + /// - positive subnormal numbers + /// - positive numbers + /// - positive infinity + /// - positive signaling NaN + /// - positive quiet NaN. + /// + /// The ordering established by this function does not always agree with the + /// [`PartialOrd`] and [`PartialEq`] implementations of `f64`. For example, + /// they consider negative and positive zero equal, while `total_cmp` + /// doesn't. + /// + /// The interpretation of the signaling NaN bit follows the definition in + /// the IEEE 754 standard, which may not match the interpretation by some of + /// the older, non-conformant (e.g. MIPS) hardware implementations. + /// + /// # Example + /// + /// ``` + /// struct GoodBoy { + /// name: String, + /// weight: f64, + /// } + /// + /// let mut bois = vec![ + /// GoodBoy { name: "Pucci".to_owned(), weight: 0.1 }, + /// GoodBoy { name: "Woofer".to_owned(), weight: 99.0 }, + /// GoodBoy { name: "Yapper".to_owned(), weight: 10.0 }, + /// GoodBoy { name: "Chonk".to_owned(), weight: f64::INFINITY }, + /// GoodBoy { name: "Abs. Unit".to_owned(), weight: f64::NAN }, + /// GoodBoy { name: "Floaty".to_owned(), weight: -5.0 }, + /// ]; + /// + /// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight)); + /// + /// // `f64::NAN` could be positive or negative, which will affect the sort order. + /// if f64::NAN.is_sign_negative() { + /// assert!(bois.into_iter().map(|b| b.weight) + /// .zip([f64::NAN, -5.0, 0.1, 10.0, 99.0, f64::INFINITY].iter()) + /// .all(|(a, b)| a.to_bits() == b.to_bits())) + /// } else { + /// assert!(bois.into_iter().map(|b| b.weight) + /// .zip([-5.0, 0.1, 10.0, 99.0, f64::INFINITY, f64::NAN].iter()) + /// .all(|(a, b)| a.to_bits() == b.to_bits())) + /// } + /// ``` + #[stable(feature = "total_cmp", since = "1.62.0")] + #[must_use] + #[inline] + pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { + let mut left = self.to_bits() as i64; + let mut right = other.to_bits() as i64; + + // In case of negatives, flip all the bits except the sign + // to achieve a similar layout as two's complement integers + // + // Why does this work? IEEE 754 floats consist of three fields: + // Sign bit, exponent and mantissa. The set of exponent and mantissa + // fields as a whole have the property that their bitwise order is + // equal to the numeric magnitude where the magnitude is defined. + // The magnitude is not normally defined on NaN values, but + // IEEE 754 totalOrder defines the NaN values also to follow the + // bitwise order. This leads to order explained in the doc comment. + // However, the representation of magnitude is the same for negative + // and positive numbers – only the sign bit is different. + // To easily compare the floats as signed integers, we need to + // flip the exponent and mantissa bits in case of negative numbers. + // We effectively convert the numbers to "two's complement" form. + // + // To do the flipping, we construct a mask and XOR against it. + // We branchlessly calculate an "all-ones except for the sign bit" + // mask from negative-signed values: right shifting sign-extends + // the integer, so we "fill" the mask with sign bits, and then + // convert to unsigned to push one more zero bit. + // On positive values, the mask is all zeros, so it's a no-op. + left ^= (((left >> 63) as u64) >> 1) as i64; + right ^= (((right >> 63) as u64) >> 1) as i64; + + left.cmp(&right) + } + + /// Restrict a value to a certain interval unless it is NaN. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// Note that this function returns NaN if the initial value was NaN as + /// well. + /// + /// # Panics + /// + /// Panics if `min > max`, `min` is NaN, or `max` is NaN. + /// + /// # Examples + /// + /// ``` + /// assert!((-3.0f64).clamp(-2.0, 1.0) == -2.0); + /// assert!((0.0f64).clamp(-2.0, 1.0) == 0.0); + /// assert!((2.0f64).clamp(-2.0, 1.0) == 1.0); + /// assert!((f64::NAN).clamp(-2.0, 1.0).is_nan()); + /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] + #[stable(feature = "clamp", since = "1.50.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn clamp(mut self, min: f64, max: f64) -> f64 { + const_assert!( + min <= max, + "min > max, or either was NaN", + "min > max, or either was NaN. min = {min:?}, max = {max:?}", + min: f64, + max: f64, + ); + + if self < min { + self = min; + } + if self > max { + self = max; + } + self + } + + /// Computes the absolute value of `self`. + /// + /// This function always returns the precise result. + /// + /// # Examples + /// + /// ``` + /// let x = 3.5_f64; + /// let y = -3.5_f64; + /// + /// assert_eq!(x.abs(), x); + /// assert_eq!(y.abs(), -y); + /// + /// assert!(f64::NAN.abs().is_nan()); + /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn abs(self) -> f64 { + // SAFETY: this is actually a safe intrinsic + unsafe { intrinsics::fabsf64(self) } + } + + /// Returns a number that represents the sign of `self`. + /// + /// - `1.0` if the number is positive, `+0.0` or `INFINITY` + /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` + /// - NaN if the number is NaN + /// + /// # Examples + /// + /// ``` + /// let f = 3.5_f64; + /// + /// assert_eq!(f.signum(), 1.0); + /// assert_eq!(f64::NEG_INFINITY.signum(), -1.0); + /// + /// assert!(f64::NAN.signum().is_nan()); + /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn signum(self) -> f64 { + if self.is_nan() { Self::NAN } else { 1.0_f64.copysign(self) } + } + + /// Returns a number composed of the magnitude of `self` and the sign of + /// `sign`. + /// + /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. + /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. + /// + /// # Examples + /// + /// ``` + /// let f = 3.5_f64; + /// + /// assert_eq!(f.copysign(0.42), 3.5_f64); + /// assert_eq!(f.copysign(-0.42), -3.5_f64); + /// assert_eq!((-f).copysign(0.42), 3.5_f64); + /// assert_eq!((-f).copysign(-0.42), -3.5_f64); + /// + /// assert!(f64::NAN.copysign(1.0).is_nan()); + /// ``` + #[must_use = "method returns a new number and does not mutate the original value"] + #[stable(feature = "copysign", since = "1.35.0")] + #[rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION")] + #[inline] + pub const fn copysign(self, sign: f64) -> f64 { + // SAFETY: this is actually a safe intrinsic + unsafe { intrinsics::copysignf64(self, sign) } + } +} diff --git a/CoqOfRust/core/num/flt2dec/decoder.rs b/CoqOfRust/core/num/flt2dec/decoder.rs new file mode 100644 index 000000000..40b3aae24 --- /dev/null +++ b/CoqOfRust/core/num/flt2dec/decoder.rs @@ -0,0 +1,100 @@ +//! Decodes a floating-point value into individual parts and error ranges. + +use crate::num::FpCategory; +use crate::num::dec2flt::float::RawFloat; + +/// Decoded unsigned finite value, such that: +/// +/// - The original value equals to `mant * 2^exp`. +/// +/// - Any number from `(mant - minus) * 2^exp` to `(mant + plus) * 2^exp` will +/// round to the original value. The range is inclusive only when +/// `inclusive` is `true`. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct Decoded { + /// The scaled mantissa. + pub mant: u64, + /// The lower error range. + pub minus: u64, + /// The upper error range. + pub plus: u64, + /// The shared exponent in base 2. + pub exp: i16, + /// True when the error range is inclusive. + /// + /// In IEEE 754, this is true when the original mantissa was even. + pub inclusive: bool, +} + +/// Decoded unsigned value. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum FullDecoded { + /// Not-a-number. + Nan, + /// Infinities, either positive or negative. + Infinite, + /// Zero, either positive or negative. + Zero, + /// Finite numbers with further decoded fields. + Finite(Decoded), +} + +/// A floating point type which can be `decode`d. +pub trait DecodableFloat: RawFloat + Copy { + /// The minimum positive normalized value. + fn min_pos_norm_value() -> Self; +} + +impl DecodableFloat for f32 { + fn min_pos_norm_value() -> Self { + f32::MIN_POSITIVE + } +} + +impl DecodableFloat for f64 { + fn min_pos_norm_value() -> Self { + f64::MIN_POSITIVE + } +} + +/// Returns a sign (true when negative) and `FullDecoded` value +/// from given floating point number. +pub fn decode(v: T) -> (/*negative?*/ bool, FullDecoded) { + let (mant, exp, sign) = v.integer_decode(); + let even = (mant & 1) == 0; + let decoded = match v.classify() { + FpCategory::Nan => FullDecoded::Nan, + FpCategory::Infinite => FullDecoded::Infinite, + FpCategory::Zero => FullDecoded::Zero, + FpCategory::Subnormal => { + // neighbors: (mant - 2, exp) -- (mant, exp) -- (mant + 2, exp) + // Float::integer_decode always preserves the exponent, + // so the mantissa is scaled for subnormals. + FullDecoded::Finite(Decoded { mant, minus: 1, plus: 1, exp, inclusive: even }) + } + FpCategory::Normal => { + let minnorm = ::min_pos_norm_value().integer_decode(); + if mant == minnorm.0 { + // neighbors: (maxmant, exp - 1) -- (minnormmant, exp) -- (minnormmant + 1, exp) + // where maxmant = minnormmant * 2 - 1 + FullDecoded::Finite(Decoded { + mant: mant << 2, + minus: 1, + plus: 2, + exp: exp - 2, + inclusive: even, + }) + } else { + // neighbors: (mant - 1, exp) -- (mant, exp) -- (mant + 1, exp) + FullDecoded::Finite(Decoded { + mant: mant << 1, + minus: 1, + plus: 1, + exp: exp - 1, + inclusive: even, + }) + } + } + }; + (sign < 0, decoded) +} diff --git a/CoqOfRust/core/num/flt2dec/estimator.rs b/CoqOfRust/core/num/flt2dec/estimator.rs new file mode 100644 index 000000000..50e2f7052 --- /dev/null +++ b/CoqOfRust/core/num/flt2dec/estimator.rs @@ -0,0 +1,14 @@ +//! The exponent estimator. + +/// Finds `k_0` such that `10^(k_0-1) < mant * 2^exp <= 10^(k_0+1)`. +/// +/// This is used to approximate `k = ceil(log_10 (mant * 2^exp))`; +/// the true `k` is either `k_0` or `k_0+1`. +#[doc(hidden)] +pub fn estimate_scaling_factor(mant: u64, exp: i16) -> i16 { + // 2^(nbits-1) < mant <= 2^nbits if mant > 0 + let nbits = 64 - (mant - 1).leading_zeros() as i64; + // 1292913986 = floor(2^32 * log_10 2) + // therefore this always underestimates (or is exact), but not much. + (((nbits + exp as i64) * 1292913986) >> 32) as i16 +} diff --git a/CoqOfRust/core/num/flt2dec/mod.rs b/CoqOfRust/core/num/flt2dec/mod.rs new file mode 100644 index 000000000..d6413fadc --- /dev/null +++ b/CoqOfRust/core/num/flt2dec/mod.rs @@ -0,0 +1,672 @@ +/*! + +Floating-point number to decimal conversion routines. + +# Problem statement + +We are given the floating-point number `v = f * 2^e` with an integer `f`, +and its bounds `minus` and `plus` such that any number between `v - minus` and +`v + plus` will be rounded to `v`. For the simplicity we assume that +this range is exclusive. Then we would like to get the unique decimal +representation `V = 0.d[0..n-1] * 10^k` such that: + +- `d[0]` is non-zero. + +- It's correctly rounded when parsed back: `v - minus < V < v + plus`. + Furthermore it is shortest such one, i.e., there is no representation + with less than `n` digits that is correctly rounded. + +- It's closest to the original value: `abs(V - v) <= 10^(k-n) / 2`. Note that + there might be two representations satisfying this uniqueness requirement, + in which case some tie-breaking mechanism is used. + +We will call this mode of operation as to the *shortest* mode. This mode is used +when there is no additional constraint, and can be thought as a "natural" mode +as it matches the ordinary intuition (it at least prints `0.1f32` as "0.1"). + +We have two more modes of operation closely related to each other. In these modes +we are given either the number of significant digits `n` or the last-digit +limitation `limit` (which determines the actual `n`), and we would like to get +the representation `V = 0.d[0..n-1] * 10^k` such that: + +- `d[0]` is non-zero, unless `n` was zero in which case only `k` is returned. + +- It's closest to the original value: `abs(V - v) <= 10^(k-n) / 2`. Again, + there might be some tie-breaking mechanism. + +When `limit` is given but not `n`, we set `n` such that `k - n = limit` +so that the last digit `d[n-1]` is scaled by `10^(k-n) = 10^limit`. +If such `n` is negative, we clip it to zero so that we will only get `k`. +We are also limited by the supplied buffer. This limitation is used to print +the number up to given number of fractional digits without knowing +the correct `k` beforehand. + +We will call the mode of operation requiring `n` as to the *exact* mode, +and one requiring `limit` as to the *fixed* mode. The exact mode is a subset of +the fixed mode: the sufficiently large last-digit limitation will eventually fill +the supplied buffer and let the algorithm to return. + +# Implementation overview + +It is easy to get the floating point printing correct but slow (Russ Cox has +[demonstrated](https://research.swtch.com/ftoa) how it's easy), or incorrect but +fast (naïve division and modulo). But it is surprisingly hard to print +floating point numbers correctly *and* efficiently. + +There are two classes of algorithms widely known to be correct. + +- The "Dragon" family of algorithm is first described by Guy L. Steele Jr. and + Jon L. White. They rely on the fixed-size big integer for their correctness. + A slight improvement was found later, which is posthumously described by + Robert G. Burger and R. Kent Dybvig. David Gay's `dtoa.c` routine is + a popular implementation of this strategy. + +- The "Grisu" family of algorithm is first described by Florian Loitsch. + They use very cheap integer-only procedure to determine the close-to-correct + representation which is at least guaranteed to be shortest. The variant, + Grisu3, actively detects if the resulting representation is incorrect. + +We implement both algorithms with necessary tweaks to suit our requirements. +In particular, published literatures are short of the actual implementation +difficulties like how to avoid arithmetic overflows. Each implementation, +available in `strategy::dragon` and `strategy::grisu` respectively, +extensively describes all necessary justifications and many proofs for them. +(It is still difficult to follow though. You have been warned.) + +Both implementations expose two public functions: + +- `format_shortest(decoded, buf)`, which always needs at least + `MAX_SIG_DIGITS` digits of buffer. Implements the shortest mode. + +- `format_exact(decoded, buf, limit)`, which accepts as small as + one digit of buffer. Implements exact and fixed modes. + +They try to fill the `u8` buffer with digits and returns the number of digits +written and the exponent `k`. They are total for all finite `f32` and `f64` +inputs (Grisu internally falls back to Dragon if necessary). + +The rendered digits are formatted into the actual string form with +four functions: + +- `to_shortest_str` prints the shortest representation, which can be padded by + zeroes to make *at least* given number of fractional digits. + +- `to_shortest_exp_str` prints the shortest representation, which can be + padded by zeroes when its exponent is in the specified ranges, + or can be printed in the exponential form such as `1.23e45`. + +- `to_exact_exp_str` prints the exact representation with given number of + digits in the exponential form. + +- `to_exact_fixed_str` prints the fixed representation with *exactly* + given number of fractional digits. + +They all return a slice of preallocated `Part` array, which corresponds to +the individual part of strings: a fixed string, a part of rendered digits, +a number of zeroes or a small (`u16`) number. The caller is expected to +provide a large enough buffer and `Part` array, and to assemble the final +string from resulting `Part`s itself. + +All algorithms and formatting functions are accompanied by extensive tests +in `coretests::num::flt2dec` module. It also shows how to use individual +functions. + +*/ + +// while this is extensively documented, this is in principle private which is +// only made public for testing. do not expose us. +#![doc(hidden)] +#![unstable( + feature = "flt2dec", + reason = "internal routines only exposed for testing", + issue = "none" +)] + +pub use self::decoder::{DecodableFloat, Decoded, FullDecoded, decode}; +use super::fmt::{Formatted, Part}; +use crate::mem::MaybeUninit; + +pub mod decoder; +pub mod estimator; + +/// Digit-generation algorithms. +pub mod strategy { + pub mod dragon; + pub mod grisu; +} + +/// The minimum size of buffer necessary for the shortest mode. +/// +/// It is a bit non-trivial to derive, but this is one plus the maximal number of +/// significant decimal digits from formatting algorithms with the shortest result. +/// The exact formula is `ceil(# bits in mantissa * log_10 2 + 1)`. +pub const MAX_SIG_DIGITS: usize = 17; + +/// When `d` contains decimal digits, increase the last digit and propagate carry. +/// Returns a next digit when it causes the length to change. +#[doc(hidden)] +pub fn round_up(d: &mut [u8]) -> Option { + match d.iter().rposition(|&c| c != b'9') { + Some(i) => { + // d[i+1..n] is all nines + d[i] += 1; + for j in i + 1..d.len() { + d[j] = b'0'; + } + None + } + None if d.len() > 0 => { + // 999..999 rounds to 1000..000 with an increased exponent + d[0] = b'1'; + for j in 1..d.len() { + d[j] = b'0'; + } + Some(b'0') + } + None => { + // an empty buffer rounds up (a bit strange but reasonable) + Some(b'1') + } + } +} + +/// Formats given decimal digits `0.<...buf...> * 10^exp` into the decimal form +/// with at least given number of fractional digits. The result is stored to +/// the supplied parts array and a slice of written parts is returned. +/// +/// `frac_digits` can be less than the number of actual fractional digits in `buf`; +/// it will be ignored and full digits will be printed. It is only used to print +/// additional zeroes after rendered digits. Thus `frac_digits` of 0 means that +/// it will only print given digits and nothing else. +fn digits_to_dec_str<'a>( + buf: &'a [u8], + exp: i16, + frac_digits: usize, + parts: &'a mut [MaybeUninit>], +) -> &'a [Part<'a>] { + assert!(!buf.is_empty()); + assert!(buf[0] > b'0'); + assert!(parts.len() >= 4); + + // if there is the restriction on the last digit position, `buf` is assumed to be + // left-padded with the virtual zeroes. the number of virtual zeroes, `nzeroes`, + // equals to `max(0, exp + frac_digits - buf.len())`, so that the position of + // the last digit `exp - buf.len() - nzeroes` is no more than `-frac_digits`: + // + // |<-virtual->| + // |<---- buf ---->| zeroes | exp + // 0. 1 2 3 4 5 6 7 8 9 _ _ _ _ _ _ x 10 + // | | | + // 10^exp 10^(exp-buf.len()) 10^(exp-buf.len()-nzeroes) + // + // `nzeroes` is individually calculated for each case in order to avoid overflow. + + if exp <= 0 { + // the decimal point is before rendered digits: [0.][000...000][1234][____] + let minus_exp = -(exp as i32) as usize; + parts[0] = MaybeUninit::new(Part::Copy(b"0.")); + parts[1] = MaybeUninit::new(Part::Zero(minus_exp)); + parts[2] = MaybeUninit::new(Part::Copy(buf)); + if frac_digits > buf.len() && frac_digits - buf.len() > minus_exp { + parts[3] = MaybeUninit::new(Part::Zero((frac_digits - buf.len()) - minus_exp)); + // SAFETY: we just initialized the elements `..4`. + unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) } + } else { + // SAFETY: we just initialized the elements `..3`. + unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) } + } + } else { + let exp = exp as usize; + if exp < buf.len() { + // the decimal point is inside rendered digits: [12][.][34][____] + parts[0] = MaybeUninit::new(Part::Copy(&buf[..exp])); + parts[1] = MaybeUninit::new(Part::Copy(b".")); + parts[2] = MaybeUninit::new(Part::Copy(&buf[exp..])); + if frac_digits > buf.len() - exp { + parts[3] = MaybeUninit::new(Part::Zero(frac_digits - (buf.len() - exp))); + // SAFETY: we just initialized the elements `..4`. + unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) } + } else { + // SAFETY: we just initialized the elements `..3`. + unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) } + } + } else { + // the decimal point is after rendered digits: [1234][____0000] or [1234][__][.][__]. + parts[0] = MaybeUninit::new(Part::Copy(buf)); + parts[1] = MaybeUninit::new(Part::Zero(exp - buf.len())); + if frac_digits > 0 { + parts[2] = MaybeUninit::new(Part::Copy(b".")); + parts[3] = MaybeUninit::new(Part::Zero(frac_digits)); + // SAFETY: we just initialized the elements `..4`. + unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) } + } else { + // SAFETY: we just initialized the elements `..2`. + unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) } + } + } + } +} + +/// Formats the given decimal digits `0.<...buf...> * 10^exp` into the exponential +/// form with at least the given number of significant digits. When `upper` is `true`, +/// the exponent will be prefixed by `E`; otherwise that's `e`. The result is +/// stored to the supplied parts array and a slice of written parts is returned. +/// +/// `min_digits` can be less than the number of actual significant digits in `buf`; +/// it will be ignored and full digits will be printed. It is only used to print +/// additional zeroes after rendered digits. Thus, `min_digits == 0` means that +/// it will only print the given digits and nothing else. +fn digits_to_exp_str<'a>( + buf: &'a [u8], + exp: i16, + min_ndigits: usize, + upper: bool, + parts: &'a mut [MaybeUninit>], +) -> &'a [Part<'a>] { + assert!(!buf.is_empty()); + assert!(buf[0] > b'0'); + assert!(parts.len() >= 6); + + let mut n = 0; + + parts[n] = MaybeUninit::new(Part::Copy(&buf[..1])); + n += 1; + + if buf.len() > 1 || min_ndigits > 1 { + parts[n] = MaybeUninit::new(Part::Copy(b".")); + parts[n + 1] = MaybeUninit::new(Part::Copy(&buf[1..])); + n += 2; + if min_ndigits > buf.len() { + parts[n] = MaybeUninit::new(Part::Zero(min_ndigits - buf.len())); + n += 1; + } + } + + // 0.1234 x 10^exp = 1.234 x 10^(exp-1) + let exp = exp as i32 - 1; // avoid underflow when exp is i16::MIN + if exp < 0 { + parts[n] = MaybeUninit::new(Part::Copy(if upper { b"E-" } else { b"e-" })); + parts[n + 1] = MaybeUninit::new(Part::Num(-exp as u16)); + } else { + parts[n] = MaybeUninit::new(Part::Copy(if upper { b"E" } else { b"e" })); + parts[n + 1] = MaybeUninit::new(Part::Num(exp as u16)); + } + // SAFETY: we just initialized the elements `..n + 2`. + unsafe { MaybeUninit::slice_assume_init_ref(&parts[..n + 2]) } +} + +/// Sign formatting options. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Sign { + /// Prints `-` for any negative value. + Minus, // -inf -1 -0 0 1 inf nan + /// Prints `-` for any negative value, or `+` otherwise. + MinusPlus, // -inf -1 -0 +0 +1 +inf nan +} + +/// Returns the static byte string corresponding to the sign to be formatted. +/// It can be either `""`, `"+"` or `"-"`. +fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static str { + match (*decoded, sign) { + (FullDecoded::Nan, _) => "", + (_, Sign::Minus) => { + if negative { + "-" + } else { + "" + } + } + (_, Sign::MinusPlus) => { + if negative { + "-" + } else { + "+" + } + } + } +} + +/// Formats the given floating point number into the decimal form with at least +/// given number of fractional digits. The result is stored to the supplied parts +/// array while utilizing given byte buffer as a scratch. `upper` is currently +/// unused but left for the future decision to change the case of non-finite values, +/// i.e., `inf` and `nan`. The first part to be rendered is always a `Part::Sign` +/// (which can be an empty string if no sign is rendered). +/// +/// `format_shortest` should be the underlying digit-generation function. +/// It should return the part of the buffer that it initialized. +/// You probably would want `strategy::grisu::format_shortest` for this. +/// +/// `frac_digits` can be less than the number of actual fractional digits in `v`; +/// it will be ignored and full digits will be printed. It is only used to print +/// additional zeroes after rendered digits. Thus `frac_digits` of 0 means that +/// it will only print given digits and nothing else. +/// +/// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long. +/// There should be at least 4 parts available, due to the worst case like +/// `[+][0.][0000][2][0000]` with `frac_digits = 10`. +pub fn to_shortest_str<'a, T, F>( + mut format_shortest: F, + v: T, + sign: Sign, + frac_digits: usize, + buf: &'a mut [MaybeUninit], + parts: &'a mut [MaybeUninit>], +) -> Formatted<'a> +where + T: DecodableFloat, + F: FnMut(&Decoded, &'a mut [MaybeUninit]) -> (&'a [u8], i16), +{ + assert!(parts.len() >= 4); + assert!(buf.len() >= MAX_SIG_DIGITS); + + let (negative, full_decoded) = decode(v); + let sign = determine_sign(sign, &full_decoded, negative); + match full_decoded { + FullDecoded::Nan => { + parts[0] = MaybeUninit::new(Part::Copy(b"NaN")); + // SAFETY: we just initialized the elements `..1`. + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + } + FullDecoded::Infinite => { + parts[0] = MaybeUninit::new(Part::Copy(b"inf")); + // SAFETY: we just initialized the elements `..1`. + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + } + FullDecoded::Zero => { + if frac_digits > 0 { + // [0.][0000] + parts[0] = MaybeUninit::new(Part::Copy(b"0.")); + parts[1] = MaybeUninit::new(Part::Zero(frac_digits)); + Formatted { + sign, + // SAFETY: we just initialized the elements `..2`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) }, + } + } else { + parts[0] = MaybeUninit::new(Part::Copy(b"0")); + Formatted { + sign, + // SAFETY: we just initialized the elements `..1`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) }, + } + } + } + FullDecoded::Finite(ref decoded) => { + let (buf, exp) = format_shortest(decoded, buf); + Formatted { sign, parts: digits_to_dec_str(buf, exp, frac_digits, parts) } + } + } +} + +/// Formats the given floating point number into the decimal form or +/// the exponential form, depending on the resulting exponent. The result is +/// stored to the supplied parts array while utilizing given byte buffer +/// as a scratch. `upper` is used to determine the case of non-finite values +/// (`inf` and `nan`) or the case of the exponent prefix (`e` or `E`). +/// The first part to be rendered is always a `Part::Sign` (which can be +/// an empty string if no sign is rendered). +/// +/// `format_shortest` should be the underlying digit-generation function. +/// It should return the part of the buffer that it initialized. +/// You probably would want `strategy::grisu::format_shortest` for this. +/// +/// The `dec_bounds` is a tuple `(lo, hi)` such that the number is formatted +/// as decimal only when `10^lo <= V < 10^hi`. Note that this is the *apparent* `V` +/// instead of the actual `v`! Thus any printed exponent in the exponential form +/// cannot be in this range, avoiding any confusion. +/// +/// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long. +/// There should be at least 6 parts available, due to the worst case like +/// `[+][1][.][2345][e][-][6]`. +pub fn to_shortest_exp_str<'a, T, F>( + mut format_shortest: F, + v: T, + sign: Sign, + dec_bounds: (i16, i16), + upper: bool, + buf: &'a mut [MaybeUninit], + parts: &'a mut [MaybeUninit>], +) -> Formatted<'a> +where + T: DecodableFloat, + F: FnMut(&Decoded, &'a mut [MaybeUninit]) -> (&'a [u8], i16), +{ + assert!(parts.len() >= 6); + assert!(buf.len() >= MAX_SIG_DIGITS); + assert!(dec_bounds.0 <= dec_bounds.1); + + let (negative, full_decoded) = decode(v); + let sign = determine_sign(sign, &full_decoded, negative); + match full_decoded { + FullDecoded::Nan => { + parts[0] = MaybeUninit::new(Part::Copy(b"NaN")); + // SAFETY: we just initialized the elements `..1`. + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + } + FullDecoded::Infinite => { + parts[0] = MaybeUninit::new(Part::Copy(b"inf")); + // SAFETY: we just initialized the elements `..1`. + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + } + FullDecoded::Zero => { + parts[0] = if dec_bounds.0 <= 0 && 0 < dec_bounds.1 { + MaybeUninit::new(Part::Copy(b"0")) + } else { + MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" })) + }; + // SAFETY: we just initialized the elements `..1`. + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + } + FullDecoded::Finite(ref decoded) => { + let (buf, exp) = format_shortest(decoded, buf); + let vis_exp = exp as i32 - 1; + let parts = if dec_bounds.0 as i32 <= vis_exp && vis_exp < dec_bounds.1 as i32 { + digits_to_dec_str(buf, exp, 0, parts) + } else { + digits_to_exp_str(buf, exp, 0, upper, parts) + }; + Formatted { sign, parts } + } + } +} + +/// Returns a rather crude approximation (upper bound) for the maximum buffer size +/// calculated from the given decoded exponent. +/// +/// The exact limit is: +/// +/// - when `exp < 0`, the maximum length is `ceil(log_10 (5^-exp * (2^64 - 1)))`. +/// - when `exp >= 0`, the maximum length is `ceil(log_10 (2^exp * (2^64 - 1)))`. +/// +/// `ceil(log_10 (x^exp * (2^64 - 1)))` is less than `ceil(log_10 (2^64 - 1)) + +/// ceil(exp * log_10 x)`, which is in turn less than `20 + (1 + exp * log_10 x)`. +/// We use the facts that `log_10 2 < 5/16` and `log_10 5 < 12/16`, which is +/// enough for our purposes. +/// +/// Why do we need this? `format_exact` functions will fill the entire buffer +/// unless limited by the last digit restriction, but it is possible that +/// the number of digits requested is ridiculously large (say, 30,000 digits). +/// The vast majority of buffer will be filled with zeroes, so we don't want to +/// allocate all the buffer beforehand. Consequently, for any given arguments, +/// 826 bytes of buffer should be sufficient for `f64`. Compare this with +/// the actual number for the worst case: 770 bytes (when `exp = -1074`). +fn estimate_max_buf_len(exp: i16) -> usize { + 21 + ((if exp < 0 { -12 } else { 5 } * exp as i32) as usize >> 4) +} + +/// Formats given floating point number into the exponential form with +/// exactly given number of significant digits. The result is stored to +/// the supplied parts array while utilizing given byte buffer as a scratch. +/// `upper` is used to determine the case of the exponent prefix (`e` or `E`). +/// The first part to be rendered is always a `Part::Sign` (which can be +/// an empty string if no sign is rendered). +/// +/// `format_exact` should be the underlying digit-generation function. +/// It should return the part of the buffer that it initialized. +/// You probably would want `strategy::grisu::format_exact` for this. +/// +/// The byte buffer should be at least `ndigits` bytes long unless `ndigits` is +/// so large that only the fixed number of digits will be ever written. +/// (The tipping point for `f64` is about 800, so 1000 bytes should be enough.) +/// There should be at least 6 parts available, due to the worst case like +/// `[+][1][.][2345][e][-][6]`. +pub fn to_exact_exp_str<'a, T, F>( + mut format_exact: F, + v: T, + sign: Sign, + ndigits: usize, + upper: bool, + buf: &'a mut [MaybeUninit], + parts: &'a mut [MaybeUninit>], +) -> Formatted<'a> +where + T: DecodableFloat, + F: FnMut(&Decoded, &'a mut [MaybeUninit], i16) -> (&'a [u8], i16), +{ + assert!(parts.len() >= 6); + assert!(ndigits > 0); + + let (negative, full_decoded) = decode(v); + let sign = determine_sign(sign, &full_decoded, negative); + match full_decoded { + FullDecoded::Nan => { + parts[0] = MaybeUninit::new(Part::Copy(b"NaN")); + // SAFETY: we just initialized the elements `..1`. + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + } + FullDecoded::Infinite => { + parts[0] = MaybeUninit::new(Part::Copy(b"inf")); + // SAFETY: we just initialized the elements `..1`. + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + } + FullDecoded::Zero => { + if ndigits > 1 { + // [0.][0000][e0] + parts[0] = MaybeUninit::new(Part::Copy(b"0.")); + parts[1] = MaybeUninit::new(Part::Zero(ndigits - 1)); + parts[2] = MaybeUninit::new(Part::Copy(if upper { b"E0" } else { b"e0" })); + Formatted { + sign, + // SAFETY: we just initialized the elements `..3`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) }, + } + } else { + parts[0] = MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" })); + Formatted { + sign, + // SAFETY: we just initialized the elements `..1`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) }, + } + } + } + FullDecoded::Finite(ref decoded) => { + let maxlen = estimate_max_buf_len(decoded.exp); + assert!(buf.len() >= ndigits || buf.len() >= maxlen); + + let trunc = if ndigits < maxlen { ndigits } else { maxlen }; + let (buf, exp) = format_exact(decoded, &mut buf[..trunc], i16::MIN); + Formatted { sign, parts: digits_to_exp_str(buf, exp, ndigits, upper, parts) } + } + } +} + +/// Formats given floating point number into the decimal form with exactly +/// given number of fractional digits. The result is stored to the supplied parts +/// array while utilizing given byte buffer as a scratch. `upper` is currently +/// unused but left for the future decision to change the case of non-finite values, +/// i.e., `inf` and `nan`. The first part to be rendered is always a `Part::Sign` +/// (which can be an empty string if no sign is rendered). +/// +/// `format_exact` should be the underlying digit-generation function. +/// It should return the part of the buffer that it initialized. +/// You probably would want `strategy::grisu::format_exact` for this. +/// +/// The byte buffer should be enough for the output unless `frac_digits` is +/// so large that only the fixed number of digits will be ever written. +/// (The tipping point for `f64` is about 800, and 1000 bytes should be enough.) +/// There should be at least 4 parts available, due to the worst case like +/// `[+][0.][0000][2][0000]` with `frac_digits = 10`. +pub fn to_exact_fixed_str<'a, T, F>( + mut format_exact: F, + v: T, + sign: Sign, + frac_digits: usize, + buf: &'a mut [MaybeUninit], + parts: &'a mut [MaybeUninit>], +) -> Formatted<'a> +where + T: DecodableFloat, + F: FnMut(&Decoded, &'a mut [MaybeUninit], i16) -> (&'a [u8], i16), +{ + assert!(parts.len() >= 4); + + let (negative, full_decoded) = decode(v); + let sign = determine_sign(sign, &full_decoded, negative); + match full_decoded { + FullDecoded::Nan => { + parts[0] = MaybeUninit::new(Part::Copy(b"NaN")); + // SAFETY: we just initialized the elements `..1`. + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + } + FullDecoded::Infinite => { + parts[0] = MaybeUninit::new(Part::Copy(b"inf")); + // SAFETY: we just initialized the elements `..1`. + Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } } + } + FullDecoded::Zero => { + if frac_digits > 0 { + // [0.][0000] + parts[0] = MaybeUninit::new(Part::Copy(b"0.")); + parts[1] = MaybeUninit::new(Part::Zero(frac_digits)); + Formatted { + sign, + // SAFETY: we just initialized the elements `..2`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) }, + } + } else { + parts[0] = MaybeUninit::new(Part::Copy(b"0")); + Formatted { + sign, + // SAFETY: we just initialized the elements `..1`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) }, + } + } + } + FullDecoded::Finite(ref decoded) => { + let maxlen = estimate_max_buf_len(decoded.exp); + assert!(buf.len() >= maxlen); + + // it *is* possible that `frac_digits` is ridiculously large. + // `format_exact` will end rendering digits much earlier in this case, + // because we are strictly limited by `maxlen`. + let limit = if frac_digits < 0x8000 { -(frac_digits as i16) } else { i16::MIN }; + let (buf, exp) = format_exact(decoded, &mut buf[..maxlen], limit); + if exp <= limit { + // the restriction couldn't been met, so this should render like zero no matter + // `exp` was. this does not include the case that the restriction has been met + // only after the final rounding-up; it's a regular case with `exp = limit + 1`. + debug_assert_eq!(buf.len(), 0); + if frac_digits > 0 { + // [0.][0000] + parts[0] = MaybeUninit::new(Part::Copy(b"0.")); + parts[1] = MaybeUninit::new(Part::Zero(frac_digits)); + Formatted { + sign, + // SAFETY: we just initialized the elements `..2`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) }, + } + } else { + parts[0] = MaybeUninit::new(Part::Copy(b"0")); + Formatted { + sign, + // SAFETY: we just initialized the elements `..1`. + parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) }, + } + } + } else { + Formatted { sign, parts: digits_to_dec_str(buf, exp, frac_digits, parts) } + } + } + } +} diff --git a/CoqOfRust/core/num/flt2dec/strategy/dragon.rs b/CoqOfRust/core/num/flt2dec/strategy/dragon.rs new file mode 100644 index 000000000..e801f07b3 --- /dev/null +++ b/CoqOfRust/core/num/flt2dec/strategy/dragon.rs @@ -0,0 +1,389 @@ +//! Almost direct (but slightly optimized) Rust translation of Figure 3 of "Printing +//! Floating-Point Numbers Quickly and Accurately"[^1]. +//! +//! [^1]: Burger, R. G. and Dybvig, R. K. 1996. Printing floating-point numbers +//! quickly and accurately. SIGPLAN Not. 31, 5 (May. 1996), 108-116. + +use crate::cmp::Ordering; +use crate::mem::MaybeUninit; +use crate::num::bignum::{Big32x40 as Big, Digit32 as Digit}; +use crate::num::flt2dec::estimator::estimate_scaling_factor; +use crate::num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up}; + +static POW10: [Digit; 10] = + [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]; +// precalculated arrays of `Digit`s for 5^(2^n). +static POW5TO16: [Digit; 2] = [0x86f26fc1, 0x23]; +static POW5TO32: [Digit; 3] = [0x85acef81, 0x2d6d415b, 0x4ee]; +static POW5TO64: [Digit; 5] = [0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x184f03]; +static POW5TO128: [Digit; 10] = [ + 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da, 0xa6337f19, + 0xe91f2603, 0x24e, +]; +static POW5TO256: [Digit; 19] = [ + 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70, 0xd595d80f, 0x26b2716e, + 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17, 0x55bc28f2, 0x80dcc7f7, + 0xf46eeddc, 0x5fdcefce, 0x553f7, +]; + +#[doc(hidden)] +pub fn mul_pow10(x: &mut Big, n: usize) -> &mut Big { + debug_assert!(n < 512); + // Save ourself the left shift for the smallest cases. + if n < 8 { + return x.mul_small(POW10[n & 7]); + } + // Multiply by the powers of 5 and shift the 2s in at the end. + // This keeps the intermediate products smaller and faster. + if n & 7 != 0 { + x.mul_small(POW10[n & 7] >> (n & 7)); + } + if n & 8 != 0 { + x.mul_small(POW10[8] >> 8); + } + if n & 16 != 0 { + x.mul_digits(&POW5TO16); + } + if n & 32 != 0 { + x.mul_digits(&POW5TO32); + } + if n & 64 != 0 { + x.mul_digits(&POW5TO64); + } + if n & 128 != 0 { + x.mul_digits(&POW5TO128); + } + if n & 256 != 0 { + x.mul_digits(&POW5TO256); + } + x.mul_pow2(n) +} + +fn div_2pow10(x: &mut Big, mut n: usize) -> &mut Big { + let largest = POW10.len() - 1; + while n > largest { + x.div_rem_small(POW10[largest]); + n -= largest; + } + x.div_rem_small(POW10[n] << 1); + x +} + +// only usable when `x < 16 * scale`; `scaleN` should be `scale.mul_small(N)` +fn div_rem_upto_16<'a>( + x: &'a mut Big, + scale: &Big, + scale2: &Big, + scale4: &Big, + scale8: &Big, +) -> (u8, &'a mut Big) { + let mut d = 0; + if *x >= *scale8 { + x.sub(scale8); + d += 8; + } + if *x >= *scale4 { + x.sub(scale4); + d += 4; + } + if *x >= *scale2 { + x.sub(scale2); + d += 2; + } + if *x >= *scale { + x.sub(scale); + d += 1; + } + debug_assert!(*x < *scale); + (d, x) +} + +/// The shortest mode implementation for Dragon. +pub fn format_shortest<'a>( + d: &Decoded, + buf: &'a mut [MaybeUninit], +) -> (/*digits*/ &'a [u8], /*exp*/ i16) { + // the number `v` to format is known to be: + // - equal to `mant * 2^exp`; + // - preceded by `(mant - 2 * minus) * 2^exp` in the original type; and + // - followed by `(mant + 2 * plus) * 2^exp` in the original type. + // + // obviously, `minus` and `plus` cannot be zero. (for infinities, we use out-of-range values.) + // also we assume that at least one digit is generated, i.e., `mant` cannot be zero too. + // + // this also means that any number between `low = (mant - minus) * 2^exp` and + // `high = (mant + plus) * 2^exp` will map to this exact floating point number, + // with bounds included when the original mantissa was even (i.e., `!mant_was_odd`). + + assert!(d.mant > 0); + assert!(d.minus > 0); + assert!(d.plus > 0); + assert!(d.mant.checked_add(d.plus).is_some()); + assert!(d.mant.checked_sub(d.minus).is_some()); + assert!(buf.len() >= MAX_SIG_DIGITS); + + // `a.cmp(&b) < rounding` is `if d.inclusive {a <= b} else {a < b}` + let rounding = if d.inclusive { Ordering::Greater } else { Ordering::Equal }; + + // estimate `k_0` from original inputs satisfying `10^(k_0-1) < high <= 10^(k_0+1)`. + // the tight bound `k` satisfying `10^(k-1) < high <= 10^k` is calculated later. + let mut k = estimate_scaling_factor(d.mant + d.plus, d.exp); + + // convert `{mant, plus, minus} * 2^exp` into the fractional form so that: + // - `v = mant / scale` + // - `low = (mant - minus) / scale` + // - `high = (mant + plus) / scale` + let mut mant = Big::from_u64(d.mant); + let mut minus = Big::from_u64(d.minus); + let mut plus = Big::from_u64(d.plus); + let mut scale = Big::from_small(1); + if d.exp < 0 { + scale.mul_pow2(-d.exp as usize); + } else { + mant.mul_pow2(d.exp as usize); + minus.mul_pow2(d.exp as usize); + plus.mul_pow2(d.exp as usize); + } + + // divide `mant` by `10^k`. now `scale / 10 < mant + plus <= scale * 10`. + if k >= 0 { + mul_pow10(&mut scale, k as usize); + } else { + mul_pow10(&mut mant, -k as usize); + mul_pow10(&mut minus, -k as usize); + mul_pow10(&mut plus, -k as usize); + } + + // fixup when `mant + plus > scale` (or `>=`). + // we are not actually modifying `scale`, since we can skip the initial multiplication instead. + // now `scale < mant + plus <= scale * 10` and we are ready to generate digits. + // + // note that `d[0]` *can* be zero, when `scale - plus < mant < scale`. + // in this case rounding-up condition (`up` below) will be triggered immediately. + if scale.cmp(mant.clone().add(&plus)) < rounding { + // equivalent to scaling `scale` by 10 + k += 1; + } else { + mant.mul_small(10); + minus.mul_small(10); + plus.mul_small(10); + } + + // cache `(2, 4, 8) * scale` for digit generation. + let mut scale2 = scale.clone(); + scale2.mul_pow2(1); + let mut scale4 = scale.clone(); + scale4.mul_pow2(2); + let mut scale8 = scale.clone(); + scale8.mul_pow2(3); + + let mut down; + let mut up; + let mut i = 0; + loop { + // invariants, where `d[0..n-1]` are digits generated so far: + // - `v = mant / scale * 10^(k-n-1) + d[0..n-1] * 10^(k-n)` + // - `v - low = minus / scale * 10^(k-n-1)` + // - `high - v = plus / scale * 10^(k-n-1)` + // - `(mant + plus) / scale <= 10` (thus `mant / scale < 10`) + // where `d[i..j]` is a shorthand for `d[i] * 10^(j-i) + ... + d[j-1] * 10 + d[j]`. + + // generate one digit: `d[n] = floor(mant / scale) < 10`. + let (d, _) = div_rem_upto_16(&mut mant, &scale, &scale2, &scale4, &scale8); + debug_assert!(d < 10); + buf[i] = MaybeUninit::new(b'0' + d); + i += 1; + + // this is a simplified description of the modified Dragon algorithm. + // many intermediate derivations and completeness arguments are omitted for convenience. + // + // start with modified invariants, as we've updated `n`: + // - `v = mant / scale * 10^(k-n) + d[0..n-1] * 10^(k-n)` + // - `v - low = minus / scale * 10^(k-n)` + // - `high - v = plus / scale * 10^(k-n)` + // + // assume that `d[0..n-1]` is the shortest representation between `low` and `high`, + // i.e., `d[0..n-1]` satisfies both of the following but `d[0..n-2]` doesn't: + // - `low < d[0..n-1] * 10^(k-n) < high` (bijectivity: digits round to `v`); and + // - `abs(v / 10^(k-n) - d[0..n-1]) <= 1/2` (the last digit is correct). + // + // the second condition simplifies to `2 * mant <= scale`. + // solving invariants in terms of `mant`, `low` and `high` yields + // a simpler version of the first condition: `-plus < mant < minus`. + // since `-plus < 0 <= mant`, we have the correct shortest representation + // when `mant < minus` and `2 * mant <= scale`. + // (the former becomes `mant <= minus` when the original mantissa is even.) + // + // when the second doesn't hold (`2 * mant > scale`), we need to increase the last digit. + // this is enough for restoring that condition: we already know that + // the digit generation guarantees `0 <= v / 10^(k-n) - d[0..n-1] < 1`. + // in this case, the first condition becomes `-plus < mant - scale < minus`. + // since `mant < scale` after the generation, we have `scale < mant + plus`. + // (again, this becomes `scale <= mant + plus` when the original mantissa is even.) + // + // in short: + // - stop and round `down` (keep digits as is) when `mant < minus` (or `<=`). + // - stop and round `up` (increase the last digit) when `scale < mant + plus` (or `<=`). + // - keep generating otherwise. + down = mant.cmp(&minus) < rounding; + up = scale.cmp(mant.clone().add(&plus)) < rounding; + if down || up { + break; + } // we have the shortest representation, proceed to the rounding + + // restore the invariants. + // this makes the algorithm always terminating: `minus` and `plus` always increases, + // but `mant` is clipped modulo `scale` and `scale` is fixed. + mant.mul_small(10); + minus.mul_small(10); + plus.mul_small(10); + } + + // rounding up happens when + // i) only the rounding-up condition was triggered, or + // ii) both conditions were triggered and tie breaking prefers rounding up. + if up && (!down || *mant.mul_pow2(1) >= scale) { + // if rounding up changes the length, the exponent should also change. + // it seems that this condition is very hard to satisfy (possibly impossible), + // but we are just being safe and consistent here. + // SAFETY: we initialized that memory above. + if let Some(c) = round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) }) { + buf[i] = MaybeUninit::new(c); + i += 1; + k += 1; + } + } + + // SAFETY: we initialized that memory above. + (unsafe { MaybeUninit::slice_assume_init_ref(&buf[..i]) }, k) +} + +/// The exact and fixed mode implementation for Dragon. +pub fn format_exact<'a>( + d: &Decoded, + buf: &'a mut [MaybeUninit], + limit: i16, +) -> (/*digits*/ &'a [u8], /*exp*/ i16) { + assert!(d.mant > 0); + assert!(d.minus > 0); + assert!(d.plus > 0); + assert!(d.mant.checked_add(d.plus).is_some()); + assert!(d.mant.checked_sub(d.minus).is_some()); + + // estimate `k_0` from original inputs satisfying `10^(k_0-1) < v <= 10^(k_0+1)`. + let mut k = estimate_scaling_factor(d.mant, d.exp); + + // `v = mant / scale`. + let mut mant = Big::from_u64(d.mant); + let mut scale = Big::from_small(1); + if d.exp < 0 { + scale.mul_pow2(-d.exp as usize); + } else { + mant.mul_pow2(d.exp as usize); + } + + // divide `mant` by `10^k`. now `scale / 10 < mant <= scale * 10`. + if k >= 0 { + mul_pow10(&mut scale, k as usize); + } else { + mul_pow10(&mut mant, -k as usize); + } + + // fixup when `mant + plus >= scale`, where `plus / scale = 10^-buf.len() / 2`. + // in order to keep the fixed-size bignum, we actually use `mant + floor(plus) >= scale`. + // we are not actually modifying `scale`, since we can skip the initial multiplication instead. + // again with the shortest algorithm, `d[0]` can be zero but will be eventually rounded up. + if *div_2pow10(&mut scale.clone(), buf.len()).add(&mant) >= scale { + // equivalent to scaling `scale` by 10 + k += 1; + } else { + mant.mul_small(10); + } + + // if we are working with the last-digit limitation, we need to shorten the buffer + // before the actual rendering in order to avoid double rounding. + // note that we have to enlarge the buffer again when rounding up happens! + let mut len = if k < limit { + // oops, we cannot even produce *one* digit. + // this is possible when, say, we've got something like 9.5 and it's being rounded to 10. + // we return an empty buffer, with an exception of the later rounding-up case + // which occurs when `k == limit` and has to produce exactly one digit. + 0 + } else if ((k as i32 - limit as i32) as usize) < buf.len() { + (k - limit) as usize + } else { + buf.len() + }; + + if len > 0 { + // cache `(2, 4, 8) * scale` for digit generation. + // (this can be expensive, so do not calculate them when the buffer is empty.) + let mut scale2 = scale.clone(); + scale2.mul_pow2(1); + let mut scale4 = scale.clone(); + scale4.mul_pow2(2); + let mut scale8 = scale.clone(); + scale8.mul_pow2(3); + + for i in 0..len { + if mant.is_zero() { + // following digits are all zeroes, we stop here + // do *not* try to perform rounding! rather, fill remaining digits. + for c in &mut buf[i..len] { + *c = MaybeUninit::new(b'0'); + } + // SAFETY: we initialized that memory above. + return (unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, k); + } + + let mut d = 0; + if mant >= scale8 { + mant.sub(&scale8); + d += 8; + } + if mant >= scale4 { + mant.sub(&scale4); + d += 4; + } + if mant >= scale2 { + mant.sub(&scale2); + d += 2; + } + if mant >= scale { + mant.sub(&scale); + d += 1; + } + debug_assert!(mant < scale); + debug_assert!(d < 10); + buf[i] = MaybeUninit::new(b'0' + d); + mant.mul_small(10); + } + } + + // rounding up if we stop in the middle of digits + // if the following digits are exactly 5000..., check the prior digit and try to + // round to even (i.e., avoid rounding up when the prior digit is even). + let order = mant.cmp(scale.mul_small(5)); + if order == Ordering::Greater + || (order == Ordering::Equal + // SAFETY: `buf[len-1]` is initialized. + && len > 0 && unsafe { buf[len - 1].assume_init() } & 1 == 1) + { + // if rounding up changes the length, the exponent should also change. + // but we've been requested a fixed number of digits, so do not alter the buffer... + // SAFETY: we initialized that memory above. + if let Some(c) = round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..len]) }) { + // ...unless we've been requested the fixed precision instead. + // we also need to check that, if the original buffer was empty, + // the additional digit can only be added when `k == limit` (edge case). + k += 1; + if k > limit && len < buf.len() { + buf[len] = MaybeUninit::new(c); + len += 1; + } + } + } + + // SAFETY: we initialized that memory above. + (unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, k) +} diff --git a/CoqOfRust/core/num/flt2dec/strategy/grisu.rs b/CoqOfRust/core/num/flt2dec/strategy/grisu.rs new file mode 100644 index 000000000..bdf544a41 --- /dev/null +++ b/CoqOfRust/core/num/flt2dec/strategy/grisu.rs @@ -0,0 +1,776 @@ +//! Rust adaptation of the Grisu3 algorithm described in "Printing Floating-Point Numbers Quickly +//! and Accurately with Integers"[^1]. It uses about 1KB of precomputed table, and in turn, it's +//! very quick for most inputs. +//! +//! [^1]: Florian Loitsch. 2010. Printing floating-point numbers quickly and +//! accurately with integers. SIGPLAN Not. 45, 6 (June 2010), 233-243. + +use crate::mem::MaybeUninit; +use crate::num::diy_float::Fp; +use crate::num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up}; + +// see the comments in `format_shortest_opt` for the rationale. +#[doc(hidden)] +pub const ALPHA: i16 = -60; +#[doc(hidden)] +pub const GAMMA: i16 = -32; + +/* +# the following Python code generates this table: +for i in xrange(-308, 333, 8): + if i >= 0: f = 10**i; e = 0 + else: f = 2**(80-4*i) // 10**-i; e = 4 * i - 80 + l = f.bit_length() + f = ((f << 64 >> (l-1)) + 1) >> 1; e += l - 64 + print ' (%#018x, %5d, %4d),' % (f, e, i) +*/ + +#[doc(hidden)] +pub static CACHED_POW10: [(u64, i16, i16); 81] = [ + // (f, e, k) + (0xe61acf033d1a45df, -1087, -308), + (0xab70fe17c79ac6ca, -1060, -300), + (0xff77b1fcbebcdc4f, -1034, -292), + (0xbe5691ef416bd60c, -1007, -284), + (0x8dd01fad907ffc3c, -980, -276), + (0xd3515c2831559a83, -954, -268), + (0x9d71ac8fada6c9b5, -927, -260), + (0xea9c227723ee8bcb, -901, -252), + (0xaecc49914078536d, -874, -244), + (0x823c12795db6ce57, -847, -236), + (0xc21094364dfb5637, -821, -228), + (0x9096ea6f3848984f, -794, -220), + (0xd77485cb25823ac7, -768, -212), + (0xa086cfcd97bf97f4, -741, -204), + (0xef340a98172aace5, -715, -196), + (0xb23867fb2a35b28e, -688, -188), + (0x84c8d4dfd2c63f3b, -661, -180), + (0xc5dd44271ad3cdba, -635, -172), + (0x936b9fcebb25c996, -608, -164), + (0xdbac6c247d62a584, -582, -156), + (0xa3ab66580d5fdaf6, -555, -148), + (0xf3e2f893dec3f126, -529, -140), + (0xb5b5ada8aaff80b8, -502, -132), + (0x87625f056c7c4a8b, -475, -124), + (0xc9bcff6034c13053, -449, -116), + (0x964e858c91ba2655, -422, -108), + (0xdff9772470297ebd, -396, -100), + (0xa6dfbd9fb8e5b88f, -369, -92), + (0xf8a95fcf88747d94, -343, -84), + (0xb94470938fa89bcf, -316, -76), + (0x8a08f0f8bf0f156b, -289, -68), + (0xcdb02555653131b6, -263, -60), + (0x993fe2c6d07b7fac, -236, -52), + (0xe45c10c42a2b3b06, -210, -44), + (0xaa242499697392d3, -183, -36), + (0xfd87b5f28300ca0e, -157, -28), + (0xbce5086492111aeb, -130, -20), + (0x8cbccc096f5088cc, -103, -12), + (0xd1b71758e219652c, -77, -4), + (0x9c40000000000000, -50, 4), + (0xe8d4a51000000000, -24, 12), + (0xad78ebc5ac620000, 3, 20), + (0x813f3978f8940984, 30, 28), + (0xc097ce7bc90715b3, 56, 36), + (0x8f7e32ce7bea5c70, 83, 44), + (0xd5d238a4abe98068, 109, 52), + (0x9f4f2726179a2245, 136, 60), + (0xed63a231d4c4fb27, 162, 68), + (0xb0de65388cc8ada8, 189, 76), + (0x83c7088e1aab65db, 216, 84), + (0xc45d1df942711d9a, 242, 92), + (0x924d692ca61be758, 269, 100), + (0xda01ee641a708dea, 295, 108), + (0xa26da3999aef774a, 322, 116), + (0xf209787bb47d6b85, 348, 124), + (0xb454e4a179dd1877, 375, 132), + (0x865b86925b9bc5c2, 402, 140), + (0xc83553c5c8965d3d, 428, 148), + (0x952ab45cfa97a0b3, 455, 156), + (0xde469fbd99a05fe3, 481, 164), + (0xa59bc234db398c25, 508, 172), + (0xf6c69a72a3989f5c, 534, 180), + (0xb7dcbf5354e9bece, 561, 188), + (0x88fcf317f22241e2, 588, 196), + (0xcc20ce9bd35c78a5, 614, 204), + (0x98165af37b2153df, 641, 212), + (0xe2a0b5dc971f303a, 667, 220), + (0xa8d9d1535ce3b396, 694, 228), + (0xfb9b7cd9a4a7443c, 720, 236), + (0xbb764c4ca7a44410, 747, 244), + (0x8bab8eefb6409c1a, 774, 252), + (0xd01fef10a657842c, 800, 260), + (0x9b10a4e5e9913129, 827, 268), + (0xe7109bfba19c0c9d, 853, 276), + (0xac2820d9623bf429, 880, 284), + (0x80444b5e7aa7cf85, 907, 292), + (0xbf21e44003acdd2d, 933, 300), + (0x8e679c2f5e44ff8f, 960, 308), + (0xd433179d9c8cb841, 986, 316), + (0x9e19db92b4e31ba9, 1013, 324), + (0xeb96bf6ebadf77d9, 1039, 332), +]; + +#[doc(hidden)] +pub const CACHED_POW10_FIRST_E: i16 = -1087; +#[doc(hidden)] +pub const CACHED_POW10_LAST_E: i16 = 1039; + +#[doc(hidden)] +pub fn cached_power(alpha: i16, gamma: i16) -> (i16, Fp) { + let offset = CACHED_POW10_FIRST_E as i32; + let range = (CACHED_POW10.len() as i32) - 1; + let domain = (CACHED_POW10_LAST_E - CACHED_POW10_FIRST_E) as i32; + let idx = ((gamma as i32) - offset) * range / domain; + let (f, e, k) = CACHED_POW10[idx as usize]; + debug_assert!(alpha <= e && e <= gamma); + (k, Fp { f, e }) +} + +/// Given `x > 0`, returns `(k, 10^k)` such that `10^k <= x < 10^(k+1)`. +#[doc(hidden)] +pub fn max_pow10_no_more_than(x: u32) -> (u8, u32) { + debug_assert!(x > 0); + + const X9: u32 = 10_0000_0000; + const X8: u32 = 1_0000_0000; + const X7: u32 = 1000_0000; + const X6: u32 = 100_0000; + const X5: u32 = 10_0000; + const X4: u32 = 1_0000; + const X3: u32 = 1000; + const X2: u32 = 100; + const X1: u32 = 10; + + if x < X4 { + if x < X2 { + if x < X1 { (0, 1) } else { (1, X1) } + } else { + if x < X3 { (2, X2) } else { (3, X3) } + } + } else { + if x < X6 { + if x < X5 { (4, X4) } else { (5, X5) } + } else if x < X8 { + if x < X7 { (6, X6) } else { (7, X7) } + } else { + if x < X9 { (8, X8) } else { (9, X9) } + } + } +} + +/// The shortest mode implementation for Grisu. +/// +/// It returns `None` when it would return an inexact representation otherwise. +pub fn format_shortest_opt<'a>( + d: &Decoded, + buf: &'a mut [MaybeUninit], +) -> Option<(/*digits*/ &'a [u8], /*exp*/ i16)> { + assert!(d.mant > 0); + assert!(d.minus > 0); + assert!(d.plus > 0); + assert!(d.mant.checked_add(d.plus).is_some()); + assert!(d.mant.checked_sub(d.minus).is_some()); + assert!(buf.len() >= MAX_SIG_DIGITS); + assert!(d.mant + d.plus < (1 << 61)); // we need at least three bits of additional precision + + // start with the normalized values with the shared exponent + let plus = Fp { f: d.mant + d.plus, e: d.exp }.normalize(); + let minus = Fp { f: d.mant - d.minus, e: d.exp }.normalize_to(plus.e); + let v = Fp { f: d.mant, e: d.exp }.normalize_to(plus.e); + + // find any `cached = 10^minusk` such that `ALPHA <= minusk + plus.e + 64 <= GAMMA`. + // since `plus` is normalized, this means `2^(62 + ALPHA) <= plus * cached < 2^(64 + GAMMA)`; + // given our choices of `ALPHA` and `GAMMA`, this puts `plus * cached` into `[4, 2^32)`. + // + // it is obviously desirable to maximize `GAMMA - ALPHA`, + // so that we don't need many cached powers of 10, but there are some considerations: + // + // 1. we want to keep `floor(plus * cached)` within `u32` since it needs a costly division. + // (this is not really avoidable, remainder is required for accuracy estimation.) + // 2. the remainder of `floor(plus * cached)` repeatedly gets multiplied by 10, + // and it should not overflow. + // + // the first gives `64 + GAMMA <= 32`, while the second gives `10 * 2^-ALPHA <= 2^64`; + // -60 and -32 is the maximal range with this constraint, and V8 also uses them. + let (minusk, cached) = cached_power(ALPHA - plus.e - 64, GAMMA - plus.e - 64); + + // scale fps. this gives the maximal error of 1 ulp (proved from Theorem 5.1). + let plus = plus.mul(&cached); + let minus = minus.mul(&cached); + let v = v.mul(&cached); + debug_assert_eq!(plus.e, minus.e); + debug_assert_eq!(plus.e, v.e); + + // +- actual range of minus + // | <---|---------------------- unsafe region --------------------------> | + // | | | + // | |<--->| | <--------------- safe region ---------------> | | + // | | | | | | + // |1 ulp|1 ulp| |1 ulp|1 ulp| |1 ulp|1 ulp| + // |<--->|<--->| |<--->|<--->| |<--->|<--->| + // |-----|-----|-------...-------|-----|-----|-------...-------|-----|-----| + // | minus | | v | | plus | + // minus1 minus0 v - 1 ulp v + 1 ulp plus0 plus1 + // + // above `minus`, `v` and `plus` are *quantized* approximations (error < 1 ulp). + // as we don't know the error is positive or negative, we use two approximations spaced equally + // and have the maximal error of 2 ulps. + // + // the "unsafe region" is a liberal interval which we initially generate. + // the "safe region" is a conservative interval which we only accept. + // we start with the correct repr within the unsafe region, and try to find the closest repr + // to `v` which is also within the safe region. if we can't, we give up. + let plus1 = plus.f + 1; + // let plus0 = plus.f - 1; // only for explanation + // let minus0 = minus.f + 1; // only for explanation + let minus1 = minus.f - 1; + let e = -plus.e as usize; // shared exponent + + // divide `plus1` into integral and fractional parts. + // integral parts are guaranteed to fit in u32, since cached power guarantees `plus < 2^32` + // and normalized `plus.f` is always less than `2^64 - 2^4` due to the precision requirement. + let plus1int = (plus1 >> e) as u32; + let plus1frac = plus1 & ((1 << e) - 1); + + // calculate the largest `10^max_kappa` no more than `plus1` (thus `plus1 < 10^(max_kappa+1)`). + // this is an upper bound of `kappa` below. + let (max_kappa, max_ten_kappa) = max_pow10_no_more_than(plus1int); + + let mut i = 0; + let exp = max_kappa as i16 - minusk + 1; + + // Theorem 6.2: if `k` is the greatest integer s.t. `0 <= y mod 10^k <= y - x`, + // then `V = floor(y / 10^k) * 10^k` is in `[x, y]` and one of the shortest + // representations (with the minimal number of significant digits) in that range. + // + // find the digit length `kappa` between `(minus1, plus1)` as per Theorem 6.2. + // Theorem 6.2 can be adopted to exclude `x` by requiring `y mod 10^k < y - x` instead. + // (e.g., `x` = 32000, `y` = 32777; `kappa` = 2 since `y mod 10^3 = 777 < y - x = 777`.) + // the algorithm relies on the later verification phase to exclude `y`. + let delta1 = plus1 - minus1; + // let delta1int = (delta1 >> e) as usize; // only for explanation + let delta1frac = delta1 & ((1 << e) - 1); + + // render integral parts, while checking for the accuracy at each step. + let mut ten_kappa = max_ten_kappa; // 10^kappa + let mut remainder = plus1int; // digits yet to be rendered + loop { + // we always have at least one digit to render, as `plus1 >= 10^kappa` + // invariants: + // - `delta1int <= remainder < 10^(kappa+1)` + // - `plus1int = d[0..n-1] * 10^(kappa+1) + remainder` + // (it follows that `remainder = plus1int % 10^(kappa+1)`) + + // divide `remainder` by `10^kappa`. both are scaled by `2^-e`. + let q = remainder / ten_kappa; + let r = remainder % ten_kappa; + debug_assert!(q < 10); + buf[i] = MaybeUninit::new(b'0' + q as u8); + i += 1; + + let plus1rem = ((r as u64) << e) + plus1frac; // == (plus1 % 10^kappa) * 2^e + if plus1rem < delta1 { + // `plus1 % 10^kappa < delta1 = plus1 - minus1`; we've found the correct `kappa`. + let ten_kappa = (ten_kappa as u64) << e; // scale 10^kappa back to the shared exponent + return round_and_weed( + // SAFETY: we initialized that memory above. + unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) }, + exp, + plus1rem, + delta1, + plus1 - v.f, + ten_kappa, + 1, + ); + } + + // break the loop when we have rendered all integral digits. + // the exact number of digits is `max_kappa + 1` as `plus1 < 10^(max_kappa+1)`. + if i > max_kappa as usize { + debug_assert_eq!(ten_kappa, 1); + break; + } + + // restore invariants + ten_kappa /= 10; + remainder = r; + } + + // render fractional parts, while checking for the accuracy at each step. + // this time we rely on repeated multiplications, as division will lose the precision. + let mut remainder = plus1frac; + let mut threshold = delta1frac; + let mut ulp = 1; + loop { + // the next digit should be significant as we've tested that before breaking out + // invariants, where `m = max_kappa + 1` (# of digits in the integral part): + // - `remainder < 2^e` + // - `plus1frac * 10^(n-m) = d[m..n-1] * 2^e + remainder` + + remainder *= 10; // won't overflow, `2^e * 10 < 2^64` + threshold *= 10; + ulp *= 10; + + // divide `remainder` by `10^kappa`. + // both are scaled by `2^e / 10^kappa`, so the latter is implicit here. + let q = remainder >> e; + let r = remainder & ((1 << e) - 1); + debug_assert!(q < 10); + buf[i] = MaybeUninit::new(b'0' + q as u8); + i += 1; + + if r < threshold { + let ten_kappa = 1 << e; // implicit divisor + return round_and_weed( + // SAFETY: we initialized that memory above. + unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) }, + exp, + r, + threshold, + (plus1 - v.f) * ulp, + ten_kappa, + ulp, + ); + } + + // restore invariants + remainder = r; + } + + // we've generated all significant digits of `plus1`, but not sure if it's the optimal one. + // for example, if `minus1` is 3.14153... and `plus1` is 3.14158..., there are 5 different + // shortest representation from 3.14154 to 3.14158 but we only have the greatest one. + // we have to successively decrease the last digit and check if this is the optimal repr. + // there are at most 9 candidates (..1 to ..9), so this is fairly quick. ("rounding" phase) + // + // the function checks if this "optimal" repr is actually within the ulp ranges, + // and also, it is possible that the "second-to-optimal" repr can actually be optimal + // due to the rounding error. in either cases this returns `None`. ("weeding" phase) + // + // all arguments here are scaled by the common (but implicit) value `k`, so that: + // - `remainder = (plus1 % 10^kappa) * k` + // - `threshold = (plus1 - minus1) * k` (and also, `remainder < threshold`) + // - `plus1v = (plus1 - v) * k` (and also, `threshold > plus1v` from prior invariants) + // - `ten_kappa = 10^kappa * k` + // - `ulp = 2^-e * k` + fn round_and_weed( + buf: &mut [u8], + exp: i16, + remainder: u64, + threshold: u64, + plus1v: u64, + ten_kappa: u64, + ulp: u64, + ) -> Option<(&[u8], i16)> { + assert!(!buf.is_empty()); + + // produce two approximations to `v` (actually `plus1 - v`) within 1.5 ulps. + // the resulting representation should be the closest representation to both. + // + // here `plus1 - v` is used since calculations are done with respect to `plus1` + // in order to avoid overflow/underflow (hence the seemingly swapped names). + let plus1v_down = plus1v + ulp; // plus1 - (v - 1 ulp) + let plus1v_up = plus1v - ulp; // plus1 - (v + 1 ulp) + + // decrease the last digit and stop at the closest representation to `v + 1 ulp`. + let mut plus1w = remainder; // plus1w(n) = plus1 - w(n) + { + let last = buf.last_mut().unwrap(); + + // we work with the approximated digits `w(n)`, which is initially equal to `plus1 - + // plus1 % 10^kappa`. after running the loop body `n` times, `w(n) = plus1 - + // plus1 % 10^kappa - n * 10^kappa`. we set `plus1w(n) = plus1 - w(n) = + // plus1 % 10^kappa + n * 10^kappa` (thus `remainder = plus1w(0)`) to simplify checks. + // note that `plus1w(n)` is always increasing. + // + // we have three conditions to terminate. any of them will make the loop unable to + // proceed, but we then have at least one valid representation known to be closest to + // `v + 1 ulp` anyway. we will denote them as TC1 through TC3 for brevity. + // + // TC1: `w(n) <= v + 1 ulp`, i.e., this is the last repr that can be the closest one. + // this is equivalent to `plus1 - w(n) = plus1w(n) >= plus1 - (v + 1 ulp) = plus1v_up`. + // combined with TC2 (which checks if `w(n+1)` is valid), this prevents the possible + // overflow on the calculation of `plus1w(n)`. + // + // TC2: `w(n+1) < minus1`, i.e., the next repr definitely does not round to `v`. + // this is equivalent to `plus1 - w(n) + 10^kappa = plus1w(n) + 10^kappa > + // plus1 - minus1 = threshold`. the left hand side can overflow, but we know + // `threshold > plus1v`, so if TC1 is false, `threshold - plus1w(n) > + // threshold - (plus1v - 1 ulp) > 1 ulp` and we can safely test if + // `threshold - plus1w(n) < 10^kappa` instead. + // + // TC3: `abs(w(n) - (v + 1 ulp)) <= abs(w(n+1) - (v + 1 ulp))`, i.e., the next repr is + // no closer to `v + 1 ulp` than the current repr. given `z(n) = plus1v_up - plus1w(n)`, + // this becomes `abs(z(n)) <= abs(z(n+1))`. again assuming that TC1 is false, we have + // `z(n) > 0`. we have two cases to consider: + // + // - when `z(n+1) >= 0`: TC3 becomes `z(n) <= z(n+1)`. as `plus1w(n)` is increasing, + // `z(n)` should be decreasing and this is clearly false. + // - when `z(n+1) < 0`: + // - TC3a: the precondition is `plus1v_up < plus1w(n) + 10^kappa`. assuming TC2 is + // false, `threshold >= plus1w(n) + 10^kappa` so it cannot overflow. + // - TC3b: TC3 becomes `z(n) <= -z(n+1)`, i.e., `plus1v_up - plus1w(n) >= + // plus1w(n+1) - plus1v_up = plus1w(n) + 10^kappa - plus1v_up`. the negated TC1 + // gives `plus1v_up > plus1w(n)`, so it cannot overflow or underflow when + // combined with TC3a. + // + // consequently, we should stop when `TC1 || TC2 || (TC3a && TC3b)`. the following is + // equal to its inverse, `!TC1 && !TC2 && (!TC3a || !TC3b)`. + while plus1w < plus1v_up + && threshold - plus1w >= ten_kappa + && (plus1w + ten_kappa < plus1v_up + || plus1v_up - plus1w >= plus1w + ten_kappa - plus1v_up) + { + *last -= 1; + debug_assert!(*last > b'0'); // the shortest repr cannot end with `0` + plus1w += ten_kappa; + } + } + + // check if this representation is also the closest representation to `v - 1 ulp`. + // + // this is simply same to the terminating conditions for `v + 1 ulp`, with all `plus1v_up` + // replaced by `plus1v_down` instead. overflow analysis equally holds. + if plus1w < plus1v_down + && threshold - plus1w >= ten_kappa + && (plus1w + ten_kappa < plus1v_down + || plus1v_down - plus1w >= plus1w + ten_kappa - plus1v_down) + { + return None; + } + + // now we have the closest representation to `v` between `plus1` and `minus1`. + // this is too liberal, though, so we reject any `w(n)` not between `plus0` and `minus0`, + // i.e., `plus1 - plus1w(n) <= minus0` or `plus1 - plus1w(n) >= plus0`. we utilize the facts + // that `threshold = plus1 - minus1` and `plus1 - plus0 = minus0 - minus1 = 2 ulp`. + if 2 * ulp <= plus1w && plus1w <= threshold - 4 * ulp { Some((buf, exp)) } else { None } + } +} + +/// The shortest mode implementation for Grisu with Dragon fallback. +/// +/// This should be used for most cases. +pub fn format_shortest<'a>( + d: &Decoded, + buf: &'a mut [MaybeUninit], +) -> (/*digits*/ &'a [u8], /*exp*/ i16) { + use crate::num::flt2dec::strategy::dragon::format_shortest as fallback; + // SAFETY: The borrow checker is not smart enough to let us use `buf` + // in the second branch, so we launder the lifetime here. But we only re-use + // `buf` if `format_shortest_opt` returned `None` so this is okay. + match format_shortest_opt(d, unsafe { &mut *(buf as *mut _) }) { + Some(ret) => ret, + None => fallback(d, buf), + } +} + +/// The exact and fixed mode implementation for Grisu. +/// +/// It returns `None` when it would return an inexact representation otherwise. +pub fn format_exact_opt<'a>( + d: &Decoded, + buf: &'a mut [MaybeUninit], + limit: i16, +) -> Option<(/*digits*/ &'a [u8], /*exp*/ i16)> { + assert!(d.mant > 0); + assert!(d.mant < (1 << 61)); // we need at least three bits of additional precision + assert!(!buf.is_empty()); + + // normalize and scale `v`. + let v = Fp { f: d.mant, e: d.exp }.normalize(); + let (minusk, cached) = cached_power(ALPHA - v.e - 64, GAMMA - v.e - 64); + let v = v.mul(&cached); + + // divide `v` into integral and fractional parts. + let e = -v.e as usize; + let vint = (v.f >> e) as u32; + let vfrac = v.f & ((1 << e) - 1); + + let requested_digits = buf.len(); + + const POW10_UP_TO_9: [u32; 10] = + [1, 10, 100, 1000, 10_000, 100_000, 1_000_000, 10_000_000, 100_000_000, 1_000_000_000]; + + // We deviate from the original algorithm here and do some early checks to determine if we can satisfy requested_digits. + // If we determine that we can't, we exit early and avoid most of the heavy lifting that the algorithm otherwise does. + // + // When vfrac is zero, we can easily determine if vint can satisfy requested digits: + // If requested_digits >= 11, vint is not able to exhaust the count by itself since 10^(11 -1) > u32 max value >= vint. + // If vint < 10^(requested_digits - 1), vint cannot exhaust the count. + // Otherwise, vint might be able to exhaust the count and we need to execute the rest of the code. + if (vfrac == 0) && ((requested_digits >= 11) || (vint < POW10_UP_TO_9[requested_digits - 1])) { + return None; + } + + // both old `v` and new `v` (scaled by `10^-k`) has an error of < 1 ulp (Theorem 5.1). + // as we don't know the error is positive or negative, we use two approximations + // spaced equally and have the maximal error of 2 ulps (same to the shortest case). + // + // the goal is to find the exactly rounded series of digits that are common to + // both `v - 1 ulp` and `v + 1 ulp`, so that we are maximally confident. + // if this is not possible, we don't know which one is the correct output for `v`, + // so we give up and fall back. + // + // `err` is defined as `1 ulp * 2^e` here (same to the ulp in `vfrac`), + // and we will scale it whenever `v` gets scaled. + let mut err = 1; + + // calculate the largest `10^max_kappa` no more than `v` (thus `v < 10^(max_kappa+1)`). + // this is an upper bound of `kappa` below. + let (max_kappa, max_ten_kappa) = max_pow10_no_more_than(vint); + + let mut i = 0; + let exp = max_kappa as i16 - minusk + 1; + + // if we are working with the last-digit limitation, we need to shorten the buffer + // before the actual rendering in order to avoid double rounding. + // note that we have to enlarge the buffer again when rounding up happens! + let len = if exp <= limit { + // oops, we cannot even produce *one* digit. + // this is possible when, say, we've got something like 9.5 and it's being rounded to 10. + // + // in principle we can immediately call `possibly_round` with an empty buffer, + // but scaling `max_ten_kappa << e` by 10 can result in overflow. + // thus we are being sloppy here and widen the error range by a factor of 10. + // this will increase the false negative rate, but only very, *very* slightly; + // it can only matter noticeably when the mantissa is bigger than 60 bits. + // + // SAFETY: `len=0`, so the obligation of having initialized this memory is trivial. + return unsafe { + possibly_round(buf, 0, exp, limit, v.f / 10, (max_ten_kappa as u64) << e, err << e) + }; + } else if ((exp as i32 - limit as i32) as usize) < buf.len() { + (exp - limit) as usize + } else { + buf.len() + }; + debug_assert!(len > 0); + + // render integral parts. + // the error is entirely fractional, so we don't need to check it in this part. + let mut kappa = max_kappa as i16; + let mut ten_kappa = max_ten_kappa; // 10^kappa + let mut remainder = vint; // digits yet to be rendered + loop { + // we always have at least one digit to render + // invariants: + // - `remainder < 10^(kappa+1)` + // - `vint = d[0..n-1] * 10^(kappa+1) + remainder` + // (it follows that `remainder = vint % 10^(kappa+1)`) + + // divide `remainder` by `10^kappa`. both are scaled by `2^-e`. + let q = remainder / ten_kappa; + let r = remainder % ten_kappa; + debug_assert!(q < 10); + buf[i] = MaybeUninit::new(b'0' + q as u8); + i += 1; + + // is the buffer full? run the rounding pass with the remainder. + if i == len { + let vrem = ((r as u64) << e) + vfrac; // == (v % 10^kappa) * 2^e + // SAFETY: we have initialized `len` many bytes. + return unsafe { + possibly_round(buf, len, exp, limit, vrem, (ten_kappa as u64) << e, err << e) + }; + } + + // break the loop when we have rendered all integral digits. + // the exact number of digits is `max_kappa + 1` as `plus1 < 10^(max_kappa+1)`. + if i > max_kappa as usize { + debug_assert_eq!(ten_kappa, 1); + debug_assert_eq!(kappa, 0); + break; + } + + // restore invariants + kappa -= 1; + ten_kappa /= 10; + remainder = r; + } + + // render fractional parts. + // + // in principle we can continue to the last available digit and check for the accuracy. + // unfortunately we are working with the finite-sized integers, so we need some criterion + // to detect the overflow. V8 uses `remainder > err`, which becomes false when + // the first `i` significant digits of `v - 1 ulp` and `v` differ. however this rejects + // too many otherwise valid input. + // + // since the later phase has a correct overflow detection, we instead use tighter criterion: + // we continue til `err` exceeds `10^kappa / 2`, so that the range between `v - 1 ulp` and + // `v + 1 ulp` definitely contains two or more rounded representations. this is same to + // the first two comparisons from `possibly_round`, for the reference. + let mut remainder = vfrac; + let maxerr = 1 << (e - 1); + while err < maxerr { + // invariants, where `m = max_kappa + 1` (# of digits in the integral part): + // - `remainder < 2^e` + // - `vfrac * 10^(n-m) = d[m..n-1] * 2^e + remainder` + // - `err = 10^(n-m)` + + remainder *= 10; // won't overflow, `2^e * 10 < 2^64` + err *= 10; // won't overflow, `err * 10 < 2^e * 5 < 2^64` + + // divide `remainder` by `10^kappa`. + // both are scaled by `2^e / 10^kappa`, so the latter is implicit here. + let q = remainder >> e; + let r = remainder & ((1 << e) - 1); + debug_assert!(q < 10); + buf[i] = MaybeUninit::new(b'0' + q as u8); + i += 1; + + // is the buffer full? run the rounding pass with the remainder. + if i == len { + // SAFETY: we have initialized `len` many bytes. + return unsafe { possibly_round(buf, len, exp, limit, r, 1 << e, err) }; + } + + // restore invariants + remainder = r; + } + + // further calculation is useless (`possibly_round` definitely fails), so we give up. + return None; + + // we've generated all requested digits of `v`, which should be also same to corresponding + // digits of `v - 1 ulp`. now we check if there is a unique representation shared by + // both `v - 1 ulp` and `v + 1 ulp`; this can be either same to generated digits, or + // to the rounded-up version of those digits. if the range contains multiple representations + // of the same length, we cannot be sure and should return `None` instead. + // + // all arguments here are scaled by the common (but implicit) value `k`, so that: + // - `remainder = (v % 10^kappa) * k` + // - `ten_kappa = 10^kappa * k` + // - `ulp = 2^-e * k` + // + // SAFETY: the first `len` bytes of `buf` must be initialized. + unsafe fn possibly_round( + buf: &mut [MaybeUninit], + mut len: usize, + mut exp: i16, + limit: i16, + remainder: u64, + ten_kappa: u64, + ulp: u64, + ) -> Option<(&[u8], i16)> { + debug_assert!(remainder < ten_kappa); + + // 10^kappa + // : : :<->: : + // : : : : : + // :|1 ulp|1 ulp| : + // :|<--->|<--->| : + // ----|-----|-----|---- + // | v | + // v - 1 ulp v + 1 ulp + // + // (for the reference, the dotted line indicates the exact value for + // possible representations in given number of digits.) + // + // error is too large that there are at least three possible representations + // between `v - 1 ulp` and `v + 1 ulp`. we cannot determine which one is correct. + if ulp >= ten_kappa { + return None; + } + + // 10^kappa + // :<------->: + // : : + // : |1 ulp|1 ulp| + // : |<--->|<--->| + // ----|-----|-----|---- + // | v | + // v - 1 ulp v + 1 ulp + // + // in fact, 1/2 ulp is enough to introduce two possible representations. + // (remember that we need a unique representation for both `v - 1 ulp` and `v + 1 ulp`.) + // this won't overflow, as `ulp < ten_kappa` from the first check. + if ten_kappa - ulp <= ulp { + return None; + } + + // remainder + // :<->| : + // : | : + // :<--------- 10^kappa ---------->: + // | : | : + // |1 ulp|1 ulp| : + // |<--->|<--->| : + // ----|-----|-----|------------------------ + // | v | + // v - 1 ulp v + 1 ulp + // + // if `v + 1 ulp` is closer to the rounded-down representation (which is already in `buf`), + // then we can safely return. note that `v - 1 ulp` *can* be less than the current + // representation, but as `1 ulp < 10^kappa / 2`, this condition is enough: + // the distance between `v - 1 ulp` and the current representation + // cannot exceed `10^kappa / 2`. + // + // the condition equals to `remainder + ulp < 10^kappa / 2`. + // since this can easily overflow, first check if `remainder < 10^kappa / 2`. + // we've already verified that `ulp < 10^kappa / 2`, so as long as + // `10^kappa` did not overflow after all, the second check is fine. + if ten_kappa - remainder > remainder && ten_kappa - 2 * remainder >= 2 * ulp { + // SAFETY: our caller initialized that memory. + return Some((unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, exp)); + } + + // :<------- remainder ------>| : + // : | : + // :<--------- 10^kappa --------->: + // : | | : | + // : |1 ulp|1 ulp| + // : |<--->|<--->| + // -----------------------|-----|-----|----- + // | v | + // v - 1 ulp v + 1 ulp + // + // on the other hands, if `v - 1 ulp` is closer to the rounded-up representation, + // we should round up and return. for the same reason we don't need to check `v + 1 ulp`. + // + // the condition equals to `remainder - ulp >= 10^kappa / 2`. + // again we first check if `remainder > ulp` (note that this is not `remainder >= ulp`, + // as `10^kappa` is never zero). also note that `remainder - ulp <= 10^kappa`, + // so the second check does not overflow. + if remainder > ulp && ten_kappa - (remainder - ulp) <= remainder - ulp { + if let Some(c) = + // SAFETY: our caller must have initialized that memory. + round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..len]) }) + { + // only add an additional digit when we've been requested the fixed precision. + // we also need to check that, if the original buffer was empty, + // the additional digit can only be added when `exp == limit` (edge case). + exp += 1; + if exp > limit && len < buf.len() { + buf[len] = MaybeUninit::new(c); + len += 1; + } + } + // SAFETY: we and our caller initialized that memory. + return Some((unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, exp)); + } + + // otherwise we are doomed (i.e., some values between `v - 1 ulp` and `v + 1 ulp` are + // rounding down and others are rounding up) and give up. + None + } +} + +/// The exact and fixed mode implementation for Grisu with Dragon fallback. +/// +/// This should be used for most cases. +pub fn format_exact<'a>( + d: &Decoded, + buf: &'a mut [MaybeUninit], + limit: i16, +) -> (/*digits*/ &'a [u8], /*exp*/ i16) { + use crate::num::flt2dec::strategy::dragon::format_exact as fallback; + // SAFETY: The borrow checker is not smart enough to let us use `buf` + // in the second branch, so we launder the lifetime here. But we only re-use + // `buf` if `format_exact_opt` returned `None` so this is okay. + match format_exact_opt(d, unsafe { &mut *(buf as *mut _) }, limit) { + Some(ret) => ret, + None => fallback(d, buf, limit), + } +} diff --git a/CoqOfRust/core/num/fmt.rs b/CoqOfRust/core/num/fmt.rs new file mode 100644 index 000000000..ed6119715 --- /dev/null +++ b/CoqOfRust/core/num/fmt.rs @@ -0,0 +1,108 @@ +//! Shared utilities used by both float and integer formatting. +#![doc(hidden)] +#![unstable( + feature = "numfmt", + reason = "internal routines only exposed for testing", + issue = "none" +)] + +/// Formatted parts. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Part<'a> { + /// Given number of zero digits. + Zero(usize), + /// A literal number up to 5 digits. + Num(u16), + /// A verbatim copy of given bytes. + Copy(&'a [u8]), +} + +impl<'a> Part<'a> { + /// Returns the exact byte length of given part. + pub fn len(&self) -> usize { + match *self { + Part::Zero(nzeroes) => nzeroes, + Part::Num(v) => { + if v < 1_000 { + if v < 10 { + 1 + } else if v < 100 { + 2 + } else { + 3 + } + } else { + if v < 10_000 { 4 } else { 5 } + } + } + Part::Copy(buf) => buf.len(), + } + } + + /// Writes a part into the supplied buffer. + /// Returns the number of written bytes, or `None` if the buffer is not enough. + /// (It may still leave partially written bytes in the buffer; do not rely on that.) + pub fn write(&self, out: &mut [u8]) -> Option { + let len = self.len(); + if out.len() >= len { + match *self { + Part::Zero(nzeroes) => { + for c in &mut out[..nzeroes] { + *c = b'0'; + } + } + Part::Num(mut v) => { + for c in out[..len].iter_mut().rev() { + *c = b'0' + (v % 10) as u8; + v /= 10; + } + } + Part::Copy(buf) => { + out[..buf.len()].copy_from_slice(buf); + } + } + Some(len) + } else { + None + } + } +} + +/// Formatted result containing one or more parts. +/// This can be written to the byte buffer or converted to the allocated string. +#[allow(missing_debug_implementations)] +#[derive(Clone)] +pub struct Formatted<'a> { + /// A byte slice representing a sign, either `""`, `"-"` or `"+"`. + pub sign: &'static str, + /// Formatted parts to be rendered after a sign and optional zero padding. + pub parts: &'a [Part<'a>], +} + +impl<'a> Formatted<'a> { + /// Returns the exact byte length of combined formatted result. + pub fn len(&self) -> usize { + let mut len = self.sign.len(); + for part in self.parts { + len += part.len(); + } + len + } + + /// Writes all formatted parts into the supplied buffer. + /// Returns the number of written bytes, or `None` if the buffer is not enough. + /// (It may still leave partially written bytes in the buffer; do not rely on that.) + pub fn write(&self, out: &mut [u8]) -> Option { + if out.len() < self.sign.len() { + return None; + } + out[..self.sign.len()].copy_from_slice(self.sign.as_bytes()); + + let mut written = self.sign.len(); + for part in self.parts { + let len = part.write(&mut out[written..])?; + written += len; + } + Some(written) + } +} diff --git a/CoqOfRust/core/num/int_log10.rs b/CoqOfRust/core/num/int_log10.rs new file mode 100644 index 000000000..0ce31b40a --- /dev/null +++ b/CoqOfRust/core/num/int_log10.rs @@ -0,0 +1,148 @@ +/// These functions compute the integer logarithm of their type, assuming +/// that someone has already checked that the value is strictly positive. + +// 0 < val <= u8::MAX +#[inline] +pub const fn u8(val: u8) -> u32 { + let val = val as u32; + + // For better performance, avoid branches by assembling the solution + // in the bits above the low 8 bits. + + // Adding c1 to val gives 10 in the top bits for val < 10, 11 for val >= 10 + const C1: u32 = 0b11_00000000 - 10; // 758 + // Adding c2 to val gives 01 in the top bits for val < 100, 10 for val >= 100 + const C2: u32 = 0b10_00000000 - 100; // 412 + + // Value of top bits: + // +c1 +c2 1&2 + // 0..=9 10 01 00 = 0 + // 10..=99 11 01 01 = 1 + // 100..=255 11 10 10 = 2 + ((val + C1) & (val + C2)) >> 8 +} + +// 0 < val < 100_000 +#[inline] +const fn less_than_5(val: u32) -> u32 { + // Similar to u8, when adding one of these constants to val, + // we get two possible bit patterns above the low 17 bits, + // depending on whether val is below or above the threshold. + const C1: u32 = 0b011_00000000000000000 - 10; // 393206 + const C2: u32 = 0b100_00000000000000000 - 100; // 524188 + const C3: u32 = 0b111_00000000000000000 - 1000; // 916504 + const C4: u32 = 0b100_00000000000000000 - 10000; // 514288 + + // Value of top bits: + // +c1 +c2 1&2 +c3 +c4 3&4 ^ + // 0..=9 010 011 010 110 011 010 000 = 0 + // 10..=99 011 011 011 110 011 010 001 = 1 + // 100..=999 011 100 000 110 011 010 010 = 2 + // 1000..=9999 011 100 000 111 011 011 011 = 3 + // 10000..=99999 011 100 000 111 100 100 100 = 4 + (((val + C1) & (val + C2)) ^ ((val + C3) & (val + C4))) >> 17 +} + +// 0 < val <= u16::MAX +#[inline] +pub const fn u16(val: u16) -> u32 { + less_than_5(val as u32) +} + +// 0 < val <= u32::MAX +#[inline] +pub const fn u32(mut val: u32) -> u32 { + let mut log = 0; + if val >= 100_000 { + val /= 100_000; + log += 5; + } + log + less_than_5(val) +} + +// 0 < val <= u64::MAX +#[inline] +pub const fn u64(mut val: u64) -> u32 { + let mut log = 0; + if val >= 10_000_000_000 { + val /= 10_000_000_000; + log += 10; + } + if val >= 100_000 { + val /= 100_000; + log += 5; + } + log + less_than_5(val as u32) +} + +// 0 < val <= u128::MAX +#[inline] +pub const fn u128(mut val: u128) -> u32 { + let mut log = 0; + if val >= 100_000_000_000_000_000_000_000_000_000_000 { + val /= 100_000_000_000_000_000_000_000_000_000_000; + log += 32; + return log + u32(val as u32); + } + if val >= 10_000_000_000_000_000 { + val /= 10_000_000_000_000_000; + log += 16; + } + log + u64(val as u64) +} + +#[cfg(target_pointer_width = "16")] +#[inline] +pub const fn usize(val: usize) -> u32 { + u16(val as _) +} + +#[cfg(target_pointer_width = "32")] +#[inline] +pub const fn usize(val: usize) -> u32 { + u32(val as _) +} + +#[cfg(target_pointer_width = "64")] +#[inline] +pub const fn usize(val: usize) -> u32 { + u64(val as _) +} + +// 0 < val <= i8::MAX +#[inline] +pub const fn i8(val: i8) -> u32 { + u8(val as u8) +} + +// 0 < val <= i16::MAX +#[inline] +pub const fn i16(val: i16) -> u32 { + u16(val as u16) +} + +// 0 < val <= i32::MAX +#[inline] +pub const fn i32(val: i32) -> u32 { + u32(val as u32) +} + +// 0 < val <= i64::MAX +#[inline] +pub const fn i64(val: i64) -> u32 { + u64(val as u64) +} + +// 0 < val <= i128::MAX +#[inline] +pub const fn i128(val: i128) -> u32 { + u128(val as u128) +} + +/// Instantiate this panic logic once, rather than for all the ilog methods +/// on every single primitive type. +#[cold] +#[track_caller] +pub const fn panic_for_nonpositive_argument() -> ! { + panic!("argument of integer logarithm must be positive") +} diff --git a/CoqOfRust/core/num/int_macros.rs b/CoqOfRust/core/num/int_macros.rs new file mode 100644 index 000000000..9a2026009 --- /dev/null +++ b/CoqOfRust/core/num/int_macros.rs @@ -0,0 +1,3667 @@ +macro_rules! int_impl { + ( + Self = $SelfT:ty, + ActualT = $ActualT:ident, + UnsignedT = $UnsignedT:ty, + + // There are all for use *only* in doc comments. + // As such, they're all passed as literals -- passing them as a string + // literal is fine if they need to be multiple code tokens. + // In non-comments, use the associated constants rather than these. + BITS = $BITS:literal, + BITS_MINUS_ONE = $BITS_MINUS_ONE:literal, + Min = $Min:literal, + Max = $Max:literal, + rot = $rot:literal, + rot_op = $rot_op:literal, + rot_result = $rot_result:literal, + swap_op = $swap_op:literal, + swapped = $swapped:literal, + reversed = $reversed:literal, + le_bytes = $le_bytes:literal, + be_bytes = $be_bytes:literal, + to_xe_bytes_doc = $to_xe_bytes_doc:expr, + from_xe_bytes_doc = $from_xe_bytes_doc:expr, + bound_condition = $bound_condition:literal, + ) => { + /// The smallest value that can be represented by this integer type + #[doc = concat!("(−2", $BITS_MINUS_ONE, "", $bound_condition, ").")] + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN, ", stringify!($Min), ");")] + /// ``` + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MIN: Self = !Self::MAX; + + /// The largest value that can be represented by this integer type + #[doc = concat!("(2", $BITS_MINUS_ONE, " − 1", $bound_condition, ").")] + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($Max), ");")] + /// ``` + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MAX: Self = (<$UnsignedT>::MAX >> 1) as Self; + + /// The size of this integer type in bits. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")] + /// ``` + #[stable(feature = "int_bits_const", since = "1.53.0")] + pub const BITS: u32 = <$UnsignedT>::BITS; + + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0b100_0000", stringify!($SelfT), ";")] + /// + /// assert_eq!(n.count_ones(), 1); + /// ``` + /// + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[doc(alias = "popcount")] + #[doc(alias = "popcnt")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() } + + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.count_zeros(), 1);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn count_zeros(self) -> u32 { + (!self).count_ones() + } + + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// Depending on what you're doing with the value, you might also be interested in the + /// [`ilog2`] function which returns a consistent number, even if the type widens. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = -1", stringify!($SelfT), ";")] + /// + /// assert_eq!(n.leading_zeros(), 0); + /// ``` + #[doc = concat!("[`ilog2`]: ", stringify!($SelfT), "::ilog2")] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn leading_zeros(self) -> u32 { + (self as $UnsignedT).leading_zeros() + } + + /// Returns the number of trailing zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = -4", stringify!($SelfT), ";")] + /// + /// assert_eq!(n.trailing_zeros(), 2); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn trailing_zeros(self) -> u32 { + (self as $UnsignedT).trailing_zeros() + } + + /// Returns the number of leading ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = -1", stringify!($SelfT), ";")] + /// + #[doc = concat!("assert_eq!(n.leading_ones(), ", stringify!($BITS), ");")] + /// ``` + #[stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn leading_ones(self) -> u32 { + (self as $UnsignedT).leading_ones() + } + + /// Returns the number of trailing ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 3", stringify!($SelfT), ";")] + /// + /// assert_eq!(n.trailing_ones(), 2); + /// ``` + #[stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn trailing_ones(self) -> u32 { + (self as $UnsignedT).trailing_ones() + } + + /// Returns the bit pattern of `self` reinterpreted as an unsigned integer of the same size. + /// + /// This produces the same result as an `as` cast, but ensures that the bit-width remains + /// the same. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(integer_sign_cast)] + /// + #[doc = concat!("let n = -1", stringify!($SelfT), ";")] + /// + #[doc = concat!("assert_eq!(n.cast_unsigned(), ", stringify!($UnsignedT), "::MAX);")] + /// ``` + #[unstable(feature = "integer_sign_cast", issue = "125882")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn cast_unsigned(self) -> $UnsignedT { + self as $UnsignedT + } + + /// Shifts the bits to the left by a specified amount, `n`, + /// wrapping the truncated bits to the end of the resulting integer. + /// + /// Please note this isn't the same operation as the `<<` shifting operator! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $rot_op, stringify!($SelfT), ";")] + #[doc = concat!("let m = ", $rot_result, ";")] + /// + #[doc = concat!("assert_eq!(n.rotate_left(", $rot, "), m);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn rotate_left(self, n: u32) -> Self { + (self as $UnsignedT).rotate_left(n) as Self + } + + /// Shifts the bits to the right by a specified amount, `n`, + /// wrapping the truncated bits to the beginning of the resulting + /// integer. + /// + /// Please note this isn't the same operation as the `>>` shifting operator! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $rot_result, stringify!($SelfT), ";")] + #[doc = concat!("let m = ", $rot_op, ";")] + /// + #[doc = concat!("assert_eq!(n.rotate_right(", $rot, "), m);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn rotate_right(self, n: u32) -> Self { + (self as $UnsignedT).rotate_right(n) as Self + } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $swap_op, stringify!($SelfT), ";")] + /// + /// let m = n.swap_bytes(); + /// + #[doc = concat!("assert_eq!(m, ", $swapped, ");")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn swap_bytes(self) -> Self { + (self as $UnsignedT).swap_bytes() as Self + } + + /// Reverses the order of bits in the integer. The least significant bit becomes the most significant bit, + /// second least-significant bit becomes second most-significant bit, etc. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $swap_op, stringify!($SelfT), ";")] + /// let m = n.reverse_bits(); + /// + #[doc = concat!("assert_eq!(m, ", $reversed, ");")] + #[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")] + /// ``` + #[stable(feature = "reverse_bits", since = "1.37.0")] + #[rustc_const_stable(feature = "reverse_bits", since = "1.37.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn reverse_bits(self) -> Self { + (self as $UnsignedT).reverse_bits() as Self + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "big") { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_be(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_be(n), n.swap_bytes())")] + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] + #[must_use] + #[inline] + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(not(target_endian = "big"))] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "little") { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_le(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_le(n), n.swap_bytes())")] + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] + #[must_use] + #[inline] + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(not(target_endian = "little"))] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_be(self) -> Self { // or not to be? + #[cfg(target_endian = "big")] + { + self + } + #[cfg(not(target_endian = "big"))] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(not(target_endian = "little"))] + { + self.swap_bytes() + } + } + + /// Checked integer addition. Computes `self + rhs`, returning `None` + /// if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(1), Some(", stringify!($SelfT), "::MAX - 1));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_add(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_add(rhs); + if intrinsics::unlikely(b) { None } else { Some(a) } + } + + /// Strict integer addition. Computes `self + rhs`, panicking + /// if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).strict_add(1), ", stringify!($SelfT), "::MAX - 1);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_add(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_add(rhs); + if b { overflow_panic::add() } else { a } + } + + /// Unchecked integer addition. Computes `self + rhs`, assuming overflow + /// cannot occur. + /// + /// Calling `x.unchecked_add(y)` is semantically equivalent to calling + /// `x.`[`checked_add`]`(y).`[`unwrap_unchecked`]`()`. + /// + /// If you're just trying to avoid the panic in debug mode, then **do not** + /// use this. Instead, you're looking for [`wrapping_add`]. + /// + /// # Safety + /// + /// This results in undefined behavior when + #[doc = concat!("`self + rhs > ", stringify!($SelfT), "::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`,")] + /// i.e. when [`checked_add`] would return `None`. + /// + /// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked + #[doc = concat!("[`checked_add`]: ", stringify!($SelfT), "::checked_add")] + #[doc = concat!("[`wrapping_add`]: ", stringify!($SelfT), "::wrapping_add")] + #[stable(feature = "unchecked_math", since = "1.79.0")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_add(self, rhs: Self) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_add cannot overflow"), + ( + lhs: $SelfT = self, + rhs: $SelfT = rhs, + ) => !lhs.overflowing_add(rhs).1, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + intrinsics::unchecked_add(self, rhs) + } + } + + /// Checked addition with an unsigned integer. Computes `self + rhs`, + /// returning `None` if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_unsigned(2), Some(3));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_unsigned(3), None);")] + /// ``` + #[stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_add_unsigned(self, rhs: $UnsignedT) -> Option { + let (a, b) = self.overflowing_add_unsigned(rhs); + if intrinsics::unlikely(b) { None } else { Some(a) } + } + + /// Strict addition with an unsigned integer. Computes `self + rhs`, + /// panicking if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_add_unsigned(2), 3);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_unsigned(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_add_unsigned(self, rhs: $UnsignedT) -> Self { + let (a, b) = self.overflowing_add_unsigned(rhs); + if b { overflow_panic::add() } else { a } + } + + /// Checked integer subtraction. Computes `self - rhs`, returning `None` if + /// overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub(1), Some(", stringify!($SelfT), "::MIN + 1));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub(3), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_sub(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_sub(rhs); + if intrinsics::unlikely(b) { None } else { Some(a) } + } + + /// Strict integer subtraction. Computes `self - rhs`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).strict_sub(1), ", stringify!($SelfT), "::MIN + 1);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_sub(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_sub(rhs); + if b { overflow_panic::sub() } else { a } + } + + /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow + /// cannot occur. + /// + /// Calling `x.unchecked_sub(y)` is semantically equivalent to calling + /// `x.`[`checked_sub`]`(y).`[`unwrap_unchecked`]`()`. + /// + /// If you're just trying to avoid the panic in debug mode, then **do not** + /// use this. Instead, you're looking for [`wrapping_sub`]. + /// + /// # Safety + /// + /// This results in undefined behavior when + #[doc = concat!("`self - rhs > ", stringify!($SelfT), "::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`,")] + /// i.e. when [`checked_sub`] would return `None`. + /// + /// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked + #[doc = concat!("[`checked_sub`]: ", stringify!($SelfT), "::checked_sub")] + #[doc = concat!("[`wrapping_sub`]: ", stringify!($SelfT), "::wrapping_sub")] + #[stable(feature = "unchecked_math", since = "1.79.0")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_sub cannot overflow"), + ( + lhs: $SelfT = self, + rhs: $SelfT = rhs, + ) => !lhs.overflowing_sub(rhs).1, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + intrinsics::unchecked_sub(self, rhs) + } + } + + /// Checked subtraction with an unsigned integer. Computes `self - rhs`, + /// returning `None` if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_unsigned(2), Some(-1));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub_unsigned(3), None);")] + /// ``` + #[stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_sub_unsigned(self, rhs: $UnsignedT) -> Option { + let (a, b) = self.overflowing_sub_unsigned(rhs); + if intrinsics::unlikely(b) { None } else { Some(a) } + } + + /// Strict subtraction with an unsigned integer. Computes `self - rhs`, + /// panicking if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_sub_unsigned(2), -1);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub_unsigned(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_sub_unsigned(self, rhs: $UnsignedT) -> Self { + let (a, b) = self.overflowing_sub_unsigned(rhs); + if b { overflow_panic::sub() } else { a } + } + + /// Checked integer multiplication. Computes `self * rhs`, returning `None` if + /// overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(1), Some(", stringify!($SelfT), "::MAX));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_mul(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_mul(rhs); + if intrinsics::unlikely(b) { None } else { Some(a) } + } + + /// Strict integer multiplication. Computes `self * rhs`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.strict_mul(1), ", stringify!($SelfT), "::MAX);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ``` should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_mul(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_mul(rhs); + if b { overflow_panic::mul() } else { a } + } + + /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow + /// cannot occur. + /// + /// Calling `x.unchecked_mul(y)` is semantically equivalent to calling + /// `x.`[`checked_mul`]`(y).`[`unwrap_unchecked`]`()`. + /// + /// If you're just trying to avoid the panic in debug mode, then **do not** + /// use this. Instead, you're looking for [`wrapping_mul`]. + /// + /// # Safety + /// + /// This results in undefined behavior when + #[doc = concat!("`self * rhs > ", stringify!($SelfT), "::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`,")] + /// i.e. when [`checked_mul`] would return `None`. + /// + /// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked + #[doc = concat!("[`checked_mul`]: ", stringify!($SelfT), "::checked_mul")] + #[doc = concat!("[`wrapping_mul`]: ", stringify!($SelfT), "::wrapping_mul")] + #[stable(feature = "unchecked_math", since = "1.79.0")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_mul cannot overflow"), + ( + lhs: $SelfT = self, + rhs: $SelfT = rhs, + ) => !lhs.overflowing_mul(rhs).1, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + intrinsics::unchecked_mul(self, rhs) + } + } + + /// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0` + /// or the division results in overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).checked_div(-1), Some(", stringify!($Max), "));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_div(-1), None);")] + #[doc = concat!("assert_eq!((1", stringify!($SelfT), ").checked_div(0), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_checked_int_div", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_div(self, rhs: Self) -> Option { + if intrinsics::unlikely(rhs == 0 || ((self == Self::MIN) && (rhs == -1))) { + None + } else { + // SAFETY: div by zero and by INT_MIN have been checked above + Some(unsafe { intrinsics::unchecked_div(self, rhs) }) + } + } + + /// Strict integer division. Computes `self / rhs`, panicking + /// if overflow occurred. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// The only case where such an overflow can occur is when one divides `MIN / -1` on a signed type (where + /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value + /// that is too large to represent in the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).strict_div(-1), ", stringify!($Max), ");")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_div(-1);")] + /// ``` + /// + /// The following panics because of division by zero: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_div(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_div(rhs); + if b { overflow_panic::div() } else { a } + } + + /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, + /// returning `None` if `rhs == 0` or the division results in overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).checked_div_euclid(-1), Some(", stringify!($Max), "));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_div_euclid(-1), None);")] + #[doc = concat!("assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None);")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_div_euclid(self, rhs: Self) -> Option { + // Using `&` helps LLVM see that it is the same check made in division. + if intrinsics::unlikely(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) { + None + } else { + Some(self.div_euclid(rhs)) + } + } + + /// Strict Euclidean division. Computes `self.div_euclid(rhs)`, panicking + /// if overflow occurred. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// The only case where such an overflow can occur is when one divides `MIN / -1` on a signed type (where + /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value + /// that is too large to represent in the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).strict_div_euclid(-1), ", stringify!($Max), ");")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_div_euclid(-1);")] + /// ``` + /// + /// The following panics because of division by zero: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_div_euclid(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_div_euclid(rhs); + if b { overflow_panic::div() } else { a } + } + + /// Checked integer remainder. Computes `self % rhs`, returning `None` if + /// `rhs == 0` or the division results in overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(2), Some(1));")] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_checked_int_div", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_rem(self, rhs: Self) -> Option { + if intrinsics::unlikely(rhs == 0 || ((self == Self::MIN) && (rhs == -1))) { + None + } else { + // SAFETY: div by zero and by INT_MIN have been checked above + Some(unsafe { intrinsics::unchecked_rem(self, rhs) }) + } + } + + /// Strict integer remainder. Computes `self % rhs`, panicking if + /// the division results in overflow. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// The only case where such an overflow can occur is `x % y` for `MIN / -1` on a + /// signed type (where `MIN` is the negative minimal value), which is invalid due to implementation artifacts. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_rem(2), 1);")] + /// ``` + /// + /// The following panics because of division by zero: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem(0);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem(-1);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_rem(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_rem(rhs); + if b { overflow_panic::rem() } else { a } + } + + /// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` + /// if `rhs == 0` or the division results in overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));")] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None);")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { + // Using `&` helps LLVM see that it is the same check made in division. + if intrinsics::unlikely(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) { + None + } else { + Some(self.rem_euclid(rhs)) + } + } + + /// Strict Euclidean remainder. Computes `self.rem_euclid(rhs)`, panicking if + /// the division results in overflow. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// The only case where such an overflow can occur is `x % y` for `MIN / -1` on a + /// signed type (where `MIN` is the negative minimal value), which is invalid due to implementation artifacts. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_rem_euclid(2), 1);")] + /// ``` + /// + /// The following panics because of division by zero: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem_euclid(0);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem_euclid(-1);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_rem_euclid(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_rem_euclid(rhs); + if b { overflow_panic::rem() } else { a } + } + + /// Checked negation. Computes `-self`, returning `None` if `self == MIN`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_neg(), Some(-5));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_neg(), None);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_neg(self) -> Option { + let (a, b) = self.overflowing_neg(); + if intrinsics::unlikely(b) { None } else { Some(a) } + } + + /// Unchecked negation. Computes `-self`, assuming overflow cannot occur. + /// + /// # Safety + /// + /// This results in undefined behavior when + #[doc = concat!("`self == ", stringify!($SelfT), "::MIN`,")] + /// i.e. when [`checked_neg`] would return `None`. + /// + #[doc = concat!("[`checked_neg`]: ", stringify!($SelfT), "::checked_neg")] + #[unstable( + feature = "unchecked_neg", + reason = "niche optimization path", + issue = "85122", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_neg(self) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_neg cannot overflow"), + ( + lhs: $SelfT = self, + ) => !lhs.overflowing_neg().1, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + intrinsics::unchecked_sub(0, self) + } + } + + /// Strict negation. Computes `-self`, panicking if `self == MIN`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_neg(), -5);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_neg();")] + /// + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_neg(self) -> Self { + let (a, b) = self.overflowing_neg(); + if b { overflow_panic::neg() } else { a } + } + + /// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger + /// than or equal to the number of bits in `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".checked_shl(4), Some(0x10));")] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".checked_shl(129), None);")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shl(", stringify!($BITS_MINUS_ONE), "), Some(0));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_shl(self, rhs: u32) -> Option { + // Not using overflowing_shl as that's a wrapping shift + if rhs < Self::BITS { + // SAFETY: just checked the RHS is in-range + Some(unsafe { self.unchecked_shl(rhs) }) + } else { + None + } + } + + /// Strict shift left. Computes `self << rhs`, panicking if `rhs` is larger + /// than or equal to the number of bits in `self`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".strict_shl(4), 0x10);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0x1", stringify!($SelfT), ".strict_shl(129);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_shl(self, rhs: u32) -> Self { + let (a, b) = self.overflowing_shl(rhs); + if b { overflow_panic::shl() } else { a } + } + + /// Unchecked shift left. Computes `self << rhs`, assuming that + /// `rhs` is less than the number of bits in `self`. + /// + /// # Safety + /// + /// This results in undefined behavior if `rhs` is larger than + /// or equal to the number of bits in `self`, + /// i.e. when [`checked_shl`] would return `None`. + /// + #[doc = concat!("[`checked_shl`]: ", stringify!($SelfT), "::checked_shl")] + #[unstable( + feature = "unchecked_shifts", + reason = "niche optimization path", + issue = "85122", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_shl cannot overflow"), + ( + rhs: u32 = rhs, + ) => rhs < <$ActualT>::BITS, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + intrinsics::unchecked_shl(self, rhs) + } + } + + /// Unbounded shift left. Computes `self << rhs`, without bounding the value of `rhs`. + /// + /// If `rhs` is larger or equal to the number of bits in `self`, + /// the entire value is shifted out, and `0` is returned. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(unbounded_shifts)] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(4), 0x10);")] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(129), 0);")] + /// ``` + #[unstable(feature = "unbounded_shifts", issue = "129375")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unbounded_shl(self, rhs: u32) -> $SelfT{ + if rhs < Self::BITS { + // SAFETY: + // rhs is just checked to be in-range above + unsafe { self.unchecked_shl(rhs) } + } else { + 0 + } + } + + /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is + /// larger than or equal to the number of bits in `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shr(4), Some(0x1));")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shr(128), None);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_shr(self, rhs: u32) -> Option { + // Not using overflowing_shr as that's a wrapping shift + if rhs < Self::BITS { + // SAFETY: just checked the RHS is in-range + Some(unsafe { self.unchecked_shr(rhs) }) + } else { + None + } + } + + /// Strict shift right. Computes `self >> rhs`, panicking `rhs` is + /// larger than or equal to the number of bits in `self`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".strict_shr(4), 0x1);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(128);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_shr(self, rhs: u32) -> Self { + let (a, b) = self.overflowing_shr(rhs); + if b { overflow_panic::shr() } else { a } + } + + /// Unchecked shift right. Computes `self >> rhs`, assuming that + /// `rhs` is less than the number of bits in `self`. + /// + /// # Safety + /// + /// This results in undefined behavior if `rhs` is larger than + /// or equal to the number of bits in `self`, + /// i.e. when [`checked_shr`] would return `None`. + /// + #[doc = concat!("[`checked_shr`]: ", stringify!($SelfT), "::checked_shr")] + #[unstable( + feature = "unchecked_shifts", + reason = "niche optimization path", + issue = "85122", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_shr cannot overflow"), + ( + rhs: u32 = rhs, + ) => rhs < <$ActualT>::BITS, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + intrinsics::unchecked_shr(self, rhs) + } + } + + /// Unbounded shift right. Computes `self >> rhs`, without bounding the value of `rhs`. + /// + /// If `rhs` is larger or equal to the number of bits in `self`, + /// the entire value is shifted out, which yields `0` for a positive number, + /// and `-1` for a negative number. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(unbounded_shifts)] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(4), 0x1);")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(129), 0);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.unbounded_shr(129), -1);")] + /// ``` + #[unstable(feature = "unbounded_shifts", issue = "129375")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unbounded_shr(self, rhs: u32) -> $SelfT{ + if rhs < Self::BITS { + // SAFETY: + // rhs is just checked to be in-range above + unsafe { self.unchecked_shr(rhs) } + } else { + // A shift by `Self::BITS-1` suffices for signed integers, because the sign bit is copied for each of the shifted bits. + + // SAFETY: + // `Self::BITS-1` is guaranteed to be less than `Self::BITS` + unsafe { self.unchecked_shr(Self::BITS - 1) } + } + } + + /// Checked absolute value. Computes `self.abs()`, returning `None` if + /// `self == MIN`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").checked_abs(), Some(5));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_abs(), None);")] + /// ``` + #[stable(feature = "no_panic_abs", since = "1.13.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_abs(self) -> Option { + if self.is_negative() { + self.checked_neg() + } else { + Some(self) + } + } + + /// Strict absolute value. Computes `self.abs()`, panicking if + /// `self == MIN`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").strict_abs(), 5);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_abs();")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_abs(self) -> Self { + if self.is_negative() { + self.strict_neg() + } else { + self + } + } + + /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if + /// overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(8", stringify!($SelfT), ".checked_pow(2), Some(64));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);")] + /// ``` + + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_pow(self, mut exp: u32) -> Option { + if exp == 0 { + return Some(1); + } + let mut base = self; + let mut acc: Self = 1; + + loop { + if (exp & 1) == 1 { + acc = try_opt!(acc.checked_mul(base)); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return Some(acc); + } + } + exp /= 2; + base = try_opt!(base.checked_mul(base)); + } + } + + /// Strict exponentiation. Computes `self.pow(exp)`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(8", stringify!($SelfT), ".strict_pow(2), 64);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc: Self = 1; + + loop { + if (exp & 1) == 1 { + acc = acc.strict_mul(base); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return acc; + } + } + exp /= 2; + base = base.strict_mul(base); + } + } + + /// Returns the square root of the number, rounded down. + /// + /// Returns `None` if `self` is negative. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_isqrt(), Some(3));")] + /// ``` + #[stable(feature = "isqrt", since = "1.84.0")] + #[rustc_const_stable(feature = "isqrt", since = "1.84.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_isqrt(self) -> Option { + if self < 0 { + None + } else { + // SAFETY: Input is nonnegative in this `else` branch. + let result = unsafe { + crate::num::int_sqrt::$ActualT(self as $ActualT) as $SelfT + }; + + // Inform the optimizer what the range of outputs is. If + // testing `core` crashes with no panic message and a + // `num::int_sqrt::i*` test failed, it's because your edits + // caused these assertions to become false. + // + // SAFETY: Integer square root is a monotonically nondecreasing + // function, which means that increasing the input will never + // cause the output to decrease. Thus, since the input for + // nonnegative signed integers is bounded by + // `[0, <$ActualT>::MAX]`, sqrt(n) will be bounded by + // `[sqrt(0), sqrt(<$ActualT>::MAX)]`. + unsafe { + // SAFETY: `<$ActualT>::MAX` is nonnegative. + const MAX_RESULT: $SelfT = unsafe { + crate::num::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT + }; + + crate::hint::assert_unchecked(result >= 0); + crate::hint::assert_unchecked(result <= MAX_RESULT); + } + + Some(result) + } + } + + /// Saturating integer addition. Computes `self + rhs`, saturating at the numeric + /// bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_add(100), ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_add(-1), ", stringify!($SelfT), "::MIN);")] + /// ``` + + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn saturating_add(self, rhs: Self) -> Self { + intrinsics::saturating_add(self, rhs) + } + + /// Saturating addition with an unsigned integer. Computes `self + rhs`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_unsigned(2), 3);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_add_unsigned(100), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_add_unsigned(self, rhs: $UnsignedT) -> Self { + // Overflow can only happen at the upper bound + // We cannot use `unwrap_or` here because it is not `const` + match self.checked_add_unsigned(rhs) { + Some(x) => x, + None => Self::MAX, + } + } + + /// Saturating integer subtraction. Computes `self - rhs`, saturating at the + /// numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_sub(127), -27);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub(100), ", stringify!($SelfT), "::MIN);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_sub(-1), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn saturating_sub(self, rhs: Self) -> Self { + intrinsics::saturating_sub(self, rhs) + } + + /// Saturating subtraction with an unsigned integer. Computes `self - rhs`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_sub_unsigned(127), -27);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub_unsigned(100), ", stringify!($SelfT), "::MIN);")] + /// ``` + #[stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_sub_unsigned(self, rhs: $UnsignedT) -> Self { + // Overflow can only happen at the lower bound + // We cannot use `unwrap_or` here because it is not `const` + match self.checked_sub_unsigned(rhs) { + Some(x) => x, + None => Self::MIN, + } + } + + /// Saturating integer negation. Computes `-self`, returning `MAX` if `self == MIN` + /// instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_neg(), -100);")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").saturating_neg(), 100);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_neg(), ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_neg(), ", stringify!($SelfT), "::MIN + 1);")] + /// ``` + + #[stable(feature = "saturating_neg", since = "1.45.0")] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn saturating_neg(self) -> Self { + intrinsics::saturating_sub(0, self) + } + + /// Saturating absolute value. Computes `self.abs()`, returning `MAX` if `self == + /// MIN` instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_abs(), 100);")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").saturating_abs(), 100);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_abs(), ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).saturating_abs(), ", stringify!($SelfT), "::MAX);")] + /// ``` + + #[stable(feature = "saturating_neg", since = "1.45.0")] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_abs(self) -> Self { + if self.is_negative() { + self.saturating_neg() + } else { + self + } + } + + /// Saturating integer multiplication. Computes `self * rhs`, saturating at the + /// numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".saturating_mul(12), 120);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_mul(10), ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_mul(10), ", stringify!($SelfT), "::MIN);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_mul(self, rhs: Self) -> Self { + match self.checked_mul(rhs) { + Some(x) => x, + None => if (self < 0) == (rhs < 0) { + Self::MAX + } else { + Self::MIN + } + } + } + + /// Saturating integer division. Computes `self / rhs`, saturating at the + /// numeric bounds instead of overflowing. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".saturating_div(2), 2);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_div(-1), ", stringify!($SelfT), "::MIN + 1);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_div(-1), ", stringify!($SelfT), "::MAX);")] + /// + /// ``` + #[stable(feature = "saturating_div", since = "1.58.0")] + #[rustc_const_stable(feature = "saturating_div", since = "1.58.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_div(self, rhs: Self) -> Self { + match self.overflowing_div(rhs) { + (result, false) => result, + (_result, true) => Self::MAX, // MIN / -1 is the only possible saturating overflow + } + } + + /// Saturating integer exponentiation. Computes `self.pow(exp)`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!((-4", stringify!($SelfT), ").saturating_pow(3), -64);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(2), ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT), "::MIN);")] + /// ``` + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_pow(self, exp: u32) -> Self { + match self.checked_pow(exp) { + Some(x) => x, + None if self < 0 && exp % 2 == 1 => Self::MIN, + None => Self::MAX, + } + } + + /// Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the + /// boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_add(27), 127);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add(2), ", stringify!($SelfT), "::MIN + 1);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn wrapping_add(self, rhs: Self) -> Self { + intrinsics::wrapping_add(self, rhs) + } + + /// Wrapping (modular) addition with an unsigned integer. Computes + /// `self + rhs`, wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_add_unsigned(27), 127);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add_unsigned(2), ", stringify!($SelfT), "::MIN + 1);")] + /// ``` + #[stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn wrapping_add_unsigned(self, rhs: $UnsignedT) -> Self { + self.wrapping_add(rhs as Self) + } + + /// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the + /// boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".wrapping_sub(127), -127);")] + #[doc = concat!("assert_eq!((-2", stringify!($SelfT), ").wrapping_sub(", stringify!($SelfT), "::MAX), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn wrapping_sub(self, rhs: Self) -> Self { + intrinsics::wrapping_sub(self, rhs) + } + + /// Wrapping (modular) subtraction with an unsigned integer. Computes + /// `self - rhs`, wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".wrapping_sub_unsigned(127), -127);")] + #[doc = concat!("assert_eq!((-2", stringify!($SelfT), ").wrapping_sub_unsigned(", stringify!($UnsignedT), "::MAX), -1);")] + /// ``` + #[stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn wrapping_sub_unsigned(self, rhs: $UnsignedT) -> Self { + self.wrapping_sub(rhs as Self) + } + + /// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at + /// the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".wrapping_mul(12), 120);")] + /// assert_eq!(11i8.wrapping_mul(12), -124); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn wrapping_mul(self, rhs: Self) -> Self { + intrinsics::wrapping_mul(self, rhs) + } + + /// Wrapping (modular) division. Computes `self / rhs`, wrapping around at the + /// boundary of the type. + /// + /// The only case where such wrapping can occur is when one divides `MIN / -1` on a signed type (where + /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value + /// that is too large to represent in the type. In such a case, this function returns `MIN` itself. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_div(10), 10);")] + /// assert_eq!((-128i8).wrapping_div(-1), -128); + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_wrapping_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_div(self, rhs: Self) -> Self { + self.overflowing_div(rhs).0 + } + + /// Wrapping Euclidean division. Computes `self.div_euclid(rhs)`, + /// wrapping around at the boundary of the type. + /// + /// Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is the negative minimal value + /// for the type). This is equivalent to `-MIN`, a positive value that is too large to represent in the + /// type. In this case, this method returns `MIN` itself. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);")] + /// assert_eq!((-128i8).wrapping_div_euclid(-1), -128); + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { + self.overflowing_div_euclid(rhs).0 + } + + /// Wrapping (modular) remainder. Computes `self % rhs`, wrapping around at the + /// boundary of the type. + /// + /// Such wrap-around never actually occurs mathematically; implementation artifacts make `x % y` + /// invalid for `MIN / -1` on a signed type (where `MIN` is the negative minimal value). In such a case, + /// this function returns `0`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_rem(10), 0);")] + /// assert_eq!((-128i8).wrapping_rem(-1), 0); + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_wrapping_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_rem(self, rhs: Self) -> Self { + self.overflowing_rem(rhs).0 + } + + /// Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around + /// at the boundary of the type. + /// + /// Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is the negative minimal value + /// for the type). In this case, this method returns 0. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);")] + /// assert_eq!((-128i8).wrapping_rem_euclid(-1), 0); + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { + self.overflowing_rem_euclid(rhs).0 + } + + /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary + /// of the type. + /// + /// The only case where such wrapping can occur is when one negates `MIN` on a signed type (where `MIN` + /// is the negative minimal value for the type); this is a positive value that is too large to represent + /// in the type. In such a case, this function returns `MIN` itself. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_neg(), -100);")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").wrapping_neg(), 100);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.wrapping_neg(), ", stringify!($SelfT), "::MIN);")] + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn wrapping_neg(self) -> Self { + (0 as $SelfT).wrapping_sub(self) + } + + /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` removes + /// any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. + /// + /// Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is restricted to + /// the range of the type, rather than the bits shifted out of the LHS being returned to the other end. + /// The primitive integer types all implement a [`rotate_left`](Self::rotate_left) function, + /// which may be what you want instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").wrapping_shl(7), -128);")] + #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").wrapping_shl(128), -1);")] + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + 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 { + self.unchecked_shl(rhs & (Self::BITS - 1)) + } + } + + /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`, where `mask` + /// removes any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. + /// + /// Note that this is *not* the same as a rotate-right; the RHS of a wrapping shift-right is restricted + /// to the range of the type, rather than the bits shifted out of the LHS being returned to the other + /// end. The primitive integer types all implement a [`rotate_right`](Self::rotate_right) function, + /// which may be what you want instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!((-128", stringify!($SelfT), ").wrapping_shr(7), -1);")] + /// assert_eq!((-128i16).wrapping_shr(64), -128); + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + 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 { + self.unchecked_shr(rhs & (Self::BITS - 1)) + } + } + + /// Wrapping (modular) absolute value. Computes `self.abs()`, wrapping around at + /// the boundary of the type. + /// + /// The only case where such wrapping can occur is when one takes the absolute value of the negative + /// minimal value for the type; this is a positive value that is too large to represent in the type. In + /// such a case, this function returns `MIN` itself. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_abs(), 100);")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").wrapping_abs(), 100);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.wrapping_abs(), ", stringify!($SelfT), "::MIN);")] + /// assert_eq!((-128i8).wrapping_abs() as u8, 128); + /// ``` + #[stable(feature = "no_panic_abs", since = "1.13.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[allow(unused_attributes)] + #[inline] + pub const fn wrapping_abs(self) -> Self { + if self.is_negative() { + self.wrapping_neg() + } else { + self + } + } + + /// Computes the absolute value of `self` without any wrapping + /// or panicking. + /// + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".unsigned_abs(), 100", stringify!($UnsignedT), ");")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").unsigned_abs(), 100", stringify!($UnsignedT), ");")] + /// assert_eq!((-128i8).unsigned_abs(), 128u8); + /// ``` + #[stable(feature = "unsigned_abs", since = "1.51.0")] + #[rustc_const_stable(feature = "unsigned_abs", since = "1.51.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unsigned_abs(self) -> $UnsignedT { + self.wrapping_abs() as $UnsignedT + } + + /// Wrapping (modular) exponentiation. Computes `self.pow(exp)`, + /// wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".wrapping_pow(4), 81);")] + /// assert_eq!(3i8.wrapping_pow(5), -13); + /// assert_eq!(3i8.wrapping_pow(6), -39); + /// ``` + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc: Self = 1; + + if intrinsics::is_val_statically_known(exp) { + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); + } + exp /= 2; + base = base.wrapping_mul(base); + } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary. + acc.wrapping_mul(base) + } else { + // This is faster than the above when the exponent is not known + // at compile time. We can't use the same code for the constant + // exponent case because LLVM is currently unable to unroll + // this loop. + loop { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return acc; + } + } + exp /= 2; + base = base.wrapping_mul(base); + } + } + } + + /// Calculates `self` + `rhs`. + /// + /// Returns a tuple of the addition along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would have + /// occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($SelfT), "::MIN, true));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { + let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT); + (a as Self, b) + } + + /// Calculates `self` + `rhs` + `carry` and checks for overflow. + /// + /// Performs "ternary addition" of two integer operands and a carry-in + /// bit, and returns a tuple of the sum along with a boolean indicating + /// whether an arithmetic overflow would occur. On overflow, the wrapped + /// value is returned. + /// + /// This allows chaining together multiple additions to create a wider + /// addition, and can be useful for bignum addition. This method should + /// only be used for the most significant word; for the less significant + /// words the unsigned method + #[doc = concat!("[`", stringify!($UnsignedT), "::carrying_add`]")] + /// should be used. + /// + /// The output boolean returned by this method is *not* a carry flag, + /// and should *not* be added to a more significant word. + /// + /// If the input carry is false, this method is equivalent to + /// [`overflowing_add`](Self::overflowing_add). + /// + /// # Examples + /// + /// ``` + /// #![feature(bigint_helper_methods)] + /// // Only the most significant word is signed. + /// // + #[doc = concat!("// 10 MAX (a = 10 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")] + #[doc = concat!("// + -5 9 (b = -5 × 2^", stringify!($BITS), " + 9)")] + /// // --------- + #[doc = concat!("// 6 8 (sum = 6 × 2^", stringify!($BITS), " + 8)")] + /// + #[doc = concat!("let (a1, a0): (", stringify!($SelfT), ", ", stringify!($UnsignedT), ") = (10, ", stringify!($UnsignedT), "::MAX);")] + #[doc = concat!("let (b1, b0): (", stringify!($SelfT), ", ", stringify!($UnsignedT), ") = (-5, 9);")] + /// let carry0 = false; + /// + #[doc = concat!("// ", stringify!($UnsignedT), "::carrying_add for the less significant words")] + /// let (sum0, carry1) = a0.carrying_add(b0, carry0); + /// assert_eq!(carry1, true); + /// + #[doc = concat!("// ", stringify!($SelfT), "::carrying_add for the most significant word")] + /// let (sum1, overflow) = a1.carrying_add(b1, carry1); + /// assert_eq!(overflow, false); + /// + /// assert_eq!((sum1, sum0), (6, 8)); + /// ``` + #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool) { + // note: longer-term this should be done via an intrinsic. + // note: no intermediate overflow is required (https://github.com/rust-lang/rust/issues/85532#issuecomment-1032214946). + let (a, b) = self.overflowing_add(rhs); + let (c, d) = a.overflowing_add(carry as $SelfT); + (c, b != d) + } + + /// Calculates `self` + `rhs` with an unsigned `rhs`. + /// + /// Returns a tuple of the addition along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_unsigned(2), (3, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN).overflowing_add_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MAX, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_unsigned(3), (", stringify!($SelfT), "::MIN, true));")] + /// ``` + #[stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_add_unsigned(self, rhs: $UnsignedT) -> (Self, bool) { + let rhs = rhs as Self; + let (res, overflowed) = self.overflowing_add(rhs); + (res, overflowed ^ (rhs < 0)) + } + + /// Calculates `self` - `rhs`. + /// + /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow + /// would occur. If an overflow would have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT); + (a as Self, b) + } + + /// Calculates `self` − `rhs` − `borrow` and checks for + /// overflow. + /// + /// Performs "ternary subtraction" by subtracting both an integer + /// operand and a borrow-in bit from `self`, and returns a tuple of the + /// difference along with a boolean indicating whether an arithmetic + /// overflow would occur. On overflow, the wrapped value is returned. + /// + /// This allows chaining together multiple subtractions to create a + /// wider subtraction, and can be useful for bignum subtraction. This + /// method should only be used for the most significant word; for the + /// less significant words the unsigned method + #[doc = concat!("[`", stringify!($UnsignedT), "::borrowing_sub`]")] + /// should be used. + /// + /// The output boolean returned by this method is *not* a borrow flag, + /// and should *not* be subtracted from a more significant word. + /// + /// If the input borrow is false, this method is equivalent to + /// [`overflowing_sub`](Self::overflowing_sub). + /// + /// # Examples + /// + /// ``` + /// #![feature(bigint_helper_methods)] + /// // Only the most significant word is signed. + /// // + #[doc = concat!("// 6 8 (a = 6 × 2^", stringify!($BITS), " + 8)")] + #[doc = concat!("// - -5 9 (b = -5 × 2^", stringify!($BITS), " + 9)")] + /// // --------- + #[doc = concat!("// 10 MAX (diff = 10 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")] + /// + #[doc = concat!("let (a1, a0): (", stringify!($SelfT), ", ", stringify!($UnsignedT), ") = (6, 8);")] + #[doc = concat!("let (b1, b0): (", stringify!($SelfT), ", ", stringify!($UnsignedT), ") = (-5, 9);")] + /// let borrow0 = false; + /// + #[doc = concat!("// ", stringify!($UnsignedT), "::borrowing_sub for the less significant words")] + /// let (diff0, borrow1) = a0.borrowing_sub(b0, borrow0); + /// assert_eq!(borrow1, true); + /// + #[doc = concat!("// ", stringify!($SelfT), "::borrowing_sub for the most significant word")] + /// let (diff1, overflow) = a1.borrowing_sub(b1, borrow1); + /// assert_eq!(overflow, false); + /// + #[doc = concat!("assert_eq!((diff1, diff0), (10, ", stringify!($UnsignedT), "::MAX));")] + /// ``` + #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool) { + // note: longer-term this should be done via an intrinsic. + // note: no intermediate overflow is required (https://github.com/rust-lang/rust/issues/85532#issuecomment-1032214946). + let (a, b) = self.overflowing_sub(rhs); + let (c, d) = a.overflowing_sub(borrow as $SelfT); + (c, b != d) + } + + /// Calculates `self` - `rhs` with an unsigned `rhs`. + /// + /// Returns a tuple of the subtraction along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_unsigned(2), (-1, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX).overflowing_sub_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MIN, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).overflowing_sub_unsigned(3), (", stringify!($SelfT), "::MAX, true));")] + /// ``` + #[stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_sub_unsigned(self, rhs: $UnsignedT) -> (Self, bool) { + let rhs = rhs as Self; + let (res, overflowed) = self.overflowing_sub(rhs); + (res, overflowed ^ (rhs < 0)) + } + + /// Calculates the multiplication of `self` and `rhs`. + /// + /// Returns a tuple of the multiplication along with a boolean indicating whether an arithmetic overflow + /// would occur. If an overflow would have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_mul(2), (10, false));")] + /// assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true)); + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT); + (a as Self, b) + } + + /// Calculates the divisor when `self` is divided by `rhs`. + /// + /// Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would + /// occur. If an overflow would occur then self is returned. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div(-1), (", stringify!($SelfT), "::MIN, true));")] + /// ``` + #[inline] + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_overflowing_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { + // Using `&` helps LLVM see that it is the same check made in division. + if intrinsics::unlikely((self == Self::MIN) & (rhs == -1)) { + (self, true) + } else { + (self / rhs, false) + } + } + + /// Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. + /// + /// Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would + /// occur. If an overflow would occur then `self` is returned. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringify!($SelfT), "::MIN, true));")] + /// ``` + #[inline] + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + // Using `&` helps LLVM see that it is the same check made in division. + if intrinsics::unlikely((self == Self::MIN) & (rhs == -1)) { + (self, true) + } else { + (self.div_euclid(rhs), false) + } + } + + /// Calculates the remainder when `self` is divided by `rhs`. + /// + /// Returns a tuple of the remainder after dividing along with a boolean indicating whether an + /// arithmetic overflow would occur. If an overflow would occur then 0 is returned. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem(-1), (0, true));")] + /// ``` + #[inline] + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_overflowing_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + if intrinsics::unlikely(rhs == -1) { + (0, self == Self::MIN) + } else { + (self % rhs, false) + } + } + + + /// Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`. + /// + /// Returns a tuple of the remainder after dividing along with a boolean indicating whether an + /// arithmetic overflow would occur. If an overflow would occur then 0 is returned. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true));")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + if intrinsics::unlikely(rhs == -1) { + (0, self == Self::MIN) + } else { + (self.rem_euclid(rhs), false) + } + } + + + /// Negates self, overflowing if this is equal to the minimum value. + /// + /// Returns a tuple of the negated version of self along with a boolean indicating whether an overflow + /// happened. If `self` is the minimum value (e.g., `i32::MIN` for values of type `i32`), then the + /// minimum value will be returned again and `true` will be returned for an overflow happening. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_neg(), (", stringify!($SelfT), "::MIN, true));")] + /// ``` + #[inline] + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[allow(unused_attributes)] + pub const fn overflowing_neg(self) -> (Self, bool) { + if intrinsics::unlikely(self == Self::MIN) { + (Self::MIN, true) + } else { + (-self, false) + } + } + + /// Shifts self left by `rhs` bits. + /// + /// Returns a tuple of the shifted version of self along with a boolean indicating whether the shift + /// value was larger than or equal to the number of bits. If the shift value is too large, then value is + /// masked (N-1) where N is the number of bits, and this value is then used to perform the shift. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT),".overflowing_shl(4), (0x10, false));")] + /// assert_eq!(0x1i32.overflowing_shl(36), (0x10, true)); + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".overflowing_shl(", stringify!($BITS_MINUS_ONE), "), (0, false));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), rhs >= Self::BITS) + } + + /// Shifts self right by `rhs` bits. + /// + /// Returns a tuple of the shifted version of self along with a boolean indicating whether the shift + /// value was larger than or equal to the number of bits. If the shift value is too large, then value is + /// masked (N-1) where N is the number of bits, and this value is then used to perform the shift. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(4), (0x1, false));")] + /// assert_eq!(0x10i32.overflowing_shr(36), (0x1, true)); + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), rhs >= Self::BITS) + } + + /// Computes the absolute value of `self`. + /// + /// Returns a tuple of the absolute version of self along with a boolean indicating whether an overflow + /// happened. If self is the minimum value + #[doc = concat!("(e.g., ", stringify!($SelfT), "::MIN for values of type ", stringify!($SelfT), "),")] + /// then the minimum value will be returned again and true will be returned + /// for an overflow happening. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".overflowing_abs(), (10, false));")] + #[doc = concat!("assert_eq!((-10", stringify!($SelfT), ").overflowing_abs(), (10, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN).overflowing_abs(), (", stringify!($SelfT), "::MIN, true));")] + /// ``` + #[stable(feature = "no_panic_abs", since = "1.13.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_abs(self) -> (Self, bool) { + (self.wrapping_abs(), self == Self::MIN) + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// Returns a tuple of the exponentiation along with a bool indicating + /// whether an overflow happened. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".overflowing_pow(4), (81, false));")] + /// assert_eq!(3i8.overflowing_pow(5), (-13, true)); + /// ``` + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { + if exp == 0 { + return (1,false); + } + let mut base = self; + let mut acc: Self = 1; + let mut overflown = false; + // Scratch space for storing results of overflowing_mul. + let mut r; + + loop { + if (exp & 1) == 1 { + r = acc.overflowing_mul(base); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + r.1 |= overflown; + return r; + } + acc = r.0; + overflown |= r.1; + } + exp /= 2; + r = base.overflowing_mul(base); + base = r.0; + overflown |= r.1; + } + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let x: ", stringify!($SelfT), " = 2; // or any other integer type")] + /// + /// assert_eq!(x.pow(5), 32); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc = 1; + + if intrinsics::is_val_statically_known(exp) { + while exp > 1 { + if (exp & 1) == 1 { + acc = acc * base; + } + exp /= 2; + base = base * base; + } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc * base + } else { + // This is faster than the above when the exponent is not known + // at compile time. We can't use the same code for the constant + // exponent case because LLVM is currently unable to unroll + // this loop. + loop { + if (exp & 1) == 1 { + acc = acc * base; + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return acc; + } + } + exp /= 2; + base = base * base; + } + } + } + + /// Returns the square root of the number, rounded down. + /// + /// # Panics + /// + /// This function will panic if `self` is negative. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".isqrt(), 3);")] + /// ``` + #[stable(feature = "isqrt", since = "1.84.0")] + #[rustc_const_stable(feature = "isqrt", since = "1.84.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn isqrt(self) -> Self { + match self.checked_isqrt() { + Some(sqrt) => sqrt, + None => crate::num::int_sqrt::panic_for_negative_argument(), + } + } + + /// Calculates the quotient of Euclidean division of `self` by `rhs`. + /// + /// This computes the integer `q` such that `self = q * rhs + r`, with + /// `r = self.rem_euclid(rhs)` and `0 <= r < abs(rhs)`. + /// + /// In other words, the result is `self / rhs` rounded to the integer `q` + /// such that `self >= q * rhs`. + /// If `self > 0`, this is equal to rounding towards zero (the default in Rust); + /// if `self < 0`, this is equal to rounding away from zero (towards +/- infinity). + /// If `rhs > 0`, this is equal to rounding towards -infinity; + /// if `rhs < 0`, this is equal to rounding towards +infinity. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero or if `self` is `Self::MIN` + /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let a: ", stringify!($SelfT), " = 7; // or any other integer type")] + /// let b = 4; + /// + /// assert_eq!(a.div_euclid(b), 1); // 7 >= 4 * 1 + /// assert_eq!(a.div_euclid(-b), -1); // 7 >= -4 * -1 + /// assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2 + /// assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn div_euclid(self, rhs: Self) -> Self { + let q = self / rhs; + if self % rhs < 0 { + return if rhs > 0 { q - 1 } else { q + 1 } + } + q + } + + + /// Calculates the least nonnegative remainder of `self (mod rhs)`. + /// + /// This is done as if by the Euclidean division algorithm -- given + /// `r = self.rem_euclid(rhs)`, the result satisfies + /// `self = rhs * self.div_euclid(rhs) + r` and `0 <= r < abs(rhs)`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero or if `self` is `Self::MIN` and + /// `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let a: ", stringify!($SelfT), " = 7; // or any other integer type")] + /// let b = 4; + /// + /// assert_eq!(a.rem_euclid(b), 3); + /// assert_eq!((-a).rem_euclid(b), 1); + /// assert_eq!(a.rem_euclid(-b), 3); + /// assert_eq!((-a).rem_euclid(-b), 1); + /// ``` + /// + /// This will panic: + /// ```should_panic + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.rem_euclid(-1);")] + /// ``` + #[doc(alias = "modulo", alias = "mod")] + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn rem_euclid(self, rhs: Self) -> Self { + let r = self % rhs; + if r < 0 { + // Semantically equivalent to `if rhs < 0 { r - rhs } else { r + rhs }`. + // If `rhs` is not `Self::MIN`, then `r + abs(rhs)` will not overflow + // and is clearly equivalent, because `r` is negative. + // Otherwise, `rhs` is `Self::MIN`, then we have + // `r.wrapping_add(Self::MIN.wrapping_abs())`, which evaluates + // to `r.wrapping_add(Self::MIN)`, which is equivalent to + // `r - Self::MIN`, which is what we wanted (and will not overflow + // for negative `r`). + r.wrapping_add(rhs.wrapping_abs()) + } else { + r + } + } + + /// Calculates the quotient of `self` and `rhs`, rounding the result towards negative infinity. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero or if `self` is `Self::MIN` + /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(int_roundings)] + #[doc = concat!("let a: ", stringify!($SelfT)," = 8;")] + /// let b = 3; + /// + /// assert_eq!(a.div_floor(b), 2); + /// assert_eq!(a.div_floor(-b), -3); + /// assert_eq!((-a).div_floor(b), -3); + /// assert_eq!((-a).div_floor(-b), 2); + /// ``` + #[unstable(feature = "int_roundings", issue = "88581")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn div_floor(self, rhs: Self) -> Self { + let d = self / rhs; + let r = self % rhs; + + // If the remainder is non-zero, we need to subtract one if the + // signs of self and rhs differ, as this means we rounded upwards + // instead of downwards. We do this branchlessly by creating a mask + // which is all-ones iff the signs differ, and 0 otherwise. Then by + // adding this mask (which corresponds to the signed value -1), we + // get our correction. + let correction = (self ^ rhs) >> (Self::BITS - 1); + if r != 0 { + d + correction + } else { + d + } + } + + /// Calculates the quotient of `self` and `rhs`, rounding the result towards positive infinity. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero or if `self` is `Self::MIN` + /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(int_roundings)] + #[doc = concat!("let a: ", stringify!($SelfT)," = 8;")] + /// let b = 3; + /// + /// assert_eq!(a.div_ceil(b), 3); + /// assert_eq!(a.div_ceil(-b), -2); + /// assert_eq!((-a).div_ceil(b), -2); + /// assert_eq!((-a).div_ceil(-b), 3); + /// ``` + #[unstable(feature = "int_roundings", issue = "88581")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn div_ceil(self, rhs: Self) -> Self { + let d = self / rhs; + let r = self % rhs; + + // When remainder is non-zero we have a.div_ceil(b) == 1 + a.div_floor(b), + // so we can re-use the algorithm from div_floor, just adding 1. + let correction = 1 + ((self ^ rhs) >> (Self::BITS - 1)); + if r != 0 { + d + correction + } else { + d + } + } + + /// If `rhs` is positive, calculates the smallest value greater than or + /// equal to `self` that is a multiple of `rhs`. If `rhs` is negative, + /// calculates the largest value less than or equal to `self` that is a + /// multiple of `rhs`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// On overflow, this function will panic if overflow checks are enabled (default in debug + /// mode) and wrap if overflow checks are disabled (default in release mode). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(int_roundings)] + #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")] + #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")] + #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(-8), 16);")] + #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(-8), 16);")] + #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").next_multiple_of(8), -16);")] + #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").next_multiple_of(8), -16);")] + #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").next_multiple_of(-8), -16);")] + #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").next_multiple_of(-8), -24);")] + /// ``` + #[unstable(feature = "int_roundings", issue = "88581")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn next_multiple_of(self, rhs: Self) -> Self { + // This would otherwise fail when calculating `r` when self == T::MIN. + if rhs == -1 { + return self; + } + + let r = self % rhs; + let m = if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) { + r + rhs + } else { + r + }; + + if m == 0 { + self + } else { + self + (rhs - m) + } + } + + /// If `rhs` is positive, calculates the smallest value greater than or + /// equal to `self` that is a multiple of `rhs`. If `rhs` is negative, + /// calculates the largest value less than or equal to `self` that is a + /// multiple of `rhs`. Returns `None` if `rhs` is zero or the operation + /// would result in overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(int_roundings)] + #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(16));")] + #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(24));")] + #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".checked_next_multiple_of(-8), Some(16));")] + #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".checked_next_multiple_of(-8), Some(16));")] + #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").checked_next_multiple_of(8), Some(-16));")] + #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").checked_next_multiple_of(8), Some(-16));")] + #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").checked_next_multiple_of(-8), Some(-16));")] + #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").checked_next_multiple_of(-8), Some(-24));")] + #[doc = concat!("assert_eq!(1_", stringify!($SelfT), ".checked_next_multiple_of(0), None);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_next_multiple_of(2), None);")] + /// ``` + #[unstable(feature = "int_roundings", issue = "88581")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_next_multiple_of(self, rhs: Self) -> Option { + // This would otherwise fail when calculating `r` when self == T::MIN. + if rhs == -1 { + return Some(self); + } + + let r = try_opt!(self.checked_rem(rhs)); + let m = if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) { + // r + rhs cannot overflow because they have opposite signs + r + rhs + } else { + r + }; + + if m == 0 { + Some(self) + } else { + // rhs - m cannot overflow because m has the same sign as rhs + self.checked_add(rhs - m) + } + } + + /// Returns the logarithm of the number with respect to an arbitrary base, + /// rounded down. + /// + /// This method might not be optimized owing to implementation details; + /// `ilog2` can produce results more efficiently for base 2, and `ilog10` + /// can produce results more efficiently for base 10. + /// + /// # Panics + /// + /// This function will panic if `self` is less than or equal to zero, + /// or if `base` is less than 2. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn ilog(self, base: Self) -> u32 { + assert!(base >= 2, "base of integer logarithm must be at least 2"); + if let Some(log) = self.checked_ilog(base) { + log + } else { + int_log10::panic_for_nonpositive_argument() + } + } + + /// Returns the base 2 logarithm of the number, rounded down. + /// + /// # Panics + /// + /// This function will panic if `self` is less than or equal to zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn ilog2(self) -> u32 { + if let Some(log) = self.checked_ilog2() { + log + } else { + int_log10::panic_for_nonpositive_argument() + } + } + + /// Returns the base 10 logarithm of the number, rounded down. + /// + /// # Panics + /// + /// This function will panic if `self` is less than or equal to zero. + /// + /// # Example + /// + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn ilog10(self) -> u32 { + if let Some(log) = self.checked_ilog10() { + log + } else { + int_log10::panic_for_nonpositive_argument() + } + } + + /// Returns the logarithm of the number with respect to an arbitrary base, + /// rounded down. + /// + /// Returns `None` if the number is negative or zero, or if the base is not at least 2. + /// + /// This method might not be optimized owing to implementation details; + /// `checked_ilog2` can produce results more efficiently for base 2, and + /// `checked_ilog10` can produce results more efficiently for base 10. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_ilog(self, base: Self) -> Option { + if self <= 0 || base <= 1 { + None + } else { + // Delegate to the unsigned implementation. + // The condition makes sure that both casts are exact. + (self as $UnsignedT).checked_ilog(base as $UnsignedT) + } + } + + /// Returns the base 2 logarithm of the number, rounded down. + /// + /// Returns `None` if the number is negative or zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_ilog2(self) -> Option { + if self <= 0 { + None + } else { + // SAFETY: We just checked that this number is positive + let log = (Self::BITS - 1) - unsafe { intrinsics::ctlz_nonzero(self) as u32 }; + Some(log) + } + } + + /// Returns the base 10 logarithm of the number, rounded down. + /// + /// Returns `None` if the number is negative or zero. + /// + /// # Example + /// + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_ilog10(self) -> Option { + if self > 0 { + Some(int_log10::$ActualT(self as $ActualT)) + } else { + None + } + } + + /// Computes the absolute value of `self`. + /// + /// # Overflow behavior + /// + /// The absolute value of + #[doc = concat!("`", stringify!($SelfT), "::MIN`")] + /// cannot be represented as an + #[doc = concat!("`", stringify!($SelfT), "`,")] + /// and attempting to calculate it will cause an overflow. This means + /// that code in debug mode will trigger a panic on this case and + /// optimized code will return + #[doc = concat!("`", stringify!($SelfT), "::MIN`")] + /// without a panic. If you do not want this behavior, consider + /// using [`unsigned_abs`](Self::unsigned_abs) instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".abs(), 10);")] + #[doc = concat!("assert_eq!((-10", stringify!($SelfT), ").abs(), 10);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[allow(unused_attributes)] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn abs(self) -> Self { + // Note that the #[rustc_inherit_overflow_checks] and #[inline] + // above mean that the overflow semantics of the subtraction + // depend on the crate we're being called from. + if self.is_negative() { + -self + } else { + self + } + } + + /// Computes the absolute difference between `self` and `other`. + /// + /// This function always returns the correct answer without overflow or + /// panics by returning an unsigned integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(80), 20", stringify!($UnsignedT), ");")] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(110), 10", stringify!($UnsignedT), ");")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").abs_diff(80), 180", stringify!($UnsignedT), ");")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").abs_diff(-120), 20", stringify!($UnsignedT), ");")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.abs_diff(", stringify!($SelfT), "::MAX), ", stringify!($UnsignedT), "::MAX);")] + /// ``` + #[stable(feature = "int_abs_diff", since = "1.60.0")] + #[rustc_const_stable(feature = "int_abs_diff", since = "1.60.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn abs_diff(self, other: Self) -> $UnsignedT { + if self < other { + // Converting a non-negative x from signed to unsigned by using + // `x as U` is left unchanged, but a negative x is converted + // to value x + 2^N. Thus if `s` and `o` are binary variables + // respectively indicating whether `self` and `other` are + // negative, we are computing the mathematical value: + // + // (other + o*2^N) - (self + s*2^N) mod 2^N + // other - self + (o-s)*2^N mod 2^N + // other - self mod 2^N + // + // Finally, taking the mod 2^N of the mathematical value of + // `other - self` does not change it as it already is + // in the range [0, 2^N). + (other as $UnsignedT).wrapping_sub(self as $UnsignedT) + } else { + (self as $UnsignedT).wrapping_sub(other as $UnsignedT) + } + } + + /// Returns a number representing sign of `self`. + /// + /// - `0` if the number is zero + /// - `1` if the number is positive + /// - `-1` if the number is negative + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".signum(), 1);")] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".signum(), 0);")] + #[doc = concat!("assert_eq!((-10", stringify!($SelfT), ").signum(), -1);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_sign", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn signum(self) -> Self { + // Picking the right way to phrase this is complicated + // () + // so delegate it to `Ord` which is already producing -1/0/+1 + // exactly like we need and can be the place to deal with the complexity. + + // FIXME(const-hack): replace with cmp + if self < 0 { -1 } + else if self == 0 { 0 } + else { 1 } + } + + /// Returns `true` if `self` is positive and `false` if the number is zero or + /// negative. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert!(10", stringify!($SelfT), ".is_positive());")] + #[doc = concat!("assert!(!(-10", stringify!($SelfT), ").is_positive());")] + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[inline(always)] + pub const fn is_positive(self) -> bool { self > 0 } + + /// Returns `true` if `self` is negative and `false` if the number is zero or + /// positive. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert!((-10", stringify!($SelfT), ").is_negative());")] + #[doc = concat!("assert!(!10", stringify!($SelfT), ".is_negative());")] + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[inline(always)] + pub const fn is_negative(self) -> bool { self < 0 } + + /// Returns the memory representation of this integer as a byte array in + /// big-endian (network) byte order. + /// + #[doc = $to_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes();")] + #[doc = concat!("assert_eq!(bytes, ", $be_bytes, ");")] + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { + self.to_be().to_ne_bytes() + } + + /// Returns the memory representation of this integer as a byte array in + /// little-endian byte order. + /// + #[doc = $to_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes();")] + #[doc = concat!("assert_eq!(bytes, ", $le_bytes, ");")] + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { + self.to_le().to_ne_bytes() + } + + /// Returns the memory representation of this integer as a byte array in + /// native byte order. + /// + /// As the target platform's native endianness is used, portable code + /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, + /// instead. + /// + #[doc = $to_xe_bytes_doc] + /// + /// [`to_be_bytes`]: Self::to_be_bytes + /// [`to_le_bytes`]: Self::to_le_bytes + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes();")] + /// assert_eq!( + /// bytes, + /// if cfg!(target_endian = "big") { + #[doc = concat!(" ", $be_bytes)] + /// } else { + #[doc = concat!(" ", $le_bytes)] + /// } + /// ); + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + // SAFETY: const sound because integers are plain old datatypes so we can always + // transmute them to arrays of bytes + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { + // SAFETY: integers are plain old datatypes so we can always transmute them to + // arrays of bytes + unsafe { mem::transmute(self) } + } + + /// Creates an integer value from its representation as a byte array in + /// big endian. + /// + #[doc = $from_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, ");")] + #[doc = concat!("assert_eq!(value, ", $swap_op, ");")] + /// ``` + /// + /// When starting from a slice rather than an array, fallible conversion APIs can be used: + /// + /// ``` + #[doc = concat!("fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")] + #[doc = concat!(" let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")] + /// *input = rest; + #[doc = concat!(" ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())")] + /// } + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use] + #[inline] + pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_be(Self::from_ne_bytes(bytes)) + } + + /// Creates an integer value from its representation as a byte array in + /// little endian. + /// + #[doc = $from_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, ");")] + #[doc = concat!("assert_eq!(value, ", $swap_op, ");")] + /// ``` + /// + /// When starting from a slice rather than an array, fallible conversion APIs can be used: + /// + /// ``` + #[doc = concat!("fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")] + #[doc = concat!(" let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")] + /// *input = rest; + #[doc = concat!(" ", stringify!($SelfT), "::from_le_bytes(int_bytes.try_into().unwrap())")] + /// } + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use] + #[inline] + pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_le(Self::from_ne_bytes(bytes)) + } + + /// Creates an integer value from its memory representation as a byte + /// array in native endianness. + /// + /// As the target platform's native endianness is used, portable code + /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as + /// appropriate instead. + /// + /// [`from_be_bytes`]: Self::from_be_bytes + /// [`from_le_bytes`]: Self::from_le_bytes + /// + #[doc = $from_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") {")] + #[doc = concat!(" ", $be_bytes)] + /// } else { + #[doc = concat!(" ", $le_bytes)] + /// }); + #[doc = concat!("assert_eq!(value, ", $swap_op, ");")] + /// ``` + /// + /// When starting from a slice rather than an array, fallible conversion APIs can be used: + /// + /// ``` + #[doc = concat!("fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")] + #[doc = concat!(" let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")] + /// *input = rest; + #[doc = concat!(" ", stringify!($SelfT), "::from_ne_bytes(int_bytes.try_into().unwrap())")] + /// } + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use] + // SAFETY: const sound because integers are plain old datatypes so we can always + // transmute to them + #[inline] + pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { + // SAFETY: integers are plain old datatypes so we can always transmute to them + unsafe { mem::transmute(bytes) } + } + + /// New code should prefer to use + #[doc = concat!("[`", stringify!($SelfT), "::MIN", "`] instead.")] + /// + /// Returns the smallest value that can be represented by this integer type. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline(always)] + #[rustc_promotable] + #[rustc_const_stable(feature = "const_min_value", since = "1.32.0")] + #[deprecated(since = "TBD", note = "replaced by the `MIN` associated constant on this type")] + #[rustc_diagnostic_item = concat!(stringify!($SelfT), "_legacy_fn_min_value")] + pub const fn min_value() -> Self { + Self::MIN + } + + /// New code should prefer to use + #[doc = concat!("[`", stringify!($SelfT), "::MAX", "`] instead.")] + /// + /// Returns the largest value that can be represented by this integer type. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline(always)] + #[rustc_promotable] + #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] + #[deprecated(since = "TBD", note = "replaced by the `MAX` associated constant on this type")] + #[rustc_diagnostic_item = concat!(stringify!($SelfT), "_legacy_fn_max_value")] + pub const fn max_value() -> Self { + Self::MAX + } + } +} diff --git a/CoqOfRust/core/num/int_sqrt.rs b/CoqOfRust/core/num/int_sqrt.rs new file mode 100644 index 000000000..601e81f69 --- /dev/null +++ b/CoqOfRust/core/num/int_sqrt.rs @@ -0,0 +1,316 @@ +//! These functions use the [Karatsuba square root algorithm][1] to compute the +//! [integer square root](https://en.wikipedia.org/wiki/Integer_square_root) +//! for the primitive integer types. +//! +//! The signed integer functions can only handle **nonnegative** inputs, so +//! that must be checked before calling those. +//! +//! [1]: +//! "Paul Zimmermann. Karatsuba Square Root. \[Research Report\] RR-3805, +//! INRIA. 1999, pp.8. (inria-00072854)" + +/// This array stores the [integer square roots]( +/// https://en.wikipedia.org/wiki/Integer_square_root) and remainders of each +/// [`u8`](prim@u8) value. For example, `U8_ISQRT_WITH_REMAINDER[17]` will be +/// `(4, 1)` because the integer square root of 17 is 4 and because 17 is 1 +/// higher than 4 squared. +const U8_ISQRT_WITH_REMAINDER: [(u8, u8); 256] = { + let mut result = [(0, 0); 256]; + + let mut n: usize = 0; + let mut isqrt_n: usize = 0; + while n < result.len() { + result[n] = (isqrt_n as u8, (n - isqrt_n.pow(2)) as u8); + + n += 1; + if n == (isqrt_n + 1).pow(2) { + isqrt_n += 1; + } + } + + result +}; + +/// Returns the [integer square root]( +/// https://en.wikipedia.org/wiki/Integer_square_root) of any [`u8`](prim@u8) +/// input. +#[must_use = "this returns the result of the operation, \ + without modifying the original"] +#[inline] +pub const fn u8(n: u8) -> u8 { + U8_ISQRT_WITH_REMAINDER[n as usize].0 +} + +/// Generates an `i*` function that returns the [integer square root]( +/// https://en.wikipedia.org/wiki/Integer_square_root) of any **nonnegative** +/// input of a specific signed integer type. +macro_rules! signed_fn { + ($SignedT:ident, $UnsignedT:ident) => { + /// Returns the [integer square root]( + /// https://en.wikipedia.org/wiki/Integer_square_root) of any + /// **nonnegative** + #[doc = concat!("[`", stringify!($SignedT), "`](prim@", stringify!($SignedT), ")")] + /// input. + /// + /// # Safety + /// + /// This results in undefined behavior when the input is negative. + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const unsafe fn $SignedT(n: $SignedT) -> $SignedT { + debug_assert!(n >= 0, "Negative input inside `isqrt`."); + $UnsignedT(n as $UnsignedT) as $SignedT + } + }; +} + +signed_fn!(i8, u8); +signed_fn!(i16, u16); +signed_fn!(i32, u32); +signed_fn!(i64, u64); +signed_fn!(i128, u128); + +/// Generates a `u*` function that returns the [integer square root]( +/// https://en.wikipedia.org/wiki/Integer_square_root) of any input of +/// a specific unsigned integer type. +macro_rules! unsigned_fn { + ($UnsignedT:ident, $HalfBitsT:ident, $stages:ident) => { + /// Returns the [integer square root]( + /// https://en.wikipedia.org/wiki/Integer_square_root) of any + #[doc = concat!("[`", stringify!($UnsignedT), "`](prim@", stringify!($UnsignedT), ")")] + /// input. + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn $UnsignedT(mut n: $UnsignedT) -> $UnsignedT { + if n <= <$HalfBitsT>::MAX as $UnsignedT { + $HalfBitsT(n as $HalfBitsT) as $UnsignedT + } else { + // The normalization shift satisfies the Karatsuba square root + // algorithm precondition "a₃ ≥ b/4" where a₃ is the most + // significant quarter of `n`'s bits and b is the number of + // values that can be represented by that quarter of the bits. + // + // b/4 would then be all 0s except the second most significant + // bit (010...0) in binary. Since a₃ must be at least b/4, a₃'s + // most significant bit or its neighbor must be a 1. Since a₃'s + // most significant bits are `n`'s most significant bits, the + // same applies to `n`. + // + // The reason to shift by an even number of bits is because an + // even number of bits produces the square root shifted to the + // left by half of the normalization shift: + // + // sqrt(n << (2 * p)) + // sqrt(2.pow(2 * p) * n) + // sqrt(2.pow(2 * p)) * sqrt(n) + // 2.pow(p) * sqrt(n) + // sqrt(n) << p + // + // Shifting by an odd number of bits leaves an ugly sqrt(2) + // multiplied in: + // + // sqrt(n << (2 * p + 1)) + // sqrt(2.pow(2 * p + 1) * n) + // sqrt(2 * 2.pow(2 * p) * n) + // sqrt(2) * sqrt(2.pow(2 * p)) * sqrt(n) + // sqrt(2) * 2.pow(p) * sqrt(n) + // sqrt(2) * (sqrt(n) << p) + const EVEN_MAKING_BITMASK: u32 = !1; + let normalization_shift = n.leading_zeros() & EVEN_MAKING_BITMASK; + n <<= normalization_shift; + + let s = $stages(n); + + let denormalization_shift = normalization_shift >> 1; + s >> denormalization_shift + } + } + }; +} + +/// Generates the first stage of the computation after normalization. +/// +/// # Safety +/// +/// `$n` must be nonzero. +macro_rules! first_stage { + ($original_bits:literal, $n:ident) => {{ + debug_assert!($n != 0, "`$n` is zero in `first_stage!`."); + + const N_SHIFT: u32 = $original_bits - 8; + let n = $n >> N_SHIFT; + + let (s, r) = U8_ISQRT_WITH_REMAINDER[n as usize]; + + // Inform the optimizer that `s` is nonzero. This will allow it to + // avoid generating code to handle division-by-zero panics in the next + // stage. + // + // SAFETY: If the original `$n` is zero, the top of the `unsigned_fn` + // macro recurses instead of continuing to this point, so the original + // `$n` wasn't a 0 if we've reached here. + // + // Then the `unsigned_fn` macro normalizes `$n` so that at least one of + // its two most-significant bits is a 1. + // + // Then this stage puts the eight most-significant bits of `$n` into + // `n`. This means that `n` here has at least one 1 bit in its two + // most-significant bits, making `n` nonzero. + // + // `U8_ISQRT_WITH_REMAINDER[n as usize]` will give a nonzero `s` when + // given a nonzero `n`. + unsafe { crate::hint::assert_unchecked(s != 0) }; + (s, r) + }}; +} + +/// Generates a middle stage of the computation. +/// +/// # Safety +/// +/// `$s` must be nonzero. +macro_rules! middle_stage { + ($original_bits:literal, $ty:ty, $n:ident, $s:ident, $r:ident) => {{ + debug_assert!($s != 0, "`$s` is zero in `middle_stage!`."); + + const N_SHIFT: u32 = $original_bits - <$ty>::BITS; + let n = ($n >> N_SHIFT) as $ty; + + const HALF_BITS: u32 = <$ty>::BITS >> 1; + const QUARTER_BITS: u32 = <$ty>::BITS >> 2; + const LOWER_HALF_1_BITS: $ty = (1 << HALF_BITS) - 1; + const LOWEST_QUARTER_1_BITS: $ty = (1 << QUARTER_BITS) - 1; + + let lo = n & LOWER_HALF_1_BITS; + let numerator = (($r as $ty) << QUARTER_BITS) | (lo >> QUARTER_BITS); + let denominator = ($s as $ty) << 1; + let q = numerator / denominator; + let u = numerator % denominator; + + let mut s = ($s << QUARTER_BITS) as $ty + q; + let (mut r, overflow) = + ((u << QUARTER_BITS) | (lo & LOWEST_QUARTER_1_BITS)).overflowing_sub(q * q); + if overflow { + r = r.wrapping_add(2 * s - 1); + s -= 1; + } + + // Inform the optimizer that `s` is nonzero. This will allow it to + // avoid generating code to handle division-by-zero panics in the next + // stage. + // + // SAFETY: If the original `$n` is zero, the top of the `unsigned_fn` + // macro recurses instead of continuing to this point, so the original + // `$n` wasn't a 0 if we've reached here. + // + // Then the `unsigned_fn` macro normalizes `$n` so that at least one of + // its two most-significant bits is a 1. + // + // Then these stages take as many of the most-significant bits of `$n` + // as will fit in this stage's type. For example, the stage that + // handles `u32` deals with the 32 most-significant bits of `$n`. This + // means that each stage has at least one 1 bit in `n`'s two + // most-significant bits, making `n` nonzero. + // + // Then this stage will produce the correct integer square root for + // that `n` value. Since `n` is nonzero, `s` will also be nonzero. + unsafe { crate::hint::assert_unchecked(s != 0) }; + (s, r) + }}; +} + +/// Generates the last stage of the computation before denormalization. +/// +/// # Safety +/// +/// `$s` must be nonzero. +macro_rules! last_stage { + ($ty:ty, $n:ident, $s:ident, $r:ident) => {{ + debug_assert!($s != 0, "`$s` is zero in `last_stage!`."); + + const HALF_BITS: u32 = <$ty>::BITS >> 1; + const QUARTER_BITS: u32 = <$ty>::BITS >> 2; + const LOWER_HALF_1_BITS: $ty = (1 << HALF_BITS) - 1; + + let lo = $n & LOWER_HALF_1_BITS; + let numerator = (($r as $ty) << QUARTER_BITS) | (lo >> QUARTER_BITS); + let denominator = ($s as $ty) << 1; + + let q = numerator / denominator; + let mut s = ($s << QUARTER_BITS) as $ty + q; + let (s_squared, overflow) = s.overflowing_mul(s); + if overflow || s_squared > $n { + s -= 1; + } + s + }}; +} + +/// Takes the normalized [`u16`](prim@u16) input and gets its normalized +/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root). +/// +/// # Safety +/// +/// `n` must be nonzero. +#[inline] +const fn u16_stages(n: u16) -> u16 { + let (s, r) = first_stage!(16, n); + last_stage!(u16, n, s, r) +} + +/// Takes the normalized [`u32`](prim@u32) input and gets its normalized +/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root). +/// +/// # Safety +/// +/// `n` must be nonzero. +#[inline] +const fn u32_stages(n: u32) -> u32 { + let (s, r) = first_stage!(32, n); + let (s, r) = middle_stage!(32, u16, n, s, r); + last_stage!(u32, n, s, r) +} + +/// Takes the normalized [`u64`](prim@u64) input and gets its normalized +/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root). +/// +/// # Safety +/// +/// `n` must be nonzero. +#[inline] +const fn u64_stages(n: u64) -> u64 { + let (s, r) = first_stage!(64, n); + let (s, r) = middle_stage!(64, u16, n, s, r); + let (s, r) = middle_stage!(64, u32, n, s, r); + last_stage!(u64, n, s, r) +} + +/// Takes the normalized [`u128`](prim@u128) input and gets its normalized +/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root). +/// +/// # Safety +/// +/// `n` must be nonzero. +#[inline] +const fn u128_stages(n: u128) -> u128 { + let (s, r) = first_stage!(128, n); + let (s, r) = middle_stage!(128, u16, n, s, r); + let (s, r) = middle_stage!(128, u32, n, s, r); + let (s, r) = middle_stage!(128, u64, n, s, r); + last_stage!(u128, n, s, r) +} + +unsigned_fn!(u16, u8, u16_stages); +unsigned_fn!(u32, u16, u32_stages); +unsigned_fn!(u64, u32, u64_stages); +unsigned_fn!(u128, u64, u128_stages); + +/// Instantiate this panic logic once, rather than for all the isqrt methods +/// on every single primitive type. +#[cold] +#[track_caller] +pub const fn panic_for_negative_argument() -> ! { + panic!("argument of integer square root cannot be negative") +} diff --git a/CoqOfRust/core/num/mod.rs b/CoqOfRust/core/num/mod.rs new file mode 100644 index 000000000..e36f20fd5 --- /dev/null +++ b/CoqOfRust/core/num/mod.rs @@ -0,0 +1,1668 @@ +//! Numeric traits and functions for the built-in numeric types. + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::panic::const_panic; +use crate::str::FromStr; +use crate::ub_checks::assert_unsafe_precondition; +use crate::{ascii, intrinsics, mem}; + +// FIXME(const-hack): Used because the `?` operator is not allowed in a const context. +macro_rules! try_opt { + ($e:expr) => { + match $e { + Some(x) => x, + None => return None, + } + }; +} + +// Use this when the generated code should differ between signed and unsigned types. +macro_rules! sign_dependent_expr { + (signed ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => { + $signed_case + }; + (unsigned ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => { + $unsigned_case + }; +} + +// All these modules are technically private and only exposed for coretests: +#[cfg(not(no_fp_fmt_parse))] +pub mod bignum; +#[cfg(not(no_fp_fmt_parse))] +pub mod dec2flt; +#[cfg(not(no_fp_fmt_parse))] +pub mod diy_float; +#[cfg(not(no_fp_fmt_parse))] +pub mod flt2dec; +pub mod fmt; + +#[macro_use] +mod int_macros; // import int_impl! +#[macro_use] +mod uint_macros; // import uint_impl! + +mod error; +mod int_log10; +mod int_sqrt; +mod nonzero; +mod overflow_panic; +mod saturating; +mod wrapping; + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(no_fp_fmt_parse))] +pub use dec2flt::ParseFloatError; +#[stable(feature = "int_error_matching", since = "1.55.0")] +pub use error::IntErrorKind; +#[stable(feature = "rust1", since = "1.0.0")] +pub use error::ParseIntError; +#[stable(feature = "try_from", since = "1.34.0")] +pub use error::TryFromIntError; +#[stable(feature = "generic_nonzero", since = "1.79.0")] +pub use nonzero::NonZero; +#[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" +)] +pub use nonzero::ZeroablePrimitive; +#[stable(feature = "signed_nonzero", since = "1.34.0")] +pub use nonzero::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize}; +#[stable(feature = "nonzero", since = "1.28.0")] +pub use nonzero::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize}; +#[stable(feature = "saturating_int_impl", since = "1.74.0")] +pub use saturating::Saturating; +#[stable(feature = "rust1", since = "1.0.0")] +pub use wrapping::Wrapping; + +macro_rules! usize_isize_to_xe_bytes_doc { + () => { + " + +**Note**: This function returns an array of length 2, 4 or 8 bytes +depending on the target pointer size. + +" + }; +} + +macro_rules! usize_isize_from_xe_bytes_doc { + () => { + " + +**Note**: This function takes an array of length 2, 4 or 8 bytes +depending on the target pointer size. + +" + }; +} + +macro_rules! midpoint_impl { + ($SelfT:ty, unsigned) => { + /// Calculates the middle point of `self` and `rhs`. + /// + /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a + /// sufficiently-large unsigned integral type. This implies that the result is + /// always rounded towards zero and that no overflow will ever occur. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")] + /// ``` + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn midpoint(self, rhs: $SelfT) -> $SelfT { + // Use the well known branchless algorithm from Hacker's Delight to compute + // `(a + b) / 2` without overflowing: `((a ^ b) >> 1) + (a & b)`. + ((self ^ rhs) >> 1) + (self & rhs) + } + }; + ($SelfT:ty, signed) => { + /// Calculates the middle point of `self` and `rhs`. + /// + /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a + /// sufficiently-large signed integral type. This implies that the result is + /// always rounded towards zero and that no overflow will ever occur. + /// + /// # Examples + /// + /// ``` + /// #![feature(num_midpoint_signed)] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] + #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").midpoint(2), 0);")] + #[doc = concat!("assert_eq!((-7", stringify!($SelfT), ").midpoint(0), -3);")] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-7), -3);")] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(7), 3);")] + /// ``` + #[unstable(feature = "num_midpoint_signed", issue = "110840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn midpoint(self, rhs: Self) -> Self { + // Use the well known branchless algorithm from Hacker's Delight to compute + // `(a + b) / 2` without overflowing: `((a ^ b) >> 1) + (a & b)`. + let t = ((self ^ rhs) >> 1) + (self & rhs); + // Except that it fails for integers whose sum is an odd negative number as + // their floor is one less than their average. So we adjust the result. + t + (if t < 0 { 1 } else { 0 } & (self ^ rhs)) + } + }; + ($SelfT:ty, $WideT:ty, unsigned) => { + /// Calculates the middle point of `self` and `rhs`. + /// + /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a + /// sufficiently-large unsigned integral type. This implies that the result is + /// always rounded towards zero and that no overflow will ever occur. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")] + /// ``` + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn midpoint(self, rhs: $SelfT) -> $SelfT { + ((self as $WideT + rhs as $WideT) / 2) as $SelfT + } + }; + ($SelfT:ty, $WideT:ty, signed) => { + /// Calculates the middle point of `self` and `rhs`. + /// + /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a + /// sufficiently-large signed integral type. This implies that the result is + /// always rounded towards zero and that no overflow will ever occur. + /// + /// # Examples + /// + /// ``` + /// #![feature(num_midpoint_signed)] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] + #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").midpoint(2), 0);")] + #[doc = concat!("assert_eq!((-7", stringify!($SelfT), ").midpoint(0), -3);")] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-7), -3);")] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(7), 3);")] + /// ``` + #[unstable(feature = "num_midpoint_signed", issue = "110840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn midpoint(self, rhs: $SelfT) -> $SelfT { + ((self as $WideT + rhs as $WideT) / 2) as $SelfT + } + }; +} + +macro_rules! widening_impl { + ($SelfT:ty, $WideT:ty, $BITS:literal, unsigned) => { + /// Calculates the complete product `self * rhs` without the possibility to overflow. + /// + /// This returns the low-order (wrapping) bits and the high-order (overflow) bits + /// of the result as two separate values, in that order. + /// + /// If you also need to add a carry to the wide result, then you want + /// [`Self::carrying_mul`] instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// Please note that this example is shared between integer types. + /// Which explains why `u32` is used here. + /// + /// ``` + /// #![feature(bigint_helper_methods)] + /// assert_eq!(5u32.widening_mul(2), (10, 0)); + /// assert_eq!(1_000_000_000u32.widening_mul(10), (1410065408, 2)); + /// ``` + #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn widening_mul(self, rhs: Self) -> (Self, Self) { + // note: longer-term this should be done via an intrinsic, + // but for now we can deal without an impl for u128/i128 + // SAFETY: overflow will be contained within the wider types + let wide = unsafe { (self as $WideT).unchecked_mul(rhs as $WideT) }; + (wide as $SelfT, (wide >> $BITS) as $SelfT) + } + + /// Calculates the "full multiplication" `self * rhs + carry` + /// without the possibility to overflow. + /// + /// This returns the low-order (wrapping) bits and the high-order (overflow) bits + /// of the result as two separate values, in that order. + /// + /// Performs "long multiplication" which takes in an extra amount to add, and may return an + /// additional amount of overflow. This allows for chaining together multiple + /// multiplications to create "big integers" which represent larger values. + /// + /// If you don't need the `carry`, then you can use [`Self::widening_mul`] instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// Please note that this example is shared between integer types. + /// Which explains why `u32` is used here. + /// + /// ``` + /// #![feature(bigint_helper_methods)] + /// assert_eq!(5u32.carrying_mul(2, 0), (10, 0)); + /// assert_eq!(5u32.carrying_mul(2, 10), (20, 0)); + /// assert_eq!(1_000_000_000u32.carrying_mul(10, 0), (1410065408, 2)); + /// assert_eq!(1_000_000_000u32.carrying_mul(10, 10), (1410065418, 2)); + #[doc = concat!("assert_eq!(", + stringify!($SelfT), "::MAX.carrying_mul(", stringify!($SelfT), "::MAX, ", stringify!($SelfT), "::MAX), ", + "(0, ", stringify!($SelfT), "::MAX));" + )] + /// ``` + /// + /// This is the core operation needed for scalar multiplication when + /// implementing it for wider-than-native types. + /// + /// ``` + /// #![feature(bigint_helper_methods)] + /// fn scalar_mul_eq(little_endian_digits: &mut Vec, multiplicand: u16) { + /// let mut carry = 0; + /// for d in little_endian_digits.iter_mut() { + /// (*d, carry) = d.carrying_mul(multiplicand, carry); + /// } + /// if carry != 0 { + /// little_endian_digits.push(carry); + /// } + /// } + /// + /// let mut v = vec![10, 20]; + /// scalar_mul_eq(&mut v, 3); + /// assert_eq!(v, [30, 60]); + /// + /// assert_eq!(0x87654321_u64 * 0xFEED, 0x86D3D159E38D); + /// let mut v = vec![0x4321, 0x8765]; + /// scalar_mul_eq(&mut v, 0xFEED); + /// assert_eq!(v, [0xE38D, 0xD159, 0x86D3]); + /// ``` + /// + /// If `carry` is zero, this is similar to [`overflowing_mul`](Self::overflowing_mul), + /// except that it gives the value of the overflow instead of just whether one happened: + /// + /// ``` + /// #![feature(bigint_helper_methods)] + /// let r = u8::carrying_mul(7, 13, 0); + /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(7, 13)); + /// let r = u8::carrying_mul(13, 42, 0); + /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(13, 42)); + /// ``` + /// + /// The value of the first field in the returned tuple matches what you'd get + /// by combining the [`wrapping_mul`](Self::wrapping_mul) and + /// [`wrapping_add`](Self::wrapping_add) methods: + /// + /// ``` + /// #![feature(bigint_helper_methods)] + /// assert_eq!( + /// 789_u16.carrying_mul(456, 123).0, + /// 789_u16.wrapping_mul(456).wrapping_add(123), + /// ); + /// ``` + #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self) { + // note: longer-term this should be done via an intrinsic, + // but for now we can deal without an impl for u128/i128 + // SAFETY: overflow will be contained within the wider types + let wide = unsafe { + (self as $WideT).unchecked_mul(rhs as $WideT).unchecked_add(carry as $WideT) + }; + (wide as $SelfT, (wide >> $BITS) as $SelfT) + } + }; +} + +impl i8 { + int_impl! { + Self = i8, + ActualT = i8, + UnsignedT = u8, + BITS = 8, + BITS_MINUS_ONE = 7, + Min = -128, + Max = 127, + rot = 2, + rot_op = "-0x7e", + rot_result = "0xa", + swap_op = "0x12", + swapped = "0x12", + reversed = "0x48", + le_bytes = "[0x12]", + be_bytes = "[0x12]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } + midpoint_impl! { i8, i16, signed } +} + +impl i16 { + int_impl! { + Self = i16, + ActualT = i16, + UnsignedT = u16, + BITS = 16, + BITS_MINUS_ONE = 15, + Min = -32768, + Max = 32767, + rot = 4, + rot_op = "-0x5ffd", + rot_result = "0x3a", + swap_op = "0x1234", + swapped = "0x3412", + reversed = "0x2c48", + le_bytes = "[0x34, 0x12]", + be_bytes = "[0x12, 0x34]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } + midpoint_impl! { i16, i32, signed } +} + +impl i32 { + int_impl! { + Self = i32, + ActualT = i32, + UnsignedT = u32, + BITS = 32, + BITS_MINUS_ONE = 31, + Min = -2147483648, + Max = 2147483647, + rot = 8, + rot_op = "0x10000b3", + rot_result = "0xb301", + swap_op = "0x12345678", + swapped = "0x78563412", + reversed = "0x1e6a2c48", + le_bytes = "[0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } + midpoint_impl! { i32, i64, signed } +} + +impl i64 { + int_impl! { + Self = i64, + ActualT = i64, + UnsignedT = u64, + BITS = 64, + BITS_MINUS_ONE = 63, + Min = -9223372036854775808, + Max = 9223372036854775807, + rot = 12, + rot_op = "0xaa00000000006e1", + rot_result = "0x6e10aa", + swap_op = "0x1234567890123456", + swapped = "0x5634129078563412", + reversed = "0x6a2c48091e6a2c48", + le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } + midpoint_impl! { i64, signed } +} + +impl i128 { + int_impl! { + Self = i128, + ActualT = i128, + UnsignedT = u128, + BITS = 128, + BITS_MINUS_ONE = 127, + Min = -170141183460469231731687303715884105728, + Max = 170141183460469231731687303715884105727, + rot = 16, + rot_op = "0x13f40000000000000000000000004f76", + rot_result = "0x4f7613f4", + swap_op = "0x12345678901234567890123456789012", + swapped = "0x12907856341290785634129078563412", + reversed = "0x48091e6a2c48091e6a2c48091e6a2c48", + le_bytes = "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ + 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } + midpoint_impl! { i128, signed } +} + +#[cfg(target_pointer_width = "16")] +impl isize { + int_impl! { + Self = isize, + ActualT = i16, + UnsignedT = usize, + BITS = 16, + BITS_MINUS_ONE = 15, + Min = -32768, + Max = 32767, + rot = 4, + rot_op = "-0x5ffd", + rot_result = "0x3a", + swap_op = "0x1234", + swapped = "0x3412", + reversed = "0x2c48", + le_bytes = "[0x34, 0x12]", + be_bytes = "[0x12, 0x34]", + to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(), + from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(), + bound_condition = " on 16-bit targets", + } + midpoint_impl! { isize, i32, signed } +} + +#[cfg(target_pointer_width = "32")] +impl isize { + int_impl! { + Self = isize, + ActualT = i32, + UnsignedT = usize, + BITS = 32, + BITS_MINUS_ONE = 31, + Min = -2147483648, + Max = 2147483647, + rot = 8, + rot_op = "0x10000b3", + rot_result = "0xb301", + swap_op = "0x12345678", + swapped = "0x78563412", + reversed = "0x1e6a2c48", + le_bytes = "[0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78]", + to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(), + from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(), + bound_condition = " on 32-bit targets", + } + midpoint_impl! { isize, i64, signed } +} + +#[cfg(target_pointer_width = "64")] +impl isize { + int_impl! { + Self = isize, + ActualT = i64, + UnsignedT = usize, + BITS = 64, + BITS_MINUS_ONE = 63, + Min = -9223372036854775808, + Max = 9223372036854775807, + rot = 12, + rot_op = "0xaa00000000006e1", + rot_result = "0x6e10aa", + swap_op = "0x1234567890123456", + swapped = "0x5634129078563412", + reversed = "0x6a2c48091e6a2c48", + le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(), + from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(), + bound_condition = " on 64-bit targets", + } + midpoint_impl! { isize, signed } +} + +/// If the bit selected by this mask is set, ascii is lower case. +const ASCII_CASE_MASK: u8 = 0b0010_0000; + +impl u8 { + uint_impl! { + Self = u8, + ActualT = u8, + SignedT = i8, + BITS = 8, + BITS_MINUS_ONE = 7, + MAX = 255, + rot = 2, + rot_op = "0x82", + rot_result = "0xa", + swap_op = "0x12", + swapped = "0x12", + reversed = "0x48", + le_bytes = "[0x12]", + be_bytes = "[0x12]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } + widening_impl! { u8, u16, 8, unsigned } + midpoint_impl! { u8, u16, unsigned } + + /// Checks if the value is within the ASCII range. + /// + /// # Examples + /// + /// ``` + /// let ascii = 97u8; + /// let non_ascii = 150u8; + /// + /// assert!(ascii.is_ascii()); + /// assert!(!non_ascii.is_ascii()); + /// ``` + #[must_use] + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_u8_is_ascii", since = "1.43.0")] + #[inline] + pub const fn is_ascii(&self) -> bool { + *self <= 127 + } + + /// If the value of this byte is within the ASCII range, returns it as an + /// [ASCII character](ascii::Char). Otherwise, returns `None`. + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_ascii(&self) -> Option { + ascii::Char::from_u8(*self) + } + + /// Makes a copy of the value in its ASCII upper case equivalent. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To uppercase the value in-place, use [`make_ascii_uppercase`]. + /// + /// # Examples + /// + /// ``` + /// let lowercase_a = 97u8; + /// + /// assert_eq!(65, lowercase_a.to_ascii_uppercase()); + /// ``` + /// + /// [`make_ascii_uppercase`]: Self::make_ascii_uppercase + #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"] + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] + #[inline] + pub const fn to_ascii_uppercase(&self) -> u8 { + // Toggle the 6th bit if this is a lowercase letter + *self ^ ((self.is_ascii_lowercase() as u8) * ASCII_CASE_MASK) + } + + /// Makes a copy of the value in its ASCII lower case equivalent. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To lowercase the value in-place, use [`make_ascii_lowercase`]. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = 65u8; + /// + /// assert_eq!(97, uppercase_a.to_ascii_lowercase()); + /// ``` + /// + /// [`make_ascii_lowercase`]: Self::make_ascii_lowercase + #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"] + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] + #[inline] + pub const fn to_ascii_lowercase(&self) -> u8 { + // Set the 6th bit if this is an uppercase letter + *self | (self.is_ascii_uppercase() as u8 * ASCII_CASE_MASK) + } + + /// Assumes self is ascii + #[inline] + pub(crate) const fn ascii_change_case_unchecked(&self) -> u8 { + *self ^ ASCII_CASE_MASK + } + + /// Checks that two values are an ASCII case-insensitive match. + /// + /// This is equivalent to `to_ascii_lowercase(a) == to_ascii_lowercase(b)`. + /// + /// # Examples + /// + /// ``` + /// let lowercase_a = 97u8; + /// let uppercase_a = 65u8; + /// + /// assert!(lowercase_a.eq_ignore_ascii_case(&uppercase_a)); + /// ``` + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] + #[inline] + pub const fn eq_ignore_ascii_case(&self, other: &u8) -> bool { + self.to_ascii_lowercase() == other.to_ascii_lowercase() + } + + /// Converts this value to its ASCII upper case equivalent in-place. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new uppercased value without modifying the existing one, use + /// [`to_ascii_uppercase`]. + /// + /// # Examples + /// + /// ``` + /// let mut byte = b'a'; + /// + /// byte.make_ascii_uppercase(); + /// + /// assert_eq!(b'A', byte); + /// ``` + /// + /// [`to_ascii_uppercase`]: Self::to_ascii_uppercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] + #[inline] + pub const fn make_ascii_uppercase(&mut self) { + *self = self.to_ascii_uppercase(); + } + + /// Converts this value to its ASCII lower case equivalent in-place. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new lowercased value without modifying the existing one, use + /// [`to_ascii_lowercase`]. + /// + /// # Examples + /// + /// ``` + /// let mut byte = b'A'; + /// + /// byte.make_ascii_lowercase(); + /// + /// assert_eq!(b'a', byte); + /// ``` + /// + /// [`to_ascii_lowercase`]: Self::to_ascii_lowercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] + #[inline] + pub const fn make_ascii_lowercase(&mut self) { + *self = self.to_ascii_lowercase(); + } + + /// Checks if the value is an ASCII alphabetic character: + /// + /// - U+0041 'A' ..= U+005A 'Z', or + /// - U+0061 'a' ..= U+007A 'z'. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = b'\x1b'; + /// + /// assert!(uppercase_a.is_ascii_alphabetic()); + /// assert!(uppercase_g.is_ascii_alphabetic()); + /// assert!(a.is_ascii_alphabetic()); + /// assert!(g.is_ascii_alphabetic()); + /// assert!(!zero.is_ascii_alphabetic()); + /// assert!(!percent.is_ascii_alphabetic()); + /// assert!(!space.is_ascii_alphabetic()); + /// assert!(!lf.is_ascii_alphabetic()); + /// assert!(!esc.is_ascii_alphabetic()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_alphabetic(&self) -> bool { + matches!(*self, b'A'..=b'Z' | b'a'..=b'z') + } + + /// Checks if the value is an ASCII uppercase character: + /// U+0041 'A' ..= U+005A 'Z'. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = b'\x1b'; + /// + /// assert!(uppercase_a.is_ascii_uppercase()); + /// assert!(uppercase_g.is_ascii_uppercase()); + /// assert!(!a.is_ascii_uppercase()); + /// assert!(!g.is_ascii_uppercase()); + /// assert!(!zero.is_ascii_uppercase()); + /// assert!(!percent.is_ascii_uppercase()); + /// assert!(!space.is_ascii_uppercase()); + /// assert!(!lf.is_ascii_uppercase()); + /// assert!(!esc.is_ascii_uppercase()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_uppercase(&self) -> bool { + matches!(*self, b'A'..=b'Z') + } + + /// Checks if the value is an ASCII lowercase character: + /// U+0061 'a' ..= U+007A 'z'. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = b'\x1b'; + /// + /// assert!(!uppercase_a.is_ascii_lowercase()); + /// assert!(!uppercase_g.is_ascii_lowercase()); + /// assert!(a.is_ascii_lowercase()); + /// assert!(g.is_ascii_lowercase()); + /// assert!(!zero.is_ascii_lowercase()); + /// assert!(!percent.is_ascii_lowercase()); + /// assert!(!space.is_ascii_lowercase()); + /// assert!(!lf.is_ascii_lowercase()); + /// assert!(!esc.is_ascii_lowercase()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_lowercase(&self) -> bool { + matches!(*self, b'a'..=b'z') + } + + /// Checks if the value is an ASCII alphanumeric character: + /// + /// - U+0041 'A' ..= U+005A 'Z', or + /// - U+0061 'a' ..= U+007A 'z', or + /// - U+0030 '0' ..= U+0039 '9'. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = b'\x1b'; + /// + /// assert!(uppercase_a.is_ascii_alphanumeric()); + /// assert!(uppercase_g.is_ascii_alphanumeric()); + /// assert!(a.is_ascii_alphanumeric()); + /// assert!(g.is_ascii_alphanumeric()); + /// assert!(zero.is_ascii_alphanumeric()); + /// assert!(!percent.is_ascii_alphanumeric()); + /// assert!(!space.is_ascii_alphanumeric()); + /// assert!(!lf.is_ascii_alphanumeric()); + /// assert!(!esc.is_ascii_alphanumeric()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_alphanumeric(&self) -> bool { + matches!(*self, b'0'..=b'9') | matches!(*self, b'A'..=b'Z') | matches!(*self, b'a'..=b'z') + } + + /// Checks if the value is an ASCII decimal digit: + /// U+0030 '0' ..= U+0039 '9'. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = b'\x1b'; + /// + /// assert!(!uppercase_a.is_ascii_digit()); + /// assert!(!uppercase_g.is_ascii_digit()); + /// assert!(!a.is_ascii_digit()); + /// assert!(!g.is_ascii_digit()); + /// assert!(zero.is_ascii_digit()); + /// assert!(!percent.is_ascii_digit()); + /// assert!(!space.is_ascii_digit()); + /// assert!(!lf.is_ascii_digit()); + /// assert!(!esc.is_ascii_digit()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_digit(&self) -> bool { + matches!(*self, b'0'..=b'9') + } + + /// Checks if the value is an ASCII octal digit: + /// U+0030 '0' ..= U+0037 '7'. + /// + /// # Examples + /// + /// ``` + /// #![feature(is_ascii_octdigit)] + /// + /// let uppercase_a = b'A'; + /// let a = b'a'; + /// let zero = b'0'; + /// let seven = b'7'; + /// let nine = b'9'; + /// let percent = b'%'; + /// let lf = b'\n'; + /// + /// assert!(!uppercase_a.is_ascii_octdigit()); + /// assert!(!a.is_ascii_octdigit()); + /// assert!(zero.is_ascii_octdigit()); + /// assert!(seven.is_ascii_octdigit()); + /// assert!(!nine.is_ascii_octdigit()); + /// assert!(!percent.is_ascii_octdigit()); + /// assert!(!lf.is_ascii_octdigit()); + /// ``` + #[must_use] + #[unstable(feature = "is_ascii_octdigit", issue = "101288")] + #[inline] + pub const fn is_ascii_octdigit(&self) -> bool { + matches!(*self, b'0'..=b'7') + } + + /// Checks if the value is an ASCII hexadecimal digit: + /// + /// - U+0030 '0' ..= U+0039 '9', or + /// - U+0041 'A' ..= U+0046 'F', or + /// - U+0061 'a' ..= U+0066 'f'. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = b'\x1b'; + /// + /// assert!(uppercase_a.is_ascii_hexdigit()); + /// assert!(!uppercase_g.is_ascii_hexdigit()); + /// assert!(a.is_ascii_hexdigit()); + /// assert!(!g.is_ascii_hexdigit()); + /// assert!(zero.is_ascii_hexdigit()); + /// assert!(!percent.is_ascii_hexdigit()); + /// assert!(!space.is_ascii_hexdigit()); + /// assert!(!lf.is_ascii_hexdigit()); + /// assert!(!esc.is_ascii_hexdigit()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_hexdigit(&self) -> bool { + matches!(*self, b'0'..=b'9') | matches!(*self, b'A'..=b'F') | matches!(*self, b'a'..=b'f') + } + + /// Checks if the value is an ASCII punctuation character: + /// + /// - U+0021 ..= U+002F `! " # $ % & ' ( ) * + , - . /`, or + /// - U+003A ..= U+0040 `: ; < = > ? @`, or + /// - U+005B ..= U+0060 `` [ \ ] ^ _ ` ``, or + /// - U+007B ..= U+007E `{ | } ~` + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = b'\x1b'; + /// + /// assert!(!uppercase_a.is_ascii_punctuation()); + /// assert!(!uppercase_g.is_ascii_punctuation()); + /// assert!(!a.is_ascii_punctuation()); + /// assert!(!g.is_ascii_punctuation()); + /// assert!(!zero.is_ascii_punctuation()); + /// assert!(percent.is_ascii_punctuation()); + /// assert!(!space.is_ascii_punctuation()); + /// assert!(!lf.is_ascii_punctuation()); + /// assert!(!esc.is_ascii_punctuation()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_punctuation(&self) -> bool { + matches!(*self, b'!'..=b'/') + | matches!(*self, b':'..=b'@') + | matches!(*self, b'['..=b'`') + | matches!(*self, b'{'..=b'~') + } + + /// Checks if the value is an ASCII graphic character: + /// U+0021 '!' ..= U+007E '~'. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = b'\x1b'; + /// + /// assert!(uppercase_a.is_ascii_graphic()); + /// assert!(uppercase_g.is_ascii_graphic()); + /// assert!(a.is_ascii_graphic()); + /// assert!(g.is_ascii_graphic()); + /// assert!(zero.is_ascii_graphic()); + /// assert!(percent.is_ascii_graphic()); + /// assert!(!space.is_ascii_graphic()); + /// assert!(!lf.is_ascii_graphic()); + /// assert!(!esc.is_ascii_graphic()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_graphic(&self) -> bool { + matches!(*self, b'!'..=b'~') + } + + /// Checks if the value is an ASCII whitespace character: + /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED, + /// U+000C FORM FEED, or U+000D CARRIAGE RETURN. + /// + /// Rust uses the WhatWG Infra Standard's [definition of ASCII + /// whitespace][infra-aw]. There are several other definitions in + /// wide use. For instance, [the POSIX locale][pct] includes + /// U+000B VERTICAL TAB as well as all the above characters, + /// but—from the very same specification—[the default rule for + /// "field splitting" in the Bourne shell][bfs] considers *only* + /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace. + /// + /// If you are writing a program that will process an existing + /// file format, check what that format's definition of whitespace is + /// before using this function. + /// + /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace + /// [pct]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01 + /// [bfs]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = b'\x1b'; + /// + /// assert!(!uppercase_a.is_ascii_whitespace()); + /// assert!(!uppercase_g.is_ascii_whitespace()); + /// assert!(!a.is_ascii_whitespace()); + /// assert!(!g.is_ascii_whitespace()); + /// assert!(!zero.is_ascii_whitespace()); + /// assert!(!percent.is_ascii_whitespace()); + /// assert!(space.is_ascii_whitespace()); + /// assert!(lf.is_ascii_whitespace()); + /// assert!(!esc.is_ascii_whitespace()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_whitespace(&self) -> bool { + matches!(*self, b'\t' | b'\n' | b'\x0C' | b'\r' | b' ') + } + + /// Checks if the value is an ASCII control character: + /// U+0000 NUL ..= U+001F UNIT SEPARATOR, or U+007F DELETE. + /// Note that most ASCII whitespace characters are control + /// characters, but SPACE is not. + /// + /// # Examples + /// + /// ``` + /// let uppercase_a = b'A'; + /// let uppercase_g = b'G'; + /// let a = b'a'; + /// let g = b'g'; + /// let zero = b'0'; + /// let percent = b'%'; + /// let space = b' '; + /// let lf = b'\n'; + /// let esc = b'\x1b'; + /// + /// assert!(!uppercase_a.is_ascii_control()); + /// assert!(!uppercase_g.is_ascii_control()); + /// assert!(!a.is_ascii_control()); + /// assert!(!g.is_ascii_control()); + /// assert!(!zero.is_ascii_control()); + /// assert!(!percent.is_ascii_control()); + /// assert!(!space.is_ascii_control()); + /// assert!(lf.is_ascii_control()); + /// assert!(esc.is_ascii_control()); + /// ``` + #[must_use] + #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] + #[inline] + pub const fn is_ascii_control(&self) -> bool { + matches!(*self, b'\0'..=b'\x1F' | b'\x7F') + } + + /// Returns an iterator that produces an escaped version of a `u8`, + /// treating it as an ASCII character. + /// + /// The behavior is identical to [`ascii::escape_default`]. + /// + /// # Examples + /// + /// ``` + /// + /// assert_eq!("0", b'0'.escape_ascii().to_string()); + /// assert_eq!("\\t", b'\t'.escape_ascii().to_string()); + /// assert_eq!("\\r", b'\r'.escape_ascii().to_string()); + /// assert_eq!("\\n", b'\n'.escape_ascii().to_string()); + /// assert_eq!("\\'", b'\''.escape_ascii().to_string()); + /// assert_eq!("\\\"", b'"'.escape_ascii().to_string()); + /// assert_eq!("\\\\", b'\\'.escape_ascii().to_string()); + /// assert_eq!("\\x9d", b'\x9d'.escape_ascii().to_string()); + /// ``` + #[must_use = "this returns the escaped byte as an iterator, \ + without modifying the original"] + #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] + #[inline] + pub fn escape_ascii(self) -> ascii::EscapeDefault { + ascii::escape_default(self) + } + + #[inline] + pub(crate) const fn is_utf8_char_boundary(self) -> bool { + // This is bit magic equivalent to: b < 128 || b >= 192 + (self as i8) >= -0x40 + } +} + +impl u16 { + uint_impl! { + Self = u16, + ActualT = u16, + SignedT = i16, + BITS = 16, + BITS_MINUS_ONE = 15, + MAX = 65535, + rot = 4, + rot_op = "0xa003", + rot_result = "0x3a", + swap_op = "0x1234", + swapped = "0x3412", + reversed = "0x2c48", + le_bytes = "[0x34, 0x12]", + be_bytes = "[0x12, 0x34]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } + widening_impl! { u16, u32, 16, unsigned } + midpoint_impl! { u16, u32, unsigned } + + /// Checks if the value is a Unicode surrogate code point, which are disallowed values for [`char`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(utf16_extra)] + /// + /// let low_non_surrogate = 0xA000u16; + /// let low_surrogate = 0xD800u16; + /// let high_surrogate = 0xDC00u16; + /// let high_non_surrogate = 0xE000u16; + /// + /// assert!(!low_non_surrogate.is_utf16_surrogate()); + /// assert!(low_surrogate.is_utf16_surrogate()); + /// assert!(high_surrogate.is_utf16_surrogate()); + /// assert!(!high_non_surrogate.is_utf16_surrogate()); + /// ``` + #[must_use] + #[unstable(feature = "utf16_extra", issue = "94919")] + #[inline] + pub const fn is_utf16_surrogate(self) -> bool { + matches!(self, 0xD800..=0xDFFF) + } +} + +impl u32 { + uint_impl! { + Self = u32, + ActualT = u32, + SignedT = i32, + BITS = 32, + BITS_MINUS_ONE = 31, + MAX = 4294967295, + rot = 8, + rot_op = "0x10000b3", + rot_result = "0xb301", + swap_op = "0x12345678", + swapped = "0x78563412", + reversed = "0x1e6a2c48", + le_bytes = "[0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } + widening_impl! { u32, u64, 32, unsigned } + midpoint_impl! { u32, u64, unsigned } +} + +impl u64 { + uint_impl! { + Self = u64, + ActualT = u64, + SignedT = i64, + BITS = 64, + BITS_MINUS_ONE = 63, + MAX = 18446744073709551615, + rot = 12, + rot_op = "0xaa00000000006e1", + rot_result = "0x6e10aa", + swap_op = "0x1234567890123456", + swapped = "0x5634129078563412", + reversed = "0x6a2c48091e6a2c48", + le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } + widening_impl! { u64, u128, 64, unsigned } + midpoint_impl! { u64, u128, unsigned } +} + +impl u128 { + uint_impl! { + Self = u128, + ActualT = u128, + SignedT = i128, + BITS = 128, + BITS_MINUS_ONE = 127, + MAX = 340282366920938463463374607431768211455, + rot = 16, + rot_op = "0x13f40000000000000000000000004f76", + rot_result = "0x4f7613f4", + swap_op = "0x12345678901234567890123456789012", + swapped = "0x12907856341290785634129078563412", + reversed = "0x48091e6a2c48091e6a2c48091e6a2c48", + le_bytes = "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ + 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } + midpoint_impl! { u128, unsigned } +} + +#[cfg(target_pointer_width = "16")] +impl usize { + uint_impl! { + Self = usize, + ActualT = u16, + SignedT = isize, + BITS = 16, + BITS_MINUS_ONE = 15, + MAX = 65535, + rot = 4, + rot_op = "0xa003", + rot_result = "0x3a", + swap_op = "0x1234", + swapped = "0x3412", + reversed = "0x2c48", + le_bytes = "[0x34, 0x12]", + be_bytes = "[0x12, 0x34]", + to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(), + from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(), + bound_condition = " on 16-bit targets", + } + widening_impl! { usize, u32, 16, unsigned } + midpoint_impl! { usize, u32, unsigned } +} + +#[cfg(target_pointer_width = "32")] +impl usize { + uint_impl! { + Self = usize, + ActualT = u32, + SignedT = isize, + BITS = 32, + BITS_MINUS_ONE = 31, + MAX = 4294967295, + rot = 8, + rot_op = "0x10000b3", + rot_result = "0xb301", + swap_op = "0x12345678", + swapped = "0x78563412", + reversed = "0x1e6a2c48", + le_bytes = "[0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78]", + to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(), + from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(), + bound_condition = " on 32-bit targets", + } + widening_impl! { usize, u64, 32, unsigned } + midpoint_impl! { usize, u64, unsigned } +} + +#[cfg(target_pointer_width = "64")] +impl usize { + uint_impl! { + Self = usize, + ActualT = u64, + SignedT = isize, + BITS = 64, + BITS_MINUS_ONE = 63, + MAX = 18446744073709551615, + rot = 12, + rot_op = "0xaa00000000006e1", + rot_result = "0x6e10aa", + swap_op = "0x1234567890123456", + swapped = "0x5634129078563412", + reversed = "0x6a2c48091e6a2c48", + le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(), + from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(), + bound_condition = " on 64-bit targets", + } + widening_impl! { usize, u128, 64, unsigned } + midpoint_impl! { usize, u128, unsigned } +} + +impl usize { + /// Returns an `usize` where every byte is equal to `x`. + #[inline] + pub(crate) const fn repeat_u8(x: u8) -> usize { + usize::from_ne_bytes([x; mem::size_of::()]) + } + + /// Returns an `usize` where every byte pair is equal to `x`. + #[inline] + pub(crate) const fn repeat_u16(x: u16) -> usize { + let mut r = 0usize; + let mut i = 0; + while i < mem::size_of::() { + // Use `wrapping_shl` to make it work on targets with 16-bit `usize` + r = r.wrapping_shl(16) | (x as usize); + i += 2; + } + r + } +} + +/// A classification of floating point numbers. +/// +/// This `enum` is used as the return type for [`f32::classify`] and [`f64::classify`]. See +/// their documentation for more. +/// +/// # Examples +/// +/// ``` +/// use std::num::FpCategory; +/// +/// let num = 12.4_f32; +/// let inf = f32::INFINITY; +/// let zero = 0f32; +/// let sub: f32 = 1.1754942e-38; +/// let nan = f32::NAN; +/// +/// assert_eq!(num.classify(), FpCategory::Normal); +/// assert_eq!(inf.classify(), FpCategory::Infinite); +/// assert_eq!(zero.classify(), FpCategory::Zero); +/// assert_eq!(sub.classify(), FpCategory::Subnormal); +/// assert_eq!(nan.classify(), FpCategory::Nan); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +pub enum FpCategory { + /// NaN (not a number): this value results from calculations like `(-1.0).sqrt()`. + /// + /// See [the documentation for `f32`](f32) for more information on the unusual properties + /// of NaN. + #[stable(feature = "rust1", since = "1.0.0")] + Nan, + + /// Positive or negative infinity, which often results from dividing a nonzero number + /// by zero. + #[stable(feature = "rust1", since = "1.0.0")] + Infinite, + + /// Positive or negative zero. + /// + /// See [the documentation for `f32`](f32) for more information on the signedness of zeroes. + #[stable(feature = "rust1", since = "1.0.0")] + Zero, + + /// “Subnormal” or “denormal” floating point representation (less precise, relative to + /// their magnitude, than [`Normal`]). + /// + /// Subnormal numbers are larger in magnitude than [`Zero`] but smaller in magnitude than all + /// [`Normal`] numbers. + /// + /// [`Normal`]: Self::Normal + /// [`Zero`]: Self::Zero + #[stable(feature = "rust1", since = "1.0.0")] + Subnormal, + + /// A regular floating point number, not any of the exceptional categories. + /// + /// The smallest positive normal numbers are [`f32::MIN_POSITIVE`] and [`f64::MIN_POSITIVE`], + /// and the largest positive normal numbers are [`f32::MAX`] and [`f64::MAX`]. (Unlike signed + /// integers, floating point numbers are symmetric in their range, so negating any of these + /// constants will produce their negative counterpart.) + #[stable(feature = "rust1", since = "1.0.0")] + Normal, +} + +macro_rules! from_str_radix_int_impl { + ($($t:ty)*) => {$( + #[stable(feature = "rust1", since = "1.0.0")] + impl FromStr for $t { + type Err = ParseIntError; + #[inline] + fn from_str(src: &str) -> Result { + <$t>::from_str_radix(src, 10) + } + } + )*} +} +from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 } + +/// Determines if a string of text of that length of that radix could be guaranteed to be +/// stored in the given type T. +/// Note that if the radix is known to the compiler, it is just the check of digits.len that +/// is done at runtime. +#[doc(hidden)] +#[inline(always)] +#[unstable(issue = "none", feature = "std_internals")] +pub const fn can_not_overflow(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool { + radix <= 16 && digits.len() <= mem::size_of::() * 2 - is_signed_ty as usize +} + +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cold] +#[track_caller] +const fn from_str_radix_panic(radix: u32) -> ! { + const_panic!( + "from_str_radix_int: must lie in the range `[2, 36]`", + "from_str_radix_int: must lie in the range `[2, 36]` - found {radix}", + radix: u32 = radix, + ) +} + +macro_rules! from_str_radix { + ($signedness:ident $($int_ty:ty)+) => {$( + impl $int_ty { + /// Converts a string slice in a given base to an integer. + /// + /// The string is expected to be an optional + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + " `+` or `-` " + } + if unsigned { + " `+` " + } + }] + /// sign followed by only digits. Leading and trailing non-digit characters (including + /// whitespace) represent an error. Underscores (which are accepted in rust literals) + /// also represent an error. + /// + /// Digits are a subset of these characters, depending on `radix`: + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// + /// This function panics if `radix` is not in the range from 2 to 36. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + #[doc = concat!("assert_eq!(", stringify!($int_ty), "::from_str_radix(\"A\", 16), Ok(10));")] + /// ``` + /// Trailing space returns error: + /// ``` + #[doc = concat!("assert!(", stringify!($int_ty), "::from_str_radix(\"1 \", 10).is_err());")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")] + #[inline] + pub const fn from_str_radix(src: &str, radix: u32) -> Result<$int_ty, ParseIntError> { + use self::IntErrorKind::*; + use self::ParseIntError as PIE; + + if 2 > radix || radix > 36 { + from_str_radix_panic(radix); + } + + if src.is_empty() { + return Err(PIE { kind: Empty }); + } + + #[allow(unused_comparisons)] + let is_signed_ty = 0 > <$int_ty>::MIN; + + // all valid digits are ascii, so we will just iterate over the utf8 bytes + // and cast them to chars. .to_digit() will safely return None for anything + // other than a valid ascii digit for the given radix, including the first-byte + // of multi-byte sequences + let src = src.as_bytes(); + + let (is_positive, mut digits) = match src { + [b'+' | b'-'] => { + return Err(PIE { kind: InvalidDigit }); + } + [b'+', rest @ ..] => (true, rest), + [b'-', rest @ ..] if is_signed_ty => (false, rest), + _ => (true, src), + }; + + let mut result = 0; + + macro_rules! unwrap_or_PIE { + ($option:expr, $kind:ident) => { + match $option { + Some(value) => value, + None => return Err(PIE { kind: $kind }), + } + }; + } + + if can_not_overflow::<$int_ty>(radix, is_signed_ty, digits) { + // If the len of the str is short compared to the range of the type + // we are parsing into, then we can be certain that an overflow will not occur. + // This bound is when `radix.pow(digits.len()) - 1 <= T::MAX` but the condition + // above is a faster (conservative) approximation of this. + // + // Consider radix 16 as it has the highest information density per digit and will thus overflow the earliest: + // `u8::MAX` is `ff` - any str of len 2 is guaranteed to not overflow. + // `i8::MAX` is `7f` - only a str of len 1 is guaranteed to not overflow. + macro_rules! run_unchecked_loop { + ($unchecked_additive_op:tt) => {{ + while let [c, rest @ ..] = digits { + result = result * (radix as $int_ty); + let x = unwrap_or_PIE!((*c as char).to_digit(radix), InvalidDigit); + result = result $unchecked_additive_op (x as $int_ty); + digits = rest; + } + }}; + } + if is_positive { + run_unchecked_loop!(+) + } else { + run_unchecked_loop!(-) + }; + } else { + macro_rules! run_checked_loop { + ($checked_additive_op:ident, $overflow_err:ident) => {{ + while let [c, rest @ ..] = digits { + // When `radix` is passed in as a literal, rather than doing a slow `imul` + // the compiler can use shifts if `radix` can be expressed as a + // sum of powers of 2 (x*10 can be written as x*8 + x*2). + // When the compiler can't use these optimisations, + // the latency of the multiplication can be hidden by issuing it + // before the result is needed to improve performance on + // modern out-of-order CPU as multiplication here is slower + // than the other instructions, we can get the end result faster + // doing multiplication first and let the CPU spends other cycles + // doing other computation and get multiplication result later. + let mul = result.checked_mul(radix as $int_ty); + let x = unwrap_or_PIE!((*c as char).to_digit(radix), InvalidDigit) as $int_ty; + result = unwrap_or_PIE!(mul, $overflow_err); + result = unwrap_or_PIE!(<$int_ty>::$checked_additive_op(result, x), $overflow_err); + digits = rest; + } + }}; + } + if is_positive { + run_checked_loop!(checked_add, PosOverflow) + } else { + run_checked_loop!(checked_sub, NegOverflow) + }; + } + Ok(result) + } + } + )+} +} + +from_str_radix! { unsigned u8 u16 u32 u64 u128 } +from_str_radix! { signed i8 i16 i32 i64 i128 } + +// Re-use the relevant implementation of from_str_radix for isize and usize to avoid outputting two +// identical functions. +macro_rules! from_str_radix_size_impl { + ($($signedness:ident $t:ident $size:ty),*) => {$( + impl $size { + /// Converts a string slice in a given base to an integer. + /// + /// The string is expected to be an optional + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + " `+` or `-` " + } + if unsigned { + " `+` " + } + }] + /// sign followed by only digits. Leading and trailing non-digit characters (including + /// whitespace) represent an error. Underscores (which are accepted in rust literals) + /// also represent an error. + /// + /// Digits are a subset of these characters, depending on `radix`: + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// + /// This function panics if `radix` is not in the range from 2 to 36. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + #[doc = concat!("assert_eq!(", stringify!($size), "::from_str_radix(\"A\", 16), Ok(10));")] + /// ``` + /// Trailing space returns error: + /// ``` + #[doc = concat!("assert!(", stringify!($size), "::from_str_radix(\"1 \", 10).is_err());")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")] + #[inline] + pub const fn from_str_radix(src: &str, radix: u32) -> Result<$size, ParseIntError> { + match <$t>::from_str_radix(src, radix) { + Ok(x) => Ok(x as $size), + Err(e) => Err(e), + } + } + })*} +} + +#[cfg(target_pointer_width = "16")] +from_str_radix_size_impl! { signed i16 isize, unsigned u16 usize } +#[cfg(target_pointer_width = "32")] +from_str_radix_size_impl! { signed i32 isize, unsigned u32 usize } +#[cfg(target_pointer_width = "64")] +from_str_radix_size_impl! { signed i64 isize, unsigned u64 usize } diff --git a/CoqOfRust/core/num/nonzero.rs b/CoqOfRust/core/num/nonzero.rs new file mode 100644 index 000000000..a9294306b --- /dev/null +++ b/CoqOfRust/core/num/nonzero.rs @@ -0,0 +1,2231 @@ +//! Definitions of integer that is known not to equal zero. + +use super::{IntErrorKind, ParseIntError}; +use crate::cmp::Ordering; +use crate::hash::{Hash, Hasher}; +use crate::marker::{Freeze, StructuralPartialEq}; +use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign}; +use crate::panic::{RefUnwindSafe, UnwindSafe}; +use crate::str::FromStr; +use crate::{fmt, intrinsics, ptr, ub_checks}; + +/// A marker trait for primitive types which can be zero. +/// +/// This is an implementation detail for [NonZero]\ which may disappear or be replaced at any time. +/// +/// # Safety +/// +/// Types implementing this trait must be primitives that are valid when zeroed. +/// +/// The associated `Self::NonZeroInner` type must have the same size+align as `Self`, +/// but with a niche and bit validity making it so the following `transmutes` are sound: +/// +/// - `Self::NonZeroInner` to `Option` +/// - `Option` to `Self` +/// +/// (And, consequently, `Self::NonZeroInner` to `Self`.) +#[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" +)] +pub unsafe trait ZeroablePrimitive: Sized + Copy + private::Sealed { + #[doc(hidden)] + type NonZeroInner: Sized + Copy; +} + +macro_rules! impl_zeroable_primitive { + ($($NonZeroInner:ident ( $primitive:ty )),+ $(,)?) => { + mod private { + use super::*; + + #[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" + )] + pub trait Sealed {} + + $( + // This inner type is never shown directly, so intentionally does not have Debug + #[expect(missing_debug_implementations)] + // Since this struct is non-generic and derives Copy, + // the derived Clone is `*self` and thus doesn't field-project. + #[derive(Clone, Copy)] + #[repr(transparent)] + #[rustc_layout_scalar_valid_range_start(1)] + #[rustc_nonnull_optimization_guaranteed] + #[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" + )] + pub struct $NonZeroInner($primitive); + + // This is required to allow matching a constant. We don't get it from a derive + // because the derived `PartialEq` would do a field projection, which is banned + // by . + #[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" + )] + impl StructuralPartialEq for $NonZeroInner {} + )+ + } + + $( + #[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" + )] + impl private::Sealed for $primitive {} + + #[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" + )] + unsafe impl ZeroablePrimitive for $primitive { + type NonZeroInner = private::$NonZeroInner; + } + )+ + }; +} + +impl_zeroable_primitive!( + NonZeroU8Inner(u8), + NonZeroU16Inner(u16), + NonZeroU32Inner(u32), + NonZeroU64Inner(u64), + NonZeroU128Inner(u128), + NonZeroUsizeInner(usize), + NonZeroI8Inner(i8), + NonZeroI16Inner(i16), + NonZeroI32Inner(i32), + NonZeroI64Inner(i64), + NonZeroI128Inner(i128), + NonZeroIsizeInner(isize), +); + +/// A value that is known not to equal zero. +/// +/// This enables some memory layout optimization. +/// For example, `Option>` is the same size as `u32`: +/// +/// ``` +/// use core::{mem::size_of, num::NonZero}; +/// +/// assert_eq!(size_of::>>(), size_of::()); +/// ``` +#[stable(feature = "generic_nonzero", since = "1.79.0")] +#[repr(transparent)] +#[rustc_nonnull_optimization_guaranteed] +#[rustc_diagnostic_item = "NonZero"] +pub struct NonZero(T::NonZeroInner); + +macro_rules! impl_nonzero_fmt { + ($(#[$Attribute:meta] $Trait:ident)*) => { + $( + #[$Attribute] + impl fmt::$Trait for NonZero + where + T: ZeroablePrimitive + fmt::$Trait, + { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.get().fmt(f) + } + } + )* + }; +} + +impl_nonzero_fmt! { + #[stable(feature = "nonzero", since = "1.28.0")] + Debug + #[stable(feature = "nonzero", since = "1.28.0")] + Display + #[stable(feature = "nonzero", since = "1.28.0")] + Binary + #[stable(feature = "nonzero", since = "1.28.0")] + Octal + #[stable(feature = "nonzero", since = "1.28.0")] + LowerHex + #[stable(feature = "nonzero", since = "1.28.0")] + UpperHex + #[stable(feature = "nonzero_fmt_exp", since = "1.84.0")] + LowerExp + #[stable(feature = "nonzero_fmt_exp", since = "1.84.0")] + UpperExp +} + +macro_rules! impl_nonzero_auto_trait { + (unsafe $Trait:ident) => { + #[stable(feature = "nonzero", since = "1.28.0")] + unsafe impl $Trait for NonZero where T: ZeroablePrimitive + $Trait {} + }; + ($Trait:ident) => { + #[stable(feature = "nonzero", since = "1.28.0")] + impl $Trait for NonZero where T: ZeroablePrimitive + $Trait {} + }; +} + +// Implement auto-traits manually based on `T` to avoid docs exposing +// the `ZeroablePrimitive::NonZeroInner` implementation detail. +impl_nonzero_auto_trait!(unsafe Freeze); +impl_nonzero_auto_trait!(RefUnwindSafe); +impl_nonzero_auto_trait!(unsafe Send); +impl_nonzero_auto_trait!(unsafe Sync); +impl_nonzero_auto_trait!(Unpin); +impl_nonzero_auto_trait!(UnwindSafe); + +#[stable(feature = "nonzero", since = "1.28.0")] +impl Clone for NonZero +where + T: ZeroablePrimitive, +{ + #[inline] + fn clone(&self) -> Self { + *self + } +} + +#[stable(feature = "nonzero", since = "1.28.0")] +impl Copy for NonZero where T: ZeroablePrimitive {} + +#[stable(feature = "nonzero", since = "1.28.0")] +impl PartialEq for NonZero +where + T: ZeroablePrimitive + PartialEq, +{ + #[inline] + fn eq(&self, other: &Self) -> bool { + self.get() == other.get() + } + + #[inline] + fn ne(&self, other: &Self) -> bool { + self.get() != other.get() + } +} + +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralPartialEq for NonZero where T: ZeroablePrimitive + StructuralPartialEq {} + +#[stable(feature = "nonzero", since = "1.28.0")] +impl Eq for NonZero where T: ZeroablePrimitive + Eq {} + +#[stable(feature = "nonzero", since = "1.28.0")] +impl PartialOrd for NonZero +where + T: ZeroablePrimitive + PartialOrd, +{ + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + self.get().partial_cmp(&other.get()) + } + + #[inline] + fn lt(&self, other: &Self) -> bool { + self.get() < other.get() + } + + #[inline] + fn le(&self, other: &Self) -> bool { + self.get() <= other.get() + } + + #[inline] + fn gt(&self, other: &Self) -> bool { + self.get() > other.get() + } + + #[inline] + fn ge(&self, other: &Self) -> bool { + self.get() >= other.get() + } +} + +#[stable(feature = "nonzero", since = "1.28.0")] +impl Ord for NonZero +where + T: ZeroablePrimitive + Ord, +{ + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.get().cmp(&other.get()) + } + + #[inline] + fn max(self, other: Self) -> Self { + // SAFETY: The maximum of two non-zero values is still non-zero. + unsafe { Self::new_unchecked(self.get().max(other.get())) } + } + + #[inline] + fn min(self, other: Self) -> Self { + // SAFETY: The minimum of two non-zero values is still non-zero. + unsafe { Self::new_unchecked(self.get().min(other.get())) } + } + + #[inline] + fn clamp(self, min: Self, max: Self) -> Self { + // SAFETY: A non-zero value clamped between two non-zero values is still non-zero. + unsafe { Self::new_unchecked(self.get().clamp(min.get(), max.get())) } + } +} + +#[stable(feature = "nonzero", since = "1.28.0")] +impl Hash for NonZero +where + T: ZeroablePrimitive + Hash, +{ + #[inline] + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.get().hash(state) + } +} + +#[stable(feature = "from_nonzero", since = "1.31.0")] +impl From> for T +where + T: ZeroablePrimitive, +{ + #[inline] + fn from(nonzero: NonZero) -> Self { + // Call `get` method to keep range information. + nonzero.get() + } +} + +#[stable(feature = "nonzero_bitor", since = "1.45.0")] +impl BitOr for NonZero +where + T: ZeroablePrimitive + BitOr, +{ + type Output = Self; + + #[inline] + fn bitor(self, rhs: Self) -> Self::Output { + // SAFETY: Bitwise OR of two non-zero values is still non-zero. + unsafe { Self::new_unchecked(self.get() | rhs.get()) } + } +} + +#[stable(feature = "nonzero_bitor", since = "1.45.0")] +impl BitOr for NonZero +where + T: ZeroablePrimitive + BitOr, +{ + type Output = Self; + + #[inline] + fn bitor(self, rhs: T) -> Self::Output { + // SAFETY: Bitwise OR of a non-zero value with anything is still non-zero. + unsafe { Self::new_unchecked(self.get() | rhs) } + } +} + +#[stable(feature = "nonzero_bitor", since = "1.45.0")] +impl BitOr> for T +where + T: ZeroablePrimitive + BitOr, +{ + type Output = NonZero; + + #[inline] + fn bitor(self, rhs: NonZero) -> Self::Output { + // SAFETY: Bitwise OR of anything with a non-zero value is still non-zero. + unsafe { NonZero::new_unchecked(self | rhs.get()) } + } +} + +#[stable(feature = "nonzero_bitor", since = "1.45.0")] +impl BitOrAssign for NonZero +where + T: ZeroablePrimitive, + Self: BitOr, +{ + #[inline] + fn bitor_assign(&mut self, rhs: Self) { + *self = *self | rhs; + } +} + +#[stable(feature = "nonzero_bitor", since = "1.45.0")] +impl BitOrAssign for NonZero +where + T: ZeroablePrimitive, + Self: BitOr, +{ + #[inline] + fn bitor_assign(&mut self, rhs: T) { + *self = *self | rhs; + } +} + +impl NonZero +where + T: ZeroablePrimitive, +{ + /// Creates a non-zero if the given value is not zero. + #[stable(feature = "nonzero", since = "1.28.0")] + #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] + #[must_use] + #[inline] + pub const fn new(n: T) -> Option { + // SAFETY: Memory layout optimization guarantees that `Option>` has + // the same layout and size as `T`, with `0` representing `None`. + unsafe { intrinsics::transmute_unchecked(n) } + } + + /// Creates a non-zero without checking whether the value is non-zero. + /// This results in undefined behavior if the value is zero. + /// + /// # Safety + /// + /// The value must not be zero. + #[stable(feature = "nonzero", since = "1.28.0")] + #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] + #[must_use] + #[inline] + pub const unsafe fn new_unchecked(n: T) -> Self { + match Self::new(n) { + Some(n) => n, + None => { + // SAFETY: The caller guarantees that `n` is non-zero, so this is unreachable. + unsafe { + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "NonZero::new_unchecked requires the argument to be non-zero", + () => false, + ); + intrinsics::unreachable() + } + } + } + } + + /// Converts a reference to a non-zero mutable reference + /// if the referenced value is not zero. + #[unstable(feature = "nonzero_from_mut", issue = "106290")] + #[must_use] + #[inline] + pub fn from_mut(n: &mut T) -> Option<&mut Self> { + // SAFETY: Memory layout optimization guarantees that `Option>` has + // the same layout and size as `T`, with `0` representing `None`. + let opt_n = unsafe { &mut *(ptr::from_mut(n).cast::>()) }; + + opt_n.as_mut() + } + + /// Converts a mutable reference to a non-zero mutable reference + /// without checking whether the referenced value is non-zero. + /// This results in undefined behavior if the referenced value is zero. + /// + /// # Safety + /// + /// The referenced value must not be zero. + #[unstable(feature = "nonzero_from_mut", issue = "106290")] + #[must_use] + #[inline] + pub unsafe fn from_mut_unchecked(n: &mut T) -> &mut Self { + match Self::from_mut(n) { + Some(n) => n, + None => { + // SAFETY: The caller guarantees that `n` references a value that is non-zero, so this is unreachable. + unsafe { + ub_checks::assert_unsafe_precondition!( + check_library_ub, + "NonZero::from_mut_unchecked requires the argument to dereference as non-zero", + () => false, + ); + intrinsics::unreachable() + } + } + } + } + + /// Returns the contained value as a primitive type. + #[stable(feature = "nonzero", since = "1.28.0")] + #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] + #[inline] + pub const fn get(self) -> T { + // Rustc can set range metadata only if it loads `self` from + // memory somewhere. If the value of `self` was from by-value argument + // of some not-inlined function, LLVM don't have range metadata + // to understand that the value cannot be zero. + // + // Using the transmute `assume`s the range at runtime. + // + // Even once LLVM supports `!range` metadata for function arguments + // (see ), this can't + // be `.0` because MCP#807 bans field-projecting into `scalar_valid_range` + // types, and it arguably wouldn't want to be anyway because if this is + // MIR-inlined, there's no opportunity to put that argument metadata anywhere. + // + // The good answer here will eventually be pattern types, which will hopefully + // allow it to go back to `.0`, maybe with a cast of some sort. + // + // SAFETY: `ZeroablePrimitive` guarantees that the size and bit validity + // of `.0` is such that this transmute is sound. + unsafe { intrinsics::transmute_unchecked(self) } + } +} + +macro_rules! nonzero_integer { + ( + #[$stability:meta] + Self = $Ty:ident, + Primitive = $signedness:ident $Int:ident, + UnsignedPrimitive = $Uint:ty, + + // Used in doc comments. + rot = $rot:literal, + rot_op = $rot_op:literal, + rot_result = $rot_result:literal, + swap_op = $swap_op:literal, + swapped = $swapped:literal, + reversed = $reversed:literal, + leading_zeros_test = $leading_zeros_test:expr, + ) => { + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + concat!("An [`", stringify!($Int), "`] that is known not to equal zero.") + } + if unsigned { + concat!("A [`", stringify!($Int), "`] that is known not to equal zero.") + } + }] + /// + /// This enables some memory layout optimization. + #[doc = concat!("For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:")] + /// + /// ```rust + /// use std::mem::size_of; + #[doc = concat!("assert_eq!(size_of::>(), size_of::<", stringify!($Int), ">());")] + /// ``` + /// + /// # Layout + /// + #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")] + /// with the exception that `0` is not a valid instance. + #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`,")] + /// including in FFI. + /// + /// Thanks to the [null pointer optimization], + #[doc = concat!("`", stringify!($Ty), "` and `Option<", stringify!($Ty), ">`")] + /// are guaranteed to have the same size and alignment: + /// + /// ``` + /// # use std::mem::{size_of, align_of}; + #[doc = concat!("use std::num::", stringify!($Ty), ";")] + /// + #[doc = concat!("assert_eq!(size_of::<", stringify!($Ty), ">(), size_of::>());")] + #[doc = concat!("assert_eq!(align_of::<", stringify!($Ty), ">(), align_of::>());")] + /// ``` + /// + /// [null pointer optimization]: crate::option#representation + #[$stability] + pub type $Ty = NonZero<$Int>; + + impl NonZero<$Int> { + /// The size of this non-zero integer type in bits. + /// + #[doc = concat!("This value is equal to [`", stringify!($Int), "::BITS`].")] + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::BITS, ", stringify!($Int), "::BITS);")] + /// ``` + #[stable(feature = "nonzero_bits", since = "1.67.0")] + pub const BITS: u32 = <$Int>::BITS; + + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let n = NonZero::<", stringify!($Int), ">::new(", $leading_zeros_test, ")?;")] + /// + /// assert_eq!(n.leading_zeros(), 0); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn leading_zeros(self) -> u32 { + // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`. + unsafe { + intrinsics::ctlz_nonzero(self.get() as $Uint) + } + } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let n = NonZero::<", stringify!($Int), ">::new(0b0101000)?;")] + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn trailing_zeros(self) -> u32 { + // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. + unsafe { + intrinsics::cttz_nonzero(self.get() as $Uint) + } + } + + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(non_zero_count_ones)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let a = NonZero::<", stringify!($Int), ">::new(0b100_0000)?;")] + #[doc = concat!("let b = NonZero::<", stringify!($Int), ">::new(0b100_0011)?;")] + /// + /// assert_eq!(a.count_ones(), NonZero::new(1)?); + /// assert_eq!(b.count_ones(), NonZero::new(3)?); + /// # Some(()) + /// # } + /// ``` + /// + #[unstable(feature = "non_zero_count_ones", issue = "120287")] + #[doc(alias = "popcount")] + #[doc(alias = "popcnt")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn count_ones(self) -> NonZero { + // SAFETY: + // `self` is non-zero, which means it has at least one bit set, which means + // that the result of `count_ones` is non-zero. + unsafe { NonZero::new_unchecked(self.get().count_ones()) } + } + + /// Shifts the bits to the left by a specified amount, `n`, + /// wrapping the truncated bits to the end of the resulting integer. + /// + /// Please note this isn't the same operation as the `<<` shifting operator! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(nonzero_bitwise)] + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let n = NonZero::new(", $rot_op, stringify!($Int), ")?;")] + #[doc = concat!("let m = NonZero::new(", $rot_result, ")?;")] + /// + #[doc = concat!("assert_eq!(n.rotate_left(", $rot, "), m);")] + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_bitwise", issue = "128281")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn rotate_left(self, n: u32) -> Self { + let result = self.get().rotate_left(n); + // SAFETY: Rotating bits preserves the property int > 0. + unsafe { Self::new_unchecked(result) } + } + + /// Shifts the bits to the right by a specified amount, `n`, + /// wrapping the truncated bits to the beginning of the resulting + /// integer. + /// + /// Please note this isn't the same operation as the `>>` shifting operator! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(nonzero_bitwise)] + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let n = NonZero::new(", $rot_result, stringify!($Int), ")?;")] + #[doc = concat!("let m = NonZero::new(", $rot_op, ")?;")] + /// + #[doc = concat!("assert_eq!(n.rotate_right(", $rot, "), m);")] + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_bitwise", issue = "128281")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn rotate_right(self, n: u32) -> Self { + let result = self.get().rotate_right(n); + // SAFETY: Rotating bits preserves the property int > 0. + unsafe { Self::new_unchecked(result) } + } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(nonzero_bitwise)] + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let n = NonZero::new(", $swap_op, stringify!($Int), ")?;")] + /// let m = n.swap_bytes(); + /// + #[doc = concat!("assert_eq!(m, NonZero::new(", $swapped, ")?);")] + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_bitwise", issue = "128281")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn swap_bytes(self) -> Self { + let result = self.get().swap_bytes(); + // SAFETY: Shuffling bytes preserves the property int > 0. + unsafe { Self::new_unchecked(result) } + } + + /// Reverses the order of bits in the integer. The least significant bit becomes the most significant bit, + /// second least-significant bit becomes second most-significant bit, etc. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(nonzero_bitwise)] + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let n = NonZero::new(", $swap_op, stringify!($Int), ")?;")] + /// let m = n.reverse_bits(); + /// + #[doc = concat!("assert_eq!(m, NonZero::new(", $reversed, ")?);")] + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_bitwise", issue = "128281")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn reverse_bits(self) -> Self { + let result = self.get().reverse_bits(); + // SAFETY: Reversing bits preserves the property int > 0. + unsafe { Self::new_unchecked(result) } + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(nonzero_bitwise)] + /// # use std::num::NonZero; + #[doc = concat!("use std::num::", stringify!($Ty), ";")] + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let n = NonZero::new(0x1A", stringify!($Int), ")?;")] + /// + /// if cfg!(target_endian = "big") { + #[doc = concat!(" assert_eq!(", stringify!($Ty), "::from_be(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(", stringify!($Ty), "::from_be(n), n.swap_bytes())")] + /// } + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_bitwise", issue = "128281")] + #[must_use] + #[inline(always)] + pub const fn from_be(x: Self) -> Self { + let result = $Int::from_be(x.get()); + // SAFETY: Shuffling bytes preserves the property int > 0. + unsafe { Self::new_unchecked(result) } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(nonzero_bitwise)] + /// # use std::num::NonZero; + #[doc = concat!("use std::num::", stringify!($Ty), ";")] + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let n = NonZero::new(0x1A", stringify!($Int), ")?;")] + /// + /// if cfg!(target_endian = "little") { + #[doc = concat!(" assert_eq!(", stringify!($Ty), "::from_le(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(", stringify!($Ty), "::from_le(n), n.swap_bytes())")] + /// } + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_bitwise", issue = "128281")] + #[must_use] + #[inline(always)] + pub const fn from_le(x: Self) -> Self { + let result = $Int::from_le(x.get()); + // SAFETY: Shuffling bytes preserves the property int > 0. + unsafe { Self::new_unchecked(result) } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(nonzero_bitwise)] + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let n = NonZero::new(0x1A", stringify!($Int), ")?;")] + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_bitwise", issue = "128281")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn to_be(self) -> Self { + let result = self.get().to_be(); + // SAFETY: Shuffling bytes preserves the property int > 0. + unsafe { Self::new_unchecked(result) } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(nonzero_bitwise)] + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let n = NonZero::new(0x1A", stringify!($Int), ")?;")] + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_bitwise", issue = "128281")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn to_le(self) -> Self { + let result = self.get().to_le(); + // SAFETY: Shuffling bytes preserves the property int > 0. + unsafe { Self::new_unchecked(result) } + } + + nonzero_integer_signedness_dependent_methods! { + Primitive = $signedness $Int, + UnsignedPrimitive = $Uint, + } + + /// Multiplies two non-zero integers together. + /// Checks for overflow and returns [`None`] on overflow. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")] + #[doc = concat!("let four = NonZero::new(4", stringify!($Int), ")?;")] + #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(four), two.checked_mul(two)); + /// assert_eq!(None, max.checked_mul(two)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_mul(self, other: Self) -> Option { + if let Some(result) = self.get().checked_mul(other.get()) { + // SAFETY: + // - `checked_mul` returns `None` on overflow + // - `self` and `other` are non-zero + // - the only way to get zero from a multiplication without overflow is for one + // of the sides to be zero + // + // So the result cannot be zero. + Some(unsafe { Self::new_unchecked(result) }) + } else { + None + } + } + + /// Multiplies two non-zero integers together. + #[doc = concat!("Return [`NonZero::<", stringify!($Int), ">::MAX`] on overflow.")] + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")] + #[doc = concat!("let four = NonZero::new(4", stringify!($Int), ")?;")] + #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(four, two.saturating_mul(two)); + /// assert_eq!(max, four.saturating_mul(max)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_mul(self, other: Self) -> Self { + // SAFETY: + // - `saturating_mul` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, + // all of which are non-zero + // - `self` and `other` are non-zero + // - the only way to get zero from a multiplication without overflow is for one + // of the sides to be zero + // + // So the result cannot be zero. + unsafe { Self::new_unchecked(self.get().saturating_mul(other.get())) } + } + + /// Multiplies two non-zero integers together, + /// assuming overflow cannot occur. + /// Overflow is unchecked, and it is undefined behavior to overflow + /// *even if the result would wrap to a non-zero value*. + /// The behavior is undefined as soon as + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + concat!("`self * rhs > ", stringify!($Int), "::MAX`, ", + "or `self * rhs < ", stringify!($Int), "::MIN`.") + } + if unsigned { + concat!("`self * rhs > ", stringify!($Int), "::MAX`.") + } + }] + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")] + #[doc = concat!("let four = NonZero::new(4", stringify!($Int), ")?;")] + /// + /// assert_eq!(four, unsafe { two.unchecked_mul(two) }); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const unsafe fn unchecked_mul(self, other: Self) -> Self { + // SAFETY: The caller ensures there is no overflow. + unsafe { Self::new_unchecked(self.get().unchecked_mul(other.get())) } + } + + /// Raises non-zero value to an integer power. + /// Checks for overflow and returns [`None`] on overflow. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ")?;")] + #[doc = concat!("let twenty_seven = NonZero::new(27", stringify!($Int), ")?;")] + #[doc = concat!("let half_max = NonZero::new(", stringify!($Int), "::MAX / 2)?;")] + /// + /// assert_eq!(Some(twenty_seven), three.checked_pow(3)); + /// assert_eq!(None, half_max.checked_pow(3)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_pow(self, other: u32) -> Option { + if let Some(result) = self.get().checked_pow(other) { + // SAFETY: + // - `checked_pow` returns `None` on overflow/underflow + // - `self` is non-zero + // - the only way to get zero from an exponentiation without overflow is + // for base to be zero + // + // So the result cannot be zero. + Some(unsafe { Self::new_unchecked(result) }) + } else { + None + } + } + + /// Raise non-zero value to an integer power. + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + concat!("Return [`NonZero::<", stringify!($Int), ">::MIN`] ", + "or [`NonZero::<", stringify!($Int), ">::MAX`] on overflow.") + } + if unsigned { + concat!("Return [`NonZero::<", stringify!($Int), ">::MAX`] on overflow.") + } + }] + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ")?;")] + #[doc = concat!("let twenty_seven = NonZero::new(27", stringify!($Int), ")?;")] + #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(twenty_seven, three.saturating_pow(3)); + /// assert_eq!(max, max.saturating_pow(3)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_pow(self, other: u32) -> Self { + // SAFETY: + // - `saturating_pow` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, + // all of which are non-zero + // - `self` is non-zero + // - the only way to get zero from an exponentiation without overflow is + // for base to be zero + // + // So the result cannot be zero. + unsafe { Self::new_unchecked(self.get().saturating_pow(other)) } + } + } + + #[stable(feature = "nonzero_parse", since = "1.35.0")] + impl FromStr for NonZero<$Int> { + type Err = ParseIntError; + fn from_str(src: &str) -> Result { + Self::new(<$Int>::from_str_radix(src, 10)?) + .ok_or(ParseIntError { + kind: IntErrorKind::Zero + }) + } + } + + nonzero_integer_signedness_dependent_impls!($signedness $Int); + }; + + ( + Self = $Ty:ident, + Primitive = unsigned $Int:ident, + rot = $rot:literal, + rot_op = $rot_op:literal, + rot_result = $rot_result:literal, + swap_op = $swap_op:literal, + swapped = $swapped:literal, + reversed = $reversed:literal, + $(,)? + ) => { + nonzero_integer! { + #[stable(feature = "nonzero", since = "1.28.0")] + Self = $Ty, + Primitive = unsigned $Int, + UnsignedPrimitive = $Int, + rot = $rot, + rot_op = $rot_op, + rot_result = $rot_result, + swap_op = $swap_op, + swapped = $swapped, + reversed = $reversed, + leading_zeros_test = concat!(stringify!($Int), "::MAX"), + } + }; + + ( + Self = $Ty:ident, + Primitive = signed $Int:ident, + UnsignedPrimitive = $UInt:ident, + rot = $rot:literal, + rot_op = $rot_op:literal, + rot_result = $rot_result:literal, + swap_op = $swap_op:literal, + swapped = $swapped:literal, + reversed = $reversed:literal, + ) => { + nonzero_integer! { + #[stable(feature = "signed_nonzero", since = "1.34.0")] + Self = $Ty, + Primitive = signed $Int, + UnsignedPrimitive = $UInt, + rot = $rot, + rot_op = $rot_op, + rot_result = $rot_result, + swap_op = $swap_op, + swapped = $swapped, + reversed = $reversed, + leading_zeros_test = concat!("-1", stringify!($Int)), + } + }; +} + +macro_rules! nonzero_integer_signedness_dependent_impls { + // Impls for unsigned nonzero types only. + (unsigned $Int:ty) => { + #[stable(feature = "nonzero_div", since = "1.51.0")] + impl Div> for $Int { + type Output = $Int; + + /// This operation rounds towards zero, truncating any fractional + /// part of the exact result, and cannot panic. + #[inline] + fn div(self, other: NonZero<$Int>) -> $Int { + // SAFETY: Division by zero is checked because `other` is non-zero, + // and MIN/-1 is checked because `self` is an unsigned int. + unsafe { intrinsics::unchecked_div(self, other.get()) } + } + } + + #[stable(feature = "nonzero_div_assign", since = "1.79.0")] + impl DivAssign> for $Int { + /// This operation rounds towards zero, truncating any fractional + /// part of the exact result, and cannot panic. + #[inline] + fn div_assign(&mut self, other: NonZero<$Int>) { + *self = *self / other; + } + } + + #[stable(feature = "nonzero_div", since = "1.51.0")] + impl Rem> for $Int { + type Output = $Int; + + /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. + #[inline] + fn rem(self, other: NonZero<$Int>) -> $Int { + // SAFETY: Remainder by zero is checked because `other` is non-zero, + // and MIN/-1 is checked because `self` is an unsigned int. + unsafe { intrinsics::unchecked_rem(self, other.get()) } + } + } + + #[stable(feature = "nonzero_div_assign", since = "1.79.0")] + impl RemAssign> for $Int { + /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. + #[inline] + fn rem_assign(&mut self, other: NonZero<$Int>) { + *self = *self % other; + } + } + + impl NonZero<$Int> { + /// Calculates the quotient of `self` and `rhs`, rounding the result towards positive infinity. + /// + /// The result is guaranteed to be non-zero. + /// + /// # Examples + /// + /// ``` + /// # #![feature(unsigned_nonzero_div_ceil)] + /// # use std::num::NonZero; + #[doc = concat!("let one = NonZero::new(1", stringify!($Int), ").unwrap();")] + #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX).unwrap();")] + /// assert_eq!(one.div_ceil(max), one); + /// + #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ").unwrap();")] + #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ").unwrap();")] + /// assert_eq!(three.div_ceil(two), two); + /// ``` + #[unstable(feature = "unsigned_nonzero_div_ceil", issue = "132968")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn div_ceil(self, rhs: Self) -> Self { + let v = self.get().div_ceil(rhs.get()); + // SAFETY: ceiled division of two positive integers can never be zero. + unsafe { Self::new_unchecked(v) } + } + } + }; + // Impls for signed nonzero types only. + (signed $Int:ty) => { + #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] + impl Neg for NonZero<$Int> { + type Output = Self; + + #[inline] + fn neg(self) -> Self { + // SAFETY: negation of nonzero cannot yield zero values. + unsafe { Self::new_unchecked(self.get().neg()) } + } + } + + forward_ref_unop! { impl Neg, neg for NonZero<$Int>, + #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] } + }; +} + +#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5974 +macro_rules! nonzero_integer_signedness_dependent_methods { + // Associated items for unsigned nonzero types only. + ( + Primitive = unsigned $Int:ident, + UnsignedPrimitive = $Uint:ty, + ) => { + /// The smallest value that can be represented by this non-zero + /// integer type, 1. + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::MIN.get(), 1", stringify!($Int), ");")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MIN: Self = Self::new(1).unwrap(); + + /// The largest value that can be represented by this non-zero + /// integer type, + #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::MAX.get(), ", stringify!($Int), "::MAX);")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); + + /// Adds an unsigned integer to a non-zero value. + /// Checks for overflow and returns [`None`] on overflow. + /// As a consequence, the result cannot wrap to zero. + /// + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = NonZero::new(1", stringify!($Int), ")?;")] + #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")] + #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(two), one.checked_add(1)); + /// assert_eq!(None, max.checked_add(1)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_add(self, other: $Int) -> Option { + if let Some(result) = self.get().checked_add(other) { + // SAFETY: + // - `checked_add` returns `None` on overflow + // - `self` is non-zero + // - the only way to get zero from an addition without overflow is for both + // sides to be zero + // + // So the result cannot be zero. + Some(unsafe { Self::new_unchecked(result) }) + } else { + None + } + } + + /// Adds an unsigned integer to a non-zero value. + #[doc = concat!("Return [`NonZero::<", stringify!($Int), ">::MAX`] on overflow.")] + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = NonZero::new(1", stringify!($Int), ")?;")] + #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")] + #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(two, one.saturating_add(1)); + /// assert_eq!(max, max.saturating_add(1)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_add(self, other: $Int) -> Self { + // SAFETY: + // - `saturating_add` returns `u*::MAX` on overflow, which is non-zero + // - `self` is non-zero + // - the only way to get zero from an addition without overflow is for both + // sides to be zero + // + // So the result cannot be zero. + unsafe { Self::new_unchecked(self.get().saturating_add(other)) } + } + + /// Adds an unsigned integer to a non-zero value, + /// assuming overflow cannot occur. + /// Overflow is unchecked, and it is undefined behavior to overflow + /// *even if the result would wrap to a non-zero value*. + /// The behavior is undefined as soon as + #[doc = concat!("`self + rhs > ", stringify!($Int), "::MAX`.")] + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = NonZero::new(1", stringify!($Int), ")?;")] + #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")] + /// + /// assert_eq!(two, unsafe { one.unchecked_add(1) }); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const unsafe fn unchecked_add(self, other: $Int) -> Self { + // SAFETY: The caller ensures there is no overflow. + unsafe { Self::new_unchecked(self.get().unchecked_add(other)) } + } + + /// Returns the smallest power of two greater than or equal to `self`. + /// Checks for overflow and returns [`None`] + /// if the next power of two is greater than the type’s maximum value. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")] + #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ")?;")] + #[doc = concat!("let four = NonZero::new(4", stringify!($Int), ")?;")] + #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(two), two.checked_next_power_of_two() ); + /// assert_eq!(Some(four), three.checked_next_power_of_two() ); + /// assert_eq!(None, max.checked_next_power_of_two() ); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_next_power_of_two(self) -> Option { + if let Some(nz) = self.get().checked_next_power_of_two() { + // SAFETY: The next power of two is positive + // and overflow is checked. + Some(unsafe { Self::new_unchecked(nz) }) + } else { + None + } + } + + /// Returns the base 2 logarithm of the number, rounded down. + /// + /// This is the same operation as + #[doc = concat!("[`", stringify!($Int), "::ilog2`],")] + /// except that it has no failure cases to worry about + /// since this value can never be zero. + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("assert_eq!(NonZero::new(7", stringify!($Int), ")?.ilog2(), 2);")] + #[doc = concat!("assert_eq!(NonZero::new(8", stringify!($Int), ")?.ilog2(), 3);")] + #[doc = concat!("assert_eq!(NonZero::new(9", stringify!($Int), ")?.ilog2(), 3);")] + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn ilog2(self) -> u32 { + Self::BITS - 1 - self.leading_zeros() + } + + /// Returns the base 10 logarithm of the number, rounded down. + /// + /// This is the same operation as + #[doc = concat!("[`", stringify!($Int), "::ilog10`],")] + /// except that it has no failure cases to worry about + /// since this value can never be zero. + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("assert_eq!(NonZero::new(99", stringify!($Int), ")?.ilog10(), 1);")] + #[doc = concat!("assert_eq!(NonZero::new(100", stringify!($Int), ")?.ilog10(), 2);")] + #[doc = concat!("assert_eq!(NonZero::new(101", stringify!($Int), ")?.ilog10(), 2);")] + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn ilog10(self) -> u32 { + super::int_log10::$Int(self.get()) + } + + /// Calculates the middle point of `self` and `rhs`. + /// + /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a + /// sufficiently-large signed integral type. This implies that the result is + /// always rounded towards negative infinity and that no overflow will ever occur. + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = NonZero::new(1", stringify!($Int), ")?;")] + #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")] + #[doc = concat!("let four = NonZero::new(4", stringify!($Int), ")?;")] + /// + /// assert_eq!(one.midpoint(four), two); + /// assert_eq!(four.midpoint(one), two); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn midpoint(self, rhs: Self) -> Self { + // SAFETY: The only way to get `0` with midpoint is to have two opposite or + // near opposite numbers: (-5, 5), (0, 1), (0, 0) which is impossible because + // of the unsignedness of this number and also because `Self` is guaranteed to + // never being 0. + unsafe { Self::new_unchecked(self.get().midpoint(rhs.get())) } + } + + /// Returns `true` if and only if `self == (1 << k)` for some `k`. + /// + /// On many architectures, this function can perform better than `is_power_of_two()` + /// on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let eight = NonZero::new(8", stringify!($Int), ")?;")] + /// assert!(eight.is_power_of_two()); + #[doc = concat!("let ten = NonZero::new(10", stringify!($Int), ")?;")] + /// assert!(!ten.is_power_of_two()); + /// # Some(()) + /// # } + /// ``` + #[must_use] + #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] + #[rustc_const_stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] + #[inline] + pub const fn is_power_of_two(self) -> bool { + // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here. + // On the basic x86-64 target, this saves 3 instructions for the zero check. + // On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction + // compared to the `POPCNT` implementation on the underlying integer type. + + intrinsics::ctpop(self.get()) < 2 + } + + /// Returns the square root of the number, rounded down. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let ten = NonZero::new(10", stringify!($Int), ")?;")] + #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ")?;")] + /// + /// assert_eq!(ten.isqrt(), three); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "isqrt", since = "1.84.0")] + #[rustc_const_stable(feature = "isqrt", since = "1.84.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn isqrt(self) -> Self { + let result = self.get().isqrt(); + + // SAFETY: Integer square root is a monotonically nondecreasing + // function, which means that increasing the input will never cause + // the output to decrease. Thus, since the input for nonzero + // unsigned integers has a lower bound of 1, the lower bound of the + // results will be sqrt(1), which is 1, so a result can't be zero. + unsafe { Self::new_unchecked(result) } + } + }; + + // Associated items for signed nonzero types only. + ( + Primitive = signed $Int:ident, + UnsignedPrimitive = $Uint:ty, + ) => { + /// The smallest value that can be represented by this non-zero + /// integer type, + #[doc = concat!("equal to [`", stringify!($Int), "::MIN`].")] + /// + /// Note: While most integer types are defined for every whole + /// number between `MIN` and `MAX`, signed non-zero integers are + /// a special case. They have a "gap" at 0. + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::MIN.get(), ", stringify!($Int), "::MIN);")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MIN: Self = Self::new(<$Int>::MIN).unwrap(); + + /// The largest value that can be represented by this non-zero + /// integer type, + #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] + /// + /// Note: While most integer types are defined for every whole + /// number between `MIN` and `MAX`, signed non-zero integers are + /// a special case. They have a "gap" at 0. + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + /// # + #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::MAX.get(), ", stringify!($Int), "::MAX);")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); + + /// Computes the absolute value of self. + #[doc = concat!("See [`", stringify!($Int), "::abs`]")] + /// for documentation on overflow behavior. + /// + /// # Example + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = NonZero::new(1", stringify!($Int), ")?;")] + #[doc = concat!("let neg = NonZero::new(-1", stringify!($Int), ")?;")] + /// + /// assert_eq!(pos, pos.abs()); + /// assert_eq!(pos, neg.abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn abs(self) -> Self { + // SAFETY: This cannot overflow to zero. + unsafe { Self::new_unchecked(self.get().abs()) } + } + + /// Checked absolute value. + /// Checks for overflow and returns [`None`] if + #[doc = concat!("`self == NonZero::<", stringify!($Int), ">::MIN`.")] + /// The result cannot be zero. + /// + /// # Example + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = NonZero::new(1", stringify!($Int), ")?;")] + #[doc = concat!("let neg = NonZero::new(-1", stringify!($Int), ")?;")] + #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(Some(pos), neg.checked_abs()); + /// assert_eq!(None, min.checked_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_abs(self) -> Option { + if let Some(nz) = self.get().checked_abs() { + // SAFETY: absolute value of nonzero cannot yield zero values. + Some(unsafe { Self::new_unchecked(nz) }) + } else { + None + } + } + + /// Computes the absolute value of self, + /// with overflow information, see + #[doc = concat!("[`", stringify!($Int), "::overflowing_abs`].")] + /// + /// # Example + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = NonZero::new(1", stringify!($Int), ")?;")] + #[doc = concat!("let neg = NonZero::new(-1", stringify!($Int), ")?;")] + #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!((pos, false), pos.overflowing_abs()); + /// assert_eq!((pos, false), neg.overflowing_abs()); + /// assert_eq!((min, true), min.overflowing_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_abs(self) -> (Self, bool) { + let (nz, flag) = self.get().overflowing_abs(); + ( + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { Self::new_unchecked(nz) }, + flag, + ) + } + + /// Saturating absolute value, see + #[doc = concat!("[`", stringify!($Int), "::saturating_abs`].")] + /// + /// # Example + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = NonZero::new(1", stringify!($Int), ")?;")] + #[doc = concat!("let neg = NonZero::new(-1", stringify!($Int), ")?;")] + #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")] + #[doc = concat!("let min_plus = NonZero::new(", stringify!($Int), "::MIN + 1)?;")] + #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos, pos.saturating_abs()); + /// assert_eq!(pos, neg.saturating_abs()); + /// assert_eq!(max, min.saturating_abs()); + /// assert_eq!(max, min_plus.saturating_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_abs(self) -> Self { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { Self::new_unchecked(self.get().saturating_abs()) } + } + + /// Wrapping absolute value, see + #[doc = concat!("[`", stringify!($Int), "::wrapping_abs`].")] + /// + /// # Example + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = NonZero::new(1", stringify!($Int), ")?;")] + #[doc = concat!("let neg = NonZero::new(-1", stringify!($Int), ")?;")] + #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")] + #[doc = concat!("# let max = NonZero::new(", stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos, pos.wrapping_abs()); + /// assert_eq!(pos, neg.wrapping_abs()); + /// assert_eq!(min, min.wrapping_abs()); + /// assert_eq!(max, (-max).wrapping_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_abs(self) -> Self { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { Self::new_unchecked(self.get().wrapping_abs()) } + } + + /// Computes the absolute value of self + /// without any wrapping or panicking. + /// + /// # Example + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let u_pos = NonZero::new(1", stringify!($Uint), ")?;")] + #[doc = concat!("let i_pos = NonZero::new(1", stringify!($Int), ")?;")] + #[doc = concat!("let i_neg = NonZero::new(-1", stringify!($Int), ")?;")] + #[doc = concat!("let i_min = NonZero::new(", stringify!($Int), "::MIN)?;")] + #[doc = concat!("let u_max = NonZero::new(", stringify!($Uint), "::MAX / 2 + 1)?;")] + /// + /// assert_eq!(u_pos, i_pos.unsigned_abs()); + /// assert_eq!(u_pos, i_neg.unsigned_abs()); + /// assert_eq!(u_max, i_min.unsigned_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unsigned_abs(self) -> NonZero<$Uint> { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { NonZero::new_unchecked(self.get().unsigned_abs()) } + } + + /// Returns `true` if `self` is positive and `false` if the + /// number is negative. + /// + /// # Example + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = NonZero::new(5", stringify!($Int), ")?;")] + #[doc = concat!("let neg_five = NonZero::new(-5", stringify!($Int), ")?;")] + /// + /// assert!(pos_five.is_positive()); + /// assert!(!neg_five.is_positive()); + /// # Some(()) + /// # } + /// ``` + #[must_use] + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn is_positive(self) -> bool { + self.get().is_positive() + } + + /// Returns `true` if `self` is negative and `false` if the + /// number is positive. + /// + /// # Example + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = NonZero::new(5", stringify!($Int), ")?;")] + #[doc = concat!("let neg_five = NonZero::new(-5", stringify!($Int), ")?;")] + /// + /// assert!(neg_five.is_negative()); + /// assert!(!pos_five.is_negative()); + /// # Some(()) + /// # } + /// ``` + #[must_use] + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn is_negative(self) -> bool { + self.get().is_negative() + } + + /// Checked negation. Computes `-self`, + #[doc = concat!("returning `None` if `self == NonZero::<", stringify!($Int), ">::MIN`.")] + /// + /// # Example + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = NonZero::new(5", stringify!($Int), ")?;")] + #[doc = concat!("let neg_five = NonZero::new(-5", stringify!($Int), ")?;")] + #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.checked_neg(), Some(neg_five)); + /// assert_eq!(min.checked_neg(), None); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn checked_neg(self) -> Option { + if let Some(result) = self.get().checked_neg() { + // SAFETY: negation of nonzero cannot yield zero values. + return Some(unsafe { Self::new_unchecked(result) }); + } + None + } + + /// Negates self, overflowing if this is equal to the minimum value. + /// + #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")] + /// for documentation on overflow behavior. + /// + /// # Example + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = NonZero::new(5", stringify!($Int), ")?;")] + #[doc = concat!("let neg_five = NonZero::new(-5", stringify!($Int), ")?;")] + #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false)); + /// assert_eq!(min.overflowing_neg(), (min, true)); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn overflowing_neg(self) -> (Self, bool) { + let (result, overflow) = self.get().overflowing_neg(); + // SAFETY: negation of nonzero cannot yield zero values. + ((unsafe { Self::new_unchecked(result) }), overflow) + } + + /// Saturating negation. Computes `-self`, + #[doc = concat!("returning [`NonZero::<", stringify!($Int), ">::MAX`]")] + #[doc = concat!("if `self == NonZero::<", stringify!($Int), ">::MIN`")] + /// instead of overflowing. + /// + /// # Example + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = NonZero::new(5", stringify!($Int), ")?;")] + #[doc = concat!("let neg_five = NonZero::new(-5", stringify!($Int), ")?;")] + #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")] + #[doc = concat!("let min_plus_one = NonZero::new(", stringify!($Int), "::MIN + 1)?;")] + #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos_five.saturating_neg(), neg_five); + /// assert_eq!(min.saturating_neg(), max); + /// assert_eq!(max.saturating_neg(), min_plus_one); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn saturating_neg(self) -> Self { + if let Some(result) = self.checked_neg() { + return result; + } + Self::MAX + } + + /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary + /// of the type. + /// + #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")] + /// for documentation on overflow behavior. + /// + /// # Example + /// + /// ``` + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = NonZero::new(5", stringify!($Int), ")?;")] + #[doc = concat!("let neg_five = NonZero::new(-5", stringify!($Int), ")?;")] + #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.wrapping_neg(), neg_five); + /// assert_eq!(min.wrapping_neg(), min); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn wrapping_neg(self) -> Self { + let result = self.get().wrapping_neg(); + // SAFETY: negation of nonzero cannot yield zero values. + unsafe { Self::new_unchecked(result) } + } + }; +} + +nonzero_integer! { + Self = NonZeroU8, + Primitive = unsigned u8, + rot = 2, + rot_op = "0x82", + rot_result = "0xa", + swap_op = "0x12", + swapped = "0x12", + reversed = "0x48", +} + +nonzero_integer! { + Self = NonZeroU16, + Primitive = unsigned u16, + rot = 4, + rot_op = "0xa003", + rot_result = "0x3a", + swap_op = "0x1234", + swapped = "0x3412", + reversed = "0x2c48", +} + +nonzero_integer! { + Self = NonZeroU32, + Primitive = unsigned u32, + rot = 8, + rot_op = "0x10000b3", + rot_result = "0xb301", + swap_op = "0x12345678", + swapped = "0x78563412", + reversed = "0x1e6a2c48", +} + +nonzero_integer! { + Self = NonZeroU64, + Primitive = unsigned u64, + rot = 12, + rot_op = "0xaa00000000006e1", + rot_result = "0x6e10aa", + swap_op = "0x1234567890123456", + swapped = "0x5634129078563412", + reversed = "0x6a2c48091e6a2c48", +} + +nonzero_integer! { + Self = NonZeroU128, + Primitive = unsigned u128, + rot = 16, + rot_op = "0x13f40000000000000000000000004f76", + rot_result = "0x4f7613f4", + swap_op = "0x12345678901234567890123456789012", + swapped = "0x12907856341290785634129078563412", + reversed = "0x48091e6a2c48091e6a2c48091e6a2c48", +} + +#[cfg(target_pointer_width = "16")] +nonzero_integer! { + Self = NonZeroUsize, + Primitive = unsigned usize, + rot = 4, + rot_op = "0xa003", + rot_result = "0x3a", + swap_op = "0x1234", + swapped = "0x3412", + reversed = "0x2c48", +} + +#[cfg(target_pointer_width = "32")] +nonzero_integer! { + Self = NonZeroUsize, + Primitive = unsigned usize, + rot = 8, + rot_op = "0x10000b3", + rot_result = "0xb301", + swap_op = "0x12345678", + swapped = "0x78563412", + reversed = "0x1e6a2c48", +} + +#[cfg(target_pointer_width = "64")] +nonzero_integer! { + Self = NonZeroUsize, + Primitive = unsigned usize, + rot = 12, + rot_op = "0xaa00000000006e1", + rot_result = "0x6e10aa", + swap_op = "0x1234567890123456", + swapped = "0x5634129078563412", + reversed = "0x6a2c48091e6a2c48", +} + +nonzero_integer! { + Self = NonZeroI8, + Primitive = signed i8, + UnsignedPrimitive = u8, + rot = 2, + rot_op = "-0x7e", + rot_result = "0xa", + swap_op = "0x12", + swapped = "0x12", + reversed = "0x48", +} + +nonzero_integer! { + Self = NonZeroI16, + Primitive = signed i16, + UnsignedPrimitive = u16, + rot = 4, + rot_op = "-0x5ffd", + rot_result = "0x3a", + swap_op = "0x1234", + swapped = "0x3412", + reversed = "0x2c48", +} + +nonzero_integer! { + Self = NonZeroI32, + Primitive = signed i32, + UnsignedPrimitive = u32, + rot = 8, + rot_op = "0x10000b3", + rot_result = "0xb301", + swap_op = "0x12345678", + swapped = "0x78563412", + reversed = "0x1e6a2c48", +} + +nonzero_integer! { + Self = NonZeroI64, + Primitive = signed i64, + UnsignedPrimitive = u64, + rot = 12, + rot_op = "0xaa00000000006e1", + rot_result = "0x6e10aa", + swap_op = "0x1234567890123456", + swapped = "0x5634129078563412", + reversed = "0x6a2c48091e6a2c48", +} + +nonzero_integer! { + Self = NonZeroI128, + Primitive = signed i128, + UnsignedPrimitive = u128, + rot = 16, + rot_op = "0x13f40000000000000000000000004f76", + rot_result = "0x4f7613f4", + swap_op = "0x12345678901234567890123456789012", + swapped = "0x12907856341290785634129078563412", + reversed = "0x48091e6a2c48091e6a2c48091e6a2c48", +} + +#[cfg(target_pointer_width = "16")] +nonzero_integer! { + Self = NonZeroIsize, + Primitive = signed isize, + UnsignedPrimitive = usize, + rot = 4, + rot_op = "-0x5ffd", + rot_result = "0x3a", + swap_op = "0x1234", + swapped = "0x3412", + reversed = "0x2c48", +} + +#[cfg(target_pointer_width = "32")] +nonzero_integer! { + Self = NonZeroIsize, + Primitive = signed isize, + UnsignedPrimitive = usize, + rot = 8, + rot_op = "0x10000b3", + rot_result = "0xb301", + swap_op = "0x12345678", + swapped = "0x78563412", + reversed = "0x1e6a2c48", +} + +#[cfg(target_pointer_width = "64")] +nonzero_integer! { + Self = NonZeroIsize, + Primitive = signed isize, + UnsignedPrimitive = usize, + rot = 12, + rot_op = "0xaa00000000006e1", + rot_result = "0x6e10aa", + swap_op = "0x1234567890123456", + swapped = "0x5634129078563412", + reversed = "0x6a2c48091e6a2c48", +} diff --git a/CoqOfRust/core/num/overflow_panic.rs b/CoqOfRust/core/num/overflow_panic.rs new file mode 100644 index 000000000..203037ffb --- /dev/null +++ b/CoqOfRust/core/num/overflow_panic.rs @@ -0,0 +1,51 @@ +//! Functions for panicking on overflow. +//! +//! In particular, these are used by the `strict_` methods on integers. + +#[cold] +#[track_caller] +pub const fn add() -> ! { + panic!("attempt to add with overflow") +} + +#[cold] +#[track_caller] +pub const fn sub() -> ! { + panic!("attempt to subtract with overflow") +} + +#[cold] +#[track_caller] +pub const fn mul() -> ! { + panic!("attempt to multiply with overflow") +} + +#[cold] +#[track_caller] +pub const fn div() -> ! { + panic!("attempt to divide with overflow") +} + +#[cold] +#[track_caller] +pub const fn rem() -> ! { + panic!("attempt to calculate the remainder with overflow") +} + +#[cold] +#[track_caller] +pub const fn neg() -> ! { + panic!("attempt to negate with overflow") +} + +#[cold] +#[track_caller] +pub const fn shr() -> ! { + panic!("attempt to shift right with overflow") +} + +#[cold] +#[track_caller] +pub const fn shl() -> ! { + panic!("attempt to shift left with overflow") +} diff --git a/CoqOfRust/core/num/saturating.rs b/CoqOfRust/core/num/saturating.rs new file mode 100644 index 000000000..3f4791e16 --- /dev/null +++ b/CoqOfRust/core/num/saturating.rs @@ -0,0 +1,1077 @@ +//! Definitions of `Saturating`. + +use crate::fmt; +use crate::ops::{ + Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, + Mul, MulAssign, Neg, Not, Rem, RemAssign, Sub, SubAssign, +}; + +/// Provides intentionally-saturating arithmetic on `T`. +/// +/// Operations like `+` on `u32` values are intended to never overflow, +/// and in some debug configurations overflow is detected and results +/// in a panic. While most arithmetic falls into this category, some +/// code explicitly expects and relies upon saturating arithmetic. +/// +/// Saturating arithmetic can be achieved either through methods like +/// `saturating_add`, or through the `Saturating` type, which says that +/// all standard arithmetic operations on the underlying value are +/// intended to have saturating semantics. +/// +/// The underlying value can be retrieved through the `.0` index of the +/// `Saturating` tuple. +/// +/// # Examples +/// +/// ``` +/// use std::num::Saturating; +/// +/// let max = Saturating(u32::MAX); +/// let one = Saturating(1u32); +/// +/// assert_eq!(u32::MAX, (max + one).0); +/// ``` +#[stable(feature = "saturating_int_impl", since = "1.74.0")] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)] +#[repr(transparent)] +#[rustc_diagnostic_item = "Saturating"] +pub struct Saturating(#[stable(feature = "saturating_int_impl", since = "1.74.0")] pub T); + +#[stable(feature = "saturating_int_impl", since = "1.74.0")] +impl fmt::Debug for Saturating { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +#[stable(feature = "saturating_int_impl", since = "1.74.0")] +impl fmt::Display for Saturating { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +#[stable(feature = "saturating_int_impl", since = "1.74.0")] +impl fmt::Binary for Saturating { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +#[stable(feature = "saturating_int_impl", since = "1.74.0")] +impl fmt::Octal for Saturating { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +#[stable(feature = "saturating_int_impl", since = "1.74.0")] +impl fmt::LowerHex for Saturating { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +#[stable(feature = "saturating_int_impl", since = "1.74.0")] +impl fmt::UpperHex for Saturating { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +// FIXME the correct implementation is not clear. Waiting for a real world use case at https://github.com/rust-lang/libs-team/issues/230 +// +// #[allow(unused_macros)] +// macro_rules! sh_impl_signed { +// ($t:ident, $f:ident) => { +// // FIXME what is the correct implementation here? see discussion https://github.com/rust-lang/rust/pull/87921#discussion_r695870065 +// // +// // #[unstable(feature = "saturating_int_impl", issue = "87920")] +// // impl Shl<$f> for Saturating<$t> { +// // type Output = Saturating<$t>; +// // +// // #[inline] +// // fn shl(self, other: $f) -> Saturating<$t> { +// // if other < 0 { +// // Saturating(self.0.shr((-other & self::shift_max::$t as $f) as u32)) +// // } else { +// // Saturating(self.0.shl((other & self::shift_max::$t as $f) as u32)) +// // } +// // } +// // } +// // forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f, +// // #[unstable(feature = "saturating_int_impl", issue = "87920")] } +// // +// // #[unstable(feature = "saturating_int_impl", issue = "87920")] +// // impl ShlAssign<$f> for Saturating<$t> { +// // #[inline] +// // fn shl_assign(&mut self, other: $f) { +// // *self = *self << other; +// // } +// // } +// // forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f } +// +// #[unstable(feature = "saturating_int_impl", issue = "87920")] +// impl Shr<$f> for Saturating<$t> { +// type Output = Saturating<$t>; +// +// #[inline] +// fn shr(self, other: $f) -> Saturating<$t> { +// if other < 0 { +// Saturating(self.0.shl((-other & self::shift_max::$t as $f) as u32)) +// } else { +// Saturating(self.0.shr((other & self::shift_max::$t as $f) as u32)) +// } +// } +// } +// forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f, +// #[unstable(feature = "saturating_int_impl", issue = "87920")] } +// +// #[unstable(feature = "saturating_int_impl", issue = "87920")] +// impl ShrAssign<$f> for Saturating<$t> { +// #[inline] +// fn shr_assign(&mut self, other: $f) { +// *self = *self >> other; +// } +// } +// forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f } +// }; +// } +// +// macro_rules! sh_impl_unsigned { +// ($t:ident, $f:ident) => { +// #[unstable(feature = "saturating_int_impl", issue = "87920")] +// impl Shl<$f> for Saturating<$t> { +// type Output = Saturating<$t>; +// +// #[inline] +// fn shl(self, other: $f) -> Saturating<$t> { +// Saturating(self.0.wrapping_shl(other as u32)) +// } +// } +// forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f, +// #[unstable(feature = "saturating_int_impl", issue = "87920")] } +// +// #[unstable(feature = "saturating_int_impl", issue = "87920")] +// impl ShlAssign<$f> for Saturating<$t> { +// #[inline] +// fn shl_assign(&mut self, other: $f) { +// *self = *self << other; +// } +// } +// forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f } +// +// #[unstable(feature = "saturating_int_impl", issue = "87920")] +// impl Shr<$f> for Saturating<$t> { +// type Output = Saturating<$t>; +// +// #[inline] +// fn shr(self, other: $f) -> Saturating<$t> { +// Saturating(self.0.wrapping_shr(other as u32)) +// } +// } +// forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f, +// #[unstable(feature = "saturating_int_impl", issue = "87920")] } +// +// #[unstable(feature = "saturating_int_impl", issue = "87920")] +// impl ShrAssign<$f> for Saturating<$t> { +// #[inline] +// fn shr_assign(&mut self, other: $f) { +// *self = *self >> other; +// } +// } +// forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f } +// }; +// } +// +// // FIXME (#23545): uncomment the remaining impls +// macro_rules! sh_impl_all { +// ($($t:ident)*) => ($( +// //sh_impl_unsigned! { $t, u8 } +// //sh_impl_unsigned! { $t, u16 } +// //sh_impl_unsigned! { $t, u32 } +// //sh_impl_unsigned! { $t, u64 } +// //sh_impl_unsigned! { $t, u128 } +// sh_impl_unsigned! { $t, usize } +// +// //sh_impl_signed! { $t, i8 } +// //sh_impl_signed! { $t, i16 } +// //sh_impl_signed! { $t, i32 } +// //sh_impl_signed! { $t, i64 } +// //sh_impl_signed! { $t, i128 } +// //sh_impl_signed! { $t, isize } +// )*) +// } +// +// sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } + +// FIXME(30524): impl Op for Saturating, impl OpAssign for Saturating +macro_rules! saturating_impl { + ($($t:ty)*) => ($( + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl Add for Saturating<$t> { + type Output = Saturating<$t>; + + #[inline] + fn add(self, other: Saturating<$t>) -> Saturating<$t> { + Saturating(self.0.saturating_add(other.0)) + } + } + forward_ref_binop! { impl Add, add for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl AddAssign for Saturating<$t> { + #[inline] + fn add_assign(&mut self, other: Saturating<$t>) { + *self = *self + other; + } + } + forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, Saturating<$t> } + + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] + impl AddAssign<$t> for Saturating<$t> { + #[inline] + fn add_assign(&mut self, other: $t) { + *self = *self + Saturating(other); + } + } + forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, $t } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl Sub for Saturating<$t> { + type Output = Saturating<$t>; + + #[inline] + fn sub(self, other: Saturating<$t>) -> Saturating<$t> { + Saturating(self.0.saturating_sub(other.0)) + } + } + forward_ref_binop! { impl Sub, sub for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl SubAssign for Saturating<$t> { + #[inline] + fn sub_assign(&mut self, other: Saturating<$t>) { + *self = *self - other; + } + } + forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, Saturating<$t> } + + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] + impl SubAssign<$t> for Saturating<$t> { + #[inline] + fn sub_assign(&mut self, other: $t) { + *self = *self - Saturating(other); + } + } + forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, $t } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl Mul for Saturating<$t> { + type Output = Saturating<$t>; + + #[inline] + fn mul(self, other: Saturating<$t>) -> Saturating<$t> { + Saturating(self.0.saturating_mul(other.0)) + } + } + forward_ref_binop! { impl Mul, mul for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl MulAssign for Saturating<$t> { + #[inline] + fn mul_assign(&mut self, other: Saturating<$t>) { + *self = *self * other; + } + } + forward_ref_op_assign! { impl MulAssign, mul_assign for Saturating<$t>, Saturating<$t> } + + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] + impl MulAssign<$t> for Saturating<$t> { + #[inline] + fn mul_assign(&mut self, other: $t) { + *self = *self * Saturating(other); + } + } + forward_ref_op_assign! { impl MulAssign, mul_assign for Saturating<$t>, $t } + + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("assert_eq!(Saturating(2", stringify!($t), "), Saturating(5", stringify!($t), ") / Saturating(2));")] + #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MAX), Saturating(", stringify!($t), "::MAX) / Saturating(1));")] + #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN), Saturating(", stringify!($t), "::MIN) / Saturating(1));")] + /// ``` + /// + /// ```should_panic + /// use std::num::Saturating; + /// + #[doc = concat!("let _ = Saturating(0", stringify!($t), ") / Saturating(0);")] + /// ``` + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl Div for Saturating<$t> { + type Output = Saturating<$t>; + + #[inline] + fn div(self, other: Saturating<$t>) -> Saturating<$t> { + Saturating(self.0.saturating_div(other.0)) + } + } + forward_ref_binop! { impl Div, div for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl DivAssign for Saturating<$t> { + #[inline] + fn div_assign(&mut self, other: Saturating<$t>) { + *self = *self / other; + } + } + forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, Saturating<$t> } + + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] + impl DivAssign<$t> for Saturating<$t> { + #[inline] + fn div_assign(&mut self, other: $t) { + *self = *self / Saturating(other); + } + } + forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, $t } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl Rem for Saturating<$t> { + type Output = Saturating<$t>; + + #[inline] + fn rem(self, other: Saturating<$t>) -> Saturating<$t> { + Saturating(self.0.rem(other.0)) + } + } + forward_ref_binop! { impl Rem, rem for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl RemAssign for Saturating<$t> { + #[inline] + fn rem_assign(&mut self, other: Saturating<$t>) { + *self = *self % other; + } + } + forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, Saturating<$t> } + + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] + impl RemAssign<$t> for Saturating<$t> { + #[inline] + fn rem_assign(&mut self, other: $t) { + *self = *self % Saturating(other); + } + } + forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, $t } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl Not for Saturating<$t> { + type Output = Saturating<$t>; + + #[inline] + fn not(self) -> Saturating<$t> { + Saturating(!self.0) + } + } + forward_ref_unop! { impl Not, not for Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl BitXor for Saturating<$t> { + type Output = Saturating<$t>; + + #[inline] + fn bitxor(self, other: Saturating<$t>) -> Saturating<$t> { + Saturating(self.0 ^ other.0) + } + } + forward_ref_binop! { impl BitXor, bitxor for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl BitXorAssign for Saturating<$t> { + #[inline] + fn bitxor_assign(&mut self, other: Saturating<$t>) { + *self = *self ^ other; + } + } + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, Saturating<$t> } + + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] + impl BitXorAssign<$t> for Saturating<$t> { + #[inline] + fn bitxor_assign(&mut self, other: $t) { + *self = *self ^ Saturating(other); + } + } + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, $t } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl BitOr for Saturating<$t> { + type Output = Saturating<$t>; + + #[inline] + fn bitor(self, other: Saturating<$t>) -> Saturating<$t> { + Saturating(self.0 | other.0) + } + } + forward_ref_binop! { impl BitOr, bitor for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl BitOrAssign for Saturating<$t> { + #[inline] + fn bitor_assign(&mut self, other: Saturating<$t>) { + *self = *self | other; + } + } + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, Saturating<$t> } + + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] + impl BitOrAssign<$t> for Saturating<$t> { + #[inline] + fn bitor_assign(&mut self, other: $t) { + *self = *self | Saturating(other); + } + } + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, $t } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl BitAnd for Saturating<$t> { + type Output = Saturating<$t>; + + #[inline] + fn bitand(self, other: Saturating<$t>) -> Saturating<$t> { + Saturating(self.0 & other.0) + } + } + forward_ref_binop! { impl BitAnd, bitand for Saturating<$t>, Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl BitAndAssign for Saturating<$t> { + #[inline] + fn bitand_assign(&mut self, other: Saturating<$t>) { + *self = *self & other; + } + } + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Saturating<$t>, Saturating<$t> } + + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] + impl BitAndAssign<$t> for Saturating<$t> { + #[inline] + fn bitand_assign(&mut self, other: $t) { + *self = *self & Saturating(other); + } + } + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Saturating<$t>, $t } + + )*) +} + +saturating_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +macro_rules! saturating_int_impl { + ($($t:ty)*) => ($( + impl Saturating<$t> { + /// Returns the smallest value that can be represented by this integer type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("assert_eq!(>::MIN, Saturating(", stringify!($t), "::MIN));")] + /// ``` + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const MIN: Self = Self(<$t>::MIN); + + /// Returns the largest value that can be represented by this integer type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("assert_eq!(>::MAX, Saturating(", stringify!($t), "::MAX));")] + /// ``` + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const MAX: Self = Self(<$t>::MAX); + + /// Returns the size of this integer type in bits. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("assert_eq!(>::BITS, ", stringify!($t), "::BITS);")] + /// ``` + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const BITS: u32 = <$t>::BITS; + + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("let n = Saturating(0b01001100", stringify!($t), ");")] + /// + /// assert_eq!(n.count_ones(), 3); + /// ``` + #[inline] + #[doc(alias = "popcount")] + #[doc(alias = "popcnt")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const fn count_ones(self) -> u32 { + self.0.count_ones() + } + + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("assert_eq!(Saturating(!0", stringify!($t), ").count_zeros(), 0);")] + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const fn count_zeros(self) -> u32 { + self.0.count_zeros() + } + + /// Returns the number of trailing zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("let n = Saturating(0b0101000", stringify!($t), ");")] + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const fn trailing_zeros(self) -> u32 { + self.0.trailing_zeros() + } + + /// Shifts the bits to the left by a specified amount, `n`, + /// saturating the truncated bits to the end of the resulting + /// integer. + /// + /// Please note this isn't the same operation as the `<<` shifting + /// operator! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + /// let n: Saturating = Saturating(0x0123456789ABCDEF); + /// let m: Saturating = Saturating(-0x76543210FEDCBA99); + /// + /// assert_eq!(n.rotate_left(32), m); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const fn rotate_left(self, n: u32) -> Self { + Saturating(self.0.rotate_left(n)) + } + + /// Shifts the bits to the right by a specified amount, `n`, + /// saturating the truncated bits to the beginning of the resulting + /// integer. + /// + /// Please note this isn't the same operation as the `>>` shifting + /// operator! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + /// let n: Saturating = Saturating(0x0123456789ABCDEF); + /// let m: Saturating = Saturating(-0xFEDCBA987654322); + /// + /// assert_eq!(n.rotate_right(4), m); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const fn rotate_right(self, n: u32) -> Self { + Saturating(self.0.rotate_right(n)) + } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + /// let n: Saturating = Saturating(0b0000000_01010101); + /// assert_eq!(n, Saturating(85)); + /// + /// let m = n.swap_bytes(); + /// + /// assert_eq!(m, Saturating(0b01010101_00000000)); + /// assert_eq!(m, Saturating(21760)); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const fn swap_bytes(self) -> Self { + Saturating(self.0.swap_bytes()) + } + + /// Reverses the bit pattern of the integer. + /// + /// # Examples + /// + /// Please note that this example is shared between integer types. + /// Which explains why `i16` is used here. + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + /// let n = Saturating(0b0000000_01010101i16); + /// assert_eq!(n, Saturating(85)); + /// + /// let m = n.reverse_bits(); + /// + /// assert_eq!(m.0 as u16, 0b10101010_00000000); + /// assert_eq!(m, Saturating(-22016)); + /// ``` + #[inline] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn reverse_bits(self) -> Self { + Saturating(self.0.reverse_bits()) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")] + /// + /// if cfg!(target_endian = "big") { + #[doc = concat!(" assert_eq!(>::from_be(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(>::from_be(n), n.swap_bytes())")] + /// } + /// ``` + #[inline] + #[must_use] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const fn from_be(x: Self) -> Self { + Saturating(<$t>::from_be(x.0)) + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")] + /// + /// if cfg!(target_endian = "little") { + #[doc = concat!(" assert_eq!(>::from_le(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(>::from_le(n), n.swap_bytes())")] + /// } + /// ``` + #[inline] + #[must_use] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const fn from_le(x: Self) -> Self { + Saturating(<$t>::from_le(x.0)) + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")] + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[inline] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn to_be(self) -> Self { + Saturating(self.0.to_be()) + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")] + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[inline] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn to_le(self) -> Self { + Saturating(self.0.to_le()) + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("assert_eq!(Saturating(3", stringify!($t), ").pow(4), Saturating(81));")] + /// ``` + /// + /// Results that are too large are saturated: + /// + /// ``` + /// use std::num::Saturating; + /// + /// assert_eq!(Saturating(3i8).pow(5), Saturating(127)); + /// assert_eq!(Saturating(3i8).pow(6), Saturating(127)); + /// ``` + #[inline] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn pow(self, exp: u32) -> Self { + Saturating(self.0.saturating_pow(exp)) + } + } + )*) +} + +saturating_int_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +macro_rules! saturating_int_impl_signed { + ($($t:ty)*) => ($( + impl Saturating<$t> { + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("let n = Saturating(", stringify!($t), "::MAX >> 2);")] + /// + /// assert_eq!(n.leading_zeros(), 3); + /// ``` + #[inline] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn leading_zeros(self) -> u32 { + self.0.leading_zeros() + } + + /// Saturating absolute value. Computes `self.abs()`, returning `MAX` if `self == MIN` + /// instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("assert_eq!(Saturating(100", stringify!($t), ").abs(), Saturating(100));")] + #[doc = concat!("assert_eq!(Saturating(-100", stringify!($t), ").abs(), Saturating(100));")] + #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN).abs(), Saturating((", stringify!($t), "::MIN + 1).abs()));")] + #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN).abs(), Saturating(", stringify!($t), "::MIN.saturating_abs()));")] + #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN).abs(), Saturating(", stringify!($t), "::MAX));")] + /// ``` + #[inline] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn abs(self) -> Saturating<$t> { + Saturating(self.0.saturating_abs()) + } + + /// Returns a number representing sign of `self`. + /// + /// - `0` if the number is zero + /// - `1` if the number is positive + /// - `-1` if the number is negative + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("assert_eq!(Saturating(10", stringify!($t), ").signum(), Saturating(1));")] + #[doc = concat!("assert_eq!(Saturating(0", stringify!($t), ").signum(), Saturating(0));")] + #[doc = concat!("assert_eq!(Saturating(-10", stringify!($t), ").signum(), Saturating(-1));")] + /// ``` + #[inline] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn signum(self) -> Saturating<$t> { + Saturating(self.0.signum()) + } + + /// Returns `true` if `self` is positive and `false` if the number is zero or + /// negative. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("assert!(Saturating(10", stringify!($t), ").is_positive());")] + #[doc = concat!("assert!(!Saturating(-10", stringify!($t), ").is_positive());")] + /// ``` + #[must_use] + #[inline] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const fn is_positive(self) -> bool { + self.0.is_positive() + } + + /// Returns `true` if `self` is negative and `false` if the number is zero or + /// positive. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("assert!(Saturating(-10", stringify!($t), ").is_negative());")] + #[doc = concat!("assert!(!Saturating(10", stringify!($t), ").is_negative());")] + /// ``` + #[must_use] + #[inline] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const fn is_negative(self) -> bool { + self.0.is_negative() + } + } + + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + impl Neg for Saturating<$t> { + type Output = Self; + #[inline] + fn neg(self) -> Self { + Saturating(self.0.saturating_neg()) + } + } + forward_ref_unop! { impl Neg, neg for Saturating<$t>, + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } + )*) +} + +saturating_int_impl_signed! { isize i8 i16 i32 i64 i128 } + +macro_rules! saturating_int_impl_unsigned { + ($($t:ty)*) => ($( + impl Saturating<$t> { + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("let n = Saturating(", stringify!($t), "::MAX >> 2);")] + /// + /// assert_eq!(n.leading_zeros(), 2); + /// ``` + #[inline] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn leading_zeros(self) -> u32 { + self.0.leading_zeros() + } + + /// Returns `true` if and only if `self == 2^k` for some `k`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Saturating; + /// + #[doc = concat!("assert!(Saturating(16", stringify!($t), ").is_power_of_two());")] + #[doc = concat!("assert!(!Saturating(10", stringify!($t), ").is_power_of_two());")] + /// ``` + #[must_use] + #[inline] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const fn is_power_of_two(self) -> bool { + self.0.is_power_of_two() + } + + } + )*) +} + +saturating_int_impl_unsigned! { usize u8 u16 u32 u64 u128 } + +// Related to potential Shl and ShlAssign implementation +// +// mod shift_max { +// #![allow(non_upper_case_globals)] +// +// #[cfg(target_pointer_width = "16")] +// mod platform { +// pub const usize: u32 = super::u16; +// pub const isize: u32 = super::i16; +// } +// +// #[cfg(target_pointer_width = "32")] +// mod platform { +// pub const usize: u32 = super::u32; +// pub const isize: u32 = super::i32; +// } +// +// #[cfg(target_pointer_width = "64")] +// mod platform { +// pub const usize: u32 = super::u64; +// pub const isize: u32 = super::i64; +// } +// +// pub const i8: u32 = (1 << 3) - 1; +// pub const i16: u32 = (1 << 4) - 1; +// pub const i32: u32 = (1 << 5) - 1; +// pub const i64: u32 = (1 << 6) - 1; +// pub const i128: u32 = (1 << 7) - 1; +// pub use self::platform::isize; +// +// pub const u8: u32 = i8; +// pub const u16: u32 = i16; +// pub const u32: u32 = i32; +// pub const u64: u32 = i64; +// pub const u128: u32 = i128; +// pub use self::platform::usize; +// } diff --git a/CoqOfRust/core/num/shells/i128.rs b/CoqOfRust/core/num/shells/i128.rs new file mode 100644 index 000000000..b3b3d3b48 --- /dev/null +++ b/CoqOfRust/core/num/shells/i128.rs @@ -0,0 +1,11 @@ +//! Redundant constants module for the [`i128` primitive type][i128]. +//! +//! New code should use the associated constants directly on the primitive type. + +#![stable(feature = "i128", since = "1.26.0")] +#![deprecated( + since = "TBD", + note = "all constants in this module replaced by associated constants on `i128`" +)] + +int_module! { i128, #[stable(feature = "i128", since="1.26.0")] } diff --git a/CoqOfRust/core/num/shells/i16.rs b/CoqOfRust/core/num/shells/i16.rs new file mode 100644 index 000000000..70a452e19 --- /dev/null +++ b/CoqOfRust/core/num/shells/i16.rs @@ -0,0 +1,11 @@ +//! Redundant constants module for the [`i16` primitive type][i16]. +//! +//! New code should use the associated constants directly on the primitive type. + +#![stable(feature = "rust1", since = "1.0.0")] +#![deprecated( + since = "TBD", + note = "all constants in this module replaced by associated constants on `i16`" +)] + +int_module! { i16 } diff --git a/CoqOfRust/core/num/shells/i32.rs b/CoqOfRust/core/num/shells/i32.rs new file mode 100644 index 000000000..c30849e25 --- /dev/null +++ b/CoqOfRust/core/num/shells/i32.rs @@ -0,0 +1,11 @@ +//! Redundant constants module for the [`i32` primitive type][i32]. +//! +//! New code should use the associated constants directly on the primitive type. + +#![stable(feature = "rust1", since = "1.0.0")] +#![deprecated( + since = "TBD", + note = "all constants in this module replaced by associated constants on `i32`" +)] + +int_module! { i32 } diff --git a/CoqOfRust/core/num/shells/i64.rs b/CoqOfRust/core/num/shells/i64.rs new file mode 100644 index 000000000..77d95d712 --- /dev/null +++ b/CoqOfRust/core/num/shells/i64.rs @@ -0,0 +1,11 @@ +//! Redundant constants module for the [`i64` primitive type][i64]. +//! +//! New code should use the associated constants directly on the primitive type. + +#![stable(feature = "rust1", since = "1.0.0")] +#![deprecated( + since = "TBD", + note = "all constants in this module replaced by associated constants on `i64`" +)] + +int_module! { i64 } diff --git a/CoqOfRust/core/num/shells/i8.rs b/CoqOfRust/core/num/shells/i8.rs new file mode 100644 index 000000000..516ba8cde --- /dev/null +++ b/CoqOfRust/core/num/shells/i8.rs @@ -0,0 +1,11 @@ +//! Redundant constants module for the [`i8` primitive type][i8]. +//! +//! New code should use the associated constants directly on the primitive type. + +#![stable(feature = "rust1", since = "1.0.0")] +#![deprecated( + since = "TBD", + note = "all constants in this module replaced by associated constants on `i8`" +)] + +int_module! { i8 } diff --git a/CoqOfRust/core/num/shells/int_macros.rs b/CoqOfRust/core/num/shells/int_macros.rs new file mode 100644 index 000000000..8ae9b7aba --- /dev/null +++ b/CoqOfRust/core/num/shells/int_macros.rs @@ -0,0 +1,46 @@ +#![doc(hidden)] + +macro_rules! int_module { + ($T:ident) => (int_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); + ($T:ident, #[$attr:meta]) => ( + #[doc = concat!( + "The smallest value that can be represented by this integer type. Use ", + "[`", stringify!($T), "::MIN", "`] instead." + )] + /// + /// # Examples + /// + /// ```rust + /// // deprecated way + #[doc = concat!("let min = std::", stringify!($T), "::MIN;")] + /// + /// // intended way + #[doc = concat!("let min = ", stringify!($T), "::MIN;")] + /// ``` + /// + #[$attr] + #[deprecated(since = "TBD", note = "replaced by the `MIN` associated constant on this type")] + #[rustc_diagnostic_item = concat!(stringify!($T), "_legacy_const_min")] + pub const MIN: $T = $T::MIN; + + #[doc = concat!( + "The largest value that can be represented by this integer type. Use ", + "[`", stringify!($T), "::MAX", "`] instead." + )] + /// + /// # Examples + /// + /// ```rust + /// // deprecated way + #[doc = concat!("let max = std::", stringify!($T), "::MAX;")] + /// + /// // intended way + #[doc = concat!("let max = ", stringify!($T), "::MAX;")] + /// ``` + /// + #[$attr] + #[deprecated(since = "TBD", note = "replaced by the `MAX` associated constant on this type")] + #[rustc_diagnostic_item = concat!(stringify!($T), "_legacy_const_max")] + pub const MAX: $T = $T::MAX; + ) +} diff --git a/CoqOfRust/core/num/shells/isize.rs b/CoqOfRust/core/num/shells/isize.rs new file mode 100644 index 000000000..828f7345b --- /dev/null +++ b/CoqOfRust/core/num/shells/isize.rs @@ -0,0 +1,11 @@ +//! Redundant constants module for the [`isize` primitive type][isize]. +//! +//! New code should use the associated constants directly on the primitive type. + +#![stable(feature = "rust1", since = "1.0.0")] +#![deprecated( + since = "TBD", + note = "all constants in this module replaced by associated constants on `isize`" +)] + +int_module! { isize } diff --git a/CoqOfRust/core/num/shells/u128.rs b/CoqOfRust/core/num/shells/u128.rs new file mode 100644 index 000000000..b1e30e384 --- /dev/null +++ b/CoqOfRust/core/num/shells/u128.rs @@ -0,0 +1,11 @@ +//! Redundant constants module for the [`u128` primitive type][u128]. +//! +//! New code should use the associated constants directly on the primitive type. + +#![stable(feature = "i128", since = "1.26.0")] +#![deprecated( + since = "TBD", + note = "all constants in this module replaced by associated constants on `u128`" +)] + +int_module! { u128, #[stable(feature = "i128", since="1.26.0")] } diff --git a/CoqOfRust/core/num/shells/u16.rs b/CoqOfRust/core/num/shells/u16.rs new file mode 100644 index 000000000..7394977e5 --- /dev/null +++ b/CoqOfRust/core/num/shells/u16.rs @@ -0,0 +1,11 @@ +//! Redundant constants module for the [`u16` primitive type][u16]. +//! +//! New code should use the associated constants directly on the primitive type. + +#![stable(feature = "rust1", since = "1.0.0")] +#![deprecated( + since = "TBD", + note = "all constants in this module replaced by associated constants on `u16`" +)] + +int_module! { u16 } diff --git a/CoqOfRust/core/num/shells/u32.rs b/CoqOfRust/core/num/shells/u32.rs new file mode 100644 index 000000000..4c84274e7 --- /dev/null +++ b/CoqOfRust/core/num/shells/u32.rs @@ -0,0 +1,11 @@ +//! Redundant constants module for the [`u32` primitive type][u32]. +//! +//! New code should use the associated constants directly on the primitive type. + +#![stable(feature = "rust1", since = "1.0.0")] +#![deprecated( + since = "TBD", + note = "all constants in this module replaced by associated constants on `u32`" +)] + +int_module! { u32 } diff --git a/CoqOfRust/core/num/shells/u64.rs b/CoqOfRust/core/num/shells/u64.rs new file mode 100644 index 000000000..47a95c682 --- /dev/null +++ b/CoqOfRust/core/num/shells/u64.rs @@ -0,0 +1,11 @@ +//! Redundant constants module for the [`u64` primitive type][u64]. +//! +//! New code should use the associated constants directly on the primitive type. + +#![stable(feature = "rust1", since = "1.0.0")] +#![deprecated( + since = "TBD", + note = "all constants in this module replaced by associated constants on `u64`" +)] + +int_module! { u64 } diff --git a/CoqOfRust/core/num/shells/u8.rs b/CoqOfRust/core/num/shells/u8.rs new file mode 100644 index 000000000..360baef72 --- /dev/null +++ b/CoqOfRust/core/num/shells/u8.rs @@ -0,0 +1,11 @@ +//! Redundant constants module for the [`u8` primitive type][u8]. +//! +//! New code should use the associated constants directly on the primitive type. + +#![stable(feature = "rust1", since = "1.0.0")] +#![deprecated( + since = "TBD", + note = "all constants in this module replaced by associated constants on `u8`" +)] + +int_module! { u8 } diff --git a/CoqOfRust/core/num/shells/usize.rs b/CoqOfRust/core/num/shells/usize.rs new file mode 100644 index 000000000..44c24dfc2 --- /dev/null +++ b/CoqOfRust/core/num/shells/usize.rs @@ -0,0 +1,11 @@ +//! Redundant constants module for the [`usize` primitive type][usize]. +//! +//! New code should use the associated constants directly on the primitive type. + +#![stable(feature = "rust1", since = "1.0.0")] +#![deprecated( + since = "TBD", + note = "all constants in this module replaced by associated constants on `usize`" +)] + +int_module! { usize } diff --git a/CoqOfRust/core/num/uint_macros.rs b/CoqOfRust/core/num/uint_macros.rs new file mode 100644 index 000000000..c79b2f7ad --- /dev/null +++ b/CoqOfRust/core/num/uint_macros.rs @@ -0,0 +1,3374 @@ +macro_rules! uint_impl { + ( + Self = $SelfT:ty, + ActualT = $ActualT:ident, + SignedT = $SignedT:ident, + + // There are all for use *only* in doc comments. + // As such, they're all passed as literals -- passing them as a string + // literal is fine if they need to be multiple code tokens. + // In non-comments, use the associated constants rather than these. + BITS = $BITS:literal, + BITS_MINUS_ONE = $BITS_MINUS_ONE:literal, + MAX = $MaxV:literal, + rot = $rot:literal, + rot_op = $rot_op:literal, + rot_result = $rot_result:literal, + swap_op = $swap_op:literal, + swapped = $swapped:literal, + reversed = $reversed:literal, + le_bytes = $le_bytes:literal, + be_bytes = $be_bytes:literal, + to_xe_bytes_doc = $to_xe_bytes_doc:expr, + from_xe_bytes_doc = $from_xe_bytes_doc:expr, + bound_condition = $bound_condition:literal, + ) => { + /// The smallest value that can be represented by this integer type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN, 0);")] + /// ``` + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MIN: Self = 0; + + /// The largest value that can be represented by this integer type + #[doc = concat!("(2", $BITS, " − 1", $bound_condition, ").")] + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($MaxV), ");")] + /// ``` + #[stable(feature = "assoc_int_consts", since = "1.43.0")] + pub const MAX: Self = !0; + + /// The size of this integer type in bits. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")] + /// ``` + #[stable(feature = "int_bits_const", since = "1.53.0")] + pub const BITS: u32 = Self::MAX.count_ones(); + + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0b01001100", stringify!($SelfT), ";")] + /// assert_eq!(n.count_ones(), 3); + /// + #[doc = concat!("let max = ", stringify!($SelfT),"::MAX;")] + #[doc = concat!("assert_eq!(max.count_ones(), ", stringify!($BITS), ");")] + /// + #[doc = concat!("let zero = 0", stringify!($SelfT), ";")] + /// assert_eq!(zero.count_ones(), 0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[doc(alias = "popcount")] + #[doc(alias = "popcnt")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn count_ones(self) -> u32 { + return intrinsics::ctpop(self); + } + + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let zero = 0", stringify!($SelfT), ";")] + #[doc = concat!("assert_eq!(zero.count_zeros(), ", stringify!($BITS), ");")] + /// + #[doc = concat!("let max = ", stringify!($SelfT),"::MAX;")] + /// assert_eq!(max.count_zeros(), 0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn count_zeros(self) -> u32 { + (!self).count_ones() + } + + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// Depending on what you're doing with the value, you might also be interested in the + /// [`ilog2`] function which returns a consistent number, even if the type widens. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", stringify!($SelfT), "::MAX >> 2;")] + /// assert_eq!(n.leading_zeros(), 2); + /// + #[doc = concat!("let zero = 0", stringify!($SelfT), ";")] + #[doc = concat!("assert_eq!(zero.leading_zeros(), ", stringify!($BITS), ");")] + /// + #[doc = concat!("let max = ", stringify!($SelfT),"::MAX;")] + /// assert_eq!(max.leading_zeros(), 0); + /// ``` + #[doc = concat!("[`ilog2`]: ", stringify!($SelfT), "::ilog2")] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn leading_zeros(self) -> u32 { + return intrinsics::ctlz(self as $ActualT); + } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0b0101000", stringify!($SelfT), ";")] + /// assert_eq!(n.trailing_zeros(), 3); + /// + #[doc = concat!("let zero = 0", stringify!($SelfT), ";")] + #[doc = concat!("assert_eq!(zero.trailing_zeros(), ", stringify!($BITS), ");")] + /// + #[doc = concat!("let max = ", stringify!($SelfT),"::MAX;")] + #[doc = concat!("assert_eq!(max.trailing_zeros(), 0);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn trailing_zeros(self) -> u32 { + return intrinsics::cttz(self); + } + + /// Returns the number of leading ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = !(", stringify!($SelfT), "::MAX >> 2);")] + /// assert_eq!(n.leading_ones(), 2); + /// + #[doc = concat!("let zero = 0", stringify!($SelfT), ";")] + /// assert_eq!(zero.leading_ones(), 0); + /// + #[doc = concat!("let max = ", stringify!($SelfT),"::MAX;")] + #[doc = concat!("assert_eq!(max.leading_ones(), ", stringify!($BITS), ");")] + /// ``` + #[stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn leading_ones(self) -> u32 { + (!self).leading_zeros() + } + + /// Returns the number of trailing ones in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0b1010111", stringify!($SelfT), ";")] + /// assert_eq!(n.trailing_ones(), 3); + /// + #[doc = concat!("let zero = 0", stringify!($SelfT), ";")] + /// assert_eq!(zero.trailing_ones(), 0); + /// + #[doc = concat!("let max = ", stringify!($SelfT),"::MAX;")] + #[doc = concat!("assert_eq!(max.trailing_ones(), ", stringify!($BITS), ");")] + /// ``` + #[stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn trailing_ones(self) -> u32 { + (!self).trailing_zeros() + } + + /// Returns the bit pattern of `self` reinterpreted as a signed integer of the same size. + /// + /// This produces the same result as an `as` cast, but ensures that the bit-width remains + /// the same. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(integer_sign_cast)] + /// + #[doc = concat!("let n = ", stringify!($SelfT), "::MAX;")] + /// + #[doc = concat!("assert_eq!(n.cast_signed(), -1", stringify!($SignedT), ");")] + /// ``` + #[unstable(feature = "integer_sign_cast", issue = "125882")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn cast_signed(self) -> $SignedT { + self as $SignedT + } + + /// Shifts the bits to the left by a specified amount, `n`, + /// wrapping the truncated bits to the end of the resulting integer. + /// + /// Please note this isn't the same operation as the `<<` shifting operator! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $rot_op, stringify!($SelfT), ";")] + #[doc = concat!("let m = ", $rot_result, ";")] + /// + #[doc = concat!("assert_eq!(n.rotate_left(", $rot, "), m);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn rotate_left(self, n: u32) -> Self { + return intrinsics::rotate_left(self, n); + } + + /// Shifts the bits to the right by a specified amount, `n`, + /// wrapping the truncated bits to the beginning of the resulting + /// integer. + /// + /// Please note this isn't the same operation as the `>>` shifting operator! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $rot_result, stringify!($SelfT), ";")] + #[doc = concat!("let m = ", $rot_op, ";")] + /// + #[doc = concat!("assert_eq!(n.rotate_right(", $rot, "), m);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn rotate_right(self, n: u32) -> Self { + return intrinsics::rotate_right(self, n); + } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $swap_op, stringify!($SelfT), ";")] + /// let m = n.swap_bytes(); + /// + #[doc = concat!("assert_eq!(m, ", $swapped, ");")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn swap_bytes(self) -> Self { + intrinsics::bswap(self as $ActualT) as Self + } + + /// Reverses the order of bits in the integer. The least significant bit becomes the most significant bit, + /// second least-significant bit becomes second most-significant bit, etc. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = ", $swap_op, stringify!($SelfT), ";")] + /// let m = n.reverse_bits(); + /// + #[doc = concat!("assert_eq!(m, ", $reversed, ");")] + #[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")] + /// ``` + #[stable(feature = "reverse_bits", since = "1.37.0")] + #[rustc_const_stable(feature = "reverse_bits", since = "1.37.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn reverse_bits(self) -> Self { + intrinsics::bitreverse(self as $ActualT) as Self + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "big") { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_be(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_be(n), n.swap_bytes())")] + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use] + #[inline(always)] + pub const fn from_be(x: Self) -> Self { + #[cfg(target_endian = "big")] + { + x + } + #[cfg(not(target_endian = "big"))] + { + x.swap_bytes() + } + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "little") { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_le(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(", stringify!($SelfT), "::from_le(n), n.swap_bytes())")] + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use] + #[inline(always)] + pub const fn from_le(x: Self) -> Self { + #[cfg(target_endian = "little")] + { + x + } + #[cfg(not(target_endian = "little"))] + { + x.swap_bytes() + } + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn to_be(self) -> Self { // or not to be? + #[cfg(target_endian = "big")] + { + self + } + #[cfg(not(target_endian = "big"))] + { + self.swap_bytes() + } + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = 0x1A", stringify!($SelfT), ";")] + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(not(target_endian = "little"))] + { + self.swap_bytes() + } + } + + /// Checked integer addition. Computes `self + rhs`, returning `None` + /// if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!( + "assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(1), ", + "Some(", stringify!($SelfT), "::MAX - 1));" + )] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_add(self, rhs: Self) -> Option { + // This used to use `overflowing_add`, but that means it ends up being + // a `wrapping_add`, losing some optimization opportunities. Notably, + // phrasing it this way helps `.checked_add(1)` optimize to a check + // against `MAX` and a `add nuw`. + // Per , + // LLVM is happy to re-form the intrinsic later if useful. + + if intrinsics::unlikely(intrinsics::add_with_overflow(self, rhs).1) { + None + } else { + // SAFETY: Just checked it doesn't overflow + Some(unsafe { intrinsics::unchecked_add(self, rhs) }) + } + } + + /// Strict integer addition. Computes `self + rhs`, panicking + /// if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).strict_add(1), ", stringify!($SelfT), "::MAX - 1);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_add(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_add(rhs); + if b { overflow_panic::add() } else { a } + } + + /// Unchecked integer addition. Computes `self + rhs`, assuming overflow + /// cannot occur. + /// + /// Calling `x.unchecked_add(y)` is semantically equivalent to calling + /// `x.`[`checked_add`]`(y).`[`unwrap_unchecked`]`()`. + /// + /// If you're just trying to avoid the panic in debug mode, then **do not** + /// use this. Instead, you're looking for [`wrapping_add`]. + /// + /// # Safety + /// + /// This results in undefined behavior when + #[doc = concat!("`self + rhs > ", stringify!($SelfT), "::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`,")] + /// i.e. when [`checked_add`] would return `None`. + /// + /// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked + #[doc = concat!("[`checked_add`]: ", stringify!($SelfT), "::checked_add")] + #[doc = concat!("[`wrapping_add`]: ", stringify!($SelfT), "::wrapping_add")] + #[stable(feature = "unchecked_math", since = "1.79.0")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_add(self, rhs: Self) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_add cannot overflow"), + ( + lhs: $SelfT = self, + rhs: $SelfT = rhs, + ) => !lhs.overflowing_add(rhs).1, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + intrinsics::unchecked_add(self, rhs) + } + } + + /// Checked addition with a signed integer. Computes `self + rhs`, + /// returning `None` if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(2), Some(3));")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(-2), None);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_signed(3), None);")] + /// ``` + #[stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_add_signed(self, rhs: $SignedT) -> Option { + let (a, b) = self.overflowing_add_signed(rhs); + if intrinsics::unlikely(b) { None } else { Some(a) } + } + + /// Strict addition with a signed integer. Computes `self + rhs`, + /// panicking if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_add_signed(2), 3);")] + /// ``` + /// + /// The following panic because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_add_signed(-2);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_signed(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_add_signed(self, rhs: $SignedT) -> Self { + let (a, b) = self.overflowing_add_signed(rhs); + if b { overflow_panic::add() } else { a } + } + + /// Checked integer subtraction. Computes `self - rhs`, returning + /// `None` if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub(1), Some(0));")] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".checked_sub(1), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_sub(self, rhs: Self) -> Option { + // Per PR#103299, there's no advantage to the `overflowing` intrinsic + // for *unsigned* subtraction and we just emit the manual check anyway. + // Thus, rather than using `overflowing_sub` that produces a wrapping + // subtraction, check it ourself so we can use an unchecked one. + + if self < rhs { + None + } else { + // SAFETY: just checked this can't overflow + Some(unsafe { intrinsics::unchecked_sub(self, rhs) }) + } + } + + /// Strict integer subtraction. Computes `self - rhs`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_sub(1), 0);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0", stringify!($SelfT), ".strict_sub(1);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_sub(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_sub(rhs); + if b { overflow_panic::sub() } else { a } + } + + /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow + /// cannot occur. + /// + /// Calling `x.unchecked_sub(y)` is semantically equivalent to calling + /// `x.`[`checked_sub`]`(y).`[`unwrap_unchecked`]`()`. + /// + /// If you're just trying to avoid the panic in debug mode, then **do not** + /// use this. Instead, you're looking for [`wrapping_sub`]. + /// + /// If you find yourself writing code like this: + /// + /// ``` + /// # let foo = 30_u32; + /// # let bar = 20; + /// if foo >= bar { + /// // SAFETY: just checked it will not overflow + /// let diff = unsafe { foo.unchecked_sub(bar) }; + /// // ... use diff ... + /// } + /// ``` + /// + /// Consider changing it to + /// + /// ``` + /// # let foo = 30_u32; + /// # let bar = 20; + /// if let Some(diff) = foo.checked_sub(bar) { + /// // ... use diff ... + /// } + /// ``` + /// + /// As that does exactly the same thing -- including telling the optimizer + /// that the subtraction cannot overflow -- but avoids needing `unsafe`. + /// + /// # Safety + /// + /// This results in undefined behavior when + #[doc = concat!("`self - rhs > ", stringify!($SelfT), "::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`,")] + /// i.e. when [`checked_sub`] would return `None`. + /// + /// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked + #[doc = concat!("[`checked_sub`]: ", stringify!($SelfT), "::checked_sub")] + #[doc = concat!("[`wrapping_sub`]: ", stringify!($SelfT), "::wrapping_sub")] + #[stable(feature = "unchecked_math", since = "1.79.0")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_sub cannot overflow"), + ( + lhs: $SelfT = self, + rhs: $SelfT = rhs, + ) => !lhs.overflowing_sub(rhs).1, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + intrinsics::unchecked_sub(self, rhs) + } + } + + /// Checked subtraction with a signed integer. Computes `self - rhs`, + /// returning `None` if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(mixed_integer_ops_unsigned_sub)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_signed(2), None);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_signed(-2), Some(3));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_sub_signed(-4), None);")] + /// ``` + #[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_sub_signed(self, rhs: $SignedT) -> Option { + let (res, overflow) = self.overflowing_sub_signed(rhs); + + if !overflow { + Some(res) + } else { + None + } + } + + #[doc = concat!( + "Checked integer subtraction. Computes `self - rhs` and checks if the result fits into an [`", + stringify!($SignedT), "`], returning `None` if overflow occurred." + )] + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(unsigned_signed_diff)] + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_signed_diff(2), Some(8));")] + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_signed_diff(10), Some(-8));")] + #[doc = concat!( + "assert_eq!(", + stringify!($SelfT), + "::MAX.checked_signed_diff(", + stringify!($SignedT), + "::MAX as ", + stringify!($SelfT), + "), None);" + )] + #[doc = concat!( + "assert_eq!((", + stringify!($SignedT), + "::MAX as ", + stringify!($SelfT), + ").checked_signed_diff(", + stringify!($SelfT), + "::MAX), Some(", + stringify!($SignedT), + "::MIN));" + )] + #[doc = concat!( + "assert_eq!((", + stringify!($SignedT), + "::MAX as ", + stringify!($SelfT), + " + 1).checked_signed_diff(0), None);" + )] + #[doc = concat!( + "assert_eq!(", + stringify!($SelfT), + "::MAX.checked_signed_diff(", + stringify!($SelfT), + "::MAX), Some(0));" + )] + /// ``` + #[unstable(feature = "unsigned_signed_diff", issue = "126041")] + #[inline] + pub const fn checked_signed_diff(self, rhs: Self) -> Option<$SignedT> { + let res = self.wrapping_sub(rhs) as $SignedT; + let overflow = (self >= rhs) == (res < 0); + + if !overflow { + Some(res) + } else { + None + } + } + + /// Checked integer multiplication. Computes `self * rhs`, returning + /// `None` if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_mul(1), Some(5));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_mul(self, rhs: Self) -> Option { + let (a, b) = self.overflowing_mul(rhs); + if intrinsics::unlikely(b) { None } else { Some(a) } + } + + /// Strict integer multiplication. Computes `self * rhs`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_mul(1), 5);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ``` should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_mul(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_mul(rhs); + if b { overflow_panic::mul() } else { a } + } + + /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow + /// cannot occur. + /// + /// Calling `x.unchecked_mul(y)` is semantically equivalent to calling + /// `x.`[`checked_mul`]`(y).`[`unwrap_unchecked`]`()`. + /// + /// If you're just trying to avoid the panic in debug mode, then **do not** + /// use this. Instead, you're looking for [`wrapping_mul`]. + /// + /// # Safety + /// + /// This results in undefined behavior when + #[doc = concat!("`self * rhs > ", stringify!($SelfT), "::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`,")] + /// i.e. when [`checked_mul`] would return `None`. + /// + /// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked + #[doc = concat!("[`checked_mul`]: ", stringify!($SelfT), "::checked_mul")] + #[doc = concat!("[`wrapping_mul`]: ", stringify!($SelfT), "::wrapping_mul")] + #[stable(feature = "unchecked_math", since = "1.79.0")] + #[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_mul cannot overflow"), + ( + lhs: $SelfT = self, + rhs: $SelfT = rhs, + ) => !lhs.overflowing_mul(rhs).1, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + intrinsics::unchecked_mul(self, rhs) + } + } + + /// Checked integer division. Computes `self / rhs`, returning `None` + /// if `rhs == 0`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(128", stringify!($SelfT), ".checked_div(2), Some(64));")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_checked_int_div", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_div(self, rhs: Self) -> Option { + if intrinsics::unlikely(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_div(self, rhs) }) + } + } + + /// Strict integer division. Computes `self / rhs`. + /// + /// Strict division on unsigned types is just normal division. There's no + /// way overflow could ever happen. This function exists so that all + /// operations are accounted for in the strict operations. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_div(10), 10);")] + /// ``` + /// + /// The following panics because of division by zero: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn strict_div(self, rhs: Self) -> Self { + self / rhs + } + + /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` + /// if `rhs == 0`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(128", stringify!($SelfT), ".checked_div_euclid(2), Some(64));")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None);")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_div_euclid(self, rhs: Self) -> Option { + if intrinsics::unlikely(rhs == 0) { + None + } else { + Some(self.div_euclid(rhs)) + } + } + + /// Strict Euclidean division. Computes `self.div_euclid(rhs)`. + /// + /// Strict division on unsigned types is just normal division. There's no + /// way overflow could ever happen. This function exists so that all + /// operations are accounted for in the strict operations. Since, for the + /// positive integers, all common definitions of division are equal, this + /// is exactly equal to `self.strict_div(rhs)`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_div_euclid(10), 10);")] + /// ``` + /// The following panics because of division by zero: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn strict_div_euclid(self, rhs: Self) -> Self { + self / rhs + } + + /// Checked integer remainder. Computes `self % rhs`, returning `None` + /// if `rhs == 0`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(2), Some(1));")] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_checked_int_div", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_rem(self, rhs: Self) -> Option { + if intrinsics::unlikely(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) }) + } + } + + /// Strict integer remainder. Computes `self % rhs`. + /// + /// Strict remainder calculation on unsigned types is just the regular + /// remainder calculation. There's no way overflow could ever happen. + /// This function exists so that all operations are accounted for in the + /// strict operations. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_rem(10), 0);")] + /// ``` + /// + /// The following panics because of division by zero: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem(0);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn strict_rem(self, rhs: Self) -> Self { + self % rhs + } + + /// Checked Euclidean modulo. Computes `self.rem_euclid(rhs)`, returning `None` + /// if `rhs == 0`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));")] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_rem_euclid(self, rhs: Self) -> Option { + if intrinsics::unlikely(rhs == 0) { + None + } else { + Some(self.rem_euclid(rhs)) + } + } + + /// Strict Euclidean modulo. Computes `self.rem_euclid(rhs)`. + /// + /// Strict modulo calculation on unsigned types is just the regular + /// remainder calculation. There's no way overflow could ever happen. + /// This function exists so that all operations are accounted for in the + /// strict operations. Since, for the positive integers, all common + /// definitions of division are equal, this is exactly equal to + /// `self.strict_rem(rhs)`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_rem_euclid(10), 0);")] + /// ``` + /// + /// The following panics because of division by zero: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem_euclid(0);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn strict_rem_euclid(self, rhs: Self) -> Self { + self % rhs + } + + /// Returns the logarithm of the number with respect to an arbitrary base, + /// rounded down. + /// + /// This method might not be optimized owing to implementation details; + /// `ilog2` can produce results more efficiently for base 2, and `ilog10` + /// can produce results more efficiently for base 10. + /// + /// # Panics + /// + /// This function will panic if `self` is zero, or if `base` is less than 2. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn ilog(self, base: Self) -> u32 { + assert!(base >= 2, "base of integer logarithm must be at least 2"); + if let Some(log) = self.checked_ilog(base) { + log + } else { + int_log10::panic_for_nonpositive_argument() + } + } + + /// Returns the base 2 logarithm of the number, rounded down. + /// + /// # Panics + /// + /// This function will panic if `self` is zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn ilog2(self) -> u32 { + if let Some(log) = self.checked_ilog2() { + log + } else { + int_log10::panic_for_nonpositive_argument() + } + } + + /// Returns the base 10 logarithm of the number, rounded down. + /// + /// # Panics + /// + /// This function will panic if `self` is zero. + /// + /// # Example + /// + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn ilog10(self) -> u32 { + if let Some(log) = self.checked_ilog10() { + log + } else { + int_log10::panic_for_nonpositive_argument() + } + } + + /// Returns the logarithm of the number with respect to an arbitrary base, + /// rounded down. + /// + /// Returns `None` if the number is zero, or if the base is not at least 2. + /// + /// This method might not be optimized owing to implementation details; + /// `checked_ilog2` can produce results more efficiently for base 2, and + /// `checked_ilog10` can produce results more efficiently for base 10. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_ilog(self, base: Self) -> Option { + if self <= 0 || base <= 1 { + None + } else if self < base { + Some(0) + } else { + // Since base >= self, n >= 1 + let mut n = 1; + let mut r = base; + + // Optimization for 128 bit wide integers. + if Self::BITS == 128 { + // The following is a correct lower bound for ⌊log(base,self)⌋ because + // + // log(base,self) = log(2,self) / log(2,base) + // ≥ ⌊log(2,self)⌋ / (⌊log(2,base)⌋ + 1) + // + // hence + // + // ⌊log(base,self)⌋ ≥ ⌊ ⌊log(2,self)⌋ / (⌊log(2,base)⌋ + 1) ⌋ . + n = self.ilog2() / (base.ilog2() + 1); + r = base.pow(n); + } + + while r <= self / base { + n += 1; + r *= base; + } + Some(n) + } + } + + /// Returns the base 2 logarithm of the number, rounded down. + /// + /// Returns `None` if the number is zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_ilog2(self) -> Option { + match NonZero::new(self) { + Some(x) => Some(x.ilog2()), + None => None, + } + } + + /// Returns the base 10 logarithm of the number, rounded down. + /// + /// Returns `None` if the number is zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_ilog10(self) -> Option { + match NonZero::new(self) { + Some(x) => Some(x.ilog10()), + None => None, + } + } + + /// Checked negation. Computes `-self`, returning `None` unless `self == + /// 0`. + /// + /// Note that negating any positive integer will overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".checked_neg(), Some(0));")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_neg(), None);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_neg(self) -> Option { + let (a, b) = self.overflowing_neg(); + if intrinsics::unlikely(b) { None } else { Some(a) } + } + + /// Strict negation. Computes `-self`, panicking unless `self == + /// 0`. + /// + /// Note that negating any positive integer will overflow. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".strict_neg(), 0);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_neg();")] + /// + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_neg(self) -> Self { + let (a, b) = self.overflowing_neg(); + if b { overflow_panic::neg() } else { a } + } + + /// Checked shift left. Computes `self << rhs`, returning `None` + /// if `rhs` is larger than or equal to the number of bits in `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".checked_shl(4), Some(0x10));")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shl(129), None);")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shl(", stringify!($BITS_MINUS_ONE), "), Some(0));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_shl(self, rhs: u32) -> Option { + // Not using overflowing_shl as that's a wrapping shift + if rhs < Self::BITS { + // SAFETY: just checked the RHS is in-range + Some(unsafe { self.unchecked_shl(rhs) }) + } else { + None + } + } + + /// Strict shift left. Computes `self << rhs`, panicking if `rhs` is larger + /// than or equal to the number of bits in `self`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".strict_shl(4), 0x10);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shl(129);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_shl(self, rhs: u32) -> Self { + let (a, b) = self.overflowing_shl(rhs); + if b { overflow_panic::shl() } else { a } + } + + /// Unchecked shift left. Computes `self << rhs`, assuming that + /// `rhs` is less than the number of bits in `self`. + /// + /// # Safety + /// + /// This results in undefined behavior if `rhs` is larger than + /// or equal to the number of bits in `self`, + /// i.e. when [`checked_shl`] would return `None`. + /// + #[doc = concat!("[`checked_shl`]: ", stringify!($SelfT), "::checked_shl")] + #[unstable( + feature = "unchecked_shifts", + reason = "niche optimization path", + issue = "85122", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_shl cannot overflow"), + ( + rhs: u32 = rhs, + ) => rhs < <$ActualT>::BITS, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + intrinsics::unchecked_shl(self, rhs) + } + } + + /// Unbounded shift left. Computes `self << rhs`, without bounding the value of `rhs`. + /// + /// If `rhs` is larger or equal to the number of bits in `self`, + /// the entire value is shifted out, and `0` is returned. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(unbounded_shifts)] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(4), 0x10);")] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(129), 0);")] + /// ``` + #[unstable(feature = "unbounded_shifts", issue = "129375")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unbounded_shl(self, rhs: u32) -> $SelfT{ + if rhs < Self::BITS { + // SAFETY: + // rhs is just checked to be in-range above + unsafe { self.unchecked_shl(rhs) } + } else { + 0 + } + } + + /// Checked shift right. Computes `self >> rhs`, returning `None` + /// if `rhs` is larger than or equal to the number of bits in `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shr(4), Some(0x1));")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".checked_shr(129), None);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_shr(self, rhs: u32) -> Option { + // Not using overflowing_shr as that's a wrapping shift + if rhs < Self::BITS { + // SAFETY: just checked the RHS is in-range + Some(unsafe { self.unchecked_shr(rhs) }) + } else { + None + } + } + + /// Strict shift right. Computes `self >> rhs`, panicking `rhs` is + /// larger than or equal to the number of bits in `self`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".strict_shr(4), 0x1);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(129);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_shr(self, rhs: u32) -> Self { + let (a, b) = self.overflowing_shr(rhs); + if b { overflow_panic::shr() } else { a } + } + + /// Unchecked shift right. Computes `self >> rhs`, assuming that + /// `rhs` is less than the number of bits in `self`. + /// + /// # Safety + /// + /// This results in undefined behavior if `rhs` is larger than + /// or equal to the number of bits in `self`, + /// i.e. when [`checked_shr`] would return `None`. + /// + #[doc = concat!("[`checked_shr`]: ", stringify!($SelfT), "::checked_shr")] + #[unstable( + feature = "unchecked_shifts", + reason = "niche optimization path", + issue = "85122", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_shr cannot overflow"), + ( + rhs: u32 = rhs, + ) => rhs < <$ActualT>::BITS, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + intrinsics::unchecked_shr(self, rhs) + } + } + + /// Unbounded shift right. Computes `self >> rhs`, without bounding the value of `rhs`. + /// + /// If `rhs` is larger or equal to the number of bits in `self`, + /// the entire value is shifted out, and `0` is returned. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(unbounded_shifts)] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(4), 0x1);")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(129), 0);")] + /// ``` + #[unstable(feature = "unbounded_shifts", issue = "129375")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unbounded_shr(self, rhs: u32) -> $SelfT{ + if rhs < Self::BITS { + // SAFETY: + // rhs is just checked to be in-range above + unsafe { self.unchecked_shr(rhs) } + } else { + 0 + } + } + + /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if + /// overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_pow(5), Some(32));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);")] + /// ``` + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_pow(self, mut exp: u32) -> Option { + if exp == 0 { + return Some(1); + } + let mut base = self; + let mut acc: Self = 1; + + loop { + if (exp & 1) == 1 { + acc = try_opt!(acc.checked_mul(base)); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return Some(acc); + } + } + exp /= 2; + base = try_opt!(base.checked_mul(base)); + } + } + + /// Strict exponentiation. Computes `self.pow(exp)`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".strict_pow(5), 32);")] + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc: Self = 1; + + loop { + if (exp & 1) == 1 { + acc = acc.strict_mul(base); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return acc; + } + } + exp /= 2; + base = base.strict_mul(base); + } + } + + /// Saturating integer addition. Computes `self + rhs`, saturating at + /// the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_add(127), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[inline(always)] + pub const fn saturating_add(self, rhs: Self) -> Self { + intrinsics::saturating_add(self, rhs) + } + + /// Saturating addition with a signed integer. Computes `self + rhs`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(2), 3);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(-2), 0);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_add_signed(4), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_add_signed(self, rhs: $SignedT) -> Self { + let (res, overflow) = self.overflowing_add(rhs as Self); + if overflow == (rhs < 0) { + res + } else if overflow { + Self::MAX + } else { + 0 + } + } + + /// Saturating integer subtraction. Computes `self - rhs`, saturating + /// at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_sub(27), 73);")] + #[doc = concat!("assert_eq!(13", stringify!($SelfT), ".saturating_sub(127), 0);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[inline(always)] + pub const fn saturating_sub(self, rhs: Self) -> Self { + intrinsics::saturating_sub(self, rhs) + } + + /// Saturating integer subtraction. Computes `self` - `rhs`, saturating at + /// the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(mixed_integer_ops_unsigned_sub)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_sub_signed(2), 0);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_sub_signed(-2), 3);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_sub_signed(-4), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_sub_signed(self, rhs: $SignedT) -> Self { + let (res, overflow) = self.overflowing_sub_signed(rhs); + + if !overflow { + res + } else if rhs < 0 { + Self::MAX + } else { + 0 + } + } + + /// Saturating integer multiplication. Computes `self * rhs`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".saturating_mul(10), 20);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($SelfT),"::MAX);")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_mul(self, rhs: Self) -> Self { + match self.checked_mul(rhs) { + Some(x) => x, + None => Self::MAX, + } + } + + /// Saturating integer division. Computes `self / rhs`, saturating at the + /// numeric bounds instead of overflowing. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".saturating_div(2), 2);")] + /// + /// ``` + #[stable(feature = "saturating_div", since = "1.58.0")] + #[rustc_const_stable(feature = "saturating_div", since = "1.58.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn saturating_div(self, rhs: Self) -> Self { + // on unsigned types, there is no overflow in integer division + self.wrapping_div(rhs) + } + + /// Saturating integer exponentiation. Computes `self.pow(exp)`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(4", stringify!($SelfT), ".saturating_pow(3), 64);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_pow(self, exp: u32) -> Self { + match self.checked_pow(exp) { + Some(x) => x, + None => Self::MAX, + } + } + + /// Wrapping (modular) addition. Computes `self + rhs`, + /// wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(200", stringify!($SelfT), ".wrapping_add(55), 255);")] + #[doc = concat!("assert_eq!(200", stringify!($SelfT), ".wrapping_add(", stringify!($SelfT), "::MAX), 199);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn wrapping_add(self, rhs: Self) -> Self { + intrinsics::wrapping_add(self, rhs) + } + + /// Wrapping (modular) addition with a signed integer. Computes + /// `self + rhs`, wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(2), 3);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(-2), ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_add_signed(4), 1);")] + /// ``` + #[stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_add_signed(self, rhs: $SignedT) -> Self { + self.wrapping_add(rhs as Self) + } + + /// Wrapping (modular) subtraction. Computes `self - rhs`, + /// wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_sub(100), 0);")] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_sub(", stringify!($SelfT), "::MAX), 101);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn wrapping_sub(self, rhs: Self) -> Self { + intrinsics::wrapping_sub(self, rhs) + } + + /// Wrapping (modular) subtraction with a signed integer. Computes + /// `self - rhs`, wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(mixed_integer_ops_unsigned_sub)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_sub_signed(2), ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_sub_signed(-2), 3);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_sub_signed(-4), 1);")] + /// ``` + #[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_sub_signed(self, rhs: $SignedT) -> Self { + self.wrapping_sub(rhs as Self) + } + + /// Wrapping (modular) multiplication. Computes `self * + /// rhs`, wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// Please note that this example is shared between integer types. + /// Which explains why `u8` is used here. + /// + /// ``` + /// assert_eq!(10u8.wrapping_mul(12), 120); + /// assert_eq!(25u8.wrapping_mul(12), 44); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn wrapping_mul(self, rhs: Self) -> Self { + intrinsics::wrapping_mul(self, rhs) + } + + /// Wrapping (modular) division. Computes `self / rhs`. + /// + /// Wrapped division on unsigned types is just normal division. There's + /// no way wrapping could ever happen. This function exists so that all + /// operations are accounted for in the wrapping operations. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_div(10), 10);")] + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_wrapping_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn wrapping_div(self, rhs: Self) -> Self { + self / rhs + } + + /// Wrapping Euclidean division. Computes `self.div_euclid(rhs)`. + /// + /// Wrapped division on unsigned types is just normal division. There's + /// no way wrapping could ever happen. This function exists so that all + /// operations are accounted for in the wrapping operations. Since, for + /// the positive integers, all common definitions of division are equal, + /// this is exactly equal to `self.wrapping_div(rhs)`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn wrapping_div_euclid(self, rhs: Self) -> Self { + self / rhs + } + + /// Wrapping (modular) remainder. Computes `self % rhs`. + /// + /// Wrapped remainder calculation on unsigned types is just the regular + /// remainder calculation. There's no way wrapping could ever happen. + /// This function exists so that all operations are accounted for in the + /// wrapping operations. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_rem(10), 0);")] + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_wrapping_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn wrapping_rem(self, rhs: Self) -> Self { + self % rhs + } + + /// Wrapping Euclidean modulo. Computes `self.rem_euclid(rhs)`. + /// + /// Wrapped modulo calculation on unsigned types is just the regular + /// remainder calculation. There's no way wrapping could ever happen. + /// This function exists so that all operations are accounted for in the + /// wrapping operations. Since, for the positive integers, all common + /// definitions of division are equal, this is exactly equal to + /// `self.wrapping_rem(rhs)`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self { + self % rhs + } + + /// Wrapping (modular) negation. Computes `-self`, + /// wrapping around at the boundary of the type. + /// + /// Since unsigned types do not have negative equivalents + /// all applications of this function will wrap (except for `-0`). + /// For values smaller than the corresponding signed type's maximum + /// the result is the same as casting the corresponding signed value. + /// Any larger values are equivalent to `MAX + 1 - (val - MAX - 1)` where + /// `MAX` is the corresponding signed type's maximum. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".wrapping_neg(), 0);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_neg(), 1);")] + #[doc = concat!("assert_eq!(13_", stringify!($SelfT), ".wrapping_neg(), (!13) + 1);")] + #[doc = concat!("assert_eq!(42_", stringify!($SelfT), ".wrapping_neg(), !(42 - 1));")] + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn wrapping_neg(self) -> Self { + (0 as $SelfT).wrapping_sub(self) + } + + /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, + /// where `mask` removes any high-order bits of `rhs` that + /// would cause the shift to exceed the bitwidth of the type. + /// + /// Note that this is *not* the same as a rotate-left; the + /// RHS of a wrapping shift-left is restricted to the range + /// of the type, rather than the bits shifted out of the LHS + /// being returned to the other end. The primitive integer + /// types all implement a [`rotate_left`](Self::rotate_left) function, + /// which may be what you want instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_shl(7), 128);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_shl(128), 1);")] + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + 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 { + self.unchecked_shl(rhs & (Self::BITS - 1)) + } + } + + /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`, + /// where `mask` removes any high-order bits of `rhs` that + /// would cause the shift to exceed the bitwidth of the type. + /// + /// Note that this is *not* the same as a rotate-right; the + /// RHS of a wrapping shift-right is restricted to the range + /// of the type, rather than the bits shifted out of the LHS + /// being returned to the other end. The primitive integer + /// types all implement a [`rotate_right`](Self::rotate_right) function, + /// which may be what you want instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(128", stringify!($SelfT), ".wrapping_shr(7), 1);")] + #[doc = concat!("assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);")] + /// ``` + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + 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 { + self.unchecked_shr(rhs & (Self::BITS - 1)) + } + } + + /// Wrapping (modular) exponentiation. Computes `self.pow(exp)`, + /// wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".wrapping_pow(5), 243);")] + /// assert_eq!(3u8.wrapping_pow(6), 217); + /// ``` + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc: Self = 1; + + if intrinsics::is_val_statically_known(exp) { + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); + } + exp /= 2; + base = base.wrapping_mul(base); + } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary. + acc.wrapping_mul(base) + } else { + // This is faster than the above when the exponent is not known + // at compile time. We can't use the same code for the constant + // exponent case because LLVM is currently unable to unroll + // this loop. + loop { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return acc; + } + } + exp /= 2; + base = base.wrapping_mul(base); + } + } + } + + /// Calculates `self` + `rhs`. + /// + /// Returns a tuple of the addition along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { + let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT); + (a as Self, b) + } + + /// Calculates `self` + `rhs` + `carry` and returns a tuple containing + /// the sum and the output carry. + /// + /// Performs "ternary addition" of two integer operands and a carry-in + /// bit, and returns an output integer and a carry-out bit. This allows + /// chaining together multiple additions to create a wider addition, and + /// can be useful for bignum addition. + /// + #[doc = concat!("This can be thought of as a ", stringify!($BITS), "-bit \"full adder\", in the electronics sense.")] + /// + /// If the input carry is false, this method is equivalent to + /// [`overflowing_add`](Self::overflowing_add), and the output carry is + /// equal to the overflow flag. Note that although carry and overflow + /// flags are similar for unsigned integers, they are different for + /// signed integers. + /// + /// # Examples + /// + /// ``` + /// #![feature(bigint_helper_methods)] + /// + #[doc = concat!("// 3 MAX (a = 3 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")] + #[doc = concat!("// + 5 7 (b = 5 × 2^", stringify!($BITS), " + 7)")] + /// // --------- + #[doc = concat!("// 9 6 (sum = 9 × 2^", stringify!($BITS), " + 6)")] + /// + #[doc = concat!("let (a1, a0): (", stringify!($SelfT), ", ", stringify!($SelfT), ") = (3, ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("let (b1, b0): (", stringify!($SelfT), ", ", stringify!($SelfT), ") = (5, 7);")] + /// let carry0 = false; + /// + /// let (sum0, carry1) = a0.carrying_add(b0, carry0); + /// assert_eq!(carry1, true); + /// let (sum1, carry2) = a1.carrying_add(b1, carry1); + /// assert_eq!(carry2, false); + /// + /// assert_eq!((sum1, sum0), (9, 6)); + /// ``` + #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool) { + // note: longer-term this should be done via an intrinsic, but this has been shown + // to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic + let (a, b) = self.overflowing_add(rhs); + let (c, d) = a.overflowing_add(carry as $SelfT); + (c, b | d) + } + + /// Calculates `self` + `rhs` with a signed `rhs`. + /// + /// Returns a tuple of the addition along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(2), (3, false));")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(-2), (", stringify!($SelfT), "::MAX, true));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_signed(4), (1, true));")] + /// ``` + #[stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_add_signed(self, rhs: $SignedT) -> (Self, bool) { + let (res, overflowed) = self.overflowing_add(rhs as Self); + (res, overflowed ^ (rhs < 0)) + } + + /// Calculates `self` - `rhs`. + /// + /// Returns a tuple of the subtraction along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));")] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT); + (a as Self, b) + } + + /// Calculates `self` − `rhs` − `borrow` and returns a tuple + /// containing the difference and the output borrow. + /// + /// Performs "ternary subtraction" by subtracting both an integer + /// operand and a borrow-in bit from `self`, and returns an output + /// integer and a borrow-out bit. This allows chaining together multiple + /// subtractions to create a wider subtraction, and can be useful for + /// bignum subtraction. + /// + /// # Examples + /// + /// ``` + /// #![feature(bigint_helper_methods)] + /// + #[doc = concat!("// 9 6 (a = 9 × 2^", stringify!($BITS), " + 6)")] + #[doc = concat!("// - 5 7 (b = 5 × 2^", stringify!($BITS), " + 7)")] + /// // --------- + #[doc = concat!("// 3 MAX (diff = 3 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")] + /// + #[doc = concat!("let (a1, a0): (", stringify!($SelfT), ", ", stringify!($SelfT), ") = (9, 6);")] + #[doc = concat!("let (b1, b0): (", stringify!($SelfT), ", ", stringify!($SelfT), ") = (5, 7);")] + /// let borrow0 = false; + /// + /// let (diff0, borrow1) = a0.borrowing_sub(b0, borrow0); + /// assert_eq!(borrow1, true); + /// let (diff1, borrow2) = a1.borrowing_sub(b1, borrow1); + /// assert_eq!(borrow2, false); + /// + #[doc = concat!("assert_eq!((diff1, diff0), (3, ", stringify!($SelfT), "::MAX));")] + /// ``` + #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool) { + // note: longer-term this should be done via an intrinsic, but this has been shown + // to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic + let (a, b) = self.overflowing_sub(rhs); + let (c, d) = a.overflowing_sub(borrow as $SelfT); + (c, b | d) + } + + /// Calculates `self` - `rhs` with a signed `rhs` + /// + /// Returns a tuple of the subtraction along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(mixed_integer_ops_unsigned_sub)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_signed(2), (", stringify!($SelfT), "::MAX, true));")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_signed(-2), (3, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_sub_signed(-4), (1, true));")] + /// ``` + #[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_sub_signed(self, rhs: $SignedT) -> (Self, bool) { + let (res, overflow) = self.overflowing_sub(rhs as Self); + + (res, overflow ^ (rhs < 0)) + } + + /// Computes the absolute difference between `self` and `other`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(80), 20", stringify!($SelfT), ");")] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(110), 10", stringify!($SelfT), ");")] + /// ``` + #[stable(feature = "int_abs_diff", since = "1.60.0")] + #[rustc_const_stable(feature = "int_abs_diff", since = "1.60.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn abs_diff(self, other: Self) -> Self { + if mem::size_of::() == 1 { + // Trick LLVM into generating the psadbw instruction when SSE2 + // is available and this function is autovectorized for u8's. + (self as i32).wrapping_sub(other as i32).abs() as Self + } else { + if self < other { + other - self + } else { + self - other + } + } + } + + /// Calculates the multiplication of `self` and `rhs`. + /// + /// Returns a tuple of the multiplication along with a boolean + /// indicating whether an arithmetic overflow would occur. If an + /// overflow would have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// Please note that this example is shared between integer types. + /// Which explains why `u32` is used here. + /// + /// ``` + /// assert_eq!(5u32.overflowing_mul(2), (10, false)); + /// assert_eq!(1_000_000_000u32.overflowing_mul(10), (1410065408, true)); + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT); + (a as Self, b) + } + + /// Calculates the divisor when `self` is divided by `rhs`. + /// + /// Returns a tuple of the divisor along with a boolean indicating + /// whether an arithmetic overflow would occur. Note that for unsigned + /// integers overflow never occurs, so the second value is always + /// `false`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));")] + /// ``` + #[inline(always)] + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_overflowing_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[track_caller] + pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { + (self / rhs, false) + } + + /// Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. + /// + /// Returns a tuple of the divisor along with a boolean indicating + /// whether an arithmetic overflow would occur. Note that for unsigned + /// integers overflow never occurs, so the second value is always + /// `false`. + /// Since, for the positive integers, all common + /// definitions of division are equal, this + /// is exactly equal to `self.overflowing_div(rhs)`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));")] + /// ``` + #[inline(always)] + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[track_caller] + pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { + (self / rhs, false) + } + + /// Calculates the remainder when `self` is divided by `rhs`. + /// + /// Returns a tuple of the remainder after dividing along with a boolean + /// indicating whether an arithmetic overflow would occur. Note that for + /// unsigned integers overflow never occurs, so the second value is + /// always `false`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));")] + /// ``` + #[inline(always)] + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_overflowing_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[track_caller] + pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { + (self % rhs, false) + } + + /// Calculates the remainder `self.rem_euclid(rhs)` as if by Euclidean division. + /// + /// Returns a tuple of the modulo after dividing along with a boolean + /// indicating whether an arithmetic overflow would occur. Note that for + /// unsigned integers overflow never occurs, so the second value is + /// always `false`. + /// Since, for the positive integers, all common + /// definitions of division are equal, this operation + /// is exactly equal to `self.overflowing_rem(rhs)`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));")] + /// ``` + #[inline(always)] + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[track_caller] + pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { + (self % rhs, false) + } + + /// Negates self in an overflowing fashion. + /// + /// Returns `!self + 1` using wrapping operations to return the value + /// that represents the negation of this unsigned value. Note that for + /// positive unsigned values overflow always occurs, but negating 0 does + /// not overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".overflowing_neg(), (0, false));")] + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2i32 as ", stringify!($SelfT), ", true));")] + /// ``` + #[inline(always)] + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn overflowing_neg(self) -> (Self, bool) { + ((!self).wrapping_add(1), self != 0) + } + + /// Shifts self left by `rhs` bits. + /// + /// Returns a tuple of the shifted version of self along with a boolean + /// indicating whether the shift value was larger than or equal to the + /// number of bits. If the shift value is too large, then value is + /// masked (N-1) where N is the number of bits, and this value is then + /// used to perform the shift. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(4), (0x10, false));")] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(132), (0x10, true));")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".overflowing_shl(", stringify!($BITS_MINUS_ONE), "), (0, false));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), rhs >= Self::BITS) + } + + /// Shifts self right by `rhs` bits. + /// + /// Returns a tuple of the shifted version of self along with a boolean + /// indicating whether the shift value was larger than or equal to the + /// number of bits. If the shift value is too large, then value is + /// masked (N-1) where N is the number of bits, and this value is then + /// used to perform the shift. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(4), (0x1, false));")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));")] + /// ``` + #[stable(feature = "wrapping", since = "1.7.0")] + #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), rhs >= Self::BITS) + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// Returns a tuple of the exponentiation along with a bool indicating + /// whether an overflow happened. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".overflowing_pow(5), (243, false));")] + /// assert_eq!(3u8.overflowing_pow(6), (217, true)); + /// ``` + #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { + if exp == 0{ + return (1,false); + } + let mut base = self; + let mut acc: Self = 1; + let mut overflown = false; + // Scratch space for storing results of overflowing_mul. + let mut r; + + loop { + if (exp & 1) == 1 { + r = acc.overflowing_mul(base); + // since exp!=0, finally the exp must be 1. + if exp == 1 { + r.1 |= overflown; + return r; + } + acc = r.0; + overflown |= r.1; + } + exp /= 2; + r = base.overflowing_mul(base); + base = r.0; + overflown |= r.1; + } + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".pow(5), 32);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc = 1; + + if intrinsics::is_val_statically_known(exp) { + while exp > 1 { + if (exp & 1) == 1 { + acc = acc * base; + } + exp /= 2; + base = base * base; + } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc * base + } else { + // This is faster than the above when the exponent is not known + // at compile time. We can't use the same code for the constant + // exponent case because LLVM is currently unable to unroll + // this loop. + loop { + if (exp & 1) == 1 { + acc = acc * base; + // since exp!=0, finally the exp must be 1. + if exp == 1 { + return acc; + } + } + exp /= 2; + base = base * base; + } + } + } + + /// Returns the square root of the number, rounded down. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".isqrt(), 3);")] + /// ``` + #[stable(feature = "isqrt", since = "1.84.0")] + #[rustc_const_stable(feature = "isqrt", since = "1.84.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn isqrt(self) -> Self { + let result = crate::num::int_sqrt::$ActualT(self as $ActualT) as $SelfT; + + // Inform the optimizer what the range of outputs is. If testing + // `core` crashes with no panic message and a `num::int_sqrt::u*` + // test failed, it's because your edits caused these assertions or + // the assertions in `fn isqrt` of `nonzero.rs` to become false. + // + // SAFETY: Integer square root is a monotonically nondecreasing + // function, which means that increasing the input will never + // cause the output to decrease. Thus, since the input for unsigned + // integers is bounded by `[0, <$ActualT>::MAX]`, sqrt(n) will be + // bounded by `[sqrt(0), sqrt(<$ActualT>::MAX)]`. + unsafe { + const MAX_RESULT: $SelfT = crate::num::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT; + crate::hint::assert_unchecked(result <= MAX_RESULT); + } + + result + } + + /// Performs Euclidean division. + /// + /// Since, for the positive integers, all common + /// definitions of division are equal, this + /// is exactly equal to `self / rhs`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer type")] + /// ``` + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn div_euclid(self, rhs: Self) -> Self { + self / rhs + } + + + /// Calculates the least remainder of `self (mod rhs)`. + /// + /// Since, for the positive integers, all common + /// definitions of division are equal, this + /// is exactly equal to `self % rhs`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type")] + /// ``` + #[doc(alias = "modulo", alias = "mod")] + #[stable(feature = "euclidean_division", since = "1.38.0")] + #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn rem_euclid(self, rhs: Self) -> Self { + self % rhs + } + + /// Calculates the quotient of `self` and `rhs`, rounding the result towards negative infinity. + /// + /// This is the same as performing `self / rhs` for all unsigned integers. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(int_roundings)] + #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_floor(4), 1);")] + /// ``` + #[unstable(feature = "int_roundings", issue = "88581")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn div_floor(self, rhs: Self) -> Self { + self / rhs + } + + /// Calculates the quotient of `self` and `rhs`, rounding the result towards positive infinity. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_ceil(4), 2);")] + /// ``` + #[stable(feature = "int_roundings1", since = "1.73.0")] + #[rustc_const_stable(feature = "int_roundings1", since = "1.73.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn div_ceil(self, rhs: Self) -> Self { + let d = self / rhs; + let r = self % rhs; + if r > 0 { + d + 1 + } else { + d + } + } + + /// Calculates the smallest value greater than or equal to `self` that + /// is a multiple of `rhs`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// On overflow, this function will panic if overflow checks are enabled (default in debug + /// mode) and wrap if overflow checks are disabled (default in release mode). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")] + #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")] + /// ``` + #[stable(feature = "int_roundings1", since = "1.73.0")] + #[rustc_const_stable(feature = "int_roundings1", since = "1.73.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn next_multiple_of(self, rhs: Self) -> Self { + match self % rhs { + 0 => self, + r => self + (rhs - r) + } + } + + /// Calculates the smallest value greater than or equal to `self` that + /// is a multiple of `rhs`. Returns `None` if `rhs` is zero or the + /// operation would result in overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(16));")] + #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(24));")] + #[doc = concat!("assert_eq!(1_", stringify!($SelfT), ".checked_next_multiple_of(0), None);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_next_multiple_of(2), None);")] + /// ``` + #[stable(feature = "int_roundings1", since = "1.73.0")] + #[rustc_const_stable(feature = "int_roundings1", since = "1.73.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_next_multiple_of(self, rhs: Self) -> Option { + match try_opt!(self.checked_rem(rhs)) { + 0 => Some(self), + // rhs - r cannot overflow because r is smaller than rhs + r => self.checked_add(rhs - r) + } + } + + /// Returns `true` if `self` is an integer multiple of `rhs`, and false otherwise. + /// + /// This function is equivalent to `self % rhs == 0`, except that it will not panic + /// for `rhs == 0`. Instead, `0.is_multiple_of(0) == true`, and for any non-zero `n`, + /// `n.is_multiple_of(0) == false`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(unsigned_is_multiple_of)] + #[doc = concat!("assert!(6_", stringify!($SelfT), ".is_multiple_of(2));")] + #[doc = concat!("assert!(!5_", stringify!($SelfT), ".is_multiple_of(2));")] + /// + #[doc = concat!("assert!(0_", stringify!($SelfT), ".is_multiple_of(0));")] + #[doc = concat!("assert!(!6_", stringify!($SelfT), ".is_multiple_of(0));")] + /// ``` + #[unstable(feature = "unsigned_is_multiple_of", issue = "128101")] + #[must_use] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn is_multiple_of(self, rhs: Self) -> bool { + match rhs { + 0 => self == 0, + _ => self % rhs == 0, + } + } + + /// Returns `true` if and only if `self == 2^k` for some `k`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert!(16", stringify!($SelfT), ".is_power_of_two());")] + #[doc = concat!("assert!(!10", stringify!($SelfT), ".is_power_of_two());")] + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_is_power_of_two", since = "1.32.0")] + #[inline(always)] + pub const fn is_power_of_two(self) -> bool { + self.count_ones() == 1 + } + + // Returns one less than next power of two. + // (For 8u8 next power of two is 8u8 and for 6u8 it is 8u8) + // + // 8u8.one_less_than_next_power_of_two() == 7 + // 6u8.one_less_than_next_power_of_two() == 7 + // + // This method cannot overflow, as in the `next_power_of_two` + // overflow cases it instead ends up returning the maximum value + // of the type, and can return 0 for 0. + #[inline] + const fn one_less_than_next_power_of_two(self) -> Self { + if self <= 1 { return 0; } + + 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 z = unsafe { intrinsics::ctlz_nonzero(p) }; + <$SelfT>::MAX >> z + } + + /// Returns the smallest power of two greater than or equal to `self`. + /// + /// When return value overflows (i.e., `self > (1 << (N-1))` for type + /// `uN`), it panics in debug mode and the return value is wrapped to 0 in + /// release mode (the only situation in which this method can return 0). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".next_power_of_two(), 2);")] + #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);")] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".next_power_of_two(), 1);")] + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn next_power_of_two(self) -> Self { + self.one_less_than_next_power_of_two() + 1 + } + + /// Returns the smallest power of two greater than or equal to `self`. If + /// the next power of two is greater than the type's maximum value, + /// `None` is returned, otherwise the power of two is wrapped in `Some`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_next_power_of_two(), Some(2));")] + #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".checked_next_power_of_two(), Some(4));")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_next_power_of_two(), None);")] + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn checked_next_power_of_two(self) -> Option { + self.one_less_than_next_power_of_two().checked_add(1) + } + + /// Returns the smallest power of two greater than or equal to `n`. If + /// the next power of two is greater than the type's maximum value, + /// the return value is wrapped to `0`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_next_power_of_two)] + /// + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".wrapping_next_power_of_two(), 2);")] + #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".wrapping_next_power_of_two(), 4);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_next_power_of_two(), 0);")] + /// ``` + #[inline] + #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", + reason = "needs decision on wrapping behavior")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub const fn wrapping_next_power_of_two(self) -> Self { + self.one_less_than_next_power_of_two().wrapping_add(1) + } + + /// Returns the memory representation of this integer as a byte array in + /// big-endian (network) byte order. + /// + #[doc = $to_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes();")] + #[doc = concat!("assert_eq!(bytes, ", $be_bytes, ");")] + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { + self.to_be().to_ne_bytes() + } + + /// Returns the memory representation of this integer as a byte array in + /// little-endian byte order. + /// + #[doc = $to_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes();")] + #[doc = concat!("assert_eq!(bytes, ", $le_bytes, ");")] + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { + self.to_le().to_ne_bytes() + } + + /// Returns the memory representation of this integer as a byte array in + /// native byte order. + /// + /// As the target platform's native endianness is used, portable code + /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, + /// instead. + /// + #[doc = $to_xe_bytes_doc] + /// + /// [`to_be_bytes`]: Self::to_be_bytes + /// [`to_le_bytes`]: Self::to_le_bytes + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes();")] + /// assert_eq!( + /// bytes, + /// if cfg!(target_endian = "big") { + #[doc = concat!(" ", $be_bytes)] + /// } else { + #[doc = concat!(" ", $le_bytes)] + /// } + /// ); + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + // SAFETY: const sound because integers are plain old datatypes so we can always + // transmute them to arrays of bytes + #[inline] + pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { + // SAFETY: integers are plain old datatypes so we can always transmute them to + // arrays of bytes + unsafe { mem::transmute(self) } + } + + /// Creates a native endian integer value from its representation + /// as a byte array in big endian. + /// + #[doc = $from_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, ");")] + #[doc = concat!("assert_eq!(value, ", $swap_op, ");")] + /// ``` + /// + /// When starting from a slice rather than an array, fallible conversion APIs can be used: + /// + /// ``` + #[doc = concat!("fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")] + #[doc = concat!(" let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")] + /// *input = rest; + #[doc = concat!(" ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())")] + /// } + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use] + #[inline] + pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_be(Self::from_ne_bytes(bytes)) + } + + /// Creates a native endian integer value from its representation + /// as a byte array in little endian. + /// + #[doc = $from_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, ");")] + #[doc = concat!("assert_eq!(value, ", $swap_op, ");")] + /// ``` + /// + /// When starting from a slice rather than an array, fallible conversion APIs can be used: + /// + /// ``` + #[doc = concat!("fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")] + #[doc = concat!(" let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")] + /// *input = rest; + #[doc = concat!(" ", stringify!($SelfT), "::from_le_bytes(int_bytes.try_into().unwrap())")] + /// } + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use] + #[inline] + pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_le(Self::from_ne_bytes(bytes)) + } + + /// Creates a native endian integer value from its memory representation + /// as a byte array in native endianness. + /// + /// As the target platform's native endianness is used, portable code + /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as + /// appropriate instead. + /// + /// [`from_be_bytes`]: Self::from_be_bytes + /// [`from_le_bytes`]: Self::from_le_bytes + /// + #[doc = $from_xe_bytes_doc] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") {")] + #[doc = concat!(" ", $be_bytes, "")] + /// } else { + #[doc = concat!(" ", $le_bytes, "")] + /// }); + #[doc = concat!("assert_eq!(value, ", $swap_op, ");")] + /// ``` + /// + /// When starting from a slice rather than an array, fallible conversion APIs can be used: + /// + /// ``` + #[doc = concat!("fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {")] + #[doc = concat!(" let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());")] + /// *input = rest; + #[doc = concat!(" ", stringify!($SelfT), "::from_ne_bytes(int_bytes.try_into().unwrap())")] + /// } + /// ``` + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use] + // SAFETY: const sound because integers are plain old datatypes so we can always + // transmute to them + #[inline] + pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { + // SAFETY: integers are plain old datatypes so we can always transmute to them + unsafe { mem::transmute(bytes) } + } + + /// New code should prefer to use + #[doc = concat!("[`", stringify!($SelfT), "::MIN", "`] instead.")] + /// + /// Returns the smallest value that can be represented by this integer type. + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_promotable] + #[inline(always)] + #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] + #[deprecated(since = "TBD", note = "replaced by the `MIN` associated constant on this type")] + #[rustc_diagnostic_item = concat!(stringify!($SelfT), "_legacy_fn_min_value")] + pub const fn min_value() -> Self { Self::MIN } + + /// New code should prefer to use + #[doc = concat!("[`", stringify!($SelfT), "::MAX", "`] instead.")] + /// + /// Returns the largest value that can be represented by this integer type. + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_promotable] + #[inline(always)] + #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] + #[deprecated(since = "TBD", note = "replaced by the `MAX` associated constant on this type")] + #[rustc_diagnostic_item = concat!(stringify!($SelfT), "_legacy_fn_max_value")] + pub const fn max_value() -> Self { Self::MAX } + } +} diff --git a/CoqOfRust/core/num/wrapping.rs b/CoqOfRust/core/num/wrapping.rs new file mode 100644 index 000000000..1156b389e --- /dev/null +++ b/CoqOfRust/core/num/wrapping.rs @@ -0,0 +1,1090 @@ +//! Definitions of `Wrapping`. + +use crate::fmt; +use crate::ops::{ + Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, + Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign, +}; + +/// Provides intentionally-wrapped arithmetic on `T`. +/// +/// Operations like `+` on `u32` values are intended to never overflow, +/// and in some debug configurations overflow is detected and results +/// in a panic. While most arithmetic falls into this category, some +/// code explicitly expects and relies upon modular arithmetic (e.g., +/// hashing). +/// +/// Wrapping arithmetic can be achieved either through methods like +/// `wrapping_add`, or through the `Wrapping` type, which says that +/// all standard arithmetic operations on the underlying value are +/// intended to have wrapping semantics. +/// +/// The underlying value can be retrieved through the `.0` index of the +/// `Wrapping` tuple. +/// +/// # Examples +/// +/// ``` +/// use std::num::Wrapping; +/// +/// let zero = Wrapping(0u32); +/// let one = Wrapping(1u32); +/// +/// assert_eq!(u32::MAX, (zero - one).0); +/// ``` +/// +/// # Layout +/// +/// `Wrapping` is guaranteed to have the same layout and ABI as `T`. +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)] +#[repr(transparent)] +#[rustc_diagnostic_item = "Wrapping"] +pub struct Wrapping(#[stable(feature = "rust1", since = "1.0.0")] pub T); + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Wrapping { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +#[stable(feature = "wrapping_display", since = "1.10.0")] +impl fmt::Display for Wrapping { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +#[stable(feature = "wrapping_fmt", since = "1.11.0")] +impl fmt::Binary for Wrapping { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +#[stable(feature = "wrapping_fmt", since = "1.11.0")] +impl fmt::Octal for Wrapping { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +#[stable(feature = "wrapping_fmt", since = "1.11.0")] +impl fmt::LowerHex for Wrapping { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +#[stable(feature = "wrapping_fmt", since = "1.11.0")] +impl fmt::UpperHex for Wrapping { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +#[allow(unused_macros)] +macro_rules! sh_impl_signed { + ($t:ident, $f:ident) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl Shl<$f> for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline] + fn shl(self, other: $f) -> Wrapping<$t> { + if other < 0 { + Wrapping(self.0.wrapping_shr((-other & self::shift_max::$t as $f) as u32)) + } else { + Wrapping(self.0.wrapping_shl((other & self::shift_max::$t as $f) as u32)) + } + } + } + forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } + + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl ShlAssign<$f> for Wrapping<$t> { + #[inline] + fn shl_assign(&mut self, other: $f) { + *self = *self << other; + } + } + forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Shr<$f> for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline] + fn shr(self, other: $f) -> Wrapping<$t> { + if other < 0 { + Wrapping(self.0.wrapping_shl((-other & self::shift_max::$t as $f) as u32)) + } else { + Wrapping(self.0.wrapping_shr((other & self::shift_max::$t as $f) as u32)) + } + } + } + forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } + + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl ShrAssign<$f> for Wrapping<$t> { + #[inline] + fn shr_assign(&mut self, other: $f) { + *self = *self >> other; + } + } + forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f } + }; +} + +macro_rules! sh_impl_unsigned { + ($t:ident, $f:ident) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl Shl<$f> for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline] + fn shl(self, other: $f) -> Wrapping<$t> { + Wrapping(self.0.wrapping_shl((other & self::shift_max::$t as $f) as u32)) + } + } + forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } + + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl ShlAssign<$f> for Wrapping<$t> { + #[inline] + fn shl_assign(&mut self, other: $f) { + *self = *self << other; + } + } + forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Shr<$f> for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline] + fn shr(self, other: $f) -> Wrapping<$t> { + Wrapping(self.0.wrapping_shr((other & self::shift_max::$t as $f) as u32)) + } + } + forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } + + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl ShrAssign<$f> for Wrapping<$t> { + #[inline] + fn shr_assign(&mut self, other: $f) { + *self = *self >> other; + } + } + forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f } + }; +} + +// FIXME (#23545): uncomment the remaining impls +macro_rules! sh_impl_all { + ($($t:ident)*) => ($( + //sh_impl_unsigned! { $t, u8 } + //sh_impl_unsigned! { $t, u16 } + //sh_impl_unsigned! { $t, u32 } + //sh_impl_unsigned! { $t, u64 } + //sh_impl_unsigned! { $t, u128 } + sh_impl_unsigned! { $t, usize } + + //sh_impl_signed! { $t, i8 } + //sh_impl_signed! { $t, i16 } + //sh_impl_signed! { $t, i32 } + //sh_impl_signed! { $t, i64 } + //sh_impl_signed! { $t, i128 } + //sh_impl_signed! { $t, isize } + )*) +} + +sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } + +// FIXME(30524): impl Op for Wrapping, impl OpAssign for Wrapping +macro_rules! wrapping_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Add for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline] + fn add(self, other: Wrapping<$t>) -> Wrapping<$t> { + Wrapping(self.0.wrapping_add(other.0)) + } + } + forward_ref_binop! { impl Add, add for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } + + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl AddAssign for Wrapping<$t> { + #[inline] + fn add_assign(&mut self, other: Wrapping<$t>) { + *self = *self + other; + } + } + forward_ref_op_assign! { impl AddAssign, add_assign for Wrapping<$t>, Wrapping<$t> } + + #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] + impl AddAssign<$t> for Wrapping<$t> { + #[inline] + fn add_assign(&mut self, other: $t) { + *self = *self + Wrapping(other); + } + } + forward_ref_op_assign! { impl AddAssign, add_assign for Wrapping<$t>, $t } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Sub for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline] + fn sub(self, other: Wrapping<$t>) -> Wrapping<$t> { + Wrapping(self.0.wrapping_sub(other.0)) + } + } + forward_ref_binop! { impl Sub, sub for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } + + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl SubAssign for Wrapping<$t> { + #[inline] + fn sub_assign(&mut self, other: Wrapping<$t>) { + *self = *self - other; + } + } + forward_ref_op_assign! { impl SubAssign, sub_assign for Wrapping<$t>, Wrapping<$t> } + + #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] + impl SubAssign<$t> for Wrapping<$t> { + #[inline] + fn sub_assign(&mut self, other: $t) { + *self = *self - Wrapping(other); + } + } + forward_ref_op_assign! { impl SubAssign, sub_assign for Wrapping<$t>, $t } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Mul for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline] + fn mul(self, other: Wrapping<$t>) -> Wrapping<$t> { + Wrapping(self.0.wrapping_mul(other.0)) + } + } + forward_ref_binop! { impl Mul, mul for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } + + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl MulAssign for Wrapping<$t> { + #[inline] + fn mul_assign(&mut self, other: Wrapping<$t>) { + *self = *self * other; + } + } + forward_ref_op_assign! { impl MulAssign, mul_assign for Wrapping<$t>, Wrapping<$t> } + + #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] + impl MulAssign<$t> for Wrapping<$t> { + #[inline] + fn mul_assign(&mut self, other: $t) { + *self = *self * Wrapping(other); + } + } + forward_ref_op_assign! { impl MulAssign, mul_assign for Wrapping<$t>, $t } + + #[stable(feature = "wrapping_div", since = "1.3.0")] + impl Div for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline] + fn div(self, other: Wrapping<$t>) -> Wrapping<$t> { + Wrapping(self.0.wrapping_div(other.0)) + } + } + forward_ref_binop! { impl Div, div for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } + + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl DivAssign for Wrapping<$t> { + #[inline] + fn div_assign(&mut self, other: Wrapping<$t>) { + *self = *self / other; + } + } + forward_ref_op_assign! { impl DivAssign, div_assign for Wrapping<$t>, Wrapping<$t> } + + #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] + impl DivAssign<$t> for Wrapping<$t> { + #[inline] + fn div_assign(&mut self, other: $t) { + *self = *self / Wrapping(other); + } + } + forward_ref_op_assign! { impl DivAssign, div_assign for Wrapping<$t>, $t } + + #[stable(feature = "wrapping_impls", since = "1.7.0")] + impl Rem for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline] + fn rem(self, other: Wrapping<$t>) -> Wrapping<$t> { + Wrapping(self.0.wrapping_rem(other.0)) + } + } + forward_ref_binop! { impl Rem, rem for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } + + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl RemAssign for Wrapping<$t> { + #[inline] + fn rem_assign(&mut self, other: Wrapping<$t>) { + *self = *self % other; + } + } + forward_ref_op_assign! { impl RemAssign, rem_assign for Wrapping<$t>, Wrapping<$t> } + + #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] + impl RemAssign<$t> for Wrapping<$t> { + #[inline] + fn rem_assign(&mut self, other: $t) { + *self = *self % Wrapping(other); + } + } + forward_ref_op_assign! { impl RemAssign, rem_assign for Wrapping<$t>, $t } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Not for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline] + fn not(self) -> Wrapping<$t> { + Wrapping(!self.0) + } + } + forward_ref_unop! { impl Not, not for Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } + + #[stable(feature = "rust1", since = "1.0.0")] + impl BitXor for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline] + fn bitxor(self, other: Wrapping<$t>) -> Wrapping<$t> { + Wrapping(self.0 ^ other.0) + } + } + forward_ref_binop! { impl BitXor, bitxor for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } + + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl BitXorAssign for Wrapping<$t> { + #[inline] + fn bitxor_assign(&mut self, other: Wrapping<$t>) { + *self = *self ^ other; + } + } + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Wrapping<$t>, Wrapping<$t> } + + #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] + impl BitXorAssign<$t> for Wrapping<$t> { + #[inline] + fn bitxor_assign(&mut self, other: $t) { + *self = *self ^ Wrapping(other); + } + } + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Wrapping<$t>, $t } + + #[stable(feature = "rust1", since = "1.0.0")] + impl BitOr for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline] + fn bitor(self, other: Wrapping<$t>) -> Wrapping<$t> { + Wrapping(self.0 | other.0) + } + } + forward_ref_binop! { impl BitOr, bitor for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } + + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl BitOrAssign for Wrapping<$t> { + #[inline] + fn bitor_assign(&mut self, other: Wrapping<$t>) { + *self = *self | other; + } + } + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Wrapping<$t>, Wrapping<$t> } + + #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] + impl BitOrAssign<$t> for Wrapping<$t> { + #[inline] + fn bitor_assign(&mut self, other: $t) { + *self = *self | Wrapping(other); + } + } + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Wrapping<$t>, $t } + + #[stable(feature = "rust1", since = "1.0.0")] + impl BitAnd for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline] + fn bitand(self, other: Wrapping<$t>) -> Wrapping<$t> { + Wrapping(self.0 & other.0) + } + } + forward_ref_binop! { impl BitAnd, bitand for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } + + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl BitAndAssign for Wrapping<$t> { + #[inline] + fn bitand_assign(&mut self, other: Wrapping<$t>) { + *self = *self & other; + } + } + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Wrapping<$t>, Wrapping<$t> } + + #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] + impl BitAndAssign<$t> for Wrapping<$t> { + #[inline] + fn bitand_assign(&mut self, other: $t) { + *self = *self & Wrapping(other); + } + } + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Wrapping<$t>, $t } + + #[stable(feature = "wrapping_neg", since = "1.10.0")] + impl Neg for Wrapping<$t> { + type Output = Self; + #[inline] + fn neg(self) -> Self { + Wrapping(0) - self + } + } + forward_ref_unop! { impl Neg, neg for Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } + + )*) +} + +wrapping_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +macro_rules! wrapping_int_impl { + ($($t:ty)*) => ($( + impl Wrapping<$t> { + /// Returns the smallest value that can be represented by this integer type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(>::MIN, Wrapping(", stringify!($t), "::MIN));")] + /// ``` + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const MIN: Self = Self(<$t>::MIN); + + /// Returns the largest value that can be represented by this integer type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(>::MAX, Wrapping(", stringify!($t), "::MAX));")] + /// ``` + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const MAX: Self = Self(<$t>::MAX); + + /// Returns the size of this integer type in bits. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(>::BITS, ", stringify!($t), "::BITS);")] + /// ``` + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const BITS: u32 = <$t>::BITS; + + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(0b01001100", stringify!($t), ");")] + /// + /// assert_eq!(n.count_ones(), 3); + /// ``` + #[inline] + #[doc(alias = "popcount")] + #[doc(alias = "popcnt")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn count_ones(self) -> u32 { + self.0.count_ones() + } + + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(Wrapping(!0", stringify!($t), ").count_zeros(), 0);")] + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn count_zeros(self) -> u32 { + self.0.count_zeros() + } + + /// Returns the number of trailing zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(0b0101000", stringify!($t), ");")] + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn trailing_zeros(self) -> u32 { + self.0.trailing_zeros() + } + + /// Shifts the bits to the left by a specified amount, `n`, + /// wrapping the truncated bits to the end of the resulting + /// integer. + /// + /// Please note this isn't the same operation as the `<<` shifting + /// operator! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// let m: Wrapping = Wrapping(-0x76543210FEDCBA99); + /// + /// assert_eq!(n.rotate_left(32), m); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn rotate_left(self, n: u32) -> Self { + Wrapping(self.0.rotate_left(n)) + } + + /// Shifts the bits to the right by a specified amount, `n`, + /// wrapping the truncated bits to the beginning of the resulting + /// integer. + /// + /// Please note this isn't the same operation as the `>>` shifting + /// operator! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// let m: Wrapping = Wrapping(-0xFEDCBA987654322); + /// + /// assert_eq!(n.rotate_right(4), m); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn rotate_right(self, n: u32) -> Self { + Wrapping(self.0.rotate_right(n)) + } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0b0000000_01010101); + /// assert_eq!(n, Wrapping(85)); + /// + /// let m = n.swap_bytes(); + /// + /// assert_eq!(m, Wrapping(0b01010101_00000000)); + /// assert_eq!(m, Wrapping(21760)); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn swap_bytes(self) -> Self { + Wrapping(self.0.swap_bytes()) + } + + /// Reverses the bit pattern of the integer. + /// + /// # Examples + /// + /// Please note that this example is shared between integer types. + /// Which explains why `i16` is used here. + /// + /// Basic usage: + /// + /// ``` + /// use std::num::Wrapping; + /// + /// let n = Wrapping(0b0000000_01010101i16); + /// assert_eq!(n, Wrapping(85)); + /// + /// let m = n.reverse_bits(); + /// + /// assert_eq!(m.0 as u16, 0b10101010_00000000); + /// assert_eq!(m, Wrapping(-22016)); + /// ``` + #[stable(feature = "reverse_bits", since = "1.37.0")] + #[rustc_const_stable(feature = "const_reverse_bits", since = "1.37.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn reverse_bits(self) -> Self { + Wrapping(self.0.reverse_bits()) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(0x1A", stringify!($t), ");")] + /// + /// if cfg!(target_endian = "big") { + #[doc = concat!(" assert_eq!(>::from_be(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(>::from_be(n), n.swap_bytes())")] + /// } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn from_be(x: Self) -> Self { + Wrapping(<$t>::from_be(x.0)) + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(0x1A", stringify!($t), ");")] + /// + /// if cfg!(target_endian = "little") { + #[doc = concat!(" assert_eq!(>::from_le(n), n)")] + /// } else { + #[doc = concat!(" assert_eq!(>::from_le(n), n.swap_bytes())")] + /// } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn from_le(x: Self) -> Self { + Wrapping(<$t>::from_le(x.0)) + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(0x1A", stringify!($t), ");")] + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn to_be(self) -> Self { + Wrapping(self.0.to_be()) + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(0x1A", stringify!($t), ");")] + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn to_le(self) -> Self { + Wrapping(self.0.to_le()) + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(Wrapping(3", stringify!($t), ").pow(4), Wrapping(81));")] + /// ``` + /// + /// Results that are too large are wrapped: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// assert_eq!(Wrapping(3i8).pow(5), Wrapping(-13)); + /// assert_eq!(Wrapping(3i8).pow(6), Wrapping(-39)); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn pow(self, exp: u32) -> Self { + Wrapping(self.0.wrapping_pow(exp)) + } + } + )*) +} + +wrapping_int_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +macro_rules! wrapping_int_impl_signed { + ($($t:ty)*) => ($( + impl Wrapping<$t> { + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(", stringify!($t), "::MAX) >> 2;")] + /// + /// assert_eq!(n.leading_zeros(), 3); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn leading_zeros(self) -> u32 { + self.0.leading_zeros() + } + + /// Computes the absolute value of `self`, wrapping around at + /// the boundary of the type. + /// + /// The only case where such wrapping can occur is when one takes the absolute value of the negative + /// minimal value for the type this is a positive value that is too large to represent in the type. In + /// such a case, this function returns `MIN` itself. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(Wrapping(100", stringify!($t), ").abs(), Wrapping(100));")] + #[doc = concat!("assert_eq!(Wrapping(-100", stringify!($t), ").abs(), Wrapping(100));")] + #[doc = concat!("assert_eq!(Wrapping(", stringify!($t), "::MIN).abs(), Wrapping(", stringify!($t), "::MIN));")] + /// assert_eq!(Wrapping(-128i8).abs().0 as u8, 128u8); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn abs(self) -> Wrapping<$t> { + Wrapping(self.0.wrapping_abs()) + } + + /// Returns a number representing sign of `self`. + /// + /// - `0` if the number is zero + /// - `1` if the number is positive + /// - `-1` if the number is negative + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(Wrapping(10", stringify!($t), ").signum(), Wrapping(1));")] + #[doc = concat!("assert_eq!(Wrapping(0", stringify!($t), ").signum(), Wrapping(0));")] + #[doc = concat!("assert_eq!(Wrapping(-10", stringify!($t), ").signum(), Wrapping(-1));")] + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn signum(self) -> Wrapping<$t> { + Wrapping(self.0.signum()) + } + + /// Returns `true` if `self` is positive and `false` if the number is zero or + /// negative. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert!(Wrapping(10", stringify!($t), ").is_positive());")] + #[doc = concat!("assert!(!Wrapping(-10", stringify!($t), ").is_positive());")] + /// ``` + #[must_use] + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn is_positive(self) -> bool { + self.0.is_positive() + } + + /// Returns `true` if `self` is negative and `false` if the number is zero or + /// positive. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert!(Wrapping(-10", stringify!($t), ").is_negative());")] + #[doc = concat!("assert!(!Wrapping(10", stringify!($t), ").is_negative());")] + /// ``` + #[must_use] + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn is_negative(self) -> bool { + self.0.is_negative() + } + } + )*) +} + +wrapping_int_impl_signed! { isize i8 i16 i32 i64 i128 } + +macro_rules! wrapping_int_impl_unsigned { + ($($t:ty)*) => ($( + impl Wrapping<$t> { + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("let n = Wrapping(", stringify!($t), "::MAX) >> 2;")] + /// + /// assert_eq!(n.leading_zeros(), 2); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub const fn leading_zeros(self) -> u32 { + self.0.leading_zeros() + } + + /// Returns `true` if and only if `self == 2^k` for some `k`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert!(Wrapping(16", stringify!($t), ").is_power_of_two());")] + #[doc = concat!("assert!(!Wrapping(10", stringify!($t), ").is_power_of_two());")] + /// ``` + #[must_use] + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn is_power_of_two(self) -> bool { + self.0.is_power_of_two() + } + + /// Returns the smallest power of two greater than or equal to `self`. + /// + /// When return value overflows (i.e., `self > (1 << (N-1))` for type + /// `uN`), overflows to `2^N = 0`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_next_power_of_two)] + /// use std::num::Wrapping; + /// + #[doc = concat!("assert_eq!(Wrapping(2", stringify!($t), ").next_power_of_two(), Wrapping(2));")] + #[doc = concat!("assert_eq!(Wrapping(3", stringify!($t), ").next_power_of_two(), Wrapping(4));")] + #[doc = concat!("assert_eq!(Wrapping(200_u8).next_power_of_two(), Wrapping(0));")] + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", + reason = "needs decision on wrapping behavior")] + pub fn next_power_of_two(self) -> Self { + Wrapping(self.0.wrapping_next_power_of_two()) + } + } + )*) +} + +wrapping_int_impl_unsigned! { usize u8 u16 u32 u64 u128 } + +mod shift_max { + #![allow(non_upper_case_globals)] + + #[cfg(target_pointer_width = "16")] + mod platform { + pub const usize: u32 = super::u16; + pub const isize: u32 = super::i16; + } + + #[cfg(target_pointer_width = "32")] + mod platform { + pub const usize: u32 = super::u32; + pub const isize: u32 = super::i32; + } + + #[cfg(target_pointer_width = "64")] + mod platform { + pub const usize: u32 = super::u64; + pub const isize: u32 = super::i64; + } + + pub const i8: u32 = (1 << 3) - 1; + pub const i16: u32 = (1 << 4) - 1; + pub const i32: u32 = (1 << 5) - 1; + pub const i64: u32 = (1 << 6) - 1; + pub const i128: u32 = (1 << 7) - 1; + pub use self::platform::isize; + + pub const u8: u32 = i8; + pub const u16: u32 = i16; + pub const u32: u32 = i32; + pub const u64: u32 = i64; + pub const u128: u32 = i128; + pub use self::platform::usize; +} diff --git a/CoqOfRust/core/ops/arith.rs b/CoqOfRust/core/ops/arith.rs new file mode 100644 index 000000000..565bccf58 --- /dev/null +++ b/CoqOfRust/core/ops/arith.rs @@ -0,0 +1,1022 @@ +/// The addition operator `+`. +/// +/// Note that `Rhs` is `Self` by default, but this is not mandatory. For +/// example, [`std::time::SystemTime`] implements `Add`, which permits +/// operations of the form `SystemTime = SystemTime + Duration`. +/// +/// [`std::time::SystemTime`]: ../../std/time/struct.SystemTime.html +/// +/// # Examples +/// +/// ## `Add`able points +/// +/// ``` +/// use std::ops::Add; +/// +/// #[derive(Debug, Copy, Clone, PartialEq)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl Add for Point { +/// type Output = Self; +/// +/// fn add(self, other: Self) -> Self { +/// Self { +/// x: self.x + other.x, +/// y: self.y + other.y, +/// } +/// } +/// } +/// +/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 }, +/// Point { x: 3, y: 3 }); +/// ``` +/// +/// ## Implementing `Add` with generics +/// +/// Here is an example of the same `Point` struct implementing the `Add` trait +/// using generics. +/// +/// ``` +/// use std::ops::Add; +/// +/// #[derive(Debug, Copy, Clone, PartialEq)] +/// struct Point { +/// x: T, +/// y: T, +/// } +/// +/// // Notice that the implementation uses the associated type `Output`. +/// impl> Add for Point { +/// type Output = Self; +/// +/// fn add(self, other: Self) -> Self::Output { +/// Self { +/// x: self.x + other.x, +/// y: self.y + other.y, +/// } +/// } +/// } +/// +/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 }, +/// Point { x: 3, y: 3 }); +/// ``` +#[lang = "add"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + on(all(_Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",), + on(all(_Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",), + message = "cannot add `{Rhs}` to `{Self}`", + label = "no implementation for `{Self} + {Rhs}`", + append_const_msg +)] +#[doc(alias = "+")] +#[cfg_attr(not(bootstrap), const_trait)] +pub trait Add { + /// The resulting type after applying the `+` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `+` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 + 1, 13); + /// ``` + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "add"] + #[stable(feature = "rust1", since = "1.0.0")] + fn add(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! add_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(bootstrap)] + impl Add for $t { + type Output = $t; + + #[inline] + #[track_caller] + #[rustc_inherit_overflow_checks] + fn add(self, other: $t) -> $t { self + other } + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(not(bootstrap))] + impl const Add for $t { + type Output = $t; + + #[inline] + #[track_caller] + #[rustc_inherit_overflow_checks] + fn add(self, other: $t) -> $t { self + other } + } + + forward_ref_binop! { impl Add, add for $t, $t } + )*) +} + +add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } + +/// The subtraction operator `-`. +/// +/// Note that `Rhs` is `Self` by default, but this is not mandatory. For +/// example, [`std::time::SystemTime`] implements `Sub`, which permits +/// operations of the form `SystemTime = SystemTime - Duration`. +/// +/// [`std::time::SystemTime`]: ../../std/time/struct.SystemTime.html +/// +/// # Examples +/// +/// ## `Sub`tractable points +/// +/// ``` +/// use std::ops::Sub; +/// +/// #[derive(Debug, Copy, Clone, PartialEq)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl Sub for Point { +/// type Output = Self; +/// +/// fn sub(self, other: Self) -> Self::Output { +/// Self { +/// x: self.x - other.x, +/// y: self.y - other.y, +/// } +/// } +/// } +/// +/// assert_eq!(Point { x: 3, y: 3 } - Point { x: 2, y: 3 }, +/// Point { x: 1, y: 0 }); +/// ``` +/// +/// ## Implementing `Sub` with generics +/// +/// Here is an example of the same `Point` struct implementing the `Sub` trait +/// using generics. +/// +/// ``` +/// use std::ops::Sub; +/// +/// #[derive(Debug, PartialEq)] +/// struct Point { +/// x: T, +/// y: T, +/// } +/// +/// // Notice that the implementation uses the associated type `Output`. +/// impl> Sub for Point { +/// type Output = Self; +/// +/// fn sub(self, other: Self) -> Self::Output { +/// Point { +/// x: self.x - other.x, +/// y: self.y - other.y, +/// } +/// } +/// } +/// +/// assert_eq!(Point { x: 2, y: 3 } - Point { x: 1, y: 0 }, +/// Point { x: 1, y: 3 }); +/// ``` +#[lang = "sub"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "cannot subtract `{Rhs}` from `{Self}`", + label = "no implementation for `{Self} - {Rhs}`", + append_const_msg +)] +#[doc(alias = "-")] +pub trait Sub { + /// The resulting type after applying the `-` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `-` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 - 1, 11); + /// ``` + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "sub"] + #[stable(feature = "rust1", since = "1.0.0")] + fn sub(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! sub_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Sub for $t { + type Output = $t; + + #[inline] + #[track_caller] + #[rustc_inherit_overflow_checks] + fn sub(self, other: $t) -> $t { self - other } + } + + forward_ref_binop! { impl Sub, sub for $t, $t } + )*) +} + +sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } + +/// The multiplication operator `*`. +/// +/// Note that `Rhs` is `Self` by default, but this is not mandatory. +/// +/// # Examples +/// +/// ## `Mul`tipliable rational numbers +/// +/// ``` +/// use std::ops::Mul; +/// +/// // By the fundamental theorem of arithmetic, rational numbers in lowest +/// // terms are unique. So, by keeping `Rational`s in reduced form, we can +/// // derive `Eq` and `PartialEq`. +/// #[derive(Debug, Eq, PartialEq)] +/// struct Rational { +/// numerator: usize, +/// denominator: usize, +/// } +/// +/// impl Rational { +/// fn new(numerator: usize, denominator: usize) -> Self { +/// if denominator == 0 { +/// panic!("Zero is an invalid denominator!"); +/// } +/// +/// // Reduce to lowest terms by dividing by the greatest common +/// // divisor. +/// let gcd = gcd(numerator, denominator); +/// Self { +/// numerator: numerator / gcd, +/// denominator: denominator / gcd, +/// } +/// } +/// } +/// +/// impl Mul for Rational { +/// // The multiplication of rational numbers is a closed operation. +/// type Output = Self; +/// +/// fn mul(self, rhs: Self) -> Self { +/// let numerator = self.numerator * rhs.numerator; +/// let denominator = self.denominator * rhs.denominator; +/// Self::new(numerator, denominator) +/// } +/// } +/// +/// // Euclid's two-thousand-year-old algorithm for finding the greatest common +/// // divisor. +/// fn gcd(x: usize, y: usize) -> usize { +/// let mut x = x; +/// let mut y = y; +/// while y != 0 { +/// let t = y; +/// y = x % y; +/// x = t; +/// } +/// x +/// } +/// +/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4)); +/// assert_eq!(Rational::new(2, 3) * Rational::new(3, 4), +/// Rational::new(1, 2)); +/// ``` +/// +/// ## Multiplying vectors by scalars as in linear algebra +/// +/// ``` +/// use std::ops::Mul; +/// +/// struct Scalar { value: usize } +/// +/// #[derive(Debug, PartialEq)] +/// struct Vector { value: Vec } +/// +/// impl Mul for Vector { +/// type Output = Self; +/// +/// fn mul(self, rhs: Scalar) -> Self::Output { +/// Self { value: self.value.iter().map(|v| v * rhs.value).collect() } +/// } +/// } +/// +/// let vector = Vector { value: vec![2, 4, 6] }; +/// let scalar = Scalar { value: 3 }; +/// assert_eq!(vector * scalar, Vector { value: vec![6, 12, 18] }); +/// ``` +#[lang = "mul"] +#[stable(feature = "rust1", since = "1.0.0")] +#[diagnostic::on_unimplemented( + message = "cannot multiply `{Self}` by `{Rhs}`", + label = "no implementation for `{Self} * {Rhs}`" +)] +#[doc(alias = "*")] +pub trait Mul { + /// The resulting type after applying the `*` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `*` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 * 2, 24); + /// ``` + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "mul"] + #[stable(feature = "rust1", since = "1.0.0")] + fn mul(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! mul_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Mul for $t { + type Output = $t; + + #[inline] + #[track_caller] + #[rustc_inherit_overflow_checks] + fn mul(self, other: $t) -> $t { self * other } + } + + forward_ref_binop! { impl Mul, mul for $t, $t } + )*) +} + +mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } + +/// The division operator `/`. +/// +/// Note that `Rhs` is `Self` by default, but this is not mandatory. +/// +/// # Examples +/// +/// ## `Div`idable rational numbers +/// +/// ``` +/// use std::ops::Div; +/// +/// // By the fundamental theorem of arithmetic, rational numbers in lowest +/// // terms are unique. So, by keeping `Rational`s in reduced form, we can +/// // derive `Eq` and `PartialEq`. +/// #[derive(Debug, Eq, PartialEq)] +/// struct Rational { +/// numerator: usize, +/// denominator: usize, +/// } +/// +/// impl Rational { +/// fn new(numerator: usize, denominator: usize) -> Self { +/// if denominator == 0 { +/// panic!("Zero is an invalid denominator!"); +/// } +/// +/// // Reduce to lowest terms by dividing by the greatest common +/// // divisor. +/// let gcd = gcd(numerator, denominator); +/// Self { +/// numerator: numerator / gcd, +/// denominator: denominator / gcd, +/// } +/// } +/// } +/// +/// impl Div for Rational { +/// // The division of rational numbers is a closed operation. +/// type Output = Self; +/// +/// fn div(self, rhs: Self) -> Self::Output { +/// if rhs.numerator == 0 { +/// panic!("Cannot divide by zero-valued `Rational`!"); +/// } +/// +/// let numerator = self.numerator * rhs.denominator; +/// let denominator = self.denominator * rhs.numerator; +/// Self::new(numerator, denominator) +/// } +/// } +/// +/// // Euclid's two-thousand-year-old algorithm for finding the greatest common +/// // divisor. +/// fn gcd(x: usize, y: usize) -> usize { +/// let mut x = x; +/// let mut y = y; +/// while y != 0 { +/// let t = y; +/// y = x % y; +/// x = t; +/// } +/// x +/// } +/// +/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4)); +/// assert_eq!(Rational::new(1, 2) / Rational::new(3, 4), +/// Rational::new(2, 3)); +/// ``` +/// +/// ## Dividing vectors by scalars as in linear algebra +/// +/// ``` +/// use std::ops::Div; +/// +/// struct Scalar { value: f32 } +/// +/// #[derive(Debug, PartialEq)] +/// struct Vector { value: Vec } +/// +/// impl Div for Vector { +/// type Output = Self; +/// +/// fn div(self, rhs: Scalar) -> Self::Output { +/// Self { value: self.value.iter().map(|v| v / rhs.value).collect() } +/// } +/// } +/// +/// let scalar = Scalar { value: 2f32 }; +/// let vector = Vector { value: vec![2f32, 4f32, 6f32] }; +/// assert_eq!(vector / scalar, Vector { value: vec![1f32, 2f32, 3f32] }); +/// ``` +#[lang = "div"] +#[stable(feature = "rust1", since = "1.0.0")] +#[diagnostic::on_unimplemented( + message = "cannot divide `{Self}` by `{Rhs}`", + label = "no implementation for `{Self} / {Rhs}`" +)] +#[doc(alias = "/")] +pub trait Div { + /// The resulting type after applying the `/` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `/` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 / 2, 6); + /// ``` + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "div"] + #[stable(feature = "rust1", since = "1.0.0")] + fn div(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! div_impl_integer { + ($(($($t:ty)*) => $panic:expr),*) => ($($( + /// This operation rounds towards zero, truncating any + /// fractional part of the exact result. + /// + /// # Panics + /// + #[doc = $panic] + #[stable(feature = "rust1", since = "1.0.0")] + impl Div for $t { + type Output = $t; + + #[inline] + #[track_caller] + fn div(self, other: $t) -> $t { self / other } + } + + forward_ref_binop! { impl Div, div for $t, $t } + )*)*) +} + +div_impl_integer! { + (usize u8 u16 u32 u64 u128) => "This operation will panic if `other == 0`.", + (isize i8 i16 i32 i64 i128) => "This operation will panic if `other == 0` or the division results in overflow." +} + +macro_rules! div_impl_float { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Div for $t { + type Output = $t; + + #[inline] + fn div(self, other: $t) -> $t { self / other } + } + + forward_ref_binop! { impl Div, div for $t, $t } + )*) +} + +div_impl_float! { f16 f32 f64 f128 } + +/// The remainder operator `%`. +/// +/// Note that `Rhs` is `Self` by default, but this is not mandatory. +/// +/// # Examples +/// +/// This example implements `Rem` on a `SplitSlice` object. After `Rem` is +/// implemented, one can use the `%` operator to find out what the remaining +/// elements of the slice would be after splitting it into equal slices of a +/// given length. +/// +/// ``` +/// use std::ops::Rem; +/// +/// #[derive(PartialEq, Debug)] +/// struct SplitSlice<'a, T> { +/// slice: &'a [T], +/// } +/// +/// impl<'a, T> Rem for SplitSlice<'a, T> { +/// type Output = Self; +/// +/// fn rem(self, modulus: usize) -> Self::Output { +/// let len = self.slice.len(); +/// let rem = len % modulus; +/// let start = len - rem; +/// Self {slice: &self.slice[start..]} +/// } +/// } +/// +/// // If we were to divide &[0, 1, 2, 3, 4, 5, 6, 7] into slices of size 3, +/// // the remainder would be &[6, 7]. +/// assert_eq!(SplitSlice { slice: &[0, 1, 2, 3, 4, 5, 6, 7] } % 3, +/// SplitSlice { slice: &[6, 7] }); +/// ``` +#[lang = "rem"] +#[stable(feature = "rust1", since = "1.0.0")] +#[diagnostic::on_unimplemented( + message = "cannot calculate the remainder of `{Self}` divided by `{Rhs}`", + label = "no implementation for `{Self} % {Rhs}`" +)] +#[doc(alias = "%")] +pub trait Rem { + /// The resulting type after applying the `%` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `%` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 % 10, 2); + /// ``` + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "rem"] + #[stable(feature = "rust1", since = "1.0.0")] + fn rem(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! rem_impl_integer { + ($(($($t:ty)*) => $panic:expr),*) => ($($( + /// This operation satisfies `n % d == n - (n / d) * d`. The + /// result has the same sign as the left operand. + /// + /// # Panics + /// + #[doc = $panic] + #[stable(feature = "rust1", since = "1.0.0")] + impl Rem for $t { + type Output = $t; + + #[inline] + #[track_caller] + fn rem(self, other: $t) -> $t { self % other } + } + + forward_ref_binop! { impl Rem, rem for $t, $t } + )*)*) +} + +rem_impl_integer! { + (usize u8 u16 u32 u64 u128) => "This operation will panic if `other == 0`.", + (isize i8 i16 i32 i64 i128) => "This operation will panic if `other == 0` or if `self / other` results in overflow." +} + +macro_rules! rem_impl_float { + ($($t:ty)*) => ($( + + /// The remainder from the division of two floats. + /// + /// The remainder has the same sign as the dividend and is computed as: + /// `x - (x / y).trunc() * y`. + /// + /// # Examples + /// ``` + /// let x: f32 = 50.50; + /// let y: f32 = 8.125; + /// let remainder = x - (x / y).trunc() * y; + /// + /// // The answer to both operations is 1.75 + /// assert_eq!(x % y, remainder); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + impl Rem for $t { + type Output = $t; + + #[inline] + fn rem(self, other: $t) -> $t { self % other } + } + + forward_ref_binop! { impl Rem, rem for $t, $t } + )*) +} + +rem_impl_float! { f16 f32 f64 f128 } + +/// The unary negation operator `-`. +/// +/// # Examples +/// +/// An implementation of `Neg` for `Sign`, which allows the use of `-` to +/// negate its value. +/// +/// ``` +/// use std::ops::Neg; +/// +/// #[derive(Debug, PartialEq)] +/// enum Sign { +/// Negative, +/// Zero, +/// Positive, +/// } +/// +/// impl Neg for Sign { +/// type Output = Self; +/// +/// fn neg(self) -> Self::Output { +/// match self { +/// Sign::Negative => Sign::Positive, +/// Sign::Zero => Sign::Zero, +/// Sign::Positive => Sign::Negative, +/// } +/// } +/// } +/// +/// // A negative positive is a negative. +/// assert_eq!(-Sign::Positive, Sign::Negative); +/// // A double negative is a positive. +/// assert_eq!(-Sign::Negative, Sign::Positive); +/// // Zero is its own negation. +/// assert_eq!(-Sign::Zero, Sign::Zero); +/// ``` +#[lang = "neg"] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "-")] +pub trait Neg { + /// The resulting type after applying the `-` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the unary `-` operation. + /// + /// # Example + /// + /// ``` + /// let x: i32 = 12; + /// assert_eq!(-x, -12); + /// ``` + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "neg"] + #[stable(feature = "rust1", since = "1.0.0")] + fn neg(self) -> Self::Output; +} + +macro_rules! neg_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Neg for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn neg(self) -> $t { -self } + } + + forward_ref_unop! { impl Neg, neg for $t } + )*) +} + +neg_impl! { isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } + +/// The addition assignment operator `+=`. +/// +/// # Examples +/// +/// This example creates a `Point` struct that implements the `AddAssign` +/// trait, and then demonstrates add-assigning to a mutable `Point`. +/// +/// ``` +/// use std::ops::AddAssign; +/// +/// #[derive(Debug, Copy, Clone, PartialEq)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl AddAssign for Point { +/// fn add_assign(&mut self, other: Self) { +/// *self = Self { +/// x: self.x + other.x, +/// y: self.y + other.y, +/// }; +/// } +/// } +/// +/// let mut point = Point { x: 1, y: 0 }; +/// point += Point { x: 2, y: 3 }; +/// assert_eq!(point, Point { x: 3, y: 3 }); +/// ``` +#[lang = "add_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[diagnostic::on_unimplemented( + message = "cannot add-assign `{Rhs}` to `{Self}`", + label = "no implementation for `{Self} += {Rhs}`" +)] +#[doc(alias = "+")] +#[doc(alias = "+=")] +pub trait AddAssign { + /// Performs the `+=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x += 1; + /// assert_eq!(x, 13); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn add_assign(&mut self, rhs: Rhs); +} + +macro_rules! add_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl AddAssign for $t { + #[inline] + #[track_caller] + #[rustc_inherit_overflow_checks] + fn add_assign(&mut self, other: $t) { *self += other } + } + + forward_ref_op_assign! { impl AddAssign, add_assign for $t, $t } + )+) +} + +add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } + +/// The subtraction assignment operator `-=`. +/// +/// # Examples +/// +/// This example creates a `Point` struct that implements the `SubAssign` +/// trait, and then demonstrates sub-assigning to a mutable `Point`. +/// +/// ``` +/// use std::ops::SubAssign; +/// +/// #[derive(Debug, Copy, Clone, PartialEq)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl SubAssign for Point { +/// fn sub_assign(&mut self, other: Self) { +/// *self = Self { +/// x: self.x - other.x, +/// y: self.y - other.y, +/// }; +/// } +/// } +/// +/// let mut point = Point { x: 3, y: 3 }; +/// point -= Point { x: 2, y: 3 }; +/// assert_eq!(point, Point {x: 1, y: 0}); +/// ``` +#[lang = "sub_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[diagnostic::on_unimplemented( + message = "cannot subtract-assign `{Rhs}` from `{Self}`", + label = "no implementation for `{Self} -= {Rhs}`" +)] +#[doc(alias = "-")] +#[doc(alias = "-=")] +pub trait SubAssign { + /// Performs the `-=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x -= 1; + /// assert_eq!(x, 11); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn sub_assign(&mut self, rhs: Rhs); +} + +macro_rules! sub_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl SubAssign for $t { + #[inline] + #[track_caller] + #[rustc_inherit_overflow_checks] + fn sub_assign(&mut self, other: $t) { *self -= other } + } + + forward_ref_op_assign! { impl SubAssign, sub_assign for $t, $t } + )+) +} + +sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } + +/// The multiplication assignment operator `*=`. +/// +/// # Examples +/// +/// ``` +/// use std::ops::MulAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct Frequency { hertz: f64 } +/// +/// impl MulAssign for Frequency { +/// fn mul_assign(&mut self, rhs: f64) { +/// self.hertz *= rhs; +/// } +/// } +/// +/// let mut frequency = Frequency { hertz: 50.0 }; +/// frequency *= 4.0; +/// assert_eq!(Frequency { hertz: 200.0 }, frequency); +/// ``` +#[lang = "mul_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[diagnostic::on_unimplemented( + message = "cannot multiply-assign `{Self}` by `{Rhs}`", + label = "no implementation for `{Self} *= {Rhs}`" +)] +#[doc(alias = "*")] +#[doc(alias = "*=")] +pub trait MulAssign { + /// Performs the `*=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x *= 2; + /// assert_eq!(x, 24); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn mul_assign(&mut self, rhs: Rhs); +} + +macro_rules! mul_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl MulAssign for $t { + #[inline] + #[track_caller] + #[rustc_inherit_overflow_checks] + fn mul_assign(&mut self, other: $t) { *self *= other } + } + + forward_ref_op_assign! { impl MulAssign, mul_assign for $t, $t } + )+) +} + +mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } + +/// The division assignment operator `/=`. +/// +/// # Examples +/// +/// ``` +/// use std::ops::DivAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct Frequency { hertz: f64 } +/// +/// impl DivAssign for Frequency { +/// fn div_assign(&mut self, rhs: f64) { +/// self.hertz /= rhs; +/// } +/// } +/// +/// let mut frequency = Frequency { hertz: 200.0 }; +/// frequency /= 4.0; +/// assert_eq!(Frequency { hertz: 50.0 }, frequency); +/// ``` +#[lang = "div_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[diagnostic::on_unimplemented( + message = "cannot divide-assign `{Self}` by `{Rhs}`", + label = "no implementation for `{Self} /= {Rhs}`" +)] +#[doc(alias = "/")] +#[doc(alias = "/=")] +pub trait DivAssign { + /// Performs the `/=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x /= 2; + /// assert_eq!(x, 6); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn div_assign(&mut self, rhs: Rhs); +} + +macro_rules! div_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl DivAssign for $t { + #[inline] + #[track_caller] + fn div_assign(&mut self, other: $t) { *self /= other } + } + + forward_ref_op_assign! { impl DivAssign, div_assign for $t, $t } + )+) +} + +div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } + +/// The remainder assignment operator `%=`. +/// +/// # Examples +/// +/// ``` +/// use std::ops::RemAssign; +/// +/// struct CookieJar { cookies: u32 } +/// +/// impl RemAssign for CookieJar { +/// fn rem_assign(&mut self, piles: u32) { +/// self.cookies %= piles; +/// } +/// } +/// +/// let mut jar = CookieJar { cookies: 31 }; +/// let piles = 4; +/// +/// println!("Splitting up {} cookies into {} even piles!", jar.cookies, piles); +/// +/// jar %= piles; +/// +/// println!("{} cookies remain in the cookie jar!", jar.cookies); +/// ``` +#[lang = "rem_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[diagnostic::on_unimplemented( + message = "cannot calculate and assign the remainder of `{Self}` divided by `{Rhs}`", + label = "no implementation for `{Self} %= {Rhs}`" +)] +#[doc(alias = "%")] +#[doc(alias = "%=")] +pub trait RemAssign { + /// Performs the `%=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x %= 10; + /// assert_eq!(x, 2); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn rem_assign(&mut self, rhs: Rhs); +} + +macro_rules! rem_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl RemAssign for $t { + #[inline] + #[track_caller] + fn rem_assign(&mut self, other: $t) { *self %= other } + } + + forward_ref_op_assign! { impl RemAssign, rem_assign for $t, $t } + )+) +} + +rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } diff --git a/CoqOfRust/core/ops/async_function.rs b/CoqOfRust/core/ops/async_function.rs new file mode 100644 index 000000000..4b230b15a --- /dev/null +++ b/CoqOfRust/core/ops/async_function.rs @@ -0,0 +1,158 @@ +use crate::future::Future; +use crate::marker::Tuple; + +/// An async-aware version of the [`Fn`](crate::ops::Fn) trait. +/// +/// All `async fn` and functions returning futures implement this trait. +#[unstable(feature = "async_closure", issue = "62290")] +#[rustc_paren_sugar] +#[fundamental] +#[must_use = "async closures are lazy and do nothing unless called"] +#[lang = "async_fn"] +pub trait AsyncFn: AsyncFnMut { + /// Call the [`AsyncFn`], returning a future which may borrow from the called closure. + #[unstable(feature = "async_fn_traits", issue = "none")] + extern "rust-call" fn async_call(&self, args: Args) -> Self::CallRefFuture<'_>; +} + +/// An async-aware version of the [`FnMut`](crate::ops::FnMut) trait. +/// +/// All `async fn` and functions returning futures implement this trait. +#[unstable(feature = "async_closure", issue = "62290")] +#[rustc_paren_sugar] +#[fundamental] +#[must_use = "async closures are lazy and do nothing unless called"] +#[lang = "async_fn_mut"] +pub trait AsyncFnMut: AsyncFnOnce { + /// Future returned by [`AsyncFnMut::async_call_mut`] and [`AsyncFn::async_call`]. + #[unstable(feature = "async_fn_traits", issue = "none")] + #[lang = "call_ref_future"] + type CallRefFuture<'a>: Future + where + Self: 'a; + + /// Call the [`AsyncFnMut`], returning a future which may borrow from the called closure. + #[unstable(feature = "async_fn_traits", issue = "none")] + extern "rust-call" fn async_call_mut(&mut self, args: Args) -> Self::CallRefFuture<'_>; +} + +/// An async-aware version of the [`FnOnce`](crate::ops::FnOnce) trait. +/// +/// All `async fn` and functions returning futures implement this trait. +#[unstable(feature = "async_closure", issue = "62290")] +#[rustc_paren_sugar] +#[fundamental] +#[must_use = "async closures are lazy and do nothing unless called"] +#[lang = "async_fn_once"] +pub trait AsyncFnOnce { + /// Future returned by [`AsyncFnOnce::async_call_once`]. + #[unstable(feature = "async_fn_traits", issue = "none")] + #[lang = "call_once_future"] + type CallOnceFuture: Future; + + /// Output type of the called closure's future. + #[unstable(feature = "async_fn_traits", issue = "none")] + #[lang = "async_fn_once_output"] + type Output; + + /// Call the [`AsyncFnOnce`], returning a future which may move out of the called closure. + #[unstable(feature = "async_fn_traits", issue = "none")] + extern "rust-call" fn async_call_once(self, args: Args) -> Self::CallOnceFuture; +} + +mod impls { + use super::{AsyncFn, AsyncFnMut, AsyncFnOnce}; + use crate::marker::Tuple; + + #[unstable(feature = "async_fn_traits", issue = "none")] + impl AsyncFn for &F + where + F: AsyncFn, + { + extern "rust-call" fn async_call(&self, args: A) -> Self::CallRefFuture<'_> { + F::async_call(*self, args) + } + } + + #[unstable(feature = "async_fn_traits", issue = "none")] + impl AsyncFnMut for &F + where + F: AsyncFn, + { + type CallRefFuture<'a> + = F::CallRefFuture<'a> + where + Self: 'a; + + extern "rust-call" fn async_call_mut(&mut self, args: A) -> Self::CallRefFuture<'_> { + F::async_call(*self, args) + } + } + + #[unstable(feature = "async_fn_traits", issue = "none")] + impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce for &'a F + where + F: AsyncFn, + { + type Output = F::Output; + type CallOnceFuture = F::CallRefFuture<'a>; + + extern "rust-call" fn async_call_once(self, args: A) -> Self::CallOnceFuture { + F::async_call(self, args) + } + } + + #[unstable(feature = "async_fn_traits", issue = "none")] + impl AsyncFnMut for &mut F + where + F: AsyncFnMut, + { + type CallRefFuture<'a> + = F::CallRefFuture<'a> + where + Self: 'a; + + extern "rust-call" fn async_call_mut(&mut self, args: A) -> Self::CallRefFuture<'_> { + F::async_call_mut(*self, args) + } + } + + #[unstable(feature = "async_fn_traits", issue = "none")] + impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce for &'a mut F + where + F: AsyncFnMut, + { + type Output = F::Output; + type CallOnceFuture = F::CallRefFuture<'a>; + + extern "rust-call" fn async_call_once(self, args: A) -> Self::CallOnceFuture { + F::async_call_mut(self, args) + } + } +} + +mod internal_implementation_detail { + /// A helper trait that is used to enforce that the `ClosureKind` of a goal + /// is within the capabilities of a `CoroutineClosure`, and which allows us + /// to delay the projection of the tupled upvar types until after upvar + /// analysis is complete. + /// + /// The `Self` type is expected to be the `kind_ty` of the coroutine-closure, + /// and thus either `?0` or `i8`/`i16`/`i32` (see docs for `ClosureKind` + /// for an explanation of that). The `GoalKind` is also the same type, but + /// representing the kind of the trait that the closure is being called with. + #[lang = "async_fn_kind_helper"] + trait AsyncFnKindHelper { + // Projects a set of closure inputs (arguments), a region, and a set of upvars + // (by move and by ref) to the upvars that we expect the coroutine to have + // according to the `GoalKind` parameter above. + // + // The `Upvars` parameter should be the upvars of the parent coroutine-closure, + // and the `BorrowedUpvarsAsFnPtr` will be a function pointer that has the shape + // `for<'env> fn() -> (&'env T, ...)`. This allows us to represent the binder + // of the closure's self-capture, and these upvar types will be instantiated with + // the `'closure_env` region provided to the associated type. + #[lang = "async_fn_kind_upvars"] + type Upvars<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>; + } +} diff --git a/CoqOfRust/core/ops/bit.rs b/CoqOfRust/core/ops/bit.rs new file mode 100644 index 000000000..6984100e4 --- /dev/null +++ b/CoqOfRust/core/ops/bit.rs @@ -0,0 +1,1032 @@ +/// The unary logical negation operator `!`. +/// +/// # Examples +/// +/// An implementation of `Not` for `Answer`, which enables the use of `!` to +/// invert its value. +/// +/// ``` +/// use std::ops::Not; +/// +/// #[derive(Debug, PartialEq)] +/// enum Answer { +/// Yes, +/// No, +/// } +/// +/// impl Not for Answer { +/// type Output = Self; +/// +/// fn not(self) -> Self::Output { +/// match self { +/// Answer::Yes => Answer::No, +/// Answer::No => Answer::Yes +/// } +/// } +/// } +/// +/// assert_eq!(!Answer::Yes, Answer::No); +/// assert_eq!(!Answer::No, Answer::Yes); +/// ``` +#[lang = "not"] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "!")] +pub trait Not { + /// The resulting type after applying the `!` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the unary `!` operation. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(!true, false); + /// assert_eq!(!false, true); + /// assert_eq!(!1u8, 254); + /// assert_eq!(!0u8, 255); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn not(self) -> Self::Output; +} + +macro_rules! not_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Not for $t { + type Output = $t; + + #[inline] + fn not(self) -> $t { !self } + } + + forward_ref_unop! { impl Not, not for $t } + )*) +} + +not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +#[stable(feature = "not_never", since = "1.60.0")] +impl Not for ! { + type Output = !; + + #[inline] + fn not(self) -> ! { + match self {} + } +} + +/// The bitwise AND operator `&`. +/// +/// Note that `Rhs` is `Self` by default, but this is not mandatory. +/// +/// # Examples +/// +/// An implementation of `BitAnd` for a wrapper around `bool`. +/// +/// ``` +/// use std::ops::BitAnd; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitAnd for Scalar { +/// type Output = Self; +/// +/// // rhs is the "right-hand side" of the expression `a & b` +/// fn bitand(self, rhs: Self) -> Self::Output { +/// Self(self.0 & rhs.0) +/// } +/// } +/// +/// assert_eq!(Scalar(true) & Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(true) & Scalar(false), Scalar(false)); +/// assert_eq!(Scalar(false) & Scalar(true), Scalar(false)); +/// assert_eq!(Scalar(false) & Scalar(false), Scalar(false)); +/// ``` +/// +/// An implementation of `BitAnd` for a wrapper around `Vec`. +/// +/// ``` +/// use std::ops::BitAnd; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitAnd for BooleanVector { +/// type Output = Self; +/// +/// fn bitand(self, Self(rhs): Self) -> Self::Output { +/// let Self(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// Self( +/// lhs.iter() +/// .zip(rhs.iter()) +/// .map(|(x, y)| *x & *y) +/// .collect() +/// ) +/// } +/// } +/// +/// let bv1 = BooleanVector(vec![true, true, false, false]); +/// let bv2 = BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![true, false, false, false]); +/// assert_eq!(bv1 & bv2, expected); +/// ``` +#[lang = "bitand"] +#[doc(alias = "&")] +#[stable(feature = "rust1", since = "1.0.0")] +#[diagnostic::on_unimplemented( + message = "no implementation for `{Self} & {Rhs}`", + label = "no implementation for `{Self} & {Rhs}`" +)] +pub trait BitAnd { + /// The resulting type after applying the `&` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `&` operation. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(true & false, false); + /// assert_eq!(true & true, true); + /// assert_eq!(5u8 & 1u8, 1); + /// assert_eq!(5u8 & 2u8, 0); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn bitand(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! bitand_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl BitAnd for $t { + type Output = $t; + + #[inline] + fn bitand(self, rhs: $t) -> $t { self & rhs } + } + + forward_ref_binop! { impl BitAnd, bitand for $t, $t } + )*) +} + +bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise OR operator `|`. +/// +/// Note that `Rhs` is `Self` by default, but this is not mandatory. +/// +/// # Examples +/// +/// An implementation of `BitOr` for a wrapper around `bool`. +/// +/// ``` +/// use std::ops::BitOr; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitOr for Scalar { +/// type Output = Self; +/// +/// // rhs is the "right-hand side" of the expression `a | b` +/// fn bitor(self, rhs: Self) -> Self::Output { +/// Self(self.0 | rhs.0) +/// } +/// } +/// +/// assert_eq!(Scalar(true) | Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(true) | Scalar(false), Scalar(true)); +/// assert_eq!(Scalar(false) | Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(false) | Scalar(false), Scalar(false)); +/// ``` +/// +/// An implementation of `BitOr` for a wrapper around `Vec`. +/// +/// ``` +/// use std::ops::BitOr; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitOr for BooleanVector { +/// type Output = Self; +/// +/// fn bitor(self, Self(rhs): Self) -> Self::Output { +/// let Self(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// Self( +/// lhs.iter() +/// .zip(rhs.iter()) +/// .map(|(x, y)| *x | *y) +/// .collect() +/// ) +/// } +/// } +/// +/// let bv1 = BooleanVector(vec![true, true, false, false]); +/// let bv2 = BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![true, true, true, false]); +/// assert_eq!(bv1 | bv2, expected); +/// ``` +#[lang = "bitor"] +#[doc(alias = "|")] +#[stable(feature = "rust1", since = "1.0.0")] +#[diagnostic::on_unimplemented( + message = "no implementation for `{Self} | {Rhs}`", + label = "no implementation for `{Self} | {Rhs}`" +)] +pub trait BitOr { + /// The resulting type after applying the `|` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `|` operation. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(true | false, true); + /// assert_eq!(false | false, false); + /// assert_eq!(5u8 | 1u8, 5); + /// assert_eq!(5u8 | 2u8, 7); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn bitor(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! bitor_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl BitOr for $t { + type Output = $t; + + #[inline] + fn bitor(self, rhs: $t) -> $t { self | rhs } + } + + forward_ref_binop! { impl BitOr, bitor for $t, $t } + )*) +} + +bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise XOR operator `^`. +/// +/// Note that `Rhs` is `Self` by default, but this is not mandatory. +/// +/// # Examples +/// +/// An implementation of `BitXor` that lifts `^` to a wrapper around `bool`. +/// +/// ``` +/// use std::ops::BitXor; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitXor for Scalar { +/// type Output = Self; +/// +/// // rhs is the "right-hand side" of the expression `a ^ b` +/// fn bitxor(self, rhs: Self) -> Self::Output { +/// Self(self.0 ^ rhs.0) +/// } +/// } +/// +/// assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false)); +/// assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true)); +/// assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false)); +/// ``` +/// +/// An implementation of `BitXor` trait for a wrapper around `Vec`. +/// +/// ``` +/// use std::ops::BitXor; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitXor for BooleanVector { +/// type Output = Self; +/// +/// fn bitxor(self, Self(rhs): Self) -> Self::Output { +/// let Self(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// Self( +/// lhs.iter() +/// .zip(rhs.iter()) +/// .map(|(x, y)| *x ^ *y) +/// .collect() +/// ) +/// } +/// } +/// +/// let bv1 = BooleanVector(vec![true, true, false, false]); +/// let bv2 = BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![false, true, true, false]); +/// assert_eq!(bv1 ^ bv2, expected); +/// ``` +#[lang = "bitxor"] +#[doc(alias = "^")] +#[stable(feature = "rust1", since = "1.0.0")] +#[diagnostic::on_unimplemented( + message = "no implementation for `{Self} ^ {Rhs}`", + label = "no implementation for `{Self} ^ {Rhs}`" +)] +pub trait BitXor { + /// The resulting type after applying the `^` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `^` operation. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(true ^ false, true); + /// assert_eq!(true ^ true, false); + /// assert_eq!(5u8 ^ 1u8, 4); + /// assert_eq!(5u8 ^ 2u8, 7); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn bitxor(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! bitxor_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl BitXor for $t { + type Output = $t; + + #[inline] + fn bitxor(self, other: $t) -> $t { self ^ other } + } + + forward_ref_binop! { impl BitXor, bitxor for $t, $t } + )*) +} + +bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The left shift operator `<<`. Note that because this trait is implemented +/// for all integer types with multiple right-hand-side types, Rust's type +/// checker has special handling for `_ << _`, setting the result type for +/// integer operations to the type of the left-hand-side operand. This means +/// that though `a << b` and `a.shl(b)` are one and the same from an evaluation +/// standpoint, they are different when it comes to type inference. +/// +/// # Examples +/// +/// An implementation of `Shl` that lifts the `<<` operation on integers to a +/// wrapper around `usize`. +/// +/// ``` +/// use std::ops::Shl; +/// +/// #[derive(PartialEq, Debug)] +/// struct Scalar(usize); +/// +/// impl Shl for Scalar { +/// type Output = Self; +/// +/// fn shl(self, Self(rhs): Self) -> Self::Output { +/// let Self(lhs) = self; +/// Self(lhs << rhs) +/// } +/// } +/// +/// assert_eq!(Scalar(4) << Scalar(2), Scalar(16)); +/// ``` +/// +/// An implementation of `Shl` that spins a vector leftward by a given amount. +/// +/// ``` +/// use std::ops::Shl; +/// +/// #[derive(PartialEq, Debug)] +/// struct SpinVector { +/// vec: Vec, +/// } +/// +/// impl Shl for SpinVector { +/// type Output = Self; +/// +/// fn shl(self, rhs: usize) -> Self::Output { +/// // Rotate the vector by `rhs` places. +/// let (a, b) = self.vec.split_at(rhs); +/// let mut spun_vector = vec![]; +/// spun_vector.extend_from_slice(b); +/// spun_vector.extend_from_slice(a); +/// Self { vec: spun_vector } +/// } +/// } +/// +/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2, +/// SpinVector { vec: vec![2, 3, 4, 0, 1] }); +/// ``` +#[lang = "shl"] +#[doc(alias = "<<")] +#[stable(feature = "rust1", since = "1.0.0")] +#[diagnostic::on_unimplemented( + message = "no implementation for `{Self} << {Rhs}`", + label = "no implementation for `{Self} << {Rhs}`" +)] +pub trait Shl { + /// The resulting type after applying the `<<` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `<<` operation. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(5u8 << 1, 10); + /// assert_eq!(1u8 << 1, 2); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn shl(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! shl_impl { + ($t:ty, $f:ty) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl Shl<$f> for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn shl(self, other: $f) -> $t { + self << other + } + } + + forward_ref_binop! { impl Shl, shl for $t, $f } + }; +} + +macro_rules! shl_impl_all { + ($($t:ty)*) => ($( + shl_impl! { $t, u8 } + shl_impl! { $t, u16 } + shl_impl! { $t, u32 } + shl_impl! { $t, u64 } + shl_impl! { $t, u128 } + shl_impl! { $t, usize } + + shl_impl! { $t, i8 } + shl_impl! { $t, i16 } + shl_impl! { $t, i32 } + shl_impl! { $t, i64 } + shl_impl! { $t, i128 } + shl_impl! { $t, isize } + )*) +} + +shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 } + +/// The right shift operator `>>`. Note that because this trait is implemented +/// for all integer types with multiple right-hand-side types, Rust's type +/// checker has special handling for `_ >> _`, setting the result type for +/// integer operations to the type of the left-hand-side operand. This means +/// that though `a >> b` and `a.shr(b)` are one and the same from an evaluation +/// standpoint, they are different when it comes to type inference. +/// +/// # Examples +/// +/// An implementation of `Shr` that lifts the `>>` operation on integers to a +/// wrapper around `usize`. +/// +/// ``` +/// use std::ops::Shr; +/// +/// #[derive(PartialEq, Debug)] +/// struct Scalar(usize); +/// +/// impl Shr for Scalar { +/// type Output = Self; +/// +/// fn shr(self, Self(rhs): Self) -> Self::Output { +/// let Self(lhs) = self; +/// Self(lhs >> rhs) +/// } +/// } +/// +/// assert_eq!(Scalar(16) >> Scalar(2), Scalar(4)); +/// ``` +/// +/// An implementation of `Shr` that spins a vector rightward by a given amount. +/// +/// ``` +/// use std::ops::Shr; +/// +/// #[derive(PartialEq, Debug)] +/// struct SpinVector { +/// vec: Vec, +/// } +/// +/// impl Shr for SpinVector { +/// type Output = Self; +/// +/// fn shr(self, rhs: usize) -> Self::Output { +/// // Rotate the vector by `rhs` places. +/// let (a, b) = self.vec.split_at(self.vec.len() - rhs); +/// let mut spun_vector = vec![]; +/// spun_vector.extend_from_slice(b); +/// spun_vector.extend_from_slice(a); +/// Self { vec: spun_vector } +/// } +/// } +/// +/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2, +/// SpinVector { vec: vec![3, 4, 0, 1, 2] }); +/// ``` +#[lang = "shr"] +#[doc(alias = ">>")] +#[stable(feature = "rust1", since = "1.0.0")] +#[diagnostic::on_unimplemented( + message = "no implementation for `{Self} >> {Rhs}`", + label = "no implementation for `{Self} >> {Rhs}`" +)] +pub trait Shr { + /// The resulting type after applying the `>>` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `>>` operation. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(5u8 >> 1, 2); + /// assert_eq!(2u8 >> 1, 1); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn shr(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! shr_impl { + ($t:ty, $f:ty) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl Shr<$f> for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn shr(self, other: $f) -> $t { + self >> other + } + } + + forward_ref_binop! { impl Shr, shr for $t, $f } + }; +} + +macro_rules! shr_impl_all { + ($($t:ty)*) => ($( + shr_impl! { $t, u8 } + shr_impl! { $t, u16 } + shr_impl! { $t, u32 } + shr_impl! { $t, u64 } + shr_impl! { $t, u128 } + shr_impl! { $t, usize } + + shr_impl! { $t, i8 } + shr_impl! { $t, i16 } + shr_impl! { $t, i32 } + shr_impl! { $t, i64 } + shr_impl! { $t, i128 } + shr_impl! { $t, isize } + )*) +} + +shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } + +/// The bitwise AND assignment operator `&=`. +/// +/// # Examples +/// +/// An implementation of `BitAndAssign` that lifts the `&=` operator to a +/// wrapper around `bool`. +/// +/// ``` +/// use std::ops::BitAndAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitAndAssign for Scalar { +/// // rhs is the "right-hand side" of the expression `a &= b` +/// fn bitand_assign(&mut self, rhs: Self) { +/// *self = Self(self.0 & rhs.0) +/// } +/// } +/// +/// let mut scalar = Scalar(true); +/// scalar &= Scalar(true); +/// assert_eq!(scalar, Scalar(true)); +/// +/// let mut scalar = Scalar(true); +/// scalar &= Scalar(false); +/// assert_eq!(scalar, Scalar(false)); +/// +/// let mut scalar = Scalar(false); +/// scalar &= Scalar(true); +/// assert_eq!(scalar, Scalar(false)); +/// +/// let mut scalar = Scalar(false); +/// scalar &= Scalar(false); +/// assert_eq!(scalar, Scalar(false)); +/// ``` +/// +/// Here, the `BitAndAssign` trait is implemented for a wrapper around +/// `Vec`. +/// +/// ``` +/// use std::ops::BitAndAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitAndAssign for BooleanVector { +/// // `rhs` is the "right-hand side" of the expression `a &= b`. +/// fn bitand_assign(&mut self, rhs: Self) { +/// assert_eq!(self.0.len(), rhs.0.len()); +/// *self = Self( +/// self.0 +/// .iter() +/// .zip(rhs.0.iter()) +/// .map(|(x, y)| *x & *y) +/// .collect() +/// ); +/// } +/// } +/// +/// let mut bv = BooleanVector(vec![true, true, false, false]); +/// bv &= BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![true, false, false, false]); +/// assert_eq!(bv, expected); +/// ``` +#[lang = "bitand_assign"] +#[doc(alias = "&=")] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[diagnostic::on_unimplemented( + message = "no implementation for `{Self} &= {Rhs}`", + label = "no implementation for `{Self} &= {Rhs}`" +)] +pub trait BitAndAssign { + /// Performs the `&=` operation. + /// + /// # Examples + /// + /// ``` + /// let mut x = true; + /// x &= false; + /// assert_eq!(x, false); + /// + /// let mut x = true; + /// x &= true; + /// assert_eq!(x, true); + /// + /// let mut x: u8 = 5; + /// x &= 1; + /// assert_eq!(x, 1); + /// + /// let mut x: u8 = 5; + /// x &= 2; + /// assert_eq!(x, 0); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn bitand_assign(&mut self, rhs: Rhs); +} + +macro_rules! bitand_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl BitAndAssign for $t { + #[inline] + fn bitand_assign(&mut self, other: $t) { *self &= other } + } + + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for $t, $t } + )+) +} + +bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise OR assignment operator `|=`. +/// +/// # Examples +/// +/// ``` +/// use std::ops::BitOrAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct PersonalPreferences { +/// likes_cats: bool, +/// likes_dogs: bool, +/// } +/// +/// impl BitOrAssign for PersonalPreferences { +/// fn bitor_assign(&mut self, rhs: Self) { +/// self.likes_cats |= rhs.likes_cats; +/// self.likes_dogs |= rhs.likes_dogs; +/// } +/// } +/// +/// let mut prefs = PersonalPreferences { likes_cats: true, likes_dogs: false }; +/// prefs |= PersonalPreferences { likes_cats: false, likes_dogs: true }; +/// assert_eq!(prefs, PersonalPreferences { likes_cats: true, likes_dogs: true }); +/// ``` +#[lang = "bitor_assign"] +#[doc(alias = "|=")] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[diagnostic::on_unimplemented( + message = "no implementation for `{Self} |= {Rhs}`", + label = "no implementation for `{Self} |= {Rhs}`" +)] +pub trait BitOrAssign { + /// Performs the `|=` operation. + /// + /// # Examples + /// + /// ``` + /// let mut x = true; + /// x |= false; + /// assert_eq!(x, true); + /// + /// let mut x = false; + /// x |= false; + /// assert_eq!(x, false); + /// + /// let mut x: u8 = 5; + /// x |= 1; + /// assert_eq!(x, 5); + /// + /// let mut x: u8 = 5; + /// x |= 2; + /// assert_eq!(x, 7); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn bitor_assign(&mut self, rhs: Rhs); +} + +macro_rules! bitor_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl BitOrAssign for $t { + #[inline] + fn bitor_assign(&mut self, other: $t) { *self |= other } + } + + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for $t, $t } + )+) +} + +bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise XOR assignment operator `^=`. +/// +/// # Examples +/// +/// ``` +/// use std::ops::BitXorAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct Personality { +/// has_soul: bool, +/// likes_knitting: bool, +/// } +/// +/// impl BitXorAssign for Personality { +/// fn bitxor_assign(&mut self, rhs: Self) { +/// self.has_soul ^= rhs.has_soul; +/// self.likes_knitting ^= rhs.likes_knitting; +/// } +/// } +/// +/// let mut personality = Personality { has_soul: false, likes_knitting: true }; +/// personality ^= Personality { has_soul: true, likes_knitting: true }; +/// assert_eq!(personality, Personality { has_soul: true, likes_knitting: false}); +/// ``` +#[lang = "bitxor_assign"] +#[doc(alias = "^=")] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[diagnostic::on_unimplemented( + message = "no implementation for `{Self} ^= {Rhs}`", + label = "no implementation for `{Self} ^= {Rhs}`" +)] +pub trait BitXorAssign { + /// Performs the `^=` operation. + /// + /// # Examples + /// + /// ``` + /// let mut x = true; + /// x ^= false; + /// assert_eq!(x, true); + /// + /// let mut x = true; + /// x ^= true; + /// assert_eq!(x, false); + /// + /// let mut x: u8 = 5; + /// x ^= 1; + /// assert_eq!(x, 4); + /// + /// let mut x: u8 = 5; + /// x ^= 2; + /// assert_eq!(x, 7); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn bitxor_assign(&mut self, rhs: Rhs); +} + +macro_rules! bitxor_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl BitXorAssign for $t { + #[inline] + fn bitxor_assign(&mut self, other: $t) { *self ^= other } + } + + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for $t, $t } + )+) +} + +bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The left shift assignment operator `<<=`. +/// +/// # Examples +/// +/// An implementation of `ShlAssign` for a wrapper around `usize`. +/// +/// ``` +/// use std::ops::ShlAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(usize); +/// +/// impl ShlAssign for Scalar { +/// fn shl_assign(&mut self, rhs: usize) { +/// self.0 <<= rhs; +/// } +/// } +/// +/// let mut scalar = Scalar(4); +/// scalar <<= 2; +/// assert_eq!(scalar, Scalar(16)); +/// ``` +#[lang = "shl_assign"] +#[doc(alias = "<<=")] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[diagnostic::on_unimplemented( + message = "no implementation for `{Self} <<= {Rhs}`", + label = "no implementation for `{Self} <<= {Rhs}`" +)] +pub trait ShlAssign { + /// Performs the `<<=` operation. + /// + /// # Examples + /// + /// ``` + /// let mut x: u8 = 5; + /// x <<= 1; + /// assert_eq!(x, 10); + /// + /// let mut x: u8 = 1; + /// x <<= 1; + /// assert_eq!(x, 2); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn shl_assign(&mut self, rhs: Rhs); +} + +macro_rules! shl_assign_impl { + ($t:ty, $f:ty) => { + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl ShlAssign<$f> for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn shl_assign(&mut self, other: $f) { + *self <<= other + } + } + + forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f } + }; +} + +macro_rules! shl_assign_impl_all { + ($($t:ty)*) => ($( + shl_assign_impl! { $t, u8 } + shl_assign_impl! { $t, u16 } + shl_assign_impl! { $t, u32 } + shl_assign_impl! { $t, u64 } + shl_assign_impl! { $t, u128 } + shl_assign_impl! { $t, usize } + + shl_assign_impl! { $t, i8 } + shl_assign_impl! { $t, i16 } + shl_assign_impl! { $t, i32 } + shl_assign_impl! { $t, i64 } + shl_assign_impl! { $t, i128 } + shl_assign_impl! { $t, isize } + )*) +} + +shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } + +/// The right shift assignment operator `>>=`. +/// +/// # Examples +/// +/// An implementation of `ShrAssign` for a wrapper around `usize`. +/// +/// ``` +/// use std::ops::ShrAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(usize); +/// +/// impl ShrAssign for Scalar { +/// fn shr_assign(&mut self, rhs: usize) { +/// self.0 >>= rhs; +/// } +/// } +/// +/// let mut scalar = Scalar(16); +/// scalar >>= 2; +/// assert_eq!(scalar, Scalar(4)); +/// ``` +#[lang = "shr_assign"] +#[doc(alias = ">>=")] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[diagnostic::on_unimplemented( + message = "no implementation for `{Self} >>= {Rhs}`", + label = "no implementation for `{Self} >>= {Rhs}`" +)] +pub trait ShrAssign { + /// Performs the `>>=` operation. + /// + /// # Examples + /// + /// ``` + /// let mut x: u8 = 5; + /// x >>= 1; + /// assert_eq!(x, 2); + /// + /// let mut x: u8 = 2; + /// x >>= 1; + /// assert_eq!(x, 1); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn shr_assign(&mut self, rhs: Rhs); +} + +macro_rules! shr_assign_impl { + ($t:ty, $f:ty) => { + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl ShrAssign<$f> for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn shr_assign(&mut self, other: $f) { + *self >>= other + } + } + + forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f } + }; +} + +macro_rules! shr_assign_impl_all { + ($($t:ty)*) => ($( + shr_assign_impl! { $t, u8 } + shr_assign_impl! { $t, u16 } + shr_assign_impl! { $t, u32 } + shr_assign_impl! { $t, u64 } + shr_assign_impl! { $t, u128 } + shr_assign_impl! { $t, usize } + + shr_assign_impl! { $t, i8 } + shr_assign_impl! { $t, i16 } + shr_assign_impl! { $t, i32 } + shr_assign_impl! { $t, i64 } + shr_assign_impl! { $t, i128 } + shr_assign_impl! { $t, isize } + )*) +} + +shr_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } diff --git a/CoqOfRust/core/ops/control_flow.rs b/CoqOfRust/core/ops/control_flow.rs new file mode 100644 index 000000000..c4429b3cd --- /dev/null +++ b/CoqOfRust/core/ops/control_flow.rs @@ -0,0 +1,253 @@ +use crate::{convert, ops}; + +/// Used to tell an operation whether it should exit early or go on as usual. +/// +/// This is used when exposing things (like graph traversals or visitors) where +/// you want the user to be able to choose whether to exit early. +/// Having the enum makes it clearer -- no more wondering "wait, what did `false` +/// mean again?" -- and allows including a value. +/// +/// Similar to [`Option`] and [`Result`], this enum can be used with the `?` operator +/// to return immediately if the [`Break`] variant is present or otherwise continue normally +/// with the value inside the [`Continue`] variant. +/// +/// # Examples +/// +/// Early-exiting from [`Iterator::try_for_each`]: +/// ``` +/// use std::ops::ControlFlow; +/// +/// let r = (2..100).try_for_each(|x| { +/// if 403 % x == 0 { +/// return ControlFlow::Break(x) +/// } +/// +/// ControlFlow::Continue(()) +/// }); +/// assert_eq!(r, ControlFlow::Break(13)); +/// ``` +/// +/// A basic tree traversal: +/// ``` +/// use std::ops::ControlFlow; +/// +/// pub struct TreeNode { +/// value: T, +/// left: Option>>, +/// right: Option>>, +/// } +/// +/// impl TreeNode { +/// pub fn traverse_inorder(&self, f: &mut impl FnMut(&T) -> ControlFlow) -> ControlFlow { +/// if let Some(left) = &self.left { +/// left.traverse_inorder(f)?; +/// } +/// f(&self.value)?; +/// if let Some(right) = &self.right { +/// right.traverse_inorder(f)?; +/// } +/// ControlFlow::Continue(()) +/// } +/// fn leaf(value: T) -> Option>> { +/// Some(Box::new(Self { value, left: None, right: None })) +/// } +/// } +/// +/// let node = TreeNode { +/// value: 0, +/// left: TreeNode::leaf(1), +/// right: Some(Box::new(TreeNode { +/// value: -1, +/// left: TreeNode::leaf(5), +/// right: TreeNode::leaf(2), +/// })) +/// }; +/// let mut sum = 0; +/// +/// let res = node.traverse_inorder(&mut |val| { +/// if *val < 0 { +/// ControlFlow::Break(*val) +/// } else { +/// sum += *val; +/// ControlFlow::Continue(()) +/// } +/// }); +/// assert_eq!(res, ControlFlow::Break(-1)); +/// assert_eq!(sum, 6); +/// ``` +/// +/// [`Break`]: ControlFlow::Break +/// [`Continue`]: ControlFlow::Continue +#[stable(feature = "control_flow_enum_type", since = "1.55.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "ControlFlow")] +// ControlFlow should not implement PartialOrd or Ord, per RFC 3058: +// https://rust-lang.github.io/rfcs/3058-try-trait-v2.html#traits-for-controlflow +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ControlFlow { + /// Move on to the next phase of the operation as normal. + #[stable(feature = "control_flow_enum_type", since = "1.55.0")] + #[lang = "Continue"] + Continue(C), + /// Exit the operation without running subsequent phases. + #[stable(feature = "control_flow_enum_type", since = "1.55.0")] + #[lang = "Break"] + Break(B), + // Yes, the order of the variants doesn't match the type parameters. + // They're in this order so that `ControlFlow` <-> `Result` + // is a no-op conversion in the `Try` implementation. +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl ops::Try for ControlFlow { + type Output = C; + type Residual = ControlFlow; + + #[inline] + fn from_output(output: Self::Output) -> Self { + ControlFlow::Continue(output) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + ControlFlow::Continue(c) => ControlFlow::Continue(c), + ControlFlow::Break(b) => ControlFlow::Break(ControlFlow::Break(b)), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +// Note: manually specifying the residual type instead of using the default to work around +// https://github.com/rust-lang/rust/issues/99940 +impl ops::FromResidual> for ControlFlow { + #[inline] + fn from_residual(residual: ControlFlow) -> Self { + match residual { + ControlFlow::Break(b) => ControlFlow::Break(b), + } + } +} + +#[unstable(feature = "try_trait_v2_residual", issue = "91285")] +impl ops::Residual for ControlFlow { + type TryType = ControlFlow; +} + +impl ControlFlow { + /// Returns `true` if this is a `Break` variant. + /// + /// # Examples + /// + /// ``` + /// use std::ops::ControlFlow; + /// + /// assert!(ControlFlow::::Break(3).is_break()); + /// assert!(!ControlFlow::::Continue(3).is_break()); + /// ``` + #[inline] + #[stable(feature = "control_flow_enum_is", since = "1.59.0")] + pub fn is_break(&self) -> bool { + matches!(*self, ControlFlow::Break(_)) + } + + /// Returns `true` if this is a `Continue` variant. + /// + /// # Examples + /// + /// ``` + /// use std::ops::ControlFlow; + /// + /// assert!(!ControlFlow::::Break(3).is_continue()); + /// assert!(ControlFlow::::Continue(3).is_continue()); + /// ``` + #[inline] + #[stable(feature = "control_flow_enum_is", since = "1.59.0")] + pub fn is_continue(&self) -> bool { + matches!(*self, ControlFlow::Continue(_)) + } + + /// Converts the `ControlFlow` into an `Option` which is `Some` if the + /// `ControlFlow` was `Break` and `None` otherwise. + /// + /// # Examples + /// + /// ``` + /// use std::ops::ControlFlow; + /// + /// assert_eq!(ControlFlow::::Break(3).break_value(), Some(3)); + /// assert_eq!(ControlFlow::::Continue(3).break_value(), None); + /// ``` + #[inline] + #[stable(feature = "control_flow_enum", since = "1.83.0")] + pub fn break_value(self) -> Option { + match self { + ControlFlow::Continue(..) => None, + ControlFlow::Break(x) => Some(x), + } + } + + /// Maps `ControlFlow` to `ControlFlow` by applying a function + /// to the break value in case it exists. + #[inline] + #[stable(feature = "control_flow_enum", since = "1.83.0")] + pub fn map_break(self, f: impl FnOnce(B) -> T) -> ControlFlow { + match self { + ControlFlow::Continue(x) => ControlFlow::Continue(x), + ControlFlow::Break(x) => ControlFlow::Break(f(x)), + } + } + + /// Converts the `ControlFlow` into an `Option` which is `Some` if the + /// `ControlFlow` was `Continue` and `None` otherwise. + /// + /// # Examples + /// + /// ``` + /// use std::ops::ControlFlow; + /// + /// assert_eq!(ControlFlow::::Break(3).continue_value(), None); + /// assert_eq!(ControlFlow::::Continue(3).continue_value(), Some(3)); + /// ``` + #[inline] + #[stable(feature = "control_flow_enum", since = "1.83.0")] + pub fn continue_value(self) -> Option { + match self { + ControlFlow::Continue(x) => Some(x), + ControlFlow::Break(..) => None, + } + } + + /// Maps `ControlFlow` to `ControlFlow` by applying a function + /// to the continue value in case it exists. + #[inline] + #[stable(feature = "control_flow_enum", since = "1.83.0")] + pub fn map_continue(self, f: impl FnOnce(C) -> T) -> ControlFlow { + match self { + ControlFlow::Continue(x) => ControlFlow::Continue(f(x)), + ControlFlow::Break(x) => ControlFlow::Break(x), + } + } +} + +/// These are used only as part of implementing the iterator adapters. +/// They have mediocre names and non-obvious semantics, so aren't +/// currently on a path to potential stabilization. +impl ControlFlow { + /// Creates a `ControlFlow` from any type implementing `Try`. + #[inline] + pub(crate) fn from_try(r: R) -> Self { + match R::branch(r) { + ControlFlow::Continue(v) => ControlFlow::Continue(v), + ControlFlow::Break(v) => ControlFlow::Break(R::from_residual(v)), + } + } + + /// Converts a `ControlFlow` into any type implementing `Try`. + #[inline] + pub(crate) fn into_try(self) -> R { + match self { + ControlFlow::Continue(v) => R::from_output(v), + ControlFlow::Break(v) => v, + } + } +} diff --git a/CoqOfRust/core/ops/coroutine.rs b/CoqOfRust/core/ops/coroutine.rs new file mode 100644 index 000000000..c7d596d74 --- /dev/null +++ b/CoqOfRust/core/ops/coroutine.rs @@ -0,0 +1,140 @@ +use crate::pin::Pin; + +/// The result of a coroutine resumption. +/// +/// This enum is returned from the `Coroutine::resume` method and indicates the +/// possible return values of a coroutine. Currently this corresponds to either +/// a suspension point (`Yielded`) or a termination point (`Complete`). +#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] +#[lang = "coroutine_state"] +#[unstable(feature = "coroutine_trait", issue = "43122")] +pub enum CoroutineState { + /// The coroutine suspended with a value. + /// + /// This state indicates that a coroutine has been suspended, and typically + /// corresponds to a `yield` statement. The value provided in this variant + /// corresponds to the expression passed to `yield` and allows coroutines to + /// provide a value each time they yield. + Yielded(Y), + + /// The coroutine completed with a return value. + /// + /// This state indicates that a coroutine has finished execution with the + /// provided value. Once a coroutine has returned `Complete` it is + /// considered a programmer error to call `resume` again. + Complete(R), +} + +/// The trait implemented by builtin coroutine types. +/// +/// Coroutines are currently an +/// experimental language feature in Rust. Added in [RFC 2033] coroutines are +/// currently intended to primarily provide a building block for async/await +/// syntax but will likely extend to also providing an ergonomic definition for +/// iterators and other primitives. +/// +/// The syntax and semantics for coroutines is unstable and will require a +/// further RFC for stabilization. At this time, though, the syntax is +/// closure-like: +/// +/// ```rust +/// #![feature(coroutines)] +/// #![feature(coroutine_trait)] +/// #![feature(stmt_expr_attributes)] +/// +/// use std::ops::{Coroutine, CoroutineState}; +/// use std::pin::Pin; +/// +/// fn main() { +/// let mut coroutine = #[coroutine] || { +/// yield 1; +/// "foo" +/// }; +/// +/// match Pin::new(&mut coroutine).resume(()) { +/// CoroutineState::Yielded(1) => {} +/// _ => panic!("unexpected return from resume"), +/// } +/// match Pin::new(&mut coroutine).resume(()) { +/// CoroutineState::Complete("foo") => {} +/// _ => panic!("unexpected return from resume"), +/// } +/// } +/// ``` +/// +/// More documentation of coroutines can be found in the [unstable book]. +/// +/// [RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033 +/// [unstable book]: ../../unstable-book/language-features/coroutines.html +#[lang = "coroutine"] +#[unstable(feature = "coroutine_trait", issue = "43122")] +#[fundamental] +#[must_use = "coroutines are lazy and do nothing unless resumed"] +pub trait Coroutine { + /// The type of value this coroutine yields. + /// + /// This associated type corresponds to the `yield` expression and the + /// values which are allowed to be returned each time a coroutine yields. + /// For example an iterator-as-a-coroutine would likely have this type as + /// `T`, the type being iterated over. + #[lang = "coroutine_yield"] + type Yield; + + /// The type of value this coroutine returns. + /// + /// This corresponds to the type returned from a coroutine either with a + /// `return` statement or implicitly as the last expression of a coroutine + /// literal. For example futures would use this as `Result` as it + /// represents a completed future. + #[lang = "coroutine_return"] + type Return; + + /// Resumes the execution of this coroutine. + /// + /// This function will resume execution of the coroutine or start execution + /// if it hasn't already. This call will return back into the coroutine's + /// last suspension point, resuming execution from the latest `yield`. The + /// coroutine will continue executing until it either yields or returns, at + /// which point this function will return. + /// + /// # Return value + /// + /// The `CoroutineState` enum returned from this function indicates what + /// state the coroutine is in upon returning. If the `Yielded` variant is + /// returned then the coroutine has reached a suspension point and a value + /// has been yielded out. Coroutines in this state are available for + /// resumption at a later point. + /// + /// If `Complete` is returned then the coroutine has completely finished + /// with the value provided. It is invalid for the coroutine to be resumed + /// again. + /// + /// # Panics + /// + /// This function may panic if it is called after the `Complete` variant has + /// been returned previously. While coroutine literals in the language are + /// guaranteed to panic on resuming after `Complete`, this is not guaranteed + /// for all implementations of the `Coroutine` trait. + #[lang = "coroutine_resume"] + fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState; +} + +#[unstable(feature = "coroutine_trait", issue = "43122")] +impl, R> Coroutine for Pin<&mut G> { + type Yield = G::Yield; + type Return = G::Return; + + fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState { + G::resume((*self).as_mut(), arg) + } +} + +#[unstable(feature = "coroutine_trait", issue = "43122")] +impl + Unpin, R> Coroutine for &mut G { + type Yield = G::Yield; + type Return = G::Return; + + fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState { + G::resume(Pin::new(&mut *self), arg) + } +} diff --git a/CoqOfRust/core/ops/deref.rs b/CoqOfRust/core/ops/deref.rs new file mode 100644 index 000000000..c36d55fe2 --- /dev/null +++ b/CoqOfRust/core/ops/deref.rs @@ -0,0 +1,444 @@ +/// Used for immutable dereferencing operations, like `*v`. +/// +/// In addition to being used for explicit dereferencing operations with the +/// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly +/// by the compiler in many circumstances. This mechanism is called +/// ["`Deref` coercion"][coercion]. In mutable contexts, [`DerefMut`] is used and +/// mutable deref coercion similarly occurs. +/// +/// **Warning:** Deref coercion is a powerful language feature which has +/// far-reaching implications for every type that implements `Deref`. The +/// compiler will silently insert calls to `Deref::deref`. For this reason, one +/// should be careful about implementing `Deref` and only do so when deref +/// coercion is desirable. See [below][implementing] for advice on when this is +/// typically desirable or undesirable. +/// +/// Types that implement `Deref` or `DerefMut` are often called "smart +/// pointers" and the mechanism of deref coercion has been specifically designed +/// to facilitate the pointer-like behavior that name suggests. Often, the +/// purpose of a "smart pointer" type is to change the ownership semantics +/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the +/// storage semantics of a contained value (for example, [`Box`][box]). +/// +/// # Deref coercion +/// +/// If `T` implements `Deref`, and `v` is a value of type `T`, then: +/// +/// * In immutable contexts, `*v` (where `T` is neither a reference nor a raw +/// pointer) is equivalent to `*Deref::deref(&v)`. +/// * Values of type `&T` are coerced to values of type `&U` +/// * `T` implicitly implements all the methods of the type `U` which take the +/// `&self` receiver. +/// +/// For more details, visit [the chapter in *The Rust Programming Language*][book] +/// as well as the reference sections on [the dereference operator][ref-deref-op], +/// [method resolution], and [type coercions]. +/// +/// # When to implement `Deref` or `DerefMut` +/// +/// The same advice applies to both deref traits. In general, deref traits +/// **should** be implemented if: +/// +/// 1. a value of the type transparently behaves like a value of the target +/// type; +/// 1. the implementation of the deref function is cheap; and +/// 1. users of the type will not be surprised by any deref coercion behavior. +/// +/// In general, deref traits **should not** be implemented if: +/// +/// 1. the deref implementations could fail unexpectedly; or +/// 1. the type has methods that are likely to collide with methods on the +/// target type; or +/// 1. committing to deref coercion as part of the public API is not desirable. +/// +/// Note that there's a large difference between implementing deref traits +/// generically over many target types, and doing so only for specific target +/// types. +/// +/// Generic implementations, such as for [`Box`][box] (which is generic over +/// every type and dereferences to `T`) should be careful to provide few or no +/// methods, since the target type is unknown and therefore every method could +/// collide with one on the target type, causing confusion for users. +/// `impl Box` has no methods (though several associated functions), +/// partly for this reason. +/// +/// Specific implementations, such as for [`String`][string] (whose `Deref` +/// implementation has `Target = str`) can have many methods, since avoiding +/// collision is much easier. `String` and `str` both have many methods, and +/// `String` additionally behaves as if it has every method of `str` because of +/// deref coercion. The implementing type may also be generic while the +/// implementation is still specific in this sense; for example, [`Vec`][vec] +/// dereferences to `[T]`, so methods of `T` are not applicable. +/// +/// Consider also that deref coercion means that deref traits are a much larger +/// part of a type's public API than any other trait as it is implicitly called +/// by the compiler. Therefore, it is advisable to consider whether this is +/// something you are comfortable supporting as a public API. +/// +/// The [`AsRef`] and [`Borrow`][core::borrow::Borrow] traits have very similar +/// signatures to `Deref`. It may be desirable to implement either or both of +/// these, whether in addition to or rather than deref traits. See their +/// documentation for details. +/// +/// # Fallibility +/// +/// **This trait's method should never unexpectedly fail**. Deref coercion means +/// the compiler will often insert calls to `Deref::deref` implicitly. Failure +/// during dereferencing can be extremely confusing when `Deref` is invoked +/// implicitly. In the majority of uses it should be infallible, though it may +/// be acceptable to panic if the type is misused through programmer error, for +/// example. +/// +/// However, infallibility is not enforced and therefore not guaranteed. +/// As such, `unsafe` code should not rely on infallibility in general for +/// soundness. +/// +/// [book]: ../../book/ch15-02-deref.html +/// [coercion]: #deref-coercion +/// [implementing]: #when-to-implement-deref-or-derefmut +/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator +/// [method resolution]: ../../reference/expressions/method-call-expr.html +/// [type coercions]: ../../reference/type-coercions.html +/// [box]: ../../alloc/boxed/struct.Box.html +/// [string]: ../../alloc/string/struct.String.html +/// [vec]: ../../alloc/vec/struct.Vec.html +/// [rc]: ../../alloc/rc/struct.Rc.html +/// [cow]: ../../alloc/borrow/enum.Cow.html +/// +/// # Examples +/// +/// A struct with a single field which is accessible by dereferencing the +/// struct. +/// +/// ``` +/// use std::ops::Deref; +/// +/// struct DerefExample { +/// value: T +/// } +/// +/// impl Deref for DerefExample { +/// type Target = T; +/// +/// fn deref(&self) -> &Self::Target { +/// &self.value +/// } +/// } +/// +/// let x = DerefExample { value: 'a' }; +/// assert_eq!('a', *x); +/// ``` +#[lang = "deref"] +#[doc(alias = "*")] +#[doc(alias = "&*")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Deref"] +#[cfg_attr(not(bootstrap), const_trait)] +pub trait Deref { + /// The resulting type after dereferencing. + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "deref_target"] + #[lang = "deref_target"] + type Target: ?Sized; + + /// Dereferences the value. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "deref_method"] + fn deref(&self) -> &Self::Target; +} + +#[cfg(bootstrap)] +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for &T { + type Target = T; + + #[rustc_diagnostic_item = "noop_method_deref"] + fn deref(&self) -> &T { + *self + } +} + +#[cfg(not(bootstrap))] +#[stable(feature = "rust1", since = "1.0.0")] +impl const Deref for &T { + type Target = T; + + #[rustc_diagnostic_item = "noop_method_deref"] + fn deref(&self) -> &T { + *self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl !DerefMut for &T {} + +#[cfg(bootstrap)] +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for &mut T { + type Target = T; + + fn deref(&self) -> &T { + *self + } +} + +#[cfg(not(bootstrap))] +#[stable(feature = "rust1", since = "1.0.0")] +impl const Deref for &mut T { + type Target = T; + + fn deref(&self) -> &T { + *self + } +} + +/// Used for mutable dereferencing operations, like in `*v = 1;`. +/// +/// In addition to being used for explicit dereferencing operations with the +/// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly +/// by the compiler in many circumstances. This mechanism is called +/// ["mutable deref coercion"][coercion]. In immutable contexts, [`Deref`] is used. +/// +/// **Warning:** Deref coercion is a powerful language feature which has +/// far-reaching implications for every type that implements `DerefMut`. The +/// compiler will silently insert calls to `DerefMut::deref_mut`. For this +/// reason, one should be careful about implementing `DerefMut` and only do so +/// when mutable deref coercion is desirable. See [the `Deref` docs][implementing] +/// for advice on when this is typically desirable or undesirable. +/// +/// Types that implement `DerefMut` or `Deref` are often called "smart +/// pointers" and the mechanism of deref coercion has been specifically designed +/// to facilitate the pointer-like behavior that name suggests. Often, the +/// purpose of a "smart pointer" type is to change the ownership semantics +/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the +/// storage semantics of a contained value (for example, [`Box`][box]). +/// +/// # Mutable deref coercion +/// +/// If `T` implements `DerefMut`, and `v` is a value of type `T`, +/// then: +/// +/// * In mutable contexts, `*v` (where `T` is neither a reference nor a raw pointer) +/// is equivalent to `*DerefMut::deref_mut(&mut v)`. +/// * Values of type `&mut T` are coerced to values of type `&mut U` +/// * `T` implicitly implements all the (mutable) methods of the type `U`. +/// +/// For more details, visit [the chapter in *The Rust Programming Language*][book] +/// as well as the reference sections on [the dereference operator][ref-deref-op], +/// [method resolution] and [type coercions]. +/// +/// # Fallibility +/// +/// **This trait's method should never unexpectedly fail**. Deref coercion means +/// the compiler will often insert calls to `DerefMut::deref_mut` implicitly. +/// Failure during dereferencing can be extremely confusing when `DerefMut` is +/// invoked implicitly. In the majority of uses it should be infallible, though +/// it may be acceptable to panic if the type is misused through programmer +/// error, for example. +/// +/// However, infallibility is not enforced and therefore not guaranteed. +/// As such, `unsafe` code should not rely on infallibility in general for +/// soundness. +/// +/// [book]: ../../book/ch15-02-deref.html +/// [coercion]: #mutable-deref-coercion +/// [implementing]: Deref#when-to-implement-deref-or-derefmut +/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator +/// [method resolution]: ../../reference/expressions/method-call-expr.html +/// [type coercions]: ../../reference/type-coercions.html +/// [box]: ../../alloc/boxed/struct.Box.html +/// [string]: ../../alloc/string/struct.String.html +/// [rc]: ../../alloc/rc/struct.Rc.html +/// [cow]: ../../alloc/borrow/enum.Cow.html +/// +/// # Examples +/// +/// A struct with a single field which is modifiable by dereferencing the +/// struct. +/// +/// ``` +/// use std::ops::{Deref, DerefMut}; +/// +/// struct DerefMutExample { +/// value: T +/// } +/// +/// impl Deref for DerefMutExample { +/// type Target = T; +/// +/// fn deref(&self) -> &Self::Target { +/// &self.value +/// } +/// } +/// +/// impl DerefMut for DerefMutExample { +/// fn deref_mut(&mut self) -> &mut Self::Target { +/// &mut self.value +/// } +/// } +/// +/// let mut x = DerefMutExample { value: 'a' }; +/// *x = 'b'; +/// assert_eq!('b', x.value); +/// ``` +#[cfg(not(bootstrap))] +#[lang = "deref_mut"] +#[doc(alias = "*")] +#[stable(feature = "rust1", since = "1.0.0")] +#[const_trait] +pub trait DerefMut: ~const Deref { + /// Mutably dereferences the value. + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "deref_mut_method"] + fn deref_mut(&mut self) -> &mut Self::Target; +} + +/// Bootstrap +#[lang = "deref_mut"] +#[doc(alias = "*")] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(bootstrap)] +pub trait DerefMut: Deref { + /// Mutably dereferences the value. + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "deref_mut_method"] + fn deref_mut(&mut self) -> &mut Self::Target; +} + +#[cfg(bootstrap)] +#[stable(feature = "rust1", since = "1.0.0")] +impl DerefMut for &mut T { + fn deref_mut(&mut self) -> &mut T { + *self + } +} + +#[cfg(not(bootstrap))] +#[stable(feature = "rust1", since = "1.0.0")] +impl const DerefMut for &mut T { + fn deref_mut(&mut self) -> &mut T { + *self + } +} + +/// Perma-unstable marker trait. Indicates that the type has a well-behaved [`Deref`] +/// (and, if applicable, [`DerefMut`]) implementation. This is relied on for soundness +/// of deref patterns. +/// +/// FIXME(deref_patterns): The precise semantics are undecided; the rough idea is that +/// successive calls to `deref`/`deref_mut` without intermediate mutation should be +/// idempotent, in the sense that they return the same value as far as pattern-matching +/// is concerned. Calls to `deref`/`deref_mut` must leave the pointer itself likewise +/// unchanged. +#[unstable(feature = "deref_pure_trait", issue = "87121")] +#[lang = "deref_pure"] +pub unsafe trait DerefPure {} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for &T {} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for &mut T {} + +/// Indicates that a struct can be used as a method receiver. +/// That is, a type can use this type as a type of `self`, like this: +/// ```compile_fail +/// # // This is currently compile_fail because the compiler-side parts +/// # // of arbitrary_self_types are not implemented +/// use std::ops::Receiver; +/// +/// struct SmartPointer(T); +/// +/// impl Receiver for SmartPointer { +/// type Target = T; +/// } +/// +/// struct MyContainedType; +/// +/// impl MyContainedType { +/// fn method(self: SmartPointer) { +/// // ... +/// } +/// } +/// +/// fn main() { +/// let ptr = SmartPointer(MyContainedType); +/// ptr.method(); +/// } +/// ``` +/// This trait is blanket implemented for any type which implements +/// [`Deref`], which includes stdlib pointer types like `Box`,`Rc`, `&T`, +/// and `Pin

`. For that reason, it's relatively rare to need to +/// implement this directly. You'll typically do this only if you need +/// to implement a smart pointer type which can't implement [`Deref`]; perhaps +/// because you're interfacing with another programming language and can't +/// guarantee that references comply with Rust's aliasing rules. +/// +/// When looking for method candidates, Rust will explore a chain of possible +/// `Receiver`s, so for example each of the following methods work: +/// ``` +/// use std::boxed::Box; +/// use std::rc::Rc; +/// +/// // Both `Box` and `Rc` (indirectly) implement Receiver +/// +/// struct MyContainedType; +/// +/// fn main() { +/// let t = Rc::new(Box::new(MyContainedType)); +/// t.method_a(); +/// t.method_b(); +/// t.method_c(); +/// } +/// +/// impl MyContainedType { +/// fn method_a(&self) { +/// +/// } +/// fn method_b(self: &Box) { +/// +/// } +/// fn method_c(self: &Rc>) { +/// +/// } +/// } +/// ``` +#[lang = "receiver"] +#[unstable(feature = "arbitrary_self_types", issue = "44874")] +pub trait Receiver { + /// The target type on which the method may be called. + #[rustc_diagnostic_item = "receiver_target"] + #[lang = "receiver_target"] + #[unstable(feature = "arbitrary_self_types", issue = "44874")] + type Target: ?Sized; +} + +#[unstable(feature = "arbitrary_self_types", issue = "44874")] +impl Receiver for P +where + P: Deref, +{ + type Target = T; +} + +/// Indicates that a struct can be used as a method receiver, without the +/// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box`, +/// `Rc`, `&T`, and `Pin

`. +/// +/// This trait will shortly be removed and replaced with a more generic +/// facility based around the current "arbitrary self types" unstable feature. +/// That new facility will use the replacement trait above called `Receiver` +/// which is why this is now named `LegacyReceiver`. +#[lang = "legacy_receiver"] +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +#[doc(hidden)] +pub trait LegacyReceiver { + // Empty. +} + +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +impl LegacyReceiver for &T {} + +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +impl LegacyReceiver for &mut T {} diff --git a/CoqOfRust/core/ops/drop.rs b/CoqOfRust/core/ops/drop.rs new file mode 100644 index 000000000..f3314364e --- /dev/null +++ b/CoqOfRust/core/ops/drop.rs @@ -0,0 +1,248 @@ +/// Custom code within the destructor. +/// +/// When a value is no longer needed, Rust will run a "destructor" on that value. +/// The most common way that a value is no longer needed is when it goes out of +/// scope. Destructors may still run in other circumstances, but we're going to +/// focus on scope for the examples here. To learn about some of those other cases, +/// please see [the reference] section on destructors. +/// +/// [the reference]: https://doc.rust-lang.org/reference/destructors.html +/// +/// This destructor consists of two components: +/// - A call to `Drop::drop` for that value, if this special `Drop` trait is implemented for its type. +/// - The automatically generated "drop glue" which recursively calls the destructors +/// of all the fields of this value. +/// +/// As Rust automatically calls the destructors of all contained fields, +/// you don't have to implement `Drop` in most cases. But there are some cases where +/// it is useful, for example for types which directly manage a resource. +/// That resource may be memory, it may be a file descriptor, it may be a network socket. +/// Once a value of that type is no longer going to be used, it should "clean up" its +/// resource by freeing the memory or closing the file or socket. This is +/// the job of a destructor, and therefore the job of `Drop::drop`. +/// +/// ## Examples +/// +/// To see destructors in action, let's take a look at the following program: +/// +/// ```rust +/// struct HasDrop; +/// +/// impl Drop for HasDrop { +/// fn drop(&mut self) { +/// println!("Dropping HasDrop!"); +/// } +/// } +/// +/// struct HasTwoDrops { +/// one: HasDrop, +/// two: HasDrop, +/// } +/// +/// impl Drop for HasTwoDrops { +/// fn drop(&mut self) { +/// println!("Dropping HasTwoDrops!"); +/// } +/// } +/// +/// fn main() { +/// let _x = HasTwoDrops { one: HasDrop, two: HasDrop }; +/// println!("Running!"); +/// } +/// ``` +/// +/// Rust will first call `Drop::drop` for `_x` and then for both `_x.one` and `_x.two`, +/// meaning that running this will print +/// +/// ```text +/// Running! +/// Dropping HasTwoDrops! +/// Dropping HasDrop! +/// Dropping HasDrop! +/// ``` +/// +/// Even if we remove the implementation of `Drop` for `HasTwoDrop`, the destructors of its fields are still called. +/// This would result in +/// +/// ```test +/// Running! +/// Dropping HasDrop! +/// Dropping HasDrop! +/// ``` +/// +/// ## You cannot call `Drop::drop` yourself +/// +/// Because `Drop::drop` is used to clean up a value, it may be dangerous to use this value after +/// the method has been called. As `Drop::drop` does not take ownership of its input, +/// Rust prevents misuse by not allowing you to call `Drop::drop` directly. +/// +/// In other words, if you tried to explicitly call `Drop::drop` in the above example, you'd get a compiler error. +/// +/// If you'd like to explicitly call the destructor of a value, [`mem::drop`] can be used instead. +/// +/// [`mem::drop`]: drop +/// +/// ## Drop order +/// +/// Which of our two `HasDrop` drops first, though? For structs, it's the same +/// order that they're declared: first `one`, then `two`. If you'd like to try +/// this yourself, you can modify `HasDrop` above to contain some data, like an +/// integer, and then use it in the `println!` inside of `Drop`. This behavior is +/// guaranteed by the language. +/// +/// Unlike for structs, local variables are dropped in reverse order: +/// +/// ```rust +/// struct Foo; +/// +/// impl Drop for Foo { +/// fn drop(&mut self) { +/// println!("Dropping Foo!") +/// } +/// } +/// +/// struct Bar; +/// +/// impl Drop for Bar { +/// fn drop(&mut self) { +/// println!("Dropping Bar!") +/// } +/// } +/// +/// fn main() { +/// let _foo = Foo; +/// let _bar = Bar; +/// } +/// ``` +/// +/// This will print +/// +/// ```text +/// Dropping Bar! +/// Dropping Foo! +/// ``` +/// +/// Please see [the reference] for the full rules. +/// +/// [the reference]: https://doc.rust-lang.org/reference/destructors.html +/// +/// ## `Copy` and `Drop` are exclusive +/// +/// You cannot implement both [`Copy`] and `Drop` on the same type. Types that +/// are `Copy` get implicitly duplicated by the compiler, making it very +/// hard to predict when, and how often destructors will be executed. As such, +/// these types cannot have destructors. +/// +/// ## Drop check +/// +/// Dropping interacts with the borrow checker in subtle ways: when a type `T` is being implicitly +/// dropped as some variable of this type goes out of scope, the borrow checker needs to ensure that +/// calling `T`'s destructor at this moment is safe. In particular, it also needs to be safe to +/// recursively drop all the fields of `T`. For example, it is crucial that code like the following +/// is being rejected: +/// +/// ```compile_fail,E0597 +/// use std::cell::Cell; +/// +/// struct S<'a>(Cell>>, Box); +/// impl Drop for S<'_> { +/// fn drop(&mut self) { +/// if let Some(r) = self.0.get() { +/// // Print the contents of the `Box` in `r`. +/// println!("{}", r.1); +/// } +/// } +/// } +/// +/// fn main() { +/// // Set up two `S` that point to each other. +/// let s1 = S(Cell::new(None), Box::new(42)); +/// let s2 = S(Cell::new(Some(&s1)), Box::new(42)); +/// s1.0.set(Some(&s2)); +/// // Now they both get dropped. But whichever is the 2nd one +/// // to be dropped will access the `Box` in the first one, +/// // which is a use-after-free! +/// } +/// ``` +/// +/// The Nomicon discusses the need for [drop check in more detail][drop check]. +/// +/// To reject such code, the "drop check" analysis determines which types and lifetimes need to +/// still be live when `T` gets dropped. The exact details of this analysis are not yet +/// stably guaranteed and **subject to change**. Currently, the analysis works as follows: +/// - If `T` has no drop glue, then trivially nothing is required to be live. This is the case if +/// neither `T` nor any of its (recursive) fields have a destructor (`impl Drop`). [`PhantomData`], +/// arrays of length 0 and [`ManuallyDrop`] are considered to never have a destructor, no matter +/// their field type. +/// - If `T` has drop glue, then, for all types `U` that are *owned* by any field of `T`, +/// recursively add the types and lifetimes that need to be live when `U` gets dropped. The set of +/// owned types is determined by recursively traversing `T`: +/// - Recursively descend through `PhantomData`, `Box`, tuples, and arrays (excluding arrays of +/// length 0). +/// - Stop at reference and raw pointer types as well as function pointers and function items; +/// they do not own anything. +/// - Stop at non-composite types (type parameters that remain generic in the current context and +/// base types such as integers and `bool`); these types are owned. +/// - When hitting an ADT with `impl Drop`, stop there; this type is owned. +/// - When hitting an ADT without `impl Drop`, recursively descend to its fields. (For an `enum`, +/// consider all fields of all variants.) +/// - Furthermore, if `T` implements `Drop`, then all generic (lifetime and type) parameters of `T` +/// must be live. +/// +/// In the above example, the last clause implies that `'a` must be live when `S<'a>` is dropped, +/// and hence the example is rejected. If we remove the `impl Drop`, the liveness requirement +/// disappears and the example is accepted. +/// +/// There exists an unstable way for a type to opt-out of the last clause; this is called "drop +/// check eyepatch" or `may_dangle`. For more details on this nightly-only feature, see the +/// [discussion in the Nomicon][nomicon]. +/// +/// [`ManuallyDrop`]: crate::mem::ManuallyDrop +/// [`PhantomData`]: crate::marker::PhantomData +/// [drop check]: ../../nomicon/dropck.html +/// [nomicon]: ../../nomicon/phantom-data.html#an-exception-the-special-case-of-the-standard-library-and-its-unstable-may_dangle +#[lang = "drop"] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(bootstrap), const_trait)] +pub trait Drop { + /// Executes the destructor for this type. + /// + /// This method is called implicitly when the value goes out of scope, + /// and cannot be called explicitly (this is compiler error [E0040]). + /// However, the [`mem::drop`] function in the prelude can be + /// used to call the argument's `Drop` implementation. + /// + /// When this method has been called, `self` has not yet been deallocated. + /// That only happens after the method is over. + /// If this wasn't the case, `self` would be a dangling reference. + /// + /// # Panics + /// + /// Implementations should generally avoid [`panic!`]ing, because `drop()` may itself be called + /// during unwinding due to a panic, and if the `drop()` panics in that situation (a “double + /// panic”), this will likely abort the program. It is possible to check [`panicking()`] first, + /// which may be desirable for a `Drop` implementation that is reporting a bug of the kind + /// “you didn't finish using this before it was dropped”; but most types should simply clean up + /// their owned allocations or other resources and return normally from `drop()`, regardless of + /// what state they are in. + /// + /// Note that even if this panics, the value is considered to be dropped; + /// you must not cause `drop` to be called again. This is normally automatically + /// handled by the compiler, but when using unsafe code, can sometimes occur + /// unintentionally, particularly when using [`ptr::drop_in_place`]. + /// + /// [E0040]: ../../error_codes/E0040.html + /// [`panic!`]: crate::panic! + /// [`panicking()`]: ../../std/thread/fn.panicking.html + /// [`mem::drop`]: drop + /// [`ptr::drop_in_place`]: crate::ptr::drop_in_place + #[stable(feature = "rust1", since = "1.0.0")] + fn drop(&mut self); +} + +/// Fallback function to call surface level `Drop::drop` function +#[allow(drop_bounds)] +#[lang = "fallback_surface_drop"] +pub(crate) fn fallback_surface_drop(x: &mut T) { + ::drop(x) +} diff --git a/CoqOfRust/core/ops/function.rs b/CoqOfRust/core/ops/function.rs new file mode 100644 index 000000000..e9014458b --- /dev/null +++ b/CoqOfRust/core/ops/function.rs @@ -0,0 +1,308 @@ +use crate::marker::Tuple; + +/// The version of the call operator that takes an immutable receiver. +/// +/// Instances of `Fn` can be called repeatedly without mutating state. +/// +/// *This trait (`Fn`) is not to be confused with [function pointers] +/// (`fn`).* +/// +/// `Fn` is implemented automatically by closures which only take immutable +/// references to captured variables or don't capture anything at all, as well +/// as (safe) [function pointers] (with some caveats, see their documentation +/// for more details). Additionally, for any type `F` that implements `Fn`, `&F` +/// implements `Fn`, too. +/// +/// Since both [`FnMut`] and [`FnOnce`] are supertraits of `Fn`, any +/// instance of `Fn` can be used as a parameter where a [`FnMut`] or [`FnOnce`] +/// is expected. +/// +/// Use `Fn` as a bound when you want to accept a parameter of function-like +/// type and need to call it repeatedly and without mutating state (e.g., when +/// calling it concurrently). If you do not need such strict requirements, use +/// [`FnMut`] or [`FnOnce`] as bounds. +/// +/// See the [chapter on closures in *The Rust Programming Language*][book] for +/// some more information on this topic. +/// +/// Also of note is the special syntax for `Fn` traits (e.g. +/// `Fn(usize, bool) -> usize`). Those interested in the technical details of +/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. +/// +/// [book]: ../../book/ch13-01-closures.html +/// [function pointers]: fn +/// [nomicon]: ../../nomicon/hrtb.html +/// +/// # Examples +/// +/// ## Calling a closure +/// +/// ``` +/// let square = |x| x * x; +/// assert_eq!(square(5), 25); +/// ``` +/// +/// ## Using a `Fn` parameter +/// +/// ``` +/// fn call_with_one(func: F) -> usize +/// where F: Fn(usize) -> usize { +/// func(1) +/// } +/// +/// let double = |x| x * 2; +/// assert_eq!(call_with_one(double), 2); +/// ``` +#[lang = "fn"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_paren_sugar] +#[rustc_on_unimplemented( + on( + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" + ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), + message = "expected a `{Trait}` closure, found `{Self}`", + label = "expected an `{Trait}` closure, found `{Self}`" +)] +#[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use = "closures are lazy and do nothing unless called"] +// FIXME(const_trait_impl) #[const_trait] +pub trait Fn: FnMut { + /// Performs the call operation. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call(&self, args: Args) -> Self::Output; +} + +/// The version of the call operator that takes a mutable receiver. +/// +/// Instances of `FnMut` can be called repeatedly and may mutate state. +/// +/// `FnMut` is implemented automatically by closures which take mutable +/// references to captured variables, as well as all types that implement +/// [`Fn`], e.g., (safe) [function pointers] (since `FnMut` is a supertrait of +/// [`Fn`]). Additionally, for any type `F` that implements `FnMut`, `&mut F` +/// implements `FnMut`, too. +/// +/// Since [`FnOnce`] is a supertrait of `FnMut`, any instance of `FnMut` can be +/// used where a [`FnOnce`] is expected, and since [`Fn`] is a subtrait of +/// `FnMut`, any instance of [`Fn`] can be used where `FnMut` is expected. +/// +/// Use `FnMut` as a bound when you want to accept a parameter of function-like +/// type and need to call it repeatedly, while allowing it to mutate state. +/// If you don't want the parameter to mutate state, use [`Fn`] as a +/// bound; if you don't need to call it repeatedly, use [`FnOnce`]. +/// +/// See the [chapter on closures in *The Rust Programming Language*][book] for +/// some more information on this topic. +/// +/// Also of note is the special syntax for `Fn` traits (e.g. +/// `Fn(usize, bool) -> usize`). Those interested in the technical details of +/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. +/// +/// [book]: ../../book/ch13-01-closures.html +/// [function pointers]: fn +/// [nomicon]: ../../nomicon/hrtb.html +/// +/// # Examples +/// +/// ## Calling a mutably capturing closure +/// +/// ``` +/// let mut x = 5; +/// { +/// let mut square_x = || x *= x; +/// square_x(); +/// } +/// assert_eq!(x, 25); +/// ``` +/// +/// ## Using a `FnMut` parameter +/// +/// ``` +/// fn do_twice(mut func: F) +/// where F: FnMut() +/// { +/// func(); +/// func(); +/// } +/// +/// let mut x: usize = 1; +/// { +/// let add_two_to_x = || x += 2; +/// do_twice(add_two_to_x); +/// } +/// +/// assert_eq!(x, 5); +/// ``` +#[lang = "fn_mut"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_paren_sugar] +#[rustc_on_unimplemented( + on( + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" + ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), + message = "expected a `{Trait}` closure, found `{Self}`", + label = "expected an `{Trait}` closure, found `{Self}`" +)] +#[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use = "closures are lazy and do nothing unless called"] +// FIXME(const_trait_impl) #[const_trait] +pub trait FnMut: FnOnce { + /// Performs the call operation. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + +/// The version of the call operator that takes a by-value receiver. +/// +/// Instances of `FnOnce` can be called, but might not be callable multiple +/// times. Because of this, if the only thing known about a type is that it +/// implements `FnOnce`, it can only be called once. +/// +/// `FnOnce` is implemented automatically by closures that might consume captured +/// variables, as well as all types that implement [`FnMut`], e.g., (safe) +/// [function pointers] (since `FnOnce` is a supertrait of [`FnMut`]). +/// +/// Since both [`Fn`] and [`FnMut`] are subtraits of `FnOnce`, any instance of +/// [`Fn`] or [`FnMut`] can be used where a `FnOnce` is expected. +/// +/// Use `FnOnce` as a bound when you want to accept a parameter of function-like +/// type and only need to call it once. If you need to call the parameter +/// repeatedly, use [`FnMut`] as a bound; if you also need it to not mutate +/// state, use [`Fn`]. +/// +/// See the [chapter on closures in *The Rust Programming Language*][book] for +/// some more information on this topic. +/// +/// Also of note is the special syntax for `Fn` traits (e.g. +/// `Fn(usize, bool) -> usize`). Those interested in the technical details of +/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. +/// +/// [book]: ../../book/ch13-01-closures.html +/// [function pointers]: fn +/// [nomicon]: ../../nomicon/hrtb.html +/// +/// # Examples +/// +/// ## Using a `FnOnce` parameter +/// +/// ``` +/// fn consume_with_relish(func: F) +/// where F: FnOnce() -> String +/// { +/// // `func` consumes its captured variables, so it cannot be run more +/// // than once. +/// println!("Consumed: {}", func()); +/// +/// println!("Delicious!"); +/// +/// // Attempting to invoke `func()` again will throw a `use of moved +/// // value` error for `func`. +/// } +/// +/// let x = String::from("x"); +/// let consume_and_return_x = move || x; +/// consume_with_relish(consume_and_return_x); +/// +/// // `consume_and_return_x` can no longer be invoked at this point +/// ``` +#[lang = "fn_once"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_paren_sugar] +#[rustc_on_unimplemented( + on( + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" + ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), + message = "expected a `{Trait}` closure, found `{Self}`", + label = "expected an `{Trait}` closure, found `{Self}`" +)] +#[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use = "closures are lazy and do nothing unless called"] +// FIXME(const_trait_impl) #[const_trait] +pub trait FnOnce { + /// The returned type after the call operator is used. + #[lang = "fn_once_output"] + #[stable(feature = "fn_once_output", since = "1.12.0")] + type Output; + + /// Performs the call operation. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +mod impls { + use crate::marker::Tuple; + + #[stable(feature = "rust1", since = "1.0.0")] + impl Fn for &F + where + F: Fn, + { + extern "rust-call" fn call(&self, args: A) -> F::Output { + (**self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl FnMut for &F + where + F: Fn, + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (**self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl FnOnce for &F + where + F: Fn, + { + type Output = F::Output; + + extern "rust-call" fn call_once(self, args: A) -> F::Output { + (*self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl FnMut for &mut F + where + F: FnMut, + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (*self).call_mut(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl FnOnce for &mut F + where + F: FnMut, + { + type Output = F::Output; + extern "rust-call" fn call_once(self, args: A) -> F::Output { + (*self).call_mut(args) + } + } +} diff --git a/CoqOfRust/core/ops/index.rs b/CoqOfRust/core/ops/index.rs new file mode 100644 index 000000000..37d9a28fb --- /dev/null +++ b/CoqOfRust/core/ops/index.rs @@ -0,0 +1,176 @@ +/// Used for indexing operations (`container[index]`) in immutable contexts. +/// +/// `container[index]` is actually syntactic sugar for `*container.index(index)`, +/// but only when used as an immutable value. If a mutable value is requested, +/// [`IndexMut`] is used instead. This allows nice things such as +/// `let value = v[index]` if the type of `value` implements [`Copy`]. +/// +/// # Examples +/// +/// The following example implements `Index` on a read-only `NucleotideCount` +/// container, enabling individual counts to be retrieved with index syntax. +/// +/// ``` +/// use std::ops::Index; +/// +/// enum Nucleotide { +/// A, +/// C, +/// G, +/// T, +/// } +/// +/// struct NucleotideCount { +/// a: usize, +/// c: usize, +/// g: usize, +/// t: usize, +/// } +/// +/// impl Index for NucleotideCount { +/// type Output = usize; +/// +/// fn index(&self, nucleotide: Nucleotide) -> &Self::Output { +/// match nucleotide { +/// Nucleotide::A => &self.a, +/// Nucleotide::C => &self.c, +/// Nucleotide::G => &self.g, +/// Nucleotide::T => &self.t, +/// } +/// } +/// } +/// +/// let nucleotide_count = NucleotideCount {a: 14, c: 9, g: 10, t: 12}; +/// assert_eq!(nucleotide_count[Nucleotide::A], 14); +/// assert_eq!(nucleotide_count[Nucleotide::C], 9); +/// assert_eq!(nucleotide_count[Nucleotide::G], 10); +/// assert_eq!(nucleotide_count[Nucleotide::T], 12); +/// ``` +#[lang = "index"] +#[diagnostic::on_unimplemented( + message = "the type `{Self}` cannot be indexed by `{Idx}`", + label = "`{Self}` cannot be indexed by `{Idx}`" +)] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "]")] +#[doc(alias = "[")] +#[doc(alias = "[]")] +pub trait Index { + /// The returned type after indexing. + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "IndexOutput"] + type Output: ?Sized; + + /// Performs the indexing (`container[index]`) operation. + /// + /// # Panics + /// + /// May panic if the index is out of bounds. + #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] + fn index(&self, index: Idx) -> &Self::Output; +} + +/// Used for indexing operations (`container[index]`) in mutable contexts. +/// +/// `container[index]` is actually syntactic sugar for +/// `*container.index_mut(index)`, but only when used as a mutable value. If +/// an immutable value is requested, the [`Index`] trait is used instead. This +/// allows nice things such as `v[index] = value`. +/// +/// # Examples +/// +/// A very simple implementation of a `Balance` struct that has two sides, where +/// each can be indexed mutably and immutably. +/// +/// ``` +/// use std::ops::{Index, IndexMut}; +/// +/// #[derive(Debug)] +/// enum Side { +/// Left, +/// Right, +/// } +/// +/// #[derive(Debug, PartialEq)] +/// enum Weight { +/// Kilogram(f32), +/// Pound(f32), +/// } +/// +/// struct Balance { +/// pub left: Weight, +/// pub right: Weight, +/// } +/// +/// impl Index for Balance { +/// type Output = Weight; +/// +/// fn index(&self, index: Side) -> &Self::Output { +/// println!("Accessing {index:?}-side of balance immutably"); +/// match index { +/// Side::Left => &self.left, +/// Side::Right => &self.right, +/// } +/// } +/// } +/// +/// impl IndexMut for Balance { +/// fn index_mut(&mut self, index: Side) -> &mut Self::Output { +/// println!("Accessing {index:?}-side of balance mutably"); +/// match index { +/// Side::Left => &mut self.left, +/// Side::Right => &mut self.right, +/// } +/// } +/// } +/// +/// let mut balance = Balance { +/// right: Weight::Kilogram(2.5), +/// left: Weight::Pound(1.5), +/// }; +/// +/// // In this case, `balance[Side::Right]` is sugar for +/// // `*balance.index(Side::Right)`, since we are only *reading* +/// // `balance[Side::Right]`, not writing it. +/// assert_eq!(balance[Side::Right], Weight::Kilogram(2.5)); +/// +/// // However, in this case `balance[Side::Left]` is sugar for +/// // `*balance.index_mut(Side::Left)`, since we are writing +/// // `balance[Side::Left]`. +/// balance[Side::Left] = Weight::Kilogram(3.0); +/// ``` +#[lang = "index_mut"] +#[rustc_on_unimplemented( + on( + _Self = "&str", + note = "you can use `.chars().nth()` or `.bytes().nth()` +see chapter in The Book " + ), + on( + _Self = "str", + note = "you can use `.chars().nth()` or `.bytes().nth()` +see chapter in The Book " + ), + on( + _Self = "alloc::string::String", + note = "you can use `.chars().nth()` or `.bytes().nth()` +see chapter in The Book " + ), + message = "the type `{Self}` cannot be mutably indexed by `{Idx}`", + label = "`{Self}` cannot be mutably indexed by `{Idx}`" +)] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "[")] +#[doc(alias = "]")] +#[doc(alias = "[]")] +pub trait IndexMut: Index { + /// Performs the mutable indexing (`container[index]`) operation. + /// + /// # Panics + /// + /// May panic if the index is out of bounds. + #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] + fn index_mut(&mut self, index: Idx) -> &mut Self::Output; +} diff --git a/CoqOfRust/core/ops/index_range.rs b/CoqOfRust/core/ops/index_range.rs new file mode 100644 index 000000000..dce3514a1 --- /dev/null +++ b/CoqOfRust/core/ops/index_range.rs @@ -0,0 +1,171 @@ +use crate::iter::{FusedIterator, TrustedLen}; +use crate::num::NonZero; +use crate::ub_checks; + +/// Like a `Range`, but with a safety invariant that `start <= end`. +/// +/// This means that `end - start` cannot overflow, allowing some μoptimizations. +/// +/// (Normal `Range` code needs to handle degenerate ranges like `10..0`, +/// which takes extra checks compared to only handling the canonical form.) +#[derive(Clone, Debug, PartialEq, Eq)] +pub(crate) struct IndexRange { + start: usize, + end: usize, +} + +impl IndexRange { + /// # Safety + /// - `start <= end` + #[inline] + pub const unsafe fn new_unchecked(start: usize, end: usize) -> Self { + ub_checks::assert_unsafe_precondition!( + check_library_ub, + "IndexRange::new_unchecked requires `start <= end`", + (start: usize = start, end: usize = end) => start <= end, + ); + IndexRange { start, end } + } + + #[inline] + pub const fn zero_to(end: usize) -> Self { + IndexRange { start: 0, end } + } + + #[inline] + pub const fn start(&self) -> usize { + self.start + } + + #[inline] + pub const fn end(&self) -> usize { + self.end + } + + #[inline] + pub const fn len(&self) -> usize { + // SAFETY: By invariant, this cannot wrap + // Using the intrinsic because a UB check here impedes LLVM optimization. (#131563) + unsafe { crate::intrinsics::unchecked_sub(self.end, self.start) } + } + + /// # Safety + /// - Can only be called when `start < end`, aka when `len > 0`. + #[inline] + unsafe fn next_unchecked(&mut self) -> usize { + debug_assert!(self.start < self.end); + + let value = self.start; + // SAFETY: The range isn't empty, so this cannot overflow + self.start = unsafe { value.unchecked_add(1) }; + value + } + + /// # Safety + /// - Can only be called when `start < end`, aka when `len > 0`. + #[inline] + unsafe fn next_back_unchecked(&mut self) -> usize { + debug_assert!(self.start < self.end); + + // SAFETY: The range isn't empty, so this cannot overflow + let value = unsafe { self.end.unchecked_sub(1) }; + self.end = value; + value + } + + /// Removes the first `n` items from this range, returning them as an `IndexRange`. + /// If there are fewer than `n`, then the whole range is returned and + /// `self` is left empty. + /// + /// This is designed to help implement `Iterator::advance_by`. + #[inline] + pub fn take_prefix(&mut self, n: usize) -> Self { + let mid = if n <= self.len() { + // SAFETY: We just checked that this will be between start and end, + // and thus the addition cannot overflow. + // Using the intrinsic avoids a superfluous UB check. + unsafe { crate::intrinsics::unchecked_add(self.start, n) } + } else { + self.end + }; + let prefix = Self { start: self.start, end: mid }; + self.start = mid; + prefix + } + + /// Removes the last `n` items from this range, returning them as an `IndexRange`. + /// If there are fewer than `n`, then the whole range is returned and + /// `self` is left empty. + /// + /// This is designed to help implement `Iterator::advance_back_by`. + #[inline] + pub fn take_suffix(&mut self, n: usize) -> Self { + let mid = if n <= self.len() { + // SAFETY: We just checked that this will be between start and end, + // and thus the subtraction cannot overflow. + // Using the intrinsic avoids a superfluous UB check. + unsafe { crate::intrinsics::unchecked_sub(self.end, n) } + } else { + self.start + }; + let suffix = Self { start: mid, end: self.end }; + self.end = mid; + suffix + } +} + +impl Iterator for IndexRange { + type Item = usize; + + #[inline] + fn next(&mut self) -> Option { + if self.len() > 0 { + // SAFETY: We just checked that the range is non-empty + unsafe { Some(self.next_unchecked()) } + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + let taken = self.take_prefix(n); + NonZero::new(n - taken.len()).map_or(Ok(()), Err) + } +} + +impl DoubleEndedIterator for IndexRange { + #[inline] + fn next_back(&mut self) -> Option { + if self.len() > 0 { + // SAFETY: We just checked that the range is non-empty + unsafe { Some(self.next_back_unchecked()) } + } else { + None + } + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + let taken = self.take_suffix(n); + NonZero::new(n - taken.len()).map_or(Ok(()), Err) + } +} + +impl ExactSizeIterator for IndexRange { + #[inline] + fn len(&self) -> usize { + self.len() + } +} + +// SAFETY: Because we only deal in `usize`, our `len` is always perfect. +unsafe impl TrustedLen for IndexRange {} + +impl FusedIterator for IndexRange {} diff --git a/CoqOfRust/core/ops/mod.rs b/CoqOfRust/core/ops/mod.rs new file mode 100644 index 000000000..40526f958 --- /dev/null +++ b/CoqOfRust/core/ops/mod.rs @@ -0,0 +1,201 @@ +//! Overloadable operators. +//! +//! Implementing these traits allows you to overload certain operators. +//! +//! Some of these traits are imported by the prelude, so they are available in +//! every Rust program. Only operators backed by traits can be overloaded. For +//! example, the addition operator (`+`) can be overloaded through the [`Add`] +//! trait, but since the assignment operator (`=`) has no backing trait, there +//! is no way of overloading its semantics. Additionally, this module does not +//! provide any mechanism to create new operators. If traitless overloading or +//! custom operators are required, you should look toward macros to extend +//! Rust's syntax. +//! +//! Implementations of operator traits should be unsurprising in their +//! respective contexts, keeping in mind their usual meanings and +//! [operator precedence]. For example, when implementing [`Mul`], the operation +//! should have some resemblance to multiplication (and share expected +//! properties like associativity). +//! +//! Note that the `&&` and `||` operators are currently not supported for +//! overloading. Due to their short circuiting nature, they require a different +//! design from traits for other operators like [`BitAnd`]. Designs for them are +//! under discussion. +//! +//! Many of the operators take their operands by value. In non-generic +//! contexts involving built-in types, this is usually not a problem. +//! However, using these operators in generic code, requires some +//! attention if values have to be reused as opposed to letting the operators +//! consume them. One option is to occasionally use [`clone`]. +//! Another option is to rely on the types involved providing additional +//! operator implementations for references. For example, for a user-defined +//! type `T` which is supposed to support addition, it is probably a good +//! idea to have both `T` and `&T` implement the traits [`Add`][`Add`] and +//! [`Add<&T>`][`Add`] so that generic code can be written without unnecessary +//! cloning. +//! +//! # Examples +//! +//! This example creates a `Point` struct that implements [`Add`] and [`Sub`], +//! and then demonstrates adding and subtracting two `Point`s. +//! +//! ```rust +//! use std::ops::{Add, Sub}; +//! +//! #[derive(Debug, Copy, Clone, PartialEq)] +//! struct Point { +//! x: i32, +//! y: i32, +//! } +//! +//! impl Add for Point { +//! type Output = Self; +//! +//! fn add(self, other: Self) -> Self { +//! Self {x: self.x + other.x, y: self.y + other.y} +//! } +//! } +//! +//! impl Sub for Point { +//! type Output = Self; +//! +//! fn sub(self, other: Self) -> Self { +//! Self {x: self.x - other.x, y: self.y - other.y} +//! } +//! } +//! +//! assert_eq!(Point {x: 3, y: 3}, Point {x: 1, y: 0} + Point {x: 2, y: 3}); +//! assert_eq!(Point {x: -1, y: -3}, Point {x: 1, y: 0} - Point {x: 2, y: 3}); +//! ``` +//! +//! See the documentation for each trait for an example implementation. +//! +//! The [`Fn`], [`FnMut`], and [`FnOnce`] traits are implemented by types that can be +//! invoked like functions. Note that [`Fn`] takes `&self`, [`FnMut`] takes `&mut +//! self` and [`FnOnce`] takes `self`. These correspond to the three kinds of +//! methods that can be invoked on an instance: call-by-reference, +//! call-by-mutable-reference, and call-by-value. The most common use of these +//! traits is to act as bounds to higher-level functions that take functions or +//! closures as arguments. +//! +//! Taking a [`Fn`] as a parameter: +//! +//! ```rust +//! fn call_with_one(func: F) -> usize +//! where F: Fn(usize) -> usize +//! { +//! func(1) +//! } +//! +//! let double = |x| x * 2; +//! assert_eq!(call_with_one(double), 2); +//! ``` +//! +//! Taking a [`FnMut`] as a parameter: +//! +//! ```rust +//! fn do_twice(mut func: F) +//! where F: FnMut() +//! { +//! func(); +//! func(); +//! } +//! +//! let mut x: usize = 1; +//! { +//! let add_two_to_x = || x += 2; +//! do_twice(add_two_to_x); +//! } +//! +//! assert_eq!(x, 5); +//! ``` +//! +//! Taking a [`FnOnce`] as a parameter: +//! +//! ```rust +//! fn consume_with_relish(func: F) +//! where F: FnOnce() -> String +//! { +//! // `func` consumes its captured variables, so it cannot be run more +//! // than once +//! println!("Consumed: {}", func()); +//! +//! println!("Delicious!"); +//! +//! // Attempting to invoke `func()` again will throw a `use of moved +//! // value` error for `func` +//! } +//! +//! let x = String::from("x"); +//! let consume_and_return_x = move || x; +//! consume_with_relish(consume_and_return_x); +//! +//! // `consume_and_return_x` can no longer be invoked at this point +//! ``` +//! +//! [`clone`]: Clone::clone +//! [operator precedence]: ../../reference/expressions.html#expression-precedence + +#![stable(feature = "rust1", since = "1.0.0")] + +mod arith; +mod async_function; +mod bit; +mod control_flow; +mod coroutine; +mod deref; +mod drop; +mod function; +mod index; +mod index_range; +mod range; +mod try_trait; +mod unsize; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::arith::{Add, Div, Mul, Neg, Rem, Sub}; +#[stable(feature = "op_assign_traits", since = "1.8.0")] +pub use self::arith::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign}; +#[unstable(feature = "async_fn_traits", issue = "none")] +pub use self::async_function::{AsyncFn, AsyncFnMut, AsyncFnOnce}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::bit::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; +#[stable(feature = "op_assign_traits", since = "1.8.0")] +pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign}; +#[stable(feature = "control_flow_enum_type", since = "1.55.0")] +pub use self::control_flow::ControlFlow; +#[unstable(feature = "coroutine_trait", issue = "43122")] +pub use self::coroutine::{Coroutine, CoroutineState}; +#[unstable(feature = "deref_pure_trait", issue = "87121")] +pub use self::deref::DerefPure; +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +pub use self::deref::LegacyReceiver; +#[unstable(feature = "arbitrary_self_types", issue = "44874")] +pub use self::deref::Receiver; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::deref::{Deref, DerefMut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::drop::Drop; +pub(crate) use self::drop::fallback_surface_drop; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::function::{Fn, FnMut, FnOnce}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::index::{Index, IndexMut}; +pub(crate) use self::index_range::IndexRange; +#[unstable(feature = "one_sided_range", issue = "69780")] +pub use self::range::OneSidedRange; +#[stable(feature = "inclusive_range", since = "1.26.0")] +pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; +#[unstable(feature = "try_trait_v2_residual", issue = "91285")] +pub use self::try_trait::Residual; +#[unstable(feature = "try_trait_v2_yeet", issue = "96374")] +pub use self::try_trait::Yeet; +pub(crate) use self::try_trait::{ChangeOutputType, NeverShortCircuit}; +#[unstable(feature = "try_trait_v2", issue = "84277")] +pub use self::try_trait::{FromResidual, Try}; +#[unstable(feature = "coerce_unsized", issue = "18598")] +pub use self::unsize::CoerceUnsized; +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +pub use self::unsize::DispatchFromDyn; diff --git a/CoqOfRust/core/ops/range.rs b/CoqOfRust/core/ops/range.rs new file mode 100644 index 000000000..727a22e45 --- /dev/null +++ b/CoqOfRust/core/ops/range.rs @@ -0,0 +1,998 @@ +use crate::fmt; +use crate::hash::Hash; + +/// An unbounded range (`..`). +/// +/// `RangeFull` is primarily used as a [slicing index], its shorthand is `..`. +/// It cannot serve as an [`Iterator`] because it doesn't have a starting point. +/// +/// # Examples +/// +/// The `..` syntax is a `RangeFull`: +/// +/// ``` +/// assert_eq!(.., std::ops::RangeFull); +/// ``` +/// +/// It does not have an [`IntoIterator`] implementation, so you can't use it in +/// a `for` loop directly. This won't compile: +/// +/// ```compile_fail,E0277 +/// for i in .. { +/// // ... +/// } +/// ``` +/// +/// Used as a [slicing index], `RangeFull` produces the full array as a slice. +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); // This is the `RangeFull` +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); +/// ``` +/// +/// [slicing index]: crate::slice::SliceIndex +#[lang = "RangeFull"] +#[doc(alias = "..")] +#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RangeFull; + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeFull { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "..") + } +} + +/// A (half-open) range bounded inclusively below and exclusively above +/// (`start..end`). +/// +/// The range `start..end` contains all values with `start <= x < end`. +/// It is empty if `start >= end`. +/// +/// # Examples +/// +/// The `start..end` syntax is a `Range`: +/// +/// ``` +/// assert_eq!((3..5), std::ops::Range { start: 3, end: 5 }); +/// assert_eq!(3 + 4 + 5, (3..6).sum()); +/// ``` +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); // This is a `Range` +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); +/// ``` +#[lang = "Range"] +#[doc(alias = "..")] +#[derive(Clone, Default, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Range { + /// The lower bound of the range (inclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub start: Idx, + /// The upper bound of the range (exclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub end: Idx, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Range { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + self.start.fmt(fmt)?; + write!(fmt, "..")?; + self.end.fmt(fmt)?; + Ok(()) + } +} + +impl> Range { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!(!(3..5).contains(&2)); + /// assert!( (3..5).contains(&3)); + /// assert!( (3..5).contains(&4)); + /// assert!(!(3..5).contains(&5)); + /// + /// assert!(!(3..3).contains(&3)); + /// assert!(!(3..2).contains(&3)); + /// + /// assert!( (0.0..1.0).contains(&0.5)); + /// assert!(!(0.0..1.0).contains(&f32::NAN)); + /// assert!(!(0.0..f32::NAN).contains(&0.5)); + /// assert!(!(f32::NAN..1.0).contains(&0.5)); + /// ``` + #[inline] + #[stable(feature = "range_contains", since = "1.35.0")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } + + /// Returns `true` if the range contains no items. + /// + /// # Examples + /// + /// ``` + /// assert!(!(3..5).is_empty()); + /// assert!( (3..3).is_empty()); + /// assert!( (3..2).is_empty()); + /// ``` + /// + /// The range is empty if either side is incomparable: + /// + /// ``` + /// assert!(!(3.0..5.0).is_empty()); + /// assert!( (3.0..f32::NAN).is_empty()); + /// assert!( (f32::NAN..5.0).is_empty()); + /// ``` + #[inline] + #[stable(feature = "range_is_empty", since = "1.47.0")] + pub fn is_empty(&self) -> bool { + !(self.start < self.end) + } +} + +/// A range only bounded inclusively below (`start..`). +/// +/// The `RangeFrom` `start..` contains all values with `x >= start`. +/// +/// *Note*: Overflow in the [`Iterator`] implementation (when the contained +/// data type reaches its numerical limit) is allowed to panic, wrap, or +/// saturate. This behavior is defined by the implementation of the [`Step`] +/// trait. For primitive integers, this follows the normal rules, and respects +/// the overflow checks profile (panic in debug, wrap in release). Note also +/// that overflow happens earlier than you might assume: the overflow happens +/// in the call to `next` that yields the maximum value, as the range must be +/// set to a state to yield the next value. +/// +/// [`Step`]: crate::iter::Step +/// +/// # Examples +/// +/// The `start..` syntax is a `RangeFrom`: +/// +/// ``` +/// assert_eq!((2..), std::ops::RangeFrom { start: 2 }); +/// assert_eq!(2 + 3 + 4, (2..).take(3).sum()); +/// ``` +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); // This is a `RangeFrom` +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); +/// ``` +#[lang = "RangeFrom"] +#[doc(alias = "..")] +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RangeFrom { + /// The lower bound of the range (inclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub start: Idx, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeFrom { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + self.start.fmt(fmt)?; + write!(fmt, "..")?; + Ok(()) + } +} + +impl> RangeFrom { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!(!(3..).contains(&2)); + /// assert!( (3..).contains(&3)); + /// assert!( (3..).contains(&1_000_000_000)); + /// + /// assert!( (0.0..).contains(&0.5)); + /// assert!(!(0.0..).contains(&f32::NAN)); + /// assert!(!(f32::NAN..).contains(&0.5)); + /// ``` + #[inline] + #[stable(feature = "range_contains", since = "1.35.0")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } +} + +/// A range only bounded exclusively above (`..end`). +/// +/// The `RangeTo` `..end` contains all values with `x < end`. +/// It cannot serve as an [`Iterator`] because it doesn't have a starting point. +/// +/// # Examples +/// +/// The `..end` syntax is a `RangeTo`: +/// +/// ``` +/// assert_eq!((..5), std::ops::RangeTo { end: 5 }); +/// ``` +/// +/// It does not have an [`IntoIterator`] implementation, so you can't use it in +/// a `for` loop directly. This won't compile: +/// +/// ```compile_fail,E0277 +/// // error[E0277]: the trait bound `std::ops::RangeTo<{integer}>: +/// // std::iter::Iterator` is not satisfied +/// for i in ..5 { +/// // ... +/// } +/// ``` +/// +/// When used as a [slicing index], `RangeTo` produces a slice of all array +/// elements before the index indicated by `end`. +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); // This is a `RangeTo` +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); +/// ``` +/// +/// [slicing index]: crate::slice::SliceIndex +#[lang = "RangeTo"] +#[doc(alias = "..")] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RangeTo { + /// The upper bound of the range (exclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub end: Idx, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeTo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "..")?; + self.end.fmt(fmt)?; + Ok(()) + } +} + +impl> RangeTo { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!( (..5).contains(&-1_000_000_000)); + /// assert!( (..5).contains(&4)); + /// assert!(!(..5).contains(&5)); + /// + /// assert!( (..1.0).contains(&0.5)); + /// assert!(!(..1.0).contains(&f32::NAN)); + /// assert!(!(..f32::NAN).contains(&0.5)); + /// ``` + #[inline] + #[stable(feature = "range_contains", since = "1.35.0")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } +} + +/// A range bounded inclusively below and above (`start..=end`). +/// +/// The `RangeInclusive` `start..=end` contains all values with `x >= start` +/// and `x <= end`. It is empty unless `start <= end`. +/// +/// This iterator is [fused], but the specific values of `start` and `end` after +/// iteration has finished are **unspecified** other than that [`.is_empty()`] +/// will return `true` once no more values will be produced. +/// +/// [fused]: crate::iter::FusedIterator +/// [`.is_empty()`]: RangeInclusive::is_empty +/// +/// # Examples +/// +/// The `start..=end` syntax is a `RangeInclusive`: +/// +/// ``` +/// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5)); +/// assert_eq!(3 + 4 + 5, (3..=5).sum()); +/// ``` +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); // This is a `RangeInclusive` +/// ``` +#[lang = "RangeInclusive"] +#[doc(alias = "..=")] +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[stable(feature = "inclusive_range", since = "1.26.0")] +pub struct RangeInclusive { + // Note that the fields here are not public to allow changing the + // representation in the future; in particular, while we could plausibly + // expose start/end, modifying them without changing (future/current) + // private fields may lead to incorrect behavior, so we don't want to + // support that mode. + pub(crate) start: Idx, + pub(crate) end: Idx, + + // This field is: + // - `false` upon construction + // - `false` when iteration has yielded an element and the iterator is not exhausted + // - `true` when iteration has been used to exhaust the iterator + // + // This is required to support PartialEq and Hash without a PartialOrd bound or specialization. + pub(crate) exhausted: bool, +} + +impl RangeInclusive { + /// Creates a new inclusive range. Equivalent to writing `start..=end`. + /// + /// # Examples + /// + /// ``` + /// use std::ops::RangeInclusive; + /// + /// assert_eq!(3..=5, RangeInclusive::new(3, 5)); + /// ``` + #[lang = "range_inclusive_new"] + #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[inline] + #[rustc_promotable] + #[rustc_const_stable(feature = "const_range_new", since = "1.32.0")] + pub const fn new(start: Idx, end: Idx) -> Self { + Self { start, end, exhausted: false } + } + + /// Returns the lower bound of the range (inclusive). + /// + /// When using an inclusive range for iteration, the values of `start()` and + /// [`end()`] are unspecified after the iteration ended. To determine + /// whether the inclusive range is empty, use the [`is_empty()`] method + /// instead of comparing `start() > end()`. + /// + /// Note: the value returned by this method is unspecified after the range + /// has been iterated to exhaustion. + /// + /// [`end()`]: RangeInclusive::end + /// [`is_empty()`]: RangeInclusive::is_empty + /// + /// # Examples + /// + /// ``` + /// assert_eq!((3..=5).start(), &3); + /// ``` + #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0")] + #[inline] + pub const fn start(&self) -> &Idx { + &self.start + } + + /// Returns the upper bound of the range (inclusive). + /// + /// When using an inclusive range for iteration, the values of [`start()`] + /// and `end()` are unspecified after the iteration ended. To determine + /// whether the inclusive range is empty, use the [`is_empty()`] method + /// instead of comparing `start() > end()`. + /// + /// Note: the value returned by this method is unspecified after the range + /// has been iterated to exhaustion. + /// + /// [`start()`]: RangeInclusive::start + /// [`is_empty()`]: RangeInclusive::is_empty + /// + /// # Examples + /// + /// ``` + /// assert_eq!((3..=5).end(), &5); + /// ``` + #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0")] + #[inline] + pub const fn end(&self) -> &Idx { + &self.end + } + + /// Destructures the `RangeInclusive` into (lower bound, upper (inclusive) bound). + /// + /// Note: the value returned by this method is unspecified after the range + /// has been iterated to exhaustion. + /// + /// # Examples + /// + /// ``` + /// assert_eq!((3..=5).into_inner(), (3, 5)); + /// ``` + #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[inline] + #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] + pub const fn into_inner(self) -> (Idx, Idx) { + (self.start, self.end) + } +} + +impl RangeInclusive { + /// Converts to an exclusive `Range` for `SliceIndex` implementations. + /// The caller is responsible for dealing with `end == usize::MAX`. + #[inline] + pub(crate) const fn into_slice_range(self) -> Range { + // If we're not exhausted, we want to simply slice `start..end + 1`. + // If we are exhausted, then slicing with `end + 1..end + 1` gives us an + // empty range that is still subject to bounds-checks for that endpoint. + let exclusive_end = self.end + 1; + let start = if self.exhausted { exclusive_end } else { self.start }; + start..exclusive_end + } +} + +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl fmt::Debug for RangeInclusive { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + self.start.fmt(fmt)?; + write!(fmt, "..=")?; + self.end.fmt(fmt)?; + if self.exhausted { + write!(fmt, " (exhausted)")?; + } + Ok(()) + } +} + +impl> RangeInclusive { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!(!(3..=5).contains(&2)); + /// assert!( (3..=5).contains(&3)); + /// assert!( (3..=5).contains(&4)); + /// assert!( (3..=5).contains(&5)); + /// assert!(!(3..=5).contains(&6)); + /// + /// assert!( (3..=3).contains(&3)); + /// assert!(!(3..=2).contains(&3)); + /// + /// assert!( (0.0..=1.0).contains(&1.0)); + /// assert!(!(0.0..=1.0).contains(&f32::NAN)); + /// assert!(!(0.0..=f32::NAN).contains(&0.0)); + /// assert!(!(f32::NAN..=1.0).contains(&1.0)); + /// ``` + /// + /// This method always returns `false` after iteration has finished: + /// + /// ``` + /// let mut r = 3..=5; + /// assert!(r.contains(&3) && r.contains(&5)); + /// for _ in r.by_ref() {} + /// // Precise field values are unspecified here + /// assert!(!r.contains(&3) && !r.contains(&5)); + /// ``` + #[inline] + #[stable(feature = "range_contains", since = "1.35.0")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } + + /// Returns `true` if the range contains no items. + /// + /// # Examples + /// + /// ``` + /// assert!(!(3..=5).is_empty()); + /// assert!(!(3..=3).is_empty()); + /// assert!( (3..=2).is_empty()); + /// ``` + /// + /// The range is empty if either side is incomparable: + /// + /// ``` + /// assert!(!(3.0..=5.0).is_empty()); + /// assert!( (3.0..=f32::NAN).is_empty()); + /// assert!( (f32::NAN..=5.0).is_empty()); + /// ``` + /// + /// This method returns `true` after iteration has finished: + /// + /// ``` + /// let mut r = 3..=5; + /// for _ in r.by_ref() {} + /// // Precise field values are unspecified here + /// assert!(r.is_empty()); + /// ``` + #[stable(feature = "range_is_empty", since = "1.47.0")] + #[inline] + pub fn is_empty(&self) -> bool { + self.exhausted || !(self.start <= self.end) + } +} + +/// A range only bounded inclusively above (`..=end`). +/// +/// The `RangeToInclusive` `..=end` contains all values with `x <= end`. +/// It cannot serve as an [`Iterator`] because it doesn't have a starting point. +/// +/// # Examples +/// +/// The `..=end` syntax is a `RangeToInclusive`: +/// +/// ``` +/// assert_eq!((..=5), std::ops::RangeToInclusive{ end: 5 }); +/// ``` +/// +/// It does not have an [`IntoIterator`] implementation, so you can't use it in a +/// `for` loop directly. This won't compile: +/// +/// ```compile_fail,E0277 +/// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>: +/// // std::iter::Iterator` is not satisfied +/// for i in ..=5 { +/// // ... +/// } +/// ``` +/// +/// When used as a [slicing index], `RangeToInclusive` produces a slice of all +/// array elements up to and including the index indicated by `end`. +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); // This is a `RangeToInclusive` +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); +/// ``` +/// +/// [slicing index]: crate::slice::SliceIndex +#[lang = "RangeToInclusive"] +#[doc(alias = "..=")] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[stable(feature = "inclusive_range", since = "1.26.0")] +pub struct RangeToInclusive { + /// The upper bound of the range (inclusive) + #[stable(feature = "inclusive_range", since = "1.26.0")] + pub end: Idx, +} + +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl fmt::Debug for RangeToInclusive { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "..=")?; + self.end.fmt(fmt)?; + Ok(()) + } +} + +impl> RangeToInclusive { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!( (..=5).contains(&-1_000_000_000)); + /// assert!( (..=5).contains(&5)); + /// assert!(!(..=5).contains(&6)); + /// + /// assert!( (..=1.0).contains(&1.0)); + /// assert!(!(..=1.0).contains(&f32::NAN)); + /// assert!(!(..=f32::NAN).contains(&0.5)); + /// ``` + #[inline] + #[stable(feature = "range_contains", since = "1.35.0")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } +} + +// RangeToInclusive cannot impl From> +// because underflow would be possible with (..0).into() + +/// An endpoint of a range of keys. +/// +/// # Examples +/// +/// `Bound`s are range endpoints: +/// +/// ``` +/// use std::ops::Bound::*; +/// use std::ops::RangeBounds; +/// +/// assert_eq!((..100).start_bound(), Unbounded); +/// assert_eq!((1..12).start_bound(), Included(&1)); +/// assert_eq!((1..12).end_bound(), Excluded(&12)); +/// ``` +/// +/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. +/// Note that in most cases, it's better to use range syntax (`1..5`) instead. +/// +/// ``` +/// use std::collections::BTreeMap; +/// use std::ops::Bound::{Excluded, Included, Unbounded}; +/// +/// let mut map = BTreeMap::new(); +/// map.insert(3, "a"); +/// map.insert(5, "b"); +/// map.insert(8, "c"); +/// +/// for (key, value) in map.range((Excluded(3), Included(8))) { +/// println!("{key}: {value}"); +/// } +/// +/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); +/// ``` +/// +/// [`BTreeMap::range`]: ../../std/collections/btree_map/struct.BTreeMap.html#method.range +#[stable(feature = "collections_bound", since = "1.17.0")] +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum Bound { + /// An inclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Included(#[stable(feature = "collections_bound", since = "1.17.0")] T), + /// An exclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Excluded(#[stable(feature = "collections_bound", since = "1.17.0")] T), + /// An infinite endpoint. Indicates that there is no bound in this direction. + #[stable(feature = "collections_bound", since = "1.17.0")] + Unbounded, +} + +impl Bound { + /// Converts from `&Bound` to `Bound<&T>`. + #[inline] + #[stable(feature = "bound_as_ref_shared", since = "1.65.0")] + pub fn as_ref(&self) -> Bound<&T> { + match *self { + Included(ref x) => Included(x), + Excluded(ref x) => Excluded(x), + Unbounded => Unbounded, + } + } + + /// Converts from `&mut Bound` to `Bound<&mut T>`. + #[inline] + #[unstable(feature = "bound_as_ref", issue = "80996")] + pub fn as_mut(&mut self) -> Bound<&mut T> { + match *self { + Included(ref mut x) => Included(x), + Excluded(ref mut x) => Excluded(x), + Unbounded => Unbounded, + } + } + + /// Maps a `Bound` to a `Bound` by applying a function to the contained value (including + /// both `Included` and `Excluded`), returning a `Bound` of the same kind. + /// + /// # Examples + /// + /// ``` + /// use std::ops::Bound::*; + /// + /// let bound_string = Included("Hello, World!"); + /// + /// assert_eq!(bound_string.map(|s| s.len()), Included(13)); + /// ``` + /// + /// ``` + /// use std::ops::Bound; + /// use Bound::*; + /// + /// let unbounded_string: Bound = Unbounded; + /// + /// assert_eq!(unbounded_string.map(|s| s.len()), Unbounded); + /// ``` + #[inline] + #[stable(feature = "bound_map", since = "1.77.0")] + pub fn map U>(self, f: F) -> Bound { + match self { + Unbounded => Unbounded, + Included(x) => Included(f(x)), + Excluded(x) => Excluded(f(x)), + } + } +} + +impl Bound<&T> { + /// Map a `Bound<&T>` to a `Bound` by cloning the contents of the bound. + /// + /// # Examples + /// + /// ``` + /// use std::ops::Bound::*; + /// use std::ops::RangeBounds; + /// + /// assert_eq!((1..12).start_bound(), Included(&1)); + /// assert_eq!((1..12).start_bound().cloned(), Included(1)); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "bound_cloned", since = "1.55.0")] + pub fn cloned(self) -> Bound { + match self { + Bound::Unbounded => Bound::Unbounded, + Bound::Included(x) => Bound::Included(x.clone()), + Bound::Excluded(x) => Bound::Excluded(x.clone()), + } + } +} + +/// `RangeBounds` is implemented by Rust's built-in range types, produced +/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. +#[stable(feature = "collections_range", since = "1.28.0")] +#[rustc_diagnostic_item = "RangeBounds"] +pub trait RangeBounds { + /// Start index bound. + /// + /// Returns the start value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// # fn main() { + /// use std::ops::Bound::*; + /// use std::ops::RangeBounds; + /// + /// assert_eq!((..10).start_bound(), Unbounded); + /// assert_eq!((3..10).start_bound(), Included(&3)); + /// # } + /// ``` + #[stable(feature = "collections_range", since = "1.28.0")] + fn start_bound(&self) -> Bound<&T>; + + /// End index bound. + /// + /// Returns the end value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// # fn main() { + /// use std::ops::Bound::*; + /// use std::ops::RangeBounds; + /// + /// assert_eq!((3..).end_bound(), Unbounded); + /// assert_eq!((3..10).end_bound(), Excluded(&10)); + /// # } + /// ``` + #[stable(feature = "collections_range", since = "1.28.0")] + fn end_bound(&self) -> Bound<&T>; + + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!( (3..5).contains(&4)); + /// assert!(!(3..5).contains(&2)); + /// + /// assert!( (0.0..1.0).contains(&0.5)); + /// assert!(!(0.0..1.0).contains(&f32::NAN)); + /// assert!(!(0.0..f32::NAN).contains(&0.5)); + /// assert!(!(f32::NAN..1.0).contains(&0.5)); + #[inline] + #[stable(feature = "range_contains", since = "1.35.0")] + fn contains(&self, item: &U) -> bool + where + T: PartialOrd, + U: ?Sized + PartialOrd, + { + (match self.start_bound() { + Included(start) => start <= item, + Excluded(start) => start < item, + Unbounded => true, + }) && (match self.end_bound() { + Included(end) => item <= end, + Excluded(end) => item < end, + Unbounded => true, + }) + } +} + +use self::Bound::{Excluded, Included, Unbounded}; + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeFull { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Unbounded + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeFrom { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + Unbounded + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeTo { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for Range { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeInclusive { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + if self.exhausted { + // When the iterator is exhausted, we usually have start == end, + // but we want the range to appear empty, containing nothing. + Excluded(&self.end) + } else { + Included(&self.end) + } + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeToInclusive { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Included(&self.end) + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for (Bound, Bound) { + fn start_bound(&self) -> Bound<&T> { + match *self { + (Included(ref start), _) => Included(start), + (Excluded(ref start), _) => Excluded(start), + (Unbounded, _) => Unbounded, + } + } + + fn end_bound(&self) -> Bound<&T> { + match *self { + (_, Included(ref end)) => Included(end), + (_, Excluded(ref end)) => Excluded(end), + (_, Unbounded) => Unbounded, + } + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl<'a, T: ?Sized + 'a> RangeBounds for (Bound<&'a T>, Bound<&'a T>) { + fn start_bound(&self) -> Bound<&T> { + self.0 + } + + fn end_bound(&self) -> Bound<&T> { + self.1 + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeFrom<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Unbounded + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeTo<&T> { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Excluded(self.end) + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for Range<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Excluded(self.end) + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeInclusive<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Included(self.end) + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeToInclusive<&T> { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Included(self.end) + } +} + +/// `OneSidedRange` is implemented for built-in range types that are unbounded +/// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`, +/// but `..`, `d..e`, and `f..=g` do not. +/// +/// Types that implement `OneSidedRange` must return `Bound::Unbounded` +/// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`. +#[unstable(feature = "one_sided_range", issue = "69780")] +pub trait OneSidedRange: RangeBounds {} + +#[unstable(feature = "one_sided_range", issue = "69780")] +impl OneSidedRange for RangeTo where Self: RangeBounds {} + +#[unstable(feature = "one_sided_range", issue = "69780")] +impl OneSidedRange for RangeFrom where Self: RangeBounds {} + +#[unstable(feature = "one_sided_range", issue = "69780")] +impl OneSidedRange for RangeToInclusive where Self: RangeBounds {} diff --git a/CoqOfRust/core/ops/try_trait.rs b/CoqOfRust/core/ops/try_trait.rs new file mode 100644 index 000000000..cd444c86e --- /dev/null +++ b/CoqOfRust/core/ops/try_trait.rs @@ -0,0 +1,428 @@ +use crate::ops::ControlFlow; + +/// The `?` operator and `try {}` blocks. +/// +/// `try_*` methods typically involve a type implementing this trait. For +/// example, the closures passed to [`Iterator::try_fold`] and +/// [`Iterator::try_for_each`] must return such a type. +/// +/// `Try` types are typically those containing two or more categories of values, +/// some subset of which are so commonly handled via early returns that it's +/// worth providing a terse (but still visible) syntax to make that easy. +/// +/// This is most often seen for error handling with [`Result`] and [`Option`]. +/// The quintessential implementation of this trait is on [`ControlFlow`]. +/// +/// # Using `Try` in Generic Code +/// +/// `Iterator::try_fold` was stabilized to call back in Rust 1.27, but +/// this trait is much newer. To illustrate the various associated types and +/// methods, let's implement our own version. +/// +/// As a reminder, an infallible version of a fold looks something like this: +/// ``` +/// fn simple_fold( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> A, +/// ) -> A { +/// for x in iter { +/// accum = f(accum, x); +/// } +/// accum +/// } +/// ``` +/// +/// So instead of `f` returning just an `A`, we'll need it to return some other +/// type that produces an `A` in the "don't short circuit" path. Conveniently, +/// that's also the type we need to return from the function. +/// +/// Let's add a new generic parameter `R` for that type, and bound it to the +/// output type that we want: +/// ``` +/// # #![feature(try_trait_v2)] +/// # use std::ops::Try; +/// fn simple_try_fold_1>( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> R, +/// ) -> R { +/// todo!() +/// } +/// ``` +/// +/// If we get through the entire iterator, we need to wrap up the accumulator +/// into the return type using [`Try::from_output`]: +/// ``` +/// # #![feature(try_trait_v2)] +/// # use std::ops::{ControlFlow, Try}; +/// fn simple_try_fold_2>( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> R, +/// ) -> R { +/// for x in iter { +/// let cf = f(accum, x).branch(); +/// match cf { +/// ControlFlow::Continue(a) => accum = a, +/// ControlFlow::Break(_) => todo!(), +/// } +/// } +/// R::from_output(accum) +/// } +/// ``` +/// +/// We'll also need [`FromResidual::from_residual`] to turn the residual back +/// into the original type. But because it's a supertrait of `Try`, we don't +/// need to mention it in the bounds. All types which implement `Try` can be +/// recreated from their corresponding residual, so we'll just call it: +/// ``` +/// # #![feature(try_trait_v2)] +/// # use std::ops::{ControlFlow, Try}; +/// pub fn simple_try_fold_3>( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> R, +/// ) -> R { +/// for x in iter { +/// let cf = f(accum, x).branch(); +/// match cf { +/// ControlFlow::Continue(a) => accum = a, +/// ControlFlow::Break(r) => return R::from_residual(r), +/// } +/// } +/// R::from_output(accum) +/// } +/// ``` +/// +/// But this "call `branch`, then `match` on it, and `return` if it was a +/// `Break`" is exactly what happens inside the `?` operator. So rather than +/// do all this manually, we can just use `?` instead: +/// ``` +/// # #![feature(try_trait_v2)] +/// # use std::ops::Try; +/// fn simple_try_fold>( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> R, +/// ) -> R { +/// for x in iter { +/// accum = f(accum, x)?; +/// } +/// R::from_output(accum) +/// } +/// ``` +#[unstable(feature = "try_trait_v2", issue = "84277")] +#[rustc_on_unimplemented( + on( + all(from_desugaring = "TryBlock"), + message = "a `try` block must return `Result` or `Option` \ + (or another type that implements `{Try}`)", + label = "could not wrap the final value of the block as `{Self}` doesn't implement `Try`", + ), + on( + all(from_desugaring = "QuestionMark"), + message = "the `?` operator can only be applied to values that implement `{Try}`", + label = "the `?` operator cannot be applied to type `{Self}`" + ) +)] +#[doc(alias = "?")] +#[lang = "Try"] +pub trait Try: FromResidual { + /// The type of the value produced by `?` when *not* short-circuiting. + #[unstable(feature = "try_trait_v2", issue = "84277")] + type Output; + + /// The type of the value passed to [`FromResidual::from_residual`] + /// as part of `?` when short-circuiting. + /// + /// This represents the possible values of the `Self` type which are *not* + /// represented by the `Output` type. + /// + /// # Note to Implementors + /// + /// The choice of this type is critical to interconversion. + /// Unlike the `Output` type, which will often be a raw generic type, + /// this type is typically a newtype of some sort to "color" the type + /// so that it's distinguishable from the residuals of other types. + /// + /// This is why `Result::Residual` is not `E`, but `Result`. + /// That way it's distinct from `ControlFlow::Residual`, for example, + /// and thus `?` on `ControlFlow` cannot be used in a method returning `Result`. + /// + /// If you're making a generic type `Foo` that implements `Try`, + /// then typically you can use `Foo` as its `Residual` + /// type: that type will have a "hole" in the correct place, and will maintain the + /// "foo-ness" of the residual so other types need to opt-in to interconversion. + #[unstable(feature = "try_trait_v2", issue = "84277")] + type Residual; + + /// Constructs the type from its `Output` type. + /// + /// This should be implemented consistently with the `branch` method + /// such that applying the `?` operator will get back the original value: + /// `Try::from_output(x).branch() --> ControlFlow::Continue(x)`. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_trait_v2)] + /// use std::ops::Try; + /// + /// assert_eq!( as Try>::from_output(3), Ok(3)); + /// assert_eq!( as Try>::from_output(4), Some(4)); + /// assert_eq!( + /// as Try>::from_output(5), + /// std::ops::ControlFlow::Continue(5), + /// ); + /// + /// # fn make_question_mark_work() -> Option<()> { + /// assert_eq!(Option::from_output(4)?, 4); + /// # None } + /// # make_question_mark_work(); + /// + /// // This is used, for example, on the accumulator in `try_fold`: + /// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() }); + /// assert_eq!(r, Some(4)); + /// ``` + #[lang = "from_output"] + #[unstable(feature = "try_trait_v2", issue = "84277")] + fn from_output(output: Self::Output) -> Self; + + /// Used in `?` to decide whether the operator should produce a value + /// (because this returned [`ControlFlow::Continue`]) + /// or propagate a value back to the caller + /// (because this returned [`ControlFlow::Break`]). + /// + /// # Examples + /// + /// ``` + /// #![feature(try_trait_v2)] + /// use std::ops::{ControlFlow, Try}; + /// + /// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3)); + /// assert_eq!(Err::(3).branch(), ControlFlow::Break(Err(3))); + /// + /// assert_eq!(Some(3).branch(), ControlFlow::Continue(3)); + /// assert_eq!(None::.branch(), ControlFlow::Break(None)); + /// + /// assert_eq!(ControlFlow::::Continue(3).branch(), ControlFlow::Continue(3)); + /// assert_eq!( + /// ControlFlow::<_, String>::Break(3).branch(), + /// ControlFlow::Break(ControlFlow::Break(3)), + /// ); + /// ``` + #[lang = "branch"] + #[unstable(feature = "try_trait_v2", issue = "84277")] + fn branch(self) -> ControlFlow; +} + +/// Used to specify which residuals can be converted into which [`crate::ops::Try`] types. +/// +/// Every `Try` type needs to be recreatable from its own associated +/// `Residual` type, but can also have additional `FromResidual` implementations +/// to support interconversion with other `Try` types. +#[rustc_on_unimplemented( + on( + all( + from_desugaring = "QuestionMark", + _Self = "core::result::Result", + R = "core::option::Option", + ), + message = "the `?` operator can only be used on `Result`s, not `Option`s, \ + in {ItemContext} that returns `Result`", + label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`", + parent_label = "this function returns a `Result`" + ), + on( + all( + from_desugaring = "QuestionMark", + _Self = "core::result::Result", + ), + // There's a special error message in the trait selection code for + // `From` in `?`, so this is not shown for result-in-result errors, + // and thus it can be phrased more strongly than `ControlFlow`'s. + message = "the `?` operator can only be used on `Result`s \ + in {ItemContext} that returns `Result`", + label = "this `?` produces `{R}`, which is incompatible with `{Self}`", + parent_label = "this function returns a `Result`" + ), + on( + all( + from_desugaring = "QuestionMark", + _Self = "core::option::Option", + R = "core::result::Result", + ), + message = "the `?` operator can only be used on `Option`s, not `Result`s, \ + in {ItemContext} that returns `Option`", + label = "use `.ok()?` if you want to discard the `{R}` error information", + parent_label = "this function returns an `Option`" + ), + on( + all( + from_desugaring = "QuestionMark", + _Self = "core::option::Option", + ), + // `Option`-in-`Option` always works, as there's only one possible + // residual, so this can also be phrased strongly. + message = "the `?` operator can only be used on `Option`s \ + in {ItemContext} that returns `Option`", + label = "this `?` produces `{R}`, which is incompatible with `{Self}`", + parent_label = "this function returns an `Option`" + ), + on( + all( + from_desugaring = "QuestionMark", + _Self = "core::ops::control_flow::ControlFlow", + R = "core::ops::control_flow::ControlFlow", + ), + message = "the `?` operator in {ItemContext} that returns `ControlFlow` \ + can only be used on other `ControlFlow`s (with the same Break type)", + label = "this `?` produces `{R}`, which is incompatible with `{Self}`", + parent_label = "this function returns a `ControlFlow`", + note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`" + ), + on( + all( + from_desugaring = "QuestionMark", + _Self = "core::ops::control_flow::ControlFlow", + // `R` is not a `ControlFlow`, as that case was matched previously + ), + message = "the `?` operator can only be used on `ControlFlow`s \ + in {ItemContext} that returns `ControlFlow`", + label = "this `?` produces `{R}`, which is incompatible with `{Self}`", + parent_label = "this function returns a `ControlFlow`", + ), + on( + all(from_desugaring = "QuestionMark"), + message = "the `?` operator can only be used in {ItemContext} \ + that returns `Result` or `Option` \ + (or another type that implements `{FromResidual}`)", + label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`", + parent_label = "this function should return `Result` or `Option` to accept `?`" + ), +)] +#[rustc_diagnostic_item = "FromResidual"] +#[unstable(feature = "try_trait_v2", issue = "84277")] +pub trait FromResidual::Residual> { + /// Constructs the type from a compatible `Residual` type. + /// + /// This should be implemented consistently with the `branch` method such + /// that applying the `?` operator will get back an equivalent residual: + /// `FromResidual::from_residual(r).branch() --> ControlFlow::Break(r)`. + /// (The residual is not mandated to be *identical* when interconversion is involved.) + /// + /// # Examples + /// + /// ``` + /// #![feature(try_trait_v2)] + /// use std::ops::{ControlFlow, FromResidual}; + /// + /// assert_eq!(Result::::from_residual(Err(3_u8)), Err(3)); + /// assert_eq!(Option::::from_residual(None), None); + /// assert_eq!( + /// ControlFlow::<_, String>::from_residual(ControlFlow::Break(5)), + /// ControlFlow::Break(5), + /// ); + /// ``` + #[lang = "from_residual"] + #[unstable(feature = "try_trait_v2", issue = "84277")] + fn from_residual(residual: R) -> Self; +} + +#[unstable( + feature = "yeet_desugar_details", + issue = "none", + reason = "just here to simplify the desugaring; will never be stabilized" +)] +#[inline] +#[track_caller] // because `Result::from_residual` has it +#[lang = "from_yeet"] +pub fn from_yeet(yeeted: Y) -> T +where + T: FromResidual>, +{ + FromResidual::from_residual(Yeet(yeeted)) +} + +/// Allows retrieving the canonical type implementing [`Try`] that has this type +/// as its residual and allows it to hold an `O` as its output. +/// +/// If you think of the `Try` trait as splitting a type into its [`Try::Output`] +/// and [`Try::Residual`] components, this allows putting them back together. +/// +/// For example, +/// `Result: Try>`, +/// and in the other direction, +/// ` as Residual>::TryType = Result`. +#[unstable(feature = "try_trait_v2_residual", issue = "91285")] +pub trait Residual { + /// The "return" type of this meta-function. + #[unstable(feature = "try_trait_v2_residual", issue = "91285")] + type TryType: Try; +} + +#[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")] +#[allow(type_alias_bounds)] +pub(crate) type ChangeOutputType>, V> = + >::TryType; + +/// An adapter for implementing non-try methods via the `Try` implementation. +/// +/// Conceptually the same as `Result`, but requiring less work in trait +/// solving and inhabited-ness checking and such, by being an obvious newtype +/// and not having `From` bounds lying around. +/// +/// Not currently planned to be exposed publicly, so just `pub(crate)`. +#[repr(transparent)] +pub(crate) struct NeverShortCircuit(pub T); + +impl NeverShortCircuit { + /// Wraps a unary function to produce one that wraps the output into a `NeverShortCircuit`. + /// + /// This is useful for implementing infallible functions in terms of the `try_` ones, + /// without accidentally capturing extra generic parameters in a closure. + #[inline] + pub fn wrap_mut_1(mut f: impl FnMut(A) -> T) -> impl FnMut(A) -> NeverShortCircuit { + move |a| NeverShortCircuit(f(a)) + } + + #[inline] + pub fn wrap_mut_2(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self { + move |a, b| NeverShortCircuit(f(a, b)) + } +} + +pub(crate) enum NeverShortCircuitResidual {} + +impl Try for NeverShortCircuit { + type Output = T; + type Residual = NeverShortCircuitResidual; + + #[inline] + fn branch(self) -> ControlFlow { + ControlFlow::Continue(self.0) + } + + #[inline] + fn from_output(x: T) -> Self { + NeverShortCircuit(x) + } +} + +impl FromResidual for NeverShortCircuit { + #[inline] + fn from_residual(never: NeverShortCircuitResidual) -> Self { + match never {} + } +} + +impl Residual for NeverShortCircuitResidual { + type TryType = NeverShortCircuit; +} + +/// Implement `FromResidual>` on your type to enable +/// `do yeet expr` syntax in functions returning your type. +#[unstable(feature = "try_trait_v2_yeet", issue = "96374")] +#[derive(Debug)] +pub struct Yeet(pub T); diff --git a/CoqOfRust/core/ops/unsize.rs b/CoqOfRust/core/ops/unsize.rs new file mode 100644 index 000000000..d2a07197f --- /dev/null +++ b/CoqOfRust/core/ops/unsize.rs @@ -0,0 +1,134 @@ +use crate::marker::Unsize; + +/// Trait that indicates that this is a pointer or a wrapper for one, +/// where unsizing can be performed on the pointee. +/// +/// See the [DST coercion RFC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce] +/// for more details. +/// +/// For builtin pointer types, pointers to `T` will coerce to pointers to `U` if `T: Unsize` +/// by converting from a thin pointer to a fat pointer. +/// +/// For custom types, the coercion here works by coercing `Foo` to `Foo` +/// provided an impl of `CoerceUnsized> for Foo` exists. +/// Such an impl can only be written if `Foo` has only a single non-phantomdata +/// field involving `T`. If the type of that field is `Bar`, an implementation +/// of `CoerceUnsized> for Bar` must exist. The coercion will work by +/// coercing the `Bar` field into `Bar` and filling in the rest of the fields +/// from `Foo` to create a `Foo`. This will effectively drill down to a pointer +/// field and coerce that. +/// +/// Generally, for smart pointers you will implement +/// `CoerceUnsized> for Ptr where T: Unsize, U: ?Sized`, with an +/// optional `?Sized` bound on `T` itself. For wrapper types that directly embed `T` +/// like `Cell` and `RefCell`, you +/// can directly implement `CoerceUnsized> for Wrap where T: CoerceUnsized`. +/// This will let coercions of types like `Cell>` work. +/// +/// [`Unsize`][unsize] is used to mark types which can be coerced to DSTs if behind +/// pointers. It is implemented automatically by the compiler. +/// +/// [dst-coerce]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md +/// [unsize]: crate::marker::Unsize +/// [nomicon-coerce]: ../../nomicon/coercions.html +#[unstable(feature = "coerce_unsized", issue = "18598")] +#[lang = "coerce_unsized"] +pub trait CoerceUnsized { + // Empty. +} + +// &mut T -> &mut U +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} +// &mut T -> &U +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {} +// &mut T -> *mut U +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {} +// &mut T -> *const U +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {} + +// &T -> &U +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} +// &T -> *const U +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a T {} + +// *mut T -> *mut U +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} +// *mut T -> *const U +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} + +// *const T -> *const U +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} + +/// `DispatchFromDyn` is used in the implementation of dyn-compatibility[^1] checks (specifically +/// allowing arbitrary self types), to guarantee that a method's receiver type can be dispatched on. +/// +/// Note: `DispatchFromDyn` was briefly named `CoerceSized` (and had a slightly different +/// interpretation). +/// +/// Imagine we have a trait object `t` with type `&dyn Tr`, where `Tr` is some trait with a method +/// `m` defined as `fn m(&self);`. When calling `t.m()`, the receiver `t` is a wide pointer, but an +/// implementation of `m` will expect a narrow pointer as `&self` (a reference to the concrete +/// type). The compiler must generate an implicit conversion from the trait object/wide pointer to +/// the concrete reference/narrow pointer. Implementing `DispatchFromDyn` indicates that that +/// conversion is allowed and thus that the type implementing `DispatchFromDyn` is safe to use as +/// the self type in an dyn-compatible method. (in the above example, the compiler will require +/// `DispatchFromDyn` is implemented for `&'a U`). +/// +/// `DispatchFromDyn` does not specify the conversion from wide pointer to narrow pointer; the +/// conversion is hard-wired into the compiler. For the conversion to work, the following +/// properties must hold (i.e., it is only safe to implement `DispatchFromDyn` for types which have +/// these properties, these are also checked by the compiler): +/// +/// * EITHER `Self` and `T` are either both references or both raw pointers; in either case, with +/// the same mutability. +/// * OR, all of the following hold +/// - `Self` and `T` must have the same type constructor, and only vary in a single type parameter +/// formal (the *coerced type*, e.g., `impl DispatchFromDyn> for Rc` is ok and the +/// single type parameter (instantiated with `T` or `U`) is the coerced type, +/// `impl DispatchFromDyn> for Rc` is not ok). +/// - The definition for `Self` must be a struct. +/// - The definition for `Self` must not be `#[repr(packed)]` or `#[repr(C)]`. +/// - Other than one-aligned, zero-sized fields, the definition for `Self` must have exactly one +/// field and that field's type must be the coerced type. Furthermore, `Self`'s field type must +/// implement `DispatchFromDyn` where `F` is the type of `T`'s field type. +/// +/// An example implementation of the trait: +/// +/// ``` +/// # #![feature(dispatch_from_dyn, unsize)] +/// # use std::{ops::DispatchFromDyn, marker::Unsize}; +/// # struct Rc(std::rc::Rc); +/// impl DispatchFromDyn> for Rc +/// where +/// T: Unsize, +/// {} +/// ``` +/// +/// [^1]: Formerly known as *object safety*. +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +#[lang = "dispatch_from_dyn"] +pub trait DispatchFromDyn { + // Empty. +} + +// &T -> &U +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} +// &mut T -> &mut U +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {} +// *const T -> *const U +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn<*const U> for *const T {} +// *mut T -> *mut U +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {} diff --git a/CoqOfRust/core/option.rs b/CoqOfRust/core/option.rs new file mode 100644 index 000000000..f4ac7af63 --- /dev/null +++ b/CoqOfRust/core/option.rs @@ -0,0 +1,2574 @@ +//! Optional values. +//! +//! Type [`Option`] represents an optional value: every [`Option`] +//! is either [`Some`] and contains a value, or [`None`], and +//! does not. [`Option`] types are very common in Rust code, as +//! they have a number of uses: +//! +//! * Initial values +//! * Return values for functions that are not defined +//! over their entire input range (partial functions) +//! * Return value for otherwise reporting simple errors, where [`None`] is +//! returned on error +//! * Optional struct fields +//! * Struct fields that can be loaned or "taken" +//! * Optional function arguments +//! * Nullable pointers +//! * Swapping things out of difficult situations +//! +//! [`Option`]s are commonly paired with pattern matching to query the presence +//! of a value and take action, always accounting for the [`None`] case. +//! +//! ``` +//! fn divide(numerator: f64, denominator: f64) -> Option { +//! if denominator == 0.0 { +//! None +//! } else { +//! Some(numerator / denominator) +//! } +//! } +//! +//! // The return value of the function is an option +//! let result = divide(2.0, 3.0); +//! +//! // Pattern match to retrieve the value +//! match result { +//! // The division was valid +//! Some(x) => println!("Result: {x}"), +//! // The division was invalid +//! None => println!("Cannot divide by 0"), +//! } +//! ``` +//! +// +// FIXME: Show how `Option` is used in practice, with lots of methods +// +//! # Options and pointers ("nullable" pointers) +//! +//! Rust's pointer types must always point to a valid location; there are +//! no "null" references. Instead, Rust has *optional* pointers, like +//! the optional owned box, [Option]<[Box\]>. +//! +//! [Box\]: ../../std/boxed/struct.Box.html +//! +//! The following example uses [`Option`] to create an optional box of +//! [`i32`]. Notice that in order to use the inner [`i32`] value, the +//! `check_optional` function first needs to use pattern matching to +//! determine whether the box has a value (i.e., it is [`Some(...)`][`Some`]) or +//! not ([`None`]). +//! +//! ``` +//! let optional = None; +//! check_optional(optional); +//! +//! let optional = Some(Box::new(9000)); +//! check_optional(optional); +//! +//! fn check_optional(optional: Option>) { +//! match optional { +//! Some(p) => println!("has value {p}"), +//! None => println!("has no value"), +//! } +//! } +//! ``` +//! +//! # The question mark operator, `?` +//! +//! Similar to the [`Result`] type, when writing code that calls many functions that return the +//! [`Option`] type, handling `Some`/`None` can be tedious. The question mark +//! operator, [`?`], hides some of the boilerplate of propagating values +//! up the call stack. +//! +//! It replaces this: +//! +//! ``` +//! # #![allow(dead_code)] +//! fn add_last_numbers(stack: &mut Vec) -> Option { +//! let a = stack.pop(); +//! let b = stack.pop(); +//! +//! match (a, b) { +//! (Some(x), Some(y)) => Some(x + y), +//! _ => None, +//! } +//! } +//! +//! ``` +//! +//! With this: +//! +//! ``` +//! # #![allow(dead_code)] +//! fn add_last_numbers(stack: &mut Vec) -> Option { +//! Some(stack.pop()? + stack.pop()?) +//! } +//! ``` +//! +//! *It's much nicer!* +//! +//! Ending the expression with [`?`] will result in the [`Some`]'s unwrapped value, unless the +//! result is [`None`], in which case [`None`] is returned early from the enclosing function. +//! +//! [`?`] can be used in functions that return [`Option`] because of the +//! early return of [`None`] that it provides. +//! +//! [`?`]: crate::ops::Try +//! [`Some`]: Some +//! [`None`]: None +//! +//! # Representation +//! +//! Rust guarantees to optimize the following types `T` such that +//! [`Option`] has the same size, alignment, and [function call ABI] as `T`. In some +//! of these cases, Rust further guarantees that +//! `transmute::<_, Option>([0u8; size_of::()])` is sound and +//! produces `Option::::None`. These cases are identified by the +//! second column: +//! +//! | `T` | `transmute::<_, Option>([0u8; size_of::()])` sound? | +//! |---------------------------------------------------------------------|----------------------------------------------------------------------| +//! | [`Box`] (specifically, only `Box`) | when `U: Sized` | +//! | `&U` | when `U: Sized` | +//! | `&mut U` | when `U: Sized` | +//! | `fn`, `extern "C" fn`[^extern_fn] | always | +//! | [`num::NonZero*`] | always | +//! | [`ptr::NonNull`] | when `U: Sized` | +//! | `#[repr(transparent)]` struct around one of the types in this list. | when it holds for the inner type | +//! +//! [^extern_fn]: this remains true for any argument/return types and any other ABI: `extern "abi" fn` (_e.g._, `extern "system" fn`) +//! +//! Under some conditions the above types `T` are also null pointer optimized when wrapped in a [`Result`][result_repr]. +//! +//! [`Box`]: ../../std/boxed/struct.Box.html +//! [`num::NonZero*`]: crate::num +//! [`ptr::NonNull`]: crate::ptr::NonNull +//! [function call ABI]: ../primitive.fn.html#abi-compatibility +//! [result_repr]: crate::result#representation +//! +//! This is called the "null pointer optimization" or NPO. +//! +//! It is further guaranteed that, for the cases above, one can +//! [`mem::transmute`] from all valid values of `T` to `Option` and +//! from `Some::(_)` to `T` (but transmuting `None::` to `T` +//! is undefined behavior). +//! +//! # Method overview +//! +//! In addition to working with pattern matching, [`Option`] provides a wide +//! variety of different methods. +//! +//! ## Querying the variant +//! +//! The [`is_some`] and [`is_none`] methods return [`true`] if the [`Option`] +//! is [`Some`] or [`None`], respectively. +//! +//! [`is_none`]: Option::is_none +//! [`is_some`]: Option::is_some +//! +//! ## Adapters for working with references +//! +//! * [`as_ref`] converts from [&][][Option]\ to [Option]<[&]T> +//! * [`as_mut`] converts from [&mut] [Option]\ to [Option]<[&mut] T> +//! * [`as_deref`] converts from [&][][Option]\ to +//! [Option]<[&]T::[Target]> +//! * [`as_deref_mut`] converts from [&mut] [Option]\ to +//! [Option]<[&mut] T::[Target]> +//! * [`as_pin_ref`] converts from [Pin]<[&][][Option]\> to +//! [Option]<[Pin]<[&]T>> +//! * [`as_pin_mut`] converts from [Pin]<[&mut] [Option]\> to +//! [Option]<[Pin]<[&mut] T>> +//! +//! [&]: reference "shared reference" +//! [&mut]: reference "mutable reference" +//! [Target]: Deref::Target "ops::Deref::Target" +//! [`as_deref`]: Option::as_deref +//! [`as_deref_mut`]: Option::as_deref_mut +//! [`as_mut`]: Option::as_mut +//! [`as_pin_mut`]: Option::as_pin_mut +//! [`as_pin_ref`]: Option::as_pin_ref +//! [`as_ref`]: Option::as_ref +//! +//! ## Extracting the contained value +//! +//! These methods extract the contained value in an [`Option`] when it +//! is the [`Some`] variant. If the [`Option`] is [`None`]: +//! +//! * [`expect`] panics with a provided custom message +//! * [`unwrap`] panics with a generic message +//! * [`unwrap_or`] returns the provided default value +//! * [`unwrap_or_default`] returns the default value of the type `T` +//! (which must implement the [`Default`] trait) +//! * [`unwrap_or_else`] returns the result of evaluating the provided +//! function +//! +//! [`expect`]: Option::expect +//! [`unwrap`]: Option::unwrap +//! [`unwrap_or`]: Option::unwrap_or +//! [`unwrap_or_default`]: Option::unwrap_or_default +//! [`unwrap_or_else`]: Option::unwrap_or_else +//! +//! ## Transforming contained values +//! +//! These methods transform [`Option`] to [`Result`]: +//! +//! * [`ok_or`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to +//! [`Err(err)`] using the provided default `err` value +//! * [`ok_or_else`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to +//! a value of [`Err`] using the provided function +//! * [`transpose`] transposes an [`Option`] of a [`Result`] into a +//! [`Result`] of an [`Option`] +//! +//! [`Err(err)`]: Err +//! [`Ok(v)`]: Ok +//! [`Some(v)`]: Some +//! [`ok_or`]: Option::ok_or +//! [`ok_or_else`]: Option::ok_or_else +//! [`transpose`]: Option::transpose +//! +//! These methods transform the [`Some`] variant: +//! +//! * [`filter`] calls the provided predicate function on the contained +//! value `t` if the [`Option`] is [`Some(t)`], and returns [`Some(t)`] +//! if the function returns `true`; otherwise, returns [`None`] +//! * [`flatten`] removes one level of nesting from an +//! [`Option>`] +//! * [`map`] transforms [`Option`] to [`Option`] by applying the +//! provided function to the contained value of [`Some`] and leaving +//! [`None`] values unchanged +//! +//! [`Some(t)`]: Some +//! [`filter`]: Option::filter +//! [`flatten`]: Option::flatten +//! [`map`]: Option::map +//! +//! These methods transform [`Option`] to a value of a possibly +//! different type `U`: +//! +//! * [`map_or`] applies the provided function to the contained value of +//! [`Some`], or returns the provided default value if the [`Option`] is +//! [`None`] +//! * [`map_or_else`] applies the provided function to the contained value +//! of [`Some`], or returns the result of evaluating the provided +//! fallback function if the [`Option`] is [`None`] +//! +//! [`map_or`]: Option::map_or +//! [`map_or_else`]: Option::map_or_else +//! +//! These methods combine the [`Some`] variants of two [`Option`] values: +//! +//! * [`zip`] returns [`Some((s, o))`] if `self` is [`Some(s)`] and the +//! provided [`Option`] value is [`Some(o)`]; otherwise, returns [`None`] +//! * [`zip_with`] calls the provided function `f` and returns +//! [`Some(f(s, o))`] if `self` is [`Some(s)`] and the provided +//! [`Option`] value is [`Some(o)`]; otherwise, returns [`None`] +//! +//! [`Some(f(s, o))`]: Some +//! [`Some(o)`]: Some +//! [`Some(s)`]: Some +//! [`Some((s, o))`]: Some +//! [`zip`]: Option::zip +//! [`zip_with`]: Option::zip_with +//! +//! ## Boolean operators +//! +//! These methods treat the [`Option`] as a boolean value, where [`Some`] +//! acts like [`true`] and [`None`] acts like [`false`]. There are two +//! categories of these methods: ones that take an [`Option`] as input, and +//! ones that take a function as input (to be lazily evaluated). +//! +//! The [`and`], [`or`], and [`xor`] methods take another [`Option`] as +//! input, and produce an [`Option`] as output. Only the [`and`] method can +//! produce an [`Option`] value having a different inner type `U` than +//! [`Option`]. +//! +//! | method | self | input | output | +//! |---------|-----------|-----------|-----------| +//! | [`and`] | `None` | (ignored) | `None` | +//! | [`and`] | `Some(x)` | `None` | `None` | +//! | [`and`] | `Some(x)` | `Some(y)` | `Some(y)` | +//! | [`or`] | `None` | `None` | `None` | +//! | [`or`] | `None` | `Some(y)` | `Some(y)` | +//! | [`or`] | `Some(x)` | (ignored) | `Some(x)` | +//! | [`xor`] | `None` | `None` | `None` | +//! | [`xor`] | `None` | `Some(y)` | `Some(y)` | +//! | [`xor`] | `Some(x)` | `None` | `Some(x)` | +//! | [`xor`] | `Some(x)` | `Some(y)` | `None` | +//! +//! [`and`]: Option::and +//! [`or`]: Option::or +//! [`xor`]: Option::xor +//! +//! The [`and_then`] and [`or_else`] methods take a function as input, and +//! only evaluate the function when they need to produce a new value. Only +//! the [`and_then`] method can produce an [`Option`] value having a +//! different inner type `U` than [`Option`]. +//! +//! | method | self | function input | function result | output | +//! |--------------|-----------|----------------|-----------------|-----------| +//! | [`and_then`] | `None` | (not provided) | (not evaluated) | `None` | +//! | [`and_then`] | `Some(x)` | `x` | `None` | `None` | +//! | [`and_then`] | `Some(x)` | `x` | `Some(y)` | `Some(y)` | +//! | [`or_else`] | `None` | (not provided) | `None` | `None` | +//! | [`or_else`] | `None` | (not provided) | `Some(y)` | `Some(y)` | +//! | [`or_else`] | `Some(x)` | (not provided) | (not evaluated) | `Some(x)` | +//! +//! [`and_then`]: Option::and_then +//! [`or_else`]: Option::or_else +//! +//! This is an example of using methods like [`and_then`] and [`or`] in a +//! pipeline of method calls. Early stages of the pipeline pass failure +//! values ([`None`]) through unchanged, and continue processing on +//! success values ([`Some`]). Toward the end, [`or`] substitutes an error +//! message if it receives [`None`]. +//! +//! ``` +//! # use std::collections::BTreeMap; +//! let mut bt = BTreeMap::new(); +//! bt.insert(20u8, "foo"); +//! bt.insert(42u8, "bar"); +//! let res = [0u8, 1, 11, 200, 22] +//! .into_iter() +//! .map(|x| { +//! // `checked_sub()` returns `None` on error +//! x.checked_sub(1) +//! // same with `checked_mul()` +//! .and_then(|x| x.checked_mul(2)) +//! // `BTreeMap::get` returns `None` on error +//! .and_then(|x| bt.get(&x)) +//! // Substitute an error message if we have `None` so far +//! .or(Some(&"error!")) +//! .copied() +//! // Won't panic because we unconditionally used `Some` above +//! .unwrap() +//! }) +//! .collect::>(); +//! assert_eq!(res, ["error!", "error!", "foo", "error!", "bar"]); +//! ``` +//! +//! ## Comparison operators +//! +//! If `T` implements [`PartialOrd`] then [`Option`] will derive its +//! [`PartialOrd`] implementation. With this order, [`None`] compares as +//! less than any [`Some`], and two [`Some`] compare the same way as their +//! contained values would in `T`. If `T` also implements +//! [`Ord`], then so does [`Option`]. +//! +//! ``` +//! assert!(None < Some(0)); +//! assert!(Some(0) < Some(1)); +//! ``` +//! +//! ## Iterating over `Option` +//! +//! An [`Option`] can be iterated over. This can be helpful if you need an +//! iterator that is conditionally empty. The iterator will either produce +//! a single value (when the [`Option`] is [`Some`]), or produce no values +//! (when the [`Option`] is [`None`]). For example, [`into_iter`] acts like +//! [`once(v)`] if the [`Option`] is [`Some(v)`], and like [`empty()`] if +//! the [`Option`] is [`None`]. +//! +//! [`Some(v)`]: Some +//! [`empty()`]: crate::iter::empty +//! [`once(v)`]: crate::iter::once +//! +//! Iterators over [`Option`] come in three types: +//! +//! * [`into_iter`] consumes the [`Option`] and produces the contained +//! value +//! * [`iter`] produces an immutable reference of type `&T` to the +//! contained value +//! * [`iter_mut`] produces a mutable reference of type `&mut T` to the +//! contained value +//! +//! [`into_iter`]: Option::into_iter +//! [`iter`]: Option::iter +//! [`iter_mut`]: Option::iter_mut +//! +//! An iterator over [`Option`] can be useful when chaining iterators, for +//! example, to conditionally insert items. (It's not always necessary to +//! explicitly call an iterator constructor: many [`Iterator`] methods that +//! accept other iterators will also accept iterable types that implement +//! [`IntoIterator`], which includes [`Option`].) +//! +//! ``` +//! let yep = Some(42); +//! let nope = None; +//! // chain() already calls into_iter(), so we don't have to do so +//! let nums: Vec = (0..4).chain(yep).chain(4..8).collect(); +//! assert_eq!(nums, [0, 1, 2, 3, 42, 4, 5, 6, 7]); +//! let nums: Vec = (0..4).chain(nope).chain(4..8).collect(); +//! assert_eq!(nums, [0, 1, 2, 3, 4, 5, 6, 7]); +//! ``` +//! +//! One reason to chain iterators in this way is that a function returning +//! `impl Iterator` must have all possible return values be of the same +//! concrete type. Chaining an iterated [`Option`] can help with that. +//! +//! ``` +//! fn make_iter(do_insert: bool) -> impl Iterator { +//! // Explicit returns to illustrate return types matching +//! match do_insert { +//! true => return (0..4).chain(Some(42)).chain(4..8), +//! false => return (0..4).chain(None).chain(4..8), +//! } +//! } +//! println!("{:?}", make_iter(true).collect::>()); +//! println!("{:?}", make_iter(false).collect::>()); +//! ``` +//! +//! If we try to do the same thing, but using [`once()`] and [`empty()`], +//! we can't return `impl Iterator` anymore because the concrete types of +//! the return values differ. +//! +//! [`empty()`]: crate::iter::empty +//! [`once()`]: crate::iter::once +//! +//! ```compile_fail,E0308 +//! # use std::iter::{empty, once}; +//! // This won't compile because all possible returns from the function +//! // must have the same concrete type. +//! fn make_iter(do_insert: bool) -> impl Iterator { +//! // Explicit returns to illustrate return types not matching +//! match do_insert { +//! true => return (0..4).chain(once(42)).chain(4..8), +//! false => return (0..4).chain(empty()).chain(4..8), +//! } +//! } +//! ``` +//! +//! ## Collecting into `Option` +//! +//! [`Option`] implements the [`FromIterator`][impl-FromIterator] trait, +//! which allows an iterator over [`Option`] values to be collected into an +//! [`Option`] of a collection of each contained value of the original +//! [`Option`] values, or [`None`] if any of the elements was [`None`]. +//! +//! [impl-FromIterator]: Option#impl-FromIterator%3COption%3CA%3E%3E-for-Option%3CV%3E +//! +//! ``` +//! let v = [Some(2), Some(4), None, Some(8)]; +//! let res: Option> = v.into_iter().collect(); +//! assert_eq!(res, None); +//! let v = [Some(2), Some(4), Some(8)]; +//! let res: Option> = v.into_iter().collect(); +//! assert_eq!(res, Some(vec![2, 4, 8])); +//! ``` +//! +//! [`Option`] also implements the [`Product`][impl-Product] and +//! [`Sum`][impl-Sum] traits, allowing an iterator over [`Option`] values +//! to provide the [`product`][Iterator::product] and +//! [`sum`][Iterator::sum] methods. +//! +//! [impl-Product]: Option#impl-Product%3COption%3CU%3E%3E-for-Option%3CT%3E +//! [impl-Sum]: Option#impl-Sum%3COption%3CU%3E%3E-for-Option%3CT%3E +//! +//! ``` +//! let v = [None, Some(1), Some(2), Some(3)]; +//! let res: Option = v.into_iter().sum(); +//! assert_eq!(res, None); +//! let v = [Some(1), Some(2), Some(21)]; +//! let res: Option = v.into_iter().product(); +//! assert_eq!(res, Some(42)); +//! ``` +//! +//! ## Modifying an [`Option`] in-place +//! +//! These methods return a mutable reference to the contained value of an +//! [`Option`]: +//! +//! * [`insert`] inserts a value, dropping any old contents +//! * [`get_or_insert`] gets the current value, inserting a provided +//! default value if it is [`None`] +//! * [`get_or_insert_default`] gets the current value, inserting the +//! default value of type `T` (which must implement [`Default`]) if it is +//! [`None`] +//! * [`get_or_insert_with`] gets the current value, inserting a default +//! computed by the provided function if it is [`None`] +//! +//! [`get_or_insert`]: Option::get_or_insert +//! [`get_or_insert_default`]: Option::get_or_insert_default +//! [`get_or_insert_with`]: Option::get_or_insert_with +//! [`insert`]: Option::insert +//! +//! These methods transfer ownership of the contained value of an +//! [`Option`]: +//! +//! * [`take`] takes ownership of the contained value of an [`Option`], if +//! any, replacing the [`Option`] with [`None`] +//! * [`replace`] takes ownership of the contained value of an [`Option`], +//! if any, replacing the [`Option`] with a [`Some`] containing the +//! provided value +//! +//! [`replace`]: Option::replace +//! [`take`]: Option::take +//! +//! # Examples +//! +//! Basic pattern matching on [`Option`]: +//! +//! ``` +//! let msg = Some("howdy"); +//! +//! // Take a reference to the contained string +//! if let Some(m) = &msg { +//! println!("{}", *m); +//! } +//! +//! // Remove the contained string, destroying the Option +//! let unwrapped_msg = msg.unwrap_or("default message"); +//! ``` +//! +//! Initialize a result to [`None`] before a loop: +//! +//! ``` +//! enum Kingdom { Plant(u32, &'static str), Animal(u32, &'static str) } +//! +//! // A list of data to search through. +//! let all_the_big_things = [ +//! Kingdom::Plant(250, "redwood"), +//! Kingdom::Plant(230, "noble fir"), +//! Kingdom::Plant(229, "sugar pine"), +//! Kingdom::Animal(25, "blue whale"), +//! Kingdom::Animal(19, "fin whale"), +//! Kingdom::Animal(15, "north pacific right whale"), +//! ]; +//! +//! // We're going to search for the name of the biggest animal, +//! // but to start with we've just got `None`. +//! let mut name_of_biggest_animal = None; +//! let mut size_of_biggest_animal = 0; +//! for big_thing in &all_the_big_things { +//! match *big_thing { +//! Kingdom::Animal(size, name) if size > size_of_biggest_animal => { +//! // Now we've found the name of some big animal +//! size_of_biggest_animal = size; +//! name_of_biggest_animal = Some(name); +//! } +//! Kingdom::Animal(..) | Kingdom::Plant(..) => () +//! } +//! } +//! +//! match name_of_biggest_animal { +//! Some(name) => println!("the biggest animal is {name}"), +//! None => println!("there are no animals :("), +//! } +//! ``` + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::iter::{self, FusedIterator, TrustedLen}; +use crate::ops::{self, ControlFlow, Deref, DerefMut}; +use crate::panicking::{panic, panic_display}; +use crate::pin::Pin; +use crate::{cmp, convert, hint, mem, slice}; + +/// The `Option` type. See [the module level documentation](self) for more. +#[doc(search_unbox)] +#[derive(Copy, Eq, Debug, Hash)] +#[rustc_diagnostic_item = "Option"] +#[lang = "Option"] +#[stable(feature = "rust1", since = "1.0.0")] +#[allow(clippy::derived_hash_with_manual_eq)] // PartialEq is manually implemented equivalently +pub enum Option { + /// No value. + #[lang = "None"] + #[stable(feature = "rust1", since = "1.0.0")] + None, + /// Some value of type `T`. + #[lang = "Some"] + #[stable(feature = "rust1", since = "1.0.0")] + Some(#[stable(feature = "rust1", since = "1.0.0")] T), +} + +///////////////////////////////////////////////////////////////////////////// +// Type implementation +///////////////////////////////////////////////////////////////////////////// + +impl Option { + ///////////////////////////////////////////////////////////////////////// + // Querying the contained values + ///////////////////////////////////////////////////////////////////////// + + /// Returns `true` if the option is a [`Some`] value. + /// + /// # Examples + /// + /// ``` + /// let x: Option = Some(2); + /// assert_eq!(x.is_some(), true); + /// + /// let x: Option = None; + /// assert_eq!(x.is_some(), false); + /// ``` + #[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_option_basics", since = "1.48.0")] + pub const fn is_some(&self) -> bool { + matches!(*self, Some(_)) + } + + /// Returns `true` if the option is a [`Some`] and the value inside of it matches a predicate. + /// + /// # Examples + /// + /// ``` + /// let x: Option = Some(2); + /// assert_eq!(x.is_some_and(|x| x > 1), true); + /// + /// let x: Option = Some(0); + /// assert_eq!(x.is_some_and(|x| x > 1), false); + /// + /// let x: Option = None; + /// assert_eq!(x.is_some_and(|x| x > 1), false); + /// ``` + #[must_use] + #[inline] + #[stable(feature = "is_some_and", since = "1.70.0")] + pub fn is_some_and(self, f: impl FnOnce(T) -> bool) -> bool { + match self { + None => false, + Some(x) => f(x), + } + } + + /// Returns `true` if the option is a [`None`] value. + /// + /// # Examples + /// + /// ``` + /// let x: Option = Some(2); + /// assert_eq!(x.is_none(), false); + /// + /// let x: Option = None; + /// assert_eq!(x.is_none(), true); + /// ``` + #[must_use = "if you intended to assert that this doesn't have a value, consider \ + wrapping this in an `assert!()` instead"] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_option_basics", since = "1.48.0")] + pub const fn is_none(&self) -> bool { + !self.is_some() + } + + /// Returns `true` if the option is a [`None`] or the value inside of it matches a predicate. + /// + /// # Examples + /// + /// ``` + /// let x: Option = Some(2); + /// assert_eq!(x.is_none_or(|x| x > 1), true); + /// + /// let x: Option = Some(0); + /// assert_eq!(x.is_none_or(|x| x > 1), false); + /// + /// let x: Option = None; + /// assert_eq!(x.is_none_or(|x| x > 1), true); + /// ``` + #[must_use] + #[inline] + #[stable(feature = "is_none_or", since = "1.82.0")] + pub fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool { + match self { + None => true, + Some(x) => f(x), + } + } + + ///////////////////////////////////////////////////////////////////////// + // Adapter for working with references + ///////////////////////////////////////////////////////////////////////// + + /// Converts from `&Option` to `Option<&T>`. + /// + /// # Examples + /// + /// Calculates the length of an Option<[String]> as an Option<[usize]> + /// without moving the [`String`]. The [`map`] method takes the `self` argument by value, + /// consuming the original, so this technique uses `as_ref` to first take an `Option` to a + /// reference to the value inside the original. + /// + /// [`map`]: Option::map + /// [String]: ../../std/string/struct.String.html "String" + /// [`String`]: ../../std/string/struct.String.html "String" + /// + /// ``` + /// let text: Option = Some("Hello, world!".to_string()); + /// // First, cast `Option` to `Option<&String>` with `as_ref`, + /// // then consume *that* with `map`, leaving `text` on the stack. + /// let text_length: Option = text.as_ref().map(|s| s.len()); + /// println!("still can print text: {text:?}"); + /// ``` + #[inline] + #[rustc_const_stable(feature = "const_option_basics", since = "1.48.0")] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn as_ref(&self) -> Option<&T> { + match *self { + Some(ref x) => Some(x), + None => None, + } + } + + /// Converts from `&mut Option` to `Option<&mut T>`. + /// + /// # Examples + /// + /// ``` + /// let mut x = Some(2); + /// match x.as_mut() { + /// Some(v) => *v = 42, + /// None => {}, + /// } + /// assert_eq!(x, Some(42)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] + pub const fn as_mut(&mut self) -> Option<&mut T> { + match *self { + Some(ref mut x) => Some(x), + None => None, + } + } + + /// Converts from [Pin]<[&]Option\> to Option<[Pin]<[&]T>>. + /// + /// [&]: reference "shared reference" + #[inline] + #[must_use] + #[stable(feature = "pin", since = "1.33.0")] + #[rustc_const_stable(feature = "const_option_ext", since = "1.84.0")] + pub const fn as_pin_ref(self: Pin<&Self>) -> Option> { + // FIXME(const-hack): use `map` once that is possible + match Pin::get_ref(self).as_ref() { + // SAFETY: `x` is guaranteed to be pinned because it comes from `self` + // which is pinned. + Some(x) => unsafe { Some(Pin::new_unchecked(x)) }, + None => None, + } + } + + /// Converts from [Pin]<[&mut] Option\> to Option<[Pin]<[&mut] T>>. + /// + /// [&mut]: reference "mutable reference" + #[inline] + #[must_use] + #[stable(feature = "pin", since = "1.33.0")] + #[rustc_const_stable(feature = "const_option_ext", since = "1.84.0")] + pub const fn as_pin_mut(self: Pin<&mut Self>) -> Option> { + // SAFETY: `get_unchecked_mut` is never used to move the `Option` inside `self`. + // `x` is guaranteed to be pinned because it comes from `self` which is pinned. + unsafe { + // FIXME(const-hack): use `map` once that is possible + match Pin::get_unchecked_mut(self).as_mut() { + Some(x) => Some(Pin::new_unchecked(x)), + None => None, + } + } + } + + #[inline] + const fn len(&self) -> usize { + // Using the intrinsic avoids emitting a branch to get the 0 or 1. + let discriminant: isize = crate::intrinsics::discriminant_value(self); + discriminant as usize + } + + /// Returns a slice of the contained value, if any. If this is `None`, an + /// empty slice is returned. This can be useful to have a single type of + /// iterator over an `Option` or slice. + /// + /// Note: Should you have an `Option<&T>` and wish to get a slice of `T`, + /// you can unpack it via `opt.map_or(&[], std::slice::from_ref)`. + /// + /// # Examples + /// + /// ```rust + /// assert_eq!( + /// [Some(1234).as_slice(), None.as_slice()], + /// [&[1234][..], &[][..]], + /// ); + /// ``` + /// + /// The inverse of this function is (discounting + /// borrowing) [`[_]::first`](slice::first): + /// + /// ```rust + /// for i in [Some(1234_u16), None] { + /// assert_eq!(i.as_ref(), i.as_slice().first()); + /// } + /// ``` + #[inline] + #[must_use] + #[stable(feature = "option_as_slice", since = "1.75.0")] + #[rustc_const_stable(feature = "const_option_ext", since = "1.84.0")] + pub const fn as_slice(&self) -> &[T] { + // SAFETY: When the `Option` is `Some`, we're using the actual pointer + // to the payload, with a length of 1, so this is equivalent to + // `slice::from_ref`, and thus is safe. + // When the `Option` is `None`, the length used is 0, so to be safe it + // just needs to be aligned, which it is because `&self` is aligned and + // the offset used is a multiple of alignment. + // + // In the new version, the intrinsic always returns a pointer to an + // in-bounds and correctly aligned position for a `T` (even if in the + // `None` case it's just padding). + unsafe { + slice::from_raw_parts( + (self as *const Self).byte_add(core::mem::offset_of!(Self, Some.0)).cast(), + self.len(), + ) + } + } + + /// Returns a mutable slice of the contained value, if any. If this is + /// `None`, an empty slice is returned. This can be useful to have a + /// single type of iterator over an `Option` or slice. + /// + /// Note: Should you have an `Option<&mut T>` instead of a + /// `&mut Option`, which this method takes, you can obtain a mutable + /// slice via `opt.map_or(&mut [], std::slice::from_mut)`. + /// + /// # Examples + /// + /// ```rust + /// assert_eq!( + /// [Some(1234).as_mut_slice(), None.as_mut_slice()], + /// [&mut [1234][..], &mut [][..]], + /// ); + /// ``` + /// + /// The result is a mutable slice of zero or one items that points into + /// our original `Option`: + /// + /// ```rust + /// let mut x = Some(1234); + /// x.as_mut_slice()[0] += 1; + /// assert_eq!(x, Some(1235)); + /// ``` + /// + /// The inverse of this method (discounting borrowing) + /// is [`[_]::first_mut`](slice::first_mut): + /// + /// ```rust + /// assert_eq!(Some(123).as_mut_slice().first_mut(), Some(&mut 123)) + /// ``` + #[inline] + #[must_use] + #[stable(feature = "option_as_slice", since = "1.75.0")] + #[rustc_const_stable(feature = "const_option_ext", since = "1.84.0")] + pub const fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: When the `Option` is `Some`, we're using the actual pointer + // to the payload, with a length of 1, so this is equivalent to + // `slice::from_mut`, and thus is safe. + // When the `Option` is `None`, the length used is 0, so to be safe it + // just needs to be aligned, which it is because `&self` is aligned and + // the offset used is a multiple of alignment. + // + // In the new version, the intrinsic creates a `*const T` from a + // mutable reference so it is safe to cast back to a mutable pointer + // here. As with `as_slice`, the intrinsic always returns a pointer to + // an in-bounds and correctly aligned position for a `T` (even if in + // the `None` case it's just padding). + unsafe { + slice::from_raw_parts_mut( + (self as *mut Self).byte_add(core::mem::offset_of!(Self, Some.0)).cast(), + self.len(), + ) + } + } + + ///////////////////////////////////////////////////////////////////////// + // Getting to contained values + ///////////////////////////////////////////////////////////////////////// + + /// Returns the contained [`Some`] value, consuming the `self` value. + /// + /// # Panics + /// + /// Panics if the value is a [`None`] with a custom panic message provided by + /// `msg`. + /// + /// # Examples + /// + /// ``` + /// let x = Some("value"); + /// assert_eq!(x.expect("fruits are healthy"), "value"); + /// ``` + /// + /// ```should_panic + /// let x: Option<&str> = None; + /// x.expect("fruits are healthy"); // panics with `fruits are healthy` + /// ``` + /// + /// # Recommended Message Style + /// + /// We recommend that `expect` messages are used to describe the reason you + /// _expect_ the `Option` should be `Some`. + /// + /// ```should_panic + /// # let slice: &[u8] = &[]; + /// let item = slice.get(0) + /// .expect("slice should not be empty"); + /// ``` + /// + /// **Hint**: If you're having trouble remembering how to phrase expect + /// error messages remember to focus on the word "should" as in "env + /// variable should be set by blah" or "the given binary should be available + /// and executable by the current user". + /// + /// For more detail on expect message styles and the reasoning behind our + /// recommendation please refer to the section on ["Common Message + /// Styles"](../../std/error/index.html#common-message-styles) in the [`std::error`](../../std/error/index.html) module docs. + #[inline] + #[track_caller] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "option_expect")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] + pub const fn expect(self, msg: &str) -> T { + match self { + Some(val) => val, + None => expect_failed(msg), + } + } + + /// Returns the contained [`Some`] value, consuming the `self` value. + /// + /// Because this function may panic, its use is generally discouraged. + /// Instead, prefer to use pattern matching and handle the [`None`] + /// case explicitly, or call [`unwrap_or`], [`unwrap_or_else`], or + /// [`unwrap_or_default`]. + /// + /// [`unwrap_or`]: Option::unwrap_or + /// [`unwrap_or_else`]: Option::unwrap_or_else + /// [`unwrap_or_default`]: Option::unwrap_or_default + /// + /// # Panics + /// + /// Panics if the self value equals [`None`]. + /// + /// # Examples + /// + /// ``` + /// let x = Some("air"); + /// assert_eq!(x.unwrap(), "air"); + /// ``` + /// + /// ```should_panic + /// let x: Option<&str> = None; + /// assert_eq!(x.unwrap(), "air"); // fails + /// ``` + #[inline(always)] + #[track_caller] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "option_unwrap")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] + pub const fn unwrap(self) -> T { + match self { + Some(val) => val, + None => unwrap_failed(), + } + } + + /// Returns the contained [`Some`] value or a provided default. + /// + /// Arguments passed to `unwrap_or` are eagerly evaluated; if you are passing + /// the result of a function call, it is recommended to use [`unwrap_or_else`], + /// which is lazily evaluated. + /// + /// [`unwrap_or_else`]: Option::unwrap_or_else + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Some("car").unwrap_or("bike"), "car"); + /// assert_eq!(None.unwrap_or("bike"), "bike"); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn unwrap_or(self, default: T) -> T { + match self { + Some(x) => x, + None => default, + } + } + + /// Returns the contained [`Some`] value or computes it from a closure. + /// + /// # Examples + /// + /// ``` + /// let k = 10; + /// assert_eq!(Some(4).unwrap_or_else(|| 2 * k), 4); + /// assert_eq!(None.unwrap_or_else(|| 2 * k), 20); + /// ``` + #[inline] + #[track_caller] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn unwrap_or_else(self, f: F) -> T + where + F: FnOnce() -> T, + { + match self { + Some(x) => x, + None => f(), + } + } + + /// Returns the contained [`Some`] value or a default. + /// + /// Consumes the `self` argument then, if [`Some`], returns the contained + /// value, otherwise if [`None`], returns the [default value] for that + /// type. + /// + /// # Examples + /// + /// ``` + /// let x: Option = None; + /// let y: Option = Some(12); + /// + /// assert_eq!(x.unwrap_or_default(), 0); + /// assert_eq!(y.unwrap_or_default(), 12); + /// ``` + /// + /// [default value]: Default::default + /// [`parse`]: str::parse + /// [`FromStr`]: crate::str::FromStr + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn unwrap_or_default(self) -> T + where + T: Default, + { + match self { + Some(x) => x, + None => T::default(), + } + } + + /// Returns the contained [`Some`] value, consuming the `self` value, + /// without checking that the value is not [`None`]. + /// + /// # Safety + /// + /// Calling this method on [`None`] is *[undefined behavior]*. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ``` + /// let x = Some("air"); + /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air"); + /// ``` + /// + /// ```no_run + /// let x: Option<&str> = None; + /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air"); // Undefined behavior! + /// ``` + #[inline] + #[track_caller] + #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] + pub const unsafe fn unwrap_unchecked(self) -> T { + match self { + Some(val) => val, + // SAFETY: the safety contract must be upheld by the caller. + None => unsafe { hint::unreachable_unchecked() }, + } + } + + ///////////////////////////////////////////////////////////////////////// + // Transforming contained values + ///////////////////////////////////////////////////////////////////////// + + /// Maps an `Option` to `Option` by applying a function to a contained value (if `Some`) or returns `None` (if `None`). + /// + /// # Examples + /// + /// Calculates the length of an Option<[String]> as an + /// Option<[usize]>, consuming the original: + /// + /// [String]: ../../std/string/struct.String.html "String" + /// ``` + /// let maybe_some_string = Some(String::from("Hello, World!")); + /// // `Option::map` takes self *by value*, consuming `maybe_some_string` + /// let maybe_some_len = maybe_some_string.map(|s| s.len()); + /// assert_eq!(maybe_some_len, Some(13)); + /// + /// let x: Option<&str> = None; + /// assert_eq!(x.map(|s| s.len()), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn map(self, f: F) -> Option + where + F: FnOnce(T) -> U, + { + match self { + Some(x) => Some(f(x)), + None => None, + } + } + + /// Calls a function with a reference to the contained value if [`Some`]. + /// + /// Returns the original option. + /// + /// # Examples + /// + /// ``` + /// let list = vec![1, 2, 3]; + /// + /// // prints "got: 2" + /// let x = list + /// .get(1) + /// .inspect(|x| println!("got: {x}")) + /// .expect("list should be long enough"); + /// + /// // prints nothing + /// list.get(5).inspect(|x| println!("got: {x}")); + /// ``` + #[inline] + #[stable(feature = "result_option_inspect", since = "1.76.0")] + pub fn inspect(self, f: F) -> Self { + if let Some(ref x) = self { + f(x); + } + + self + } + + /// Returns the provided default result (if none), + /// or applies a function to the contained value (if any). + /// + /// Arguments passed to `map_or` are eagerly evaluated; if you are passing + /// the result of a function call, it is recommended to use [`map_or_else`], + /// which is lazily evaluated. + /// + /// [`map_or_else`]: Option::map_or_else + /// + /// # Examples + /// + /// ``` + /// let x = Some("foo"); + /// assert_eq!(x.map_or(42, |v| v.len()), 3); + /// + /// let x: Option<&str> = None; + /// assert_eq!(x.map_or(42, |v| v.len()), 42); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "if you don't need the returned value, use `if let` instead"] + pub fn map_or(self, default: U, f: F) -> U + where + F: FnOnce(T) -> U, + { + match self { + Some(t) => f(t), + None => default, + } + } + + /// Computes a default function result (if none), or + /// applies a different function to the contained value (if any). + /// + /// # Basic examples + /// + /// ``` + /// let k = 21; + /// + /// let x = Some("foo"); + /// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 3); + /// + /// let x: Option<&str> = None; + /// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42); + /// ``` + /// + /// # Handling a Result-based fallback + /// + /// A somewhat common occurrence when dealing with optional values + /// in combination with [`Result`] is the case where one wants to invoke + /// a fallible fallback if the option is not present. This example + /// parses a command line argument (if present), or the contents of a file to + /// an integer. However, unlike accessing the command line argument, reading + /// the file is fallible, so it must be wrapped with `Ok`. + /// + /// ```no_run + /// # fn main() -> Result<(), Box> { + /// let v: u64 = std::env::args() + /// .nth(1) + /// .map_or_else(|| std::fs::read_to_string("/etc/someconfig.conf"), Ok)? + /// .parse()?; + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn map_or_else(self, default: D, f: F) -> U + where + D: FnOnce() -> U, + F: FnOnce(T) -> U, + { + match self { + Some(t) => f(t), + None => default(), + } + } + + /// Transforms the `Option` into a [`Result`], mapping [`Some(v)`] to + /// [`Ok(v)`] and [`None`] to [`Err(err)`]. + /// + /// Arguments passed to `ok_or` are eagerly evaluated; if you are passing the + /// result of a function call, it is recommended to use [`ok_or_else`], which is + /// lazily evaluated. + /// + /// [`Ok(v)`]: Ok + /// [`Err(err)`]: Err + /// [`Some(v)`]: Some + /// [`ok_or_else`]: Option::ok_or_else + /// + /// # Examples + /// + /// ``` + /// let x = Some("foo"); + /// assert_eq!(x.ok_or(0), Ok("foo")); + /// + /// let x: Option<&str> = None; + /// assert_eq!(x.ok_or(0), Err(0)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ok_or(self, err: E) -> Result { + match self { + Some(v) => Ok(v), + None => Err(err), + } + } + + /// Transforms the `Option` into a [`Result`], mapping [`Some(v)`] to + /// [`Ok(v)`] and [`None`] to [`Err(err())`]. + /// + /// [`Ok(v)`]: Ok + /// [`Err(err())`]: Err + /// [`Some(v)`]: Some + /// + /// # Examples + /// + /// ``` + /// let x = Some("foo"); + /// assert_eq!(x.ok_or_else(|| 0), Ok("foo")); + /// + /// let x: Option<&str> = None; + /// assert_eq!(x.ok_or_else(|| 0), Err(0)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ok_or_else(self, err: F) -> Result + where + F: FnOnce() -> E, + { + match self { + Some(v) => Ok(v), + None => Err(err()), + } + } + + /// Converts from `Option` (or `&Option`) to `Option<&T::Target>`. + /// + /// Leaves the original Option in-place, creating a new one with a reference + /// to the original one, additionally coercing the contents via [`Deref`]. + /// + /// # Examples + /// + /// ``` + /// let x: Option = Some("hey".to_owned()); + /// assert_eq!(x.as_deref(), Some("hey")); + /// + /// let x: Option = None; + /// assert_eq!(x.as_deref(), None); + /// ``` + #[inline] + #[stable(feature = "option_deref", since = "1.40.0")] + pub fn as_deref(&self) -> Option<&T::Target> + where + T: Deref, + { + self.as_ref().map(|t| t.deref()) + } + + /// Converts from `Option` (or `&mut Option`) to `Option<&mut T::Target>`. + /// + /// Leaves the original `Option` in-place, creating a new one containing a mutable reference to + /// the inner type's [`Deref::Target`] type. + /// + /// # Examples + /// + /// ``` + /// let mut x: Option = Some("hey".to_owned()); + /// assert_eq!(x.as_deref_mut().map(|x| { + /// x.make_ascii_uppercase(); + /// x + /// }), Some("HEY".to_owned().as_mut_str())); + /// ``` + #[inline] + #[stable(feature = "option_deref", since = "1.40.0")] + pub fn as_deref_mut(&mut self) -> Option<&mut T::Target> + where + T: DerefMut, + { + self.as_mut().map(|t| t.deref_mut()) + } + + ///////////////////////////////////////////////////////////////////////// + // Iterator constructors + ///////////////////////////////////////////////////////////////////////// + + /// Returns an iterator over the possibly contained value. + /// + /// # Examples + /// + /// ``` + /// let x = Some(4); + /// assert_eq!(x.iter().next(), Some(&4)); + /// + /// let x: Option = None; + /// assert_eq!(x.iter().next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter(&self) -> Iter<'_, T> { + Iter { inner: Item { opt: self.as_ref() } } + } + + /// Returns a mutable iterator over the possibly contained value. + /// + /// # Examples + /// + /// ``` + /// let mut x = Some(4); + /// match x.iter_mut().next() { + /// Some(v) => *v = 42, + /// None => {}, + /// } + /// assert_eq!(x, Some(42)); + /// + /// let mut x: Option = None; + /// assert_eq!(x.iter_mut().next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter_mut(&mut self) -> IterMut<'_, T> { + IterMut { inner: Item { opt: self.as_mut() } } + } + + ///////////////////////////////////////////////////////////////////////// + // Boolean operations on the values, eager and lazy + ///////////////////////////////////////////////////////////////////////// + + /// Returns [`None`] if the option is [`None`], otherwise returns `optb`. + /// + /// Arguments passed to `and` are eagerly evaluated; if you are passing the + /// result of a function call, it is recommended to use [`and_then`], which is + /// lazily evaluated. + /// + /// [`and_then`]: Option::and_then + /// + /// # Examples + /// + /// ``` + /// let x = Some(2); + /// let y: Option<&str> = None; + /// assert_eq!(x.and(y), None); + /// + /// let x: Option = None; + /// let y = Some("foo"); + /// assert_eq!(x.and(y), None); + /// + /// let x = Some(2); + /// let y = Some("foo"); + /// assert_eq!(x.and(y), Some("foo")); + /// + /// let x: Option = None; + /// let y: Option<&str> = None; + /// assert_eq!(x.and(y), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn and(self, optb: Option) -> Option { + match self { + Some(_) => optb, + None => None, + } + } + + /// Returns [`None`] if the option is [`None`], otherwise calls `f` with the + /// wrapped value and returns the result. + /// + /// Some languages call this operation flatmap. + /// + /// # Examples + /// + /// ``` + /// fn sq_then_to_string(x: u32) -> Option { + /// x.checked_mul(x).map(|sq| sq.to_string()) + /// } + /// + /// assert_eq!(Some(2).and_then(sq_then_to_string), Some(4.to_string())); + /// assert_eq!(Some(1_000_000).and_then(sq_then_to_string), None); // overflowed! + /// assert_eq!(None.and_then(sq_then_to_string), None); + /// ``` + /// + /// Often used to chain fallible operations that may return [`None`]. + /// + /// ``` + /// let arr_2d = [["A0", "A1"], ["B0", "B1"]]; + /// + /// let item_0_1 = arr_2d.get(0).and_then(|row| row.get(1)); + /// assert_eq!(item_0_1, Some(&"A1")); + /// + /// let item_2_0 = arr_2d.get(2).and_then(|row| row.get(0)); + /// assert_eq!(item_2_0, None); + /// ``` + #[doc(alias = "flatmap")] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("flat_map", "flatmap")] + pub fn and_then(self, f: F) -> Option + where + F: FnOnce(T) -> Option, + { + match self { + Some(x) => f(x), + None => None, + } + } + + /// Returns [`None`] if the option is [`None`], otherwise calls `predicate` + /// with the wrapped value and returns: + /// + /// - [`Some(t)`] if `predicate` returns `true` (where `t` is the wrapped + /// value), and + /// - [`None`] if `predicate` returns `false`. + /// + /// This function works similar to [`Iterator::filter()`]. You can imagine + /// the `Option` being an iterator over one or zero elements. `filter()` + /// lets you decide which elements to keep. + /// + /// # Examples + /// + /// ```rust + /// fn is_even(n: &i32) -> bool { + /// n % 2 == 0 + /// } + /// + /// assert_eq!(None.filter(is_even), None); + /// assert_eq!(Some(3).filter(is_even), None); + /// assert_eq!(Some(4).filter(is_even), Some(4)); + /// ``` + /// + /// [`Some(t)`]: Some + #[inline] + #[stable(feature = "option_filter", since = "1.27.0")] + pub fn filter

(self, predicate: P) -> Self + where + P: FnOnce(&T) -> bool, + { + if let Some(x) = self { + if predicate(&x) { + return Some(x); + } + } + None + } + + /// Returns the option if it contains a value, otherwise returns `optb`. + /// + /// Arguments passed to `or` are eagerly evaluated; if you are passing the + /// result of a function call, it is recommended to use [`or_else`], which is + /// lazily evaluated. + /// + /// [`or_else`]: Option::or_else + /// + /// # Examples + /// + /// ``` + /// let x = Some(2); + /// let y = None; + /// assert_eq!(x.or(y), Some(2)); + /// + /// let x = None; + /// let y = Some(100); + /// assert_eq!(x.or(y), Some(100)); + /// + /// let x = Some(2); + /// let y = Some(100); + /// assert_eq!(x.or(y), Some(2)); + /// + /// let x: Option = None; + /// let y = None; + /// assert_eq!(x.or(y), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn or(self, optb: Option) -> Option { + match self { + x @ Some(_) => x, + None => optb, + } + } + + /// Returns the option if it contains a value, otherwise calls `f` and + /// returns the result. + /// + /// # Examples + /// + /// ``` + /// fn nobody() -> Option<&'static str> { None } + /// fn vikings() -> Option<&'static str> { Some("vikings") } + /// + /// assert_eq!(Some("barbarians").or_else(vikings), Some("barbarians")); + /// assert_eq!(None.or_else(vikings), Some("vikings")); + /// assert_eq!(None.or_else(nobody), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn or_else(self, f: F) -> Option + where + F: FnOnce() -> Option, + { + match self { + x @ Some(_) => x, + None => f(), + } + } + + /// Returns [`Some`] if exactly one of `self`, `optb` is [`Some`], otherwise returns [`None`]. + /// + /// # Examples + /// + /// ``` + /// let x = Some(2); + /// let y: Option = None; + /// assert_eq!(x.xor(y), Some(2)); + /// + /// let x: Option = None; + /// let y = Some(2); + /// assert_eq!(x.xor(y), Some(2)); + /// + /// let x = Some(2); + /// let y = Some(2); + /// assert_eq!(x.xor(y), None); + /// + /// let x: Option = None; + /// let y: Option = None; + /// assert_eq!(x.xor(y), None); + /// ``` + #[inline] + #[stable(feature = "option_xor", since = "1.37.0")] + pub fn xor(self, optb: Option) -> Option { + match (self, optb) { + (a @ Some(_), None) => a, + (None, b @ Some(_)) => b, + _ => None, + } + } + + ///////////////////////////////////////////////////////////////////////// + // Entry-like operations to insert a value and return a reference + ///////////////////////////////////////////////////////////////////////// + + /// Inserts `value` into the option, then returns a mutable reference to it. + /// + /// If the option already contains a value, the old value is dropped. + /// + /// See also [`Option::get_or_insert`], which doesn't update the value if + /// the option already contains [`Some`]. + /// + /// # Example + /// + /// ``` + /// let mut opt = None; + /// let val = opt.insert(1); + /// assert_eq!(*val, 1); + /// assert_eq!(opt.unwrap(), 1); + /// let val = opt.insert(2); + /// assert_eq!(*val, 2); + /// *val = 3; + /// assert_eq!(opt.unwrap(), 3); + /// ``` + #[must_use = "if you intended to set a value, consider assignment instead"] + #[inline] + #[stable(feature = "option_insert", since = "1.53.0")] + pub fn insert(&mut self, value: T) -> &mut T { + *self = Some(value); + + // SAFETY: the code above just filled the option + unsafe { self.as_mut().unwrap_unchecked() } + } + + /// Inserts `value` into the option if it is [`None`], then + /// returns a mutable reference to the contained value. + /// + /// See also [`Option::insert`], which updates the value even if + /// the option already contains [`Some`]. + /// + /// # Examples + /// + /// ``` + /// let mut x = None; + /// + /// { + /// let y: &mut u32 = x.get_or_insert(5); + /// assert_eq!(y, &5); + /// + /// *y = 7; + /// } + /// + /// assert_eq!(x, Some(7)); + /// ``` + #[inline] + #[stable(feature = "option_entry", since = "1.20.0")] + pub fn get_or_insert(&mut self, value: T) -> &mut T { + self.get_or_insert_with(|| value) + } + + /// Inserts the default value into the option if it is [`None`], then + /// returns a mutable reference to the contained value. + /// + /// # Examples + /// + /// ``` + /// let mut x = None; + /// + /// { + /// let y: &mut u32 = x.get_or_insert_default(); + /// assert_eq!(y, &0); + /// + /// *y = 7; + /// } + /// + /// assert_eq!(x, Some(7)); + /// ``` + #[inline] + #[stable(feature = "option_get_or_insert_default", since = "1.83.0")] + pub fn get_or_insert_default(&mut self) -> &mut T + where + T: Default, + { + self.get_or_insert_with(T::default) + } + + /// Inserts a value computed from `f` into the option if it is [`None`], + /// then returns a mutable reference to the contained value. + /// + /// # Examples + /// + /// ``` + /// let mut x = None; + /// + /// { + /// let y: &mut u32 = x.get_or_insert_with(|| 5); + /// assert_eq!(y, &5); + /// + /// *y = 7; + /// } + /// + /// assert_eq!(x, Some(7)); + /// ``` + #[inline] + #[stable(feature = "option_entry", since = "1.20.0")] + pub fn get_or_insert_with(&mut self, f: F) -> &mut T + where + F: FnOnce() -> T, + { + if let None = self { + *self = Some(f()); + } + + // SAFETY: a `None` variant for `self` would have been replaced by a `Some` + // variant in the code above. + unsafe { self.as_mut().unwrap_unchecked() } + } + + ///////////////////////////////////////////////////////////////////////// + // Misc + ///////////////////////////////////////////////////////////////////////// + + /// Takes the value out of the option, leaving a [`None`] in its place. + /// + /// # Examples + /// + /// ``` + /// let mut x = Some(2); + /// let y = x.take(); + /// assert_eq!(x, None); + /// assert_eq!(y, Some(2)); + /// + /// let mut x: Option = None; + /// let y = x.take(); + /// assert_eq!(x, None); + /// assert_eq!(y, None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] + pub const fn take(&mut self) -> Option { + // FIXME(const-hack) replace `mem::replace` by `mem::take` when the latter is const ready + mem::replace(self, None) + } + + /// Takes the value out of the option, but only if the predicate evaluates to + /// `true` on a mutable reference to the value. + /// + /// In other words, replaces `self` with `None` if the predicate returns `true`. + /// This method operates similar to [`Option::take`] but conditional. + /// + /// # Examples + /// + /// ``` + /// let mut x = Some(42); + /// + /// let prev = x.take_if(|v| if *v == 42 { + /// *v += 1; + /// false + /// } else { + /// false + /// }); + /// assert_eq!(x, Some(43)); + /// assert_eq!(prev, None); + /// + /// let prev = x.take_if(|v| *v == 43); + /// assert_eq!(x, None); + /// assert_eq!(prev, Some(43)); + /// ``` + #[inline] + #[stable(feature = "option_take_if", since = "1.80.0")] + pub fn take_if

(&mut self, predicate: P) -> Option + where + P: FnOnce(&mut T) -> bool, + { + if self.as_mut().map_or(false, predicate) { self.take() } else { None } + } + + /// Replaces the actual value in the option by the value given in parameter, + /// returning the old value if present, + /// leaving a [`Some`] in its place without deinitializing either one. + /// + /// # Examples + /// + /// ``` + /// let mut x = Some(2); + /// let old = x.replace(5); + /// assert_eq!(x, Some(5)); + /// assert_eq!(old, Some(2)); + /// + /// let mut x = None; + /// let old = x.replace(3); + /// assert_eq!(x, Some(3)); + /// assert_eq!(old, None); + /// ``` + #[inline] + #[stable(feature = "option_replace", since = "1.31.0")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] + pub const fn replace(&mut self, value: T) -> Option { + mem::replace(self, Some(value)) + } + + /// Zips `self` with another `Option`. + /// + /// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some((s, o))`. + /// Otherwise, `None` is returned. + /// + /// # Examples + /// + /// ``` + /// let x = Some(1); + /// let y = Some("hi"); + /// let z = None::; + /// + /// assert_eq!(x.zip(y), Some((1, "hi"))); + /// assert_eq!(x.zip(z), None); + /// ``` + #[stable(feature = "option_zip_option", since = "1.46.0")] + pub fn zip(self, other: Option) -> Option<(T, U)> { + match (self, other) { + (Some(a), Some(b)) => Some((a, b)), + _ => None, + } + } + + /// Zips `self` and another `Option` with function `f`. + /// + /// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some(f(s, o))`. + /// Otherwise, `None` is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_zip)] + /// + /// #[derive(Debug, PartialEq)] + /// struct Point { + /// x: f64, + /// y: f64, + /// } + /// + /// impl Point { + /// fn new(x: f64, y: f64) -> Self { + /// Self { x, y } + /// } + /// } + /// + /// let x = Some(17.5); + /// let y = Some(42.7); + /// + /// assert_eq!(x.zip_with(y, Point::new), Some(Point { x: 17.5, y: 42.7 })); + /// assert_eq!(x.zip_with(None, Point::new), None); + /// ``` + #[unstable(feature = "option_zip", issue = "70086")] + pub fn zip_with(self, other: Option, f: F) -> Option + where + F: FnOnce(T, U) -> R, + { + match (self, other) { + (Some(a), Some(b)) => Some(f(a, b)), + _ => None, + } + } +} + +impl Option<(T, U)> { + /// Unzips an option containing a tuple of two options. + /// + /// If `self` is `Some((a, b))` this method returns `(Some(a), Some(b))`. + /// Otherwise, `(None, None)` is returned. + /// + /// # Examples + /// + /// ``` + /// let x = Some((1, "hi")); + /// let y = None::<(u8, u32)>; + /// + /// assert_eq!(x.unzip(), (Some(1), Some("hi"))); + /// assert_eq!(y.unzip(), (None, None)); + /// ``` + #[inline] + #[stable(feature = "unzip_option", since = "1.66.0")] + pub fn unzip(self) -> (Option, Option) { + match self { + Some((a, b)) => (Some(a), Some(b)), + None => (None, None), + } + } +} + +impl Option<&T> { + /// Maps an `Option<&T>` to an `Option` by copying the contents of the + /// option. + /// + /// # Examples + /// + /// ``` + /// let x = 12; + /// let opt_x = Some(&x); + /// assert_eq!(opt_x, Some(&12)); + /// let copied = opt_x.copied(); + /// assert_eq!(copied, Some(12)); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "copied", since = "1.35.0")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] + pub const fn copied(self) -> Option + where + T: Copy, + { + // FIXME(const-hack): this implementation, which sidesteps using `Option::map` since it's not const + // ready yet, should be reverted when possible to avoid code repetition + match self { + Some(&v) => Some(v), + None => None, + } + } + + /// Maps an `Option<&T>` to an `Option` by cloning the contents of the + /// option. + /// + /// # Examples + /// + /// ``` + /// let x = 12; + /// let opt_x = Some(&x); + /// assert_eq!(opt_x, Some(&12)); + /// let cloned = opt_x.cloned(); + /// assert_eq!(cloned, Some(12)); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn cloned(self) -> Option + where + T: Clone, + { + match self { + Some(t) => Some(t.clone()), + None => None, + } + } +} + +impl Option<&mut T> { + /// Maps an `Option<&mut T>` to an `Option` by copying the contents of the + /// option. + /// + /// # Examples + /// + /// ``` + /// let mut x = 12; + /// let opt_x = Some(&mut x); + /// assert_eq!(opt_x, Some(&mut 12)); + /// let copied = opt_x.copied(); + /// assert_eq!(copied, Some(12)); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "copied", since = "1.35.0")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] + pub const fn copied(self) -> Option + where + T: Copy, + { + match self { + Some(&mut t) => Some(t), + None => None, + } + } + + /// Maps an `Option<&mut T>` to an `Option` by cloning the contents of the + /// option. + /// + /// # Examples + /// + /// ``` + /// let mut x = 12; + /// let opt_x = Some(&mut x); + /// assert_eq!(opt_x, Some(&mut 12)); + /// let cloned = opt_x.cloned(); + /// assert_eq!(cloned, Some(12)); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(since = "1.26.0", feature = "option_ref_mut_cloned")] + pub fn cloned(self) -> Option + where + T: Clone, + { + match self { + Some(t) => Some(t.clone()), + None => None, + } + } +} + +impl Option> { + /// Transposes an `Option` of a [`Result`] into a [`Result`] of an `Option`. + /// + /// [`None`] will be mapped to [Ok]\([None]). + /// [Some]\([Ok]\(\_)) and [Some]\([Err]\(\_)) will be mapped to + /// [Ok]\([Some]\(\_)) and [Err]\(\_). + /// + /// # Examples + /// + /// ``` + /// #[derive(Debug, Eq, PartialEq)] + /// struct SomeErr; + /// + /// let x: Result, SomeErr> = Ok(Some(5)); + /// let y: Option> = Some(Ok(5)); + /// assert_eq!(x, y.transpose()); + /// ``` + #[inline] + #[stable(feature = "transpose_result", since = "1.33.0")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] + pub const fn transpose(self) -> Result, E> { + match self { + Some(Ok(x)) => Ok(Some(x)), + Some(Err(e)) => Err(e), + None => Ok(None), + } + } +} + +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cold] +#[track_caller] +const fn unwrap_failed() -> ! { + panic("called `Option::unwrap()` on a `None` value") +} + +// This is a separate function to reduce the code size of .expect() itself. +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cold] +#[track_caller] +const fn expect_failed(msg: &str) -> ! { + panic_display(&msg) +} + +///////////////////////////////////////////////////////////////////////////// +// Trait implementations +///////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Option +where + T: Clone, +{ + #[inline] + fn clone(&self) -> Self { + match self { + Some(x) => Some(x.clone()), + None => None, + } + } + + #[inline] + fn clone_from(&mut self, source: &Self) { + match (self, source) { + (Some(to), Some(from)) => to.clone_from(from), + (to, from) => *to = from.clone(), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Option { + /// Returns [`None`][Option::None]. + /// + /// # Examples + /// + /// ``` + /// let opt: Option = Option::default(); + /// assert!(opt.is_none()); + /// ``` + #[inline] + fn default() -> Option { + None + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for Option { + type Item = T; + type IntoIter = IntoIter; + + /// Returns a consuming iterator over the possibly contained value. + /// + /// # Examples + /// + /// ``` + /// let x = Some("string"); + /// let v: Vec<&str> = x.into_iter().collect(); + /// assert_eq!(v, ["string"]); + /// + /// let x = None; + /// let v: Vec<&str> = x.into_iter().collect(); + /// assert!(v.is_empty()); + /// ``` + #[inline] + fn into_iter(self) -> IntoIter { + IntoIter { inner: Item { opt: self } } + } +} + +#[stable(since = "1.4.0", feature = "option_iter")] +impl<'a, T> IntoIterator for &'a Option { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +#[stable(since = "1.4.0", feature = "option_iter")] +impl<'a, T> IntoIterator for &'a mut Option { + type Item = &'a mut T; + type IntoIter = IterMut<'a, T>; + + fn into_iter(self) -> IterMut<'a, T> { + self.iter_mut() + } +} + +#[stable(since = "1.12.0", feature = "option_from")] +impl From for Option { + /// Moves `val` into a new [`Some`]. + /// + /// # Examples + /// + /// ``` + /// let o: Option = Option::from(67); + /// + /// assert_eq!(Some(67), o); + /// ``` + fn from(val: T) -> Option { + Some(val) + } +} + +#[stable(feature = "option_ref_from_ref_option", since = "1.30.0")] +impl<'a, T> From<&'a Option> for Option<&'a T> { + /// Converts from `&Option` to `Option<&T>`. + /// + /// # Examples + /// + /// Converts an [Option]<[String]> into an [Option]<[usize]>, preserving + /// the original. The [`map`] method takes the `self` argument by value, consuming the original, + /// so this technique uses `from` to first take an [`Option`] to a reference + /// to the value inside the original. + /// + /// [`map`]: Option::map + /// [String]: ../../std/string/struct.String.html "String" + /// + /// ``` + /// let s: Option = Some(String::from("Hello, Rustaceans!")); + /// let o: Option = Option::from(&s).map(|ss: &String| ss.len()); + /// + /// println!("Can still print s: {s:?}"); + /// + /// assert_eq!(o, Some(18)); + /// ``` + fn from(o: &'a Option) -> Option<&'a T> { + o.as_ref() + } +} + +#[stable(feature = "option_ref_from_ref_option", since = "1.30.0")] +impl<'a, T> From<&'a mut Option> for Option<&'a mut T> { + /// Converts from `&mut Option` to `Option<&mut T>` + /// + /// # Examples + /// + /// ``` + /// let mut s = Some(String::from("Hello")); + /// let o: Option<&mut String> = Option::from(&mut s); + /// + /// match o { + /// Some(t) => *t = String::from("Hello, Rustaceans!"), + /// None => (), + /// } + /// + /// assert_eq!(s, Some(String::from("Hello, Rustaceans!"))); + /// ``` + fn from(o: &'a mut Option) -> Option<&'a mut T> { + o.as_mut() + } +} + +// Ideally, LLVM should be able to optimize our derive code to this. +// Once https://github.com/llvm/llvm-project/issues/52622 is fixed, we can +// go back to deriving `PartialEq`. +#[stable(feature = "rust1", since = "1.0.0")] +impl crate::marker::StructuralPartialEq for Option {} +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for Option { + #[inline] + fn eq(&self, other: &Self) -> bool { + // Spelling out the cases explicitly optimizes better than + // `_ => false` + match (self, other) { + (Some(l), Some(r)) => *l == *r, + (Some(_), None) => false, + (None, Some(_)) => false, + (None, None) => true, + } + } +} + +// Manually implementing here somewhat improves codegen for +// https://github.com/rust-lang/rust/issues/49892, although still +// not optimal. +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Option { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + match (self, other) { + (Some(l), Some(r)) => l.partial_cmp(r), + (Some(_), None) => Some(cmp::Ordering::Greater), + (None, Some(_)) => Some(cmp::Ordering::Less), + (None, None) => Some(cmp::Ordering::Equal), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Option { + #[inline] + fn cmp(&self, other: &Self) -> cmp::Ordering { + match (self, other) { + (Some(l), Some(r)) => l.cmp(r), + (Some(_), None) => cmp::Ordering::Greater, + (None, Some(_)) => cmp::Ordering::Less, + (None, None) => cmp::Ordering::Equal, + } + } +} + +///////////////////////////////////////////////////////////////////////////// +// The Option Iterators +///////////////////////////////////////////////////////////////////////////// + +#[derive(Clone, Debug)] +struct Item { + opt: Option, +} + +impl Iterator for Item { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + self.opt.take() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +impl DoubleEndedIterator for Item { + #[inline] + fn next_back(&mut self) -> Option { + self.opt.take() + } +} + +impl ExactSizeIterator for Item { + #[inline] + fn len(&self) -> usize { + self.opt.len() + } +} +impl FusedIterator for Item {} +unsafe impl TrustedLen for Item {} + +/// An iterator over a reference to the [`Some`] variant of an [`Option`]. +/// +/// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none. +/// +/// This `struct` is created by the [`Option::iter`] function. +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct Iter<'a, A: 'a> { + inner: Item<&'a A>, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, A> Iterator for Iter<'a, A> { + type Item = &'a A; + + #[inline] + fn next(&mut self) -> Option<&'a A> { + self.inner.next() + } + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, A> DoubleEndedIterator for Iter<'a, A> { + #[inline] + fn next_back(&mut self) -> Option<&'a A> { + self.inner.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Iter<'_, A> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Iter<'_, A> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Iter<'_, A> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Iter<'_, A> { + #[inline] + fn clone(&self) -> Self { + Iter { inner: self.inner.clone() } + } +} + +/// An iterator over a mutable reference to the [`Some`] variant of an [`Option`]. +/// +/// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none. +/// +/// This `struct` is created by the [`Option::iter_mut`] function. +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct IterMut<'a, A: 'a> { + inner: Item<&'a mut A>, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, A> Iterator for IterMut<'a, A> { + type Item = &'a mut A; + + #[inline] + fn next(&mut self) -> Option<&'a mut A> { + self.inner.next() + } + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, A> DoubleEndedIterator for IterMut<'a, A> { + #[inline] + fn next_back(&mut self) -> Option<&'a mut A> { + self.inner.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IterMut<'_, A> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IterMut<'_, A> {} +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IterMut<'_, A> {} + +/// An iterator over the value in [`Some`] variant of an [`Option`]. +/// +/// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none. +/// +/// This `struct` is created by the [`Option::into_iter`] function. +#[derive(Clone, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IntoIter { + inner: Item, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + self.inner.next() + } + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + self.inner.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIter {} + +///////////////////////////////////////////////////////////////////////////// +// FromIterator +///////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "rust1", since = "1.0.0")] +impl> FromIterator> for Option { + /// Takes each element in the [`Iterator`]: if it is [`None`][Option::None], + /// no further elements are taken, and the [`None`][Option::None] is + /// returned. Should no [`None`][Option::None] occur, a container of type + /// `V` containing the values of each [`Option`] is returned. + /// + /// # Examples + /// + /// Here is an example which increments every integer in a vector. + /// We use the checked variant of `add` that returns `None` when the + /// calculation would result in an overflow. + /// + /// ``` + /// let items = vec![0_u16, 1, 2]; + /// + /// let res: Option> = items + /// .iter() + /// .map(|x| x.checked_add(1)) + /// .collect(); + /// + /// assert_eq!(res, Some(vec![1, 2, 3])); + /// ``` + /// + /// As you can see, this will return the expected, valid items. + /// + /// Here is another example that tries to subtract one from another list + /// of integers, this time checking for underflow: + /// + /// ``` + /// let items = vec![2_u16, 1, 0]; + /// + /// let res: Option> = items + /// .iter() + /// .map(|x| x.checked_sub(1)) + /// .collect(); + /// + /// assert_eq!(res, None); + /// ``` + /// + /// Since the last element is zero, it would underflow. Thus, the resulting + /// value is `None`. + /// + /// Here is a variation on the previous example, showing that no + /// further elements are taken from `iter` after the first `None`. + /// + /// ``` + /// let items = vec![3_u16, 2, 1, 10]; + /// + /// let mut shared = 0; + /// + /// let res: Option> = items + /// .iter() + /// .map(|x| { shared += x; x.checked_sub(2) }) + /// .collect(); + /// + /// assert_eq!(res, None); + /// assert_eq!(shared, 6); + /// ``` + /// + /// Since the third element caused an underflow, no further elements were taken, + /// so the final value of `shared` is 6 (= `3 + 2 + 1`), not 16. + #[inline] + fn from_iter>>(iter: I) -> Option { + // FIXME(#11084): This could be replaced with Iterator::scan when this + // performance bug is closed. + + iter::try_process(iter.into_iter(), |i| i.collect()) + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl ops::Try for Option { + type Output = T; + type Residual = Option; + + #[inline] + fn from_output(output: Self::Output) -> Self { + Some(output) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + Some(v) => ControlFlow::Continue(v), + None => ControlFlow::Break(None), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +// Note: manually specifying the residual type instead of using the default to work around +// https://github.com/rust-lang/rust/issues/99940 +impl ops::FromResidual> for Option { + #[inline] + fn from_residual(residual: Option) -> Self { + match residual { + None => None, + } + } +} + +#[diagnostic::do_not_recommend] +#[unstable(feature = "try_trait_v2_yeet", issue = "96374")] +impl ops::FromResidual> for Option { + #[inline] + fn from_residual(ops::Yeet(()): ops::Yeet<()>) -> Self { + None + } +} + +#[unstable(feature = "try_trait_v2_residual", issue = "91285")] +impl ops::Residual for Option { + type TryType = Option; +} + +impl Option> { + /// Converts from `Option>` to `Option`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let x: Option> = Some(Some(6)); + /// assert_eq!(Some(6), x.flatten()); + /// + /// let x: Option> = Some(None); + /// assert_eq!(None, x.flatten()); + /// + /// let x: Option> = None; + /// assert_eq!(None, x.flatten()); + /// ``` + /// + /// Flattening only removes one level of nesting at a time: + /// + /// ``` + /// let x: Option>> = Some(Some(Some(6))); + /// assert_eq!(Some(Some(6)), x.flatten()); + /// assert_eq!(Some(6), x.flatten().flatten()); + /// ``` + #[inline] + #[stable(feature = "option_flattening", since = "1.40.0")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] + pub const fn flatten(self) -> Option { + // FIXME(const-hack): could be written with `and_then` + match self { + Some(inner) => inner, + None => None, + } + } +} + +impl [Option; N] { + /// Transposes a `[Option; N]` into a `Option<[T; N]>`. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_array_transpose)] + /// # use std::option::Option; + /// + /// let data = [Some(0); 1000]; + /// let data: Option<[u8; 1000]> = data.transpose(); + /// assert_eq!(data, Some([0; 1000])); + /// + /// let data = [Some(0), None]; + /// let data: Option<[u8; 2]> = data.transpose(); + /// assert_eq!(data, None); + /// ``` + #[inline] + #[unstable(feature = "option_array_transpose", issue = "130828")] + pub fn transpose(self) -> Option<[T; N]> { + self.try_map(core::convert::identity) + } +} diff --git a/CoqOfRust/core/panic.rs b/CoqOfRust/core/panic.rs new file mode 100644 index 000000000..5fa340a61 --- /dev/null +++ b/CoqOfRust/core/panic.rs @@ -0,0 +1,247 @@ +//! Panic support in the standard library. + +#![stable(feature = "core_panic_info", since = "1.41.0")] + +mod location; +mod panic_info; +mod unwind_safe; + +#[stable(feature = "panic_hooks", since = "1.10.0")] +pub use self::location::Location; +#[stable(feature = "panic_hooks", since = "1.10.0")] +pub use self::panic_info::PanicInfo; +#[stable(feature = "panic_info_message", since = "1.81.0")] +pub use self::panic_info::PanicMessage; +#[stable(feature = "catch_unwind", since = "1.9.0")] +pub use self::unwind_safe::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe}; +use crate::any::Any; + +#[doc(hidden)] +#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")] +#[allow_internal_unstable(panic_internals, const_format_args)] +#[rustc_diagnostic_item = "core_panic_2015_macro"] +#[rustc_macro_transparency = "semitransparent"] +pub macro panic_2015 { + () => ( + $crate::panicking::panic("explicit panic") + ), + ($msg:literal $(,)?) => ( + $crate::panicking::panic($msg) + ), + // Use `panic_str_2015` instead of `panic_display::<&str>` for non_fmt_panic lint. + ($msg:expr $(,)?) => ({ + $crate::panicking::panic_str_2015($msg); + }), + // Special-case the single-argument case for const_panic. + ("{}", $arg:expr $(,)?) => ({ + $crate::panicking::panic_display(&$arg); + }), + ($fmt:expr, $($arg:tt)+) => ({ + // Semicolon to prevent temporaries inside the formatting machinery from + // being considered alive in the caller after the panic_fmt call. + $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+)); + }), +} + +#[doc(hidden)] +#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")] +#[allow_internal_unstable(panic_internals, const_format_args)] +#[rustc_diagnostic_item = "core_panic_2021_macro"] +#[rustc_macro_transparency = "semitransparent"] +#[cfg(feature = "panic_immediate_abort")] +pub macro panic_2021 { + () => ( + $crate::panicking::panic("explicit panic") + ), + // Special-case the single-argument case for const_panic. + ("{}", $arg:expr $(,)?) => ({ + $crate::panicking::panic_display(&$arg); + }), + ($($t:tt)+) => ({ + // Semicolon to prevent temporaries inside the formatting machinery from + // being considered alive in the caller after the panic_fmt call. + $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)); + }), +} + +#[doc(hidden)] +#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")] +#[allow_internal_unstable( + panic_internals, + core_intrinsics, + const_dispatch, + const_eval_select, + const_format_args, + rustc_attrs +)] +#[rustc_diagnostic_item = "core_panic_2021_macro"] +#[rustc_macro_transparency = "semitransparent"] +#[cfg(not(feature = "panic_immediate_abort"))] +pub macro panic_2021 { + () => ({ + // Create a function so that the argument for `track_caller` + // can be moved inside if possible. + #[cold] + #[track_caller] + #[inline(never)] + const fn panic_cold_explicit() -> ! { + $crate::panicking::panic_explicit() + } + panic_cold_explicit(); + }), + // Special-case the single-argument case for const_panic. + ("{}", $arg:expr $(,)?) => ({ + #[cold] + #[track_caller] + #[inline(never)] + #[rustc_const_panic_str] // enforce a &&str argument in const-check and hook this by const-eval + #[rustc_do_not_const_check] // hooked by const-eval + const fn panic_cold_display(arg: &T) -> ! { + $crate::panicking::panic_display(arg) + } + panic_cold_display(&$arg); + }), + ($($t:tt)+) => ({ + // Semicolon to prevent temporaries inside the formatting machinery from + // being considered alive in the caller after the panic_fmt call. + $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)); + }), +} + +#[doc(hidden)] +#[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")] +#[allow_internal_unstable(panic_internals)] +#[rustc_diagnostic_item = "unreachable_2015_macro"] +#[rustc_macro_transparency = "semitransparent"] +pub macro unreachable_2015 { + () => ( + $crate::panicking::panic("internal error: entered unreachable code") + ), + // Use of `unreachable_display` for non_fmt_panic lint. + // NOTE: the message ("internal error ...") is embedded directly in unreachable_display + ($msg:expr $(,)?) => ({ + $crate::panicking::unreachable_display(&$msg); + }), + ($fmt:expr, $($arg:tt)*) => ( + $crate::panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) + ), +} + +#[doc(hidden)] +#[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")] +#[allow_internal_unstable(panic_internals)] +#[rustc_macro_transparency = "semitransparent"] +pub macro unreachable_2021 { + () => ( + $crate::panicking::panic("internal error: entered unreachable code") + ), + ($($t:tt)+) => ( + $crate::panic!("internal error: entered unreachable code: {}", $crate::format_args!($($t)+)) + ), +} + +/// Invokes a closure, aborting if the closure unwinds. +/// +/// When compiled with aborting panics, this function is effectively a no-op. +/// With unwinding panics, an unwind results in another call into the panic +/// hook followed by a process abort. +/// +/// # Notes +/// +/// Instead of using this function, code should attempt to support unwinding. +/// Implementing [`Drop`] allows you to restore invariants uniformly in both +/// return and unwind paths. +/// +/// If an unwind can lead to logical issues but not soundness issues, you +/// should allow the unwind. Opting out of [`UnwindSafe`] indicates to your +/// consumers that they need to consider correctness in the face of unwinds. +/// +/// If an unwind would be unsound, then this function should be used in order +/// to prevent unwinds. However, note that `extern "C" fn` will automatically +/// convert unwinds to aborts, so using this function isn't necessary for FFI. +#[unstable(feature = "abort_unwind", issue = "130338")] +#[rustc_nounwind] +pub fn abort_unwind R, R>(f: F) -> R { + f() +} + +/// An internal trait used by std to pass data from std to `panic_unwind` and +/// other panic runtimes. Not intended to be stabilized any time soon, do not +/// use. +#[unstable(feature = "std_internals", issue = "none")] +#[doc(hidden)] +pub unsafe trait PanicPayload: crate::fmt::Display { + /// Take full ownership of the contents. + /// The return type is actually `Box`, but we cannot use `Box` in core. + /// + /// After this method got called, only some dummy default value is left in `self`. + /// Calling this method twice, or calling `get` after calling this method, is an error. + /// + /// The argument is borrowed because the panic runtime (`__rust_start_panic`) only + /// gets a borrowed `dyn PanicPayload`. + fn take_box(&mut self) -> *mut (dyn Any + Send); + + /// Just borrow the contents. + fn get(&mut self) -> &(dyn Any + Send); + + /// Tries to borrow the contents as `&str`, if possible without doing any allocations. + fn as_str(&mut self) -> Option<&str> { + None + } +} + +/// Helper macro for panicking in a `const fn`. +/// Invoke as: +/// ```rust,ignore (just an example) +/// core::macros::const_panic!("boring message", "flavored message {a} {b:?}", a: u32 = foo.len(), b: Something = bar); +/// ``` +/// where the first message will be printed in const-eval, +/// and the second message will be printed at runtime. +// All uses of this macro are FIXME(const-hack). +#[unstable(feature = "panic_internals", issue = "none")] +#[doc(hidden)] +pub macro const_panic { + ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty = $val:expr),* $(,)?) => {{ + // Wrap call to `const_eval_select` in a function so that we can + // add the `rustc_allow_const_fn_unstable`. This is okay to do + // because both variants will panic, just with different messages. + #[rustc_allow_const_fn_unstable(const_eval_select)] + #[inline(always)] // inline the wrapper + #[track_caller] + const fn do_panic($($arg: $ty),*) -> ! { + $crate::intrinsics::const_eval_select!( + @capture { $($arg: $ty = $arg),* } -> !: + #[noinline] + if const #[track_caller] #[inline] { // Inline this, to prevent codegen + $crate::panic!($const_msg) + } else #[track_caller] { // Do not inline this, it makes perf worse + $crate::panic!($runtime_msg) + } + ) + } + + do_panic($($val),*) + }}, + // We support leaving away the `val` expressions for *all* arguments + // (but not for *some* arguments, that's too tricky). + ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty),* $(,)?) => { + $crate::panic::const_panic!( + $const_msg, + $runtime_msg, + $($arg: $ty = $arg),* + ) + }, +} + +/// A version of `assert` that prints a non-formatting message in const contexts. +/// +/// See [`const_panic!`]. +#[unstable(feature = "panic_internals", issue = "none")] +#[doc(hidden)] +pub macro const_assert { + ($condition: expr, $const_msg:literal, $runtime_msg:literal, $($arg:tt)*) => {{ + if !$crate::intrinsics::likely($condition) { + $crate::panic::const_panic!($const_msg, $runtime_msg, $($arg)*) + } + }} +} diff --git a/CoqOfRust/core/panic/location.rs b/CoqOfRust/core/panic/location.rs new file mode 100644 index 000000000..1ad5c07d1 --- /dev/null +++ b/CoqOfRust/core/panic/location.rs @@ -0,0 +1,202 @@ +use crate::fmt; + +/// A struct containing information about the location of a panic. +/// +/// This structure is created by [`PanicHookInfo::location()`] and [`PanicInfo::location()`]. +/// +/// [`PanicInfo::location()`]: crate::panic::PanicInfo::location +/// [`PanicHookInfo::location()`]: ../../std/panic/struct.PanicHookInfo.html#method.location +/// +/// # Examples +/// +/// ```should_panic +/// use std::panic; +/// +/// panic::set_hook(Box::new(|panic_info| { +/// if let Some(location) = panic_info.location() { +/// println!("panic occurred in file '{}' at line {}", location.file(), location.line()); +/// } else { +/// println!("panic occurred but can't get location information..."); +/// } +/// })); +/// +/// panic!("Normal panic"); +/// ``` +/// +/// # Comparisons +/// +/// Comparisons for equality and ordering are made in file, line, then column priority. +/// Files are compared as strings, not `Path`, which could be unexpected. +/// See [`Location::file`]'s documentation for more discussion. +#[lang = "panic_location"] +#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[stable(feature = "panic_hooks", since = "1.10.0")] +pub struct Location<'a> { + file: &'a str, + line: u32, + col: u32, +} + +impl<'a> Location<'a> { + /// Returns the source location of the caller of this function. If that function's caller is + /// annotated then its call location will be returned, and so on up the stack to the first call + /// within a non-tracked function body. + /// + /// # Examples + /// + /// ```standalone_crate + /// use std::panic::Location; + /// + /// /// Returns the [`Location`] at which it is called. + /// #[track_caller] + /// fn get_caller_location() -> &'static Location<'static> { + /// Location::caller() + /// } + /// + /// /// Returns a [`Location`] from within this function's definition. + /// fn get_just_one_location() -> &'static Location<'static> { + /// get_caller_location() + /// } + /// + /// let fixed_location = get_just_one_location(); + /// assert_eq!(fixed_location.file(), file!()); + /// assert_eq!(fixed_location.line(), 14); + /// assert_eq!(fixed_location.column(), 5); + /// + /// // running the same untracked function in a different location gives us the same result + /// let second_fixed_location = get_just_one_location(); + /// assert_eq!(fixed_location.file(), second_fixed_location.file()); + /// assert_eq!(fixed_location.line(), second_fixed_location.line()); + /// assert_eq!(fixed_location.column(), second_fixed_location.column()); + /// + /// let this_location = get_caller_location(); + /// assert_eq!(this_location.file(), file!()); + /// assert_eq!(this_location.line(), 28); + /// assert_eq!(this_location.column(), 21); + /// + /// // running the tracked function in a different location produces a different value + /// let another_location = get_caller_location(); + /// assert_eq!(this_location.file(), another_location.file()); + /// assert_ne!(this_location.line(), another_location.line()); + /// assert_ne!(this_location.column(), another_location.column()); + /// ``` + #[must_use] + #[stable(feature = "track_caller", since = "1.46.0")] + #[rustc_const_stable(feature = "const_caller_location", since = "1.79.0")] + #[track_caller] + #[inline] + pub const fn caller() -> &'static Location<'static> { + crate::intrinsics::caller_location() + } + + /// Returns the name of the source file from which the panic originated. + /// + /// # `&str`, not `&Path` + /// + /// The returned name refers to a source path on the compiling system, but it isn't valid to + /// represent this directly as a `&Path`. The compiled code may run on a different system with + /// a different `Path` implementation than the system providing the contents and this library + /// does not currently have a different "host path" type. + /// + /// The most surprising behavior occurs when "the same" file is reachable via multiple paths in + /// the module system (usually using the `#[path = "..."]` attribute or similar), which can + /// cause what appears to be identical code to return differing values from this function. + /// + /// # Cross-compilation + /// + /// This value is not suitable for passing to `Path::new` or similar constructors when the host + /// platform and target platform differ. + /// + /// # Examples + /// + /// ```should_panic + /// use std::panic; + /// + /// panic::set_hook(Box::new(|panic_info| { + /// if let Some(location) = panic_info.location() { + /// println!("panic occurred in file '{}'", location.file()); + /// } else { + /// println!("panic occurred but can't get location information..."); + /// } + /// })); + /// + /// panic!("Normal panic"); + /// ``` + #[must_use] + #[stable(feature = "panic_hooks", since = "1.10.0")] + #[rustc_const_stable(feature = "const_location_fields", since = "1.79.0")] + #[inline] + pub const fn file(&self) -> &str { + self.file + } + + /// Returns the line number from which the panic originated. + /// + /// # Examples + /// + /// ```should_panic + /// use std::panic; + /// + /// panic::set_hook(Box::new(|panic_info| { + /// if let Some(location) = panic_info.location() { + /// println!("panic occurred at line {}", location.line()); + /// } else { + /// println!("panic occurred but can't get location information..."); + /// } + /// })); + /// + /// panic!("Normal panic"); + /// ``` + #[must_use] + #[stable(feature = "panic_hooks", since = "1.10.0")] + #[rustc_const_stable(feature = "const_location_fields", since = "1.79.0")] + #[inline] + pub const fn line(&self) -> u32 { + self.line + } + + /// Returns the column from which the panic originated. + /// + /// # Examples + /// + /// ```should_panic + /// use std::panic; + /// + /// panic::set_hook(Box::new(|panic_info| { + /// if let Some(location) = panic_info.location() { + /// println!("panic occurred at column {}", location.column()); + /// } else { + /// println!("panic occurred but can't get location information..."); + /// } + /// })); + /// + /// panic!("Normal panic"); + /// ``` + #[must_use] + #[stable(feature = "panic_col", since = "1.25.0")] + #[rustc_const_stable(feature = "const_location_fields", since = "1.79.0")] + #[inline] + pub const fn column(&self) -> u32 { + self.col + } +} + +#[unstable( + feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` and related macros", + issue = "none" +)] +impl<'a> Location<'a> { + #[doc(hidden)] + pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self { + Location { file, line, col } + } +} + +#[stable(feature = "panic_hook_display", since = "1.26.0")] +impl fmt::Display for Location<'_> { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(formatter, "{}:{}:{}", self.file, self.line, self.col) + } +} diff --git a/CoqOfRust/core/panic/panic_info.rs b/CoqOfRust/core/panic/panic_info.rs new file mode 100644 index 000000000..9d53567a2 --- /dev/null +++ b/CoqOfRust/core/panic/panic_info.rs @@ -0,0 +1,190 @@ +use crate::fmt::{self, Display}; +use crate::panic::Location; + +/// A struct providing information about a panic. +/// +/// A `PanicInfo` structure is passed to the panic handler defined by `#[panic_handler]`. +/// +/// For the type used by the panic hook mechanism in `std`, see [`std::panic::PanicHookInfo`]. +/// +/// [`std::panic::PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html +#[lang = "panic_info"] +#[stable(feature = "panic_hooks", since = "1.10.0")] +#[derive(Debug)] +pub struct PanicInfo<'a> { + message: &'a fmt::Arguments<'a>, + location: &'a Location<'a>, + can_unwind: bool, + force_no_backtrace: bool, +} + +/// A message that was given to the `panic!()` macro. +/// +/// The [`Display`] implementation of this type will format the message with the arguments +/// that were given to the `panic!()` macro. +/// +/// See [`PanicInfo::message`]. +#[stable(feature = "panic_info_message", since = "1.81.0")] +pub struct PanicMessage<'a> { + message: &'a fmt::Arguments<'a>, +} + +impl<'a> PanicInfo<'a> { + #[inline] + pub(crate) fn new( + message: &'a fmt::Arguments<'a>, + location: &'a Location<'a>, + can_unwind: bool, + force_no_backtrace: bool, + ) -> Self { + PanicInfo { location, message, can_unwind, force_no_backtrace } + } + + /// The message that was given to the `panic!` macro. + /// + /// # Example + /// + /// The type returned by this method implements `Display`, so it can + /// be passed directly to [`write!()`] and similar macros. + /// + /// [`write!()`]: core::write + /// + /// ```ignore (no_std) + /// #[panic_handler] + /// fn panic_handler(panic_info: &PanicInfo<'_>) -> ! { + /// write!(DEBUG_OUTPUT, "panicked: {}", panic_info.message()); + /// loop {} + /// } + /// ``` + #[must_use] + #[stable(feature = "panic_info_message", since = "1.81.0")] + pub fn message(&self) -> PanicMessage<'_> { + PanicMessage { message: self.message } + } + + /// Returns information about the location from which the panic originated, + /// if available. + /// + /// This method will currently always return [`Some`], but this may change + /// in future versions. + /// + /// # Examples + /// + /// ```should_panic + /// use std::panic; + /// + /// panic::set_hook(Box::new(|panic_info| { + /// if let Some(location) = panic_info.location() { + /// println!("panic occurred in file '{}' at line {}", + /// location.file(), + /// location.line(), + /// ); + /// } else { + /// println!("panic occurred but can't get location information..."); + /// } + /// })); + /// + /// panic!("Normal panic"); + /// ``` + #[must_use] + #[stable(feature = "panic_hooks", since = "1.10.0")] + pub fn location(&self) -> Option<&Location<'_>> { + // NOTE: If this is changed to sometimes return None, + // deal with that case in std::panicking::default_hook and core::panicking::panic_fmt. + Some(&self.location) + } + + /// Returns the payload associated with the panic. + /// + /// On this type, `core::panic::PanicInfo`, this method never returns anything useful. + /// It only exists because of compatibility with [`std::panic::PanicHookInfo`], + /// which used to be the same type. + /// + /// See [`std::panic::PanicHookInfo::payload`]. + /// + /// [`std::panic::PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html + /// [`std::panic::PanicHookInfo::payload`]: ../../std/panic/struct.PanicHookInfo.html#method.payload + #[deprecated(since = "1.81.0", note = "this never returns anything useful")] + #[stable(feature = "panic_hooks", since = "1.10.0")] + #[allow(deprecated, deprecated_in_future)] + pub fn payload(&self) -> &(dyn crate::any::Any + Send) { + struct NoPayload; + &NoPayload + } + + /// Returns whether the panic handler is allowed to unwind the stack from + /// the point where the panic occurred. + /// + /// This is true for most kinds of panics with the exception of panics + /// caused by trying to unwind out of a `Drop` implementation or a function + /// whose ABI does not support unwinding. + /// + /// It is safe for a panic handler to unwind even when this function returns + /// false, however this will simply cause the panic handler to be called + /// again. + #[must_use] + #[unstable(feature = "panic_can_unwind", issue = "92988")] + pub fn can_unwind(&self) -> bool { + self.can_unwind + } + + #[unstable( + feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` and related macros", + issue = "none" + )] + #[doc(hidden)] + #[inline] + pub fn force_no_backtrace(&self) -> bool { + self.force_no_backtrace + } +} + +#[stable(feature = "panic_hook_display", since = "1.26.0")] +impl Display for PanicInfo<'_> { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("panicked at ")?; + self.location.fmt(formatter)?; + formatter.write_str(":\n")?; + formatter.write_fmt(*self.message)?; + Ok(()) + } +} + +impl<'a> PanicMessage<'a> { + /// Gets the formatted message, if it has no arguments to be formatted at runtime. + /// + /// This can be used to avoid allocations in some cases. + /// + /// # Guarantees + /// + /// For `panic!("just a literal")`, this function is guaranteed to + /// return `Some("just a literal")`. + /// + /// For most cases with placeholders, this function will return `None`. + /// + /// See [`fmt::Arguments::as_str`] for details. + #[stable(feature = "panic_info_message", since = "1.81.0")] + #[rustc_const_stable(feature = "const_arguments_as_str", since = "1.84.0")] + #[must_use] + #[inline] + pub const fn as_str(&self) -> Option<&'static str> { + self.message.as_str() + } +} + +#[stable(feature = "panic_info_message", since = "1.81.0")] +impl Display for PanicMessage<'_> { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_fmt(*self.message) + } +} + +#[stable(feature = "panic_info_message", since = "1.81.0")] +impl fmt::Debug for PanicMessage<'_> { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_fmt(*self.message) + } +} diff --git a/CoqOfRust/core/panic/unwind_safe.rs b/CoqOfRust/core/panic/unwind_safe.rs new file mode 100644 index 000000000..37859212c --- /dev/null +++ b/CoqOfRust/core/panic/unwind_safe.rs @@ -0,0 +1,313 @@ +use crate::async_iter::AsyncIterator; +use crate::cell::UnsafeCell; +use crate::fmt; +use crate::future::Future; +use crate::ops::{Deref, DerefMut}; +use crate::pin::Pin; +use crate::ptr::{NonNull, Unique}; +use crate::task::{Context, Poll}; + +/// A marker trait which represents "panic safe" types in Rust. +/// +/// This trait is implemented by default for many types and behaves similarly in +/// terms of inference of implementation to the [`Send`] and [`Sync`] traits. The +/// purpose of this trait is to encode what types are safe to cross a [`catch_unwind`] +/// boundary with no fear of unwind safety. +/// +/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html +/// +/// ## What is unwind safety? +/// +/// In Rust a function can "return" early if it either panics or calls a +/// function which transitively panics. This sort of control flow is not always +/// anticipated, and has the possibility of causing subtle bugs through a +/// combination of two critical components: +/// +/// 1. A data structure is in a temporarily invalid state when the thread +/// panics. +/// 2. This broken invariant is then later observed. +/// +/// Typically in Rust, it is difficult to perform step (2) because catching a +/// panic involves either spawning a thread (which in turn makes it difficult +/// to later witness broken invariants) or using the `catch_unwind` function in this +/// module. Additionally, even if an invariant is witnessed, it typically isn't a +/// problem in Rust because there are no uninitialized values (like in C or C++). +/// +/// It is possible, however, for **logical** invariants to be broken in Rust, +/// which can end up causing behavioral bugs. Another key aspect of unwind safety +/// in Rust is that, in the absence of `unsafe` code, a panic cannot lead to +/// memory unsafety. +/// +/// That was a bit of a whirlwind tour of unwind safety, but for more information +/// about unwind safety and how it applies to Rust, see an [associated RFC][rfc]. +/// +/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md +/// +/// ## What is `UnwindSafe`? +/// +/// Now that we've got an idea of what unwind safety is in Rust, it's also +/// important to understand what this trait represents. As mentioned above, one +/// way to witness broken invariants is through the `catch_unwind` function in this +/// module as it allows catching a panic and then re-using the environment of +/// the closure. +/// +/// Simply put, a type `T` implements `UnwindSafe` if it cannot easily allow +/// witnessing a broken invariant through the use of `catch_unwind` (catching a +/// panic). This trait is an auto trait, so it is automatically implemented for +/// many types, and it is also structurally composed (e.g., a struct is unwind +/// safe if all of its components are unwind safe). +/// +/// Note, however, that this is not an unsafe trait, so there is not a succinct +/// contract that this trait is providing. Instead it is intended as more of a +/// "speed bump" to alert users of `catch_unwind` that broken invariants may be +/// witnessed and may need to be accounted for. +/// +/// ## Who implements `UnwindSafe`? +/// +/// Types such as `&mut T` and `&RefCell` are examples which are **not** +/// unwind safe. The general idea is that any mutable state which can be shared +/// across `catch_unwind` is not unwind safe by default. This is because it is very +/// easy to witness a broken invariant outside of `catch_unwind` as the data is +/// simply accessed as usual. +/// +/// Types like `&Mutex`, however, are unwind safe because they implement +/// poisoning by default. They still allow witnessing a broken invariant, but +/// they already provide their own "speed bumps" to do so. +/// +/// ## When should `UnwindSafe` be used? +/// +/// It is not intended that most types or functions need to worry about this trait. +/// It is only used as a bound on the `catch_unwind` function and as mentioned +/// above, the lack of `unsafe` means it is mostly an advisory. The +/// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be +/// implemented for any closed over variables passed to `catch_unwind`. +#[stable(feature = "catch_unwind", since = "1.9.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "unwind_safe_trait")] +#[diagnostic::on_unimplemented( + message = "the type `{Self}` may not be safely transferred across an unwind boundary", + label = "`{Self}` may not be safely transferred across an unwind boundary" +)] +pub auto trait UnwindSafe {} + +/// A marker trait representing types where a shared reference is considered +/// unwind safe. +/// +/// This trait is namely not implemented by [`UnsafeCell`], the root of all +/// interior mutability. +/// +/// This is a "helper marker trait" used to provide impl blocks for the +/// [`UnwindSafe`] trait, for more information see that documentation. +#[stable(feature = "catch_unwind", since = "1.9.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "ref_unwind_safe_trait")] +#[diagnostic::on_unimplemented( + message = "the type `{Self}` may contain interior mutability and a reference may not be safely \ + transferrable across a catch_unwind boundary", + label = "`{Self}` may contain interior mutability and a reference may not be safely \ + transferrable across a catch_unwind boundary" +)] +pub auto trait RefUnwindSafe {} + +/// A simple wrapper around a type to assert that it is unwind safe. +/// +/// When using [`catch_unwind`] it may be the case that some of the closed over +/// variables are not unwind safe. For example if `&mut T` is captured the +/// compiler will generate a warning indicating that it is not unwind safe. It +/// might not be the case, however, that this is actually a problem due to the +/// specific usage of [`catch_unwind`] if unwind safety is specifically taken into +/// account. This wrapper struct is useful for a quick and lightweight +/// annotation that a variable is indeed unwind safe. +/// +/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html +/// +/// # Examples +/// +/// One way to use `AssertUnwindSafe` is to assert that the entire closure +/// itself is unwind safe, bypassing all checks for all variables: +/// +/// ``` +/// use std::panic::{self, AssertUnwindSafe}; +/// +/// let mut variable = 4; +/// +/// // This code will not compile because the closure captures `&mut variable` +/// // which is not considered unwind safe by default. +/// +/// // panic::catch_unwind(|| { +/// // variable += 3; +/// // }); +/// +/// // This, however, will compile due to the `AssertUnwindSafe` wrapper +/// let result = panic::catch_unwind(AssertUnwindSafe(|| { +/// variable += 3; +/// })); +/// // ... +/// ``` +/// +/// Wrapping the entire closure amounts to a blanket assertion that all captured +/// variables are unwind safe. This has the downside that if new captures are +/// added in the future, they will also be considered unwind safe. Therefore, +/// you may prefer to just wrap individual captures, as shown below. This is +/// more annotation, but it ensures that if a new capture is added which is not +/// unwind safe, you will get a compilation error at that time, which will +/// allow you to consider whether that new capture in fact represent a bug or +/// not. +/// +/// ``` +/// use std::panic::{self, AssertUnwindSafe}; +/// +/// let mut variable = 4; +/// let other_capture = 3; +/// +/// let result = { +/// let mut wrapper = AssertUnwindSafe(&mut variable); +/// panic::catch_unwind(move || { +/// **wrapper += other_capture; +/// }) +/// }; +/// // ... +/// ``` +#[stable(feature = "catch_unwind", since = "1.9.0")] +pub struct AssertUnwindSafe(#[stable(feature = "catch_unwind", since = "1.9.0")] pub T); + +// Implementations of the `UnwindSafe` trait: +// +// * By default everything is unwind safe +// * pointers T contains mutability of some form are not unwind safe +// * Unique, an owning pointer, lifts an implementation +// * Types like Mutex/RwLock which are explicitly poisoned are unwind safe +// * Our custom AssertUnwindSafe wrapper is indeed unwind safe + +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl !UnwindSafe for &mut T {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for &T {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for *const T {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for *mut T {} +#[unstable(feature = "ptr_internals", issue = "none")] +impl UnwindSafe for Unique {} +#[stable(feature = "nonnull", since = "1.25.0")] +impl UnwindSafe for NonNull {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for AssertUnwindSafe {} + +// Pretty simple implementations for the `RefUnwindSafe` marker trait, +// basically just saying that `UnsafeCell` is the +// only thing which doesn't implement it (which then transitively applies to +// everything else). +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl !RefUnwindSafe for UnsafeCell {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl RefUnwindSafe for AssertUnwindSafe {} + +#[cfg(target_has_atomic_load_store = "ptr")] +#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] +impl RefUnwindSafe for crate::sync::atomic::AtomicIsize {} +#[cfg(target_has_atomic_load_store = "8")] +#[stable(feature = "integer_atomics_stable", since = "1.34.0")] +impl RefUnwindSafe for crate::sync::atomic::AtomicI8 {} +#[cfg(target_has_atomic_load_store = "16")] +#[stable(feature = "integer_atomics_stable", since = "1.34.0")] +impl RefUnwindSafe for crate::sync::atomic::AtomicI16 {} +#[cfg(target_has_atomic_load_store = "32")] +#[stable(feature = "integer_atomics_stable", since = "1.34.0")] +impl RefUnwindSafe for crate::sync::atomic::AtomicI32 {} +#[cfg(target_has_atomic_load_store = "64")] +#[stable(feature = "integer_atomics_stable", since = "1.34.0")] +impl RefUnwindSafe for crate::sync::atomic::AtomicI64 {} +#[cfg(target_has_atomic_load_store = "128")] +#[unstable(feature = "integer_atomics", issue = "99069")] +impl RefUnwindSafe for crate::sync::atomic::AtomicI128 {} + +#[cfg(target_has_atomic_load_store = "ptr")] +#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] +impl RefUnwindSafe for crate::sync::atomic::AtomicUsize {} +#[cfg(target_has_atomic_load_store = "8")] +#[stable(feature = "integer_atomics_stable", since = "1.34.0")] +impl RefUnwindSafe for crate::sync::atomic::AtomicU8 {} +#[cfg(target_has_atomic_load_store = "16")] +#[stable(feature = "integer_atomics_stable", since = "1.34.0")] +impl RefUnwindSafe for crate::sync::atomic::AtomicU16 {} +#[cfg(target_has_atomic_load_store = "32")] +#[stable(feature = "integer_atomics_stable", since = "1.34.0")] +impl RefUnwindSafe for crate::sync::atomic::AtomicU32 {} +#[cfg(target_has_atomic_load_store = "64")] +#[stable(feature = "integer_atomics_stable", since = "1.34.0")] +impl RefUnwindSafe for crate::sync::atomic::AtomicU64 {} +#[cfg(target_has_atomic_load_store = "128")] +#[unstable(feature = "integer_atomics", issue = "99069")] +impl RefUnwindSafe for crate::sync::atomic::AtomicU128 {} + +#[cfg(target_has_atomic_load_store = "8")] +#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] +impl RefUnwindSafe for crate::sync::atomic::AtomicBool {} + +#[cfg(target_has_atomic_load_store = "ptr")] +#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] +impl RefUnwindSafe for crate::sync::atomic::AtomicPtr {} + +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl Deref for AssertUnwindSafe { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl DerefMut for AssertUnwindSafe { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } +} + +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl R> FnOnce<()> for AssertUnwindSafe { + type Output = R; + + #[inline] + extern "rust-call" fn call_once(self, _args: ()) -> R { + (self.0)() + } +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for AssertUnwindSafe { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("AssertUnwindSafe").field(&self.0).finish() + } +} + +#[stable(feature = "assertunwindsafe_default", since = "1.62.0")] +impl Default for AssertUnwindSafe { + fn default() -> Self { + Self(Default::default()) + } +} + +#[stable(feature = "futures_api", since = "1.36.0")] +impl Future for AssertUnwindSafe { + type Output = F::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // SAFETY: pin projection. AssertUnwindSafe follows structural pinning. + let pinned_field = unsafe { Pin::map_unchecked_mut(self, |x| &mut x.0) }; + F::poll(pinned_field, cx) + } +} + +#[unstable(feature = "async_iterator", issue = "79024")] +impl AsyncIterator for AssertUnwindSafe { + type Item = S::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + // SAFETY: pin projection. AssertUnwindSafe follows structural pinning. + unsafe { self.map_unchecked_mut(|x| &mut x.0) }.poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } +} diff --git a/CoqOfRust/core/panicking.rs b/CoqOfRust/core/panicking.rs new file mode 100644 index 000000000..53e2b238b --- /dev/null +++ b/CoqOfRust/core/panicking.rs @@ -0,0 +1,415 @@ +//! Panic support for core +//! +//! In core, panicking is always done with a message, resulting in a `core::panic::PanicInfo` +//! containing a `fmt::Arguments`. In std, however, panicking can be done with panic_any, which +//! throws a `Box` containing any type of value. Because of this, +//! `std::panic::PanicHookInfo` is a different type, which contains a `&dyn Any` instead of a +//! `fmt::Arguments`. std's panic handler will convert the `fmt::Arguments` to a `&dyn Any` +//! containing either a `&'static str` or `String` containing the formatted message. +//! +//! The core library cannot define any panic handler, but it can invoke it. +//! This means that the functions inside of core are allowed to panic, but to be +//! useful an upstream crate must define panicking for core to use. The current +//! interface for panicking is: +//! +//! ``` +//! fn panic_impl(pi: &core::panic::PanicInfo<'_>) -> ! +//! # { loop {} } +//! ``` +//! +//! This module contains a few other panicking functions, but these are just the +//! necessary lang items for the compiler. All panics are funneled through this +//! one function. The actual symbol is declared through the `#[panic_handler]` attribute. + +#![allow(dead_code, missing_docs)] +#![unstable( + feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` and related macros", + issue = "none" +)] + +use crate::fmt; +use crate::intrinsics::const_eval_select; +use crate::panic::{Location, PanicInfo}; + +#[cfg(feature = "panic_immediate_abort")] +const _: () = assert!(cfg!(panic = "abort"), "panic_immediate_abort requires -C panic=abort"); + +// First we define the two main entry points that all panics go through. +// In the end both are just convenience wrappers around `panic_impl`. + +/// The entry point for panicking with a formatted message. +/// +/// This is designed to reduce the amount of code required at the call +/// site as much as possible (so that `panic!()` has as low an impact +/// on (e.g.) the inlining of other functions as possible), by moving +/// the actual formatting into this shared place. +// If panic_immediate_abort, inline the abort call, +// otherwise avoid inlining because of it is cold path. +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +#[lang = "panic_fmt"] // needed for const-evaluated panics +#[rustc_do_not_const_check] // hooked by const-eval +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable +pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { + if cfg!(feature = "panic_immediate_abort") { + super::intrinsics::abort() + } + + // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call + // that gets resolved to the `#[panic_handler]` function. + extern "Rust" { + #[lang = "panic_impl"] + fn panic_impl(pi: &PanicInfo<'_>) -> !; + } + + let pi = PanicInfo::new( + &fmt, + Location::caller(), + /* can_unwind */ true, + /* force_no_backtrace */ false, + ); + + // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. + unsafe { panic_impl(&pi) } +} + +/// Like `panic_fmt`, but for non-unwinding panics. +/// +/// Has to be a separate function so that it can carry the `rustc_nounwind` attribute. +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +// This attribute has the key side-effect that if the panic handler ignores `can_unwind` +// and unwinds anyway, we will hit the "unwinding out of nounwind function" guard, +// which causes a "panic in a function that cannot unwind". +#[rustc_nounwind] +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable +#[rustc_allow_const_fn_unstable(const_eval_select)] +pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! { + const_eval_select!( + @capture { fmt: fmt::Arguments<'_>, force_no_backtrace: bool } -> !: + if const #[track_caller] { + // We don't unwind anyway at compile-time so we can call the regular `panic_fmt`. + panic_fmt(fmt) + } else #[track_caller] { + if cfg!(feature = "panic_immediate_abort") { + super::intrinsics::abort() + } + + // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call + // that gets resolved to the `#[panic_handler]` function. + extern "Rust" { + #[lang = "panic_impl"] + fn panic_impl(pi: &PanicInfo<'_>) -> !; + } + + // PanicInfo with the `can_unwind` flag set to false forces an abort. + let pi = PanicInfo::new( + &fmt, + Location::caller(), + /* can_unwind */ false, + force_no_backtrace, + ); + + // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. + unsafe { panic_impl(&pi) } + } + ) +} + +// Next we define a bunch of higher-level wrappers that all bottom out in the two core functions +// above. + +/// The underlying implementation of core's `panic!` macro when no formatting is used. +// Never inline unless panic_immediate_abort to avoid code +// bloat at the call sites as much as possible. +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable +#[lang = "panic"] // used by lints and miri for panics +pub const fn panic(expr: &'static str) -> ! { + // Use Arguments::new_const instead of format_args!("{expr}") to potentially + // reduce size overhead. The format_args! macro uses str's Display trait to + // write expr, which calls Formatter::pad, which must accommodate string + // truncation and padding (even though none is used here). Using + // Arguments::new_const may allow the compiler to omit Formatter::pad from the + // output binary, saving up to a few kilobytes. + // However, this optimization only works for `'static` strings: `new_const` also makes this + // message return `Some` from `Arguments::as_str`, which means it can become part of the panic + // payload without any allocation or copying. Shorter-lived strings would become invalid as + // stack frames get popped during unwinding, and couldn't be directly referenced from the + // payload. + panic_fmt(fmt::Arguments::new_const(&[expr])); +} + +// We generate functions for usage by compiler-generated assertions. +// +// Placing these functions in libcore means that all Rust programs can generate a jump into this +// code rather than expanding to panic("...") above, which adds extra bloat to call sites (for the +// constant string argument's pointer and length). +// +// This is especially important when this code is called often (e.g., with -Coverflow-checks) for +// reducing binary size impact. +macro_rules! panic_const { + ($($lang:ident = $message:expr,)+) => { + pub mod panic_const { + use super::*; + + $( + /// This is a panic called with a message that's a result of a MIR-produced Assert. + // + // never inline unless panic_immediate_abort to avoid code + // bloat at the call sites as much as possible + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] + #[cfg_attr(feature = "panic_immediate_abort", inline)] + #[track_caller] + #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable + #[lang = stringify!($lang)] + pub const fn $lang() -> ! { + // Use Arguments::new_const instead of format_args!("{expr}") to potentially + // reduce size overhead. The format_args! macro uses str's Display trait to + // write expr, which calls Formatter::pad, which must accommodate string + // truncation and padding (even though none is used here). Using + // Arguments::new_const may allow the compiler to omit Formatter::pad from the + // output binary, saving up to a few kilobytes. + panic_fmt(fmt::Arguments::new_const(&[$message])); + } + )+ + } + } +} + +// Unfortunately this set of strings is replicated here and in a few places in the compiler in +// slightly different forms. It's not clear if there's a good way to deduplicate without adding +// special cases to the compiler (e.g., a const generic function wouldn't have a single definition +// shared across crates, which is exactly what we want here). +panic_const! { + panic_const_add_overflow = "attempt to add with overflow", + panic_const_sub_overflow = "attempt to subtract with overflow", + panic_const_mul_overflow = "attempt to multiply with overflow", + panic_const_div_overflow = "attempt to divide with overflow", + panic_const_rem_overflow = "attempt to calculate the remainder with overflow", + panic_const_neg_overflow = "attempt to negate with overflow", + panic_const_shr_overflow = "attempt to shift right with overflow", + panic_const_shl_overflow = "attempt to shift left with overflow", + panic_const_div_by_zero = "attempt to divide by zero", + panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero", + panic_const_coroutine_resumed = "coroutine resumed after completion", + panic_const_async_fn_resumed = "`async fn` resumed after completion", + panic_const_async_gen_fn_resumed = "`async gen fn` resumed after completion", + panic_const_gen_fn_none = "`gen fn` should just keep returning `None` after completion", + panic_const_coroutine_resumed_panic = "coroutine resumed after panicking", + panic_const_async_fn_resumed_panic = "`async fn` resumed after panicking", + panic_const_async_gen_fn_resumed_panic = "`async gen fn` resumed after panicking", + panic_const_gen_fn_none_panic = "`gen fn` should just keep returning `None` after panicking", +} + +/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize on the caller. +/// If you want `#[track_caller]` for nicer errors, call `panic_nounwind_fmt` directly. +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics +#[rustc_nounwind] +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable +pub const fn panic_nounwind(expr: &'static str) -> ! { + panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ false); +} + +/// Like `panic_nounwind`, but also inhibits showing a backtrace. +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[rustc_nounwind] +pub fn panic_nounwind_nobacktrace(expr: &'static str) -> ! { + panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ true); +} + +#[track_caller] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable +pub const fn panic_explicit() -> ! { + panic_display(&"explicit panic"); +} + +#[inline] +#[track_caller] +#[rustc_diagnostic_item = "unreachable_display"] // needed for `non-fmt-panics` lint +pub fn unreachable_display(x: &T) -> ! { + panic_fmt(format_args!("internal error: entered unreachable code: {}", *x)); +} + +/// This exists solely for the 2015 edition `panic!` macro to trigger +/// a lint on `panic!(my_str_variable);`. +#[inline] +#[track_caller] +#[rustc_diagnostic_item = "panic_str_2015"] +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable +pub const fn panic_str_2015(expr: &str) -> ! { + panic_display(&expr); +} + +#[inline] +#[track_caller] +#[rustc_do_not_const_check] // hooked by const-eval +// enforce a &&str argument in const-check and hook this by const-eval +#[rustc_const_panic_str] +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable +pub const fn panic_display(x: &T) -> ! { + panic_fmt(format_args!("{}", *x)); +} + +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +#[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access +fn panic_bounds_check(index: usize, len: usize) -> ! { + if cfg!(feature = "panic_immediate_abort") { + super::intrinsics::abort() + } + + panic!("index out of bounds: the len is {len} but the index is {index}") +} + +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +#[lang = "panic_misaligned_pointer_dereference"] // needed by codegen for panic on misaligned pointer deref +#[rustc_nounwind] // `CheckAlignment` MIR pass requires this function to never unwind +fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! { + if cfg!(feature = "panic_immediate_abort") { + super::intrinsics::abort() + } + + panic_nounwind_fmt( + format_args!( + "misaligned pointer dereference: address must be a multiple of {required:#x} but is {found:#x}" + ), + /* force_no_backtrace */ false, + ) +} + +/// Panics because we cannot unwind out of a function. +/// +/// This is a separate function to avoid the codesize impact of each crate containing the string to +/// pass to `panic_nounwind`. +/// +/// This function is called directly by the codegen backend, and must not have +/// any extra arguments (including those synthesized by track_caller). +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[lang = "panic_cannot_unwind"] // needed by codegen for panic in nounwind function +#[rustc_nounwind] +fn panic_cannot_unwind() -> ! { + // Keep the text in sync with `UnwindTerminateReason::as_str` in `rustc_middle`. + panic_nounwind("panic in a function that cannot unwind") +} + +/// Panics because we are unwinding out of a destructor during cleanup. +/// +/// This is a separate function to avoid the codesize impact of each crate containing the string to +/// pass to `panic_nounwind`. +/// +/// This function is called directly by the codegen backend, and must not have +/// any extra arguments (including those synthesized by track_caller). +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[lang = "panic_in_cleanup"] // needed by codegen for panic in nounwind function +#[rustc_nounwind] +fn panic_in_cleanup() -> ! { + // Keep the text in sync with `UnwindTerminateReason::as_str` in `rustc_middle`. + panic_nounwind_nobacktrace("panic in a destructor during cleanup") +} + +/// This function is used instead of panic_fmt in const eval. +#[lang = "const_panic_fmt"] // needed by const-eval machine to replace calls to `panic_fmt` lang item +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable +pub const fn const_panic_fmt(fmt: fmt::Arguments<'_>) -> ! { + if let Some(msg) = fmt.as_str() { + // The panic_display function is hooked by const eval. + panic_display(&msg); + } else { + // SAFETY: This is only evaluated at compile time, which reliably + // handles this UB (in case this branch turns out to be reachable + // somehow). + unsafe { crate::hint::unreachable_unchecked() }; + } +} + +#[derive(Debug)] +#[doc(hidden)] +pub enum AssertKind { + Eq, + Ne, + Match, +} + +/// Internal function for `assert_eq!` and `assert_ne!` macros +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +#[doc(hidden)] +pub fn assert_failed( + kind: AssertKind, + left: &T, + right: &U, + args: Option>, +) -> ! +where + T: fmt::Debug + ?Sized, + U: fmt::Debug + ?Sized, +{ + assert_failed_inner(kind, &left, &right, args) +} + +/// Internal function for `assert_match!` +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +#[doc(hidden)] +pub fn assert_matches_failed( + left: &T, + right: &str, + args: Option>, +) -> ! { + // The pattern is a string so it can be displayed directly. + struct Pattern<'a>(&'a str); + impl fmt::Debug for Pattern<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.0) + } + } + assert_failed_inner(AssertKind::Match, &left, &Pattern(right), args); +} + +/// Non-generic version of the above functions, to avoid code bloat. +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +fn assert_failed_inner( + kind: AssertKind, + left: &dyn fmt::Debug, + right: &dyn fmt::Debug, + args: Option>, +) -> ! { + let op = match kind { + AssertKind::Eq => "==", + AssertKind::Ne => "!=", + AssertKind::Match => "matches", + }; + + match args { + Some(args) => panic!( + r#"assertion `left {op} right` failed: {args} + left: {left:?} + right: {right:?}"# + ), + None => panic!( + r#"assertion `left {op} right` failed + left: {left:?} + right: {right:?}"# + ), + } +} diff --git a/CoqOfRust/core/pat.rs b/CoqOfRust/core/pat.rs new file mode 100644 index 000000000..752e79c2d --- /dev/null +++ b/CoqOfRust/core/pat.rs @@ -0,0 +1,14 @@ +//! Helper module for exporting the `pattern_type` macro + +/// Creates a pattern type. +/// ```ignore (cannot test this from within core yet) +/// type Positive = std::pat::pattern_type!(i32 is 1..); +/// ``` +#[macro_export] +#[rustc_builtin_macro(pattern_type)] +#[unstable(feature = "pattern_type_macro", issue = "123646")] +macro_rules! pattern_type { + ($($arg:tt)*) => { + /* compiler built-in */ + }; +} diff --git a/CoqOfRust/core/pin.rs b/CoqOfRust/core/pin.rs new file mode 100644 index 000000000..f18a45083 --- /dev/null +++ b/CoqOfRust/core/pin.rs @@ -0,0 +1,2018 @@ +//! Types that pin data to a location in memory. +//! +//! It is sometimes useful to be able to rely upon a certain value not being able to *move*, +//! in the sense that its address in memory cannot change. This is useful especially when there +//! are one or more [*pointers*][pointer] pointing at that value. The ability to rely on this +//! guarantee that the value a [pointer] is pointing at (its **pointee**) will +//! +//! 1. Not be *moved* out of its memory location +//! 2. More generally, remain *valid* at that same memory location +//! +//! is called "pinning." We would say that a value which satisfies these guarantees has been +//! "pinned," in that it has been permanently (until the end of its lifespan) attached to its +//! location in memory, as though pinned to a pinboard. Pinning a value is an incredibly useful +//! building block for [`unsafe`] code to be able to reason about whether a raw pointer to the +//! pinned value is still valid. [As we'll see later][drop-guarantee], this is necessarily from the +//! time the value is first pinned until the end of its lifespan. This concept of "pinning" is +//! necessary to implement safe interfaces on top of things like self-referential types and +//! intrusive data structures which cannot currently be modeled in fully safe Rust using only +//! borrow-checked [references][reference]. +//! +//! "Pinning" allows us to put a *value* which exists at some location in memory into a state where +//! safe code cannot *move* that value to a different location in memory or otherwise invalidate it +//! at its current location (unless it implements [`Unpin`], which we will +//! [talk about below][self#unpin]). Anything that wants to interact with the pinned value in a way +//! that has the potential to violate these guarantees must promise that it will not actually +//! violate them, using the [`unsafe`] keyword to mark that such a promise is upheld by the user +//! and not the compiler. In this way, we can allow other [`unsafe`] code to rely on any pointers +//! that point to the pinned value to be valid to dereference while it is pinned. +//! +//! Note that as long as you don't use [`unsafe`], it's impossible to create or misuse a pinned +//! value in a way that is unsound. See the documentation of [`Pin`] for more +//! information on the practicalities of how to pin a value and how to use that pinned value from a +//! user's perspective without using [`unsafe`]. +//! +//! The rest of this documentation is intended to be the source of truth for users of [`Pin`] +//! that are implementing the [`unsafe`] pieces of an interface that relies on pinning for validity; +//! users of [`Pin`] in safe code do not need to read it in detail. +//! +//! There are several sections to this documentation: +//! +//! * [What is "*moving*"?][what-is-moving] +//! * [What is "pinning"?][what-is-pinning] +//! * [Address sensitivity, AKA "when do we need pinning?"][address-sensitive-values] +//! * [Examples of types with address-sensitive states][address-sensitive-examples] +//! * [Self-referential struct][self-ref] +//! * [Intrusive, doubly-linked list][linked-list] +//! * [Subtle details and the `Drop` guarantee][subtle-details] +//! +//! # What is "*moving*"? +//! [what-is-moving]: self#what-is-moving +//! +//! When we say a value is *moved*, we mean that the compiler copies, byte-for-byte, the +//! value from one location to another. In a purely mechanical sense, this is identical to +//! [`Copy`]ing a value from one place in memory to another. In Rust, "move" carries with it the +//! semantics of ownership transfer from one variable to another, which is the key difference +//! between a [`Copy`] and a move. For the purposes of this module's documentation, however, when +//! we write *move* in italics, we mean *specifically* that the value has *moved* in the mechanical +//! sense of being located at a new place in memory. +//! +//! All values in Rust are trivially *moveable*. This means that the address at which a value is +//! located is not necessarily stable in between borrows. The compiler is allowed to *move* a value +//! to a new address without running any code to notify that value that its address +//! has changed. Although the compiler will not insert memory *moves* where no semantic move has +//! occurred, there are many places where a value *may* be moved. For example, when doing +//! assignment or passing a value into a function. +//! +//! ``` +//! #[derive(Default)] +//! struct AddrTracker(Option); +//! +//! impl AddrTracker { +//! // If we haven't checked the addr of self yet, store the current +//! // address. If we have, confirm that the current address is the same +//! // as it was last time, or else panic. +//! fn check_for_move(&mut self) { +//! let current_addr = self as *mut Self as usize; +//! match self.0 { +//! None => self.0 = Some(current_addr), +//! Some(prev_addr) => assert_eq!(prev_addr, current_addr), +//! } +//! } +//! } +//! +//! // Create a tracker and store the initial address +//! let mut tracker = AddrTracker::default(); +//! tracker.check_for_move(); +//! +//! // Here we shadow the variable. This carries a semantic move, and may therefore also +//! // come with a mechanical memory *move* +//! let mut tracker = tracker; +//! +//! // May panic! +//! // tracker.check_for_move(); +//! ``` +//! +//! In this sense, Rust does not guarantee that `check_for_move()` will never panic, because the +//! compiler is permitted to *move* `tracker` in many situations. +//! +//! Common smart-pointer types such as [`Box`] and [`&mut T`] also allow *moving* the underlying +//! *value* they point at: you can move out of a [`Box`], or you can use [`mem::replace`] to +//! move a `T` out of a [`&mut T`]. Therefore, putting a value (such as `tracker` above) behind a +//! pointer isn't enough on its own to ensure that its address does not change. +//! +//! # What is "pinning"? +//! [what-is-pinning]: self#what-is-pinning +//! +//! We say that a value has been *pinned* when it has been put into a state where it is guaranteed +//! to remain *located at the same place in memory* from the time it is pinned until its +//! [`drop`] is called. +//! +//! ## Address-sensitive values, AKA "when we need pinning" +//! [address-sensitive-values]: self#address-sensitive-values-aka-when-we-need-pinning +//! +//! Most values in Rust are entirely okay with being *moved* around at-will. +//! Types for which it is *always* the case that *any* value of that type can be +//! *moved* at-will should implement [`Unpin`], which we will discuss more [below][self#unpin]. +//! +//! [`Pin`] is specifically targeted at allowing the implementation of *safe interfaces* around +//! types which have some state during which they become "address-sensitive." A value in such an +//! "address-sensitive" state is *not* okay with being *moved* around at-will. Such a value must +//! stay *un-moved* and valid during the address-sensitive portion of its lifespan because some +//! interface is relying on those invariants to be true in order for its implementation to be sound. +//! +//! As a motivating example of a type which may become address-sensitive, consider a type which +//! contains a pointer to another piece of its own data, *i.e.* a "self-referential" type. In order +//! for such a type to be implemented soundly, the pointer which points into `self`'s data must be +//! proven valid whenever it is accessed. But if that value is *moved*, the pointer will still +//! point to the old address where the value was located and not into the new location of `self`, +//! thus becoming invalid. A key example of such self-referential types are the state machines +//! generated by the compiler to implement [`Future`] for `async fn`s. +//! +//! Such types that have an *address-sensitive* state usually follow a lifecycle +//! that looks something like so: +//! +//! 1. A value is created which can be freely moved around. +//! * e.g. calling an async function which returns a state machine implementing [`Future`] +//! 2. An operation causes the value to depend on its own address not changing +//! * e.g. calling [`poll`] for the first time on the produced [`Future`] +//! 3. Further pieces of the safe interface of the type use internal [`unsafe`] operations which +//! assume that the address of the value is stable +//! * e.g. subsequent calls to [`poll`] +//! 4. Before the value is invalidated (e.g. deallocated), it is *dropped*, giving it a chance to +//! notify anything with pointers to itself that those pointers will be invalidated +//! * e.g. [`drop`]ping the [`Future`] [^pin-drop-future] +//! +//! There are two possible ways to ensure the invariants required for 2. and 3. above (which +//! apply to any address-sensitive type, not just self-referential types) do not get broken. +//! +//! 1. Have the value detect when it is moved and update all the pointers that point to itself. +//! 2. Guarantee that the address of the value does not change (and that memory is not re-used +//! for anything else) during the time that the pointers to it are expected to be valid to +//! dereference. +//! +//! Since, as we discussed, Rust can move values without notifying them that they have moved, the +//! first option is ruled out. +//! +//! In order to implement the second option, we must in some way enforce its key invariant, +//! *i.e.* prevent the value from being *moved* or otherwise invalidated (you may notice this +//! sounds an awful lot like the definition of *pinning* a value). There a few ways one might be +//! able to enforce this invariant in Rust: +//! +//! 1. Offer a wholly `unsafe` API to interact with the object, thus requiring every caller to +//! uphold the invariant themselves +//! 2. Store the value that must not be moved behind a carefully managed pointer internal to +//! the object +//! 3. Leverage the type system to encode and enforce this invariant by presenting a restricted +//! API surface to interact with *any* object that requires these invariants +//! +//! The first option is quite obviously undesirable, as the [`unsafe`]ty of the interface will +//! become viral throughout all code that interacts with the object. +//! +//! The second option is a viable solution to the problem for some use cases, in particular +//! for self-referential types. Under this model, any type that has an address sensitive state +//! would ultimately store its data in something like a [`Box`], carefully manage internal +//! access to that data to ensure no *moves* or other invalidation occurs, and finally +//! provide a safe interface on top. +//! +//! There are a couple of linked disadvantages to using this model. The most significant is that +//! each individual object must assume it is *on its own* to ensure +//! that its data does not become *moved* or otherwise invalidated. Since there is no shared +//! contract between values of different types, an object cannot assume that others interacting +//! with it will properly respect the invariants around interacting with its data and must +//! therefore protect it from everyone. Because of this, *composition* of address-sensitive types +//! requires at least a level of pointer indirection each time a new object is added to the mix +//! (and, practically, a heap allocation). +//! +//! Although there were other reasons as well, this issue of expensive composition is the key thing +//! that drove Rust towards adopting a different model. It is particularly a problem +//! when one considers, for example, the implications of composing together the [`Future`]s which +//! will eventually make up an asynchronous task (including address-sensitive `async fn` state +//! machines). It is plausible that there could be many layers of [`Future`]s composed together, +//! including multiple layers of `async fn`s handling different parts of a task. It was deemed +//! unacceptable to force indirection and allocation for each layer of composition in this case. +//! +//! [`Pin`] is an implementation of the third option. It allows us to solve the issues +//! discussed with the second option by building a *shared contractual language* around the +//! guarantees of "pinning" data. +//! +//! [^pin-drop-future]: Futures themselves do not ever need to notify other bits of code that +//! they are being dropped, however data structures like stack-based intrusive linked lists do. +//! +//! ## Using [`Pin`] to pin values +//! +//! In order to pin a value, we wrap a *pointer to that value* (of some type `Ptr`) in a +//! [`Pin`]. [`Pin`] can wrap any pointer type, forming a promise that the **pointee** +//! will not be *moved* or [otherwise invalidated][subtle-details]. +//! +//! We call such a [`Pin`]-wrapped pointer a **pinning pointer,** (or pinning reference, or pinning +//! `Box`, etc.) because its existence is the thing that is conceptually pinning the underlying +//! pointee in place: it is the metaphorical "pin" securing the data in place on the pinboard +//! (in memory). +//! +//! Notice that the thing wrapped by [`Pin`] is not the value which we want to pin itself, but +//! rather a pointer to that value! A [`Pin`] does not pin the `Ptr`; instead, it pins the +//! pointer's ***pointee** value*. +//! +//! ### Pinning as a library contract +//! +//! Pinning does not require nor make use of any compiler "magic"[^noalias], only a specific +//! contract between the [`unsafe`] parts of a library API and its users. +//! +//! It is important to stress this point as a user of the [`unsafe`] parts of the [`Pin`] API. +//! Practically, this means that performing the mechanics of "pinning" a value by creating a +//! [`Pin`] to it *does not* actually change the way the compiler behaves towards the +//! inner value! It is possible to use incorrect [`unsafe`] code to create a [`Pin`] to a +//! value which does not actually satisfy the invariants that a pinned value must satisfy, and in +//! this way lead to undefined behavior even in (from that point) fully safe code. Similarly, using +//! [`unsafe`], one may get access to a bare [`&mut T`] from a [`Pin`] and +//! use that to invalidly *move* the pinned value out. It is the job of the user of the +//! [`unsafe`] parts of the [`Pin`] API to ensure these invariants are not violated. +//! +//! This differs from e.g. [`UnsafeCell`] which changes the semantics of a program's compiled +//! output. A [`Pin`] is a handle to a value which we have promised we will not move out of, +//! but Rust still considers all values themselves to be fundamentally moveable through, *e.g.* +//! assignment or [`mem::replace`]. +//! +//! [^noalias]: There is a bit of nuance here that is still being decided about what the aliasing +//! semantics of `Pin<&mut T>` should be, but this is true as of today. +//! +//! ### How [`Pin`] prevents misuse in safe code +//! +//! In order to accomplish the goal of pinning the pointee value, [`Pin`] restricts access to +//! the wrapped `Ptr` type in safe code. Specifically, [`Pin`] disallows the ability to access +//! the wrapped pointer in ways that would allow the user to *move* the underlying pointee value or +//! otherwise re-use that memory for something else without using [`unsafe`]. For example, a +//! [`Pin<&mut T>`] makes it impossible to obtain the wrapped [&mut] T safely because +//! through that [&mut] T it would be possible to *move* the underlying value out of +//! the pointer with [`mem::replace`], etc. +//! +//! As discussed above, this promise must be upheld manually by [`unsafe`] code which interacts +//! with the [`Pin`] so that other [`unsafe`] code can rely on the pointee value being +//! *un-moved* and valid. Interfaces that operate on values which are in an address-sensitive state +//! accept an argument like [Pin]<[&mut] T> or [Pin]<[Box]\> to +//! indicate this contract to the caller. +//! +//! [As discussed below][drop-guarantee], opting in to using pinning guarantees in the interface +//! of an address-sensitive type has consequences for the implementation of some safe traits on +//! that type as well. +//! +//! ## Interaction between [`Deref`] and [`Pin`] +//! +//! Since [`Pin`] can wrap any pointer type, it uses [`Deref`] and [`DerefMut`] in +//! order to identify the type of the pinned pointee data and provide (restricted) access to it. +//! +//! A [`Pin`] where [`Ptr: Deref`][Deref] is a "`Ptr`-style pinning pointer" to a pinned +//! [`Ptr::Target`][Target] – so, a [Pin]<[Box]\> is an owned, pinning pointer to a +//! pinned `T`, and a [Pin]<[Rc]\> is a reference-counted, pinning pointer to a +//! pinned `T`. +//! +//! [`Pin`] also uses the [`::Target`][Target] type information to modify the +//! interface it is allowed to provide for interacting with that data (for example, when a +//! pinning pointer points at pinned data which implements [`Unpin`], as +//! [discussed below][self#unpin]). +//! +//! [`Pin`] requires that implementations of [`Deref`] and [`DerefMut`] on `Ptr` return a +//! pointer to the pinned data directly and do not *move* out of the `self` parameter during their +//! implementation of [`DerefMut::deref_mut`]. It is unsound for [`unsafe`] code to wrap pointer +//! types with such "malicious" implementations of [`Deref`]; see [`Pin::new_unchecked`] for +//! details. +//! +//! ## Fixing `AddrTracker` +//! +//! The guarantee of a stable address is necessary to make our `AddrTracker` example work. When +//! `check_for_move` sees a [Pin]<&mut AddrTracker>, it can safely assume that value +//! will exist at that same address until said value goes out of scope, and thus multiple calls +//! to it *cannot* panic. +//! +//! ``` +//! use std::marker::PhantomPinned; +//! use std::pin::Pin; +//! use std::pin::pin; +//! +//! #[derive(Default)] +//! struct AddrTracker { +//! prev_addr: Option, +//! // remove auto-implemented `Unpin` bound to mark this type as having some +//! // address-sensitive state. This is essential for our expected pinning +//! // guarantees to work, and is discussed more below. +//! _pin: PhantomPinned, +//! } +//! +//! impl AddrTracker { +//! fn check_for_move(self: Pin<&mut Self>) { +//! let current_addr = &*self as *const Self as usize; +//! match self.prev_addr { +//! None => { +//! // SAFETY: we do not move out of self +//! let self_data_mut = unsafe { self.get_unchecked_mut() }; +//! self_data_mut.prev_addr = Some(current_addr); +//! }, +//! Some(prev_addr) => assert_eq!(prev_addr, current_addr), +//! } +//! } +//! } +//! +//! // 1. Create the value, not yet in an address-sensitive state +//! let tracker = AddrTracker::default(); +//! +//! // 2. Pin the value by putting it behind a pinning pointer, thus putting +//! // it into an address-sensitive state +//! let mut ptr_to_pinned_tracker: Pin<&mut AddrTracker> = pin!(tracker); +//! ptr_to_pinned_tracker.as_mut().check_for_move(); +//! +//! // Trying to access `tracker` or pass `ptr_to_pinned_tracker` to anything that requires +//! // mutable access to a non-pinned version of it will no longer compile +//! +//! // 3. We can now assume that the tracker value will never be moved, thus +//! // this will never panic! +//! ptr_to_pinned_tracker.as_mut().check_for_move(); +//! ``` +//! +//! Note that this invariant is enforced by simply making it impossible to call code that would +//! perform a move on the pinned value. This is the case since the only way to access that pinned +//! value is through the pinning [Pin]<[&mut] T>>, which in turn restricts our access. +//! +//! ## [`Unpin`] +//! +//! The vast majority of Rust types have no address-sensitive states. These types +//! implement the [`Unpin`] auto-trait, which cancels the restrictive effects of +//! [`Pin`] when the *pointee* type `T` is [`Unpin`]. When [`T: Unpin`][Unpin], +//! [Pin]<[Box]\> functions identically to a non-pinning [`Box`]; similarly, +//! [Pin]<[&mut] T> would impose no additional restrictions above a regular +//! [`&mut T`]. +//! +//! The idea of this trait is to alleviate the reduced ergonomics of APIs that require the use +//! of [`Pin`] for soundness for some types, but which also want to be used by other types that +//! don't care about pinning. The prime example of such an API is [`Future::poll`]. There are many +//! [`Future`] types that don't care about pinning. These futures can implement [`Unpin`] and +//! therefore get around the pinning related restrictions in the API, while still allowing the +//! subset of [`Future`]s which *do* require pinning to be implemented soundly. +//! +//! Note that the interaction between a [`Pin`] and [`Unpin`] is through the type of the +//! **pointee** value, [`::Target`][Target]. Whether the `Ptr` type itself +//! implements [`Unpin`] does not affect the behavior of a [`Pin`]. For example, whether or not +//! [`Box`] is [`Unpin`] has no effect on the behavior of [Pin]<[Box]\>, because +//! `T` is the type of the pointee value, not [`Box`]. So, whether `T` implements [`Unpin`] is +//! the thing that will affect the behavior of the [Pin]<[Box]\>. +//! +//! Builtin types that are [`Unpin`] include all of the primitive types, like [`bool`], [`i32`], +//! and [`f32`], references ([&]T and [&mut] T), etc., as well as many +//! core and standard library types like [`Box`], [`String`], and more. +//! These types are marked [`Unpin`] because they do not have an address-sensitive state like the +//! ones we discussed above. If they did have such a state, those parts of their interface would be +//! unsound without being expressed through pinning, and they would then need to not +//! implement [`Unpin`]. +//! +//! The compiler is free to take the conservative stance of marking types as [`Unpin`] so long as +//! all of the types that compose its fields are also [`Unpin`]. This is because if a type +//! implements [`Unpin`], then it is unsound for that type's implementation to rely on +//! pinning-related guarantees for soundness, *even* when viewed through a "pinning" pointer! It is +//! the responsibility of the implementor of a type that relies upon pinning for soundness to +//! ensure that type is *not* marked as [`Unpin`] by adding [`PhantomPinned`] field. This is +//! exactly what we did with our `AddrTracker` example above. Without doing this, you *must not* +//! rely on pinning-related guarantees to apply to your type! +//! +//! If you really need to pin a value of a foreign or built-in type that implements [`Unpin`], +//! you'll need to create your own wrapper type around the [`Unpin`] type you want to pin and then +//! opt-out of [`Unpin`] using [`PhantomPinned`]. +//! +//! Exposing access to the inner field which you want to remain pinned must then be carefully +//! considered as well! Remember, exposing a method that gives access to a +//! [Pin]<[&mut] InnerT>> where InnerT: [Unpin] would allow safe code to +//! trivially move the inner value out of that pinning pointer, which is precisely what you're +//! seeking to prevent! Exposing a field of a pinned value through a pinning pointer is called +//! "projecting" a pin, and the more general case of deciding in which cases a pin should be able +//! to be projected or not is called "structural pinning." We will go into more detail about this +//! [below][structural-pinning]. +//! +//! # Examples of address-sensitive types +//! [address-sensitive-examples]: #examples-of-address-sensitive-types +//! +//! ## A self-referential struct +//! [self-ref]: #a-self-referential-struct +//! [`Unmovable`]: #a-self-referential-struct +//! +//! Self-referential structs are the simplest kind of address-sensitive type. +//! +//! It is often useful for a struct to hold a pointer back into itself, which +//! allows the program to efficiently track subsections of the struct. +//! Below, the `slice` field is a pointer into the `data` field, which +//! we could imagine being used to track a sliding window of `data` in parser +//! code. +//! +//! As mentioned before, this pattern is also used extensively by compiler-generated +//! [`Future`]s. +//! +//! ```rust +//! use std::pin::Pin; +//! use std::marker::PhantomPinned; +//! use std::ptr::NonNull; +//! +//! /// This is a self-referential struct because `self.slice` points into `self.data`. +//! struct Unmovable { +//! /// Backing buffer. +//! data: [u8; 64], +//! /// Points at `self.data` which we know is itself non-null. Raw pointer because we can't do +//! /// this with a normal reference. +//! slice: NonNull<[u8]>, +//! /// Suppress `Unpin` so that this cannot be moved out of a `Pin` once constructed. +//! _pin: PhantomPinned, +//! } +//! +//! impl Unmovable { +//! /// Creates a new `Unmovable`. +//! /// +//! /// To ensure the data doesn't move we place it on the heap behind a pinning Box. +//! /// Note that the data is pinned, but the `Pin>` which is pinning it can +//! /// itself still be moved. This is important because it means we can return the pinning +//! /// pointer from the function, which is itself a kind of move! +//! fn new() -> Pin> { +//! let res = Unmovable { +//! data: [0; 64], +//! // We only create the pointer once the data is in place +//! // otherwise it will have already moved before we even started. +//! slice: NonNull::from(&[]), +//! _pin: PhantomPinned, +//! }; +//! // First we put the data in a box, which will be its final resting place +//! let mut boxed = Box::new(res); +//! +//! // Then we make the slice field point to the proper part of that boxed data. +//! // From now on we need to make sure we don't move the boxed data. +//! boxed.slice = NonNull::from(&boxed.data); +//! +//! // To do that, we pin the data in place by pointing to it with a pinning +//! // (`Pin`-wrapped) pointer. +//! // +//! // `Box::into_pin` makes existing `Box` pin the data in-place without moving it, +//! // so we can safely do this now *after* inserting the slice pointer above, but we have +//! // to take care that we haven't performed any other semantic moves of `res` in between. +//! let pin = Box::into_pin(boxed); +//! +//! // Now we can return the pinned (through a pinning Box) data +//! pin +//! } +//! } +//! +//! let unmovable: Pin> = Unmovable::new(); +//! +//! // The inner pointee `Unmovable` struct will now never be allowed to move. +//! // Meanwhile, we are free to move the pointer around. +//! # #[allow(unused_mut)] +//! let mut still_unmoved = unmovable; +//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data)); +//! +//! // We cannot mutably dereference a `Pin` unless the pointee is `Unpin` or we use unsafe. +//! // Since our type doesn't implement `Unpin`, this will fail to compile. +//! // let mut new_unmoved = Unmovable::new(); +//! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved); +//! ``` +//! +//! ## An intrusive, doubly-linked list +//! [linked-list]: #an-intrusive-doubly-linked-list +//! +//! In an intrusive doubly-linked list, the collection itself does not own the memory in which +//! each of its elements is stored. Instead, each client is free to allocate space for elements it +//! adds to the list in whichever manner it likes, including on the stack! Elements can live on a +//! stack frame that lives shorter than the collection does provided the elements that live in a +//! given stack frame are removed from the list before going out of scope. +//! +//! To make such an intrusive data structure work, every element stores pointers to its predecessor +//! and successor within its own data, rather than having the list structure itself managing those +//! pointers. It is in this sense that the structure is "intrusive": the details of how an +//! element is stored within the larger structure "intrudes" on the implementation of the element +//! type itself! +//! +//! The full implementation details of such a data structure are outside the scope of this +//! documentation, but we will discuss how [`Pin`] can help to do so. +//! +//! Using such an intrusive pattern, elements may only be added when they are pinned. If we think +//! about the consequences of adding non-pinned values to such a list, this becomes clear: +//! +//! *Moving* or otherwise invalidating an element's data would invalidate the pointers back to it +//! which are stored in the elements ahead and behind it. Thus, in order to soundly dereference +//! the pointers stored to the next and previous elements, we must satisfy the guarantee that +//! nothing has invalidated those pointers (which point to data that we do not own). +//! +//! Moreover, the [`Drop`][Drop] implementation of each element must in some way notify its +//! predecessor and successor elements that it should be removed from the list before it is fully +//! destroyed, otherwise the pointers back to it would again become invalidated. +//! +//! Crucially, this means we have to be able to rely on [`drop`] always being called before an +//! element is invalidated. If an element could be deallocated or otherwise invalidated without +//! calling [`drop`], the pointers to it stored in its neighboring elements would +//! become invalid, which would break the data structure. +//! +//! Therefore, pinning data also comes with [the "`Drop` guarantee"][drop-guarantee]. +//! +//! # Subtle details and the `Drop` guarantee +//! [subtle-details]: self#subtle-details-and-the-drop-guarantee +//! [drop-guarantee]: self#subtle-details-and-the-drop-guarantee +//! +//! The purpose of pinning is not *just* to prevent a value from being *moved*, but more +//! generally to be able to rely on the pinned value *remaining valid **at a specific place*** in +//! memory. +//! +//! To do so, pinning a value adds an *additional* invariant that must be upheld in order for use +//! of the pinned data to be valid, on top of the ones that must be upheld for a non-pinned value +//! of the same type to be valid: +//! +//! From the moment a value is pinned by constructing a [`Pin`]ning pointer to it, that value +//! must *remain, **valid***, at that same address in memory, *until its [`drop`] handler is +//! called.* +//! +//! There is some subtlety to this which we have not yet talked about in detail. The invariant +//! described above means that, yes, +//! +//! 1. The value must not be moved out of its location in memory +//! +//! but it also implies that, +//! +//! 2. The memory location that stores the value must not get invalidated or otherwise repurposed +//! during the lifespan of the pinned value until its [`drop`] returns or panics +//! +//! This point is subtle but required for intrusive data structures to be implemented soundly. +//! +//! ## `Drop` guarantee +//! +//! There needs to be a way for a pinned value to notify any code that is relying on its pinned +//! status that it is about to be destroyed. In this way, the dependent code can remove the +//! pinned value's address from its data structures or otherwise change its behavior with the +//! knowledge that it can no longer rely on that value existing at the location it was pinned to. +//! +//! Thus, in any situation where we may want to overwrite a pinned value, that value's [`drop`] must +//! be called beforehand (unless the pinned value implements [`Unpin`], in which case we can ignore +//! all of [`Pin`]'s guarantees, as usual). +//! +//! The most common storage-reuse situations occur when a value on the stack is destroyed as part +//! of a function return and when heap storage is freed. In both cases, [`drop`] gets run for us +//! by Rust when using standard safe code. However, for manual heap allocations or otherwise +//! custom-allocated storage, [`unsafe`] code must make sure to call [`ptr::drop_in_place`] before +//! deallocating and re-using said storage. +//! +//! In addition, storage "re-use"/invalidation can happen even if no storage is (de-)allocated. +//! For example, if we had an [`Option`] which contained a `Some(v)` where `v` is pinned, then `v` +//! would be invalidated by setting that option to `None`. +//! +//! Similarly, if a [`Vec`] was used to store pinned values and [`Vec::set_len`] was used to +//! manually "kill" some elements of a vector, all of the items "killed" would become invalidated, +//! which would be *undefined behavior* if those items were pinned. +//! +//! Both of these cases are somewhat contrived, but it is crucial to remember that [`Pin`]ned data +//! *must* be [`drop`]ped before it is invalidated; not just to prevent memory leaks, but as a +//! matter of soundness. As a corollary, the following code can *never* be made safe: +//! +//! ```rust +//! # use std::mem::ManuallyDrop; +//! # use std::pin::Pin; +//! # struct Type; +//! // Pin something inside a `ManuallyDrop`. This is fine on its own. +//! let mut pin: Pin>> = Box::pin(ManuallyDrop::new(Type)); +//! +//! // However, creating a pinning mutable reference to the type *inside* +//! // the `ManuallyDrop` is not! +//! let inner: Pin<&mut Type> = unsafe { +//! Pin::map_unchecked_mut(pin.as_mut(), |x| &mut **x) +//! }; +//! ``` +//! +//! Because [`mem::ManuallyDrop`] inhibits the destructor of `Type`, it won't get run when the +//! [Box]<[ManuallyDrop]\> is dropped, thus violating the drop guarantee of the +//! [Pin]<[&mut] Type>>. +//! +//! Of course, *leaking* memory in such a way that its underlying storage will never get invalidated +//! or re-used is still fine: [`mem::forget`]ing a [`Box`] prevents its storage from ever getting +//! re-used, so the [`drop`] guarantee is still satisfied. +//! +//! # Implementing an address-sensitive type. +//! +//! This section goes into detail on important considerations for implementing your own +//! address-sensitive types, which are different from merely using [`Pin`] in a generic +//! way. +//! +//! ## Implementing [`Drop`] for types with address-sensitive states +//! [drop-impl]: self#implementing-drop-for-types-with-address-sensitive-states +//! +//! The [`drop`] function takes [`&mut self`], but this is called *even if that `self` has been +//! pinned*! Implementing [`Drop`] for a type with address-sensitive states, because if `self` was +//! indeed in an address-sensitive state before [`drop`] was called, it is as if the compiler +//! automatically called [`Pin::get_unchecked_mut`]. +//! +//! This can never cause a problem in purely safe code because creating a pinning pointer to +//! a type which has an address-sensitive (thus does not implement `Unpin`) requires `unsafe`, +//! but it is important to note that choosing to take advantage of pinning-related guarantees +//! to justify validity in the implementation of your type has consequences for that type's +//! [`Drop`][Drop] implementation as well: if an element of your type could have been pinned, +//! you must treat [`Drop`][Drop] as implicitly taking self: [Pin]<[&mut] Self>. +//! +//! You should implement [`Drop`] as follows: +//! +//! ```rust,no_run +//! # use std::pin::Pin; +//! # struct Type; +//! impl Drop for Type { +//! fn drop(&mut self) { +//! // `new_unchecked` is okay because we know this value is never used +//! // again after being dropped. +//! inner_drop(unsafe { Pin::new_unchecked(self)}); +//! fn inner_drop(this: Pin<&mut Type>) { +//! // Actual drop code goes here. +//! } +//! } +//! } +//! ``` +//! +//! The function `inner_drop` has the signature that [`drop`] *should* have in this situation. +//! This makes sure that you do not accidentally use `self`/`this` in a way that is in conflict +//! with pinning's invariants. +//! +//! Moreover, if your type is [`#[repr(packed)]`][packed], the compiler will automatically +//! move fields around to be able to drop them. It might even do +//! that for fields that happen to be sufficiently aligned. As a consequence, you cannot use +//! pinning with a [`#[repr(packed)]`][packed] type. +//! +//! ### Implementing [`Drop`] for pointer types which will be used as [`Pin`]ning pointers +//! +//! It should further be noted that creating a pinning pointer of some type `Ptr` *also* carries +//! with it implications on the way that `Ptr` type must implement [`Drop`] +//! (as well as [`Deref`] and [`DerefMut`])! When implementing a pointer type that may be used as +//! a pinning pointer, you must also take the same care described above not to *move* out of or +//! otherwise invalidate the pointee during [`Drop`], [`Deref`], or [`DerefMut`] +//! implementations. +//! +//! ## "Assigning" pinned data +//! +//! Although in general it is not valid to swap data or assign through a [`Pin`] for the same +//! reason that reusing a pinned object's memory is invalid, it is possible to do validly when +//! implemented with special care for the needs of the exact data structure which is being +//! modified. For example, the assigning function must know how to update all uses of the pinned +//! address (and any other invariants necessary to satisfy validity for that type). For +//! [`Unmovable`] (from the example above), we could write an assignment function like so: +//! +//! ``` +//! # use std::pin::Pin; +//! # use std::marker::PhantomPinned; +//! # use std::ptr::NonNull; +//! # struct Unmovable { +//! # data: [u8; 64], +//! # slice: NonNull<[u8]>, +//! # _pin: PhantomPinned, +//! # } +//! # +//! impl Unmovable { +//! // Copies the contents of `src` into `self`, fixing up the self-pointer +//! // in the process. +//! fn assign(self: Pin<&mut Self>, src: Pin<&mut Self>) { +//! unsafe { +//! let unpinned_self = Pin::into_inner_unchecked(self); +//! let unpinned_src = Pin::into_inner_unchecked(src); +//! *unpinned_self = Self { +//! data: unpinned_src.data, +//! slice: NonNull::from(&mut []), +//! _pin: PhantomPinned, +//! }; +//! +//! let data_ptr = unpinned_src.data.as_ptr() as *const u8; +//! let slice_ptr = unpinned_src.slice.as_ptr() as *const u8; +//! let offset = slice_ptr.offset_from(data_ptr) as usize; +//! let len = (*unpinned_src.slice.as_ptr()).len(); +//! +//! unpinned_self.slice = NonNull::from(&mut unpinned_self.data[offset..offset+len]); +//! } +//! } +//! } +//! ``` +//! +//! Even though we can't have the compiler do the assignment for us, it's possible to write +//! such specialized functions for types that might need it. +//! +//! Note that it _is_ possible to assign generically through a [`Pin`] by way of [`Pin::set()`]. +//! This does not violate any guarantees, since it will run [`drop`] on the pointee value before +//! assigning the new value. Thus, the [`drop`] implementation still has a chance to perform the +//! necessary notifications to dependent values before the memory location of the original pinned +//! value is overwritten. +//! +//! ## Projections and Structural Pinning +//! [structural-pinning]: self#projections-and-structural-pinning +//! +//! With ordinary structs, it is natural that we want to add *projection* methods that allow +//! borrowing one or more of the inner fields of a struct when the caller has access to a +//! borrow of the whole struct: +//! +//! ``` +//! # struct Field; +//! struct Struct { +//! field: Field, +//! // ... +//! } +//! +//! impl Struct { +//! fn field(&mut self) -> &mut Field { &mut self.field } +//! } +//! ``` +//! +//! When working with address-sensitive types, it's not obvious what the signature of these +//! functions should be. If `field` takes self: [Pin]<[&mut Struct][&mut]>, should it +//! return [`&mut Field`] or [Pin]<[`&mut Field`]>? This question also arises with +//! `enum`s and wrapper types like [`Vec`], [`Box`], and [`RefCell`]. (This question +//! applies just as well to shared references, but we'll examine the more common case of mutable +//! references for illustration) +//! +//! It turns out that it's up to the author of `Struct` to decide which type the "projection" +//! should produce. The choice must be *consistent* though: if a pin is projected to a field +//! in one place, then it should very likely not be exposed elsewhere without projecting the +//! pin. +//! +//! As the author of a data structure, you get to decide for each field whether pinning +//! "propagates" to this field or not. Pinning that propagates is also called "structural", +//! because it follows the structure of the type. +//! +//! This choice depends on what guarantees you need from the field for your [`unsafe`] code to work. +//! If the field is itself address-sensitive, or participates in the parent struct's address +//! sensitivity, it will need to be structurally pinned. +//! +//! A useful test is if [`unsafe`] code that consumes [Pin]\<[&mut Struct][&mut]> +//! also needs to take note of the address of the field itself, it may be evidence that that field +//! is structurally pinned. Unfortunately, there are no hard-and-fast rules. +//! +//! ### Choosing pinning *not to be* structural for `field`... +//! +//! While counter-intuitive, it's often the easier choice: if you do not expose a +//! [Pin]<[&mut] Field>, you do not need to be careful about other code +//! moving out of that field, you just have to ensure is that you never create pinning +//! reference to that field. This does of course also mean that if you decide a field does not +//! have structural pinning, you must not write [`unsafe`] code that assumes (invalidly) that the +//! field *is* structurally pinned! +//! +//! Fields without structural pinning may have a projection method that turns +//! [Pin]<[&mut] Struct> into [`&mut Field`]: +//! +//! ```rust,no_run +//! # use std::pin::Pin; +//! # type Field = i32; +//! # struct Struct { field: Field } +//! impl Struct { +//! fn field(self: Pin<&mut Self>) -> &mut Field { +//! // This is okay because `field` is never considered pinned, therefore we do not +//! // need to uphold any pinning guarantees for this field in particular. Of course, +//! // we must not elsewhere assume this field *is* pinned if we choose to expose +//! // such a method! +//! unsafe { &mut self.get_unchecked_mut().field } +//! } +//! } +//! ``` +//! +//! You may also in this situation impl [Unpin] for Struct {} *even if* the type of +//! `field` is not [`Unpin`]. Since we have explicitly chosen not to care about pinning guarantees +//! for `field`, the way `field`'s type interacts with pinning is no longer relevant in the +//! context of its use in `Struct`. +//! +//! ### Choosing pinning *to be* structural for `field`... +//! +//! The other option is to decide that pinning is "structural" for `field`, +//! meaning that if the struct is pinned then so is the field. +//! +//! This allows writing a projection that creates a [Pin]<[`&mut Field`]>, thus +//! witnessing that the field is pinned: +//! +//! ```rust,no_run +//! # use std::pin::Pin; +//! # type Field = i32; +//! # struct Struct { field: Field } +//! impl Struct { +//! fn field(self: Pin<&mut Self>) -> Pin<&mut Field> { +//! // This is okay because `field` is pinned when `self` is. +//! unsafe { self.map_unchecked_mut(|s| &mut s.field) } +//! } +//! } +//! ``` +//! +//! Structural pinning comes with a few extra requirements: +//! +//! 1. *Structural [`Unpin`].* A struct can be [`Unpin`] only if all of its +//! structurally-pinned fields are, too. This is [`Unpin`]'s behavior by default. +//! However, as a libray author, it is your responsibility not to write something like +//! impl\ [Unpin] for Struct\ {} and then offer a method that provides +//! structural pinning to an inner field of `T`, which may not be [`Unpin`]! (Adding *any* +//! projection operation requires unsafe code, so the fact that [`Unpin`] is a safe trait does +//! not break the principle that you only have to worry about any of this if you use +//! [`unsafe`]) +//! +//! 2. *Pinned Destruction.* As discussed [above][drop-impl], [`drop`] takes +//! [`&mut self`], but the struct (and hence its fields) might have been pinned +//! before. The destructor must be written as if its argument was +//! self: [Pin]\<[`&mut Self`]>, instead. +//! +//! As a consequence, the struct *must not* be [`#[repr(packed)]`][packed]. +//! +//! 3. *Structural Notice of Destruction.* You must uphold the +//! [`Drop` guarantee][drop-guarantee]: once your struct is pinned, the struct's storage cannot +//! be re-used without calling the structurally-pinned fields' destructors, as well. +//! +//! This can be tricky, as witnessed by [`VecDeque`]: the destructor of [`VecDeque`] +//! can fail to call [`drop`] on all elements if one of the destructors panics. This violates +//! the [`Drop` guarantee][drop-guarantee], because it can lead to elements being deallocated +//! without their destructor being called. +//! +//! [`VecDeque`] has no pinning projections, so its destructor is sound. If it wanted +//! to provide such structural pinning, its destructor would need to abort the process if any +//! of the destructors panicked. +//! +//! 4. You must not offer any other operations that could lead to data being *moved* out of +//! the structural fields when your type is pinned. For example, if the struct contains an +//! [`Option`] and there is a [`take`][Option::take]-like operation with type +//! fn([Pin]<[&mut Struct\][&mut]>) -> [`Option`], +//! then that operation can be used to move a `T` out of a pinned `Struct` – which +//! means pinning cannot be structural for the field holding this data. +//! +//! For a more complex example of moving data out of a pinned type, +//! imagine if [`RefCell`] had a method +//! fn get_pin_mut(self: [Pin]<[`&mut Self`]>) -> [Pin]<[`&mut T`]>. +//! Then we could do the following: +//! ```compile_fail +//! # use std::cell::RefCell; +//! # use std::pin::Pin; +//! fn exploit_ref_cell(rc: Pin<&mut RefCell>) { +//! // Here we get pinned access to the `T`. +//! let _: Pin<&mut T> = rc.as_mut().get_pin_mut(); +//! +//! // And here we have `&mut T` to the same data. +//! let shared: &RefCell = rc.into_ref().get_ref(); +//! let borrow = shared.borrow_mut(); +//! let content = &mut *borrow; +//! } +//! ``` +//! This is catastrophic: it means we can first pin the content of the +//! [`RefCell`] (using [RefCell]::get_pin_mut) and then move that +//! content using the mutable reference we got later. +//! +//! ### Structural Pinning examples +//! +//! For a type like [`Vec`], both possibilities (structural pinning or not) make +//! sense. A [`Vec`] with structural pinning could have `get_pin`/`get_pin_mut` +//! methods to get pinning references to elements. However, it could *not* allow calling +//! [`pop`][Vec::pop] on a pinned [`Vec`] because that would move the (structurally +//! pinned) contents! Nor could it allow [`push`][Vec::push], which might reallocate and thus also +//! move the contents. +//! +//! A [`Vec`] without structural pinning could +//! impl\ [Unpin] for [`Vec`], because the contents are never pinned +//! and the [`Vec`] itself is fine with being moved as well. +//! At that point pinning just has no effect on the vector at all. +//! +//! In the standard library, pointer types generally do not have structural pinning, +//! and thus they do not offer pinning projections. This is why [`Box`]: [Unpin] +//! holds for all `T`. It makes sense to do this for pointer types, because moving the +//! [`Box`] does not actually move the `T`: the [`Box`] can be freely +//! movable (aka [`Unpin`]) even if the `T` is not. In fact, even [Pin]<[`Box`]> and +//! [Pin]<[`&mut T`]> are always [`Unpin`] themselves, for the same reason: +//! their contents (the `T`) are pinned, but the pointers themselves can be moved without moving +//! the pinned data. For both [`Box`] and [Pin]<[`Box`]>, +//! whether the content is pinned is entirely independent of whether the +//! pointer is pinned, meaning pinning is *not* structural. +//! +//! When implementing a [`Future`] combinator, you will usually need structural pinning +//! for the nested futures, as you need to get pinning ([`Pin`]-wrapped) references to them to +//! call [`poll`]. But if your combinator contains any other data that does not need to be pinned, +//! you can make those fields not structural and hence freely access them with a +//! mutable reference even when you just have [Pin]<[`&mut Self`]> +//! (such as in your own [`poll`] implementation). +//! +//! [`&mut T`]: &mut +//! [`&mut self`]: &mut +//! [`&mut Self`]: &mut +//! [`&mut Field`]: &mut +//! [Deref]: crate::ops::Deref "ops::Deref" +//! [`Deref`]: crate::ops::Deref "ops::Deref" +//! [Target]: crate::ops::Deref::Target "ops::Deref::Target" +//! [`DerefMut`]: crate::ops::DerefMut "ops::DerefMut" +//! [`mem::swap`]: crate::mem::swap "mem::swap" +//! [`mem::forget`]: crate::mem::forget "mem::forget" +//! [ManuallyDrop]: crate::mem::ManuallyDrop "ManuallyDrop" +//! [RefCell]: crate::cell::RefCell "cell::RefCell" +//! [`drop`]: Drop::drop +//! [`ptr::write`]: crate::ptr::write "ptr::write" +//! [`Future`]: crate::future::Future "future::Future" +//! [drop-impl]: #drop-implementation +//! [drop-guarantee]: #drop-guarantee +//! [`poll`]: crate::future::Future::poll "future::Future::poll" +//! [&]: reference "shared reference" +//! [&mut]: reference "mutable reference" +//! [`unsafe`]: ../../std/keyword.unsafe.html "keyword unsafe" +//! [packed]: https://doc.rust-lang.org/nomicon/other-reprs.html#reprpacked +//! [`std::alloc`]: ../../std/alloc/index.html +//! [`Box`]: ../../std/boxed/struct.Box.html +//! [Box]: ../../std/boxed/struct.Box.html "Box" +//! [`Box`]: ../../std/boxed/struct.Box.html "Box" +//! [`Rc`]: ../../std/rc/struct.Rc.html +//! [Rc]: ../../std/rc/struct.Rc.html "rc::Rc" +//! [`Vec`]: ../../std/vec/struct.Vec.html +//! [Vec]: ../../std/vec/struct.Vec.html "Vec" +//! [`Vec`]: ../../std/vec/struct.Vec.html "Vec" +//! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len "Vec::set_len" +//! [Vec::pop]: ../../std/vec/struct.Vec.html#method.pop "Vec::pop" +//! [Vec::push]: ../../std/vec/struct.Vec.html#method.push "Vec::push" +//! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len +//! [`VecDeque`]: ../../std/collections/struct.VecDeque.html +//! [VecDeque]: ../../std/collections/struct.VecDeque.html "collections::VecDeque" +//! [`String`]: ../../std/string/struct.String.html "String" + +#![stable(feature = "pin", since = "1.33.0")] + +use crate::hash::{Hash, Hasher}; +use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver}; +#[allow(unused_imports)] +use crate::{ + cell::{RefCell, UnsafeCell}, + future::Future, + marker::PhantomPinned, + mem, ptr, +}; +use crate::{cmp, fmt}; + +/// A pointer which pins its pointee in place. +/// +/// [`Pin`] is a wrapper around some kind of pointer `Ptr` which makes that pointer "pin" its +/// pointee value in place, thus preventing the value referenced by that pointer from being moved +/// or otherwise invalidated at that place in memory unless it implements [`Unpin`]. +/// +/// *See the [`pin` module] documentation for a more thorough exploration of pinning.* +/// +/// ## Pinning values with [`Pin`] +/// +/// In order to pin a value, we wrap a *pointer to that value* (of some type `Ptr`) in a +/// [`Pin`]. [`Pin`] can wrap any pointer type, forming a promise that the **pointee** +/// will not be *moved* or [otherwise invalidated][subtle-details]. If the pointee value's type +/// implements [`Unpin`], we are free to disregard these requirements entirely and can wrap any +/// pointer to that value in [`Pin`] directly via [`Pin::new`]. If the pointee value's type does +/// not implement [`Unpin`], then Rust will not let us use the [`Pin::new`] function directly and +/// we'll need to construct a [`Pin`]-wrapped pointer in one of the more specialized manners +/// discussed below. +/// +/// We call such a [`Pin`]-wrapped pointer a **pinning pointer** (or pinning ref, or pinning +/// [`Box`], etc.) because its existence is the thing that is pinning the underlying pointee in +/// place: it is the metaphorical "pin" securing the data in place on the pinboard (in memory). +/// +/// It is important to stress that the thing in the [`Pin`] is not the value which we want to pin +/// itself, but rather a pointer to that value! A [`Pin`] does not pin the `Ptr` but rather +/// the pointer's ***pointee** value*. +/// +/// The most common set of types which require pinning related guarantees for soundness are the +/// compiler-generated state machines that implement [`Future`] for the return value of +/// `async fn`s. These compiler-generated [`Future`]s may contain self-referential pointers, one +/// of the most common use cases for [`Pin`]. More details on this point are provided in the +/// [`pin` module] docs, but suffice it to say they require the guarantees provided by pinning to +/// be implemented soundly. +/// +/// This requirement for the implementation of `async fn`s means that the [`Future`] trait +/// requires all calls to [`poll`] to use a self: [Pin]\<&mut Self> parameter instead +/// of the usual `&mut self`. Therefore, when manually polling a future, you will need to pin it +/// first. +/// +/// You may notice that `async fn`-sourced [`Future`]s are only a small percentage of all +/// [`Future`]s that exist, yet we had to modify the signature of [`poll`] for all [`Future`]s +/// to accommodate them. This is unfortunate, but there is a way that the language attempts to +/// alleviate the extra friction that this API choice incurs: the [`Unpin`] trait. +/// +/// The vast majority of Rust types have no reason to ever care about being pinned. These +/// types implement the [`Unpin`] trait, which entirely opts all values of that type out of +/// pinning-related guarantees. For values of these types, pinning a value by pointing to it with a +/// [`Pin`] will have no actual effect. +/// +/// The reason this distinction exists is exactly to allow APIs like [`Future::poll`] to take a +/// [`Pin`] as an argument for all types while only forcing [`Future`] types that actually +/// care about pinning guarantees pay the ergonomics cost. For the majority of [`Future`] types +/// that don't have a reason to care about being pinned and therefore implement [`Unpin`], the +/// [Pin]\<&mut Self> will act exactly like a regular `&mut Self`, allowing direct +/// access to the underlying value. Only types that *don't* implement [`Unpin`] will be restricted. +/// +/// ### Pinning a value of a type that implements [`Unpin`] +/// +/// If the type of the value you need to "pin" implements [`Unpin`], you can trivially wrap any +/// pointer to that value in a [`Pin`] by calling [`Pin::new`]. +/// +/// ``` +/// use std::pin::Pin; +/// +/// // Create a value of a type that implements `Unpin` +/// let mut unpin_future = std::future::ready(5); +/// +/// // Pin it by creating a pinning mutable reference to it (ready to be `poll`ed!) +/// let my_pinned_unpin_future: Pin<&mut _> = Pin::new(&mut unpin_future); +/// ``` +/// +/// ### Pinning a value inside a [`Box`] +/// +/// The simplest and most flexible way to pin a value that does not implement [`Unpin`] is to put +/// that value inside a [`Box`] and then turn that [`Box`] into a "pinning [`Box`]" by wrapping it +/// in a [`Pin`]. You can do both of these in a single step using [`Box::pin`]. Let's see an +/// example of using this flow to pin a [`Future`] returned from calling an `async fn`, a common +/// use case as described above. +/// +/// ``` +/// use std::pin::Pin; +/// +/// async fn add_one(x: u32) -> u32 { +/// x + 1 +/// } +/// +/// // Call the async function to get a future back +/// let fut = add_one(42); +/// +/// // Pin the future inside a pinning box +/// let pinned_fut: Pin> = Box::pin(fut); +/// ``` +/// +/// If you have a value which is already boxed, for example a [`Box`][Box], you can pin +/// that value in-place at its current memory address using [`Box::into_pin`]. +/// +/// ``` +/// use std::pin::Pin; +/// use std::future::Future; +/// +/// async fn add_one(x: u32) -> u32 { +/// x + 1 +/// } +/// +/// fn boxed_add_one(x: u32) -> Box> { +/// Box::new(add_one(x)) +/// } +/// +/// let boxed_fut = boxed_add_one(42); +/// +/// // Pin the future inside the existing box +/// let pinned_fut: Pin> = Box::into_pin(boxed_fut); +/// ``` +/// +/// There are similar pinning methods offered on the other standard library smart pointer types +/// as well, like [`Rc`] and [`Arc`]. +/// +/// ### Pinning a value on the stack using [`pin!`] +/// +/// There are some situations where it is desirable or even required (for example, in a `#[no_std]` +/// context where you don't have access to the standard library or allocation in general) to +/// pin a value which does not implement [`Unpin`] to its location on the stack. Doing so is +/// possible using the [`pin!`] macro. See its documentation for more. +/// +/// ## Layout and ABI +/// +/// [`Pin`] is guaranteed to have the same memory layout and ABI[^noalias] as `Ptr`. +/// +/// [^noalias]: There is a bit of nuance here that is still being decided about whether the +/// aliasing semantics of `Pin<&mut T>` should be different than `&mut T`, but this is true as of +/// today. +/// +/// [`pin!`]: crate::pin::pin "pin!" +/// [`Future`]: crate::future::Future "Future" +/// [`poll`]: crate::future::Future::poll "Future::poll" +/// [`Future::poll`]: crate::future::Future::poll "Future::poll" +/// [`pin` module]: self "pin module" +/// [`Rc`]: ../../std/rc/struct.Rc.html "Rc" +/// [`Arc`]: ../../std/sync/struct.Arc.html "Arc" +/// [Box]: ../../std/boxed/struct.Box.html "Box" +/// [`Box`]: ../../std/boxed/struct.Box.html "Box" +/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin "Box::pin" +/// [`Box::into_pin`]: ../../std/boxed/struct.Box.html#method.into_pin "Box::into_pin" +/// [subtle-details]: self#subtle-details-and-the-drop-guarantee "pin subtle details" +/// [`unsafe`]: ../../std/keyword.unsafe.html "keyword unsafe" +// +// Note: the `Clone` derive below causes unsoundness as it's possible to implement +// `Clone` for mutable references. +// See for more details. +#[stable(feature = "pin", since = "1.33.0")] +#[lang = "pin"] +#[fundamental] +#[repr(transparent)] +#[rustc_pub_transparent] +#[derive(Copy, Clone)] +pub struct Pin { + // FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to: + // - deter downstream users from accessing it (which would be unsound!), + // - let the `pin!` macro access it (such a macro requires using struct + // literal syntax in order to benefit from lifetime extension). + // + // However, if the `Deref` impl exposes a field with the same name as this + // field, then the two will collide, resulting in a confusing error when the + // user attempts to access the field through a `Pin`. Therefore, the + // name `__pointer` is designed to be unlikely to collide with any other + // field. Long-term, macro hygiene is expected to offer a more robust + // alternative, alongside `unsafe` fields. + #[unstable(feature = "unsafe_pin_internals", issue = "none")] + #[doc(hidden)] + pub __pointer: Ptr, +} + +// The following implementations aren't derived in order to avoid soundness +// issues. `&self.__pointer` should not be accessible to untrusted trait +// implementations. +// +// See for more details. + +#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl PartialEq> for Pin +where + Ptr::Target: PartialEq, +{ + fn eq(&self, other: &Pin) -> bool { + Ptr::Target::eq(self, other) + } + + fn ne(&self, other: &Pin) -> bool { + Ptr::Target::ne(self, other) + } +} + +#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl> Eq for Pin {} + +#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl PartialOrd> for Pin +where + Ptr::Target: PartialOrd, +{ + fn partial_cmp(&self, other: &Pin) -> Option { + Ptr::Target::partial_cmp(self, other) + } + + fn lt(&self, other: &Pin) -> bool { + Ptr::Target::lt(self, other) + } + + fn le(&self, other: &Pin) -> bool { + Ptr::Target::le(self, other) + } + + fn gt(&self, other: &Pin) -> bool { + Ptr::Target::gt(self, other) + } + + fn ge(&self, other: &Pin) -> bool { + Ptr::Target::ge(self, other) + } +} + +#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl> Ord for Pin { + fn cmp(&self, other: &Self) -> cmp::Ordering { + Ptr::Target::cmp(self, other) + } +} + +#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl> Hash for Pin { + fn hash(&self, state: &mut H) { + Ptr::Target::hash(self, state); + } +} + +impl> Pin { + /// Constructs a new `Pin` around a pointer to some data of a type that + /// implements [`Unpin`]. + /// + /// Unlike `Pin::new_unchecked`, this method is safe because the pointer + /// `Ptr` dereferences to an [`Unpin`] type, which cancels the pinning guarantees. + /// + /// # Examples + /// + /// ``` + /// use std::pin::Pin; + /// + /// let mut val: u8 = 5; + /// + /// // Since `val` doesn't care about being moved, we can safely create a "facade" `Pin` + /// // which will allow `val` to participate in `Pin`-bound apis without checking that + /// // pinning guarantees are actually upheld. + /// let mut pinned: Pin<&mut u8> = Pin::new(&mut val); + /// ``` + #[inline(always)] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] + #[stable(feature = "pin", since = "1.33.0")] + pub const fn new(pointer: Ptr) -> Pin { + // SAFETY: the value pointed to is `Unpin`, and so has no requirements + // around pinning. + unsafe { Pin::new_unchecked(pointer) } + } + + /// Unwraps this `Pin`, returning the underlying pointer. + /// + /// Doing this operation safely requires that the data pointed at by this pinning pointer + /// implements [`Unpin`] so that we can ignore the pinning invariants when unwrapping it. + /// + /// # Examples + /// + /// ``` + /// use std::pin::Pin; + /// + /// let mut val: u8 = 5; + /// let pinned: Pin<&mut u8> = Pin::new(&mut val); + /// + /// // Unwrap the pin to get the underlying mutable reference to the value. We can do + /// // this because `val` doesn't care about being moved, so the `Pin` was just + /// // a "facade" anyway. + /// let r = Pin::into_inner(pinned); + /// assert_eq!(*r, 5); + /// ``` + #[inline(always)] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] + #[stable(feature = "pin_into_inner", since = "1.39.0")] + pub const fn into_inner(pin: Pin) -> Ptr { + pin.__pointer + } +} + +impl Pin { + /// Constructs a new `Pin` around a reference to some data of a type that + /// may or may not implement [`Unpin`]. + /// + /// If `pointer` dereferences to an [`Unpin`] type, [`Pin::new`] should be used + /// instead. + /// + /// # Safety + /// + /// This constructor is unsafe because we cannot guarantee that the data + /// pointed to by `pointer` is pinned. At its core, pinning a value means making the + /// guarantee that the value's data will not be moved nor have its storage invalidated until + /// it gets dropped. For a more thorough explanation of pinning, see the [`pin` module docs]. + /// + /// If the caller that is constructing this `Pin` does not ensure that the data `Ptr` + /// points to is pinned, that is a violation of the API contract and may lead to undefined + /// behavior in later (even safe) operations. + /// + /// By using this method, you are also making a promise about the [`Deref`] and + /// [`DerefMut`] implementations of `Ptr`, if they exist. Most importantly, they + /// must not move out of their `self` arguments: `Pin::as_mut` and `Pin::as_ref` + /// will call `DerefMut::deref_mut` and `Deref::deref` *on the pointer type `Ptr`* + /// and expect these methods to uphold the pinning invariants. + /// Moreover, by calling this method you promise that the reference `Ptr` + /// dereferences to will not be moved out of again; in particular, it + /// must not be possible to obtain a `&mut Ptr::Target` and then + /// move out of that reference (using, for example [`mem::swap`]). + /// + /// For example, calling `Pin::new_unchecked` on an `&'a mut T` is unsafe because + /// while you are able to pin it for the given lifetime `'a`, you have no control + /// over whether it is kept pinned once `'a` ends, and therefore cannot uphold the + /// guarantee that a value, once pinned, remains pinned until it is dropped: + /// + /// ``` + /// use std::mem; + /// use std::pin::Pin; + /// + /// fn move_pinned_ref(mut a: T, mut b: T) { + /// unsafe { + /// let p: Pin<&mut T> = Pin::new_unchecked(&mut a); + /// // This should mean the pointee `a` can never move again. + /// } + /// mem::swap(&mut a, &mut b); // Potential UB down the road ⚠️ + /// // The address of `a` changed to `b`'s stack slot, so `a` got moved even + /// // though we have previously pinned it! We have violated the pinning API contract. + /// } + /// ``` + /// A value, once pinned, must remain pinned until it is dropped (unless its type implements + /// `Unpin`). Because `Pin<&mut T>` does not own the value, dropping the `Pin` will not drop + /// the value and will not end the pinning contract. So moving the value after dropping the + /// `Pin<&mut T>` is still a violation of the API contract. + /// + /// Similarly, calling `Pin::new_unchecked` on an `Rc` is unsafe because there could be + /// aliases to the same data that are not subject to the pinning restrictions: + /// ``` + /// use std::rc::Rc; + /// use std::pin::Pin; + /// + /// fn move_pinned_rc(mut x: Rc) { + /// // This should mean the pointee can never move again. + /// let pin = unsafe { Pin::new_unchecked(Rc::clone(&x)) }; + /// { + /// let p: Pin<&T> = pin.as_ref(); + /// // ... + /// } + /// drop(pin); + /// + /// let content = Rc::get_mut(&mut x).unwrap(); // Potential UB down the road ⚠️ + /// // Now, if `x` was the only reference, we have a mutable reference to + /// // data that we pinned above, which we could use to move it as we have + /// // seen in the previous example. We have violated the pinning API contract. + /// } + /// ``` + /// + /// ## Pinning of closure captures + /// + /// Particular care is required when using `Pin::new_unchecked` in a closure: + /// `Pin::new_unchecked(&mut var)` where `var` is a by-value (moved) closure capture + /// implicitly makes the promise that the closure itself is pinned, and that *all* uses + /// of this closure capture respect that pinning. + /// ``` + /// use std::pin::Pin; + /// use std::task::Context; + /// use std::future::Future; + /// + /// fn move_pinned_closure(mut x: impl Future, cx: &mut Context<'_>) { + /// // Create a closure that moves `x`, and then internally uses it in a pinned way. + /// let mut closure = move || unsafe { + /// let _ignore = Pin::new_unchecked(&mut x).poll(cx); + /// }; + /// // Call the closure, so the future can assume it has been pinned. + /// closure(); + /// // Move the closure somewhere else. This also moves `x`! + /// let mut moved = closure; + /// // Calling it again means we polled the future from two different locations, + /// // violating the pinning API contract. + /// moved(); // Potential UB ⚠️ + /// } + /// ``` + /// When passing a closure to another API, it might be moving the closure any time, so + /// `Pin::new_unchecked` on closure captures may only be used if the API explicitly documents + /// that the closure is pinned. + /// + /// The better alternative is to avoid all that trouble and do the pinning in the outer function + /// instead (here using the [`pin!`][crate::pin::pin] macro): + /// ``` + /// use std::pin::pin; + /// use std::task::Context; + /// use std::future::Future; + /// + /// fn move_pinned_closure(mut x: impl Future, cx: &mut Context<'_>) { + /// let mut x = pin!(x); + /// // Create a closure that captures `x: Pin<&mut _>`, which is safe to move. + /// let mut closure = move || { + /// let _ignore = x.as_mut().poll(cx); + /// }; + /// // Call the closure, so the future can assume it has been pinned. + /// closure(); + /// // Move the closure somewhere else. + /// let mut moved = closure; + /// // Calling it again here is fine (except that we might be polling a future that already + /// // returned `Poll::Ready`, but that is a separate problem). + /// moved(); + /// } + /// ``` + /// + /// [`mem::swap`]: crate::mem::swap + /// [`pin` module docs]: self + #[lang = "new_unchecked"] + #[inline(always)] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] + #[stable(feature = "pin", since = "1.33.0")] + pub const unsafe fn new_unchecked(pointer: Ptr) -> Pin { + Pin { __pointer: pointer } + } + + /// Gets a shared reference to the pinned value this [`Pin`] points to. + /// + /// This is a generic method to go from `&Pin>` to `Pin<&T>`. + /// It is safe because, as part of the contract of `Pin::new_unchecked`, + /// the pointee cannot move after `Pin>` got created. + /// "Malicious" implementations of `Pointer::Deref` are likewise + /// ruled out by the contract of `Pin::new_unchecked`. + #[stable(feature = "pin", since = "1.33.0")] + #[inline(always)] + pub fn as_ref(&self) -> Pin<&Ptr::Target> { + // SAFETY: see documentation on this function + unsafe { Pin::new_unchecked(&*self.__pointer) } + } +} + +// These methods being in a `Ptr: DerefMut` impl block concerns semver stability. +// Currently, calling e.g. `.set()` on a `Pin<&T>` sees that `Ptr: DerefMut` +// doesn't hold, and goes to check for a `.set()` method on `T`. But, if the +// `where Ptr: DerefMut` bound is moved to the method, rustc sees the impl block +// as a valid candidate, and doesn't go on to check other candidates when it +// sees that the bound on the method. +impl Pin { + /// Gets a mutable reference to the pinned value this `Pin` points to. + /// + /// This is a generic method to go from `&mut Pin>` to `Pin<&mut T>`. + /// It is safe because, as part of the contract of `Pin::new_unchecked`, + /// the pointee cannot move after `Pin>` got created. + /// "Malicious" implementations of `Pointer::DerefMut` are likewise + /// ruled out by the contract of `Pin::new_unchecked`. + /// + /// This method is useful when doing multiple calls to functions that consume the + /// pinning pointer. + /// + /// # Example + /// + /// ``` + /// use std::pin::Pin; + /// + /// # struct Type {} + /// impl Type { + /// fn method(self: Pin<&mut Self>) { + /// // do something + /// } + /// + /// fn call_method_twice(mut self: Pin<&mut Self>) { + /// // `method` consumes `self`, so reborrow the `Pin<&mut Self>` via `as_mut`. + /// self.as_mut().method(); + /// self.as_mut().method(); + /// } + /// } + /// ``` + #[stable(feature = "pin", since = "1.33.0")] + #[inline(always)] + pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> { + // SAFETY: see documentation on this function + unsafe { Pin::new_unchecked(&mut *self.__pointer) } + } + + /// Gets `Pin<&mut T>` to the underlying pinned value from this nested `Pin`-pointer. + /// + /// This is a generic method to go from `Pin<&mut Pin>>` to `Pin<&mut T>`. It is + /// safe because the existence of a `Pin>` ensures that the pointee, `T`, cannot + /// move in the future, and this method does not enable the pointee to move. "Malicious" + /// implementations of `Ptr::DerefMut` are likewise ruled out by the contract of + /// `Pin::new_unchecked`. + #[stable(feature = "pin_deref_mut", since = "1.84.0")] + #[must_use = "`self` will be dropped if the result is not used"] + #[inline(always)] + pub fn as_deref_mut(self: Pin<&mut Pin>) -> Pin<&mut Ptr::Target> { + // SAFETY: What we're asserting here is that going from + // + // Pin<&mut Pin> + // + // to + // + // Pin<&mut Ptr::Target> + // + // is safe. + // + // We need to ensure that two things hold for that to be the case: + // + // 1) Once we give out a `Pin<&mut Ptr::Target>`, a `&mut Ptr::Target` will not be given out. + // 2) By giving out a `Pin<&mut Ptr::Target>`, we do not risk violating + // `Pin<&mut Pin>` + // + // The existence of `Pin` is sufficient to guarantee #1: since we already have a + // `Pin`, it must already uphold the pinning guarantees, which must mean that + // `Pin<&mut Ptr::Target>` does as well, since `Pin::as_mut` is safe. We do not have to rely + // on the fact that `Ptr` is _also_ pinned. + // + // For #2, we need to ensure that code given a `Pin<&mut Ptr::Target>` cannot cause the + // `Pin` to move? That is not possible, since `Pin<&mut Ptr::Target>` no longer retains + // any access to the `Ptr` itself, much less the `Pin`. + unsafe { self.get_unchecked_mut() }.as_mut() + } + + /// Assigns a new value to the memory location pointed to by the `Pin`. + /// + /// This overwrites pinned data, but that is okay: the original pinned value's destructor gets + /// run before being overwritten and the new value is also a valid value of the same type, so + /// no pinning invariant is violated. See [the `pin` module documentation][subtle-details] + /// for more information on how this upholds the pinning invariants. + /// + /// # Example + /// + /// ``` + /// use std::pin::Pin; + /// + /// let mut val: u8 = 5; + /// let mut pinned: Pin<&mut u8> = Pin::new(&mut val); + /// println!("{}", pinned); // 5 + /// pinned.set(10); + /// println!("{}", pinned); // 10 + /// ``` + /// + /// [subtle-details]: self#subtle-details-and-the-drop-guarantee + #[stable(feature = "pin", since = "1.33.0")] + #[inline(always)] + pub fn set(&mut self, value: Ptr::Target) + where + Ptr::Target: Sized, + { + *(self.__pointer) = value; + } +} + +impl Pin { + /// Unwraps this `Pin`, returning the underlying `Ptr`. + /// + /// # Safety + /// + /// This function is unsafe. You must guarantee that you will continue to + /// treat the pointer `Ptr` as pinned after you call this function, so that + /// the invariants on the `Pin` type can be upheld. If the code using the + /// resulting `Ptr` does not continue to maintain the pinning invariants that + /// is a violation of the API contract and may lead to undefined behavior in + /// later (safe) operations. + /// + /// Note that you must be able to guarantee that the data pointed to by `Ptr` + /// will be treated as pinned all the way until its `drop` handler is complete! + /// + /// *For more information, see the [`pin` module docs][self]* + /// + /// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used + /// instead. + #[inline(always)] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] + #[stable(feature = "pin_into_inner", since = "1.39.0")] + pub const unsafe fn into_inner_unchecked(pin: Pin) -> Ptr { + pin.__pointer + } +} + +impl<'a, T: ?Sized> Pin<&'a T> { + /// Constructs a new pin by mapping the interior value. + /// + /// For example, if you wanted to get a `Pin` of a field of something, + /// you could use this to get access to that field in one line of code. + /// However, there are several gotchas with these "pinning projections"; + /// see the [`pin` module] documentation for further details on that topic. + /// + /// # Safety + /// + /// This function is unsafe. You must guarantee that the data you return + /// will not move so long as the argument value does not move (for example, + /// because it is one of the fields of that value), and also that you do + /// not move out of the argument you receive to the interior function. + /// + /// [`pin` module]: self#projections-and-structural-pinning + #[stable(feature = "pin", since = "1.33.0")] + pub unsafe fn map_unchecked(self, func: F) -> Pin<&'a U> + where + U: ?Sized, + F: FnOnce(&T) -> &U, + { + let pointer = &*self.__pointer; + let new_pointer = func(pointer); + + // SAFETY: the safety contract for `new_unchecked` must be + // upheld by the caller. + unsafe { Pin::new_unchecked(new_pointer) } + } + + /// Gets a shared reference out of a pin. + /// + /// This is safe because it is not possible to move out of a shared reference. + /// It may seem like there is an issue here with interior mutability: in fact, + /// it *is* possible to move a `T` out of a `&RefCell`. However, this is + /// not a problem as long as there does not also exist a `Pin<&T>` pointing + /// to the inner `T` inside the `RefCell`, and `RefCell` does not let you get a + /// `Pin<&T>` pointer to its contents. See the discussion on ["pinning projections"] + /// for further details. + /// + /// Note: `Pin` also implements `Deref` to the target, which can be used + /// to access the inner value. However, `Deref` only provides a reference + /// that lives for as long as the borrow of the `Pin`, not the lifetime of + /// the reference contained in the `Pin`. This method allows turning the `Pin` into a reference + /// with the same lifetime as the reference it wraps. + /// + /// ["pinning projections"]: self#projections-and-structural-pinning + #[inline(always)] + #[must_use] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] + #[stable(feature = "pin", since = "1.33.0")] + pub const fn get_ref(self) -> &'a T { + self.__pointer + } +} + +impl<'a, T: ?Sized> Pin<&'a mut T> { + /// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime. + #[inline(always)] + #[must_use = "`self` will be dropped if the result is not used"] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] + #[stable(feature = "pin", since = "1.33.0")] + pub const fn into_ref(self) -> Pin<&'a T> { + Pin { __pointer: self.__pointer } + } + + /// Gets a mutable reference to the data inside of this `Pin`. + /// + /// This requires that the data inside this `Pin` is `Unpin`. + /// + /// Note: `Pin` also implements `DerefMut` to the data, which can be used + /// to access the inner value. However, `DerefMut` only provides a reference + /// that lives for as long as the borrow of the `Pin`, not the lifetime of + /// the `Pin` itself. This method allows turning the `Pin` into a reference + /// with the same lifetime as the original `Pin`. + #[inline(always)] + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "pin", since = "1.33.0")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] + pub const fn get_mut(self) -> &'a mut T + where + T: Unpin, + { + self.__pointer + } + + /// Gets a mutable reference to the data inside of this `Pin`. + /// + /// # Safety + /// + /// This function is unsafe. You must guarantee that you will never move + /// the data out of the mutable reference you receive when you call this + /// function, so that the invariants on the `Pin` type can be upheld. + /// + /// If the underlying data is `Unpin`, `Pin::get_mut` should be used + /// instead. + #[inline(always)] + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "pin", since = "1.33.0")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] + pub const unsafe fn get_unchecked_mut(self) -> &'a mut T { + self.__pointer + } + + /// Constructs a new pin by mapping the interior value. + /// + /// For example, if you wanted to get a `Pin` of a field of something, + /// you could use this to get access to that field in one line of code. + /// However, there are several gotchas with these "pinning projections"; + /// see the [`pin` module] documentation for further details on that topic. + /// + /// # Safety + /// + /// This function is unsafe. You must guarantee that the data you return + /// will not move so long as the argument value does not move (for example, + /// because it is one of the fields of that value), and also that you do + /// not move out of the argument you receive to the interior function. + /// + /// [`pin` module]: self#projections-and-structural-pinning + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "pin", since = "1.33.0")] + pub unsafe fn map_unchecked_mut(self, func: F) -> Pin<&'a mut U> + where + U: ?Sized, + F: FnOnce(&mut T) -> &mut U, + { + // SAFETY: the caller is responsible for not moving the + // value out of this reference. + let pointer = unsafe { Pin::get_unchecked_mut(self) }; + let new_pointer = func(pointer); + // SAFETY: as the value of `this` is guaranteed to not have + // been moved out, this call to `new_unchecked` is safe. + unsafe { Pin::new_unchecked(new_pointer) } + } +} + +impl Pin<&'static T> { + /// Gets a pinning reference from a `&'static` reference. + /// + /// This is safe because `T` is borrowed immutably for the `'static` lifetime, which + /// never ends. + #[stable(feature = "pin_static_ref", since = "1.61.0")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] + pub const fn static_ref(r: &'static T) -> Pin<&'static T> { + // SAFETY: The 'static borrow guarantees the data will not be + // moved/invalidated until it gets dropped (which is never). + unsafe { Pin::new_unchecked(r) } + } +} + +impl Pin<&'static mut T> { + /// Gets a pinning mutable reference from a static mutable reference. + /// + /// This is safe because `T` is borrowed for the `'static` lifetime, which + /// never ends. + #[stable(feature = "pin_static_ref", since = "1.61.0")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] + pub const fn static_mut(r: &'static mut T) -> Pin<&'static mut T> { + // SAFETY: The 'static borrow guarantees the data will not be + // moved/invalidated until it gets dropped (which is never). + unsafe { Pin::new_unchecked(r) } + } +} + +#[stable(feature = "pin", since = "1.33.0")] +impl Deref for Pin { + type Target = Ptr::Target; + fn deref(&self) -> &Ptr::Target { + Pin::get_ref(Pin::as_ref(self)) + } +} + +#[stable(feature = "pin", since = "1.33.0")] +impl> DerefMut for Pin { + fn deref_mut(&mut self) -> &mut Ptr::Target { + Pin::get_mut(Pin::as_mut(self)) + } +} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for Pin {} + +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +impl LegacyReceiver for Pin {} + +#[stable(feature = "pin", since = "1.33.0")] +impl fmt::Debug for Pin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.__pointer, f) + } +} + +#[stable(feature = "pin", since = "1.33.0")] +impl fmt::Display for Pin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.__pointer, f) + } +} + +#[stable(feature = "pin", since = "1.33.0")] +impl fmt::Pointer for Pin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&self.__pointer, f) + } +} + +// Note: this means that any impl of `CoerceUnsized` that allows coercing from +// a type that impls `Deref` to a type that impls +// `Deref` is unsound. Any such impl would probably be unsound +// for other reasons, though, so we just need to take care not to allow such +// impls to land in std. +#[stable(feature = "pin", since = "1.33.0")] +impl CoerceUnsized> for Pin +where + Ptr: CoerceUnsized + PinCoerceUnsized, + U: PinCoerceUnsized, +{ +} + +#[stable(feature = "pin", since = "1.33.0")] +impl DispatchFromDyn> for Pin +where + Ptr: DispatchFromDyn + PinCoerceUnsized, + U: PinCoerceUnsized, +{ +} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +/// Trait that indicates that this is a pointer or a wrapper for one, where +/// unsizing can be performed on the pointee when it is pinned. +/// +/// # Safety +/// +/// If this type implements `Deref`, then the concrete type returned by `deref` +/// and `deref_mut` must not change without a modification. The following +/// operations are not considered modifications: +/// +/// * Moving the pointer. +/// * Performing unsizing coercions on the pointer. +/// * Performing dynamic dispatch with the pointer. +/// * Calling `deref` or `deref_mut` on the pointer. +/// +/// The concrete type of a trait object is the type that the vtable corresponds +/// to. The concrete type of a slice is an array of the same element type and +/// the length specified in the metadata. The concrete type of a sized type +/// is the type itself. +pub unsafe trait PinCoerceUnsized {} + +#[stable(feature = "pin", since = "1.33.0")] +unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a T {} + +#[stable(feature = "pin", since = "1.33.0")] +unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a mut T {} + +#[stable(feature = "pin", since = "1.33.0")] +unsafe impl PinCoerceUnsized for Pin {} + +#[stable(feature = "pin", since = "1.33.0")] +unsafe impl PinCoerceUnsized for *const T {} + +#[stable(feature = "pin", since = "1.33.0")] +unsafe impl PinCoerceUnsized for *mut T {} + +/// Constructs a [Pin]<[&mut] T>, by pinning a `value: T` locally. +/// +/// Unlike [`Box::pin`], this does not create a new heap allocation. As explained +/// below, the element might still end up on the heap however. +/// +/// The local pinning performed by this macro is usually dubbed "stack"-pinning. +/// Outside of `async` contexts locals do indeed get stored on the stack. In +/// `async` functions or blocks however, any locals crossing an `.await` point +/// are part of the state captured by the `Future`, and will use the storage of +/// those. That storage can either be on the heap or on the stack. Therefore, +/// local pinning is a more accurate term. +/// +/// If the type of the given value does not implement [`Unpin`], then this macro +/// pins the value in memory in a way that prevents moves. On the other hand, +/// if the type does implement [`Unpin`], [Pin]<[&mut] T> behaves +/// like [&mut] T, and operations such as +/// [`mem::replace()`][crate::mem::replace] or [`mem::take()`](crate::mem::take) +/// will allow moves of the value. +/// See [the `Unpin` section of the `pin` module][self#unpin] for details. +/// +/// ## Examples +/// +/// ### Basic usage +/// +/// ```rust +/// # use core::marker::PhantomPinned as Foo; +/// use core::pin::{pin, Pin}; +/// +/// fn stuff(foo: Pin<&mut Foo>) { +/// // … +/// # let _ = foo; +/// } +/// +/// let pinned_foo = pin!(Foo { /* … */ }); +/// stuff(pinned_foo); +/// // or, directly: +/// stuff(pin!(Foo { /* … */ })); +/// ``` +/// +/// ### Manually polling a `Future` (without `Unpin` bounds) +/// +/// ```rust +/// use std::{ +/// future::Future, +/// pin::pin, +/// task::{Context, Poll}, +/// thread, +/// }; +/// # use std::{sync::Arc, task::Wake, thread::Thread}; +/// +/// # /// A waker that wakes up the current thread when called. +/// # struct ThreadWaker(Thread); +/// # +/// # impl Wake for ThreadWaker { +/// # fn wake(self: Arc) { +/// # self.0.unpark(); +/// # } +/// # } +/// # +/// /// Runs a future to completion. +/// fn block_on(fut: Fut) -> Fut::Output { +/// let waker_that_unparks_thread = // … +/// # Arc::new(ThreadWaker(thread::current())).into(); +/// let mut cx = Context::from_waker(&waker_that_unparks_thread); +/// // Pin the future so it can be polled. +/// let mut pinned_fut = pin!(fut); +/// loop { +/// match pinned_fut.as_mut().poll(&mut cx) { +/// Poll::Pending => thread::park(), +/// Poll::Ready(res) => return res, +/// } +/// } +/// } +/// # +/// # assert_eq!(42, block_on(async { 42 })); +/// ``` +/// +/// ### With `Coroutine`s +/// +/// ```rust +/// #![feature(coroutines)] +/// #![feature(coroutine_trait)] +/// use core::{ +/// ops::{Coroutine, CoroutineState}, +/// pin::pin, +/// }; +/// +/// fn coroutine_fn() -> impl Coroutine /* not Unpin */ { +/// // Allow coroutine to be self-referential (not `Unpin`) +/// // vvvvvv so that locals can cross yield points. +/// #[coroutine] static || { +/// let foo = String::from("foo"); +/// let foo_ref = &foo; // ------+ +/// yield 0; // | <- crosses yield point! +/// println!("{foo_ref}"); // <--+ +/// yield foo.len(); +/// } +/// } +/// +/// fn main() { +/// let mut coroutine = pin!(coroutine_fn()); +/// match coroutine.as_mut().resume(()) { +/// CoroutineState::Yielded(0) => {}, +/// _ => unreachable!(), +/// } +/// match coroutine.as_mut().resume(()) { +/// CoroutineState::Yielded(3) => {}, +/// _ => unreachable!(), +/// } +/// match coroutine.resume(()) { +/// CoroutineState::Yielded(_) => unreachable!(), +/// CoroutineState::Complete(()) => {}, +/// } +/// } +/// ``` +/// +/// ## Remarks +/// +/// Precisely because a value is pinned to local storage, the resulting [Pin]<[&mut] T> +/// reference ends up borrowing a local tied to that block: it can't escape it. +/// +/// The following, for instance, fails to compile: +/// +/// ```rust,compile_fail +/// use core::pin::{pin, Pin}; +/// # use core::{marker::PhantomPinned as Foo, mem::drop as stuff}; +/// +/// let x: Pin<&mut Foo> = { +/// let x: Pin<&mut Foo> = pin!(Foo { /* … */ }); +/// x +/// }; // <- Foo is dropped +/// stuff(x); // Error: use of dropped value +/// ``` +/// +///

Error message +/// +/// ```console +/// error[E0716]: temporary value dropped while borrowed +/// --> src/main.rs:9:28 +/// | +/// 8 | let x: Pin<&mut Foo> = { +/// | - borrow later stored here +/// 9 | let x: Pin<&mut Foo> = pin!(Foo { /* … */ }); +/// | ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use +/// 10 | x +/// 11 | }; // <- Foo is dropped +/// | - temporary value is freed at the end of this statement +/// | +/// = note: consider using a `let` binding to create a longer lived value +/// ``` +/// +///
+/// +/// This makes [`pin!`] **unsuitable to pin values when intending to _return_ them**. Instead, the +/// value is expected to be passed around _unpinned_ until the point where it is to be consumed, +/// where it is then useful and even sensible to pin the value locally using [`pin!`]. +/// +/// If you really need to return a pinned value, consider using [`Box::pin`] instead. +/// +/// On the other hand, local pinning using [`pin!`] is likely to be cheaper than +/// pinning into a fresh heap allocation using [`Box::pin`]. Moreover, by virtue of not +/// requiring an allocator, [`pin!`] is the main non-`unsafe` `#![no_std]`-compatible [`Pin`] +/// constructor. +/// +/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin +#[stable(feature = "pin_macro", since = "1.68.0")] +#[rustc_macro_transparency = "semitransparent"] +#[allow_internal_unstable(unsafe_pin_internals)] +pub macro pin($value:expr $(,)?) { + // This is `Pin::new_unchecked(&mut { $value })`, so, for starters, let's + // review such a hypothetical macro (that any user-code could define): + // + // ```rust + // macro_rules! pin {( $value:expr ) => ( + // match &mut { $value } { at_value => unsafe { // Do not wrap `$value` in an `unsafe` block. + // $crate::pin::Pin::<&mut _>::new_unchecked(at_value) + // }} + // )} + // ``` + // + // Safety: + // - `type P = &mut _`. There are thus no pathological `Deref{,Mut}` impls + // that would break `Pin`'s invariants. + // - `{ $value }` is braced, making it a _block expression_, thus **moving** + // the given `$value`, and making it _become an **anonymous** temporary_. + // By virtue of being anonymous, it can no longer be accessed, thus + // preventing any attempts to `mem::replace` it or `mem::forget` it, _etc._ + // + // This gives us a `pin!` definition that is sound, and which works, but only + // in certain scenarios: + // - If the `pin!(value)` expression is _directly_ fed to a function call: + // `let poll = pin!(fut).poll(cx);` + // - If the `pin!(value)` expression is part of a scrutinee: + // ```rust + // match pin!(fut) { pinned_fut => { + // pinned_fut.as_mut().poll(...); + // pinned_fut.as_mut().poll(...); + // }} // <- `fut` is dropped here. + // ``` + // Alas, it doesn't work for the more straight-forward use-case: `let` bindings. + // ```rust + // let pinned_fut = pin!(fut); // <- temporary value is freed at the end of this statement + // pinned_fut.poll(...) // error[E0716]: temporary value dropped while borrowed + // // note: consider using a `let` binding to create a longer lived value + // ``` + // - Issues such as this one are the ones motivating https://github.com/rust-lang/rfcs/pull/66 + // + // This makes such a macro incredibly unergonomic in practice, and the reason most macros + // out there had to take the path of being a statement/binding macro (_e.g._, `pin!(future);`) + // instead of featuring the more intuitive ergonomics of an expression macro. + // + // Luckily, there is a way to avoid the problem. Indeed, the problem stems from the fact that a + // temporary is dropped at the end of its enclosing statement when it is part of the parameters + // given to function call, which has precisely been the case with our `Pin::new_unchecked()`! + // For instance, + // ```rust + // let p = Pin::new_unchecked(&mut ); + // ``` + // becomes: + // ```rust + // let p = { let mut anon = ; &mut anon }; + // ``` + // + // However, when using a literal braced struct to construct the value, references to temporaries + // can then be taken. This makes Rust change the lifespan of such temporaries so that they are, + // instead, dropped _at the end of the enscoping block_. + // For instance, + // ```rust + // let p = Pin { __pointer: &mut }; + // ``` + // becomes: + // ```rust + // let mut anon = ; + // let p = Pin { __pointer: &mut anon }; + // ``` + // which is *exactly* what we want. + // + // See https://doc.rust-lang.org/1.58.1/reference/destructors.html#temporary-lifetime-extension + // for more info. + $crate::pin::Pin::<&mut _> { __pointer: &mut { $value } } +} diff --git a/CoqOfRust/core/prelude/common.rs b/CoqOfRust/core/prelude/common.rs new file mode 100644 index 000000000..e38ef1e14 --- /dev/null +++ b/CoqOfRust/core/prelude/common.rs @@ -0,0 +1,108 @@ +//! Items common to the prelude of all editions. +//! +//! See the [module-level documentation](super) for more. + +// No formatting: this file is nothing but re-exports, and their order is worth preserving. +#![cfg_attr(rustfmt, rustfmt::skip)] + +// Re-exported core operators +#[stable(feature = "core_prelude", since = "1.4.0")] +#[doc(no_inline)] +pub use crate::marker::{Copy, Send, Sized, Sync, Unpin}; +#[stable(feature = "core_prelude", since = "1.4.0")] +#[doc(no_inline)] +pub use crate::ops::{Drop, Fn, FnMut, FnOnce}; + +// Re-exported functions +#[stable(feature = "core_prelude", since = "1.4.0")] +#[doc(no_inline)] +pub use crate::mem::drop; +#[stable(feature = "size_of_prelude", since = "1.80.0")] +#[doc(no_inline)] +pub use crate::mem::{align_of, align_of_val, size_of, size_of_val}; + +// Re-exported types and traits +#[stable(feature = "core_prelude", since = "1.4.0")] +#[doc(no_inline)] +pub use crate::clone::Clone; +#[stable(feature = "core_prelude", since = "1.4.0")] +#[doc(no_inline)] +pub use crate::cmp::{Eq, Ord, PartialEq, PartialOrd}; +#[stable(feature = "core_prelude", since = "1.4.0")] +#[doc(no_inline)] +pub use crate::convert::{AsMut, AsRef, From, Into}; +#[stable(feature = "core_prelude", since = "1.4.0")] +#[doc(no_inline)] +pub use crate::default::Default; +#[stable(feature = "core_prelude", since = "1.4.0")] +#[doc(no_inline)] +pub use crate::iter::{DoubleEndedIterator, ExactSizeIterator, Extend, IntoIterator, Iterator}; +#[stable(feature = "core_prelude", since = "1.4.0")] +#[doc(no_inline)] +pub use crate::option::Option::{self, None, Some}; +#[stable(feature = "core_prelude", since = "1.4.0")] +#[doc(no_inline)] +pub use crate::result::Result::{self, Err, Ok}; + +// Re-exported built-in macros +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(no_inline)] +pub use crate::fmt::macros::Debug; +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(no_inline)] +pub use crate::hash::macros::Hash; + +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow(deprecated)] +#[doc(no_inline)] +pub use crate::{ + assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args, + format_args_nl, include, include_bytes, include_str, line, log_syntax, module_path, option_env, + stringify, trace_macros, +}; + +#[unstable( + feature = "concat_bytes", + issue = "87555", + reason = "`concat_bytes` is not stable enough for use and is subject to change" +)] +#[doc(no_inline)] +pub use crate::concat_bytes; + +// Do not `doc(no_inline)` so that they become doc items on their own +// (no public module for them to be re-exported from). +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +pub use crate::macros::builtin::{ + alloc_error_handler, bench, derive, global_allocator, test, test_case, +}; + +#[unstable(feature = "derive_const", issue = "none")] +pub use crate::macros::builtin::derive_const; + +#[unstable( + feature = "cfg_accessible", + issue = "64797", + reason = "`cfg_accessible` is not fully implemented" +)] +pub use crate::macros::builtin::cfg_accessible; + +#[unstable( + feature = "cfg_eval", + issue = "82679", + reason = "`cfg_eval` is a recently implemented feature" +)] +pub use crate::macros::builtin::cfg_eval; + +#[unstable( + feature = "type_ascription", + issue = "23416", + reason = "placeholder syntax for type ascription" +)] +pub use crate::macros::builtin::type_ascribe; + +#[unstable( + feature = "deref_patterns", + issue = "87121", + reason = "placeholder syntax for deref patterns" +)] +pub use crate::macros::builtin::deref; diff --git a/CoqOfRust/core/prelude/mod.rs b/CoqOfRust/core/prelude/mod.rs new file mode 100644 index 000000000..496b78439 --- /dev/null +++ b/CoqOfRust/core/prelude/mod.rs @@ -0,0 +1,90 @@ +//! The core prelude +//! +//! This module is intended for users of core which do not link to std as well. +//! This module is imported by default when `#![no_std]` is used in the same +//! manner as the standard library's prelude. + +// No formatting: this file is nothing but re-exports, and their order is worth preserving. +#![cfg_attr(rustfmt, rustfmt::skip)] + +#![stable(feature = "core_prelude", since = "1.4.0")] + +mod common; + +/// The first version of the prelude of The Rust Standard Library. +/// +/// See the [module-level documentation](self) for more. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod v1 { + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::common::*; + + // Do not `doc(inline)` these `doc(hidden)` items. + #[unstable( + feature = "rustc_encodable_decodable", + issue = "none", + soft, + reason = "derive macro for `rustc-serialize`; should not be used in new code" + )] + #[allow(deprecated)] + pub use crate::macros::builtin::{RustcDecodable, RustcEncodable}; +} + +/// The 2015 version of the core prelude. +/// +/// See the [module-level documentation](self) for more. +#[stable(feature = "prelude_2015", since = "1.55.0")] +pub mod rust_2015 { + #[stable(feature = "prelude_2015", since = "1.55.0")] + #[doc(no_inline)] + pub use super::v1::*; +} + +/// The 2018 version of the core prelude. +/// +/// See the [module-level documentation](self) for more. +#[stable(feature = "prelude_2018", since = "1.55.0")] +pub mod rust_2018 { + #[stable(feature = "prelude_2018", since = "1.55.0")] + #[doc(no_inline)] + pub use super::v1::*; +} + +/// The 2021 version of the core prelude. +/// +/// See the [module-level documentation](self) for more. +#[stable(feature = "prelude_2021", since = "1.55.0")] +pub mod rust_2021 { + #[stable(feature = "prelude_2021", since = "1.55.0")] + #[doc(no_inline)] + pub use super::v1::*; + + #[stable(feature = "prelude_2021", since = "1.55.0")] + #[doc(no_inline)] + pub use crate::iter::FromIterator; + + #[stable(feature = "prelude_2021", since = "1.55.0")] + #[doc(no_inline)] + pub use crate::convert::{TryFrom, TryInto}; +} + +/// The 2024 version of the core prelude. +/// +/// See the [module-level documentation](self) for more. +#[unstable(feature = "prelude_2024", issue = "121042")] +pub mod rust_2024 { + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::common::*; + + #[stable(feature = "prelude_2021", since = "1.55.0")] + #[doc(no_inline)] + pub use crate::iter::FromIterator; + + #[stable(feature = "prelude_2021", since = "1.55.0")] + #[doc(no_inline)] + pub use crate::convert::{TryFrom, TryInto}; + + #[unstable(feature = "prelude_2024", issue = "121042")] + #[doc(no_inline)] + pub use crate::future::{Future, IntoFuture}; +} diff --git a/CoqOfRust/core/primitive.rs b/CoqOfRust/core/primitive.rs new file mode 100644 index 000000000..b5f97b898 --- /dev/null +++ b/CoqOfRust/core/primitive.rs @@ -0,0 +1,73 @@ +//! This module reexports the primitive types to allow usage that is not +//! possibly shadowed by other declared types. +//! +//! This is normally only useful in macro generated code. +//! +//! An example of this is when generating a new struct and an impl for it: +//! +//! ```rust,compile_fail +//! pub struct bool; +//! +//! impl QueryId for bool { +//! const SOME_PROPERTY: bool = true; +//! } +//! +//! # trait QueryId { const SOME_PROPERTY: ::core::primitive::bool; } +//! ``` +//! +//! Note that the `SOME_PROPERTY` associated constant would not compile, as its +//! type `bool` refers to the struct, rather than to the primitive bool type. +//! +//! A correct implementation could look like: +//! +//! ```rust +//! # #[allow(non_camel_case_types)] +//! pub struct bool; +//! +//! impl QueryId for bool { +//! const SOME_PROPERTY: ::core::primitive::bool = true; +//! } +//! +//! # trait QueryId { const SOME_PROPERTY: ::core::primitive::bool; } +//! ``` +//! +//! We also used `::core` instead of `core`, because `core` can be +//! shadowed, too. Paths, starting with `::`, are searched in +//! the [extern prelude] since Edition 2018. +//! +//! [extern prelude]: https://doc.rust-lang.org/nightly/reference/names/preludes.html#extern-prelude + +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use bool; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use char; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use f32; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use f64; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use i8; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use i16; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use i32; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use i64; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use i128; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use isize; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use str; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use u8; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use u16; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use u32; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use u64; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use u128; +#[stable(feature = "core_primitive", since = "1.43.0")] +pub use usize; diff --git a/CoqOfRust/core/primitive_docs.rs b/CoqOfRust/core/primitive_docs.rs new file mode 100644 index 000000000..e105ceadf --- /dev/null +++ b/CoqOfRust/core/primitive_docs.rs @@ -0,0 +1,1877 @@ +#[rustc_doc_primitive = "bool"] +#[doc(alias = "true")] +#[doc(alias = "false")] +/// The boolean type. +/// +/// The `bool` represents a value, which could only be either [`true`] or [`false`]. If you cast +/// a `bool` into an integer, [`true`] will be 1 and [`false`] will be 0. +/// +/// # Basic usage +/// +/// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc., +/// which allow us to perform boolean operations using `&`, `|` and `!`. +/// +/// [`if`] requires a `bool` value as its conditional. [`assert!`], which is an +/// important macro in testing, checks whether an expression is [`true`] and panics +/// if it isn't. +/// +/// ``` +/// let bool_val = true & false | false; +/// assert!(!bool_val); +/// ``` +/// +/// [`true`]: ../std/keyword.true.html +/// [`false`]: ../std/keyword.false.html +/// [`BitAnd`]: ops::BitAnd +/// [`BitOr`]: ops::BitOr +/// [`Not`]: ops::Not +/// [`if`]: ../std/keyword.if.html +/// +/// # Examples +/// +/// A trivial example of the usage of `bool`: +/// +/// ``` +/// let praise_the_borrow_checker = true; +/// +/// // using the `if` conditional +/// if praise_the_borrow_checker { +/// println!("oh, yeah!"); +/// } else { +/// println!("what?!!"); +/// } +/// +/// // ... or, a match pattern +/// match praise_the_borrow_checker { +/// true => println!("keep praising!"), +/// false => println!("you should praise!"), +/// } +/// ``` +/// +/// Also, since `bool` implements the [`Copy`] trait, we don't +/// have to worry about the move semantics (just like the integer and float primitives). +/// +/// Now an example of `bool` cast to integer type: +/// +/// ``` +/// assert_eq!(true as i32, 1); +/// assert_eq!(false as i32, 0); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_bool {} + +#[rustc_doc_primitive = "never"] +#[doc(alias = "!")] +// +/// The `!` type, also called "never". +/// +/// `!` represents the type of computations which never resolve to any value at all. For example, +/// the [`exit`] function `fn exit(code: i32) -> !` exits the process without ever returning, and +/// so returns `!`. +/// +/// `break`, `continue` and `return` expressions also have type `!`. For example we are allowed to +/// write: +/// +/// ``` +/// #![feature(never_type)] +/// # fn foo() -> u32 { +/// let x: ! = { +/// return 123 +/// }; +/// # } +/// ``` +/// +/// Although the `let` is pointless here, it illustrates the meaning of `!`. Since `x` is never +/// assigned a value (because `return` returns from the entire function), `x` can be given type +/// `!`. We could also replace `return 123` with a `panic!` or a never-ending `loop` and this code +/// would still be valid. +/// +/// A more realistic usage of `!` is in this code: +/// +/// ``` +/// # fn get_a_number() -> Option { None } +/// # loop { +/// let num: u32 = match get_a_number() { +/// Some(num) => num, +/// None => break, +/// }; +/// # } +/// ``` +/// +/// Both match arms must produce values of type [`u32`], but since `break` never produces a value +/// at all we know it can never produce a value which isn't a [`u32`]. This illustrates another +/// behavior of the `!` type - expressions with type `!` will coerce into any other type. +/// +/// [`u32`]: prim@u32 +/// [`exit`]: ../std/process/fn.exit.html +/// +/// # `!` and generics +/// +/// ## Infallible errors +/// +/// The main place you'll see `!` used explicitly is in generic code. Consider the [`FromStr`] +/// trait: +/// +/// ``` +/// trait FromStr: Sized { +/// type Err; +/// fn from_str(s: &str) -> Result; +/// } +/// ``` +/// +/// When implementing this trait for [`String`] we need to pick a type for [`Err`]. And since +/// converting a string into a string will never result in an error, the appropriate type is `!`. +/// (Currently the type actually used is an enum with no variants, though this is only because `!` +/// was added to Rust at a later date and it may change in the future.) With an [`Err`] type of +/// `!`, if we have to call [`String::from_str`] for some reason the result will be a +/// [`Result`] which we can unpack like this: +/// +/// ``` +/// #![feature(exhaustive_patterns)] +/// use std::str::FromStr; +/// let Ok(s) = String::from_str("hello"); +/// ``` +/// +/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns` +/// feature is present this means we can exhaustively match on [`Result`] by just taking the +/// [`Ok`] variant. This illustrates another behavior of `!` - it can be used to "delete" certain +/// enum variants from generic types like `Result`. +/// +/// ## Infinite loops +/// +/// While [`Result`] is very useful for removing errors, `!` can also be used to remove +/// successes as well. If we think of [`Result`] as "if this function returns, it has not +/// errored," we get a very intuitive idea of [`Result`] as well: if the function returns, it +/// *has* errored. +/// +/// For example, consider the case of a simple web server, which can be simplified to: +/// +/// ```ignore (hypothetical-example) +/// loop { +/// let (client, request) = get_request().expect("disconnected"); +/// let response = request.process(); +/// response.send(client); +/// } +/// ``` +/// +/// Currently, this isn't ideal, because we simply panic whenever we fail to get a new connection. +/// Instead, we'd like to keep track of this error, like this: +/// +/// ```ignore (hypothetical-example) +/// loop { +/// match get_request() { +/// Err(err) => break err, +/// Ok((client, request)) => { +/// let response = request.process(); +/// response.send(client); +/// }, +/// } +/// } +/// ``` +/// +/// Now, when the server disconnects, we exit the loop with an error instead of panicking. While it +/// might be intuitive to simply return the error, we might want to wrap it in a [`Result`] +/// instead: +/// +/// ```ignore (hypothetical-example) +/// fn server_loop() -> Result { +/// loop { +/// let (client, request) = get_request()?; +/// let response = request.process(); +/// response.send(client); +/// } +/// } +/// ``` +/// +/// Now, we can use `?` instead of `match`, and the return type makes a lot more sense: if the loop +/// ever stops, it means that an error occurred. We don't even have to wrap the loop in an `Ok` +/// because `!` coerces to `Result` automatically. +/// +/// [`String::from_str`]: str::FromStr::from_str +/// [`String`]: ../std/string/struct.String.html +/// [`FromStr`]: str::FromStr +/// +/// # `!` and traits +/// +/// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl` +/// which doesn't `panic!`. The reason is that functions returning an `impl Trait` where `!` +/// does not have an `impl` of `Trait` cannot diverge as their only possible code path. In other +/// words, they can't return `!` from every code path. As an example, this code doesn't compile: +/// +/// ```compile_fail +/// use std::ops::Add; +/// +/// fn foo() -> impl Add { +/// unimplemented!() +/// } +/// ``` +/// +/// But this code does: +/// +/// ``` +/// use std::ops::Add; +/// +/// fn foo() -> impl Add { +/// if true { +/// unimplemented!() +/// } else { +/// 0 +/// } +/// } +/// ``` +/// +/// The reason is that, in the first example, there are many possible types that `!` could coerce +/// to, because many types implement `Add`. However, in the second example, +/// the `else` branch returns a `0`, which the compiler infers from the return type to be of type +/// `u32`. Since `u32` is a concrete type, `!` can and will be coerced to it. See issue [#36375] +/// for more information on this quirk of `!`. +/// +/// [#36375]: https://github.com/rust-lang/rust/issues/36375 +/// +/// As it turns out, though, most traits can have an `impl` for `!`. Take [`Debug`] +/// for example: +/// +/// ``` +/// #![feature(never_type)] +/// # use std::fmt; +/// # trait Debug { +/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result; +/// # } +/// impl Debug for ! { +/// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { +/// *self +/// } +/// } +/// ``` +/// +/// Once again we're using `!`'s ability to coerce into any other type, in this case +/// [`fmt::Result`]. Since this method takes a `&!` as an argument we know that it can never be +/// called (because there is no value of type `!` for it to be called with). Writing `*self` +/// essentially tells the compiler "We know that this code can never be run, so just treat the +/// entire function body as having type [`fmt::Result`]". This pattern can be used a lot when +/// implementing traits for `!`. Generally, any trait which only has methods which take a `self` +/// parameter should have such an impl. +/// +/// On the other hand, one trait which would not be appropriate to implement is [`Default`]: +/// +/// ``` +/// trait Default { +/// fn default() -> Self; +/// } +/// ``` +/// +/// Since `!` has no values, it has no default value either. It's true that we could write an +/// `impl` for this which simply panics, but the same is true for any type (we could `impl +/// Default` for (eg.) [`File`] by just making [`default()`] panic.) +/// +/// [`File`]: ../std/fs/struct.File.html +/// [`Debug`]: fmt::Debug +/// [`default()`]: Default::default +/// +/// # Never type fallback +/// +/// When the compiler sees a value of type `!` in a [coercion site], it implicitly inserts a +/// coercion to allow the type checker to infer any type: +/// +/// ```rust,ignore (illustrative-and-has-placeholders) +/// // this +/// let x: u8 = panic!(); +/// +/// // is (essentially) turned by the compiler into +/// let x: u8 = absurd(panic!()); +/// +/// // where absurd is a function with the following signature +/// // (it's sound, because `!` always marks unreachable code): +/// fn absurd(_: !) -> T { ... } +// FIXME: use `core::convert::absurd` here instead, once it's merged +/// ``` +/// +/// This can lead to compilation errors if the type cannot be inferred: +/// +/// ```compile_fail +/// // this +/// { panic!() }; +/// +/// // gets turned into this +/// { absurd(panic!()) }; // error: can't infer the type of `absurd` +/// ``` +/// +/// To prevent such errors, the compiler remembers where it inserted `absurd` calls, and +/// if it can't infer the type, it uses the fallback type instead: +/// ```rust, ignore +/// type Fallback = /* An arbitrarily selected type! */; +/// { absurd::(panic!()) } +/// ``` +/// +/// This is what is known as "never type fallback". +/// +/// Historically, the fallback type was [`()`], causing confusing behavior where `!` spontaneously +/// coerced to `()`, even when it would not infer `()` without the fallback. There are plans to +/// change it in the [2024 edition] (and possibly in all editions on a later date); see +/// [Tracking Issue for making `!` fall back to `!`][fallback-ti]. +/// +/// [coercion site]: +/// [`()`]: prim@unit +/// [fallback-ti]: +/// [2024 edition]: +/// +#[unstable(feature = "never_type", issue = "35121")] +mod prim_never {} + +#[rustc_doc_primitive = "char"] +#[allow(rustdoc::invalid_rust_codeblocks)] +/// A character type. +/// +/// The `char` type represents a single character. More specifically, since +/// 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode +/// scalar value]'. +/// +/// This documentation describes a number of methods and trait implementations on the +/// `char` type. For technical reasons, there is additional, separate +/// documentation in [the `std::char` module](char/index.html) as well. +/// +/// # Validity and Layout +/// +/// A `char` is a '[Unicode scalar value]', which is any '[Unicode code point]' +/// other than a [surrogate code point]. This has a fixed numerical definition: +/// code points are in the range 0 to 0x10FFFF, inclusive. +/// Surrogate code points, used by UTF-16, are in the range 0xD800 to 0xDFFF. +/// +/// No `char` may be constructed, whether as a literal or at runtime, that is not a +/// Unicode scalar value. Violating this rule causes undefined behavior. +/// +/// ```compile_fail +/// // Each of these is a compiler error +/// ['\u{D800}', '\u{DFFF}', '\u{110000}']; +/// ``` +/// +/// ```should_panic +/// // Panics; from_u32 returns None. +/// char::from_u32(0xDE01).unwrap(); +/// ``` +/// +/// ```no_run +/// // Undefined behavior +/// let _ = unsafe { char::from_u32_unchecked(0x110000) }; +/// ``` +/// +/// Unicode scalar values are also the exact set of values that may be encoded in UTF-8. Because +/// `char` values are Unicode scalar values and functions may assume [incoming `str` values are +/// valid UTF-8](primitive.str.html#invariant), it is safe to store any `char` in a `str` or read +/// any character from a `str` as a `char`. +/// +/// The gap in valid `char` values is understood by the compiler, so in the +/// below example the two ranges are understood to cover the whole range of +/// possible `char` values and there is no error for a [non-exhaustive match]. +/// +/// ``` +/// let c: char = 'a'; +/// match c { +/// '\0' ..= '\u{D7FF}' => false, +/// '\u{E000}' ..= '\u{10FFFF}' => true, +/// }; +/// ``` +/// +/// All Unicode scalar values are valid `char` values, but not all of them represent a real +/// character. Many Unicode scalar values are not currently assigned to a character, but may be in +/// the future ("reserved"); some will never be a character ("noncharacters"); and some may be given +/// different meanings by different users ("private use"). +/// +/// `char` is guaranteed to have the same size, alignment, and function call ABI as `u32` on all +/// platforms. +/// ``` +/// use std::alloc::Layout; +/// assert_eq!(Layout::new::(), Layout::new::()); +/// ``` +/// +/// [Unicode code point]: https://www.unicode.org/glossary/#code_point +/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value +/// [non-exhaustive match]: ../book/ch06-02-match.html#matches-are-exhaustive +/// [surrogate code point]: https://www.unicode.org/glossary/#surrogate_code_point +/// +/// # Representation +/// +/// `char` is always four bytes in size. This is a different representation than +/// a given character would have as part of a [`String`]. For example: +/// +/// ``` +/// let v = vec!['h', 'e', 'l', 'l', 'o']; +/// +/// // five elements times four bytes for each element +/// assert_eq!(20, v.len() * std::mem::size_of::()); +/// +/// let s = String::from("hello"); +/// +/// // five elements times one byte per element +/// assert_eq!(5, s.len() * std::mem::size_of::()); +/// ``` +/// +/// [`String`]: ../std/string/struct.String.html +/// +/// As always, remember that a human intuition for 'character' might not map to +/// Unicode's definitions. For example, despite looking similar, the 'é' +/// character is one Unicode code point while 'é' is two Unicode code points: +/// +/// ``` +/// let mut chars = "é".chars(); +/// // U+00e9: 'latin small letter e with acute' +/// assert_eq!(Some('\u{00e9}'), chars.next()); +/// assert_eq!(None, chars.next()); +/// +/// let mut chars = "é".chars(); +/// // U+0065: 'latin small letter e' +/// assert_eq!(Some('\u{0065}'), chars.next()); +/// // U+0301: 'combining acute accent' +/// assert_eq!(Some('\u{0301}'), chars.next()); +/// assert_eq!(None, chars.next()); +/// ``` +/// +/// This means that the contents of the first string above _will_ fit into a +/// `char` while the contents of the second string _will not_. Trying to create +/// a `char` literal with the contents of the second string gives an error: +/// +/// ```text +/// error: character literal may only contain one codepoint: 'é' +/// let c = 'é'; +/// ^^^ +/// ``` +/// +/// Another implication of the 4-byte fixed size of a `char` is that +/// per-`char` processing can end up using a lot more memory: +/// +/// ``` +/// let s = String::from("love: ❤️"); +/// let v: Vec = s.chars().collect(); +/// +/// assert_eq!(12, std::mem::size_of_val(&s[..])); +/// assert_eq!(32, std::mem::size_of_val(&v[..])); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_char {} + +#[rustc_doc_primitive = "unit"] +#[doc(alias = "(")] +#[doc(alias = ")")] +#[doc(alias = "()")] +// +/// The `()` type, also called "unit". +/// +/// The `()` type has exactly one value `()`, and is used when there +/// is no other meaningful value that could be returned. `()` is most +/// commonly seen implicitly: functions without a `-> ...` implicitly +/// have return type `()`, that is, these are equivalent: +/// +/// ```rust +/// fn long() -> () {} +/// +/// fn short() {} +/// ``` +/// +/// The semicolon `;` can be used to discard the result of an +/// expression at the end of a block, making the expression (and thus +/// the block) evaluate to `()`. For example, +/// +/// ```rust +/// fn returns_i64() -> i64 { +/// 1i64 +/// } +/// fn returns_unit() { +/// 1i64; +/// } +/// +/// let is_i64 = { +/// returns_i64() +/// }; +/// let is_unit = { +/// returns_i64(); +/// }; +/// ``` +/// +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_unit {} + +// Required to make auto trait impls render. +// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls +#[doc(hidden)] +impl () {} + +#[rustc_doc_primitive = "pointer"] +#[doc(alias = "ptr")] +#[doc(alias = "*")] +#[doc(alias = "*const")] +#[doc(alias = "*mut")] +// +/// Raw, unsafe pointers, `*const T`, and `*mut T`. +/// +/// *[See also the `std::ptr` module](ptr).* +/// +/// Working with raw pointers in Rust is uncommon, typically limited to a few patterns. Raw pointers +/// can be out-of-bounds, unaligned, or [`null`]. However, when loading from or storing to a raw +/// pointer, it must be [valid] for the given access and aligned. When using a field expression, +/// tuple index expression, or array/slice index expression on a raw pointer, it follows the rules +/// of [in-bounds pointer arithmetic][`offset`]. +/// +/// Storing through a raw pointer using `*ptr = data` calls `drop` on the old value, so +/// [`write`] must be used if the type has drop glue and memory is not already +/// initialized - otherwise `drop` would be called on the uninitialized memory. +/// +/// Use the [`null`] and [`null_mut`] functions to create null pointers, and the +/// [`is_null`] method of the `*const T` and `*mut T` types to check for null. +/// The `*const T` and `*mut T` types also define the [`offset`] method, for +/// pointer math. +/// +/// # Common ways to create raw pointers +/// +/// ## 1. Coerce a reference (`&T`) or mutable reference (`&mut T`). +/// +/// ``` +/// let my_num: i32 = 10; +/// let my_num_ptr: *const i32 = &my_num; +/// let mut my_speed: i32 = 88; +/// let my_speed_ptr: *mut i32 = &mut my_speed; +/// ``` +/// +/// To get a pointer to a boxed value, dereference the box: +/// +/// ``` +/// let my_num: Box = Box::new(10); +/// let my_num_ptr: *const i32 = &*my_num; +/// let mut my_speed: Box = Box::new(88); +/// let my_speed_ptr: *mut i32 = &mut *my_speed; +/// ``` +/// +/// This does not take ownership of the original allocation +/// and requires no resource management later, +/// but you must not use the pointer after its lifetime. +/// +/// ## 2. Consume a box (`Box`). +/// +/// The [`into_raw`] function consumes a box and returns +/// the raw pointer. It doesn't destroy `T` or deallocate any memory. +/// +/// ``` +/// let my_speed: Box = Box::new(88); +/// let my_speed: *mut i32 = Box::into_raw(my_speed); +/// +/// // By taking ownership of the original `Box` though +/// // we are obligated to put it together later to be destroyed. +/// unsafe { +/// drop(Box::from_raw(my_speed)); +/// } +/// ``` +/// +/// Note that here the call to [`drop`] is for clarity - it indicates +/// that we are done with the given value and it should be destroyed. +/// +/// ## 3. Create it using `ptr::addr_of!` +/// +/// Instead of coercing a reference to a raw pointer, you can use the macros +/// [`ptr::addr_of!`] (for `*const T`) and [`ptr::addr_of_mut!`] (for `*mut T`). +/// These macros allow you to create raw pointers to fields to which you cannot +/// create a reference (without causing undefined behavior), such as an +/// unaligned field. This might be necessary if packed structs or uninitialized +/// memory is involved. +/// +/// ``` +/// #[derive(Debug, Default, Copy, Clone)] +/// #[repr(C, packed)] +/// struct S { +/// aligned: u8, +/// unaligned: u32, +/// } +/// let s = S::default(); +/// let p = std::ptr::addr_of!(s.unaligned); // not allowed with coercion +/// ``` +/// +/// ## 4. Get it from C. +/// +/// ``` +/// # mod libc { +/// # pub unsafe fn malloc(_size: usize) -> *mut core::ffi::c_void { core::ptr::NonNull::dangling().as_ptr() } +/// # pub unsafe fn free(_ptr: *mut core::ffi::c_void) {} +/// # } +/// # #[cfg(any())] +/// #[allow(unused_extern_crates)] +/// extern crate libc; +/// +/// use std::mem; +/// +/// unsafe { +/// let my_num: *mut i32 = libc::malloc(mem::size_of::()) as *mut i32; +/// if my_num.is_null() { +/// panic!("failed to allocate memory"); +/// } +/// libc::free(my_num as *mut core::ffi::c_void); +/// } +/// ``` +/// +/// Usually you wouldn't literally use `malloc` and `free` from Rust, +/// but C APIs hand out a lot of pointers generally, so are a common source +/// of raw pointers in Rust. +/// +/// [`null`]: ptr::null +/// [`null_mut`]: ptr::null_mut +/// [`is_null`]: pointer::is_null +/// [`offset`]: pointer::offset +/// [`into_raw`]: ../std/boxed/struct.Box.html#method.into_raw +/// [`write`]: ptr::write +/// [valid]: ptr#safety +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_pointer {} + +#[rustc_doc_primitive = "array"] +#[doc(alias = "[]")] +#[doc(alias = "[T;N]")] // unfortunately, rustdoc doesn't have fuzzy search for aliases +#[doc(alias = "[T; N]")] +/// A fixed-size array, denoted `[T; N]`, for the element type, `T`, and the +/// non-negative compile-time constant size, `N`. +/// +/// There are two syntactic forms for creating an array: +/// +/// * A list with each element, i.e., `[x, y, z]`. +/// * A repeat expression `[expr; N]` where `N` is how many times to repeat `expr` in the array. `expr` must either be: +/// +/// * A value of a type implementing the [`Copy`] trait +/// * A `const` value +/// +/// Note that `[expr; 0]` is allowed, and produces an empty array. +/// This will still evaluate `expr`, however, and immediately drop the resulting value, so +/// be mindful of side effects. +/// +/// Arrays of *any* size implement the following traits if the element type allows it: +/// +/// - [`Copy`] +/// - [`Clone`] +/// - [`Debug`] +/// - [`IntoIterator`] (implemented for `[T; N]`, `&[T; N]` and `&mut [T; N]`) +/// - [`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] +/// - [`Hash`] +/// - [`AsRef`], [`AsMut`] +/// - [`Borrow`], [`BorrowMut`] +/// +/// Arrays of sizes from 0 to 32 (inclusive) implement the [`Default`] trait +/// if the element type allows it. As a stopgap, trait implementations are +/// statically generated up to size 32. +/// +/// Arrays of sizes from 1 to 12 (inclusive) implement [`From`], where `Tuple` +/// is a homogeneous [prim@tuple] of appropriate length. +/// +/// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on +/// an array. Indeed, this provides most of the API for working with arrays. +/// +/// Slices have a dynamic size and do not coerce to arrays. Instead, use +/// `slice.try_into().unwrap()` or `::try_from(slice).unwrap()`. +/// +/// Array's `try_from(slice)` implementations (and the corresponding `slice.try_into()` +/// array implementations) succeed if the input slice length is the same as the result +/// array length. They optimize especially well when the optimizer can easily determine +/// the slice length, e.g. `<[u8; 4]>::try_from(&slice[4..8]).unwrap()`. Array implements +/// [TryFrom](crate::convert::TryFrom) returning: +/// +/// - `[T; N]` copies from the slice's elements +/// - `&[T; N]` references the original slice's elements +/// - `&mut [T; N]` references the original slice's elements +/// +/// You can move elements out of an array with a [slice pattern]. If you want +/// one element, see [`mem::replace`]. +/// +/// # Examples +/// +/// ``` +/// let mut array: [i32; 3] = [0; 3]; +/// +/// array[1] = 1; +/// array[2] = 2; +/// +/// assert_eq!([1, 2], &array[1..]); +/// +/// // This loop prints: 0 1 2 +/// for x in array { +/// print!("{x} "); +/// } +/// ``` +/// +/// You can also iterate over reference to the array's elements: +/// +/// ``` +/// let array: [i32; 3] = [0; 3]; +/// +/// for x in &array { } +/// ``` +/// +/// You can use `::try_from(slice)` or `slice.try_into()` to get an array from +/// a slice: +/// +/// ``` +/// let bytes: [u8; 3] = [1, 0, 2]; +/// assert_eq!(1, u16::from_le_bytes(<[u8; 2]>::try_from(&bytes[0..2]).unwrap())); +/// assert_eq!(512, u16::from_le_bytes(bytes[1..3].try_into().unwrap())); +/// ``` +/// +/// You can use a [slice pattern] to move elements out of an array: +/// +/// ``` +/// fn move_away(_: String) { /* Do interesting things. */ } +/// +/// let [john, roa] = ["John".to_string(), "Roa".to_string()]; +/// move_away(john); +/// move_away(roa); +/// ``` +/// +/// Arrays can be created from homogeneous tuples of appropriate length: +/// +/// ``` +/// let tuple: (u32, u32, u32) = (1, 2, 3); +/// let array: [u32; 3] = tuple.into(); +/// ``` +/// +/// # Editions +/// +/// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call +/// `array.into_iter()` auto-referenced into a [slice iterator](slice::iter). Right now, the old +/// behavior is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring +/// [`IntoIterator`] by value. In the future, the behavior on the 2015 and 2018 edition +/// might be made consistent to the behavior of later editions. +/// +/// ```rust,edition2018 +/// // Rust 2015 and 2018: +/// +/// # #![allow(array_into_iter)] // override our `deny(warnings)` +/// let array: [i32; 3] = [0; 3]; +/// +/// // This creates a slice iterator, producing references to each value. +/// for item in array.into_iter().enumerate() { +/// let (i, x): (usize, &i32) = item; +/// println!("array[{i}] = {x}"); +/// } +/// +/// // The `array_into_iter` lint suggests this change for future compatibility: +/// for item in array.iter().enumerate() { +/// let (i, x): (usize, &i32) = item; +/// println!("array[{i}] = {x}"); +/// } +/// +/// // You can explicitly iterate an array by value using `IntoIterator::into_iter` +/// for item in IntoIterator::into_iter(array).enumerate() { +/// let (i, x): (usize, i32) = item; +/// println!("array[{i}] = {x}"); +/// } +/// ``` +/// +/// Starting in the 2021 edition, `array.into_iter()` uses `IntoIterator` normally to iterate +/// by value, and `iter()` should be used to iterate by reference like previous editions. +/// +/// ```rust,edition2021 +/// // Rust 2021: +/// +/// let array: [i32; 3] = [0; 3]; +/// +/// // This iterates by reference: +/// for item in array.iter().enumerate() { +/// let (i, x): (usize, &i32) = item; +/// println!("array[{i}] = {x}"); +/// } +/// +/// // This iterates by value: +/// for item in array.into_iter().enumerate() { +/// let (i, x): (usize, i32) = item; +/// println!("array[{i}] = {x}"); +/// } +/// ``` +/// +/// Future language versions might start treating the `array.into_iter()` +/// syntax on editions 2015 and 2018 the same as on edition 2021. So code using +/// those older editions should still be written with this change in mind, to +/// prevent breakage in the future. The safest way to accomplish this is to +/// avoid the `into_iter` syntax on those editions. If an edition update is not +/// viable/desired, there are multiple alternatives: +/// * use `iter`, equivalent to the old behavior, creating references +/// * use [`IntoIterator::into_iter`], equivalent to the post-2021 behavior (Rust 1.53+) +/// * replace `for ... in array.into_iter() {` with `for ... in array {`, +/// equivalent to the post-2021 behavior (Rust 1.53+) +/// +/// ```rust,edition2018 +/// // Rust 2015 and 2018: +/// +/// let array: [i32; 3] = [0; 3]; +/// +/// // This iterates by reference: +/// for item in array.iter() { +/// let x: &i32 = item; +/// println!("{x}"); +/// } +/// +/// // This iterates by value: +/// for item in IntoIterator::into_iter(array) { +/// let x: i32 = item; +/// println!("{x}"); +/// } +/// +/// // This iterates by value: +/// for item in array { +/// let x: i32 = item; +/// println!("{x}"); +/// } +/// +/// // IntoIter can also start a chain. +/// // This iterates by value: +/// for item in IntoIterator::into_iter(array).enumerate() { +/// let (i, x): (usize, i32) = item; +/// println!("array[{i}] = {x}"); +/// } +/// ``` +/// +/// [slice]: prim@slice +/// [`Debug`]: fmt::Debug +/// [`Hash`]: hash::Hash +/// [`Borrow`]: borrow::Borrow +/// [`BorrowMut`]: borrow::BorrowMut +/// [slice pattern]: ../reference/patterns.html#slice-patterns +/// [`From`]: convert::From +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_array {} + +#[rustc_doc_primitive = "slice"] +#[doc(alias = "[")] +#[doc(alias = "]")] +#[doc(alias = "[]")] +/// A dynamically-sized view into a contiguous sequence, `[T]`. +/// +/// Contiguous here means that elements are laid out so that every element is the same +/// distance from its neighbors. +/// +/// *[See also the `std::slice` module](crate::slice).* +/// +/// Slices are a view into a block of memory represented as a pointer and a +/// length. +/// +/// ``` +/// // slicing a Vec +/// let vec = vec![1, 2, 3]; +/// let int_slice = &vec[..]; +/// // coercing an array to a slice +/// let str_slice: &[&str] = &["one", "two", "three"]; +/// ``` +/// +/// Slices are either mutable or shared. The shared slice type is `&[T]`, +/// while the mutable slice type is `&mut [T]`, where `T` represents the element +/// type. For example, you can mutate the block of memory that a mutable slice +/// points to: +/// +/// ``` +/// let mut x = [1, 2, 3]; +/// let x = &mut x[..]; // Take a full slice of `x`. +/// x[1] = 7; +/// assert_eq!(x, &[1, 7, 3]); +/// ``` +/// +/// It is possible to slice empty subranges of slices by using empty ranges (including `slice.len()..slice.len()`): +/// ``` +/// let x = [1, 2, 3]; +/// let empty = &x[0..0]; // subslice before the first element +/// assert_eq!(empty, &[]); +/// let empty = &x[..0]; // same as &x[0..0] +/// assert_eq!(empty, &[]); +/// let empty = &x[1..1]; // empty subslice in the middle +/// assert_eq!(empty, &[]); +/// let empty = &x[3..3]; // subslice after the last element +/// assert_eq!(empty, &[]); +/// let empty = &x[3..]; // same as &x[3..3] +/// assert_eq!(empty, &[]); +/// ``` +/// +/// It is not allowed to use subranges that start with lower bound bigger than `slice.len()`: +/// ```should_panic +/// let x = vec![1, 2, 3]; +/// let _ = &x[4..4]; +/// ``` +/// +/// As slices store the length of the sequence they refer to, they have twice +/// the size of pointers to [`Sized`](marker/trait.Sized.html) types. +/// Also see the reference on +/// [dynamically sized types](../reference/dynamically-sized-types.html). +/// +/// ``` +/// # use std::rc::Rc; +/// let pointer_size = std::mem::size_of::<&u8>(); +/// assert_eq!(2 * pointer_size, std::mem::size_of::<&[u8]>()); +/// assert_eq!(2 * pointer_size, std::mem::size_of::<*const [u8]>()); +/// assert_eq!(2 * pointer_size, std::mem::size_of::>()); +/// assert_eq!(2 * pointer_size, std::mem::size_of::>()); +/// ``` +/// +/// ## Trait Implementations +/// +/// Some traits are implemented for slices if the element type implements +/// that trait. This includes [`Eq`], [`Hash`] and [`Ord`]. +/// +/// ## Iteration +/// +/// The slices implement `IntoIterator`. The iterator yields references to the +/// slice elements. +/// +/// ``` +/// let numbers: &[i32] = &[0, 1, 2]; +/// for n in numbers { +/// println!("{n} is a number!"); +/// } +/// ``` +/// +/// The mutable slice yields mutable references to the elements: +/// +/// ``` +/// let mut scores: &mut [i32] = &mut [7, 8, 9]; +/// for score in scores { +/// *score += 1; +/// } +/// ``` +/// +/// This iterator yields mutable references to the slice's elements, so while +/// the element type of the slice is `i32`, the element type of the iterator is +/// `&mut i32`. +/// +/// * [`.iter`] and [`.iter_mut`] are the explicit methods to return the default +/// iterators. +/// * Further methods that return iterators are [`.split`], [`.splitn`], +/// [`.chunks`], [`.windows`] and more. +/// +/// [`Hash`]: core::hash::Hash +/// [`.iter`]: slice::iter +/// [`.iter_mut`]: slice::iter_mut +/// [`.split`]: slice::split +/// [`.splitn`]: slice::splitn +/// [`.chunks`]: slice::chunks +/// [`.windows`]: slice::windows +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_slice {} + +#[rustc_doc_primitive = "str"] +/// String slices. +/// +/// *[See also the `std::str` module](crate::str).* +/// +/// The `str` type, also called a 'string slice', is the most primitive string +/// type. It is usually seen in its borrowed form, `&str`. It is also the type +/// of string literals, `&'static str`. +/// +/// # Basic Usage +/// +/// String literals are string slices: +/// +/// ``` +/// let hello_world = "Hello, World!"; +/// ``` +/// +/// Here we have declared a string slice initialized with a string literal. +/// String literals have a static lifetime, which means the string `hello_world` +/// is guaranteed to be valid for the duration of the entire program. +/// We can explicitly specify `hello_world`'s lifetime as well: +/// +/// ``` +/// let hello_world: &'static str = "Hello, world!"; +/// ``` +/// +/// # Representation +/// +/// A `&str` is made up of two components: a pointer to some bytes, and a +/// length. You can look at these with the [`as_ptr`] and [`len`] methods: +/// +/// ``` +/// use std::slice; +/// use std::str; +/// +/// let story = "Once upon a time..."; +/// +/// let ptr = story.as_ptr(); +/// let len = story.len(); +/// +/// // story has nineteen bytes +/// assert_eq!(19, len); +/// +/// // We can re-build a str out of ptr and len. This is all unsafe because +/// // we are responsible for making sure the two components are valid: +/// let s = unsafe { +/// // First, we build a &[u8]... +/// let slice = slice::from_raw_parts(ptr, len); +/// +/// // ... and then convert that slice into a string slice +/// str::from_utf8(slice) +/// }; +/// +/// assert_eq!(s, Ok(story)); +/// ``` +/// +/// [`as_ptr`]: str::as_ptr +/// [`len`]: str::len +/// +/// Note: This example shows the internals of `&str`. `unsafe` should not be +/// used to get a string slice under normal circumstances. Use `as_str` +/// instead. +/// +/// # Invariant +/// +/// Rust libraries may assume that string slices are always valid UTF-8. +/// +/// Constructing a non-UTF-8 string slice is not immediate undefined behavior, but any function +/// called on a string slice may assume that it is valid UTF-8, which means that a non-UTF-8 string +/// slice can lead to undefined behavior down the road. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_str {} + +#[rustc_doc_primitive = "tuple"] +#[doc(alias = "(")] +#[doc(alias = ")")] +#[doc(alias = "()")] +// +/// A finite heterogeneous sequence, `(T, U, ..)`. +/// +/// Let's cover each of those in turn: +/// +/// Tuples are *finite*. In other words, a tuple has a length. Here's a tuple +/// of length `3`: +/// +/// ``` +/// ("hello", 5, 'c'); +/// ``` +/// +/// 'Length' is also sometimes called 'arity' here; each tuple of a different +/// length is a different, distinct type. +/// +/// Tuples are *heterogeneous*. This means that each element of the tuple can +/// have a different type. In that tuple above, it has the type: +/// +/// ``` +/// # let _: +/// (&'static str, i32, char) +/// # = ("hello", 5, 'c'); +/// ``` +/// +/// Tuples are a *sequence*. This means that they can be accessed by position; +/// this is called 'tuple indexing', and it looks like this: +/// +/// ```rust +/// let tuple = ("hello", 5, 'c'); +/// +/// assert_eq!(tuple.0, "hello"); +/// assert_eq!(tuple.1, 5); +/// assert_eq!(tuple.2, 'c'); +/// ``` +/// +/// The sequential nature of the tuple applies to its implementations of various +/// traits. For example, in [`PartialOrd`] and [`Ord`], the elements are compared +/// sequentially until the first non-equal set is found. +/// +/// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type). +/// +// Hardcoded anchor in src/librustdoc/html/format.rs +// linked to as `#trait-implementations-1` +/// # Trait implementations +/// +/// In this documentation the shorthand `(T₁, T₂, …, Tₙ)` is used to represent tuples of varying +/// length. When that is used, any trait bound expressed on `T` applies to each element of the +/// tuple independently. Note that this is a convenience notation to avoid repetitive +/// documentation, not valid Rust syntax. +/// +/// Due to a temporary restriction in Rust’s type system, the following traits are only +/// implemented on tuples of arity 12 or less. In the future, this may change: +/// +/// * [`PartialEq`] +/// * [`Eq`] +/// * [`PartialOrd`] +/// * [`Ord`] +/// * [`Debug`] +/// * [`Default`] +/// * [`Hash`] +/// * [`From<[T; N]>`][from] +/// +/// [from]: convert::From +/// [`Debug`]: fmt::Debug +/// [`Hash`]: hash::Hash +/// +/// The following traits are implemented for tuples of any length. These traits have +/// implementations that are automatically generated by the compiler, so are not limited by +/// missing language features. +/// +/// * [`Clone`] +/// * [`Copy`] +/// * [`Send`] +/// * [`Sync`] +/// * [`Unpin`] +/// * [`UnwindSafe`] +/// * [`RefUnwindSafe`] +/// +/// [`UnwindSafe`]: panic::UnwindSafe +/// [`RefUnwindSafe`]: panic::RefUnwindSafe +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let tuple = ("hello", 5, 'c'); +/// +/// assert_eq!(tuple.0, "hello"); +/// ``` +/// +/// Tuples are often used as a return type when you want to return more than +/// one value: +/// +/// ``` +/// fn calculate_point() -> (i32, i32) { +/// // Don't do a calculation, that's not the point of the example +/// (4, 5) +/// } +/// +/// let point = calculate_point(); +/// +/// assert_eq!(point.0, 4); +/// assert_eq!(point.1, 5); +/// +/// // Combining this with patterns can be nicer. +/// +/// let (x, y) = calculate_point(); +/// +/// assert_eq!(x, 4); +/// assert_eq!(y, 5); +/// ``` +/// +/// Homogeneous tuples can be created from arrays of appropriate length: +/// +/// ``` +/// let array: [u32; 3] = [1, 2, 3]; +/// let tuple: (u32, u32, u32) = array.into(); +/// ``` +/// +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_tuple {} + +// Required to make auto trait impls render. +// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls +#[doc(hidden)] +impl (T,) {} + +#[rustc_doc_primitive = "f16"] +#[doc(alias = "half")] +/// A 16-bit floating-point type (specifically, the "binary16" type defined in IEEE 754-2008). +/// +/// This type is very similar to [`prim@f32`] but has decreased precision because it uses half as many +/// bits. Please see [the documentation for `f32`](prim@f32) or [Wikipedia on half-precision +/// values][wikipedia] for more information. +/// +/// Note that most common platforms will not support `f16` in hardware without enabling extra target +/// features, with the notable exception of Apple Silicon (also known as M1, M2, etc.) processors. +/// Hardware support on x86-64 requires the avx512fp16 feature, while RISC-V requires Zhf. +/// Usually the fallback implementation will be to use `f32` hardware if it exists, and convert +/// between `f16` and `f32` when performing math. +/// +/// *[See also the `std::f16::consts` module](crate::f16::consts).* +/// +/// [wikipedia]: https://en.wikipedia.org/wiki/Half-precision_floating-point_format +#[unstable(feature = "f16", issue = "116909")] +mod prim_f16 {} + +#[rustc_doc_primitive = "f32"] +#[doc(alias = "single")] +/// A 32-bit floating-point type (specifically, the "binary32" type defined in IEEE 754-2008). +/// +/// This type can represent a wide range of decimal numbers, like `3.5`, `27`, +/// `-113.75`, `0.0078125`, `34359738368`, `0`, `-1`. So unlike integer types +/// (such as `i32`), floating-point types can represent non-integer numbers, +/// too. +/// +/// However, being able to represent this wide range of numbers comes at the +/// cost of precision: floats can only represent some of the real numbers and +/// calculation with floats round to a nearby representable number. For example, +/// `5.0` and `1.0` can be exactly represented as `f32`, but `1.0 / 5.0` results +/// in `0.20000000298023223876953125` since `0.2` cannot be exactly represented +/// as `f32`. Note, however, that printing floats with `println` and friends will +/// often discard insignificant digits: `println!("{}", 1.0f32 / 5.0f32)` will +/// print `0.2`. +/// +/// Additionally, `f32` can represent some special values: +/// +/// - −0.0: IEEE 754 floating-point numbers have a bit that indicates their sign, so −0.0 is a +/// possible value. For comparison −0.0 = +0.0, but floating-point operations can carry +/// the sign bit through arithmetic operations. This means −0.0 × +0.0 produces −0.0 and +/// a negative number rounded to a value smaller than a float can represent also produces −0.0. +/// - [∞](#associatedconstant.INFINITY) and +/// [−∞](#associatedconstant.NEG_INFINITY): these result from calculations +/// like `1.0 / 0.0`. +/// - [NaN (not a number)](#associatedconstant.NAN): this value results from +/// calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected +/// behavior: +/// - It is not equal to any float, including itself! This is the reason `f32` +/// doesn't implement the `Eq` trait. +/// - It is also neither smaller nor greater than any float, making it +/// impossible to sort by the default comparison operation, which is the +/// reason `f32` doesn't implement the `Ord` trait. +/// - It is also considered *infectious* as almost all calculations where one +/// of the operands is NaN will also result in NaN. The explanations on this +/// page only explicitly document behavior on NaN operands if this default +/// is deviated from. +/// - Lastly, there are multiple bit patterns that are considered NaN. +/// Rust does not currently guarantee that the bit patterns of NaN are +/// preserved over arithmetic operations, and they are not guaranteed to be +/// portable or even fully deterministic! This means that there may be some +/// surprising results upon inspecting the bit patterns, +/// as the same calculations might produce NaNs with different bit patterns. +/// This also affects the sign of the NaN: checking `is_sign_positive` or `is_sign_negative` on +/// a NaN is the most common way to run into these surprising results. +/// (Checking `x >= 0.0` or `x <= 0.0` avoids those surprises, but also how negative/positive +/// zero are treated.) +/// See the section below for what exactly is guaranteed about the bit pattern of a NaN. +/// +/// When a primitive operation (addition, subtraction, multiplication, or +/// division) is performed on this type, the result is rounded according to the +/// roundTiesToEven direction defined in IEEE 754-2008. That means: +/// +/// - The result is the representable value closest to the true value, if there +/// is a unique closest representable value. +/// - If the true value is exactly half-way between two representable values, +/// the result is the one with an even least-significant binary digit. +/// - If the true value's magnitude is ≥ `f32::MAX` + 2(`f32::MAX_EXP` − +/// `f32::MANTISSA_DIGITS` − 1), the result is ∞ or −∞ (preserving the +/// true value's sign). +/// - If the result of a sum exactly equals zero, the outcome is +0.0 unless +/// both arguments were negative, then it is -0.0. Subtraction `a - b` is +/// regarded as a sum `a + (-b)`. +/// +/// For more information on floating-point numbers, see [Wikipedia][wikipedia]. +/// +/// *[See also the `std::f32::consts` module](crate::f32::consts).* +/// +/// [wikipedia]: https://en.wikipedia.org/wiki/Single-precision_floating-point_format +/// +/// # NaN bit patterns +/// +/// This section defines the possible NaN bit patterns returned by floating-point operations. +/// +/// The bit pattern of a floating-point NaN value is defined by: +/// - a sign bit. +/// - a quiet/signaling bit. Rust assumes that the quiet/signaling bit being set to `1` indicates a +/// quiet NaN (QNaN), and a value of `0` indicates a signaling NaN (SNaN). In the following we +/// will hence just call it the "quiet bit". +/// - a payload, which makes up the rest of the significand (i.e., the mantissa) except for the +/// quiet bit. +/// +/// The rules for NaN values differ between *arithmetic* and *non-arithmetic* (or "bitwise") +/// operations. The non-arithmetic operations are unary `-`, `abs`, `copysign`, `signum`, +/// `{to,from}_bits`, `{to,from}_{be,le,ne}_bytes` and `is_sign_{positive,negative}`. These +/// operations are guaranteed to exactly preserve the bit pattern of their input except for possibly +/// changing the sign bit. +/// +/// The following rules apply when a NaN value is returned from an arithmetic operation: +/// - The result has a non-deterministic sign. +/// - The quiet bit and payload are non-deterministically chosen from +/// the following set of options: +/// +/// - **Preferred NaN**: The quiet bit is set and the payload is all-zero. +/// - **Quieting NaN propagation**: The quiet bit is set and the payload is copied from any input +/// operand that is a NaN. If the inputs and outputs do not have the same payload size (i.e., for +/// `as` casts), then +/// - If the output is smaller than the input, low-order bits of the payload get dropped. +/// - If the output is larger than the input, the payload gets filled up with 0s in the low-order +/// bits. +/// - **Unchanged NaN propagation**: The quiet bit and payload are copied from any input operand +/// that is a NaN. If the inputs and outputs do not have the same size (i.e., for `as` casts), the +/// same rules as for "quieting NaN propagation" apply, with one caveat: if the output is smaller +/// than the input, dropping the low-order bits may result in a payload of 0; a payload of 0 is not +/// possible with a signaling NaN (the all-0 significand encodes an infinity) so unchanged NaN +/// propagation cannot occur with some inputs. +/// - **Target-specific NaN**: The quiet bit is set and the payload is picked from a target-specific +/// set of "extra" possible NaN payloads. The set can depend on the input operand values. +/// See the table below for the concrete NaNs this set contains on various targets. +/// +/// In particular, if all input NaNs are quiet (or if there are no input NaNs), then the output NaN +/// is definitely quiet. Signaling NaN outputs can only occur if they are provided as an input +/// value. Similarly, if all input NaNs are preferred (or if there are no input NaNs) and the target +/// does not have any "extra" NaN payloads, then the output NaN is guaranteed to be preferred. +/// +/// The non-deterministic choice happens when the operation is executed; i.e., the result of a +/// NaN-producing floating-point operation is a stable bit pattern (looking at these bits multiple +/// times will yield consistent results), but running the same operation twice with the same inputs +/// can produce different results. +/// +/// These guarantees are neither stronger nor weaker than those of IEEE 754: IEEE 754 guarantees +/// that an operation never returns a signaling NaN, whereas it is possible for operations like +/// `SNAN * 1.0` to return a signaling NaN in Rust. Conversely, IEEE 754 makes no statement at all +/// about which quiet NaN is returned, whereas Rust restricts the set of possible results to the +/// ones listed above. +/// +/// Unless noted otherwise, the same rules also apply to NaNs returned by other library functions +/// (e.g. `min`, `minimum`, `max`, `maximum`); other aspects of their semantics and which IEEE 754 +/// operation they correspond to are documented with the respective functions. +/// +/// When an arithmetic floating-point operation is executed in `const` context, the same rules +/// apply: no guarantee is made about which of the NaN bit patterns described above will be +/// returned. The result does not have to match what happens when executing the same code at +/// runtime, and the result can vary depending on factors such as compiler version and flags. +/// +/// ### Target-specific "extra" NaN values +// FIXME: Is there a better place to put this? +/// +/// | `target_arch` | Extra payloads possible on this platform | +/// |---------------|---------| +/// | `x86`, `x86_64`, `arm`, `aarch64`, `riscv32`, `riscv64` | None | +/// | `sparc`, `sparc64` | The all-one payload | +/// | `wasm32`, `wasm64` | If all input NaNs are quiet with all-zero payload: None.
Otherwise: all possible payloads. | +/// +/// For targets not in this table, all payloads are possible. + +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_f32 {} + +#[rustc_doc_primitive = "f64"] +#[doc(alias = "double")] +/// A 64-bit floating-point type (specifically, the "binary64" type defined in IEEE 754-2008). +/// +/// This type is very similar to [`prim@f32`], but has increased precision by using twice as many +/// bits. Please see [the documentation for `f32`](prim@f32) or [Wikipedia on double-precision +/// values][wikipedia] for more information. +/// +/// *[See also the `std::f64::consts` module](crate::f64::consts).* +/// +/// [wikipedia]: https://en.wikipedia.org/wiki/Double-precision_floating-point_format +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_f64 {} + +#[rustc_doc_primitive = "f128"] +#[doc(alias = "quad")] +/// A 128-bit floating-point type (specifically, the "binary128" type defined in IEEE 754-2008). +/// +/// This type is very similar to [`prim@f32`] and [`prim@f64`], but has increased precision by using twice +/// as many bits as `f64`. Please see [the documentation for `f32`](prim@f32) or [Wikipedia on +/// quad-precision values][wikipedia] for more information. +/// +/// Note that no platforms have hardware support for `f128` without enabling target specific features, +/// as for all instruction set architectures `f128` is considered an optional feature. +/// Only Power ISA ("PowerPC") and RISC-V specify it, and only certain microarchitectures +/// actually implement it. For x86-64 and AArch64, ISA support is not even specified, +/// so it will always be a software implementation significantly slower than `f64`. +/// +/// _Note: `f128` support is incomplete. Many platforms will not be able to link math functions. On +/// x86 in particular, these functions do link but their results are always incorrect._ +/// +/// *[See also the `std::f128::consts` module](crate::f128::consts).* +/// +/// [wikipedia]: https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format +#[unstable(feature = "f128", issue = "116909")] +mod prim_f128 {} + +#[rustc_doc_primitive = "i8"] +// +/// The 8-bit signed integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_i8 {} + +#[rustc_doc_primitive = "i16"] +// +/// The 16-bit signed integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_i16 {} + +#[rustc_doc_primitive = "i32"] +// +/// The 32-bit signed integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_i32 {} + +#[rustc_doc_primitive = "i64"] +// +/// The 64-bit signed integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_i64 {} + +#[rustc_doc_primitive = "i128"] +// +/// The 128-bit signed integer type. +#[stable(feature = "i128", since = "1.26.0")] +mod prim_i128 {} + +#[rustc_doc_primitive = "u8"] +// +/// The 8-bit unsigned integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_u8 {} + +#[rustc_doc_primitive = "u16"] +// +/// The 16-bit unsigned integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_u16 {} + +#[rustc_doc_primitive = "u32"] +// +/// The 32-bit unsigned integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_u32 {} + +#[rustc_doc_primitive = "u64"] +// +/// The 64-bit unsigned integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_u64 {} + +#[rustc_doc_primitive = "u128"] +// +/// The 128-bit unsigned integer type. +#[stable(feature = "i128", since = "1.26.0")] +mod prim_u128 {} + +#[rustc_doc_primitive = "isize"] +// +/// The pointer-sized signed integer type. +/// +/// The size of this primitive is how many bytes it takes to reference any +/// location in memory. For example, on a 32 bit target, this is 4 bytes +/// and on a 64 bit target, this is 8 bytes. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_isize {} + +#[rustc_doc_primitive = "usize"] +// +/// The pointer-sized unsigned integer type. +/// +/// The size of this primitive is how many bytes it takes to reference any +/// location in memory. For example, on a 32 bit target, this is 4 bytes +/// and on a 64 bit target, this is 8 bytes. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_usize {} + +#[rustc_doc_primitive = "reference"] +#[doc(alias = "&")] +#[doc(alias = "&mut")] +// +/// References, `&T` and `&mut T`. +/// +/// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut` +/// operators on a value, or by using a [`ref`](../std/keyword.ref.html) or +/// [ref](../std/keyword.ref.html) [mut](../std/keyword.mut.html) pattern. +/// +/// For those familiar with pointers, a reference is just a pointer that is assumed to be +/// aligned, not null, and pointing to memory containing a valid value of `T` - for example, +/// &[bool] can only point to an allocation containing the integer values `1` +/// ([`true`](../std/keyword.true.html)) or `0` ([`false`](../std/keyword.false.html)), but +/// creating a &[bool] that points to an allocation containing +/// the value `3` causes undefined behavior. +/// In fact, [Option]\<&T> has the same memory representation as a +/// nullable but aligned pointer, and can be passed across FFI boundaries as such. +/// +/// In most cases, references can be used much like the original value. Field access, method +/// calling, and indexing work the same (save for mutability rules, of course). In addition, the +/// comparison operators transparently defer to the referent's implementation, allowing references +/// to be compared the same as owned values. +/// +/// References have a lifetime attached to them, which represents the scope for which the borrow is +/// valid. A lifetime is said to "outlive" another one if its representative scope is as long or +/// longer than the other. The `'static` lifetime is the longest lifetime, which represents the +/// total life of the program. For example, string literals have a `'static` lifetime because the +/// text data is embedded into the binary of the program, rather than in an allocation that needs +/// to be dynamically managed. +/// +/// `&mut T` references can be freely coerced into `&T` references with the same referent type, and +/// references with longer lifetimes can be freely coerced into references with shorter ones. +/// +/// Reference equality by address, instead of comparing the values pointed to, is accomplished via +/// implicit reference-pointer coercion and raw pointer equality via [`ptr::eq`], while +/// [`PartialEq`] compares values. +/// +/// ``` +/// use std::ptr; +/// +/// let five = 5; +/// let other_five = 5; +/// let five_ref = &five; +/// let same_five_ref = &five; +/// let other_five_ref = &other_five; +/// +/// assert!(five_ref == same_five_ref); +/// assert!(five_ref == other_five_ref); +/// +/// assert!(ptr::eq(five_ref, same_five_ref)); +/// assert!(!ptr::eq(five_ref, other_five_ref)); +/// ``` +/// +/// For more information on how to use references, see [the book's section on "References and +/// Borrowing"][book-refs]. +/// +/// [book-refs]: ../book/ch04-02-references-and-borrowing.html +/// +/// # Trait implementations +/// +/// The following traits are implemented for all `&T`, regardless of the type of its referent: +/// +/// * [`Copy`] +/// * [`Clone`] \(Note that this will not defer to `T`'s `Clone` implementation if it exists!) +/// * [`Deref`] +/// * [`Borrow`] +/// * [`fmt::Pointer`] +/// +/// [`Deref`]: ops::Deref +/// [`Borrow`]: borrow::Borrow +/// +/// `&mut T` references get all of the above except `Copy` and `Clone` (to prevent creating +/// multiple simultaneous mutable borrows), plus the following, regardless of the type of its +/// referent: +/// +/// * [`DerefMut`] +/// * [`BorrowMut`] +/// +/// [`DerefMut`]: ops::DerefMut +/// [`BorrowMut`]: borrow::BorrowMut +/// [bool]: prim@bool +/// +/// The following traits are implemented on `&T` references if the underlying `T` also implements +/// that trait: +/// +/// * All the traits in [`std::fmt`] except [`fmt::Pointer`] (which is implemented regardless of the type of its referent) and [`fmt::Write`] +/// * [`PartialOrd`] +/// * [`Ord`] +/// * [`PartialEq`] +/// * [`Eq`] +/// * [`AsRef`] +/// * [`Fn`] \(in addition, `&T` references get [`FnMut`] and [`FnOnce`] if `T: Fn`) +/// * [`Hash`] +/// * [`ToSocketAddrs`] +/// * [`Sync`] +/// +/// [`std::fmt`]: fmt +/// [`Hash`]: hash::Hash +/// [`ToSocketAddrs`]: ../std/net/trait.ToSocketAddrs.html +/// +/// `&mut T` references get all of the above except `ToSocketAddrs`, plus the following, if `T` +/// implements that trait: +/// +/// * [`AsMut`] +/// * [`FnMut`] \(in addition, `&mut T` references get [`FnOnce`] if `T: FnMut`) +/// * [`fmt::Write`] +/// * [`Iterator`] +/// * [`DoubleEndedIterator`] +/// * [`ExactSizeIterator`] +/// * [`FusedIterator`] +/// * [`TrustedLen`] +/// * [`Send`] +/// * [`io::Write`] +/// * [`Read`] +/// * [`Seek`] +/// * [`BufRead`] +/// +/// [`FusedIterator`]: iter::FusedIterator +/// [`TrustedLen`]: iter::TrustedLen +/// [`Seek`]: ../std/io/trait.Seek.html +/// [`BufRead`]: ../std/io/trait.BufRead.html +/// [`Read`]: ../std/io/trait.Read.html +/// [`io::Write`]: ../std/io/trait.Write.html +/// +/// In addition, `&T` references implement [`Send`] if and only if `T` implements [`Sync`]. +/// +/// Note that due to method call deref coercion, simply calling a trait method will act like they +/// work on references as well as they do on owned values! The implementations described here are +/// meant for generic contexts, where the final type `T` is a type parameter or otherwise not +/// locally known. +/// +/// # Safety +/// +/// For all types, `T: ?Sized`, and for all `t: &T` or `t: &mut T`, when such values cross an API +/// boundary, the following invariants must generally be upheld: +/// +/// * `t` is non-null +/// * `t` is aligned to `align_of_val(t)` +/// * if `size_of_val(t) > 0`, then `t` is dereferenceable for `size_of_val(t)` many bytes +/// +/// If `t` points at address `a`, being "dereferenceable" for N bytes means that the memory range +/// `[a, a + N)` is all contained within a single [allocated object]. +/// +/// For instance, this means that unsafe code in a safe function may assume these invariants are +/// ensured of arguments passed by the caller, and it may assume that these invariants are ensured +/// of return values from any safe functions it calls. +/// +/// For the other direction, things are more complicated: when unsafe code passes arguments +/// to safe functions or returns values from safe functions, they generally must *at least* +/// not violate these invariants. The full requirements are stronger, as the reference generally +/// must point to data that is safe to use at type `T`. +/// +/// It is not decided yet whether unsafe code may violate these invariants temporarily on internal +/// data. As a consequence, unsafe code which violates these invariants temporarily on internal data +/// may be unsound or become unsound in future versions of Rust depending on how this question is +/// decided. +/// +/// [allocated object]: ptr#allocated-object +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_ref {} + +#[rustc_doc_primitive = "fn"] +// +/// Function pointers, like `fn(usize) -> bool`. +/// +/// *See also the traits [`Fn`], [`FnMut`], and [`FnOnce`].* +/// +/// Function pointers are pointers that point to *code*, not data. They can be called +/// just like functions. Like references, function pointers are, among other things, assumed to +/// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null +/// pointers, make your type [`Option`](core::option#options-and-pointers-nullable-pointers) +/// with your required signature. +/// +/// Note that FFI requires additional care to ensure that the ABI for both sides of the call match. +/// The exact requirements are not currently documented. +/// +/// ### Safety +/// +/// Plain function pointers are obtained by casting either plain functions, or closures that don't +/// capture an environment: +/// +/// ``` +/// fn add_one(x: usize) -> usize { +/// x + 1 +/// } +/// +/// let ptr: fn(usize) -> usize = add_one; +/// assert_eq!(ptr(5), 6); +/// +/// let clos: fn(usize) -> usize = |x| x + 5; +/// assert_eq!(clos(5), 10); +/// ``` +/// +/// In addition to varying based on their signature, function pointers come in two flavors: safe +/// and unsafe. Plain `fn()` function pointers can only point to safe functions, +/// while `unsafe fn()` function pointers can point to safe or unsafe functions. +/// +/// ``` +/// fn add_one(x: usize) -> usize { +/// x + 1 +/// } +/// +/// unsafe fn add_one_unsafely(x: usize) -> usize { +/// x + 1 +/// } +/// +/// let safe_ptr: fn(usize) -> usize = add_one; +/// +/// //ERROR: mismatched types: expected normal fn, found unsafe fn +/// //let bad_ptr: fn(usize) -> usize = add_one_unsafely; +/// +/// let unsafe_ptr: unsafe fn(usize) -> usize = add_one_unsafely; +/// let really_safe_ptr: unsafe fn(usize) -> usize = add_one; +/// ``` +/// +/// ### ABI +/// +/// On top of that, function pointers can vary based on what ABI they use. This +/// is achieved by adding the `extern` keyword before the type, followed by the +/// ABI in question. The default ABI is "Rust", i.e., `fn()` is the exact same +/// type as `extern "Rust" fn()`. A pointer to a function with C ABI would have +/// type `extern "C" fn()`. +/// +/// `extern "ABI" { ... }` blocks declare functions with ABI "ABI". The default +/// here is "C", i.e., functions declared in an `extern {...}` block have "C" +/// ABI. +/// +/// For more information and a list of supported ABIs, see [the nomicon's +/// section on foreign calling conventions][nomicon-abi]. +/// +/// [nomicon-abi]: ../nomicon/ffi.html#foreign-calling-conventions +/// +/// ### Variadic functions +/// +/// Extern function declarations with the "C" or "cdecl" ABIs can also be *variadic*, allowing them +/// to be called with a variable number of arguments. Normal Rust functions, even those with an +/// `extern "ABI"`, cannot be variadic. For more information, see [the nomicon's section on +/// variadic functions][nomicon-variadic]. +/// +/// [nomicon-variadic]: ../nomicon/ffi.html#variadic-functions +/// +/// ### Creating function pointers +/// +/// When `bar` is the name of a function, then the expression `bar` is *not* a +/// function pointer. Rather, it denotes a value of an unnameable type that +/// uniquely identifies the function `bar`. The value is zero-sized because the +/// type already identifies the function. This has the advantage that "calling" +/// the value (it implements the `Fn*` traits) does not require dynamic +/// dispatch. +/// +/// This zero-sized type *coerces* to a regular function pointer. For example: +/// +/// ```rust +/// use std::mem; +/// +/// fn bar(x: i32) {} +/// +/// let not_bar_ptr = bar; // `not_bar_ptr` is zero-sized, uniquely identifying `bar` +/// assert_eq!(mem::size_of_val(¬_bar_ptr), 0); +/// +/// let bar_ptr: fn(i32) = not_bar_ptr; // force coercion to function pointer +/// assert_eq!(mem::size_of_val(&bar_ptr), mem::size_of::()); +/// +/// let footgun = &bar; // this is a shared reference to the zero-sized type identifying `bar` +/// ``` +/// +/// The last line shows that `&bar` is not a function pointer either. Rather, it +/// is a reference to the function-specific ZST. `&bar` is basically never what you +/// want when `bar` is a function. +/// +/// ### Casting to and from integers +/// +/// You can cast function pointers directly to integers: +/// +/// ```rust +/// let fnptr: fn(i32) -> i32 = |x| x+2; +/// let fnptr_addr = fnptr as usize; +/// ``` +/// +/// However, a direct cast back is not possible. You need to use `transmute`: +/// +/// ```rust +/// # #[cfg(not(miri))] { // FIXME: use strict provenance APIs once they are stable, then remove this `cfg` +/// # let fnptr: fn(i32) -> i32 = |x| x+2; +/// # let fnptr_addr = fnptr as usize; +/// let fnptr = fnptr_addr as *const (); +/// let fnptr: fn(i32) -> i32 = unsafe { std::mem::transmute(fnptr) }; +/// assert_eq!(fnptr(40), 42); +/// # } +/// ``` +/// +/// Crucially, we `as`-cast to a raw pointer before `transmute`ing to a function pointer. +/// This avoids an integer-to-pointer `transmute`, which can be problematic. +/// Transmuting between raw pointers and function pointers (i.e., two pointer types) is fine. +/// +/// Note that all of this is not portable to platforms where function pointers and data pointers +/// have different sizes. +/// +/// ### ABI compatibility +/// +/// Generally, when a function is declared with one signature and called via a function pointer with +/// a different signature, the two signatures must be *ABI-compatible* or else calling the function +/// via that function pointer is Undefined Behavior. ABI compatibility is a lot stricter than merely +/// having the same memory layout; for example, even if `i32` and `f32` have the same size and +/// alignment, they might be passed in different registers and hence not be ABI-compatible. +/// +/// ABI compatibility as a concern only arises in code that alters the type of function pointers, +/// and code that imports functions via `extern` blocks. Altering the type of function pointers is +/// wildly unsafe (as in, a lot more unsafe than even [`transmute_copy`][mem::transmute_copy]), and +/// should only occur in the most exceptional circumstances. Most Rust code just imports functions +/// via `use`. So, most likely you do not have to worry about ABI compatibility. +/// +/// But assuming such circumstances, what are the rules? For this section, we are only considering +/// the ABI of direct Rust-to-Rust calls (with both definition and callsite visible to the +/// Rust compiler), not linking in general -- once functions are imported via `extern` blocks, there +/// are more things to consider that we do not go into here. Note that this also applies to +/// passing/calling functions across language boundaries via function pointers. +/// +/// **Nothing in this section should be taken as a guarantee for non-Rust-to-Rust calls, even with +/// types from `core::ffi` or `libc`**. +/// +/// For two signatures to be considered *ABI-compatible*, they must use a compatible ABI string, +/// must take the same number of arguments, and the individual argument types and the return types +/// must be ABI-compatible. The ABI string is declared via `extern "ABI" fn(...) -> ...`; note that +/// `fn name(...) -> ...` implicitly uses the `"Rust"` ABI string and `extern fn name(...) -> ...` +/// implicitly uses the `"C"` ABI string. +/// +/// The ABI strings are guaranteed to be compatible if they are the same, or if the caller ABI +/// string is `$X-unwind` and the callee ABI string is `$X`, where `$X` is one of the following: +/// "C", "aapcs", "fastcall", "stdcall", "system", "sysv64", "thiscall", "vectorcall", "win64". +/// +/// The following types are guaranteed to be ABI-compatible: +/// +/// - `*const T`, `*mut T`, `&T`, `&mut T`, `Box` (specifically, only `Box`), and +/// `NonNull` are all ABI-compatible with each other for all `T`. They are also ABI-compatible +/// with each other for _different_ `T` if they have the same metadata type (`::Metadata`). +/// - `usize` is ABI-compatible with the `uN` integer type of the same size, and likewise `isize` is +/// ABI-compatible with the `iN` integer type of the same size. +/// - `char` is ABI-compatible with `u32`. +/// - Any two `fn` (function pointer) types are ABI-compatible with each other if they have the same +/// ABI string or the ABI string only differs in a trailing `-unwind`, independent of the rest of +/// their signature. (This means you can pass `fn()` to a function expecting `fn(i32)`, and the +/// call will be valid ABI-wise. The callee receives the result of transmuting the function pointer +/// from `fn()` to `fn(i32)`; that transmutation is itself a well-defined operation, it's just +/// almost certainly UB to later call that function pointer.) +/// - Any two types with size 0 and alignment 1 are ABI-compatible. +/// - A `repr(transparent)` type `T` is ABI-compatible with its unique non-trivial field, i.e., the +/// unique field that doesn't have size 0 and alignment 1 (if there is such a field). +/// - `i32` is ABI-compatible with `NonZero`, and similar for all other integer types. +/// - If `T` is guaranteed to be subject to the [null pointer +/// optimization](option/index.html#representation), and `E` is an enum satisfying the following +/// requirements, then `T` and `E` are ABI-compatible. Such an enum `E` is called "option-like". +/// - The enum `E` has exactly two variants. +/// - One variant has exactly one field, of type `T`. +/// - All fields of the other variant are zero-sized with 1-byte alignment. +/// +/// Furthermore, ABI compatibility satisfies the following general properties: +/// +/// - Every type is ABI-compatible with itself. +/// - If `T1` and `T2` are ABI-compatible and `T2` and `T3` are ABI-compatible, then so are `T1` and +/// `T3` (i.e., ABI-compatibility is transitive). +/// - If `T1` and `T2` are ABI-compatible, then so are `T2` and `T1` (i.e., ABI-compatibility is +/// symmetric). +/// +/// More signatures can be ABI-compatible on specific targets, but that should not be relied upon +/// since it is not portable and not a stable guarantee. +/// +/// Noteworthy cases of types *not* being ABI-compatible in general are: +/// * `bool` vs `u8`, `i32` vs `u32`, `char` vs `i32`: on some targets, the calling conventions for +/// these types differ in terms of what they guarantee for the remaining bits in the register that +/// are not used by the value. +/// * `i32` vs `f32` are not compatible either, as has already been mentioned above. +/// * `struct Foo(u32)` and `u32` are not compatible (without `repr(transparent)`) since structs are +/// aggregate types and often passed in a different way than primitives like `i32`. +/// +/// Note that these rules describe when two completely known types are ABI-compatible. When +/// considering ABI compatibility of a type declared in another crate (including the standard +/// library), consider that any type that has a private field or the `#[non_exhaustive]` attribute +/// may change its layout as a non-breaking update unless documented otherwise -- so for instance, +/// even if such a type is a 1-ZST or `repr(transparent)` right now, this might change with any +/// library version bump. +/// +/// If the declared signature and the signature of the function pointer are ABI-compatible, then the +/// function call behaves as if every argument was [`transmute`d][mem::transmute] from the +/// type in the function pointer to the type at the function declaration, and the return value is +/// [`transmute`d][mem::transmute] from the type in the declaration to the type in the +/// pointer. All the usual caveats and concerns around transmutation apply; for instance, if the +/// function expects a `NonZero` and the function pointer uses the ABI-compatible type +/// `Option>`, and the value used for the argument is `None`, then this call is Undefined +/// Behavior since transmuting `None::>` to `NonZero` violates the non-zero +/// requirement. +/// +/// ### Trait implementations +/// +/// In this documentation the shorthand `fn(T₁, T₂, …, Tₙ)` is used to represent non-variadic +/// function pointers of varying length. Note that this is a convenience notation to avoid +/// repetitive documentation, not valid Rust syntax. +/// +/// The following traits are implemented for function pointers with any number of arguments and +/// any ABI. +/// +/// * [`PartialEq`] +/// * [`Eq`] +/// * [`PartialOrd`] +/// * [`Ord`] +/// * [`Hash`] +/// * [`Pointer`] +/// * [`Debug`] +/// * [`Clone`] +/// * [`Copy`] +/// * [`Send`] +/// * [`Sync`] +/// * [`Unpin`] +/// * [`UnwindSafe`] +/// * [`RefUnwindSafe`] +/// +/// Note that while this type implements `PartialEq`, comparing function pointers is unreliable: +/// pointers to the same function can compare inequal (because functions are duplicated in multiple +/// codegen units), and pointers to *different* functions can compare equal (since identical +/// functions can be deduplicated within a codegen unit). +/// +/// [`Hash`]: hash::Hash +/// [`Pointer`]: fmt::Pointer +/// [`UnwindSafe`]: panic::UnwindSafe +/// [`RefUnwindSafe`]: panic::RefUnwindSafe +/// +/// In addition, all *safe* function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`], because +/// these traits are specially known to the compiler. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_fn {} + +// Required to make auto trait impls render. +// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls +#[doc(hidden)] +impl fn(T) -> Ret {} diff --git a/CoqOfRust/core/ptr/alignment.rs b/CoqOfRust/core/ptr/alignment.rs new file mode 100644 index 000000000..74a1d40f4 --- /dev/null +++ b/CoqOfRust/core/ptr/alignment.rs @@ -0,0 +1,360 @@ +use crate::num::NonZero; +use crate::ub_checks::assert_unsafe_precondition; +use crate::{cmp, fmt, hash, mem, num}; + +/// A type storing a `usize` which is a power of two, and thus +/// represents a possible alignment in the Rust abstract machine. +/// +/// Note that particularly large alignments, while representable in this type, +/// are likely not to be supported by actual allocators and linkers. +#[unstable(feature = "ptr_alignment_type", issue = "102070")] +#[derive(Copy, Clone, PartialEq, Eq)] +#[repr(transparent)] +pub struct Alignment(AlignmentEnum); + +// Alignment is `repr(usize)`, but via extra steps. +const _: () = assert!(mem::size_of::() == mem::size_of::()); +const _: () = assert!(mem::align_of::() == mem::align_of::()); + +fn _alignment_can_be_structurally_matched(a: Alignment) -> bool { + matches!(a, Alignment::MIN) +} + +impl Alignment { + /// The smallest possible alignment, 1. + /// + /// All addresses are always aligned at least this much. + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_alignment_type)] + /// use std::ptr::Alignment; + /// + /// assert_eq!(Alignment::MIN.as_usize(), 1); + /// ``` + #[unstable(feature = "ptr_alignment_type", issue = "102070")] + pub const MIN: Self = Self(AlignmentEnum::_Align1Shl0); + + /// Returns the alignment for a type. + /// + /// This provides the same numerical value as [`mem::align_of`], + /// but in an `Alignment` instead of a `usize`. + #[unstable(feature = "ptr_alignment_type", issue = "102070")] + #[inline] + pub const fn of() -> Self { + // SAFETY: rustc ensures that type alignment is always a power of two. + unsafe { Alignment::new_unchecked(mem::align_of::()) } + } + + /// Creates an `Alignment` from a `usize`, or returns `None` if it's + /// not a power of two. + /// + /// Note that `0` is not a power of two, nor a valid alignment. + #[unstable(feature = "ptr_alignment_type", issue = "102070")] + #[inline] + pub const fn new(align: usize) -> Option { + if align.is_power_of_two() { + // SAFETY: Just checked it only has one bit set + Some(unsafe { Self::new_unchecked(align) }) + } else { + None + } + } + + /// Creates an `Alignment` from a power-of-two `usize`. + /// + /// # Safety + /// + /// `align` must be a power of two. + /// + /// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`. + /// It must *not* be zero. + #[unstable(feature = "ptr_alignment_type", issue = "102070")] + #[inline] + pub const unsafe fn new_unchecked(align: usize) -> Self { + assert_unsafe_precondition!( + check_language_ub, + "Alignment::new_unchecked requires a power of two", + (align: usize = align) => align.is_power_of_two() + ); + + // SAFETY: By precondition, this must be a power of two, and + // our variants encompass all possible powers of two. + unsafe { mem::transmute::(align) } + } + + /// Returns the alignment as a [`usize`]. + #[unstable(feature = "ptr_alignment_type", issue = "102070")] + #[inline] + pub const fn as_usize(self) -> usize { + self.0 as usize + } + + /// Returns the alignment as a [NonZero]<[usize]>. + #[unstable(feature = "ptr_alignment_type", issue = "102070")] + #[inline] + pub const fn as_nonzero(self) -> NonZero { + // SAFETY: All the discriminants are non-zero. + unsafe { NonZero::new_unchecked(self.as_usize()) } + } + + /// Returns the base-2 logarithm of the alignment. + /// + /// This is always exact, as `self` represents a power of two. + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_alignment_type)] + /// use std::ptr::Alignment; + /// + /// assert_eq!(Alignment::of::().log2(), 0); + /// assert_eq!(Alignment::new(1024).unwrap().log2(), 10); + /// ``` + #[unstable(feature = "ptr_alignment_type", issue = "102070")] + #[inline] + pub const fn log2(self) -> u32 { + self.as_nonzero().trailing_zeros() + } + + /// Returns a bit mask that can be used to match this alignment. + /// + /// This is equivalent to `!(self.as_usize() - 1)`. + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_alignment_type)] + /// #![feature(ptr_mask)] + /// use std::ptr::{Alignment, NonNull}; + /// + /// #[repr(align(1))] struct Align1(u8); + /// #[repr(align(2))] struct Align2(u16); + /// #[repr(align(4))] struct Align4(u32); + /// let one = >::dangling().as_ptr(); + /// let two = >::dangling().as_ptr(); + /// let four = >::dangling().as_ptr(); + /// + /// assert_eq!(four.mask(Alignment::of::().mask()), four); + /// assert_eq!(four.mask(Alignment::of::().mask()), four); + /// assert_eq!(four.mask(Alignment::of::().mask()), four); + /// assert_ne!(one.mask(Alignment::of::().mask()), one); + /// ``` + #[unstable(feature = "ptr_alignment_type", issue = "102070")] + #[inline] + pub const fn mask(self) -> usize { + // SAFETY: The alignment is always nonzero, and therefore decrementing won't overflow. + !(unsafe { self.as_usize().unchecked_sub(1) }) + } + + // FIXME(const-hack) Remove me once `Ord::max` is usable in const + pub(crate) const fn max(a: Self, b: Self) -> Self { + if a.as_usize() > b.as_usize() { a } else { b } + } +} + +#[unstable(feature = "ptr_alignment_type", issue = "102070")] +impl fmt::Debug for Alignment { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?} (1 << {:?})", self.as_nonzero(), self.log2()) + } +} + +#[unstable(feature = "ptr_alignment_type", issue = "102070")] +impl TryFrom> for Alignment { + type Error = num::TryFromIntError; + + #[inline] + fn try_from(align: NonZero) -> Result { + align.get().try_into() + } +} + +#[unstable(feature = "ptr_alignment_type", issue = "102070")] +impl TryFrom for Alignment { + type Error = num::TryFromIntError; + + #[inline] + fn try_from(align: usize) -> Result { + Self::new(align).ok_or(num::TryFromIntError(())) + } +} + +#[unstable(feature = "ptr_alignment_type", issue = "102070")] +impl From for NonZero { + #[inline] + fn from(align: Alignment) -> NonZero { + align.as_nonzero() + } +} + +#[unstable(feature = "ptr_alignment_type", issue = "102070")] +impl From for usize { + #[inline] + fn from(align: Alignment) -> usize { + align.as_usize() + } +} + +#[unstable(feature = "ptr_alignment_type", issue = "102070")] +impl cmp::Ord for Alignment { + #[inline] + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.as_nonzero().get().cmp(&other.as_nonzero().get()) + } +} + +#[unstable(feature = "ptr_alignment_type", issue = "102070")] +impl cmp::PartialOrd for Alignment { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +#[unstable(feature = "ptr_alignment_type", issue = "102070")] +impl hash::Hash for Alignment { + #[inline] + fn hash(&self, state: &mut H) { + self.as_nonzero().hash(state) + } +} + +/// Returns [`Alignment::MIN`], which is valid for any type. +#[unstable(feature = "ptr_alignment_type", issue = "102070")] +impl Default for Alignment { + fn default() -> Alignment { + Alignment::MIN + } +} + +#[cfg(target_pointer_width = "16")] +#[derive(Copy, Clone, PartialEq, Eq)] +#[repr(u16)] +enum AlignmentEnum { + _Align1Shl0 = 1 << 0, + _Align1Shl1 = 1 << 1, + _Align1Shl2 = 1 << 2, + _Align1Shl3 = 1 << 3, + _Align1Shl4 = 1 << 4, + _Align1Shl5 = 1 << 5, + _Align1Shl6 = 1 << 6, + _Align1Shl7 = 1 << 7, + _Align1Shl8 = 1 << 8, + _Align1Shl9 = 1 << 9, + _Align1Shl10 = 1 << 10, + _Align1Shl11 = 1 << 11, + _Align1Shl12 = 1 << 12, + _Align1Shl13 = 1 << 13, + _Align1Shl14 = 1 << 14, + _Align1Shl15 = 1 << 15, +} + +#[cfg(target_pointer_width = "32")] +#[derive(Copy, Clone, PartialEq, Eq)] +#[repr(u32)] +enum AlignmentEnum { + _Align1Shl0 = 1 << 0, + _Align1Shl1 = 1 << 1, + _Align1Shl2 = 1 << 2, + _Align1Shl3 = 1 << 3, + _Align1Shl4 = 1 << 4, + _Align1Shl5 = 1 << 5, + _Align1Shl6 = 1 << 6, + _Align1Shl7 = 1 << 7, + _Align1Shl8 = 1 << 8, + _Align1Shl9 = 1 << 9, + _Align1Shl10 = 1 << 10, + _Align1Shl11 = 1 << 11, + _Align1Shl12 = 1 << 12, + _Align1Shl13 = 1 << 13, + _Align1Shl14 = 1 << 14, + _Align1Shl15 = 1 << 15, + _Align1Shl16 = 1 << 16, + _Align1Shl17 = 1 << 17, + _Align1Shl18 = 1 << 18, + _Align1Shl19 = 1 << 19, + _Align1Shl20 = 1 << 20, + _Align1Shl21 = 1 << 21, + _Align1Shl22 = 1 << 22, + _Align1Shl23 = 1 << 23, + _Align1Shl24 = 1 << 24, + _Align1Shl25 = 1 << 25, + _Align1Shl26 = 1 << 26, + _Align1Shl27 = 1 << 27, + _Align1Shl28 = 1 << 28, + _Align1Shl29 = 1 << 29, + _Align1Shl30 = 1 << 30, + _Align1Shl31 = 1 << 31, +} + +#[cfg(target_pointer_width = "64")] +#[derive(Copy, Clone, PartialEq, Eq)] +#[repr(u64)] +enum AlignmentEnum { + _Align1Shl0 = 1 << 0, + _Align1Shl1 = 1 << 1, + _Align1Shl2 = 1 << 2, + _Align1Shl3 = 1 << 3, + _Align1Shl4 = 1 << 4, + _Align1Shl5 = 1 << 5, + _Align1Shl6 = 1 << 6, + _Align1Shl7 = 1 << 7, + _Align1Shl8 = 1 << 8, + _Align1Shl9 = 1 << 9, + _Align1Shl10 = 1 << 10, + _Align1Shl11 = 1 << 11, + _Align1Shl12 = 1 << 12, + _Align1Shl13 = 1 << 13, + _Align1Shl14 = 1 << 14, + _Align1Shl15 = 1 << 15, + _Align1Shl16 = 1 << 16, + _Align1Shl17 = 1 << 17, + _Align1Shl18 = 1 << 18, + _Align1Shl19 = 1 << 19, + _Align1Shl20 = 1 << 20, + _Align1Shl21 = 1 << 21, + _Align1Shl22 = 1 << 22, + _Align1Shl23 = 1 << 23, + _Align1Shl24 = 1 << 24, + _Align1Shl25 = 1 << 25, + _Align1Shl26 = 1 << 26, + _Align1Shl27 = 1 << 27, + _Align1Shl28 = 1 << 28, + _Align1Shl29 = 1 << 29, + _Align1Shl30 = 1 << 30, + _Align1Shl31 = 1 << 31, + _Align1Shl32 = 1 << 32, + _Align1Shl33 = 1 << 33, + _Align1Shl34 = 1 << 34, + _Align1Shl35 = 1 << 35, + _Align1Shl36 = 1 << 36, + _Align1Shl37 = 1 << 37, + _Align1Shl38 = 1 << 38, + _Align1Shl39 = 1 << 39, + _Align1Shl40 = 1 << 40, + _Align1Shl41 = 1 << 41, + _Align1Shl42 = 1 << 42, + _Align1Shl43 = 1 << 43, + _Align1Shl44 = 1 << 44, + _Align1Shl45 = 1 << 45, + _Align1Shl46 = 1 << 46, + _Align1Shl47 = 1 << 47, + _Align1Shl48 = 1 << 48, + _Align1Shl49 = 1 << 49, + _Align1Shl50 = 1 << 50, + _Align1Shl51 = 1 << 51, + _Align1Shl52 = 1 << 52, + _Align1Shl53 = 1 << 53, + _Align1Shl54 = 1 << 54, + _Align1Shl55 = 1 << 55, + _Align1Shl56 = 1 << 56, + _Align1Shl57 = 1 << 57, + _Align1Shl58 = 1 << 58, + _Align1Shl59 = 1 << 59, + _Align1Shl60 = 1 << 60, + _Align1Shl61 = 1 << 61, + _Align1Shl62 = 1 << 62, + _Align1Shl63 = 1 << 63, +} diff --git a/CoqOfRust/core/ptr/const_ptr.rs b/CoqOfRust/core/ptr/const_ptr.rs new file mode 100644 index 000000000..f100adecb --- /dev/null +++ b/CoqOfRust/core/ptr/const_ptr.rs @@ -0,0 +1,1717 @@ +use super::*; +use crate::cmp::Ordering::{Equal, Greater, Less}; +use crate::intrinsics::const_eval_select; +use crate::mem::SizedTypeProperties; +use crate::slice::{self, SliceIndex}; + +impl *const T { + /// Returns `true` if the pointer is null. + /// + /// Note that unsized types have many possible null pointers, as only the + /// raw data pointer is considered, not their length, vtable, etc. + /// Therefore, two pointers that are null may still not compare equal to + /// each other. + /// + /// ## Behavior during const evaluation + /// + /// When this function is used during const evaluation, it may return `false` for pointers + /// that turn out to be null at runtime. Specifically, when a pointer to some memory + /// is offset beyond its bounds in such a way that the resulting pointer is null, + /// the function will still return `false`. There is no way for CTFE to know + /// the absolute position of that memory, so we cannot tell if the pointer is + /// null or not. + /// + /// # Examples + /// + /// ``` + /// let s: &str = "Follow the rabbit"; + /// let ptr: *const u8 = s.as_ptr(); + /// assert!(!ptr.is_null()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] + #[rustc_diagnostic_item = "ptr_const_is_null"] + #[inline] + #[rustc_allow_const_fn_unstable(const_eval_select)] + pub const fn is_null(self) -> bool { + // Compare via a cast to a thin pointer, so fat pointers are only + // considering their "data" part for null-ness. + let ptr = self as *const u8; + const_eval_select!( + @capture { ptr: *const u8 } -> bool: + // This use of `const_raw_ptr_comparison` has been explicitly blessed by t-lang. + if const #[rustc_allow_const_fn_unstable(const_raw_ptr_comparison)] { + match (ptr).guaranteed_eq(null_mut()) { + Some(res) => res, + // To remain maximally convervative, we stop execution when we don't + // know whether the pointer is null or not. + // We can *not* return `false` here, that would be unsound in `NonNull::new`! + None => panic!("null-ness of this pointer cannot be determined in const context"), + } + } else { + ptr.addr() == 0 + } + ) + } + + /// Casts to a pointer of another type. + #[stable(feature = "ptr_cast", since = "1.38.0")] + #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")] + #[rustc_diagnostic_item = "const_ptr_cast"] + #[inline(always)] + pub const fn cast(self) -> *const U { + self as _ + } + + /// Uses the address value in a new pointer of another type. + /// + /// This operation will ignore the address part of its `meta` operand and discard existing + /// metadata of `self`. For pointers to a sized types (thin pointers), this has the same effect + /// as a simple cast. For pointers to an unsized type (fat pointers) this recombines the address + /// with new metadata such as slice lengths or `dyn`-vtable. + /// + /// The resulting pointer will have provenance of `self`. This operation is semantically the + /// same as creating a new pointer with the data pointer value of `self` but the metadata of + /// `meta`, being fat or thin depending on the `meta` operand. + /// + /// # Examples + /// + /// This function is primarily useful for enabling pointer arithmetic on potentially fat + /// pointers. The pointer is cast to a sized pointee to utilize offset operations and then + /// recombined with its own original metadata. + /// + /// ``` + /// #![feature(set_ptr_value)] + /// # use core::fmt::Debug; + /// let arr: [i32; 3] = [1, 2, 3]; + /// let mut ptr = arr.as_ptr() as *const dyn Debug; + /// let thin = ptr as *const u8; + /// unsafe { + /// ptr = thin.add(8).with_metadata_of(ptr); + /// # assert_eq!(*(ptr as *const i32), 3); + /// println!("{:?}", &*ptr); // will print "3" + /// } + /// ``` + /// + /// # *Incorrect* usage + /// + /// The provenance from pointers is *not* combined. The result must only be used to refer to the + /// address allowed by `self`. + /// + /// ```rust,no_run + /// #![feature(set_ptr_value)] + /// let x = 0u32; + /// let y = 1u32; + /// + /// let x = (&x) as *const u32; + /// let y = (&y) as *const u32; + /// + /// let offset = (x as usize - y as usize) / 4; + /// let bad = x.wrapping_add(offset).with_metadata_of(y); + /// + /// // This dereference is UB. The pointer only has provenance for `x` but points to `y`. + /// println!("{:?}", unsafe { &*bad }); + /// ``` + #[unstable(feature = "set_ptr_value", issue = "75091")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[inline] + pub const fn with_metadata_of(self, meta: *const U) -> *const U + where + U: ?Sized, + { + from_raw_parts::(self as *const (), metadata(meta)) + } + + /// Changes constness without changing the type. + /// + /// This is a bit safer than `as` because it wouldn't silently change the type if the code is + /// refactored. + #[stable(feature = "ptr_const_cast", since = "1.65.0")] + #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")] + #[rustc_diagnostic_item = "ptr_cast_mut"] + #[inline(always)] + pub const fn cast_mut(self) -> *mut T { + self as _ + } + + /// Gets the "address" portion of the pointer. + /// + /// This is similar to `self as usize`, except that the [provenance][crate::ptr#provenance] of + /// the pointer is discarded and not [exposed][crate::ptr#exposed-provenance]. This means that + /// casting the returned address back to a pointer yields a [pointer without + /// provenance][without_provenance], which is undefined behavior to dereference. To properly + /// restore the lost information and obtain a dereferenceable pointer, use + /// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. + /// + /// If using those APIs is not possible because there is no way to preserve a pointer with the + /// required provenance, then Strict Provenance might not be for you. Use pointer-integer casts + /// or [`expose_provenance`][pointer::expose_provenance] and [`with_exposed_provenance`][with_exposed_provenance] + /// instead. However, note that this makes your code less portable and less amenable to tools + /// that check for compliance with the Rust memory model. + /// + /// On most platforms this will produce a value with the same bytes as the original + /// pointer, because all the bytes are dedicated to describing the address. + /// Platforms which need to store additional information in the pointer may + /// perform a change of representation to produce a value containing only the address + /// portion of the pointer. What that means is up to the platform to define. + /// + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. + #[must_use] + #[inline(always)] + #[stable(feature = "strict_provenance", since = "1.84.0")] + pub fn addr(self) -> usize { + // A pointer-to-integer transmute currently has exactly the right semantics: it returns the + // address without exposing the provenance. Note that this is *not* a stable guarantee about + // transmute semantics, it relies on sysroot crates having special status. + // SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the + // provenance). + unsafe { mem::transmute(self.cast::<()>()) } + } + + /// Exposes the ["provenance"][crate::ptr#provenance] part of the pointer for future use in + /// [`with_exposed_provenance`] and returns the "address" portion. + /// + /// This is equivalent to `self as usize`, which semantically discards provenance information. + /// Furthermore, this (like the `as` cast) has the implicit side-effect of marking the + /// provenance as 'exposed', so on platforms that support it you can later call + /// [`with_exposed_provenance`] to reconstitute the original pointer including its provenance. + /// + /// Due to its inherent ambiguity, [`with_exposed_provenance`] may not be supported by tools + /// that help you to stay conformant with the Rust memory model. It is recommended to use + /// [Strict Provenance][crate::ptr#strict-provenance] APIs such as [`with_addr`][pointer::with_addr] + /// wherever possible, in which case [`addr`][pointer::addr] should be used instead of `expose_provenance`. + /// + /// On most platforms this will produce a value with the same bytes as the original pointer, + /// because all the bytes are dedicated to describing the address. Platforms which need to store + /// additional information in the pointer may not support this operation, since the 'expose' + /// side-effect which is required for [`with_exposed_provenance`] to work is typically not + /// available. + /// + /// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API. + /// + /// [`with_exposed_provenance`]: with_exposed_provenance + #[must_use] + #[inline(always)] + #[stable(feature = "exposed_provenance", since = "1.84.0")] + pub fn expose_provenance(self) -> usize { + self.cast::<()>() as usize + } + + /// Creates a new pointer with the given address and the [provenance][crate::ptr#provenance] of + /// `self`. + /// + /// This is similar to a `addr as *const T` cast, but copies + /// the *provenance* of `self` to the new pointer. + /// This avoids the inherent ambiguity of the unary cast. + /// + /// This is equivalent to using [`wrapping_offset`][pointer::wrapping_offset] to offset + /// `self` to the given address, and therefore has all the same capabilities and restrictions. + /// + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. + #[must_use] + #[inline] + #[stable(feature = "strict_provenance", since = "1.84.0")] + pub fn with_addr(self, addr: usize) -> Self { + // This should probably be an intrinsic to avoid doing any sort of arithmetic, but + // meanwhile, we can implement it with `wrapping_offset`, which preserves the pointer's + // provenance. + let self_addr = self.addr() as isize; + let dest_addr = addr as isize; + let offset = dest_addr.wrapping_sub(self_addr); + self.wrapping_byte_offset(offset) + } + + /// Creates a new pointer by mapping `self`'s address to a new one, preserving the + /// [provenance][crate::ptr#provenance] of `self`. + /// + /// This is a convenience for [`with_addr`][pointer::with_addr], see that method for details. + /// + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. + #[must_use] + #[inline] + #[stable(feature = "strict_provenance", since = "1.84.0")] + pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self { + self.with_addr(f(self.addr())) + } + + /// Decompose a (possibly wide) pointer into its data pointer and metadata components. + /// + /// The pointer can be later reconstructed with [`from_raw_parts`]. + #[unstable(feature = "ptr_metadata", issue = "81513")] + #[inline] + pub const fn to_raw_parts(self) -> (*const (), ::Metadata) { + (self.cast(), metadata(self)) + } + + /// Returns `None` if the pointer is null, or else returns a shared reference to + /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_ref`] + /// must be used instead. + /// + /// [`as_uninit_ref`]: #method.as_uninit_ref + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* the pointer is null *or* + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// + /// # Examples + /// + /// ``` + /// let ptr: *const u8 = &10u8 as *const u8; + /// + /// unsafe { + /// if let Some(val_back) = ptr.as_ref() { + /// assert_eq!(val_back, &10); + /// } + /// } + /// ``` + /// + /// # Null-unchecked version + /// + /// If you are sure the pointer can never be null and are looking for some kind of + /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can + /// dereference the pointer directly. + /// + /// ``` + /// let ptr: *const u8 = &10u8 as *const u8; + /// + /// unsafe { + /// let val_back = &*ptr; + /// assert_eq!(val_back, &10); + /// } + /// ``` + #[stable(feature = "ptr_as_ref", since = "1.9.0")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] + #[inline] + pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { + // SAFETY: the caller must guarantee that `self` is valid + // for a reference if it isn't null. + if self.is_null() { None } else { unsafe { Some(&*self) } } + } + + /// Returns a shared reference to the value behind the pointer. + /// If the pointer may be null or the value may be uninitialized, [`as_uninit_ref`] must be used instead. + /// If the pointer may be null, but the value is known to have been initialized, [`as_ref`] must be used instead. + /// + /// [`as_ref`]: #method.as_ref + /// [`as_uninit_ref`]: #method.as_uninit_ref + /// + /// # Safety + /// + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_as_ref_unchecked)] + /// let ptr: *const u8 = &10u8 as *const u8; + /// + /// unsafe { + /// assert_eq!(ptr.as_ref_unchecked(), &10); + /// } + /// ``` + // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. + #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[inline] + #[must_use] + pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { + // SAFETY: the caller must guarantee that `self` is valid for a reference + unsafe { &*self } + } + + /// Returns `None` if the pointer is null, or else returns a shared reference to + /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require + /// that the value has to be initialized. + /// + /// [`as_ref`]: #method.as_ref + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* the pointer is null *or* + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_as_uninit)] + /// + /// let ptr: *const u8 = &10u8 as *const u8; + /// + /// unsafe { + /// if let Some(val_back) = ptr.as_uninit_ref() { + /// assert_eq!(val_back.assume_init(), 10); + /// } + /// } + /// ``` + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> + where + T: Sized, + { + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a reference. + if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit) }) } + } + + /// Adds a signed offset to a pointer. + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined Behavior: + /// + /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without + /// "wrapping around"), must fit in an `isize`. + /// + /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. + /// + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. + /// + /// Consider using [`wrapping_offset`] instead if these constraints are + /// difficult to satisfy. The only advantage of this method is that it + /// enables more aggressive compiler optimizations. + /// + /// [`wrapping_offset`]: #method.wrapping_offset + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// let s: &str = "123"; + /// let ptr: *const u8 = s.as_ptr(); + /// + /// unsafe { + /// assert_eq!(*ptr.offset(1) as char, '2'); + /// assert_eq!(*ptr.offset(2) as char, '3'); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn offset(self, count: isize) -> *const T + where + T: Sized, + { + #[inline] + #[rustc_allow_const_fn_unstable(const_eval_select)] + const fn runtime_offset_nowrap(this: *const (), count: isize, size: usize) -> bool { + // We can use const_eval_select here because this is only for UB checks. + const_eval_select!( + @capture { this: *const (), count: isize, size: usize } -> bool: + if const { + true + } else { + // `size` is the size of a Rust type, so we know that + // `size <= isize::MAX` and thus `as` cast here is not lossy. + let Some(byte_offset) = count.checked_mul(size as isize) else { + return false; + }; + let (_, overflow) = this.addr().overflowing_add_signed(byte_offset); + !overflow + } + ) + } + + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::offset requires the address calculation to not overflow", + ( + this: *const () = self as *const (), + count: isize = count, + size: usize = size_of::(), + ) => runtime_offset_nowrap(this, count, size) + ); + + // SAFETY: the caller must uphold the safety contract for `offset`. + unsafe { intrinsics::offset(self, count) } + } + + /// Adds a signed offset in bytes to a pointer. + /// + /// `count` is in units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [offset][pointer::offset] on it. See that method for documentation + /// and safety requirements. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_offset(self, count: isize) -> Self { + // SAFETY: the caller must uphold the safety contract for `offset`. + unsafe { self.cast::().offset(count).with_metadata_of(self) } + } + + /// Adds a signed offset to a pointer using wrapping arithmetic. + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// This operation itself is always safe, but using the resulting pointer is not. + /// + /// The resulting pointer "remembers" the [allocated object] that `self` points to; it must not + /// be used to read or write other allocated objects. + /// + /// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z` + /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still + /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless + /// `x` and `y` point into the same allocated object. + /// + /// Compared to [`offset`], this method basically delays the requirement of staying within the + /// same allocated object: [`offset`] is immediate Undefined Behavior when crossing object + /// boundaries; `wrapping_offset` produces a pointer but still leads to Undefined Behavior if a + /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`offset`] + /// can be optimized better and is thus preferable in performance-sensitive code. + /// + /// The delayed check only considers the value of the pointer that was dereferenced, not the + /// intermediate values used during the computation of the final result. For example, + /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other + /// words, leaving the allocated object and then re-entering it later is permitted. + /// + /// [`offset`]: #method.offset + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// # use std::fmt::Write; + /// // Iterate using a raw pointer in increments of two elements + /// let data = [1u8, 2, 3, 4, 5]; + /// let mut ptr: *const u8 = data.as_ptr(); + /// let step = 2; + /// let end_rounded_up = ptr.wrapping_offset(6); + /// + /// let mut out = String::new(); + /// while ptr != end_rounded_up { + /// unsafe { + /// write!(&mut out, "{}, ", *ptr).unwrap(); + /// } + /// ptr = ptr.wrapping_offset(step); + /// } + /// assert_eq!(out.as_str(), "1, 3, 5, "); + /// ``` + #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[inline(always)] + pub const fn wrapping_offset(self, count: isize) -> *const T + where + T: Sized, + { + // SAFETY: the `arith_offset` intrinsic has no prerequisites to be called. + unsafe { intrinsics::arith_offset(self, count) } + } + + /// Adds a signed offset in bytes to a pointer using wrapping arithmetic. + /// + /// `count` is in units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [wrapping_offset][pointer::wrapping_offset] on it. See that method + /// for documentation. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + pub const fn wrapping_byte_offset(self, count: isize) -> Self { + self.cast::().wrapping_offset(count).with_metadata_of(self) + } + + /// Masks out bits of the pointer according to a mask. + /// + /// This is convenience for `ptr.map_addr(|a| a & mask)`. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + /// + /// ## Examples + /// + /// ``` + /// #![feature(ptr_mask)] + /// let v = 17_u32; + /// let ptr: *const u32 = &v; + /// + /// // `u32` is 4 bytes aligned, + /// // which means that lower 2 bits are always 0. + /// let tag_mask = 0b11; + /// let ptr_mask = !tag_mask; + /// + /// // We can store something in these lower bits + /// let tagged_ptr = ptr.map_addr(|a| a | 0b10); + /// + /// // Get the "tag" back + /// let tag = tagged_ptr.addr() & tag_mask; + /// assert_eq!(tag, 0b10); + /// + /// // Note that `tagged_ptr` is unaligned, it's UB to read from it. + /// // To get original pointer `mask` can be used: + /// let masked_ptr = tagged_ptr.mask(ptr_mask); + /// assert_eq!(unsafe { *masked_ptr }, 17); + /// ``` + #[unstable(feature = "ptr_mask", issue = "98290")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[inline(always)] + pub fn mask(self, mask: usize) -> *const T { + intrinsics::ptr_mask(self.cast::<()>(), mask).with_metadata_of(self) + } + + /// Calculates the distance between two pointers within the same allocation. The returned value is in + /// units of T: the distance in bytes divided by `mem::size_of::()`. + /// + /// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::() as isize)`, + /// except that it has a lot more opportunities for UB, in exchange for the compiler + /// better understanding what you are doing. + /// + /// The primary motivation of this method is for computing the `len` of an array/slice + /// of `T` that you are currently representing as a "start" and "end" pointer + /// (and "end" is "one past the end" of the array). + /// In that case, `end.offset_from(start)` gets you the length of the array. + /// + /// All of the following safety requirements are trivially satisfied for this usecase. + /// + /// [`offset`]: #method.offset + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined Behavior: + /// + /// * `self` and `origin` must either + /// + /// * point to the same address, or + /// * both be [derived from][crate::ptr#provenance] a pointer to the same [allocated object], and the memory range between + /// the two pointers must be in bounds of that object. (See below for an example.) + /// + /// * The distance between the pointers, in bytes, must be an exact multiple + /// of the size of `T`. + /// + /// As a consequence, the absolute distance between the pointers, in bytes, computed on + /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is + /// implied by the in-bounds requirement, and the fact that no allocated object can be larger + /// than `isize::MAX` bytes. + /// + /// The requirement for pointers to be derived from the same allocated object is primarily + /// needed for `const`-compatibility: the distance between pointers into *different* allocated + /// objects is not known at compile-time. However, the requirement also exists at + /// runtime and may be exploited by optimizations. If you wish to compute the difference between + /// pointers that are not guaranteed to be from the same allocation, use `(self as isize - + /// origin as isize) / mem::size_of::()`. + // FIXME: recommend `addr()` instead of `as usize` once that is stable. + /// + /// [`add`]: #method.add + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Panics + /// + /// This function panics if `T` is a Zero-Sized Type ("ZST"). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = [0; 5]; + /// let ptr1: *const i32 = &a[1]; + /// let ptr2: *const i32 = &a[3]; + /// unsafe { + /// assert_eq!(ptr2.offset_from(ptr1), 2); + /// assert_eq!(ptr1.offset_from(ptr2), -2); + /// assert_eq!(ptr1.offset(2), ptr2); + /// assert_eq!(ptr2.offset(-2), ptr1); + /// } + /// ``` + /// + /// *Incorrect* usage: + /// + /// ```rust,no_run + /// let ptr1 = Box::into_raw(Box::new(0u8)) as *const u8; + /// let ptr2 = Box::into_raw(Box::new(1u8)) as *const u8; + /// let diff = (ptr2 as isize).wrapping_sub(ptr1 as isize); + /// // Make ptr2_other an "alias" of ptr2.add(1), but derived from ptr1. + /// let ptr2_other = (ptr1 as *const u8).wrapping_offset(diff).wrapping_offset(1); + /// assert_eq!(ptr2 as usize, ptr2_other as usize); + /// // Since ptr2_other and ptr2 are derived from pointers to different objects, + /// // computing their offset is undefined behavior, even though + /// // they point to addresses that are in-bounds of the same object! + /// unsafe { + /// let one = ptr2_other.offset_from(ptr2); // Undefined Behavior! ⚠️ + /// } + /// ``` + #[stable(feature = "ptr_offset_from", since = "1.47.0")] + #[rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn offset_from(self, origin: *const T) -> isize + where + T: Sized, + { + let pointee_size = mem::size_of::(); + assert!(0 < pointee_size && pointee_size <= isize::MAX as usize); + // SAFETY: the caller must uphold the safety contract for `ptr_offset_from`. + unsafe { intrinsics::ptr_offset_from(self, origin) } + } + + /// Calculates the distance between two pointers within the same allocation. The returned value is in + /// units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`offset_from`][pointer::offset_from] on it. See that method for + /// documentation and safety requirements. + /// + /// For non-`Sized` pointees this operation considers only the data pointers, + /// ignoring the metadata. + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_offset_from(self, origin: *const U) -> isize { + // SAFETY: the caller must uphold the safety contract for `offset_from`. + unsafe { self.cast::().offset_from(origin.cast::()) } + } + + /// Calculates the distance between two pointers within the same allocation, *where it's known that + /// `self` is equal to or greater than `origin`*. The returned value is in + /// units of T: the distance in bytes is divided by `mem::size_of::()`. + /// + /// This computes the same value that [`offset_from`](#method.offset_from) + /// would compute, but with the added precondition that the offset is + /// guaranteed to be non-negative. This method is equivalent to + /// `usize::try_from(self.offset_from(origin)).unwrap_unchecked()`, + /// but it provides slightly more information to the optimizer, which can + /// sometimes allow it to optimize slightly better with some backends. + /// + /// This method can be thought of as recovering the `count` that was passed + /// to [`add`](#method.add) (or, with the parameters in the other order, + /// to [`sub`](#method.sub)). The following are all equivalent, assuming + /// that their safety preconditions are met: + /// ```rust + /// # #![feature(ptr_sub_ptr)] + /// # unsafe fn blah(ptr: *const i32, origin: *const i32, count: usize) -> bool { + /// ptr.sub_ptr(origin) == count + /// # && + /// origin.add(count) == ptr + /// # && + /// ptr.sub(count) == origin + /// # } + /// ``` + /// + /// # Safety + /// + /// - The distance between the pointers must be non-negative (`self >= origin`) + /// + /// - *All* the safety conditions of [`offset_from`](#method.offset_from) + /// apply to this method as well; see it for the full details. + /// + /// Importantly, despite the return type of this method being able to represent + /// a larger offset, it's still *not permitted* to pass pointers which differ + /// by more than `isize::MAX` *bytes*. As such, the result of this method will + /// always be less than or equal to `isize::MAX as usize`. + /// + /// # Panics + /// + /// This function panics if `T` is a Zero-Sized Type ("ZST"). + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_sub_ptr)] + /// + /// let a = [0; 5]; + /// let ptr1: *const i32 = &a[1]; + /// let ptr2: *const i32 = &a[3]; + /// unsafe { + /// assert_eq!(ptr2.sub_ptr(ptr1), 2); + /// assert_eq!(ptr1.add(2), ptr2); + /// assert_eq!(ptr2.sub(2), ptr1); + /// assert_eq!(ptr2.sub_ptr(ptr2), 0); + /// } + /// + /// // This would be incorrect, as the pointers are not correctly ordered: + /// // ptr1.sub_ptr(ptr2) + /// ``` + #[unstable(feature = "ptr_sub_ptr", issue = "95892")] + #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn sub_ptr(self, origin: *const T) -> usize + where + T: Sized, + { + #[rustc_allow_const_fn_unstable(const_eval_select)] + const fn runtime_ptr_ge(this: *const (), origin: *const ()) -> bool { + const_eval_select!( + @capture { this: *const (), origin: *const () } -> bool: + if const { + true + } else { + this >= origin + } + ) + } + + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::sub_ptr requires `self >= origin`", + ( + this: *const () = self as *const (), + origin: *const () = origin as *const (), + ) => runtime_ptr_ge(this, origin) + ); + + let pointee_size = mem::size_of::(); + assert!(0 < pointee_size && pointee_size <= isize::MAX as usize); + // SAFETY: the caller must uphold the safety contract for `ptr_offset_from_unsigned`. + unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) } + } + + /// Calculates the distance between two pointers within the same allocation, *where it's known that + /// `self` is equal to or greater than `origin`*. The returned value is in + /// units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`sub_ptr`][pointer::sub_ptr] on it. See that method for + /// documentation and safety requirements. + /// + /// For non-`Sized` pointees this operation considers only the data pointers, + /// ignoring the metadata. + #[unstable(feature = "ptr_sub_ptr", issue = "95892")] + #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_sub_ptr(self, origin: *const U) -> usize { + // SAFETY: the caller must uphold the safety contract for `sub_ptr`. + unsafe { self.cast::().sub_ptr(origin.cast::()) } + } + + /// Returns whether two pointers are guaranteed to be equal. + /// + /// At runtime this function behaves like `Some(self == other)`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine equality of two pointers, so this function may + /// spuriously return `None` for pointers that later actually turn out to have its equality known. + /// But when it returns `Some`, the pointers' equality is guaranteed to be known. + /// + /// The return value may change from `Some` to `None` and vice versa depending on the compiler + /// version and unsafe code must not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `None` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + pub const fn guaranteed_eq(self, other: *const T) -> Option + where + T: Sized, + { + match intrinsics::ptr_guaranteed_cmp(self, other) { + 2 => None, + other => Some(other == 1), + } + } + + /// Returns whether two pointers are guaranteed to be inequal. + /// + /// At runtime this function behaves like `Some(self != other)`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine inequality of two pointers, so this function may + /// spuriously return `None` for pointers that later actually turn out to have its inequality known. + /// But when it returns `Some`, the pointers' inequality is guaranteed to be known. + /// + /// The return value may change from `Some` to `None` and vice versa depending on the compiler + /// version and unsafe code must not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `None` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + pub const fn guaranteed_ne(self, other: *const T) -> Option + where + T: Sized, + { + match self.guaranteed_eq(other) { + None => None, + Some(eq) => Some(!eq), + } + } + + /// Adds an unsigned offset to a pointer. + /// + /// This can only move the pointer forward (or not move it). If you need to move forward or + /// backward depending on the value, then you might want [`offset`](#method.offset) instead + /// which takes a signed offset. + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined Behavior: + /// + /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without + /// "wrapping around"), must fit in an `isize`. + /// + /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. + /// + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. + /// + /// Consider using [`wrapping_add`] instead if these constraints are + /// difficult to satisfy. The only advantage of this method is that it + /// enables more aggressive compiler optimizations. + /// + /// [`wrapping_add`]: #method.wrapping_add + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// let s: &str = "123"; + /// let ptr: *const u8 = s.as_ptr(); + /// + /// unsafe { + /// assert_eq!(*ptr.add(1), b'2'); + /// assert_eq!(*ptr.add(2), b'3'); + /// } + /// ``` + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn add(self, count: usize) -> Self + where + T: Sized, + { + #[cfg(debug_assertions)] + #[inline] + #[rustc_allow_const_fn_unstable(const_eval_select)] + const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool { + const_eval_select!( + @capture { this: *const (), count: usize, size: usize } -> bool: + if const { + true + } else { + let Some(byte_offset) = count.checked_mul(size) else { + return false; + }; + let (_, overflow) = this.addr().overflowing_add(byte_offset); + byte_offset <= (isize::MAX as usize) && !overflow + } + ) + } + + #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild. + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::add requires that the address calculation does not overflow", + ( + this: *const () = self as *const (), + count: usize = count, + size: usize = size_of::(), + ) => runtime_add_nowrap(this, count, size) + ); + + // SAFETY: the caller must uphold the safety contract for `offset`. + unsafe { intrinsics::offset(self, count) } + } + + /// Adds an unsigned offset in bytes to a pointer. + /// + /// `count` is in units of bytes. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [add][pointer::add] on it. See that method for documentation + /// and safety requirements. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_add(self, count: usize) -> Self { + // SAFETY: the caller must uphold the safety contract for `add`. + unsafe { self.cast::().add(count).with_metadata_of(self) } + } + + /// Subtracts an unsigned offset from a pointer. + /// + /// This can only move the pointer backward (or not move it). If you need to move forward or + /// backward depending on the value, then you might want [`offset`](#method.offset) instead + /// which takes a signed offset. + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined Behavior: + /// + /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without + /// "wrapping around"), must fit in an `isize`. + /// + /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. + /// + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. + /// + /// Consider using [`wrapping_sub`] instead if these constraints are + /// difficult to satisfy. The only advantage of this method is that it + /// enables more aggressive compiler optimizations. + /// + /// [`wrapping_sub`]: #method.wrapping_sub + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// let s: &str = "123"; + /// + /// unsafe { + /// let end: *const u8 = s.as_ptr().add(3); + /// assert_eq!(*end.sub(1), b'3'); + /// assert_eq!(*end.sub(2), b'2'); + /// } + /// ``` + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn sub(self, count: usize) -> Self + where + T: Sized, + { + #[cfg(debug_assertions)] + #[inline] + #[rustc_allow_const_fn_unstable(const_eval_select)] + const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool { + const_eval_select!( + @capture { this: *const (), count: usize, size: usize } -> bool: + if const { + true + } else { + let Some(byte_offset) = count.checked_mul(size) else { + return false; + }; + byte_offset <= (isize::MAX as usize) && this.addr() >= byte_offset + } + ) + } + + #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild. + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::sub requires that the address calculation does not overflow", + ( + this: *const () = self as *const (), + count: usize = count, + size: usize = size_of::(), + ) => runtime_sub_nowrap(this, count, size) + ); + + if T::IS_ZST { + // Pointer arithmetic does nothing when the pointee is a ZST. + self + } else { + // SAFETY: the caller must uphold the safety contract for `offset`. + // Because the pointee is *not* a ZST, that means that `count` is + // at most `isize::MAX`, and thus the negation cannot overflow. + unsafe { intrinsics::offset(self, intrinsics::unchecked_sub(0, count as isize)) } + } + } + + /// Subtracts an unsigned offset in bytes from a pointer. + /// + /// `count` is in units of bytes. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [sub][pointer::sub] on it. See that method for documentation + /// and safety requirements. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_sub(self, count: usize) -> Self { + // SAFETY: the caller must uphold the safety contract for `sub`. + unsafe { self.cast::().sub(count).with_metadata_of(self) } + } + + /// Adds an unsigned offset to a pointer using wrapping arithmetic. + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// This operation itself is always safe, but using the resulting pointer is not. + /// + /// The resulting pointer "remembers" the [allocated object] that `self` points to; it must not + /// be used to read or write other allocated objects. + /// + /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z` + /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still + /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless + /// `x` and `y` point into the same allocated object. + /// + /// Compared to [`add`], this method basically delays the requirement of staying within the + /// same allocated object: [`add`] is immediate Undefined Behavior when crossing object + /// boundaries; `wrapping_add` produces a pointer but still leads to Undefined Behavior if a + /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`add`] + /// can be optimized better and is thus preferable in performance-sensitive code. + /// + /// The delayed check only considers the value of the pointer that was dereferenced, not the + /// intermediate values used during the computation of the final result. For example, + /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the + /// allocated object and then re-entering it later is permitted. + /// + /// [`add`]: #method.add + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// # use std::fmt::Write; + /// // Iterate using a raw pointer in increments of two elements + /// let data = [1u8, 2, 3, 4, 5]; + /// let mut ptr: *const u8 = data.as_ptr(); + /// let step = 2; + /// let end_rounded_up = ptr.wrapping_add(6); + /// + /// let mut out = String::new(); + /// while ptr != end_rounded_up { + /// unsafe { + /// write!(&mut out, "{}, ", *ptr).unwrap(); + /// } + /// ptr = ptr.wrapping_add(step); + /// } + /// assert_eq!(out, "1, 3, 5, "); + /// ``` + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[inline(always)] + pub const fn wrapping_add(self, count: usize) -> Self + where + T: Sized, + { + self.wrapping_offset(count as isize) + } + + /// Adds an unsigned offset in bytes to a pointer using wrapping arithmetic. + /// + /// `count` is in units of bytes. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [wrapping_add][pointer::wrapping_add] on it. See that method for documentation. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + pub const fn wrapping_byte_add(self, count: usize) -> Self { + self.cast::().wrapping_add(count).with_metadata_of(self) + } + + /// Subtracts an unsigned offset from a pointer using wrapping arithmetic. + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// This operation itself is always safe, but using the resulting pointer is not. + /// + /// The resulting pointer "remembers" the [allocated object] that `self` points to; it must not + /// be used to read or write other allocated objects. + /// + /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z` + /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still + /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless + /// `x` and `y` point into the same allocated object. + /// + /// Compared to [`sub`], this method basically delays the requirement of staying within the + /// same allocated object: [`sub`] is immediate Undefined Behavior when crossing object + /// boundaries; `wrapping_sub` produces a pointer but still leads to Undefined Behavior if a + /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`sub`] + /// can be optimized better and is thus preferable in performance-sensitive code. + /// + /// The delayed check only considers the value of the pointer that was dereferenced, not the + /// intermediate values used during the computation of the final result. For example, + /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the + /// allocated object and then re-entering it later is permitted. + /// + /// [`sub`]: #method.sub + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// # use std::fmt::Write; + /// // Iterate using a raw pointer in increments of two elements (backwards) + /// let data = [1u8, 2, 3, 4, 5]; + /// let mut ptr: *const u8 = data.as_ptr(); + /// let start_rounded_down = ptr.wrapping_sub(2); + /// ptr = ptr.wrapping_add(4); + /// let step = 2; + /// let mut out = String::new(); + /// while ptr != start_rounded_down { + /// unsafe { + /// write!(&mut out, "{}, ", *ptr).unwrap(); + /// } + /// ptr = ptr.wrapping_sub(step); + /// } + /// assert_eq!(out, "5, 3, 1, "); + /// ``` + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[inline(always)] + pub const fn wrapping_sub(self, count: usize) -> Self + where + T: Sized, + { + self.wrapping_offset((count as isize).wrapping_neg()) + } + + /// Subtracts an unsigned offset in bytes from a pointer using wrapping arithmetic. + /// + /// `count` is in units of bytes. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [wrapping_sub][pointer::wrapping_sub] on it. See that method for documentation. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + pub const fn wrapping_byte_sub(self, count: usize) -> Self { + self.cast::().wrapping_sub(count).with_metadata_of(self) + } + + /// Reads the value from `self` without moving it. This leaves the + /// memory in `self` unchanged. + /// + /// See [`ptr::read`] for safety concerns and examples. + /// + /// [`ptr::read`]: crate::ptr::read() + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn read(self) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `read`. + unsafe { read(self) } + } + + /// Performs a volatile read of the value from `self` without moving it. This + /// leaves the memory in `self` unchanged. + /// + /// Volatile operations are intended to act on I/O memory, and are guaranteed + /// to not be elided or reordered by the compiler across other volatile + /// operations. + /// + /// See [`ptr::read_volatile`] for safety concerns and examples. + /// + /// [`ptr::read_volatile`]: crate::ptr::read_volatile() + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn read_volatile(self) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `read_volatile`. + unsafe { read_volatile(self) } + } + + /// Reads the value from `self` without moving it. This leaves the + /// memory in `self` unchanged. + /// + /// Unlike `read`, the pointer may be unaligned. + /// + /// See [`ptr::read_unaligned`] for safety concerns and examples. + /// + /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned() + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn read_unaligned(self) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `read_unaligned`. + unsafe { read_unaligned(self) } + } + + /// Copies `count * size_of` bytes from `self` to `dest`. The source + /// and destination may overlap. + /// + /// NOTE: this has the *same* argument order as [`ptr::copy`]. + /// + /// See [`ptr::copy`] for safety concerns and examples. + /// + /// [`ptr::copy`]: crate::ptr::copy() + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn copy_to(self, dest: *mut T, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `copy`. + unsafe { copy(self, dest, count) } + } + + /// Copies `count * size_of` bytes from `self` to `dest`. The source + /// and destination may *not* overlap. + /// + /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`]. + /// + /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. + /// + /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `copy_nonoverlapping`. + unsafe { copy_nonoverlapping(self, dest, count) } + } + + /// Computes the offset that needs to be applied to the pointer in order to make it aligned to + /// `align`. + /// + /// If it is not possible to align the pointer, the implementation returns + /// `usize::MAX`. + /// + /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be + /// used with the `wrapping_add` method. + /// + /// There are no guarantees whatsoever that offsetting the pointer will not overflow or go + /// beyond the allocation that the pointer points into. It is up to the caller to ensure that + /// the returned offset is correct in all terms other than alignment. + /// + /// # Panics + /// + /// The function panics if `align` is not a power-of-two. + /// + /// # Examples + /// + /// Accessing adjacent `u8` as `u16` + /// + /// ``` + /// use std::mem::align_of; + /// + /// # unsafe { + /// let x = [5_u8, 6, 7, 8, 9]; + /// let ptr = x.as_ptr(); + /// let offset = ptr.align_offset(align_of::()); + /// + /// if offset < x.len() - 1 { + /// let u16_ptr = ptr.add(offset).cast::(); + /// assert!(*u16_ptr == u16::from_ne_bytes([5, 6]) || *u16_ptr == u16::from_ne_bytes([6, 7])); + /// } else { + /// // while the pointer can be aligned via `offset`, it would point + /// // outside the allocation + /// } + /// # } + /// ``` + #[must_use] + #[inline] + #[stable(feature = "align_offset", since = "1.36.0")] + pub fn align_offset(self, align: usize) -> usize + where + T: Sized, + { + if !align.is_power_of_two() { + panic!("align_offset: align is not a power-of-two"); + } + + // SAFETY: `align` has been checked to be a power of 2 above + let ret = unsafe { align_offset(self, align) }; + + // Inform Miri that we want to consider the resulting pointer to be suitably aligned. + #[cfg(miri)] + if ret != usize::MAX { + intrinsics::miri_promise_symbolic_alignment(self.wrapping_add(ret).cast(), align); + } + + ret + } + + /// Returns whether the pointer is properly aligned for `T`. + /// + /// # Examples + /// + /// ``` + /// // On some platforms, the alignment of i32 is less than 4. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// + /// let data = AlignedI32(42); + /// let ptr = &data as *const AlignedI32; + /// + /// assert!(ptr.is_aligned()); + /// assert!(!ptr.wrapping_byte_add(1).is_aligned()); + /// ``` + #[must_use] + #[inline] + #[stable(feature = "pointer_is_aligned", since = "1.79.0")] + pub fn is_aligned(self) -> bool + where + T: Sized, + { + self.is_aligned_to(mem::align_of::()) + } + + /// Returns whether the pointer is aligned to `align`. + /// + /// For non-`Sized` pointees this operation considers only the data pointer, + /// ignoring the metadata. + /// + /// # Panics + /// + /// The function panics if `align` is not a power-of-two (this includes 0). + /// + /// # Examples + /// + /// ``` + /// #![feature(pointer_is_aligned_to)] + /// + /// // On some platforms, the alignment of i32 is less than 4. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// + /// let data = AlignedI32(42); + /// let ptr = &data as *const AlignedI32; + /// + /// assert!(ptr.is_aligned_to(1)); + /// assert!(ptr.is_aligned_to(2)); + /// assert!(ptr.is_aligned_to(4)); + /// + /// assert!(ptr.wrapping_byte_add(2).is_aligned_to(2)); + /// assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4)); + /// + /// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8)); + /// ``` + #[must_use] + #[inline] + #[unstable(feature = "pointer_is_aligned_to", issue = "96284")] + pub fn is_aligned_to(self, align: usize) -> bool { + if !align.is_power_of_two() { + panic!("is_aligned_to: align is not a power-of-two"); + } + + self.addr() & (align - 1) == 0 + } +} + +impl *const [T] { + /// Returns the length of a raw slice. + /// + /// The returned value is the number of **elements**, not the number of bytes. + /// + /// This function is safe, even when the raw slice cannot be cast to a slice + /// reference because the pointer is null or unaligned. + /// + /// # Examples + /// + /// ```rust + /// use std::ptr; + /// + /// let slice: *const [i8] = ptr::slice_from_raw_parts(ptr::null(), 3); + /// assert_eq!(slice.len(), 3); + /// ``` + #[inline] + #[stable(feature = "slice_ptr_len", since = "1.79.0")] + #[rustc_const_stable(feature = "const_slice_ptr_len", since = "1.79.0")] + pub const fn len(self) -> usize { + metadata(self) + } + + /// Returns `true` if the raw slice has a length of 0. + /// + /// # Examples + /// + /// ``` + /// use std::ptr; + /// + /// let slice: *const [i8] = ptr::slice_from_raw_parts(ptr::null(), 3); + /// assert!(!slice.is_empty()); + /// ``` + #[inline(always)] + #[stable(feature = "slice_ptr_len", since = "1.79.0")] + #[rustc_const_stable(feature = "const_slice_ptr_len", since = "1.79.0")] + pub const fn is_empty(self) -> bool { + self.len() == 0 + } + + /// Returns a raw pointer to the slice's buffer. + /// + /// This is equivalent to casting `self` to `*const T`, but more type-safe. + /// + /// # Examples + /// + /// ```rust + /// #![feature(slice_ptr_get)] + /// use std::ptr; + /// + /// let slice: *const [i8] = ptr::slice_from_raw_parts(ptr::null(), 3); + /// assert_eq!(slice.as_ptr(), ptr::null()); + /// ``` + #[inline] + #[unstable(feature = "slice_ptr_get", issue = "74265")] + pub const fn as_ptr(self) -> *const T { + self as *const T + } + + /// Gets a raw pointer to the underlying array. + /// + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_array(self) -> Option<*const [T; N]> { + if self.len() == N { + let me = self.as_ptr() as *const [T; N]; + Some(me) + } else { + None + } + } + + /// Returns a raw pointer to an element or subslice, without doing bounds + /// checking. + /// + /// Calling this method with an out-of-bounds index or when `self` is not dereferenceable + /// is *[undefined behavior]* even if the resulting pointer is not used. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_ptr_get)] + /// + /// let x = &[1, 2, 4] as *const [i32]; + /// + /// unsafe { + /// assert_eq!(x.get_unchecked(1), x.as_ptr().add(1)); + /// } + /// ``` + #[unstable(feature = "slice_ptr_get", issue = "74265")] + #[inline] + pub unsafe fn get_unchecked(self, index: I) -> *const I::Output + where + I: SliceIndex<[T]>, + { + // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. + unsafe { index.get_unchecked(self) } + } + + /// Returns `None` if the pointer is null, or else returns a shared slice to + /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require + /// that the value has to be initialized. + /// + /// [`as_ref`]: #method.as_ref + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* the pointer is null *or* + /// all of the following is true: + /// + /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::()` many bytes, + /// and it must be properly aligned. This means in particular: + /// + /// * The entire memory range of this slice must be contained within a single [allocated object]! + /// Slices can never span across multiple allocated objects. + /// + /// * The pointer must be aligned even for zero-length slices. One + /// reason for this is that enum layout optimizations may rely on references + /// (including slices of any length) being aligned and non-null to distinguish + /// them from other data. You can obtain a pointer that is usable as `data` + /// for zero-length slices using [`NonNull::dangling()`]. + /// + /// * The total size `ptr.len() * mem::size_of::()` of the slice must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, while this reference exists, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// + /// See also [`slice::from_raw_parts`][]. + /// + /// [valid]: crate::ptr#safety + /// [allocated object]: crate::ptr#allocated-object + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { + if self.is_null() { + None + } else { + // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`. + Some(unsafe { slice::from_raw_parts(self as *const MaybeUninit, self.len()) }) + } + } +} + +impl *const [T; N] { + /// Returns a raw pointer to the array's buffer. + /// + /// This is equivalent to casting `self` to `*const T`, but more type-safe. + /// + /// # Examples + /// + /// ```rust + /// #![feature(array_ptr_get)] + /// use std::ptr; + /// + /// let arr: *const [i8; 3] = ptr::null(); + /// assert_eq!(arr.as_ptr(), ptr::null()); + /// ``` + #[inline] + #[unstable(feature = "array_ptr_get", issue = "119834")] + pub const fn as_ptr(self) -> *const T { + self as *const T + } + + /// Returns a raw pointer to a slice containing the entire array. + /// + /// # Examples + /// + /// ``` + /// #![feature(array_ptr_get)] + /// + /// let arr: *const [i32; 3] = &[1, 2, 4] as *const [i32; 3]; + /// let slice: *const [i32] = arr.as_slice(); + /// assert_eq!(slice.len(), 3); + /// ``` + #[inline] + #[unstable(feature = "array_ptr_get", issue = "119834")] + pub const fn as_slice(self) -> *const [T] { + self + } +} + +// Equality for pointers +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for *const T { + #[inline] + #[allow(ambiguous_wide_pointer_comparisons)] + fn eq(&self, other: &*const T) -> bool { + *self == *other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for *const T {} + +// Comparison for pointers +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for *const T { + #[inline] + #[allow(ambiguous_wide_pointer_comparisons)] + fn cmp(&self, other: &*const T) -> Ordering { + if self < other { + Less + } else if self == other { + Equal + } else { + Greater + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for *const T { + #[inline] + #[allow(ambiguous_wide_pointer_comparisons)] + fn partial_cmp(&self, other: &*const T) -> Option { + Some(self.cmp(other)) + } + + #[inline] + #[allow(ambiguous_wide_pointer_comparisons)] + fn lt(&self, other: &*const T) -> bool { + *self < *other + } + + #[inline] + #[allow(ambiguous_wide_pointer_comparisons)] + fn le(&self, other: &*const T) -> bool { + *self <= *other + } + + #[inline] + #[allow(ambiguous_wide_pointer_comparisons)] + fn gt(&self, other: &*const T) -> bool { + *self > *other + } + + #[inline] + #[allow(ambiguous_wide_pointer_comparisons)] + fn ge(&self, other: &*const T) -> bool { + *self >= *other + } +} diff --git a/CoqOfRust/core/ptr/metadata.rs b/CoqOfRust/core/ptr/metadata.rs new file mode 100644 index 000000000..ae9810e55 --- /dev/null +++ b/CoqOfRust/core/ptr/metadata.rs @@ -0,0 +1,257 @@ +#![unstable(feature = "ptr_metadata", issue = "81513")] + +use crate::fmt; +use crate::hash::{Hash, Hasher}; +use crate::intrinsics::{aggregate_raw_ptr, ptr_metadata}; +use crate::marker::Freeze; +use crate::ptr::NonNull; + +/// Provides the pointer metadata type of any pointed-to type. +/// +/// # Pointer metadata +/// +/// Raw pointer types and reference types in Rust can be thought of as made of two parts: +/// a data pointer that contains the memory address of the value, and some metadata. +/// +/// For statically-sized types (that implement the `Sized` traits) +/// as well as for `extern` types, +/// pointers are said to be “thin”: metadata is zero-sized and its type is `()`. +/// +/// Pointers to [dynamically-sized types][dst] are said to be “wide” or “fat”, +/// they have non-zero-sized metadata: +/// +/// * For structs whose last field is a DST, metadata is the metadata for the last field +/// * For the `str` type, metadata is the length in bytes as `usize` +/// * For slice types like `[T]`, metadata is the length in items as `usize` +/// * For trait objects like `dyn SomeTrait`, metadata is [`DynMetadata`][DynMetadata] +/// (e.g. `DynMetadata`) +/// +/// In the future, the Rust language may gain new kinds of types +/// that have different pointer metadata. +/// +/// [dst]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#dynamically-sized-types-dsts +/// +/// +/// # The `Pointee` trait +/// +/// The point of this trait is its `Metadata` associated type, +/// which is `()` or `usize` or `DynMetadata<_>` as described above. +/// It is automatically implemented for every type. +/// It can be assumed to be implemented in a generic context, even without a corresponding bound. +/// +/// +/// # Usage +/// +/// Raw pointers can be decomposed into the data pointer and metadata components +/// with their [`to_raw_parts`] method. +/// +/// Alternatively, metadata alone can be extracted with the [`metadata`] function. +/// A reference can be passed to [`metadata`] and implicitly coerced. +/// +/// A (possibly-wide) pointer can be put back together from its data pointer and metadata +/// with [`from_raw_parts`] or [`from_raw_parts_mut`]. +/// +/// [`to_raw_parts`]: *const::to_raw_parts +#[lang = "pointee_trait"] +#[rustc_deny_explicit_impl(implement_via_object = false)] +pub trait Pointee { + /// The type for metadata in pointers and references to `Self`. + #[lang = "metadata_type"] + // NOTE: Keep trait bounds in `static_assert_expected_bounds_for_metadata` + // in `library/core/src/ptr/metadata.rs` + // in sync with those here: + type Metadata: fmt::Debug + Copy + Send + Sync + Ord + Hash + Unpin + Freeze; +} + +/// Pointers to types implementing this trait alias are “thin”. +/// +/// This includes statically-`Sized` types and `extern` types. +/// +/// # Example +/// +/// ```rust +/// #![feature(ptr_metadata)] +/// +/// fn this_never_panics() { +/// assert_eq!(std::mem::size_of::<&T>(), std::mem::size_of::()) +/// } +/// ``` +#[unstable(feature = "ptr_metadata", issue = "81513")] +// NOTE: don’t stabilize this before trait aliases are stable in the language? +pub trait Thin = Pointee; + +/// Extracts the metadata component of a pointer. +/// +/// Values of type `*mut T`, `&T`, or `&mut T` can be passed directly to this function +/// as they implicitly coerce to `*const T`. +/// +/// # Example +/// +/// ``` +/// #![feature(ptr_metadata)] +/// +/// assert_eq!(std::ptr::metadata("foo"), 3_usize); +/// ``` +#[inline] +pub const fn metadata(ptr: *const T) -> ::Metadata { + ptr_metadata(ptr) +} + +/// Forms a (possibly-wide) raw pointer from a data pointer and metadata. +/// +/// This function is safe but the returned pointer is not necessarily safe to dereference. +/// For slices, see the documentation of [`slice::from_raw_parts`] for safety requirements. +/// For trait objects, the metadata must come from a pointer to the same underlying erased type. +/// +/// [`slice::from_raw_parts`]: crate::slice::from_raw_parts +#[unstable(feature = "ptr_metadata", issue = "81513")] +#[inline] +pub const fn from_raw_parts( + data_pointer: *const impl Thin, + metadata: ::Metadata, +) -> *const T { + aggregate_raw_ptr(data_pointer, metadata) +} + +/// Performs the same functionality as [`from_raw_parts`], except that a +/// raw `*mut` pointer is returned, as opposed to a raw `*const` pointer. +/// +/// See the documentation of [`from_raw_parts`] for more details. +#[unstable(feature = "ptr_metadata", issue = "81513")] +#[inline] +pub const fn from_raw_parts_mut( + data_pointer: *mut impl Thin, + metadata: ::Metadata, +) -> *mut T { + aggregate_raw_ptr(data_pointer, metadata) +} + +/// The metadata for a `Dyn = dyn SomeTrait` trait object type. +/// +/// It is a pointer to a vtable (virtual call table) +/// that represents all the necessary information +/// to manipulate the concrete type stored inside a trait object. +/// The vtable notably contains: +/// +/// * type size +/// * type alignment +/// * a pointer to the type’s `drop_in_place` impl (may be a no-op for plain-old-data) +/// * pointers to all the methods for the type’s implementation of the trait +/// +/// Note that the first three are special because they’re necessary to allocate, drop, +/// and deallocate any trait object. +/// +/// It is possible to name this struct with a type parameter that is not a `dyn` trait object +/// (for example `DynMetadata`) but not to obtain a meaningful value of that struct. +/// +/// Note that while this type implements `PartialEq`, comparing vtable pointers is unreliable: +/// pointers to vtables of the same type for the same trait can compare inequal (because vtables are +/// duplicated in multiple codegen units), and pointers to vtables of *different* types/traits can +/// compare equal (since identical vtables can be deduplicated within a codegen unit). +#[lang = "dyn_metadata"] +pub struct DynMetadata { + _vtable_ptr: NonNull, + _phantom: crate::marker::PhantomData, +} + +extern "C" { + /// Opaque type for accessing vtables. + /// + /// Private implementation detail of `DynMetadata::size_of` etc. + /// There is conceptually not actually any Abstract Machine memory behind this pointer. + type VTable; +} + +impl DynMetadata { + /// When `DynMetadata` appears as the metadata field of a wide pointer, the rustc_middle layout + /// computation does magic and the resulting layout is *not* a `FieldsShape::Aggregate`, instead + /// it is a `FieldsShape::Primitive`. This means that the same type can have different layout + /// depending on whether it appears as the metadata field of a wide pointer or as a stand-alone + /// type, which understandably confuses codegen and leads to ICEs when trying to project to a + /// field of `DynMetadata`. To work around that issue, we use `transmute` instead of using a + /// field projection. + #[inline] + fn vtable_ptr(self) -> *const VTable { + // SAFETY: this layout assumption is hard-coded into the compiler. + // If it's somehow not a size match, the transmute will error. + unsafe { crate::mem::transmute::(self) } + } + + /// Returns the size of the type associated with this vtable. + #[inline] + pub fn size_of(self) -> usize { + // Note that "size stored in vtable" is *not* the same as "result of size_of_val_raw". + // Consider a reference like `&(i32, dyn Send)`: the vtable will only store the size of the + // `Send` part! + // SAFETY: DynMetadata always contains a valid vtable pointer + unsafe { crate::intrinsics::vtable_size(self.vtable_ptr() as *const ()) } + } + + /// Returns the alignment of the type associated with this vtable. + #[inline] + pub fn align_of(self) -> usize { + // SAFETY: DynMetadata always contains a valid vtable pointer + unsafe { crate::intrinsics::vtable_align(self.vtable_ptr() as *const ()) } + } + + /// Returns the size and alignment together as a `Layout` + #[inline] + pub fn layout(self) -> crate::alloc::Layout { + // SAFETY: the compiler emitted this vtable for a concrete Rust type which + // is known to have a valid layout. Same rationale as in `Layout::for_value`. + unsafe { crate::alloc::Layout::from_size_align_unchecked(self.size_of(), self.align_of()) } + } +} + +unsafe impl Send for DynMetadata {} +unsafe impl Sync for DynMetadata {} + +impl fmt::Debug for DynMetadata { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("DynMetadata").field(&self.vtable_ptr()).finish() + } +} + +// Manual impls needed to avoid `Dyn: $Trait` bounds. + +impl Unpin for DynMetadata {} + +impl Copy for DynMetadata {} + +impl Clone for DynMetadata { + #[inline] + fn clone(&self) -> Self { + *self + } +} + +impl Eq for DynMetadata {} + +impl PartialEq for DynMetadata { + #[inline] + fn eq(&self, other: &Self) -> bool { + crate::ptr::eq::(self.vtable_ptr(), other.vtable_ptr()) + } +} + +impl Ord for DynMetadata { + #[inline] + #[allow(ambiguous_wide_pointer_comparisons)] + fn cmp(&self, other: &Self) -> crate::cmp::Ordering { + <*const VTable>::cmp(&self.vtable_ptr(), &other.vtable_ptr()) + } +} + +impl PartialOrd for DynMetadata { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Hash for DynMetadata { + #[inline] + fn hash(&self, hasher: &mut H) { + crate::ptr::hash::(self.vtable_ptr(), hasher) + } +} diff --git a/CoqOfRust/core/ptr/mod.rs b/CoqOfRust/core/ptr/mod.rs new file mode 100644 index 000000000..bc4c4e168 --- /dev/null +++ b/CoqOfRust/core/ptr/mod.rs @@ -0,0 +1,2402 @@ +//! Manually manage memory through raw pointers. +//! +//! *[See also the pointer primitive types](pointer).* +//! +//! # Safety +//! +//! Many functions in this module take raw pointers as arguments and read from or write to them. For +//! this to be safe, these pointers must be *valid* for the given access. Whether a pointer is valid +//! depends on the operation it is used for (read or write), and the extent of the memory that is +//! accessed (i.e., how many bytes are read/written) -- it makes no sense to ask "is this pointer +//! valid"; one has to ask "is this pointer valid for a given access". Most functions use `*mut T` +//! and `*const T` to access only a single value, in which case the documentation omits the size and +//! implicitly assumes it to be `size_of::()` bytes. +//! +//! The precise rules for validity are not determined yet. The guarantees that are +//! provided at this point are very minimal: +//! +//! * For operations of [size zero][zst], *every* pointer is valid, including the [null] pointer. +//! The following points are only concerned with non-zero-sized accesses. +//! * A [null] pointer is *never* valid. +//! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer be +//! *dereferenceable*. The [provenance] of the pointer is used to determine which [allocated +//! object] it is derived from; a pointer is dereferenceable if the memory range of the given size +//! starting at the pointer is entirely contained within the bounds of that allocated object. Note +//! that in Rust, every (stack-allocated) variable is considered a separate allocated object. +//! * All accesses performed by functions in this module are *non-atomic* in the sense +//! of [atomic operations] used to synchronize between threads. This means it is +//! undefined behavior to perform two concurrent accesses to the same location from different +//! threads unless both accesses only read from memory. Notice that this explicitly +//! includes [`read_volatile`] and [`write_volatile`]: Volatile accesses cannot +//! be used for inter-thread synchronization. +//! * The result of casting a reference to a pointer is valid for as long as the +//! underlying object is live and no reference (just raw pointers) is used to +//! access the same memory. That is, reference and pointer accesses cannot be +//! interleaved. +//! +//! These axioms, along with careful use of [`offset`] for pointer arithmetic, +//! are enough to correctly implement many useful things in unsafe code. Stronger guarantees +//! will be provided eventually, as the [aliasing] rules are being determined. For more +//! information, see the [book] as well as the section in the reference devoted +//! to [undefined behavior][ub]. +//! +//! We say that a pointer is "dangling" if it is not valid for any non-zero-sized accesses. This +//! means out-of-bounds pointers, pointers to freed memory, null pointers, and pointers created with +//! [`NonNull::dangling`] are all dangling. +//! +//! ## Alignment +//! +//! Valid raw pointers as defined above are not necessarily properly aligned (where +//! "proper" alignment is defined by the pointee type, i.e., `*const T` must be +//! aligned to `mem::align_of::()`). However, most functions require their +//! arguments to be properly aligned, and will explicitly state +//! this requirement in their documentation. Notable exceptions to this are +//! [`read_unaligned`] and [`write_unaligned`]. +//! +//! When a function requires proper alignment, it does so even if the access +//! has size 0, i.e., even if memory is not actually touched. Consider using +//! [`NonNull::dangling`] in such cases. +//! +//! ## Pointer to reference conversion +//! +//! When converting a pointer to a reference (e.g. via `&*ptr` or `&mut *ptr`), +//! there are several rules that must be followed: +//! +//! * The pointer must be properly aligned. +//! +//! * It must be non-null. +//! +//! * It must be "dereferenceable" in the sense defined above. +//! +//! * The pointer must point to a [valid value] of type `T`. +//! +//! * You must enforce Rust's aliasing rules. The exact aliasing rules are not decided yet, so we +//! only give a rough overview here. The rules also depend on whether a mutable or a shared +//! reference is being created. +//! * When creating a mutable reference, then while this reference exists, the memory it points to +//! must not get accessed (read or written) through any other pointer or reference not derived +//! from this reference. +//! * When creating a shared reference, then while this reference exists, the memory it points to +//! must not get mutated (except inside `UnsafeCell`). +//! +//! If a pointer follows all of these rules, it is said to be +//! *convertible to a (mutable or shared) reference*. +// ^ we use this term instead of saying that the produced reference must +// be valid, as the validity of a reference is easily confused for the +// validity of the thing it refers to, and while the two concepts are +// closly related, they are not identical. +//! +//! These rules apply even if the result is unused! +//! (The part about being initialized is not yet fully decided, but until +//! it is, the only safe approach is to ensure that they are indeed initialized.) +//! +//! An example of the implications of the above rules is that an expression such +//! as `unsafe { &*(0 as *const u8) }` is Immediate Undefined Behavior. +//! +//! [valid value]: ../../reference/behavior-considered-undefined.html#invalid-values +//! +//! ## Allocated object +//! +//! An *allocated object* is a subset of program memory which is addressable +//! from Rust, and within which pointer arithmetic is possible. Examples of +//! allocated objects include heap allocations, stack-allocated variables, +//! statics, and consts. The safety preconditions of some Rust operations - +//! such as `offset` and field projections (`expr.field`) - are defined in +//! terms of the allocated objects on which they operate. +//! +//! An allocated object has a base address, a size, and a set of memory +//! addresses. It is possible for an allocated object to have zero size, but +//! such an allocated object will still have a base address. The base address +//! of an allocated object is not necessarily unique. While it is currently the +//! case that an allocated object always has a set of memory addresses which is +//! fully contiguous (i.e., has no "holes"), there is no guarantee that this +//! will not change in the future. +//! +//! For any allocated object with `base` address, `size`, and a set of +//! `addresses`, the following are guaranteed: +//! - For all addresses `a` in `addresses`, `a` is in the range `base .. (base + +//! size)` (note that this requires `a < base + size`, not `a <= base + size`) +//! - `base` is not equal to [`null()`] (i.e., the address with the numerical +//! value 0) +//! - `base + size <= usize::MAX` +//! - `size <= isize::MAX` +//! +//! As a consequence of these guarantees, given any address `a` within the set +//! of addresses of an allocated object: +//! - It is guaranteed that `a - base` does not overflow `isize` +//! - It is guaranteed that `a - base` is non-negative +//! - It is guaranteed that, given `o = a - base` (i.e., the offset of `a` within +//! the allocated object), `base + o` will not wrap around the address space (in +//! other words, will not overflow `usize`) +//! +//! [`null()`]: null +//! +//! # Provenance +//! +//! Pointers are not *simply* an "integer" or "address". For instance, it's uncontroversial +//! to say that a Use After Free is clearly Undefined Behavior, even if you "get lucky" +//! and the freed memory gets reallocated before your read/write (in fact this is the +//! worst-case scenario, UAFs would be much less concerning if this didn't happen!). +//! As another example, consider that [`wrapping_offset`] is documented to "remember" +//! the allocated object that the original pointer points to, even if it is offset far +//! outside the memory range occupied by that allocated object. +//! To rationalize claims like this, pointers need to somehow be *more* than just their addresses: +//! they must have **provenance**. +//! +//! A pointer value in Rust semantically contains the following information: +//! +//! * The **address** it points to, which can be represented by a `usize`. +//! * The **provenance** it has, defining the memory it has permission to access. Provenance can be +//! absent, in which case the pointer does not have permission to access any memory. +//! +//! The exact structure of provenance is not yet specified, but the permission defined by a +//! pointer's provenance have a *spatial* component, a *temporal* component, and a *mutability* +//! component: +//! +//! * Spatial: The set of memory addresses that the pointer is allowed to access. +//! * Temporal: The timespan during which the pointer is allowed to access those memory addresses. +//! * Mutability: Whether the pointer may only access the memory for reads, or also access it for +//! writes. Note that this can interact with the other components, e.g. a pointer might permit +//! mutation only for a subset of addresses, or only for a subset of its maximal timespan. +//! +//! When an [allocated object] is created, it has a unique Original Pointer. For alloc +//! APIs this is literally the pointer the call returns, and for local variables and statics, +//! this is the name of the variable/static. (This is mildly overloading the term "pointer" +//! for the sake of brevity/exposition.) +//! +//! The Original Pointer for an allocated object has provenance that constrains the *spatial* +//! permissions of this pointer to the memory range of the allocation, and the *temporal* +//! permissions to the lifetime of the allocation. Provenance is implicitly inherited by all +//! pointers transitively derived from the Original Pointer through operations like [`offset`], +//! borrowing, and pointer casts. Some operations may *shrink* the permissions of the derived +//! provenance, limiting how much memory it can access or how long it's valid for (i.e. borrowing a +//! subfield and subslicing can shrink the spatial component of provenance, and all borrowing can +//! shrink the temporal component of provenance). However, no operation can ever *grow* the +//! permissions of the derived provenance: even if you "know" there is a larger allocation, you +//! can't derive a pointer with a larger provenance. Similarly, you cannot "recombine" two +//! contiguous provenances back into one (i.e. with a `fn merge(&[T], &[T]) -> &[T]`). +//! +//! A reference to a place always has provenance over at least the memory that place occupies. +//! A reference to a slice always has provenance over at least the range that slice describes. +//! Whether and when exactly the provenance of a reference gets "shrunk" to *exactly* fit +//! the memory it points to is not yet determined. +//! +//! A *shared* reference only ever has provenance that permits reading from memory, +//! and never permits writes, except inside [`UnsafeCell`]. +//! +//! Provenance can affect whether a program has undefined behavior: +//! +//! * It is undefined behavior to access memory through a pointer that does not have provenance over +//! that memory. Note that a pointer "at the end" of its provenance is not actually outside its +//! provenance, it just has 0 bytes it can load/store. Zero-sized accesses do not require any +//! provenance since they access an empty range of memory. +//! +//! * It is undefined behavior to [`offset`] a pointer across a memory range that is not contained +//! in the allocated object it is derived from, or to [`offset_from`] two pointers not derived +//! from the same allocated object. Provenance is used to say what exactly "derived from" even +//! means: the lineage of a pointer is traced back to the Original Pointer it descends from, and +//! that identifies the relevant allocated object. In particular, it's always UB to offset a +//! pointer derived from something that is now deallocated, except if the offset is 0. +//! +//! But it *is* still sound to: +//! +//! * Create a pointer without provenance from just an address (see [`ptr::dangling`]). Such a +//! pointer cannot be used for memory accesses (except for zero-sized accesses). This can still be +//! useful for sentinel values like `null` *or* to represent a tagged pointer that will never be +//! dereferenceable. In general, it is always sound for an integer to pretend to be a pointer "for +//! fun" as long as you don't use operations on it which require it to be valid (non-zero-sized +//! offset, read, write, etc). +//! +//! * Forge an allocation of size zero at any sufficiently aligned non-null address. +//! i.e. the usual "ZSTs are fake, do what you want" rules apply. +//! +//! * [`wrapping_offset`] a pointer outside its provenance. This includes pointers +//! which have "no" provenance. In particular, this makes it sound to do pointer tagging tricks. +//! +//! * Compare arbitrary pointers by address. Pointer comparison ignores provenance and addresses +//! *are* just integers, so there is always a coherent answer, even if the pointers are dangling +//! or from different provenances. Note that if you get "lucky" and notice that a pointer at the +//! end of one allocated object is the "same" address as the start of another allocated object, +//! anything you do with that fact is *probably* going to be gibberish. The scope of that +//! gibberish is kept under control by the fact that the two pointers *still* aren't allowed to +//! access the other's allocation (bytes), because they still have different provenance. +//! +//! Note that the full definition of provenance in Rust is not decided yet, as this interacts +//! with the as-yet undecided [aliasing] rules. +//! +//! ## Pointers Vs Integers +//! +//! From this discussion, it becomes very clear that a `usize` *cannot* accurately represent a pointer, +//! and converting from a pointer to a `usize` is generally an operation which *only* extracts the +//! address. Converting this address back into pointer requires somehow answering the question: +//! which provenance should the resulting pointer have? +//! +//! Rust provides two ways of dealing with this situation: *Strict Provenance* and *Exposed Provenance*. +//! +//! Note that a pointer *can* represent a `usize` (via [`without_provenance`]), so the right type to +//! use in situations where a value is "sometimes a pointer and sometimes a bare `usize`" is a +//! pointer type. +//! +//! ## Strict Provenance +//! +//! "Strict Provenance" refers to a set of APIs designed to make working with provenance more +//! explicit. They are intended as substitutes for casting a pointer to an integer and back. +//! +//! Entirely avoiding integer-to-pointer casts successfully side-steps the inherent ambiguity of +//! that operation. This benefits compiler optimizations, and it is pretty much a requirement for +//! using tools like [Miri] and architectures like [CHERI] that aim to detect and diagnose pointer +//! misuse. +//! +//! The key insight to making programming without integer-to-pointer casts *at all* viable is the +//! [`with_addr`] method: +//! +//! ```text +//! /// Creates a new pointer with the given address. +//! /// +//! /// This performs the same operation as an `addr as ptr` cast, but copies +//! /// the *provenance* of `self` to the new pointer. +//! /// This allows us to dynamically preserve and propagate this important +//! /// information in a way that is otherwise impossible with a unary cast. +//! /// +//! /// This is equivalent to using `wrapping_offset` to offset `self` to the +//! /// given address, and therefore has all the same capabilities and restrictions. +//! pub fn with_addr(self, addr: usize) -> Self; +//! ``` +//! +//! So you're still able to drop down to the address representation and do whatever +//! clever bit tricks you want *as long as* you're able to keep around a pointer +//! into the allocation you care about that can "reconstitute" the provenance. +//! Usually this is very easy, because you only are taking a pointer, messing with the address, +//! and then immediately converting back to a pointer. To make this use case more ergonomic, +//! we provide the [`map_addr`] method. +//! +//! To help make it clear that code is "following" Strict Provenance semantics, we also provide an +//! [`addr`] method which promises that the returned address is not part of a +//! pointer-integer-pointer roundtrip. In the future we may provide a lint for pointer<->integer +//! casts to help you audit if your code conforms to strict provenance. +//! +//! ### Using Strict Provenance +//! +//! Most code needs no changes to conform to strict provenance, as the only really concerning +//! operation is casts from usize to a pointer. For code which *does* cast a `usize` to a pointer, +//! the scope of the change depends on exactly what you're doing. +//! +//! In general, you just need to make sure that if you want to convert a `usize` address to a +//! pointer and then use that pointer to read/write memory, you need to keep around a pointer +//! that has sufficient provenance to perform that read/write itself. In this way all of your +//! casts from an address to a pointer are essentially just applying offsets/indexing. +//! +//! This is generally trivial to do for simple cases like tagged pointers *as long as you +//! represent the tagged pointer as an actual pointer and not a `usize`*. For instance: +//! +//! ``` +//! unsafe { +//! // A flag we want to pack into our pointer +//! static HAS_DATA: usize = 0x1; +//! static FLAG_MASK: usize = !HAS_DATA; +//! +//! // Our value, which must have enough alignment to have spare least-significant-bits. +//! let my_precious_data: u32 = 17; +//! assert!(core::mem::align_of::() > 1); +//! +//! // Create a tagged pointer +//! let ptr = &my_precious_data as *const u32; +//! let tagged = ptr.map_addr(|addr| addr | HAS_DATA); +//! +//! // Check the flag: +//! if tagged.addr() & HAS_DATA != 0 { +//! // Untag and read the pointer +//! let data = *tagged.map_addr(|addr| addr & FLAG_MASK); +//! assert_eq!(data, 17); +//! } else { +//! unreachable!() +//! } +//! } +//! ``` +//! +//! (Yes, if you've been using AtomicUsize for pointers in concurrent datastructures, you should +//! be using AtomicPtr instead. If that messes up the way you atomically manipulate pointers, +//! we would like to know why, and what needs to be done to fix it.) +//! +//! Situations where a valid pointer *must* be created from just an address, such as baremetal code +//! accessing a memory-mapped interface at a fixed address, cannot currently be handled with strict +//! provenance APIs and should use [exposed provenance](#exposed-provenance). +//! +//! ## Exposed Provenance +//! +//! As discussed above, integer-to-pointer casts are not possible with Strict Provenance APIs. +//! This is by design: the goal of Strict Provenance is to provide a clear specification that we are +//! confident can be formalized unambiguously and can be subject to precise formal reasoning. +//! Integer-to-pointer casts do not (currently) have such a clear specification. +//! +//! However, there exist situations where integer-to-pointer casts cannot be avoided, or +//! where avoiding them would require major refactoring. Legacy platform APIs also regularly assume +//! that `usize` can capture all the information that makes up a pointer. +//! Bare-metal platforms can also require the synthesis of a pointer "out of thin air" without +//! anywhere to obtain proper provenance from. +//! +//! Rust's model for dealing with integer-to-pointer casts is called *Exposed Provenance*. However, +//! the semantics of Exposed Provenance are on much less solid footing than Strict Provenance, and +//! at this point it is not yet clear whether a satisfying unambiguous semantics can be defined for +//! Exposed Provenance. (If that sounds bad, be reassured that other popular languages that provide +//! integer-to-pointer casts are not faring any better.) Furthermore, Exposed Provenance will not +//! work (well) with tools like [Miri] and [CHERI]. +//! +//! Exposed Provenance is provided by the [`expose_provenance`] and [`with_exposed_provenance`] methods, +//! which are equivalent to `as` casts between pointers and integers. +//! - [`expose_provenance`] is a lot like [`addr`], but additionally adds the provenance of the +//! pointer to a global list of 'exposed' provenances. (This list is purely conceptual, it exists +//! for the purpose of specifying Rust but is not materialized in actual executions, except in +//! tools like [Miri].) +//! Memory which is outside the control of the Rust abstract machine (MMIO registers, for example) +//! is always considered to be exposed, so long as this memory is disjoint from memory that will +//! be used by the abstract machine such as the stack, heap, and statics. +//! - [`with_exposed_provenance`] can be used to construct a pointer with one of these previously +//! 'exposed' provenances. [`with_exposed_provenance`] takes only `addr: usize` as arguments, so +//! unlike in [`with_addr`] there is no indication of what the correct provenance for the returned +//! pointer is -- and that is exactly what makes integer-to-pointer casts so tricky to rigorously +//! specify! The compiler will do its best to pick the right provenance for you, but currently we +//! cannot provide any guarantees about which provenance the resulting pointer will have. Only one +//! thing is clear: if there is *no* previously 'exposed' provenance that justifies the way the +//! returned pointer will be used, the program has undefined behavior. +//! +//! If at all possible, we encourage code to be ported to [Strict Provenance] APIs, thus avoiding +//! the need for Exposed Provenance. Maximizing the amount of such code is a major win for avoiding +//! specification complexity and to facilitate adoption of tools like [CHERI] and [Miri] that can be +//! a big help in increasing the confidence in (unsafe) Rust code. However, we acknowledge that this +//! is not always possible, and offer Exposed Provenance as a way to explicit "opt out" of the +//! well-defined semantics of Strict Provenance, and "opt in" to the unclear semantics of +//! integer-to-pointer casts. +//! +//! [aliasing]: ../../nomicon/aliasing.html +//! [allocated object]: #allocated-object +//! [provenance]: #provenance +//! [book]: ../../book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer +//! [ub]: ../../reference/behavior-considered-undefined.html +//! [zst]: ../../nomicon/exotic-sizes.html#zero-sized-types-zsts +//! [atomic operations]: crate::sync::atomic +//! [`offset`]: pointer::offset +//! [`offset_from`]: pointer::offset_from +//! [`wrapping_offset`]: pointer::wrapping_offset +//! [`with_addr`]: pointer::with_addr +//! [`map_addr`]: pointer::map_addr +//! [`addr`]: pointer::addr +//! [`ptr::dangling`]: core::ptr::dangling +//! [`expose_provenance`]: pointer::expose_provenance +//! [`with_exposed_provenance`]: with_exposed_provenance +//! [Miri]: https://github.com/rust-lang/miri +//! [CHERI]: https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/ +//! [Strict Provenance]: #strict-provenance +//! [`UnsafeCell`]: core::cell::UnsafeCell + +#![stable(feature = "rust1", since = "1.0.0")] +// There are many unsafe functions taking pointers that don't dereference them. +#![allow(clippy::not_unsafe_ptr_arg_deref)] + +use crate::cmp::Ordering; +use crate::marker::FnPtr; +use crate::mem::{self, MaybeUninit, SizedTypeProperties}; +use crate::{fmt, hash, intrinsics, ub_checks}; + +mod alignment; +#[unstable(feature = "ptr_alignment_type", issue = "102070")] +pub use alignment::Alignment; + +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(inline)] +pub use crate::intrinsics::copy; +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(inline)] +pub use crate::intrinsics::copy_nonoverlapping; +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(inline)] +pub use crate::intrinsics::write_bytes; + +mod metadata; +#[unstable(feature = "ptr_metadata", issue = "81513")] +pub use metadata::{DynMetadata, Pointee, Thin, from_raw_parts, from_raw_parts_mut, metadata}; + +mod non_null; +#[stable(feature = "nonnull", since = "1.25.0")] +pub use non_null::NonNull; + +mod unique; +#[unstable(feature = "ptr_internals", issue = "none")] +pub use unique::Unique; + +mod const_ptr; +mod mut_ptr; + +/// Executes the destructor (if any) of the pointed-to value. +/// +/// This is almost the same as calling [`ptr::read`] and discarding +/// the result, but has the following advantages: +// FIXME: say something more useful than "almost the same"? +// There are open questions here: `read` requires the value to be fully valid, e.g. if `T` is a +// `bool` it must be 0 or 1, if it is a reference then it must be dereferenceable. `drop_in_place` +// only requires that `*to_drop` be "valid for dropping" and we have not defined what that means. In +// Miri it currently (May 2024) requires nothing at all for types without drop glue. +/// +/// * It is *required* to use `drop_in_place` to drop unsized types like +/// trait objects, because they can't be read out onto the stack and +/// dropped normally. +/// +/// * It is friendlier to the optimizer to do this over [`ptr::read`] when +/// dropping manually allocated memory (e.g., in the implementations of +/// `Box`/`Rc`/`Vec`), as the compiler doesn't need to prove that it's +/// sound to elide the copy. +/// +/// * It can be used to drop [pinned] data when `T` is not `repr(packed)` +/// (pinned data must not be moved before it is dropped). +/// +/// Unaligned values cannot be dropped in place, they must be copied to an aligned +/// location first using [`ptr::read_unaligned`]. For packed structs, this move is +/// done automatically by the compiler. This means the fields of packed structs +/// are not dropped in-place. +/// +/// [`ptr::read`]: self::read +/// [`ptr::read_unaligned`]: self::read_unaligned +/// [pinned]: crate::pin +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `to_drop` must be [valid] for both reads and writes. +/// +/// * `to_drop` must be properly aligned, even if `T` has size 0. +/// +/// * `to_drop` must be nonnull, even if `T` has size 0. +/// +/// * The value `to_drop` points to must be valid for dropping, which may mean +/// it must uphold additional invariants. These invariants depend on the type +/// of the value being dropped. For instance, when dropping a Box, the box's +/// pointer to the heap must be valid. +/// +/// * While `drop_in_place` is executing, the only way to access parts of +/// `to_drop` is through the `&mut self` references supplied to the +/// `Drop::drop` methods that `drop_in_place` invokes. +/// +/// Additionally, if `T` is not [`Copy`], using the pointed-to value after +/// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop = +/// foo` counts as a use because it will cause the value to be dropped +/// again. [`write()`] can be used to overwrite data without causing it to be +/// dropped. +/// +/// [valid]: self#safety +/// +/// # Examples +/// +/// Manually remove the last item from a vector: +/// +/// ``` +/// use std::ptr; +/// use std::rc::Rc; +/// +/// let last = Rc::new(1); +/// let weak = Rc::downgrade(&last); +/// +/// let mut v = vec![Rc::new(0), last]; +/// +/// unsafe { +/// // Get a raw pointer to the last element in `v`. +/// let ptr = &mut v[1] as *mut _; +/// // Shorten `v` to prevent the last item from being dropped. We do that first, +/// // to prevent issues if the `drop_in_place` below panics. +/// v.set_len(1); +/// // Without a call `drop_in_place`, the last item would never be dropped, +/// // and the memory it manages would be leaked. +/// ptr::drop_in_place(ptr); +/// } +/// +/// assert_eq!(v, &[0.into()]); +/// +/// // Ensure that the last item was dropped. +/// assert!(weak.upgrade().is_none()); +/// ``` +#[stable(feature = "drop_in_place", since = "1.8.0")] +#[lang = "drop_in_place"] +#[allow(unconditional_recursion)] +#[rustc_diagnostic_item = "ptr_drop_in_place"] +pub unsafe fn drop_in_place(to_drop: *mut T) { + // Code here does not matter - this is replaced by the + // real drop glue by the compiler. + + // SAFETY: see comment above + unsafe { drop_in_place(to_drop) } +} + +/// Creates a null raw pointer. +/// +/// This function is equivalent to zero-initializing the pointer: +/// `MaybeUninit::<*const T>::zeroed().assume_init()`. +/// The resulting pointer has the address 0. +/// +/// # Examples +/// +/// ``` +/// use std::ptr; +/// +/// let p: *const i32 = ptr::null(); +/// assert!(p.is_null()); +/// assert_eq!(p as usize, 0); // this pointer has the address 0 +/// ``` +#[inline(always)] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_promotable] +#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] +#[rustc_diagnostic_item = "ptr_null"] +pub const fn null() -> *const T { + from_raw_parts(without_provenance::<()>(0), ()) +} + +/// Creates a null mutable raw pointer. +/// +/// This function is equivalent to zero-initializing the pointer: +/// `MaybeUninit::<*mut T>::zeroed().assume_init()`. +/// The resulting pointer has the address 0. +/// +/// # Examples +/// +/// ``` +/// use std::ptr; +/// +/// let p: *mut i32 = ptr::null_mut(); +/// assert!(p.is_null()); +/// assert_eq!(p as usize, 0); // this pointer has the address 0 +/// ``` +#[inline(always)] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_promotable] +#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] +#[rustc_diagnostic_item = "ptr_null_mut"] +pub const fn null_mut() -> *mut T { + from_raw_parts_mut(without_provenance_mut::<()>(0), ()) +} + +/// Creates a pointer with the given address and no [provenance][crate::ptr#provenance]. +/// +/// This is equivalent to `ptr::null().with_addr(addr)`. +/// +/// Without provenance, this pointer is not associated with any actual allocation. Such a +/// no-provenance pointer may be used for zero-sized memory accesses (if suitably aligned), but +/// non-zero-sized memory accesses with a no-provenance pointer are UB. No-provenance pointers are +/// little more than a `usize` address in disguise. +/// +/// This is different from `addr as *const T`, which creates a pointer that picks up a previously +/// exposed provenance. See [`with_exposed_provenance`] for more details on that operation. +/// +/// This is a [Strict Provenance][crate::ptr#strict-provenance] API. +#[inline(always)] +#[must_use] +#[stable(feature = "strict_provenance", since = "1.84.0")] +#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] +pub const fn without_provenance(addr: usize) -> *const T { + // An int-to-pointer transmute currently has exactly the intended semantics: it creates a + // pointer without provenance. Note that this is *not* a stable guarantee about transmute + // semantics, it relies on sysroot crates having special status. + // SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that + // pointer). + unsafe { mem::transmute(addr) } +} + +/// Creates a new pointer that is dangling, but non-null and well-aligned. +/// +/// This is useful for initializing types which lazily allocate, like +/// `Vec::new` does. +/// +/// Note that the pointer value may potentially represent a valid pointer to +/// a `T`, which means this must not be used as a "not yet initialized" +/// sentinel value. Types that lazily allocate must track initialization by +/// some other means. +#[inline(always)] +#[must_use] +#[stable(feature = "strict_provenance", since = "1.84.0")] +#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] +pub const fn dangling() -> *const T { + without_provenance(mem::align_of::()) +} + +/// Creates a pointer with the given address and no [provenance][crate::ptr#provenance]. +/// +/// This is equivalent to `ptr::null_mut().with_addr(addr)`. +/// +/// Without provenance, this pointer is not associated with any actual allocation. Such a +/// no-provenance pointer may be used for zero-sized memory accesses (if suitably aligned), but +/// non-zero-sized memory accesses with a no-provenance pointer are UB. No-provenance pointers are +/// little more than a `usize` address in disguise. +/// +/// This is different from `addr as *mut T`, which creates a pointer that picks up a previously +/// exposed provenance. See [`with_exposed_provenance_mut`] for more details on that operation. +/// +/// This is a [Strict Provenance][crate::ptr#strict-provenance] API. +#[inline(always)] +#[must_use] +#[stable(feature = "strict_provenance", since = "1.84.0")] +#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] +pub const fn without_provenance_mut(addr: usize) -> *mut T { + // An int-to-pointer transmute currently has exactly the intended semantics: it creates a + // pointer without provenance. Note that this is *not* a stable guarantee about transmute + // semantics, it relies on sysroot crates having special status. + // SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that + // pointer). + unsafe { mem::transmute(addr) } +} + +/// Creates a new pointer that is dangling, but non-null and well-aligned. +/// +/// This is useful for initializing types which lazily allocate, like +/// `Vec::new` does. +/// +/// Note that the pointer value may potentially represent a valid pointer to +/// a `T`, which means this must not be used as a "not yet initialized" +/// sentinel value. Types that lazily allocate must track initialization by +/// some other means. +#[inline(always)] +#[must_use] +#[stable(feature = "strict_provenance", since = "1.84.0")] +#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] +pub const fn dangling_mut() -> *mut T { + without_provenance_mut(mem::align_of::()) +} + +/// Converts an address back to a pointer, picking up some previously 'exposed' +/// [provenance][crate::ptr#provenance]. +/// +/// This is fully equivalent to `addr as *const T`. The provenance of the returned pointer is that +/// of *some* pointer that was previously exposed by passing it to +/// [`expose_provenance`][pointer::expose_provenance], or a `ptr as usize` cast. In addition, memory +/// which is outside the control of the Rust abstract machine (MMIO registers, for example) is +/// always considered to be accessible with an exposed provenance, so long as this memory is disjoint +/// from memory that will be used by the abstract machine such as the stack, heap, and statics. +/// +/// The exact provenance that gets picked is not specified. The compiler will do its best to pick +/// the "right" provenance for you (whatever that may be), but currently we cannot provide any +/// guarantees about which provenance the resulting pointer will have -- and therefore there +/// is no definite specification for which memory the resulting pointer may access. +/// +/// If there is *no* previously 'exposed' provenance that justifies the way the returned pointer +/// will be used, the program has undefined behavior. In particular, the aliasing rules still apply: +/// pointers and references that have been invalidated due to aliasing accesses cannot be used +/// anymore, even if they have been exposed! +/// +/// Due to its inherent ambiguity, this operation may not be supported by tools that help you to +/// stay conformant with the Rust memory model. It is recommended to use [Strict +/// Provenance][self#strict-provenance] APIs such as [`with_addr`][pointer::with_addr] wherever +/// possible. +/// +/// On most platforms this will produce a value with the same bytes as the address. Platforms +/// which need to store additional information in a pointer may not support this operation, +/// since it is generally not possible to actually *compute* which provenance the returned +/// pointer has to pick up. +/// +/// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API. +#[must_use] +#[inline(always)] +#[stable(feature = "exposed_provenance", since = "1.84.0")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead +pub fn with_exposed_provenance(addr: usize) -> *const T { + addr as *const T +} + +/// Converts an address back to a mutable pointer, picking up some previously 'exposed' +/// [provenance][crate::ptr#provenance]. +/// +/// This is fully equivalent to `addr as *mut T`. The provenance of the returned pointer is that +/// of *some* pointer that was previously exposed by passing it to +/// [`expose_provenance`][pointer::expose_provenance], or a `ptr as usize` cast. In addition, memory +/// which is outside the control of the Rust abstract machine (MMIO registers, for example) is +/// always considered to be accessible with an exposed provenance, so long as this memory is disjoint +/// from memory that will be used by the abstract machine such as the stack, heap, and statics. +/// +/// The exact provenance that gets picked is not specified. The compiler will do its best to pick +/// the "right" provenance for you (whatever that may be), but currently we cannot provide any +/// guarantees about which provenance the resulting pointer will have -- and therefore there +/// is no definite specification for which memory the resulting pointer may access. +/// +/// If there is *no* previously 'exposed' provenance that justifies the way the returned pointer +/// will be used, the program has undefined behavior. In particular, the aliasing rules still apply: +/// pointers and references that have been invalidated due to aliasing accesses cannot be used +/// anymore, even if they have been exposed! +/// +/// Due to its inherent ambiguity, this operation may not be supported by tools that help you to +/// stay conformant with the Rust memory model. It is recommended to use [Strict +/// Provenance][self#strict-provenance] APIs such as [`with_addr`][pointer::with_addr] wherever +/// possible. +/// +/// On most platforms this will produce a value with the same bytes as the address. Platforms +/// which need to store additional information in a pointer may not support this operation, +/// since it is generally not possible to actually *compute* which provenance the returned +/// pointer has to pick up. +/// +/// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API. +#[must_use] +#[inline(always)] +#[stable(feature = "exposed_provenance", since = "1.84.0")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead +pub fn with_exposed_provenance_mut(addr: usize) -> *mut T { + addr as *mut T +} + +/// Converts a reference to a raw pointer. +/// +/// For `r: &T`, `from_ref(r)` is equivalent to `r as *const T` (except for the caveat noted below), +/// but is a bit safer since it will never silently change type or mutability, in particular if the +/// code is refactored. +/// +/// The caller must ensure that the pointee outlives the pointer this function returns, or else it +/// will end up dangling. +/// +/// The caller must also ensure that the memory the pointer (non-transitively) points to is never +/// written to (except inside an `UnsafeCell`) using this pointer or any pointer derived from it. If +/// you need to mutate the pointee, use [`from_mut`]. Specifically, to turn a mutable reference `m: +/// &mut T` into `*const T`, prefer `from_mut(m).cast_const()` to obtain a pointer that can later be +/// used for mutation. +/// +/// ## Interaction with lifetime extension +/// +/// Note that this has subtle interactions with the rules for lifetime extension of temporaries in +/// tail expressions. This code is valid, albeit in a non-obvious way: +/// ```rust +/// # type T = i32; +/// # fn foo() -> T { 42 } +/// // The temporary holding the return value of `foo` has its lifetime extended, +/// // because the surrounding expression involves no function call. +/// let p = &foo() as *const T; +/// unsafe { p.read() }; +/// ``` +/// Naively replacing the cast with `from_ref` is not valid: +/// ```rust,no_run +/// # use std::ptr; +/// # type T = i32; +/// # fn foo() -> T { 42 } +/// // The temporary holding the return value of `foo` does *not* have its lifetime extended, +/// // because the surrounding expression involves no function call. +/// let p = ptr::from_ref(&foo()); +/// unsafe { p.read() }; // UB! Reading from a dangling pointer ⚠️ +/// ``` +/// The recommended way to write this code is to avoid relying on lifetime extension +/// when raw pointers are involved: +/// ```rust +/// # use std::ptr; +/// # type T = i32; +/// # fn foo() -> T { 42 } +/// let x = foo(); +/// let p = ptr::from_ref(&x); +/// unsafe { p.read() }; +/// ``` +#[inline(always)] +#[must_use] +#[stable(feature = "ptr_from_ref", since = "1.76.0")] +#[rustc_const_stable(feature = "ptr_from_ref", since = "1.76.0")] +#[rustc_never_returns_null_ptr] +#[rustc_diagnostic_item = "ptr_from_ref"] +pub const fn from_ref(r: &T) -> *const T { + r +} + +/// Converts a mutable reference to a raw pointer. +/// +/// For `r: &mut T`, `from_mut(r)` is equivalent to `r as *mut T` (except for the caveat noted +/// below), but is a bit safer since it will never silently change type or mutability, in particular +/// if the code is refactored. +/// +/// The caller must ensure that the pointee outlives the pointer this function returns, or else it +/// will end up dangling. +/// +/// ## Interaction with lifetime extension +/// +/// Note that this has subtle interactions with the rules for lifetime extension of temporaries in +/// tail expressions. This code is valid, albeit in a non-obvious way: +/// ```rust +/// # type T = i32; +/// # fn foo() -> T { 42 } +/// // The temporary holding the return value of `foo` has its lifetime extended, +/// // because the surrounding expression involves no function call. +/// let p = &mut foo() as *mut T; +/// unsafe { p.write(T::default()) }; +/// ``` +/// Naively replacing the cast with `from_mut` is not valid: +/// ```rust,no_run +/// # use std::ptr; +/// # type T = i32; +/// # fn foo() -> T { 42 } +/// // The temporary holding the return value of `foo` does *not* have its lifetime extended, +/// // because the surrounding expression involves no function call. +/// let p = ptr::from_mut(&mut foo()); +/// unsafe { p.write(T::default()) }; // UB! Writing to a dangling pointer ⚠️ +/// ``` +/// The recommended way to write this code is to avoid relying on lifetime extension +/// when raw pointers are involved: +/// ```rust +/// # use std::ptr; +/// # type T = i32; +/// # fn foo() -> T { 42 } +/// let mut x = foo(); +/// let p = ptr::from_mut(&mut x); +/// unsafe { p.write(T::default()) }; +/// ``` +#[inline(always)] +#[must_use] +#[stable(feature = "ptr_from_ref", since = "1.76.0")] +#[rustc_const_stable(feature = "ptr_from_ref", since = "1.76.0")] +#[rustc_never_returns_null_ptr] +pub const fn from_mut(r: &mut T) -> *mut T { + r +} + +/// Forms a raw slice from a pointer and a length. +/// +/// The `len` argument is the number of **elements**, not the number of bytes. +/// +/// This function is safe, but actually using the return value is unsafe. +/// See the documentation of [`slice::from_raw_parts`] for slice safety requirements. +/// +/// [`slice::from_raw_parts`]: crate::slice::from_raw_parts +/// +/// # Examples +/// +/// ```rust +/// use std::ptr; +/// +/// // create a slice pointer when starting out with a pointer to the first element +/// let x = [5, 6, 7]; +/// let raw_pointer = x.as_ptr(); +/// let slice = ptr::slice_from_raw_parts(raw_pointer, 3); +/// assert_eq!(unsafe { &*slice }[2], 7); +/// ``` +/// +/// You must ensure that the pointer is valid and not null before dereferencing +/// the raw slice. A slice reference must never have a null pointer, even if it's empty. +/// +/// ```rust,should_panic +/// use std::ptr; +/// let danger: *const [u8] = ptr::slice_from_raw_parts(ptr::null(), 0); +/// unsafe { +/// danger.as_ref().expect("references must not be null"); +/// } +/// ``` +#[inline] +#[stable(feature = "slice_from_raw_parts", since = "1.42.0")] +#[rustc_const_stable(feature = "const_slice_from_raw_parts", since = "1.64.0")] +#[rustc_diagnostic_item = "ptr_slice_from_raw_parts"] +pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { + from_raw_parts(data, len) +} + +/// Forms a raw mutable slice from a pointer and a length. +/// +/// The `len` argument is the number of **elements**, not the number of bytes. +/// +/// Performs the same functionality as [`slice_from_raw_parts`], except that a +/// raw mutable slice is returned, as opposed to a raw immutable slice. +/// +/// This function is safe, but actually using the return value is unsafe. +/// See the documentation of [`slice::from_raw_parts_mut`] for slice safety requirements. +/// +/// [`slice::from_raw_parts_mut`]: crate::slice::from_raw_parts_mut +/// +/// # Examples +/// +/// ```rust +/// use std::ptr; +/// +/// let x = &mut [5, 6, 7]; +/// let raw_pointer = x.as_mut_ptr(); +/// let slice = ptr::slice_from_raw_parts_mut(raw_pointer, 3); +/// +/// unsafe { +/// (*slice)[2] = 99; // assign a value at an index in the slice +/// }; +/// +/// assert_eq!(unsafe { &*slice }[2], 99); +/// ``` +/// +/// You must ensure that the pointer is valid and not null before dereferencing +/// the raw slice. A slice reference must never have a null pointer, even if it's empty. +/// +/// ```rust,should_panic +/// use std::ptr; +/// let danger: *mut [u8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 0); +/// unsafe { +/// danger.as_mut().expect("references must not be null"); +/// } +/// ``` +#[inline] +#[stable(feature = "slice_from_raw_parts", since = "1.42.0")] +#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")] +#[rustc_diagnostic_item = "ptr_slice_from_raw_parts_mut"] +pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { + from_raw_parts_mut(data, len) +} + +/// Swaps the values at two mutable locations of the same type, without +/// deinitializing either. +/// +/// But for the following exceptions, this function is semantically +/// equivalent to [`mem::swap`]: +/// +/// * It operates on raw pointers instead of references. When references are +/// available, [`mem::swap`] should be preferred. +/// +/// * The two pointed-to values may overlap. If the values do overlap, then the +/// overlapping region of memory from `x` will be used. This is demonstrated +/// in the second example below. +/// +/// * The operation is "untyped" in the sense that data may be uninitialized or otherwise violate +/// the requirements of `T`. The initialization state is preserved exactly. +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * Both `x` and `y` must be [valid] for both reads and writes. They must remain valid even when the +/// other pointer is written. (This means if the memory ranges overlap, the two pointers must not +/// be subject to aliasing restrictions relative to each other.) +/// +/// * Both `x` and `y` must be properly aligned. +/// +/// Note that even if `T` has size `0`, the pointers must be properly aligned. +/// +/// [valid]: self#safety +/// +/// # Examples +/// +/// Swapping two non-overlapping regions: +/// +/// ``` +/// use std::ptr; +/// +/// let mut array = [0, 1, 2, 3]; +/// +/// let (x, y) = array.split_at_mut(2); +/// let x = x.as_mut_ptr().cast::<[u32; 2]>(); // this is `array[0..2]` +/// let y = y.as_mut_ptr().cast::<[u32; 2]>(); // this is `array[2..4]` +/// +/// unsafe { +/// ptr::swap(x, y); +/// assert_eq!([2, 3, 0, 1], array); +/// } +/// ``` +/// +/// Swapping two overlapping regions: +/// +/// ``` +/// use std::ptr; +/// +/// let mut array: [i32; 4] = [0, 1, 2, 3]; +/// +/// let array_ptr: *mut i32 = array.as_mut_ptr(); +/// +/// let x = array_ptr as *mut [i32; 3]; // this is `array[0..3]` +/// let y = unsafe { array_ptr.add(1) } as *mut [i32; 3]; // this is `array[1..4]` +/// +/// unsafe { +/// ptr::swap(x, y); +/// // The indices `1..3` of the slice overlap between `x` and `y`. +/// // Reasonable results would be for to them be `[2, 3]`, so that indices `0..3` are +/// // `[1, 2, 3]` (matching `y` before the `swap`); or for them to be `[0, 1]` +/// // so that indices `1..4` are `[0, 1, 2]` (matching `x` before the `swap`). +/// // This implementation is defined to make the latter choice. +/// assert_eq!([1, 0, 1, 2], array); +/// } +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_swap", issue = "83163")] +#[rustc_diagnostic_item = "ptr_swap"] +#[rustc_const_stable_indirect] +pub const unsafe fn swap(x: *mut T, y: *mut T) { + // Give ourselves some scratch space to work with. + // We do not have to worry about drops: `MaybeUninit` does nothing when dropped. + let mut tmp = MaybeUninit::::uninit(); + + // Perform the swap + // SAFETY: the caller must guarantee that `x` and `y` are + // valid for writes and properly aligned. `tmp` cannot be + // overlapping either `x` or `y` because `tmp` was just allocated + // on the stack as a separate allocated object. + unsafe { + copy_nonoverlapping(x, tmp.as_mut_ptr(), 1); + copy(y, x, 1); // `x` and `y` may overlap + copy_nonoverlapping(tmp.as_ptr(), y, 1); + } +} + +/// Swaps `count * size_of::()` bytes between the two regions of memory +/// beginning at `x` and `y`. The two regions must *not* overlap. +/// +/// The operation is "untyped" in the sense that data may be uninitialized or otherwise violate the +/// requirements of `T`. The initialization state is preserved exactly. +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * Both `x` and `y` must be [valid] for both reads and writes of `count * +/// size_of::()` bytes. +/// +/// * Both `x` and `y` must be properly aligned. +/// +/// * The region of memory beginning at `x` with a size of `count * +/// size_of::()` bytes must *not* overlap with the region of memory +/// beginning at `y` with the same size. +/// +/// Note that even if the effectively copied size (`count * size_of::()`) is `0`, +/// the pointers must be properly aligned. +/// +/// [valid]: self#safety +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::ptr; +/// +/// let mut x = [1, 2, 3, 4]; +/// let mut y = [7, 8, 9]; +/// +/// unsafe { +/// ptr::swap_nonoverlapping(x.as_mut_ptr(), y.as_mut_ptr(), 2); +/// } +/// +/// assert_eq!(x, [7, 8, 3, 4]); +/// assert_eq!(y, [1, 2, 9]); +/// ``` +#[inline] +#[stable(feature = "swap_nonoverlapping", since = "1.27.0")] +#[rustc_const_unstable(feature = "const_swap_nonoverlapping", issue = "133668")] +#[rustc_diagnostic_item = "ptr_swap_nonoverlapping"] +pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { + #[allow(unused)] + macro_rules! attempt_swap_as_chunks { + ($ChunkTy:ty) => { + if mem::align_of::() >= mem::align_of::<$ChunkTy>() + && mem::size_of::() % mem::size_of::<$ChunkTy>() == 0 + { + let x: *mut $ChunkTy = x.cast(); + let y: *mut $ChunkTy = y.cast(); + let count = count * (mem::size_of::() / mem::size_of::<$ChunkTy>()); + // SAFETY: these are the same bytes that the caller promised were + // ok, just typed as `MaybeUninit`s instead of as `T`s. + // The `if` condition above ensures that we're not violating + // alignment requirements, and that the division is exact so + // that we don't lose any bytes off the end. + return unsafe { swap_nonoverlapping_simple_untyped(x, y, count) }; + } + }; + } + + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null \ + and the specified memory ranges do not overlap", + ( + x: *mut () = x as *mut (), + y: *mut () = y as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + count: usize = count, + ) => { + let zero_size = size == 0 || count == 0; + ub_checks::maybe_is_aligned_and_not_null(x, align, zero_size) + && ub_checks::maybe_is_aligned_and_not_null(y, align, zero_size) + && ub_checks::maybe_is_nonoverlapping(x, y, size, count) + } + ); + + // Split up the slice into small power-of-two-sized chunks that LLVM is able + // to vectorize (unless it's a special type with more-than-pointer alignment, + // because we don't want to pessimize things like slices of SIMD vectors.) + if mem::align_of::() <= mem::size_of::() + && (!mem::size_of::().is_power_of_two() + || mem::size_of::() > mem::size_of::() * 2) + { + attempt_swap_as_chunks!(usize); + attempt_swap_as_chunks!(u8); + } + + // SAFETY: Same preconditions as this function + unsafe { swap_nonoverlapping_simple_untyped(x, y, count) } +} + +/// Same behavior and safety conditions as [`swap_nonoverlapping`] +/// +/// LLVM can vectorize this (at least it can for the power-of-two-sized types +/// `swap_nonoverlapping` tries to use) so no need to manually SIMD it. +#[inline] +const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, count: usize) { + let x = x.cast::>(); + let y = y.cast::>(); + let mut i = 0; + while i < count { + // SAFETY: By precondition, `i` is in-bounds because it's below `n` + let x = unsafe { x.add(i) }; + // SAFETY: By precondition, `i` is in-bounds because it's below `n` + // and it's distinct from `x` since the ranges are non-overlapping + let y = unsafe { y.add(i) }; + + // If we end up here, it's because we're using a simple type -- like + // a small power-of-two-sized thing -- or a special type with particularly + // large alignment, particularly SIMD types. + // Thus, we're fine just reading-and-writing it, as either it's small + // and that works well anyway or it's special and the type's author + // presumably wanted things to be done in the larger chunk. + + // SAFETY: we're only ever given pointers that are valid to read/write, + // including being aligned, and nothing here panics so it's drop-safe. + unsafe { + let a: MaybeUninit = read(x); + let b: MaybeUninit = read(y); + write(x, b); + write(y, a); + } + + i += 1; + } +} + +/// Moves `src` into the pointed `dst`, returning the previous `dst` value. +/// +/// Neither value is dropped. +/// +/// This function is semantically equivalent to [`mem::replace`] except that it +/// operates on raw pointers instead of references. When references are +/// available, [`mem::replace`] should be preferred. +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `dst` must be [valid] for both reads and writes. +/// +/// * `dst` must be properly aligned. +/// +/// * `dst` must point to a properly initialized value of type `T`. +/// +/// Note that even if `T` has size `0`, the pointer must be properly aligned. +/// +/// [valid]: self#safety +/// +/// # Examples +/// +/// ``` +/// use std::ptr; +/// +/// let mut rust = vec!['b', 'u', 's', 't']; +/// +/// // `mem::replace` would have the same effect without requiring the unsafe +/// // block. +/// let b = unsafe { +/// ptr::replace(&mut rust[0], 'r') +/// }; +/// +/// assert_eq!(b, 'b'); +/// assert_eq!(rust, &['r', 'u', 's', 't']); +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_replace", since = "1.83.0")] +#[rustc_diagnostic_item = "ptr_replace"] +pub const unsafe fn replace(dst: *mut T, src: T) -> T { + // SAFETY: the caller must guarantee that `dst` is valid to be + // cast to a mutable reference (valid for writes, aligned, initialized), + // and cannot overlap `src` since `dst` must point to a distinct + // allocated object. + unsafe { + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::replace requires that the pointer argument is aligned and non-null", + ( + addr: *const () = dst as *const (), + align: usize = align_of::(), + is_zst: bool = T::IS_ZST, + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) + ); + mem::replace(&mut *dst, src) + } +} + +/// Reads the value from `src` without moving it. This leaves the +/// memory in `src` unchanged. +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `src` must be [valid] for reads. +/// +/// * `src` must be properly aligned. Use [`read_unaligned`] if this is not the +/// case. +/// +/// * `src` must point to a properly initialized value of type `T`. +/// +/// Note that even if `T` has size `0`, the pointer must be properly aligned. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let x = 12; +/// let y = &x as *const i32; +/// +/// unsafe { +/// assert_eq!(std::ptr::read(y), 12); +/// } +/// ``` +/// +/// Manually implement [`mem::swap`]: +/// +/// ``` +/// use std::ptr; +/// +/// fn swap(a: &mut T, b: &mut T) { +/// unsafe { +/// // Create a bitwise copy of the value at `a` in `tmp`. +/// let tmp = ptr::read(a); +/// +/// // Exiting at this point (either by explicitly returning or by +/// // calling a function which panics) would cause the value in `tmp` to +/// // be dropped while the same value is still referenced by `a`. This +/// // could trigger undefined behavior if `T` is not `Copy`. +/// +/// // Create a bitwise copy of the value at `b` in `a`. +/// // This is safe because mutable references cannot alias. +/// ptr::copy_nonoverlapping(b, a, 1); +/// +/// // As above, exiting here could trigger undefined behavior because +/// // the same value is referenced by `a` and `b`. +/// +/// // Move `tmp` into `b`. +/// ptr::write(b, tmp); +/// +/// // `tmp` has been moved (`write` takes ownership of its second argument), +/// // so nothing is dropped implicitly here. +/// } +/// } +/// +/// let mut foo = "foo".to_owned(); +/// let mut bar = "bar".to_owned(); +/// +/// swap(&mut foo, &mut bar); +/// +/// assert_eq!(foo, "bar"); +/// assert_eq!(bar, "foo"); +/// ``` +/// +/// ## Ownership of the Returned Value +/// +/// `read` creates a bitwise copy of `T`, regardless of whether `T` is [`Copy`]. +/// If `T` is not [`Copy`], using both the returned value and the value at +/// `*src` can violate memory safety. Note that assigning to `*src` counts as a +/// use because it will attempt to drop the value at `*src`. +/// +/// [`write()`] can be used to overwrite data without causing it to be dropped. +/// +/// ``` +/// use std::ptr; +/// +/// let mut s = String::from("foo"); +/// unsafe { +/// // `s2` now points to the same underlying memory as `s`. +/// let mut s2: String = ptr::read(&s); +/// +/// assert_eq!(s2, "foo"); +/// +/// // Assigning to `s2` causes its original value to be dropped. Beyond +/// // this point, `s` must no longer be used, as the underlying memory has +/// // been freed. +/// s2 = String::default(); +/// assert_eq!(s2, ""); +/// +/// // Assigning to `s` would cause the old value to be dropped again, +/// // resulting in undefined behavior. +/// // s = String::from("bar"); // ERROR +/// +/// // `ptr::write` can be used to overwrite a value without dropping it. +/// ptr::write(&mut s, String::from("bar")); +/// } +/// +/// assert_eq!(s, "bar"); +/// ``` +/// +/// [valid]: self#safety +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[rustc_diagnostic_item = "ptr_read"] +pub const unsafe fn read(src: *const T) -> T { + // It would be semantically correct to implement this via `copy_nonoverlapping` + // and `MaybeUninit`, as was done before PR #109035. Calling `assume_init` + // provides enough information to know that this is a typed operation. + + // However, as of March 2023 the compiler was not capable of taking advantage + // of that information. Thus, the implementation here switched to an intrinsic, + // which lowers to `_0 = *src` in MIR, to address a few issues: + // + // - Using `MaybeUninit::assume_init` after a `copy_nonoverlapping` was not + // turning the untyped copy into a typed load. As such, the generated + // `load` in LLVM didn't get various metadata, such as `!range` (#73258), + // `!nonnull`, and `!noundef`, resulting in poorer optimization. + // - Going through the extra local resulted in multiple extra copies, even + // in optimized MIR. (Ignoring StorageLive/Dead, the intrinsic is one + // MIR statement, while the previous implementation was eight.) LLVM + // could sometimes optimize them away, but because `read` is at the core + // of so many things, not having them in the first place improves what we + // hand off to the backend. For example, `mem::replace::` previously + // emitted 4 `alloca` and 6 `memcpy`s, but is now 1 `alloc` and 3 `memcpy`s. + // - In general, this approach keeps us from getting any more bugs (like + // #106369) that boil down to "`read(p)` is worse than `*p`", as this + // makes them look identical to the backend (or other MIR consumers). + // + // Future enhancements to MIR optimizations might well allow this to return + // to the previous implementation, rather than using an intrinsic. + + // SAFETY: the caller must guarantee that `src` is valid for reads. + unsafe { + #[cfg(debug_assertions)] // Too expensive to always enable (for now?) + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::read requires that the pointer argument is aligned and non-null", + ( + addr: *const () = src as *const (), + align: usize = align_of::(), + is_zst: bool = T::IS_ZST, + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) + ); + crate::intrinsics::read_via_copy(src) + } +} + +/// Reads the value from `src` without moving it. This leaves the +/// memory in `src` unchanged. +/// +/// Unlike [`read`], `read_unaligned` works with unaligned pointers. +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `src` must be [valid] for reads. +/// +/// * `src` must point to a properly initialized value of type `T`. +/// +/// Like [`read`], `read_unaligned` creates a bitwise copy of `T`, regardless of +/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned +/// value and the value at `*src` can [violate memory safety][read-ownership]. +/// +/// Note that even if `T` has size `0`, the pointer must be non-null. +/// +/// [read-ownership]: read#ownership-of-the-returned-value +/// [valid]: self#safety +/// +/// ## On `packed` structs +/// +/// Attempting to create a raw pointer to an `unaligned` struct field with +/// an expression such as `&packed.unaligned as *const FieldType` creates an +/// intermediate unaligned reference before converting that to a raw pointer. +/// That this reference is temporary and immediately cast is inconsequential +/// as the compiler always expects references to be properly aligned. +/// As a result, using `&packed.unaligned as *const FieldType` causes immediate +/// *undefined behavior* in your program. +/// +/// Instead you must use the `&raw const` syntax to create the pointer. +/// You may use that constructed pointer together with this function. +/// +/// An example of what not to do and how this relates to `read_unaligned` is: +/// +/// ``` +/// #[repr(packed, C)] +/// struct Packed { +/// _padding: u8, +/// unaligned: u32, +/// } +/// +/// let packed = Packed { +/// _padding: 0x00, +/// unaligned: 0x01020304, +/// }; +/// +/// // Take the address of a 32-bit integer which is not aligned. +/// // In contrast to `&packed.unaligned as *const _`, this has no undefined behavior. +/// let unaligned = &raw const packed.unaligned; +/// +/// let v = unsafe { std::ptr::read_unaligned(unaligned) }; +/// assert_eq!(v, 0x01020304); +/// ``` +/// +/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however. +/// +/// # Examples +/// +/// Read a `usize` value from a byte buffer: +/// +/// ``` +/// use std::mem; +/// +/// fn read_usize(x: &[u8]) -> usize { +/// assert!(x.len() >= mem::size_of::()); +/// +/// let ptr = x.as_ptr() as *const usize; +/// +/// unsafe { ptr.read_unaligned() } +/// } +/// ``` +#[inline] +#[stable(feature = "ptr_unaligned", since = "1.17.0")] +#[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[rustc_diagnostic_item = "ptr_read_unaligned"] +pub const unsafe fn read_unaligned(src: *const T) -> T { + let mut tmp = MaybeUninit::::uninit(); + // SAFETY: the caller must guarantee that `src` is valid for reads. + // `src` cannot overlap `tmp` because `tmp` was just allocated on + // the stack as a separate allocated object. + // + // Also, since we just wrote a valid value into `tmp`, it is guaranteed + // to be properly initialized. + unsafe { + copy_nonoverlapping(src as *const u8, tmp.as_mut_ptr() as *mut u8, mem::size_of::()); + tmp.assume_init() + } +} + +/// Overwrites a memory location with the given value without reading or +/// dropping the old value. +/// +/// `write` does not drop the contents of `dst`. This is safe, but it could leak +/// allocations or resources, so care should be taken not to overwrite an object +/// that should be dropped. +/// +/// Additionally, it does not drop `src`. Semantically, `src` is moved into the +/// location pointed to by `dst`. +/// +/// This is appropriate for initializing uninitialized memory, or overwriting +/// memory that has previously been [`read`] from. +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `dst` must be [valid] for writes. +/// +/// * `dst` must be properly aligned. Use [`write_unaligned`] if this is not the +/// case. +/// +/// Note that even if `T` has size `0`, the pointer must be properly aligned. +/// +/// [valid]: self#safety +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let mut x = 0; +/// let y = &mut x as *mut i32; +/// let z = 12; +/// +/// unsafe { +/// std::ptr::write(y, z); +/// assert_eq!(std::ptr::read(y), 12); +/// } +/// ``` +/// +/// Manually implement [`mem::swap`]: +/// +/// ``` +/// use std::ptr; +/// +/// fn swap(a: &mut T, b: &mut T) { +/// unsafe { +/// // Create a bitwise copy of the value at `a` in `tmp`. +/// let tmp = ptr::read(a); +/// +/// // Exiting at this point (either by explicitly returning or by +/// // calling a function which panics) would cause the value in `tmp` to +/// // be dropped while the same value is still referenced by `a`. This +/// // could trigger undefined behavior if `T` is not `Copy`. +/// +/// // Create a bitwise copy of the value at `b` in `a`. +/// // This is safe because mutable references cannot alias. +/// ptr::copy_nonoverlapping(b, a, 1); +/// +/// // As above, exiting here could trigger undefined behavior because +/// // the same value is referenced by `a` and `b`. +/// +/// // Move `tmp` into `b`. +/// ptr::write(b, tmp); +/// +/// // `tmp` has been moved (`write` takes ownership of its second argument), +/// // so nothing is dropped implicitly here. +/// } +/// } +/// +/// let mut foo = "foo".to_owned(); +/// let mut bar = "bar".to_owned(); +/// +/// swap(&mut foo, &mut bar); +/// +/// assert_eq!(foo, "bar"); +/// assert_eq!(bar, "foo"); +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] +#[rustc_diagnostic_item = "ptr_write"] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub const unsafe fn write(dst: *mut T, src: T) { + // Semantically, it would be fine for this to be implemented as a + // `copy_nonoverlapping` and appropriate drop suppression of `src`. + + // However, implementing via that currently produces more MIR than is ideal. + // Using an intrinsic keeps it down to just the simple `*dst = move src` in + // MIR (11 statements shorter, at the time of writing), and also allows + // `src` to stay an SSA value in codegen_ssa, rather than a memory one. + + // SAFETY: the caller must guarantee that `dst` is valid for writes. + // `dst` cannot overlap `src` because the caller has mutable access + // to `dst` while `src` is owned by this function. + unsafe { + #[cfg(debug_assertions)] // Too expensive to always enable (for now?) + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::write requires that the pointer argument is aligned and non-null", + ( + addr: *mut () = dst as *mut (), + align: usize = align_of::(), + is_zst: bool = T::IS_ZST, + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) + ); + intrinsics::write_via_move(dst, src) + } +} + +/// Overwrites a memory location with the given value without reading or +/// dropping the old value. +/// +/// Unlike [`write()`], the pointer may be unaligned. +/// +/// `write_unaligned` does not drop the contents of `dst`. This is safe, but it +/// could leak allocations or resources, so care should be taken not to overwrite +/// an object that should be dropped. +/// +/// Additionally, it does not drop `src`. Semantically, `src` is moved into the +/// location pointed to by `dst`. +/// +/// This is appropriate for initializing uninitialized memory, or overwriting +/// memory that has previously been read with [`read_unaligned`]. +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `dst` must be [valid] for writes. +/// +/// Note that even if `T` has size `0`, the pointer must be non-null. +/// +/// [valid]: self#safety +/// +/// ## On `packed` structs +/// +/// Attempting to create a raw pointer to an `unaligned` struct field with +/// an expression such as `&packed.unaligned as *const FieldType` creates an +/// intermediate unaligned reference before converting that to a raw pointer. +/// That this reference is temporary and immediately cast is inconsequential +/// as the compiler always expects references to be properly aligned. +/// As a result, using `&packed.unaligned as *const FieldType` causes immediate +/// *undefined behavior* in your program. +/// +/// Instead, you must use the `&raw mut` syntax to create the pointer. +/// You may use that constructed pointer together with this function. +/// +/// An example of how to do it and how this relates to `write_unaligned` is: +/// +/// ``` +/// #[repr(packed, C)] +/// struct Packed { +/// _padding: u8, +/// unaligned: u32, +/// } +/// +/// let mut packed: Packed = unsafe { std::mem::zeroed() }; +/// +/// // Take the address of a 32-bit integer which is not aligned. +/// // In contrast to `&packed.unaligned as *mut _`, this has no undefined behavior. +/// let unaligned = &raw mut packed.unaligned; +/// +/// unsafe { std::ptr::write_unaligned(unaligned, 42) }; +/// +/// assert_eq!({packed.unaligned}, 42); // `{...}` forces copying the field instead of creating a reference. +/// ``` +/// +/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however +/// (as can be seen in the `assert_eq!` above). +/// +/// # Examples +/// +/// Write a `usize` value to a byte buffer: +/// +/// ``` +/// use std::mem; +/// +/// fn write_usize(x: &mut [u8], val: usize) { +/// assert!(x.len() >= mem::size_of::()); +/// +/// let ptr = x.as_mut_ptr() as *mut usize; +/// +/// unsafe { ptr.write_unaligned(val) } +/// } +/// ``` +#[inline] +#[stable(feature = "ptr_unaligned", since = "1.17.0")] +#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] +#[rustc_diagnostic_item = "ptr_write_unaligned"] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub const unsafe fn write_unaligned(dst: *mut T, src: T) { + // SAFETY: the caller must guarantee that `dst` is valid for writes. + // `dst` cannot overlap `src` because the caller has mutable access + // to `dst` while `src` is owned by this function. + unsafe { + copy_nonoverlapping((&raw const src) as *const u8, dst as *mut u8, mem::size_of::()); + // We are calling the intrinsic directly to avoid function calls in the generated code. + intrinsics::forget(src); + } +} + +/// Performs a volatile read of the value from `src` without moving it. This +/// leaves the memory in `src` unchanged. +/// +/// Volatile operations are intended to act on I/O memory, and are guaranteed +/// to not be elided or reordered by the compiler across other volatile +/// operations. +/// +/// # Notes +/// +/// Rust does not currently have a rigorously and formally defined memory model, +/// so the precise semantics of what "volatile" means here is subject to change +/// over time. That being said, the semantics will almost always end up pretty +/// similar to [C11's definition of volatile][c11]. +/// +/// The compiler shouldn't change the relative order or number of volatile +/// memory operations. However, volatile memory operations on zero-sized types +/// (e.g., if a zero-sized type is passed to `read_volatile`) are noops +/// and may be ignored. +/// +/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `src` must be [valid] for reads. +/// +/// * `src` must be properly aligned. +/// +/// * `src` must point to a properly initialized value of type `T`. +/// +/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of +/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned +/// value and the value at `*src` can [violate memory safety][read-ownership]. +/// However, storing non-[`Copy`] types in volatile memory is almost certainly +/// incorrect. +/// +/// Note that even if `T` has size `0`, the pointer must be properly aligned. +/// +/// [valid]: self#safety +/// [read-ownership]: read#ownership-of-the-returned-value +/// +/// Just like in C, whether an operation is volatile has no bearing whatsoever +/// on questions involving concurrent access from multiple threads. Volatile +/// accesses behave exactly like non-atomic accesses in that regard. In particular, +/// a race between a `read_volatile` and any write operation to the same location +/// is undefined behavior. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let x = 12; +/// let y = &x as *const i32; +/// +/// unsafe { +/// assert_eq!(std::ptr::read_volatile(y), 12); +/// } +/// ``` +#[inline] +#[stable(feature = "volatile", since = "1.9.0")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[rustc_diagnostic_item = "ptr_read_volatile"] +pub unsafe fn read_volatile(src: *const T) -> T { + // SAFETY: the caller must uphold the safety contract for `volatile_load`. + unsafe { + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::read_volatile requires that the pointer argument is aligned and non-null", + ( + addr: *const () = src as *const (), + align: usize = align_of::(), + is_zst: bool = T::IS_ZST, + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) + ); + intrinsics::volatile_load(src) + } +} + +/// Performs a volatile write of a memory location with the given value without +/// reading or dropping the old value. +/// +/// Volatile operations are intended to act on I/O memory, and are guaranteed +/// to not be elided or reordered by the compiler across other volatile +/// operations. +/// +/// `write_volatile` does not drop the contents of `dst`. This is safe, but it +/// could leak allocations or resources, so care should be taken not to overwrite +/// an object that should be dropped. +/// +/// Additionally, it does not drop `src`. Semantically, `src` is moved into the +/// location pointed to by `dst`. +/// +/// # Notes +/// +/// Rust does not currently have a rigorously and formally defined memory model, +/// so the precise semantics of what "volatile" means here is subject to change +/// over time. That being said, the semantics will almost always end up pretty +/// similar to [C11's definition of volatile][c11]. +/// +/// The compiler shouldn't change the relative order or number of volatile +/// memory operations. However, volatile memory operations on zero-sized types +/// (e.g., if a zero-sized type is passed to `write_volatile`) are noops +/// and may be ignored. +/// +/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `dst` must be [valid] for writes. +/// +/// * `dst` must be properly aligned. +/// +/// Note that even if `T` has size `0`, the pointer must be properly aligned. +/// +/// [valid]: self#safety +/// +/// Just like in C, whether an operation is volatile has no bearing whatsoever +/// on questions involving concurrent access from multiple threads. Volatile +/// accesses behave exactly like non-atomic accesses in that regard. In particular, +/// a race between a `write_volatile` and any other operation (reading or writing) +/// on the same location is undefined behavior. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let mut x = 0; +/// let y = &mut x as *mut i32; +/// let z = 12; +/// +/// unsafe { +/// std::ptr::write_volatile(y, z); +/// assert_eq!(std::ptr::read_volatile(y), 12); +/// } +/// ``` +#[inline] +#[stable(feature = "volatile", since = "1.9.0")] +#[rustc_diagnostic_item = "ptr_write_volatile"] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub unsafe fn write_volatile(dst: *mut T, src: T) { + // SAFETY: the caller must uphold the safety contract for `volatile_store`. + unsafe { + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::write_volatile requires that the pointer argument is aligned and non-null", + ( + addr: *mut () = dst as *mut (), + align: usize = align_of::(), + is_zst: bool = T::IS_ZST, + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) + ); + intrinsics::volatile_store(dst, src); + } +} + +/// Align pointer `p`. +/// +/// Calculate offset (in terms of elements of `size_of::()` stride) that has to be applied +/// to pointer `p` so that pointer `p` would get aligned to `a`. +/// +/// # Safety +/// `a` must be a power of two. +/// +/// # Notes +/// This implementation has been carefully tailored to not panic. It is UB for this to panic. +/// The only real change that can be made here is change of `INV_TABLE_MOD_16` and associated +/// constants. +/// +/// If we ever decide to make it possible to call the intrinsic with `a` that is not a +/// power-of-two, it will probably be more prudent to just change to a naive implementation rather +/// than trying to adapt this to accommodate that change. +/// +/// Any questions go to @nagisa. +#[allow(ptr_to_integer_transmute_in_consts)] +pub(crate) unsafe fn align_offset(p: *const T, a: usize) -> usize { + // FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <= + // 1, where the method versions of these operations are not inlined. + use intrinsics::{ + assume, cttz_nonzero, exact_div, mul_with_overflow, unchecked_rem, unchecked_shl, + unchecked_shr, unchecked_sub, wrapping_add, wrapping_mul, wrapping_sub, + }; + + /// Calculate multiplicative modular inverse of `x` modulo `m`. + /// + /// This implementation is tailored for `align_offset` and has following preconditions: + /// + /// * `m` is a power-of-two; + /// * `x < m`; (if `x ≥ m`, pass in `x % m` instead) + /// + /// Implementation of this function shall not panic. Ever. + #[inline] + const unsafe fn mod_inv(x: usize, m: usize) -> usize { + /// Multiplicative modular inverse table modulo 2⁴ = 16. + /// + /// Note, that this table does not contain values where inverse does not exist (i.e., for + /// `0⁻¹ mod 16`, `2⁻¹ mod 16`, etc.) + const INV_TABLE_MOD_16: [u8; 8] = [1, 11, 13, 7, 9, 3, 5, 15]; + /// Modulo for which the `INV_TABLE_MOD_16` is intended. + const INV_TABLE_MOD: usize = 16; + + // SAFETY: `m` is required to be a power-of-two, hence non-zero. + let m_minus_one = unsafe { unchecked_sub(m, 1) }; + let mut inverse = INV_TABLE_MOD_16[(x & (INV_TABLE_MOD - 1)) >> 1] as usize; + let mut mod_gate = INV_TABLE_MOD; + // We iterate "up" using the following formula: + // + // $$ xy ≡ 1 (mod 2ⁿ) → xy (2 - xy) ≡ 1 (mod 2²ⁿ) $$ + // + // This application needs to be applied at least until `2²ⁿ ≥ m`, at which point we can + // finally reduce the computation to our desired `m` by taking `inverse mod m`. + // + // This computation is `O(log log m)`, which is to say, that on 64-bit machines this loop + // will always finish in at most 4 iterations. + loop { + // y = y * (2 - xy) mod n + // + // Note, that we use wrapping operations here intentionally – the original formula + // uses e.g., subtraction `mod n`. It is entirely fine to do them `mod + // usize::MAX` instead, because we take the result `mod n` at the end + // anyway. + if mod_gate >= m { + break; + } + inverse = wrapping_mul(inverse, wrapping_sub(2usize, wrapping_mul(x, inverse))); + let (new_gate, overflow) = mul_with_overflow(mod_gate, mod_gate); + if overflow { + break; + } + mod_gate = new_gate; + } + inverse & m_minus_one + } + + let stride = mem::size_of::(); + + let addr: usize = p.addr(); + + // SAFETY: `a` is a power-of-two, therefore non-zero. + let a_minus_one = unsafe { unchecked_sub(a, 1) }; + + if stride == 0 { + // SPECIAL_CASE: handle 0-sized types. No matter how many times we step, the address will + // stay the same, so no offset will be able to align the pointer unless it is already + // aligned. This branch _will_ be optimized out as `stride` is known at compile-time. + let p_mod_a = addr & a_minus_one; + return if p_mod_a == 0 { 0 } else { usize::MAX }; + } + + // SAFETY: `stride == 0` case has been handled by the special case above. + let a_mod_stride = unsafe { unchecked_rem(a, stride) }; + if a_mod_stride == 0 { + // SPECIAL_CASE: In cases where the `a` is divisible by `stride`, byte offset to align a + // pointer can be computed more simply through `-p (mod a)`. In the off-chance the byte + // offset is not a multiple of `stride`, the input pointer was misaligned and no pointer + // offset will be able to produce a `p` aligned to the specified `a`. + // + // The naive `-p (mod a)` equation inhibits LLVM's ability to select instructions + // like `lea`. We compute `(round_up_to_next_alignment(p, a) - p)` instead. This + // redistributes operations around the load-bearing, but pessimizing `and` instruction + // sufficiently for LLVM to be able to utilize the various optimizations it knows about. + // + // LLVM handles the branch here particularly nicely. If this branch needs to be evaluated + // at runtime, it will produce a mask `if addr_mod_stride == 0 { 0 } else { usize::MAX }` + // in a branch-free way and then bitwise-OR it with whatever result the `-p mod a` + // computation produces. + + let aligned_address = wrapping_add(addr, a_minus_one) & wrapping_sub(0, a); + let byte_offset = wrapping_sub(aligned_address, addr); + // FIXME: Remove the assume after + // SAFETY: Masking by `-a` can only affect the low bits, and thus cannot have reduced + // the value by more than `a-1`, so even though the intermediate values might have + // wrapped, the byte_offset is always in `[0, a)`. + unsafe { assume(byte_offset < a) }; + + // SAFETY: `stride == 0` case has been handled by the special case above. + let addr_mod_stride = unsafe { unchecked_rem(addr, stride) }; + + return if addr_mod_stride == 0 { + // SAFETY: `stride` is non-zero. This is guaranteed to divide exactly as well, because + // addr has been verified to be aligned to the original type’s alignment requirements. + unsafe { exact_div(byte_offset, stride) } + } else { + usize::MAX + }; + } + + // GENERAL_CASE: From here on we’re handling the very general case where `addr` may be + // misaligned, there isn’t an obvious relationship between `stride` and `a` that we can take an + // advantage of, etc. This case produces machine code that isn’t particularly high quality, + // compared to the special cases above. The code produced here is still within the realm of + // miracles, given the situations this case has to deal with. + + // SAFETY: a is power-of-two hence non-zero. stride == 0 case is handled above. + // FIXME(const-hack) replace with min + let gcdpow = unsafe { + let x = cttz_nonzero(stride); + let y = cttz_nonzero(a); + if x < y { x } else { y } + }; + // SAFETY: gcdpow has an upper-bound that’s at most the number of bits in a `usize`. + let gcd = unsafe { unchecked_shl(1usize, gcdpow) }; + // SAFETY: gcd is always greater or equal to 1. + if addr & unsafe { unchecked_sub(gcd, 1) } == 0 { + // This branch solves for the following linear congruence equation: + // + // ` p + so = 0 mod a ` + // + // `p` here is the pointer value, `s` - stride of `T`, `o` offset in `T`s, and `a` - the + // requested alignment. + // + // With `g = gcd(a, s)`, and the above condition asserting that `p` is also divisible by + // `g`, we can denote `a' = a/g`, `s' = s/g`, `p' = p/g`, then this becomes equivalent to: + // + // ` p' + s'o = 0 mod a' ` + // ` o = (a' - (p' mod a')) * (s'^-1 mod a') ` + // + // The first term is "the relative alignment of `p` to `a`" (divided by the `g`), the + // second term is "how does incrementing `p` by `s` bytes change the relative alignment of + // `p`" (again divided by `g`). Division by `g` is necessary to make the inverse well + // formed if `a` and `s` are not co-prime. + // + // Furthermore, the result produced by this solution is not "minimal", so it is necessary + // to take the result `o mod lcm(s, a)`. This `lcm(s, a)` is the same as `a'`. + + // SAFETY: `gcdpow` has an upper-bound not greater than the number of trailing 0-bits in + // `a`. + let a2 = unsafe { unchecked_shr(a, gcdpow) }; + // SAFETY: `a2` is non-zero. Shifting `a` by `gcdpow` cannot shift out any of the set bits + // in `a` (of which it has exactly one). + let a2minus1 = unsafe { unchecked_sub(a2, 1) }; + // SAFETY: `gcdpow` has an upper-bound not greater than the number of trailing 0-bits in + // `a`. + let s2 = unsafe { unchecked_shr(stride & a_minus_one, gcdpow) }; + // SAFETY: `gcdpow` has an upper-bound not greater than the number of trailing 0-bits in + // `a`. Furthermore, the subtraction cannot overflow, because `a2 = a >> gcdpow` will + // always be strictly greater than `(p % a) >> gcdpow`. + let minusp2 = unsafe { unchecked_sub(a2, unchecked_shr(addr & a_minus_one, gcdpow)) }; + // SAFETY: `a2` is a power-of-two, as proven above. `s2` is strictly less than `a2` + // because `(s % a) >> gcdpow` is strictly less than `a >> gcdpow`. + return wrapping_mul(minusp2, unsafe { mod_inv(s2, a2) }) & a2minus1; + } + + // Cannot be aligned at all. + usize::MAX +} + +/// Compares raw pointers for equality. +/// +/// This is the same as using the `==` operator, but less generic: +/// the arguments have to be `*const T` raw pointers, +/// not anything that implements `PartialEq`. +/// +/// This can be used to compare `&T` references (which coerce to `*const T` implicitly) +/// by their address rather than comparing the values they point to +/// (which is what the `PartialEq for &T` implementation does). +/// +/// When comparing wide pointers, both the address and the metadata are tested for equality. +/// However, note that comparing trait object pointers (`*const dyn Trait`) is unreliable: pointers +/// to values of the same underlying type can compare inequal (because vtables are duplicated in +/// multiple codegen units), and pointers to values of *different* underlying type can compare equal +/// (since identical vtables can be deduplicated within a codegen unit). +/// +/// # Examples +/// +/// ``` +/// use std::ptr; +/// +/// let five = 5; +/// let other_five = 5; +/// let five_ref = &five; +/// let same_five_ref = &five; +/// let other_five_ref = &other_five; +/// +/// assert!(five_ref == same_five_ref); +/// assert!(ptr::eq(five_ref, same_five_ref)); +/// +/// assert!(five_ref == other_five_ref); +/// assert!(!ptr::eq(five_ref, other_five_ref)); +/// ``` +/// +/// Slices are also compared by their length (fat pointers): +/// +/// ``` +/// let a = [1, 2, 3]; +/// assert!(std::ptr::eq(&a[..3], &a[..3])); +/// assert!(!std::ptr::eq(&a[..2], &a[..3])); +/// assert!(!std::ptr::eq(&a[0..2], &a[1..3])); +/// ``` +#[stable(feature = "ptr_eq", since = "1.17.0")] +#[inline(always)] +#[must_use = "pointer comparison produces a value"] +#[rustc_diagnostic_item = "ptr_eq"] +#[allow(ambiguous_wide_pointer_comparisons)] // it's actually clear here +pub fn eq(a: *const T, b: *const T) -> bool { + a == b +} + +/// Compares the *addresses* of the two pointers for equality, +/// ignoring any metadata in fat pointers. +/// +/// If the arguments are thin pointers of the same type, +/// then this is the same as [`eq`]. +/// +/// # Examples +/// +/// ``` +/// use std::ptr; +/// +/// let whole: &[i32; 3] = &[1, 2, 3]; +/// let first: &i32 = &whole[0]; +/// +/// assert!(ptr::addr_eq(whole, first)); +/// assert!(!ptr::eq::(whole, first)); +/// ``` +#[stable(feature = "ptr_addr_eq", since = "1.76.0")] +#[inline(always)] +#[must_use = "pointer comparison produces a value"] +pub fn addr_eq(p: *const T, q: *const U) -> bool { + (p as *const ()) == (q as *const ()) +} + +/// Compares the *addresses* of the two function pointers for equality. +/// +/// This is the same as `f == g`, but using this function makes clear that the potentially +/// surprising semantics of function pointer comparison are involved. +/// +/// There are **very few guarantees** about how functions are compiled and they have no intrinsic +/// “identity”; in particular, this comparison: +/// +/// * May return `true` unexpectedly, in cases where functions are equivalent. +/// +/// For example, the following program is likely (but not guaranteed) to print `(true, true)` +/// when compiled with optimization: +/// +/// ``` +/// let f: fn(i32) -> i32 = |x| x; +/// let g: fn(i32) -> i32 = |x| x + 0; // different closure, different body +/// let h: fn(u32) -> u32 = |x| x + 0; // different signature too +/// dbg!(std::ptr::fn_addr_eq(f, g), std::ptr::fn_addr_eq(f, h)); // not guaranteed to be equal +/// ``` +/// +/// * May return `false` in any case. +/// +/// This is particularly likely with generic functions but may happen with any function. +/// (From an implementation perspective, this is possible because functions may sometimes be +/// processed more than once by the compiler, resulting in duplicate machine code.) +/// +/// Despite these false positives and false negatives, this comparison can still be useful. +/// Specifically, if +/// +/// * `T` is the same type as `U`, `T` is a [subtype] of `U`, or `U` is a [subtype] of `T`, and +/// * `ptr::fn_addr_eq(f, g)` returns true, +/// +/// then calling `f` and calling `g` will be equivalent. +/// +/// +/// # Examples +/// +/// ``` +/// use std::ptr; +/// +/// fn a() { println!("a"); } +/// fn b() { println!("b"); } +/// assert!(!ptr::fn_addr_eq(a as fn(), b as fn())); +/// ``` +/// +/// [subtype]: https://doc.rust-lang.org/reference/subtyping.html +#[stable(feature = "ptr_fn_addr_eq", since = "CURRENT_RUSTC_VERSION")] +#[inline(always)] +#[must_use = "function pointer comparison produces a value"] +pub fn fn_addr_eq(f: T, g: U) -> bool { + f.addr() == g.addr() +} + +/// Hash a raw pointer. +/// +/// This can be used to hash a `&T` reference (which coerces to `*const T` implicitly) +/// by its address rather than the value it points to +/// (which is what the `Hash for &T` implementation does). +/// +/// # Examples +/// +/// ``` +/// use std::hash::{DefaultHasher, Hash, Hasher}; +/// use std::ptr; +/// +/// let five = 5; +/// let five_ref = &five; +/// +/// let mut hasher = DefaultHasher::new(); +/// ptr::hash(five_ref, &mut hasher); +/// let actual = hasher.finish(); +/// +/// let mut hasher = DefaultHasher::new(); +/// (five_ref as *const i32).hash(&mut hasher); +/// let expected = hasher.finish(); +/// +/// assert_eq!(actual, expected); +/// ``` +#[stable(feature = "ptr_hash", since = "1.35.0")] +pub fn hash(hashee: *const T, into: &mut S) { + use crate::hash::Hash; + hashee.hash(into); +} + +#[stable(feature = "fnptr_impls", since = "1.4.0")] +impl PartialEq for F { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.addr() == other.addr() + } +} +#[stable(feature = "fnptr_impls", since = "1.4.0")] +impl Eq for F {} + +#[stable(feature = "fnptr_impls", since = "1.4.0")] +impl PartialOrd for F { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + self.addr().partial_cmp(&other.addr()) + } +} +#[stable(feature = "fnptr_impls", since = "1.4.0")] +impl Ord for F { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.addr().cmp(&other.addr()) + } +} + +#[stable(feature = "fnptr_impls", since = "1.4.0")] +impl hash::Hash for F { + fn hash(&self, state: &mut HH) { + state.write_usize(self.addr() as _) + } +} + +#[stable(feature = "fnptr_impls", since = "1.4.0")] +impl fmt::Pointer for F { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::pointer_fmt_inner(self.addr() as _, f) + } +} + +#[stable(feature = "fnptr_impls", since = "1.4.0")] +impl fmt::Debug for F { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::pointer_fmt_inner(self.addr() as _, f) + } +} + +/// Creates a `const` raw pointer to a place, without creating an intermediate reference. +/// +/// `addr_of!(expr)` is equivalent to `&raw const expr`. The macro is *soft-deprecated*; +/// use `&raw const` instead. +/// +/// It is still an open question under which conditions writing through an `addr_of!`-created +/// pointer is permitted. If the place `expr` evaluates to is based on a raw pointer, then the +/// result of `addr_of!` inherits all permissions from that raw pointer. However, if the place is +/// based on a reference, local variable, or `static`, then until all details are decided, the same +/// rules as for shared references apply: it is UB to write through a pointer created with this +/// operation, except for bytes located inside an `UnsafeCell`. Use `&raw mut` (or [`addr_of_mut`]) +/// to create a raw pointer that definitely permits mutation. +/// +/// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned +/// and points to initialized data. For cases where those requirements do not hold, +/// raw pointers should be used instead. However, `&expr as *const _` creates a reference +/// before casting it to a raw pointer, and that reference is subject to the same rules +/// as all other references. This macro can create a raw pointer *without* creating +/// a reference first. +/// +/// See [`addr_of_mut`] for how to create a pointer to uninitialized data. +/// Doing that with `addr_of` would not make much sense since one could only +/// read the data, and that would be Undefined Behavior. +/// +/// # Safety +/// +/// The `expr` in `addr_of!(expr)` is evaluated as a place expression, but never loads from the +/// place or requires the place to be dereferenceable. This means that `addr_of!((*ptr).field)` +/// still requires the projection to `field` to be in-bounds, using the same rules as [`offset`]. +/// However, `addr_of!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned. +/// +/// Note that `Deref`/`Index` coercions (and their mutable counterparts) are applied inside +/// `addr_of!` like everywhere else, in which case a reference is created to call `Deref::deref` or +/// `Index::index`, respectively. The statements above only apply when no such coercions are +/// applied. +/// +/// [`offset`]: pointer::offset +/// +/// # Example +/// +/// **Correct usage: Creating a pointer to unaligned data** +/// +/// ``` +/// use std::ptr; +/// +/// #[repr(packed)] +/// struct Packed { +/// f1: u8, +/// f2: u16, +/// } +/// +/// let packed = Packed { f1: 1, f2: 2 }; +/// // `&packed.f2` would create an unaligned reference, and thus be Undefined Behavior! +/// let raw_f2 = ptr::addr_of!(packed.f2); +/// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2); +/// ``` +/// +/// **Incorrect usage: Out-of-bounds fields projection** +/// +/// ```rust,no_run +/// use std::ptr; +/// +/// #[repr(C)] +/// struct MyStruct { +/// field1: i32, +/// field2: i32, +/// } +/// +/// let ptr: *const MyStruct = ptr::null(); +/// let fieldptr = unsafe { ptr::addr_of!((*ptr).field2) }; // Undefined Behavior ⚠️ +/// ``` +/// +/// The field projection `.field2` would offset the pointer by 4 bytes, +/// but the pointer is not in-bounds of an allocation for 4 bytes, +/// so this offset is Undefined Behavior. +/// See the [`offset`] docs for a full list of requirements for inbounds pointer arithmetic; the +/// same requirements apply to field projections, even inside `addr_of!`. (In particular, it makes +/// no difference whether the pointer is null or dangling.) +#[stable(feature = "raw_ref_macros", since = "1.51.0")] +#[rustc_macro_transparency = "semitransparent"] +pub macro addr_of($place:expr) { + &raw const $place +} + +/// Creates a `mut` raw pointer to a place, without creating an intermediate reference. +/// +/// `addr_of_mut!(expr)` is equivalent to `&raw mut expr`. The macro is *soft-deprecated*; +/// use `&raw mut` instead. +/// +/// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned +/// and points to initialized data. For cases where those requirements do not hold, +/// raw pointers should be used instead. However, `&mut expr as *mut _` creates a reference +/// before casting it to a raw pointer, and that reference is subject to the same rules +/// as all other references. This macro can create a raw pointer *without* creating +/// a reference first. +/// +/// # Safety +/// +/// The `expr` in `addr_of_mut!(expr)` is evaluated as a place expression, but never loads from the +/// place or requires the place to be dereferenceable. This means that `addr_of_mut!((*ptr).field)` +/// still requires the projection to `field` to be in-bounds, using the same rules as [`offset`]. +/// However, `addr_of_mut!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned. +/// +/// Note that `Deref`/`Index` coercions (and their mutable counterparts) are applied inside +/// `addr_of_mut!` like everywhere else, in which case a reference is created to call `Deref::deref` +/// or `Index::index`, respectively. The statements above only apply when no such coercions are +/// applied. +/// +/// [`offset`]: pointer::offset +/// +/// # Examples +/// +/// **Correct usage: Creating a pointer to unaligned data** +/// +/// ``` +/// use std::ptr; +/// +/// #[repr(packed)] +/// struct Packed { +/// f1: u8, +/// f2: u16, +/// } +/// +/// let mut packed = Packed { f1: 1, f2: 2 }; +/// // `&mut packed.f2` would create an unaligned reference, and thus be Undefined Behavior! +/// let raw_f2 = ptr::addr_of_mut!(packed.f2); +/// unsafe { raw_f2.write_unaligned(42); } +/// assert_eq!({packed.f2}, 42); // `{...}` forces copying the field instead of creating a reference. +/// ``` +/// +/// **Correct usage: Creating a pointer to uninitialized data** +/// +/// ```rust +/// use std::{ptr, mem::MaybeUninit}; +/// +/// struct Demo { +/// field: bool, +/// } +/// +/// let mut uninit = MaybeUninit::::uninit(); +/// // `&uninit.as_mut().field` would create a reference to an uninitialized `bool`, +/// // and thus be Undefined Behavior! +/// let f1_ptr = unsafe { ptr::addr_of_mut!((*uninit.as_mut_ptr()).field) }; +/// unsafe { f1_ptr.write(true); } +/// let init = unsafe { uninit.assume_init() }; +/// ``` +/// +/// **Incorrect usage: Out-of-bounds fields projection** +/// +/// ```rust,no_run +/// use std::ptr; +/// +/// #[repr(C)] +/// struct MyStruct { +/// field1: i32, +/// field2: i32, +/// } +/// +/// let ptr: *mut MyStruct = ptr::null_mut(); +/// let fieldptr = unsafe { ptr::addr_of_mut!((*ptr).field2) }; // Undefined Behavior ⚠️ +/// ``` +/// +/// The field projection `.field2` would offset the pointer by 4 bytes, +/// but the pointer is not in-bounds of an allocation for 4 bytes, +/// so this offset is Undefined Behavior. +/// See the [`offset`] docs for a full list of requirements for inbounds pointer arithmetic; the +/// same requirements apply to field projections, even inside `addr_of_mut!`. (In particular, it +/// makes no difference whether the pointer is null or dangling.) +#[stable(feature = "raw_ref_macros", since = "1.51.0")] +#[rustc_macro_transparency = "semitransparent"] +pub macro addr_of_mut($place:expr) { + &raw mut $place +} diff --git a/CoqOfRust/core/ptr/mut_ptr.rs b/CoqOfRust/core/ptr/mut_ptr.rs new file mode 100644 index 000000000..6d0361b8c --- /dev/null +++ b/CoqOfRust/core/ptr/mut_ptr.rs @@ -0,0 +1,2124 @@ +use super::*; +use crate::cmp::Ordering::{Equal, Greater, Less}; +use crate::intrinsics::const_eval_select; +use crate::mem::SizedTypeProperties; +use crate::slice::{self, SliceIndex}; + +impl *mut T { + /// Returns `true` if the pointer is null. + /// + /// Note that unsized types have many possible null pointers, as only the + /// raw data pointer is considered, not their length, vtable, etc. + /// Therefore, two pointers that are null may still not compare equal to + /// each other. + /// + /// ## Behavior during const evaluation + /// + /// When this function is used during const evaluation, it may return `false` for pointers + /// that turn out to be null at runtime. Specifically, when a pointer to some memory + /// is offset beyond its bounds in such a way that the resulting pointer is null, + /// the function will still return `false`. There is no way for CTFE to know + /// the absolute position of that memory, so we cannot tell if the pointer is + /// null or not. + /// + /// # Examples + /// + /// ``` + /// let mut s = [1, 2, 3]; + /// let ptr: *mut u32 = s.as_mut_ptr(); + /// assert!(!ptr.is_null()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] + #[rustc_diagnostic_item = "ptr_is_null"] + #[inline] + pub const fn is_null(self) -> bool { + self.cast_const().is_null() + } + + /// Casts to a pointer of another type. + #[stable(feature = "ptr_cast", since = "1.38.0")] + #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")] + #[rustc_diagnostic_item = "ptr_cast"] + #[inline(always)] + pub const fn cast(self) -> *mut U { + self as _ + } + + /// Uses the address value in a new pointer of another type. + /// + /// This operation will ignore the address part of its `meta` operand and discard existing + /// metadata of `self`. For pointers to a sized types (thin pointers), this has the same effect + /// as a simple cast. For pointers to an unsized type (fat pointers) this recombines the address + /// with new metadata such as slice lengths or `dyn`-vtable. + /// + /// The resulting pointer will have provenance of `self`. This operation is semantically the + /// same as creating a new pointer with the data pointer value of `self` but the metadata of + /// `meta`, being fat or thin depending on the `meta` operand. + /// + /// # Examples + /// + /// This function is primarily useful for enabling pointer arithmetic on potentially fat + /// pointers. The pointer is cast to a sized pointee to utilize offset operations and then + /// recombined with its own original metadata. + /// + /// ``` + /// #![feature(set_ptr_value)] + /// # use core::fmt::Debug; + /// let mut arr: [i32; 3] = [1, 2, 3]; + /// let mut ptr = arr.as_mut_ptr() as *mut dyn Debug; + /// let thin = ptr as *mut u8; + /// unsafe { + /// ptr = thin.add(8).with_metadata_of(ptr); + /// # assert_eq!(*(ptr as *mut i32), 3); + /// println!("{:?}", &*ptr); // will print "3" + /// } + /// ``` + /// + /// # *Incorrect* usage + /// + /// The provenance from pointers is *not* combined. The result must only be used to refer to the + /// address allowed by `self`. + /// + /// ```rust,no_run + /// #![feature(set_ptr_value)] + /// let mut x = 0u32; + /// let mut y = 1u32; + /// + /// let x = (&mut x) as *mut u32; + /// let y = (&mut y) as *mut u32; + /// + /// let offset = (x as usize - y as usize) / 4; + /// let bad = x.wrapping_add(offset).with_metadata_of(y); + /// + /// // This dereference is UB. The pointer only has provenance for `x` but points to `y`. + /// println!("{:?}", unsafe { &*bad }); + #[unstable(feature = "set_ptr_value", issue = "75091")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[inline] + pub const fn with_metadata_of(self, meta: *const U) -> *mut U + where + U: ?Sized, + { + from_raw_parts_mut::(self as *mut (), metadata(meta)) + } + + /// Changes constness without changing the type. + /// + /// This is a bit safer than `as` because it wouldn't silently change the type if the code is + /// refactored. + /// + /// While not strictly required (`*mut T` coerces to `*const T`), this is provided for symmetry + /// with [`cast_mut`] on `*const T` and may have documentation value if used instead of implicit + /// coercion. + /// + /// [`cast_mut`]: pointer::cast_mut + #[stable(feature = "ptr_const_cast", since = "1.65.0")] + #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")] + #[rustc_diagnostic_item = "ptr_cast_const"] + #[inline(always)] + pub const fn cast_const(self) -> *const T { + self as _ + } + + /// Gets the "address" portion of the pointer. + /// + /// This is similar to `self as usize`, except that the [provenance][crate::ptr#provenance] of + /// the pointer is discarded and not [exposed][crate::ptr#exposed-provenance]. This means that + /// casting the returned address back to a pointer yields a [pointer without + /// provenance][without_provenance_mut], which is undefined behavior to dereference. To properly + /// restore the lost information and obtain a dereferenceable pointer, use + /// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. + /// + /// If using those APIs is not possible because there is no way to preserve a pointer with the + /// required provenance, then Strict Provenance might not be for you. Use pointer-integer casts + /// or [`expose_provenance`][pointer::expose_provenance] and [`with_exposed_provenance`][with_exposed_provenance] + /// instead. However, note that this makes your code less portable and less amenable to tools + /// that check for compliance with the Rust memory model. + /// + /// On most platforms this will produce a value with the same bytes as the original + /// pointer, because all the bytes are dedicated to describing the address. + /// Platforms which need to store additional information in the pointer may + /// perform a change of representation to produce a value containing only the address + /// portion of the pointer. What that means is up to the platform to define. + /// + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. + #[must_use] + #[inline(always)] + #[stable(feature = "strict_provenance", since = "1.84.0")] + pub fn addr(self) -> usize { + // A pointer-to-integer transmute currently has exactly the right semantics: it returns the + // address without exposing the provenance. Note that this is *not* a stable guarantee about + // transmute semantics, it relies on sysroot crates having special status. + // SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the + // provenance). + unsafe { mem::transmute(self.cast::<()>()) } + } + + /// Exposes the ["provenance"][crate::ptr#provenance] part of the pointer for future use in + /// [`with_exposed_provenance_mut`] and returns the "address" portion. + /// + /// This is equivalent to `self as usize`, which semantically discards provenance information. + /// Furthermore, this (like the `as` cast) has the implicit side-effect of marking the + /// provenance as 'exposed', so on platforms that support it you can later call + /// [`with_exposed_provenance_mut`] to reconstitute the original pointer including its provenance. + /// + /// Due to its inherent ambiguity, [`with_exposed_provenance_mut`] may not be supported by tools + /// that help you to stay conformant with the Rust memory model. It is recommended to use + /// [Strict Provenance][crate::ptr#strict-provenance] APIs such as [`with_addr`][pointer::with_addr] + /// wherever possible, in which case [`addr`][pointer::addr] should be used instead of `expose_provenance`. + /// + /// On most platforms this will produce a value with the same bytes as the original pointer, + /// because all the bytes are dedicated to describing the address. Platforms which need to store + /// additional information in the pointer may not support this operation, since the 'expose' + /// side-effect which is required for [`with_exposed_provenance_mut`] to work is typically not + /// available. + /// + /// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API. + /// + /// [`with_exposed_provenance_mut`]: with_exposed_provenance_mut + #[inline(always)] + #[stable(feature = "exposed_provenance", since = "1.84.0")] + pub fn expose_provenance(self) -> usize { + self.cast::<()>() as usize + } + + /// Creates a new pointer with the given address and the [provenance][crate::ptr#provenance] of + /// `self`. + /// + /// This is similar to a `addr as *mut T` cast, but copies + /// the *provenance* of `self` to the new pointer. + /// This avoids the inherent ambiguity of the unary cast. + /// + /// This is equivalent to using [`wrapping_offset`][pointer::wrapping_offset] to offset + /// `self` to the given address, and therefore has all the same capabilities and restrictions. + /// + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. + #[must_use] + #[inline] + #[stable(feature = "strict_provenance", since = "1.84.0")] + pub fn with_addr(self, addr: usize) -> Self { + // This should probably be an intrinsic to avoid doing any sort of arithmetic, but + // meanwhile, we can implement it with `wrapping_offset`, which preserves the pointer's + // provenance. + let self_addr = self.addr() as isize; + let dest_addr = addr as isize; + let offset = dest_addr.wrapping_sub(self_addr); + self.wrapping_byte_offset(offset) + } + + /// Creates a new pointer by mapping `self`'s address to a new one, preserving the original + /// pointer's [provenance][crate::ptr#provenance]. + /// + /// This is a convenience for [`with_addr`][pointer::with_addr], see that method for details. + /// + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. + #[must_use] + #[inline] + #[stable(feature = "strict_provenance", since = "1.84.0")] + pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self { + self.with_addr(f(self.addr())) + } + + /// Decompose a (possibly wide) pointer into its data pointer and metadata components. + /// + /// The pointer can be later reconstructed with [`from_raw_parts_mut`]. + #[unstable(feature = "ptr_metadata", issue = "81513")] + #[inline] + pub const fn to_raw_parts(self) -> (*mut (), ::Metadata) { + (self.cast(), super::metadata(self)) + } + + /// Returns `None` if the pointer is null, or else returns a shared reference to + /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_ref`] + /// must be used instead. + /// + /// For the mutable counterpart see [`as_mut`]. + /// + /// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1 + /// [`as_mut`]: #method.as_mut + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* the pointer is null *or* + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// + /// # Examples + /// + /// ``` + /// let ptr: *mut u8 = &mut 10u8 as *mut u8; + /// + /// unsafe { + /// if let Some(val_back) = ptr.as_ref() { + /// println!("We got back the value: {val_back}!"); + /// } + /// } + /// ``` + /// + /// # Null-unchecked version + /// + /// If you are sure the pointer can never be null and are looking for some kind of + /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can + /// dereference the pointer directly. + /// + /// ``` + /// let ptr: *mut u8 = &mut 10u8 as *mut u8; + /// + /// unsafe { + /// let val_back = &*ptr; + /// println!("We got back the value: {val_back}!"); + /// } + /// ``` + #[stable(feature = "ptr_as_ref", since = "1.9.0")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] + #[inline] + pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { + // SAFETY: the caller must guarantee that `self` is valid for a + // reference if it isn't null. + if self.is_null() { None } else { unsafe { Some(&*self) } } + } + + /// Returns a shared reference to the value behind the pointer. + /// If the pointer may be null or the value may be uninitialized, [`as_uninit_ref`] must be used instead. + /// If the pointer may be null, but the value is known to have been initialized, [`as_ref`] must be used instead. + /// + /// For the mutable counterpart see [`as_mut_unchecked`]. + /// + /// [`as_ref`]: #method.as_ref + /// [`as_uninit_ref`]: #method.as_uninit_ref + /// [`as_mut_unchecked`]: #method.as_mut_unchecked + /// + /// # Safety + /// + /// When calling this method, you have to ensure that the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_as_ref_unchecked)] + /// let ptr: *mut u8 = &mut 10u8 as *mut u8; + /// + /// unsafe { + /// println!("We got back the value: {}!", ptr.as_ref_unchecked()); + /// } + /// ``` + // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. + #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[inline] + #[must_use] + pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { + // SAFETY: the caller must guarantee that `self` is valid for a reference + unsafe { &*self } + } + + /// Returns `None` if the pointer is null, or else returns a shared reference to + /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require + /// that the value has to be initialized. + /// + /// For the mutable counterpart see [`as_uninit_mut`]. + /// + /// [`as_ref`]: pointer#method.as_ref-1 + /// [`as_uninit_mut`]: #method.as_uninit_mut + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* the pointer is null *or* + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// Note that because the created reference is to `MaybeUninit`, the + /// source pointer can point to uninitialized memory. + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_as_uninit)] + /// + /// let ptr: *mut u8 = &mut 10u8 as *mut u8; + /// + /// unsafe { + /// if let Some(val_back) = ptr.as_uninit_ref() { + /// println!("We got back the value: {}!", val_back.assume_init()); + /// } + /// } + /// ``` + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> + where + T: Sized, + { + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a reference. + if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit) }) } + } + + /// Adds a signed offset to a pointer. + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined Behavior: + /// + /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without + /// "wrapping around"), must fit in an `isize`. + /// + /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. + /// + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. + /// + /// Consider using [`wrapping_offset`] instead if these constraints are + /// difficult to satisfy. The only advantage of this method is that it + /// enables more aggressive compiler optimizations. + /// + /// [`wrapping_offset`]: #method.wrapping_offset + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// let mut s = [1, 2, 3]; + /// let ptr: *mut u32 = s.as_mut_ptr(); + /// + /// unsafe { + /// assert_eq!(2, *ptr.offset(1)); + /// assert_eq!(3, *ptr.offset(2)); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn offset(self, count: isize) -> *mut T + where + T: Sized, + { + #[inline] + #[rustc_allow_const_fn_unstable(const_eval_select)] + const fn runtime_offset_nowrap(this: *const (), count: isize, size: usize) -> bool { + // We can use const_eval_select here because this is only for UB checks. + const_eval_select!( + @capture { this: *const (), count: isize, size: usize } -> bool: + if const { + true + } else { + // `size` is the size of a Rust type, so we know that + // `size <= isize::MAX` and thus `as` cast here is not lossy. + let Some(byte_offset) = count.checked_mul(size as isize) else { + return false; + }; + let (_, overflow) = this.addr().overflowing_add_signed(byte_offset); + !overflow + } + ) + } + + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::offset requires the address calculation to not overflow", + ( + this: *const () = self as *const (), + count: isize = count, + size: usize = size_of::(), + ) => runtime_offset_nowrap(this, count, size) + ); + + // SAFETY: the caller must uphold the safety contract for `offset`. + // The obtained pointer is valid for writes since the caller must + // guarantee that it points to the same allocated object as `self`. + unsafe { intrinsics::offset(self, count) } + } + + /// Adds a signed offset in bytes to a pointer. + /// + /// `count` is in units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [offset][pointer::offset] on it. See that method for documentation + /// and safety requirements. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_offset(self, count: isize) -> Self { + // SAFETY: the caller must uphold the safety contract for `offset`. + unsafe { self.cast::().offset(count).with_metadata_of(self) } + } + + /// Adds a signed offset to a pointer using wrapping arithmetic. + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// This operation itself is always safe, but using the resulting pointer is not. + /// + /// The resulting pointer "remembers" the [allocated object] that `self` points to; it must not + /// be used to read or write other allocated objects. + /// + /// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z` + /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still + /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless + /// `x` and `y` point into the same allocated object. + /// + /// Compared to [`offset`], this method basically delays the requirement of staying within the + /// same allocated object: [`offset`] is immediate Undefined Behavior when crossing object + /// boundaries; `wrapping_offset` produces a pointer but still leads to Undefined Behavior if a + /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`offset`] + /// can be optimized better and is thus preferable in performance-sensitive code. + /// + /// The delayed check only considers the value of the pointer that was dereferenced, not the + /// intermediate values used during the computation of the final result. For example, + /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other + /// words, leaving the allocated object and then re-entering it later is permitted. + /// + /// [`offset`]: #method.offset + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// // Iterate using a raw pointer in increments of two elements + /// let mut data = [1u8, 2, 3, 4, 5]; + /// let mut ptr: *mut u8 = data.as_mut_ptr(); + /// let step = 2; + /// let end_rounded_up = ptr.wrapping_offset(6); + /// + /// while ptr != end_rounded_up { + /// unsafe { + /// *ptr = 0; + /// } + /// ptr = ptr.wrapping_offset(step); + /// } + /// assert_eq!(&data, &[0, 2, 0, 4, 0]); + /// ``` + #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[inline(always)] + pub const fn wrapping_offset(self, count: isize) -> *mut T + where + T: Sized, + { + // SAFETY: the `arith_offset` intrinsic has no prerequisites to be called. + unsafe { intrinsics::arith_offset(self, count) as *mut T } + } + + /// Adds a signed offset in bytes to a pointer using wrapping arithmetic. + /// + /// `count` is in units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [wrapping_offset][pointer::wrapping_offset] on it. See that method + /// for documentation. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + pub const fn wrapping_byte_offset(self, count: isize) -> Self { + self.cast::().wrapping_offset(count).with_metadata_of(self) + } + + /// Masks out bits of the pointer according to a mask. + /// + /// This is convenience for `ptr.map_addr(|a| a & mask)`. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + /// + /// ## Examples + /// + /// ``` + /// #![feature(ptr_mask)] + /// let mut v = 17_u32; + /// let ptr: *mut u32 = &mut v; + /// + /// // `u32` is 4 bytes aligned, + /// // which means that lower 2 bits are always 0. + /// let tag_mask = 0b11; + /// let ptr_mask = !tag_mask; + /// + /// // We can store something in these lower bits + /// let tagged_ptr = ptr.map_addr(|a| a | 0b10); + /// + /// // Get the "tag" back + /// let tag = tagged_ptr.addr() & tag_mask; + /// assert_eq!(tag, 0b10); + /// + /// // Note that `tagged_ptr` is unaligned, it's UB to read from/write to it. + /// // To get original pointer `mask` can be used: + /// let masked_ptr = tagged_ptr.mask(ptr_mask); + /// assert_eq!(unsafe { *masked_ptr }, 17); + /// + /// unsafe { *masked_ptr = 0 }; + /// assert_eq!(v, 0); + /// ``` + #[unstable(feature = "ptr_mask", issue = "98290")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[inline(always)] + pub fn mask(self, mask: usize) -> *mut T { + intrinsics::ptr_mask(self.cast::<()>(), mask).cast_mut().with_metadata_of(self) + } + + /// Returns `None` if the pointer is null, or else returns a unique reference to + /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_mut`] + /// must be used instead. + /// + /// For the shared counterpart see [`as_ref`]. + /// + /// [`as_uninit_mut`]: #method.as_uninit_mut + /// [`as_ref`]: pointer#method.as_ref-1 + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* + /// the pointer is null *or* + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// + /// + /// # Examples + /// + /// ``` + /// let mut s = [1, 2, 3]; + /// let ptr: *mut u32 = s.as_mut_ptr(); + /// let first_value = unsafe { ptr.as_mut().unwrap() }; + /// *first_value = 4; + /// # assert_eq!(s, [4, 2, 3]); + /// println!("{s:?}"); // It'll print: "[4, 2, 3]". + /// ``` + /// + /// # Null-unchecked version + /// + /// If you are sure the pointer can never be null and are looking for some kind of + /// `as_mut_unchecked` that returns the `&mut T` instead of `Option<&mut T>`, know that + /// you can dereference the pointer directly. + /// + /// ``` + /// let mut s = [1, 2, 3]; + /// let ptr: *mut u32 = s.as_mut_ptr(); + /// let first_value = unsafe { &mut *ptr }; + /// *first_value = 4; + /// # assert_eq!(s, [4, 2, 3]); + /// println!("{s:?}"); // It'll print: "[4, 2, 3]". + /// ``` + #[stable(feature = "ptr_as_ref", since = "1.9.0")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] + #[inline] + pub const unsafe fn as_mut<'a>(self) -> Option<&'a mut T> { + // SAFETY: the caller must guarantee that `self` is be valid for + // a mutable reference if it isn't null. + if self.is_null() { None } else { unsafe { Some(&mut *self) } } + } + + /// Returns a unique reference to the value behind the pointer. + /// If the pointer may be null or the value may be uninitialized, [`as_uninit_mut`] must be used instead. + /// If the pointer may be null, but the value is known to have been initialized, [`as_mut`] must be used instead. + /// + /// For the shared counterpart see [`as_ref_unchecked`]. + /// + /// [`as_mut`]: #method.as_mut + /// [`as_uninit_mut`]: #method.as_uninit_mut + /// [`as_ref_unchecked`]: #method.as_mut_unchecked + /// + /// # Safety + /// + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_as_ref_unchecked)] + /// let mut s = [1, 2, 3]; + /// let ptr: *mut u32 = s.as_mut_ptr(); + /// let first_value = unsafe { ptr.as_mut_unchecked() }; + /// *first_value = 4; + /// # assert_eq!(s, [4, 2, 3]); + /// println!("{s:?}"); // It'll print: "[4, 2, 3]". + /// ``` + // FIXME: mention it in the docs for `as_mut` and `as_uninit_mut` once stabilized. + #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[inline] + #[must_use] + pub const unsafe fn as_mut_unchecked<'a>(self) -> &'a mut T { + // SAFETY: the caller must guarantee that `self` is valid for a reference + unsafe { &mut *self } + } + + /// Returns `None` if the pointer is null, or else returns a unique reference to + /// the value wrapped in `Some`. In contrast to [`as_mut`], this does not require + /// that the value has to be initialized. + /// + /// For the shared counterpart see [`as_uninit_ref`]. + /// + /// [`as_mut`]: #method.as_mut + /// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1 + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* the pointer is null *or* + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub const unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit> + where + T: Sized, + { + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a reference. + if self.is_null() { None } else { Some(unsafe { &mut *(self as *mut MaybeUninit) }) } + } + + /// Returns whether two pointers are guaranteed to be equal. + /// + /// At runtime this function behaves like `Some(self == other)`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine equality of two pointers, so this function may + /// spuriously return `None` for pointers that later actually turn out to have its equality known. + /// But when it returns `Some`, the pointers' equality is guaranteed to be known. + /// + /// The return value may change from `Some` to `None` and vice versa depending on the compiler + /// version and unsafe code must not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `None` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + pub const fn guaranteed_eq(self, other: *mut T) -> Option + where + T: Sized, + { + (self as *const T).guaranteed_eq(other as _) + } + + /// Returns whether two pointers are guaranteed to be inequal. + /// + /// At runtime this function behaves like `Some(self != other)`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine inequality of two pointers, so this function may + /// spuriously return `None` for pointers that later actually turn out to have its inequality known. + /// But when it returns `Some`, the pointers' inequality is guaranteed to be known. + /// + /// The return value may change from `Some` to `None` and vice versa depending on the compiler + /// version and unsafe code must not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `None` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + pub const fn guaranteed_ne(self, other: *mut T) -> Option + where + T: Sized, + { + (self as *const T).guaranteed_ne(other as _) + } + + /// Calculates the distance between two pointers within the same allocation. The returned value is in + /// units of T: the distance in bytes divided by `mem::size_of::()`. + /// + /// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::() as isize)`, + /// except that it has a lot more opportunities for UB, in exchange for the compiler + /// better understanding what you are doing. + /// + /// The primary motivation of this method is for computing the `len` of an array/slice + /// of `T` that you are currently representing as a "start" and "end" pointer + /// (and "end" is "one past the end" of the array). + /// In that case, `end.offset_from(start)` gets you the length of the array. + /// + /// All of the following safety requirements are trivially satisfied for this usecase. + /// + /// [`offset`]: pointer#method.offset-1 + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined Behavior: + /// + /// * `self` and `origin` must either + /// + /// * point to the same address, or + /// * both be [derived from][crate::ptr#provenance] a pointer to the same [allocated object], and the memory range between + /// the two pointers must be in bounds of that object. (See below for an example.) + /// + /// * The distance between the pointers, in bytes, must be an exact multiple + /// of the size of `T`. + /// + /// As a consequence, the absolute distance between the pointers, in bytes, computed on + /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is + /// implied by the in-bounds requirement, and the fact that no allocated object can be larger + /// than `isize::MAX` bytes. + /// + /// The requirement for pointers to be derived from the same allocated object is primarily + /// needed for `const`-compatibility: the distance between pointers into *different* allocated + /// objects is not known at compile-time. However, the requirement also exists at + /// runtime and may be exploited by optimizations. If you wish to compute the difference between + /// pointers that are not guaranteed to be from the same allocation, use `(self as isize - + /// origin as isize) / mem::size_of::()`. + // FIXME: recommend `addr()` instead of `as usize` once that is stable. + /// + /// [`add`]: #method.add + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Panics + /// + /// This function panics if `T` is a Zero-Sized Type ("ZST"). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut a = [0; 5]; + /// let ptr1: *mut i32 = &mut a[1]; + /// let ptr2: *mut i32 = &mut a[3]; + /// unsafe { + /// assert_eq!(ptr2.offset_from(ptr1), 2); + /// assert_eq!(ptr1.offset_from(ptr2), -2); + /// assert_eq!(ptr1.offset(2), ptr2); + /// assert_eq!(ptr2.offset(-2), ptr1); + /// } + /// ``` + /// + /// *Incorrect* usage: + /// + /// ```rust,no_run + /// let ptr1 = Box::into_raw(Box::new(0u8)); + /// let ptr2 = Box::into_raw(Box::new(1u8)); + /// let diff = (ptr2 as isize).wrapping_sub(ptr1 as isize); + /// // Make ptr2_other an "alias" of ptr2.add(1), but derived from ptr1. + /// let ptr2_other = (ptr1 as *mut u8).wrapping_offset(diff).wrapping_offset(1); + /// assert_eq!(ptr2 as usize, ptr2_other as usize); + /// // Since ptr2_other and ptr2 are derived from pointers to different objects, + /// // computing their offset is undefined behavior, even though + /// // they point to addresses that are in-bounds of the same object! + /// unsafe { + /// let one = ptr2_other.offset_from(ptr2); // Undefined Behavior! ⚠️ + /// } + /// ``` + #[stable(feature = "ptr_offset_from", since = "1.47.0")] + #[rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn offset_from(self, origin: *const T) -> isize + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `offset_from`. + unsafe { (self as *const T).offset_from(origin) } + } + + /// Calculates the distance between two pointers within the same allocation. The returned value is in + /// units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`offset_from`][pointer::offset_from] on it. See that method for + /// documentation and safety requirements. + /// + /// For non-`Sized` pointees this operation considers only the data pointers, + /// ignoring the metadata. + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_offset_from(self, origin: *const U) -> isize { + // SAFETY: the caller must uphold the safety contract for `offset_from`. + unsafe { self.cast::().offset_from(origin.cast::()) } + } + + /// Calculates the distance between two pointers within the same allocation, *where it's known that + /// `self` is equal to or greater than `origin`*. The returned value is in + /// units of T: the distance in bytes is divided by `mem::size_of::()`. + /// + /// This computes the same value that [`offset_from`](#method.offset_from) + /// would compute, but with the added precondition that the offset is + /// guaranteed to be non-negative. This method is equivalent to + /// `usize::try_from(self.offset_from(origin)).unwrap_unchecked()`, + /// but it provides slightly more information to the optimizer, which can + /// sometimes allow it to optimize slightly better with some backends. + /// + /// This method can be thought of as recovering the `count` that was passed + /// to [`add`](#method.add) (or, with the parameters in the other order, + /// to [`sub`](#method.sub)). The following are all equivalent, assuming + /// that their safety preconditions are met: + /// ```rust + /// # #![feature(ptr_sub_ptr)] + /// # unsafe fn blah(ptr: *mut i32, origin: *mut i32, count: usize) -> bool { + /// ptr.sub_ptr(origin) == count + /// # && + /// origin.add(count) == ptr + /// # && + /// ptr.sub(count) == origin + /// # } + /// ``` + /// + /// # Safety + /// + /// - The distance between the pointers must be non-negative (`self >= origin`) + /// + /// - *All* the safety conditions of [`offset_from`](#method.offset_from) + /// apply to this method as well; see it for the full details. + /// + /// Importantly, despite the return type of this method being able to represent + /// a larger offset, it's still *not permitted* to pass pointers which differ + /// by more than `isize::MAX` *bytes*. As such, the result of this method will + /// always be less than or equal to `isize::MAX as usize`. + /// + /// # Panics + /// + /// This function panics if `T` is a Zero-Sized Type ("ZST"). + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_sub_ptr)] + /// + /// let mut a = [0; 5]; + /// let p: *mut i32 = a.as_mut_ptr(); + /// unsafe { + /// let ptr1: *mut i32 = p.add(1); + /// let ptr2: *mut i32 = p.add(3); + /// + /// assert_eq!(ptr2.sub_ptr(ptr1), 2); + /// assert_eq!(ptr1.add(2), ptr2); + /// assert_eq!(ptr2.sub(2), ptr1); + /// assert_eq!(ptr2.sub_ptr(ptr2), 0); + /// } + /// + /// // This would be incorrect, as the pointers are not correctly ordered: + /// // ptr1.offset_from(ptr2) + #[unstable(feature = "ptr_sub_ptr", issue = "95892")] + #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn sub_ptr(self, origin: *const T) -> usize + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `sub_ptr`. + unsafe { (self as *const T).sub_ptr(origin) } + } + + /// Calculates the distance between two pointers within the same allocation, *where it's known that + /// `self` is equal to or greater than `origin`*. The returned value is in + /// units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`sub_ptr`][pointer::sub_ptr] on it. See that method for + /// documentation and safety requirements. + /// + /// For non-`Sized` pointees this operation considers only the data pointers, + /// ignoring the metadata. + #[unstable(feature = "ptr_sub_ptr", issue = "95892")] + #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_sub_ptr(self, origin: *mut U) -> usize { + // SAFETY: the caller must uphold the safety contract for `byte_sub_ptr`. + unsafe { (self as *const T).byte_sub_ptr(origin) } + } + + /// Adds an unsigned offset to a pointer. + /// + /// This can only move the pointer forward (or not move it). If you need to move forward or + /// backward depending on the value, then you might want [`offset`](#method.offset) instead + /// which takes a signed offset. + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined Behavior: + /// + /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without + /// "wrapping around"), must fit in an `isize`. + /// + /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. + /// + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. + /// + /// Consider using [`wrapping_add`] instead if these constraints are + /// difficult to satisfy. The only advantage of this method is that it + /// enables more aggressive compiler optimizations. + /// + /// [`wrapping_add`]: #method.wrapping_add + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// let s: &str = "123"; + /// let ptr: *const u8 = s.as_ptr(); + /// + /// unsafe { + /// assert_eq!('2', *ptr.add(1) as char); + /// assert_eq!('3', *ptr.add(2) as char); + /// } + /// ``` + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn add(self, count: usize) -> Self + where + T: Sized, + { + #[cfg(debug_assertions)] + #[inline] + #[rustc_allow_const_fn_unstable(const_eval_select)] + const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool { + const_eval_select!( + @capture { this: *const (), count: usize, size: usize } -> bool: + if const { + true + } else { + let Some(byte_offset) = count.checked_mul(size) else { + return false; + }; + let (_, overflow) = this.addr().overflowing_add(byte_offset); + byte_offset <= (isize::MAX as usize) && !overflow + } + ) + } + + #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild. + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::add requires that the address calculation does not overflow", + ( + this: *const () = self as *const (), + count: usize = count, + size: usize = size_of::(), + ) => runtime_add_nowrap(this, count, size) + ); + + // SAFETY: the caller must uphold the safety contract for `offset`. + unsafe { intrinsics::offset(self, count) } + } + + /// Adds an unsigned offset in bytes to a pointer. + /// + /// `count` is in units of bytes. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [add][pointer::add] on it. See that method for documentation + /// and safety requirements. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_add(self, count: usize) -> Self { + // SAFETY: the caller must uphold the safety contract for `add`. + unsafe { self.cast::().add(count).with_metadata_of(self) } + } + + /// Subtracts an unsigned offset from a pointer. + /// + /// This can only move the pointer backward (or not move it). If you need to move forward or + /// backward depending on the value, then you might want [`offset`](#method.offset) instead + /// which takes a signed offset. + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined Behavior: + /// + /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without + /// "wrapping around"), must fit in an `isize`. + /// + /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. + /// + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. + /// + /// Consider using [`wrapping_sub`] instead if these constraints are + /// difficult to satisfy. The only advantage of this method is that it + /// enables more aggressive compiler optimizations. + /// + /// [`wrapping_sub`]: #method.wrapping_sub + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// let s: &str = "123"; + /// + /// unsafe { + /// let end: *const u8 = s.as_ptr().add(3); + /// assert_eq!('3', *end.sub(1) as char); + /// assert_eq!('2', *end.sub(2) as char); + /// } + /// ``` + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn sub(self, count: usize) -> Self + where + T: Sized, + { + #[cfg(debug_assertions)] + #[inline] + #[rustc_allow_const_fn_unstable(const_eval_select)] + const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool { + const_eval_select!( + @capture { this: *const (), count: usize, size: usize } -> bool: + if const { + true + } else { + let Some(byte_offset) = count.checked_mul(size) else { + return false; + }; + byte_offset <= (isize::MAX as usize) && this.addr() >= byte_offset + } + ) + } + + #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild. + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::sub requires that the address calculation does not overflow", + ( + this: *const () = self as *const (), + count: usize = count, + size: usize = size_of::(), + ) => runtime_sub_nowrap(this, count, size) + ); + + if T::IS_ZST { + // Pointer arithmetic does nothing when the pointee is a ZST. + self + } else { + // SAFETY: the caller must uphold the safety contract for `offset`. + // Because the pointee is *not* a ZST, that means that `count` is + // at most `isize::MAX`, and thus the negation cannot overflow. + unsafe { intrinsics::offset(self, intrinsics::unchecked_sub(0, count as isize)) } + } + } + + /// Subtracts an unsigned offset in bytes from a pointer. + /// + /// `count` is in units of bytes. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [sub][pointer::sub] on it. See that method for documentation + /// and safety requirements. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_sub(self, count: usize) -> Self { + // SAFETY: the caller must uphold the safety contract for `sub`. + unsafe { self.cast::().sub(count).with_metadata_of(self) } + } + + /// Adds an unsigned offset to a pointer using wrapping arithmetic. + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// This operation itself is always safe, but using the resulting pointer is not. + /// + /// The resulting pointer "remembers" the [allocated object] that `self` points to; it must not + /// be used to read or write other allocated objects. + /// + /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z` + /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still + /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless + /// `x` and `y` point into the same allocated object. + /// + /// Compared to [`add`], this method basically delays the requirement of staying within the + /// same allocated object: [`add`] is immediate Undefined Behavior when crossing object + /// boundaries; `wrapping_add` produces a pointer but still leads to Undefined Behavior if a + /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`add`] + /// can be optimized better and is thus preferable in performance-sensitive code. + /// + /// The delayed check only considers the value of the pointer that was dereferenced, not the + /// intermediate values used during the computation of the final result. For example, + /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the + /// allocated object and then re-entering it later is permitted. + /// + /// [`add`]: #method.add + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// // Iterate using a raw pointer in increments of two elements + /// let data = [1u8, 2, 3, 4, 5]; + /// let mut ptr: *const u8 = data.as_ptr(); + /// let step = 2; + /// let end_rounded_up = ptr.wrapping_add(6); + /// + /// // This loop prints "1, 3, 5, " + /// while ptr != end_rounded_up { + /// unsafe { + /// print!("{}, ", *ptr); + /// } + /// ptr = ptr.wrapping_add(step); + /// } + /// ``` + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[inline(always)] + pub const fn wrapping_add(self, count: usize) -> Self + where + T: Sized, + { + self.wrapping_offset(count as isize) + } + + /// Adds an unsigned offset in bytes to a pointer using wrapping arithmetic. + /// + /// `count` is in units of bytes. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [wrapping_add][pointer::wrapping_add] on it. See that method for documentation. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + pub const fn wrapping_byte_add(self, count: usize) -> Self { + self.cast::().wrapping_add(count).with_metadata_of(self) + } + + /// Subtracts an unsigned offset from a pointer using wrapping arithmetic. + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// This operation itself is always safe, but using the resulting pointer is not. + /// + /// The resulting pointer "remembers" the [allocated object] that `self` points to; it must not + /// be used to read or write other allocated objects. + /// + /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z` + /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still + /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless + /// `x` and `y` point into the same allocated object. + /// + /// Compared to [`sub`], this method basically delays the requirement of staying within the + /// same allocated object: [`sub`] is immediate Undefined Behavior when crossing object + /// boundaries; `wrapping_sub` produces a pointer but still leads to Undefined Behavior if a + /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`sub`] + /// can be optimized better and is thus preferable in performance-sensitive code. + /// + /// The delayed check only considers the value of the pointer that was dereferenced, not the + /// intermediate values used during the computation of the final result. For example, + /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the + /// allocated object and then re-entering it later is permitted. + /// + /// [`sub`]: #method.sub + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// // Iterate using a raw pointer in increments of two elements (backwards) + /// let data = [1u8, 2, 3, 4, 5]; + /// let mut ptr: *const u8 = data.as_ptr(); + /// let start_rounded_down = ptr.wrapping_sub(2); + /// ptr = ptr.wrapping_add(4); + /// let step = 2; + /// // This loop prints "5, 3, 1, " + /// while ptr != start_rounded_down { + /// unsafe { + /// print!("{}, ", *ptr); + /// } + /// ptr = ptr.wrapping_sub(step); + /// } + /// ``` + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[inline(always)] + pub const fn wrapping_sub(self, count: usize) -> Self + where + T: Sized, + { + self.wrapping_offset((count as isize).wrapping_neg()) + } + + /// Subtracts an unsigned offset in bytes from a pointer using wrapping arithmetic. + /// + /// `count` is in units of bytes. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [wrapping_sub][pointer::wrapping_sub] on it. See that method for documentation. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] + pub const fn wrapping_byte_sub(self, count: usize) -> Self { + self.cast::().wrapping_sub(count).with_metadata_of(self) + } + + /// Reads the value from `self` without moving it. This leaves the + /// memory in `self` unchanged. + /// + /// See [`ptr::read`] for safety concerns and examples. + /// + /// [`ptr::read`]: crate::ptr::read() + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn read(self) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for ``. + unsafe { read(self) } + } + + /// Performs a volatile read of the value from `self` without moving it. This + /// leaves the memory in `self` unchanged. + /// + /// Volatile operations are intended to act on I/O memory, and are guaranteed + /// to not be elided or reordered by the compiler across other volatile + /// operations. + /// + /// See [`ptr::read_volatile`] for safety concerns and examples. + /// + /// [`ptr::read_volatile`]: crate::ptr::read_volatile() + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn read_volatile(self) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `read_volatile`. + unsafe { read_volatile(self) } + } + + /// Reads the value from `self` without moving it. This leaves the + /// memory in `self` unchanged. + /// + /// Unlike `read`, the pointer may be unaligned. + /// + /// See [`ptr::read_unaligned`] for safety concerns and examples. + /// + /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned() + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn read_unaligned(self) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `read_unaligned`. + unsafe { read_unaligned(self) } + } + + /// Copies `count * size_of` bytes from `self` to `dest`. The source + /// and destination may overlap. + /// + /// NOTE: this has the *same* argument order as [`ptr::copy`]. + /// + /// See [`ptr::copy`] for safety concerns and examples. + /// + /// [`ptr::copy`]: crate::ptr::copy() + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn copy_to(self, dest: *mut T, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `copy`. + unsafe { copy(self, dest, count) } + } + + /// Copies `count * size_of` bytes from `self` to `dest`. The source + /// and destination may *not* overlap. + /// + /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`]. + /// + /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. + /// + /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `copy_nonoverlapping`. + unsafe { copy_nonoverlapping(self, dest, count) } + } + + /// Copies `count * size_of` bytes from `src` to `self`. The source + /// and destination may overlap. + /// + /// NOTE: this has the *opposite* argument order of [`ptr::copy`]. + /// + /// See [`ptr::copy`] for safety concerns and examples. + /// + /// [`ptr::copy`]: crate::ptr::copy() + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn copy_from(self, src: *const T, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `copy`. + unsafe { copy(src, self, count) } + } + + /// Copies `count * size_of` bytes from `src` to `self`. The source + /// and destination may *not* overlap. + /// + /// NOTE: this has the *opposite* argument order of [`ptr::copy_nonoverlapping`]. + /// + /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. + /// + /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `copy_nonoverlapping`. + unsafe { copy_nonoverlapping(src, self, count) } + } + + /// Executes the destructor (if any) of the pointed-to value. + /// + /// See [`ptr::drop_in_place`] for safety concerns and examples. + /// + /// [`ptr::drop_in_place`]: crate::ptr::drop_in_place() + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[inline(always)] + pub unsafe fn drop_in_place(self) { + // SAFETY: the caller must uphold the safety contract for `drop_in_place`. + unsafe { drop_in_place(self) } + } + + /// Overwrites a memory location with the given value without reading or + /// dropping the old value. + /// + /// See [`ptr::write`] for safety concerns and examples. + /// + /// [`ptr::write`]: crate::ptr::write() + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn write(self, val: T) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `write`. + unsafe { write(self, val) } + } + + /// Invokes memset on the specified pointer, setting `count * size_of::()` + /// bytes of memory starting at `self` to `val`. + /// + /// See [`ptr::write_bytes`] for safety concerns and examples. + /// + /// [`ptr::write_bytes`]: crate::ptr::write_bytes() + #[doc(alias = "memset")] + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn write_bytes(self, val: u8, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `write_bytes`. + unsafe { write_bytes(self, val, count) } + } + + /// Performs a volatile write of a memory location with the given value without + /// reading or dropping the old value. + /// + /// Volatile operations are intended to act on I/O memory, and are guaranteed + /// to not be elided or reordered by the compiler across other volatile + /// operations. + /// + /// See [`ptr::write_volatile`] for safety concerns and examples. + /// + /// [`ptr::write_volatile`]: crate::ptr::write_volatile() + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn write_volatile(self, val: T) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `write_volatile`. + unsafe { write_volatile(self, val) } + } + + /// Overwrites a memory location with the given value without reading or + /// dropping the old value. + /// + /// Unlike `write`, the pointer may be unaligned. + /// + /// See [`ptr::write_unaligned`] for safety concerns and examples. + /// + /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned() + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn write_unaligned(self, val: T) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `write_unaligned`. + unsafe { write_unaligned(self, val) } + } + + /// Replaces the value at `self` with `src`, returning the old + /// value, without dropping either. + /// + /// See [`ptr::replace`] for safety concerns and examples. + /// + /// [`ptr::replace`]: crate::ptr::replace() + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[inline(always)] + pub unsafe fn replace(self, src: T) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `replace`. + unsafe { replace(self, src) } + } + + /// Swaps the values at two mutable locations of the same type, without + /// deinitializing either. They may overlap, unlike `mem::swap` which is + /// otherwise equivalent. + /// + /// See [`ptr::swap`] for safety concerns and examples. + /// + /// [`ptr::swap`]: crate::ptr::swap() + #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_unstable(feature = "const_swap", issue = "83163")] + #[inline(always)] + pub const unsafe fn swap(self, with: *mut T) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `swap`. + unsafe { swap(self, with) } + } + + /// Computes the offset that needs to be applied to the pointer in order to make it aligned to + /// `align`. + /// + /// If it is not possible to align the pointer, the implementation returns + /// `usize::MAX`. + /// + /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be + /// used with the `wrapping_add` method. + /// + /// There are no guarantees whatsoever that offsetting the pointer will not overflow or go + /// beyond the allocation that the pointer points into. It is up to the caller to ensure that + /// the returned offset is correct in all terms other than alignment. + /// + /// When this is called during compile-time evaluation (which is unstable), the implementation + /// may return `usize::MAX` in cases where that can never happen at runtime. This is because the + /// actual alignment of pointers is not known yet during compile-time, so an offset with + /// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8; + /// N]` might be allocated at an odd or an even address, but at compile-time this is not yet + /// known, so the execution has to be correct for either choice. It is therefore impossible to + /// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual + /// for unstable APIs.) + /// + /// # Panics + /// + /// The function panics if `align` is not a power-of-two. + /// + /// # Examples + /// + /// Accessing adjacent `u8` as `u16` + /// + /// ``` + /// use std::mem::align_of; + /// + /// # unsafe { + /// let mut x = [5_u8, 6, 7, 8, 9]; + /// let ptr = x.as_mut_ptr(); + /// let offset = ptr.align_offset(align_of::()); + /// + /// if offset < x.len() - 1 { + /// let u16_ptr = ptr.add(offset).cast::(); + /// *u16_ptr = 0; + /// + /// assert!(x == [0, 0, 7, 8, 9] || x == [5, 0, 0, 8, 9]); + /// } else { + /// // while the pointer can be aligned via `offset`, it would point + /// // outside the allocation + /// } + /// # } + /// ``` + #[must_use] + #[inline] + #[stable(feature = "align_offset", since = "1.36.0")] + pub fn align_offset(self, align: usize) -> usize + where + T: Sized, + { + if !align.is_power_of_two() { + panic!("align_offset: align is not a power-of-two"); + } + + // SAFETY: `align` has been checked to be a power of 2 above + let ret = unsafe { align_offset(self, align) }; + + // Inform Miri that we want to consider the resulting pointer to be suitably aligned. + #[cfg(miri)] + if ret != usize::MAX { + intrinsics::miri_promise_symbolic_alignment( + self.wrapping_add(ret).cast_const().cast(), + align, + ); + } + + ret + } + + /// Returns whether the pointer is properly aligned for `T`. + /// + /// # Examples + /// + /// ``` + /// // On some platforms, the alignment of i32 is less than 4. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// + /// let mut data = AlignedI32(42); + /// let ptr = &mut data as *mut AlignedI32; + /// + /// assert!(ptr.is_aligned()); + /// assert!(!ptr.wrapping_byte_add(1).is_aligned()); + /// ``` + #[must_use] + #[inline] + #[stable(feature = "pointer_is_aligned", since = "1.79.0")] + pub fn is_aligned(self) -> bool + where + T: Sized, + { + self.is_aligned_to(mem::align_of::()) + } + + /// Returns whether the pointer is aligned to `align`. + /// + /// For non-`Sized` pointees this operation considers only the data pointer, + /// ignoring the metadata. + /// + /// # Panics + /// + /// The function panics if `align` is not a power-of-two (this includes 0). + /// + /// # Examples + /// + /// ``` + /// #![feature(pointer_is_aligned_to)] + /// + /// // On some platforms, the alignment of i32 is less than 4. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// + /// let mut data = AlignedI32(42); + /// let ptr = &mut data as *mut AlignedI32; + /// + /// assert!(ptr.is_aligned_to(1)); + /// assert!(ptr.is_aligned_to(2)); + /// assert!(ptr.is_aligned_to(4)); + /// + /// assert!(ptr.wrapping_byte_add(2).is_aligned_to(2)); + /// assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4)); + /// + /// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8)); + /// ``` + #[must_use] + #[inline] + #[unstable(feature = "pointer_is_aligned_to", issue = "96284")] + pub fn is_aligned_to(self, align: usize) -> bool { + if !align.is_power_of_two() { + panic!("is_aligned_to: align is not a power-of-two"); + } + + self.addr() & (align - 1) == 0 + } +} + +impl *mut [T] { + /// Returns the length of a raw slice. + /// + /// The returned value is the number of **elements**, not the number of bytes. + /// + /// This function is safe, even when the raw slice cannot be cast to a slice + /// reference because the pointer is null or unaligned. + /// + /// # Examples + /// + /// ```rust + /// use std::ptr; + /// + /// let slice: *mut [i8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 3); + /// assert_eq!(slice.len(), 3); + /// ``` + #[inline(always)] + #[stable(feature = "slice_ptr_len", since = "1.79.0")] + #[rustc_const_stable(feature = "const_slice_ptr_len", since = "1.79.0")] + pub const fn len(self) -> usize { + metadata(self) + } + + /// Returns `true` if the raw slice has a length of 0. + /// + /// # Examples + /// + /// ``` + /// use std::ptr; + /// + /// let slice: *mut [i8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 3); + /// assert!(!slice.is_empty()); + /// ``` + #[inline(always)] + #[stable(feature = "slice_ptr_len", since = "1.79.0")] + #[rustc_const_stable(feature = "const_slice_ptr_len", since = "1.79.0")] + pub const fn is_empty(self) -> bool { + self.len() == 0 + } + + /// Gets a raw, mutable pointer to the underlying array. + /// + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_mut_array(self) -> Option<*mut [T; N]> { + if self.len() == N { + let me = self.as_mut_ptr() as *mut [T; N]; + Some(me) + } else { + None + } + } + + /// Divides one mutable raw slice into two at an index. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// # Panics + /// + /// Panics if `mid > len`. + /// + /// # Safety + /// + /// `mid` must be [in-bounds] of the underlying [allocated object]. + /// Which means `self` must be dereferenceable and span a single allocation + /// that is at least `mid * size_of::()` bytes long. Not upholding these + /// requirements is *[undefined behavior]* even if the resulting pointers are not used. + /// + /// Since `len` being in-bounds it is not a safety invariant of `*mut [T]` the + /// safety requirements of this method are the same as for [`split_at_mut_unchecked`]. + /// The explicit bounds check is only as useful as `len` is correct. + /// + /// [`split_at_mut_unchecked`]: #method.split_at_mut_unchecked + /// [in-bounds]: #method.add + /// [allocated object]: crate::ptr#allocated-object + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ``` + /// #![feature(raw_slice_split)] + /// #![feature(slice_ptr_get)] + /// + /// let mut v = [1, 0, 3, 0, 5, 6]; + /// let ptr = &mut v as *mut [_]; + /// unsafe { + /// let (left, right) = ptr.split_at_mut(2); + /// assert_eq!(&*left, [1, 0]); + /// assert_eq!(&*right, [3, 0, 5, 6]); + /// } + /// ``` + #[inline(always)] + #[track_caller] + #[unstable(feature = "raw_slice_split", issue = "95595")] + pub unsafe fn split_at_mut(self, mid: usize) -> (*mut [T], *mut [T]) { + assert!(mid <= self.len()); + // SAFETY: The assert above is only a safety-net as long as `self.len()` is correct + // The actual safety requirements of this function are the same as for `split_at_mut_unchecked` + unsafe { self.split_at_mut_unchecked(mid) } + } + + /// Divides one mutable raw slice into two at an index, without doing bounds checking. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// # Safety + /// + /// `mid` must be [in-bounds] of the underlying [allocated object]. + /// Which means `self` must be dereferenceable and span a single allocation + /// that is at least `mid * size_of::()` bytes long. Not upholding these + /// requirements is *[undefined behavior]* even if the resulting pointers are not used. + /// + /// [in-bounds]: #method.add + /// [out-of-bounds index]: #method.add + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ``` + /// #![feature(raw_slice_split)] + /// + /// let mut v = [1, 0, 3, 0, 5, 6]; + /// // scoped to restrict the lifetime of the borrows + /// unsafe { + /// let ptr = &mut v as *mut [_]; + /// let (left, right) = ptr.split_at_mut_unchecked(2); + /// assert_eq!(&*left, [1, 0]); + /// assert_eq!(&*right, [3, 0, 5, 6]); + /// (&mut *left)[1] = 2; + /// (&mut *right)[1] = 4; + /// } + /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); + /// ``` + #[inline(always)] + #[unstable(feature = "raw_slice_split", issue = "95595")] + pub unsafe fn split_at_mut_unchecked(self, mid: usize) -> (*mut [T], *mut [T]) { + let len = self.len(); + let ptr = self.as_mut_ptr(); + + // SAFETY: Caller must pass a valid pointer and an index that is in-bounds. + let tail = unsafe { ptr.add(mid) }; + ( + crate::ptr::slice_from_raw_parts_mut(ptr, mid), + crate::ptr::slice_from_raw_parts_mut(tail, len - mid), + ) + } + + /// Returns a raw pointer to the slice's buffer. + /// + /// This is equivalent to casting `self` to `*mut T`, but more type-safe. + /// + /// # Examples + /// + /// ```rust + /// #![feature(slice_ptr_get)] + /// use std::ptr; + /// + /// let slice: *mut [i8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 3); + /// assert_eq!(slice.as_mut_ptr(), ptr::null_mut()); + /// ``` + #[inline(always)] + #[unstable(feature = "slice_ptr_get", issue = "74265")] + pub const fn as_mut_ptr(self) -> *mut T { + self as *mut T + } + + /// Returns a raw pointer to an element or subslice, without doing bounds + /// checking. + /// + /// Calling this method with an [out-of-bounds index] or when `self` is not dereferenceable + /// is *[undefined behavior]* even if the resulting pointer is not used. + /// + /// [out-of-bounds index]: #method.add + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_ptr_get)] + /// + /// let x = &mut [1, 2, 4] as *mut [i32]; + /// + /// unsafe { + /// assert_eq!(x.get_unchecked_mut(1), x.as_mut_ptr().add(1)); + /// } + /// ``` + #[unstable(feature = "slice_ptr_get", issue = "74265")] + #[inline(always)] + pub unsafe fn get_unchecked_mut(self, index: I) -> *mut I::Output + where + I: SliceIndex<[T]>, + { + // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. + unsafe { index.get_unchecked_mut(self) } + } + + /// Returns `None` if the pointer is null, or else returns a shared slice to + /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require + /// that the value has to be initialized. + /// + /// For the mutable counterpart see [`as_uninit_slice_mut`]. + /// + /// [`as_ref`]: pointer#method.as_ref-1 + /// [`as_uninit_slice_mut`]: #method.as_uninit_slice_mut + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* the pointer is null *or* + /// all of the following is true: + /// + /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::()` many bytes, + /// and it must be properly aligned. This means in particular: + /// + /// * The entire memory range of this slice must be contained within a single [allocated object]! + /// Slices can never span across multiple allocated objects. + /// + /// * The pointer must be aligned even for zero-length slices. One + /// reason for this is that enum layout optimizations may rely on references + /// (including slices of any length) being aligned and non-null to distinguish + /// them from other data. You can obtain a pointer that is usable as `data` + /// for zero-length slices using [`NonNull::dangling()`]. + /// + /// * The total size `ptr.len() * mem::size_of::()` of the slice must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, while this reference exists, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// + /// See also [`slice::from_raw_parts`][]. + /// + /// [valid]: crate::ptr#safety + /// [allocated object]: crate::ptr#allocated-object + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { + if self.is_null() { + None + } else { + // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`. + Some(unsafe { slice::from_raw_parts(self as *const MaybeUninit, self.len()) }) + } + } + + /// Returns `None` if the pointer is null, or else returns a unique slice to + /// the value wrapped in `Some`. In contrast to [`as_mut`], this does not require + /// that the value has to be initialized. + /// + /// For the shared counterpart see [`as_uninit_slice`]. + /// + /// [`as_mut`]: #method.as_mut + /// [`as_uninit_slice`]: #method.as_uninit_slice-1 + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* the pointer is null *or* + /// all of the following is true: + /// + /// * The pointer must be [valid] for reads and writes for `ptr.len() * mem::size_of::()` + /// many bytes, and it must be properly aligned. This means in particular: + /// + /// * The entire memory range of this slice must be contained within a single [allocated object]! + /// Slices can never span across multiple allocated objects. + /// + /// * The pointer must be aligned even for zero-length slices. One + /// reason for this is that enum layout optimizations may rely on references + /// (including slices of any length) being aligned and non-null to distinguish + /// them from other data. You can obtain a pointer that is usable as `data` + /// for zero-length slices using [`NonNull::dangling()`]. + /// + /// * The total size `ptr.len() * mem::size_of::()` of the slice must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, while this reference exists, the memory the pointer points to must + /// not get accessed (read or written) through any other pointer. + /// + /// This applies even if the result of this method is unused! + /// + /// See also [`slice::from_raw_parts_mut`][]. + /// + /// [valid]: crate::ptr#safety + /// [allocated object]: crate::ptr#allocated-object + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub const unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit]> { + if self.is_null() { + None + } else { + // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`. + Some(unsafe { slice::from_raw_parts_mut(self as *mut MaybeUninit, self.len()) }) + } + } +} + +impl *mut [T; N] { + /// Returns a raw pointer to the array's buffer. + /// + /// This is equivalent to casting `self` to `*mut T`, but more type-safe. + /// + /// # Examples + /// + /// ```rust + /// #![feature(array_ptr_get)] + /// use std::ptr; + /// + /// let arr: *mut [i8; 3] = ptr::null_mut(); + /// assert_eq!(arr.as_mut_ptr(), ptr::null_mut()); + /// ``` + #[inline] + #[unstable(feature = "array_ptr_get", issue = "119834")] + pub const fn as_mut_ptr(self) -> *mut T { + self as *mut T + } + + /// Returns a raw pointer to a mutable slice containing the entire array. + /// + /// # Examples + /// + /// ``` + /// #![feature(array_ptr_get)] + /// + /// let mut arr = [1, 2, 5]; + /// let ptr: *mut [i32; 3] = &mut arr; + /// unsafe { + /// (&mut *ptr.as_mut_slice())[..2].copy_from_slice(&[3, 4]); + /// } + /// assert_eq!(arr, [3, 4, 5]); + /// ``` + #[inline] + #[unstable(feature = "array_ptr_get", issue = "119834")] + pub const fn as_mut_slice(self) -> *mut [T] { + self + } +} + +// Equality for pointers +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for *mut T { + #[inline(always)] + #[allow(ambiguous_wide_pointer_comparisons)] + fn eq(&self, other: &*mut T) -> bool { + *self == *other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for *mut T {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for *mut T { + #[inline] + #[allow(ambiguous_wide_pointer_comparisons)] + fn cmp(&self, other: &*mut T) -> Ordering { + if self < other { + Less + } else if self == other { + Equal + } else { + Greater + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for *mut T { + #[inline(always)] + #[allow(ambiguous_wide_pointer_comparisons)] + fn partial_cmp(&self, other: &*mut T) -> Option { + Some(self.cmp(other)) + } + + #[inline(always)] + #[allow(ambiguous_wide_pointer_comparisons)] + fn lt(&self, other: &*mut T) -> bool { + *self < *other + } + + #[inline(always)] + #[allow(ambiguous_wide_pointer_comparisons)] + fn le(&self, other: &*mut T) -> bool { + *self <= *other + } + + #[inline(always)] + #[allow(ambiguous_wide_pointer_comparisons)] + fn gt(&self, other: &*mut T) -> bool { + *self > *other + } + + #[inline(always)] + #[allow(ambiguous_wide_pointer_comparisons)] + fn ge(&self, other: &*mut T) -> bool { + *self >= *other + } +} diff --git a/CoqOfRust/core/ptr/non_null.rs b/CoqOfRust/core/ptr/non_null.rs new file mode 100644 index 000000000..0ad1cad69 --- /dev/null +++ b/CoqOfRust/core/ptr/non_null.rs @@ -0,0 +1,1631 @@ +use crate::cmp::Ordering; +use crate::marker::Unsize; +use crate::mem::{MaybeUninit, SizedTypeProperties}; +use crate::num::NonZero; +use crate::ops::{CoerceUnsized, DispatchFromDyn}; +use crate::pin::PinCoerceUnsized; +use crate::ptr::Unique; +use crate::slice::{self, SliceIndex}; +use crate::ub_checks::assert_unsafe_precondition; +use crate::{fmt, hash, intrinsics, mem, ptr}; + +/// `*mut T` but non-zero and [covariant]. +/// +/// This is often the correct thing to use when building data structures using +/// raw pointers, but is ultimately more dangerous to use because of its additional +/// properties. If you're not sure if you should use `NonNull`, just use `*mut T`! +/// +/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer +/// is never dereferenced. This is so that enums may use this forbidden value +/// as a discriminant -- `Option>` has the same size as `*mut T`. +/// However the pointer may still dangle if it isn't dereferenced. +/// +/// Unlike `*mut T`, `NonNull` was chosen to be covariant over `T`. This makes it +/// possible to use `NonNull` when building covariant types, but introduces the +/// risk of unsoundness if used in a type that shouldn't actually be covariant. +/// (The opposite choice was made for `*mut T` even though technically the unsoundness +/// could only be caused by calling unsafe functions.) +/// +/// Covariance is correct for most safe abstractions, such as `Box`, `Rc`, `Arc`, `Vec`, +/// and `LinkedList`. This is the case because they provide a public API that follows the +/// normal shared XOR mutable rules of Rust. +/// +/// If your type cannot safely be covariant, you must ensure it contains some +/// additional field to provide invariance. Often this field will be a [`PhantomData`] +/// type like `PhantomData>` or `PhantomData<&'a mut T>`. +/// +/// Notice that `NonNull` has a `From` instance for `&T`. However, this does +/// not change the fact that mutating through a (pointer derived from a) shared +/// reference is undefined behavior unless the mutation happens inside an +/// [`UnsafeCell`]. The same goes for creating a mutable reference from a shared +/// reference. When using this `From` instance without an `UnsafeCell`, +/// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr` +/// is never used for mutation. +/// +/// # Representation +/// +/// Thanks to the [null pointer optimization], +/// `NonNull` and `Option>` +/// are guaranteed to have the same size and alignment: +/// +/// ``` +/// # use std::mem::{size_of, align_of}; +/// use std::ptr::NonNull; +/// +/// assert_eq!(size_of::>(), size_of::>>()); +/// assert_eq!(align_of::>(), align_of::>>()); +/// +/// assert_eq!(size_of::>(), size_of::>>()); +/// assert_eq!(align_of::>(), align_of::>>()); +/// ``` +/// +/// [covariant]: https://doc.rust-lang.org/reference/subtyping.html +/// [`PhantomData`]: crate::marker::PhantomData +/// [`UnsafeCell`]: crate::cell::UnsafeCell +/// [null pointer optimization]: crate::option#representation +#[stable(feature = "nonnull", since = "1.25.0")] +#[repr(transparent)] +#[rustc_layout_scalar_valid_range_start(1)] +#[rustc_nonnull_optimization_guaranteed] +#[rustc_diagnostic_item = "NonNull"] +pub struct NonNull { + // Remember to use `.as_ptr()` instead of `.pointer`, as field projecting to + // this is banned by . + pointer: *const T, +} + +/// `NonNull` pointers are not `Send` because the data they reference may be aliased. +// N.B., this impl is unnecessary, but should provide better error messages. +#[stable(feature = "nonnull", since = "1.25.0")] +impl !Send for NonNull {} + +/// `NonNull` pointers are not `Sync` because the data they reference may be aliased. +// N.B., this impl is unnecessary, but should provide better error messages. +#[stable(feature = "nonnull", since = "1.25.0")] +impl !Sync for NonNull {} + +impl NonNull { + /// Creates a new `NonNull` that is dangling, but well-aligned. + /// + /// This is useful for initializing types which lazily allocate, like + /// `Vec::new` does. + /// + /// Note that the pointer value may potentially represent a valid pointer to + /// a `T`, which means this must not be used as a "not yet initialized" + /// sentinel value. Types that lazily allocate must track initialization by + /// some other means. + /// + /// # Examples + /// + /// ``` + /// use std::ptr::NonNull; + /// + /// let ptr = NonNull::::dangling(); + /// // Important: don't try to access the value of `ptr` without + /// // initializing it first! The pointer is not null but isn't valid either! + /// ``` + #[stable(feature = "nonnull", since = "1.25.0")] + #[rustc_const_stable(feature = "const_nonnull_dangling", since = "1.36.0")] + #[must_use] + #[inline] + pub const fn dangling() -> Self { + // SAFETY: ptr::dangling_mut() returns a non-null well-aligned pointer. + unsafe { + let ptr = crate::ptr::dangling_mut::(); + NonNull::new_unchecked(ptr) + } + } + + /// Returns a shared references to the value. In contrast to [`as_ref`], this does not require + /// that the value has to be initialized. + /// + /// For the mutable counterpart see [`as_uninit_mut`]. + /// + /// [`as_ref`]: NonNull::as_ref + /// [`as_uninit_mut`]: NonNull::as_uninit_mut + /// + /// # Safety + /// + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// Note that because the created reference is to `MaybeUninit`, the + /// source pointer can point to uninitialized memory. + #[inline] + #[must_use] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub const unsafe fn as_uninit_ref<'a>(self) -> &'a MaybeUninit { + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a reference. + unsafe { &*self.cast().as_ptr() } + } + + /// Returns a unique references to the value. In contrast to [`as_mut`], this does not require + /// that the value has to be initialized. + /// + /// For the shared counterpart see [`as_uninit_ref`]. + /// + /// [`as_mut`]: NonNull::as_mut + /// [`as_uninit_ref`]: NonNull::as_uninit_ref + /// + /// # Safety + /// + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// Note that because the created reference is to `MaybeUninit`, the + /// source pointer can point to uninitialized memory. + #[inline] + #[must_use] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub const unsafe fn as_uninit_mut<'a>(self) -> &'a mut MaybeUninit { + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a reference. + unsafe { &mut *self.cast().as_ptr() } + } +} + +impl NonNull { + /// Creates a new `NonNull`. + /// + /// # Safety + /// + /// `ptr` must be non-null. + /// + /// # Examples + /// + /// ``` + /// use std::ptr::NonNull; + /// + /// let mut x = 0u32; + /// let ptr = unsafe { NonNull::new_unchecked(&mut x as *mut _) }; + /// ``` + /// + /// *Incorrect* usage of this function: + /// + /// ```rust,no_run + /// use std::ptr::NonNull; + /// + /// // NEVER DO THAT!!! This is undefined behavior. ⚠️ + /// let ptr = unsafe { NonNull::::new_unchecked(std::ptr::null_mut()) }; + /// ``` + #[stable(feature = "nonnull", since = "1.25.0")] + #[rustc_const_stable(feature = "const_nonnull_new_unchecked", since = "1.25.0")] + #[inline] + pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { + // SAFETY: the caller must guarantee that `ptr` is non-null. + unsafe { + assert_unsafe_precondition!( + check_language_ub, + "NonNull::new_unchecked requires that the pointer is non-null", + (ptr: *mut () = ptr as *mut ()) => !ptr.is_null() + ); + NonNull { pointer: ptr as _ } + } + } + + /// Creates a new `NonNull` if `ptr` is non-null. + /// + /// # Examples + /// + /// ``` + /// use std::ptr::NonNull; + /// + /// let mut x = 0u32; + /// let ptr = NonNull::::new(&mut x as *mut _).expect("ptr is null!"); + /// + /// if let Some(ptr) = NonNull::::new(std::ptr::null_mut()) { + /// unreachable!(); + /// } + /// ``` + #[stable(feature = "nonnull", since = "1.25.0")] + #[rustc_const_unstable(feature = "const_nonnull_new", issue = "93235")] + #[inline] + pub const fn new(ptr: *mut T) -> Option { + if !ptr.is_null() { + // SAFETY: The pointer is already checked and is not null + Some(unsafe { Self::new_unchecked(ptr) }) + } else { + None + } + } + + /// Converts a reference to a `NonNull` pointer. + #[unstable(feature = "non_null_from_ref", issue = "130823")] + #[inline] + pub const fn from_ref(r: &T) -> Self { + // SAFETY: A reference cannot be null. + unsafe { NonNull { pointer: r as *const T } } + } + + /// Converts a mutable reference to a `NonNull` pointer. + #[unstable(feature = "non_null_from_ref", issue = "130823")] + #[inline] + pub const fn from_mut(r: &mut T) -> Self { + // SAFETY: A mutable reference cannot be null. + unsafe { NonNull { pointer: r as *mut T } } + } + + /// Performs the same functionality as [`std::ptr::from_raw_parts`], except that a + /// `NonNull` pointer is returned, as opposed to a raw `*const` pointer. + /// + /// See the documentation of [`std::ptr::from_raw_parts`] for more details. + /// + /// [`std::ptr::from_raw_parts`]: crate::ptr::from_raw_parts + #[unstable(feature = "ptr_metadata", issue = "81513")] + #[inline] + pub const fn from_raw_parts( + data_pointer: NonNull, + metadata: ::Metadata, + ) -> NonNull { + // SAFETY: The result of `ptr::from::raw_parts_mut` is non-null because `data_pointer` is. + unsafe { + NonNull::new_unchecked(super::from_raw_parts_mut(data_pointer.as_ptr(), metadata)) + } + } + + /// Decompose a (possibly wide) pointer into its data pointer and metadata components. + /// + /// The pointer can be later reconstructed with [`NonNull::from_raw_parts`]. + #[unstable(feature = "ptr_metadata", issue = "81513")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_raw_parts(self) -> (NonNull<()>, ::Metadata) { + (self.cast(), super::metadata(self.as_ptr())) + } + + /// Gets the "address" portion of the pointer. + /// + /// For more details see the equivalent method on a raw pointer, [`pointer::addr`]. + /// + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. + #[must_use] + #[inline] + #[stable(feature = "strict_provenance", since = "1.84.0")] + pub fn addr(self) -> NonZero { + // SAFETY: The pointer is guaranteed by the type to be non-null, + // meaning that the address will be non-zero. + unsafe { NonZero::new_unchecked(self.as_ptr().addr()) } + } + + /// Creates a new pointer with the given address and the [provenance][crate::ptr#provenance] of + /// `self`. + /// + /// For more details see the equivalent method on a raw pointer, [`pointer::with_addr`]. + /// + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. + #[must_use] + #[inline] + #[stable(feature = "strict_provenance", since = "1.84.0")] + pub fn with_addr(self, addr: NonZero) -> Self { + // SAFETY: The result of `ptr::from::with_addr` is non-null because `addr` is guaranteed to be non-zero. + unsafe { NonNull::new_unchecked(self.as_ptr().with_addr(addr.get()) as *mut _) } + } + + /// Creates a new pointer by mapping `self`'s address to a new one, preserving the + /// [provenance][crate::ptr#provenance] of `self`. + /// + /// For more details see the equivalent method on a raw pointer, [`pointer::map_addr`]. + /// + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. + #[must_use] + #[inline] + #[stable(feature = "strict_provenance", since = "1.84.0")] + pub fn map_addr(self, f: impl FnOnce(NonZero) -> NonZero) -> Self { + self.with_addr(f(self.addr())) + } + + /// Acquires the underlying `*mut` pointer. + /// + /// # Examples + /// + /// ``` + /// use std::ptr::NonNull; + /// + /// let mut x = 0u32; + /// let ptr = NonNull::new(&mut x).expect("ptr is null!"); + /// + /// let x_value = unsafe { *ptr.as_ptr() }; + /// assert_eq!(x_value, 0); + /// + /// unsafe { *ptr.as_ptr() += 2; } + /// let x_value = unsafe { *ptr.as_ptr() }; + /// assert_eq!(x_value, 2); + /// ``` + #[stable(feature = "nonnull", since = "1.25.0")] + #[rustc_const_stable(feature = "const_nonnull_as_ptr", since = "1.32.0")] + #[rustc_never_returns_null_ptr] + #[must_use] + #[inline(always)] + pub const fn as_ptr(self) -> *mut T { + // This is a transmute for the same reasons as `NonZero::get`. + + // SAFETY: `NonNull` is `transparent` over a `*const T`, and `*const T` + // and `*mut T` have the same layout, so transitively we can transmute + // our `NonNull` to a `*mut T` directly. + unsafe { mem::transmute::(self) } + } + + /// Returns a shared reference to the value. If the value may be uninitialized, [`as_uninit_ref`] + /// must be used instead. + /// + /// For the mutable counterpart see [`as_mut`]. + /// + /// [`as_uninit_ref`]: NonNull::as_uninit_ref + /// [`as_mut`]: NonNull::as_mut + /// + /// # Safety + /// + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// + /// # Examples + /// + /// ``` + /// use std::ptr::NonNull; + /// + /// let mut x = 0u32; + /// let ptr = NonNull::new(&mut x as *mut _).expect("ptr is null!"); + /// + /// let ref_x = unsafe { ptr.as_ref() }; + /// println!("{ref_x}"); + /// ``` + /// + /// [the module documentation]: crate::ptr#safety + #[stable(feature = "nonnull", since = "1.25.0")] + #[rustc_const_stable(feature = "const_nonnull_as_ref", since = "1.73.0")] + #[must_use] + #[inline(always)] + pub const unsafe fn as_ref<'a>(&self) -> &'a T { + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a reference. + // `cast_const` avoids a mutable raw pointer deref. + unsafe { &*self.as_ptr().cast_const() } + } + + /// Returns a unique reference to the value. If the value may be uninitialized, [`as_uninit_mut`] + /// must be used instead. + /// + /// For the shared counterpart see [`as_ref`]. + /// + /// [`as_uninit_mut`]: NonNull::as_uninit_mut + /// [`as_ref`]: NonNull::as_ref + /// + /// # Safety + /// + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// # Examples + /// + /// ``` + /// use std::ptr::NonNull; + /// + /// let mut x = 0u32; + /// let mut ptr = NonNull::new(&mut x).expect("null pointer"); + /// + /// let x_ref = unsafe { ptr.as_mut() }; + /// assert_eq!(*x_ref, 0); + /// *x_ref += 2; + /// assert_eq!(*x_ref, 2); + /// ``` + /// + /// [the module documentation]: crate::ptr#safety + #[stable(feature = "nonnull", since = "1.25.0")] + #[rustc_const_stable(feature = "const_ptr_as_ref", since = "1.83.0")] + #[must_use] + #[inline(always)] + pub const unsafe fn as_mut<'a>(&mut self) -> &'a mut T { + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a mutable reference. + unsafe { &mut *self.as_ptr() } + } + + /// Casts to a pointer of another type. + /// + /// # Examples + /// + /// ``` + /// use std::ptr::NonNull; + /// + /// let mut x = 0u32; + /// let ptr = NonNull::new(&mut x as *mut _).expect("null pointer"); + /// + /// let casted_ptr = ptr.cast::(); + /// let raw_ptr: *mut i8 = casted_ptr.as_ptr(); + /// ``` + #[stable(feature = "nonnull_cast", since = "1.27.0")] + #[rustc_const_stable(feature = "const_nonnull_cast", since = "1.36.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn cast(self) -> NonNull { + // SAFETY: `self` is a `NonNull` pointer which is necessarily non-null + unsafe { NonNull { pointer: self.as_ptr() as *mut U } } + } + + /// Adds an offset to a pointer. + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined Behavior: + /// + /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. + /// + /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. + /// + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. + /// + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// use std::ptr::NonNull; + /// + /// let mut s = [1, 2, 3]; + /// let ptr: NonNull = NonNull::new(s.as_mut_ptr()).unwrap(); + /// + /// unsafe { + /// println!("{}", ptr.offset(1).read()); + /// println!("{}", ptr.offset(2).read()); + /// } + /// ``` + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[must_use = "returns a new pointer rather than modifying its argument"] + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")] + pub const unsafe fn offset(self, count: isize) -> Self + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `offset`. + // Additionally safety contract of `offset` guarantees that the resulting pointer is + // pointing to an allocation, there can't be an allocation at null, thus it's safe to + // construct `NonNull`. + unsafe { NonNull { pointer: intrinsics::offset(self.as_ptr(), count) } } + } + + /// Calculates the offset from a pointer in bytes. + /// + /// `count` is in units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [offset][pointer::offset] on it. See that method for documentation + /// and safety requirements. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")] + pub const unsafe fn byte_offset(self, count: isize) -> Self { + // SAFETY: the caller must uphold the safety contract for `offset` and `byte_offset` has + // the same safety contract. + // Additionally safety contract of `offset` guarantees that the resulting pointer is + // pointing to an allocation, there can't be an allocation at null, thus it's safe to + // construct `NonNull`. + unsafe { NonNull { pointer: self.as_ptr().byte_offset(count) } } + } + + /// Adds an offset to a pointer (convenience for `.offset(count as isize)`). + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined Behavior: + /// + /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. + /// + /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. + /// + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. + /// + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// use std::ptr::NonNull; + /// + /// let s: &str = "123"; + /// let ptr: NonNull = NonNull::new(s.as_ptr().cast_mut()).unwrap(); + /// + /// unsafe { + /// println!("{}", ptr.add(1).read() as char); + /// println!("{}", ptr.add(2).read() as char); + /// } + /// ``` + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[must_use = "returns a new pointer rather than modifying its argument"] + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")] + pub const unsafe fn add(self, count: usize) -> Self + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `offset`. + // Additionally safety contract of `offset` guarantees that the resulting pointer is + // pointing to an allocation, there can't be an allocation at null, thus it's safe to + // construct `NonNull`. + unsafe { NonNull { pointer: intrinsics::offset(self.as_ptr(), count) } } + } + + /// Calculates the offset from a pointer in bytes (convenience for `.byte_offset(count as isize)`). + /// + /// `count` is in units of bytes. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`add`][NonNull::add] on it. See that method for documentation + /// and safety requirements. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")] + pub const unsafe fn byte_add(self, count: usize) -> Self { + // SAFETY: the caller must uphold the safety contract for `add` and `byte_add` has the same + // safety contract. + // Additionally safety contract of `add` guarantees that the resulting pointer is pointing + // to an allocation, there can't be an allocation at null, thus it's safe to construct + // `NonNull`. + unsafe { NonNull { pointer: self.as_ptr().byte_add(count) } } + } + + /// Subtracts an offset from a pointer (convenience for + /// `.offset((count as isize).wrapping_neg())`). + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined Behavior: + /// + /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. + /// + /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// [allocated object], and the entire memory range between `self` and the result must be in + /// bounds of that allocated object. In particular, this range must not "wrap around" the edge + /// of the address space. + /// + /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. + /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always + /// safe. + /// + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// use std::ptr::NonNull; + /// + /// let s: &str = "123"; + /// + /// unsafe { + /// let end: NonNull = NonNull::new(s.as_ptr().cast_mut()).unwrap().add(3); + /// println!("{}", end.sub(1).read() as char); + /// println!("{}", end.sub(2).read() as char); + /// } + /// ``` + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[must_use = "returns a new pointer rather than modifying its argument"] + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")] + pub const unsafe fn sub(self, count: usize) -> Self + where + T: Sized, + { + if T::IS_ZST { + // Pointer arithmetic does nothing when the pointee is a ZST. + self + } else { + // SAFETY: the caller must uphold the safety contract for `offset`. + // Because the pointee is *not* a ZST, that means that `count` is + // at most `isize::MAX`, and thus the negation cannot overflow. + unsafe { self.offset((count as isize).unchecked_neg()) } + } + } + + /// Calculates the offset from a pointer in bytes (convenience for + /// `.byte_offset((count as isize).wrapping_neg())`). + /// + /// `count` is in units of bytes. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`sub`][NonNull::sub] on it. See that method for documentation + /// and safety requirements. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[must_use] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")] + pub const unsafe fn byte_sub(self, count: usize) -> Self { + // SAFETY: the caller must uphold the safety contract for `sub` and `byte_sub` has the same + // safety contract. + // Additionally safety contract of `sub` guarantees that the resulting pointer is pointing + // to an allocation, there can't be an allocation at null, thus it's safe to construct + // `NonNull`. + unsafe { NonNull { pointer: self.as_ptr().byte_sub(count) } } + } + + /// Calculates the distance between two pointers within the same allocation. The returned value is in + /// units of T: the distance in bytes divided by `mem::size_of::()`. + /// + /// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::() as isize)`, + /// except that it has a lot more opportunities for UB, in exchange for the compiler + /// better understanding what you are doing. + /// + /// The primary motivation of this method is for computing the `len` of an array/slice + /// of `T` that you are currently representing as a "start" and "end" pointer + /// (and "end" is "one past the end" of the array). + /// In that case, `end.offset_from(start)` gets you the length of the array. + /// + /// All of the following safety requirements are trivially satisfied for this usecase. + /// + /// [`offset`]: #method.offset + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined Behavior: + /// + /// * `self` and `origin` must either + /// + /// * point to the same address, or + /// * both be *derived from* a pointer to the same [allocated object], and the memory range between + /// the two pointers must be in bounds of that object. (See below for an example.) + /// + /// * The distance between the pointers, in bytes, must be an exact multiple + /// of the size of `T`. + /// + /// As a consequence, the absolute distance between the pointers, in bytes, computed on + /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is + /// implied by the in-bounds requirement, and the fact that no allocated object can be larger + /// than `isize::MAX` bytes. + /// + /// The requirement for pointers to be derived from the same allocated object is primarily + /// needed for `const`-compatibility: the distance between pointers into *different* allocated + /// objects is not known at compile-time. However, the requirement also exists at + /// runtime and may be exploited by optimizations. If you wish to compute the difference between + /// pointers that are not guaranteed to be from the same allocation, use `(self as isize - + /// origin as isize) / mem::size_of::()`. + // FIXME: recommend `addr()` instead of `as usize` once that is stable. + /// + /// [`add`]: #method.add + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Panics + /// + /// This function panics if `T` is a Zero-Sized Type ("ZST"). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::ptr::NonNull; + /// + /// let a = [0; 5]; + /// let ptr1: NonNull = NonNull::from(&a[1]); + /// let ptr2: NonNull = NonNull::from(&a[3]); + /// unsafe { + /// assert_eq!(ptr2.offset_from(ptr1), 2); + /// assert_eq!(ptr1.offset_from(ptr2), -2); + /// assert_eq!(ptr1.offset(2), ptr2); + /// assert_eq!(ptr2.offset(-2), ptr1); + /// } + /// ``` + /// + /// *Incorrect* usage: + /// + /// ```rust,no_run + /// use std::ptr::NonNull; + /// + /// let ptr1 = NonNull::new(Box::into_raw(Box::new(0u8))).unwrap(); + /// let ptr2 = NonNull::new(Box::into_raw(Box::new(1u8))).unwrap(); + /// let diff = (ptr2.addr().get() as isize).wrapping_sub(ptr1.addr().get() as isize); + /// // Make ptr2_other an "alias" of ptr2.add(1), but derived from ptr1. + /// let diff_plus_1 = diff.wrapping_add(1); + /// let ptr2_other = NonNull::new(ptr1.as_ptr().wrapping_byte_offset(diff_plus_1)).unwrap(); + /// assert_eq!(ptr2.addr(), ptr2_other.addr()); + /// // Since ptr2_other and ptr2 are derived from pointers to different objects, + /// // computing their offset is undefined behavior, even though + /// // they point to addresses that are in-bounds of the same object! + /// + /// let one = unsafe { ptr2_other.offset_from(ptr2) }; // Undefined Behavior! ⚠️ + /// ``` + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")] + pub const unsafe fn offset_from(self, origin: NonNull) -> isize + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `offset_from`. + unsafe { self.as_ptr().offset_from(origin.as_ptr()) } + } + + /// Calculates the distance between two pointers within the same allocation. The returned value is in + /// units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`offset_from`][NonNull::offset_from] on it. See that method for + /// documentation and safety requirements. + /// + /// For non-`Sized` pointees this operation considers only the data pointers, + /// ignoring the metadata. + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")] + pub const unsafe fn byte_offset_from(self, origin: NonNull) -> isize { + // SAFETY: the caller must uphold the safety contract for `byte_offset_from`. + unsafe { self.as_ptr().byte_offset_from(origin.as_ptr()) } + } + + // N.B. `wrapping_offset``, `wrapping_add`, etc are not implemented because they can wrap to null + + /// Calculates the distance between two pointers within the same allocation, *where it's known that + /// `self` is equal to or greater than `origin`*. The returned value is in + /// units of T: the distance in bytes is divided by `mem::size_of::()`. + /// + /// This computes the same value that [`offset_from`](#method.offset_from) + /// would compute, but with the added precondition that the offset is + /// guaranteed to be non-negative. This method is equivalent to + /// `usize::try_from(self.offset_from(origin)).unwrap_unchecked()`, + /// but it provides slightly more information to the optimizer, which can + /// sometimes allow it to optimize slightly better with some backends. + /// + /// This method can be though of as recovering the `count` that was passed + /// to [`add`](#method.add) (or, with the parameters in the other order, + /// to [`sub`](#method.sub)). The following are all equivalent, assuming + /// that their safety preconditions are met: + /// ```rust + /// # #![feature(ptr_sub_ptr)] + /// # unsafe fn blah(ptr: std::ptr::NonNull, origin: std::ptr::NonNull, count: usize) -> bool { + /// ptr.sub_ptr(origin) == count + /// # && + /// origin.add(count) == ptr + /// # && + /// ptr.sub(count) == origin + /// # } + /// ``` + /// + /// # Safety + /// + /// - The distance between the pointers must be non-negative (`self >= origin`) + /// + /// - *All* the safety conditions of [`offset_from`](#method.offset_from) + /// apply to this method as well; see it for the full details. + /// + /// Importantly, despite the return type of this method being able to represent + /// a larger offset, it's still *not permitted* to pass pointers which differ + /// by more than `isize::MAX` *bytes*. As such, the result of this method will + /// always be less than or equal to `isize::MAX as usize`. + /// + /// # Panics + /// + /// This function panics if `T` is a Zero-Sized Type ("ZST"). + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_sub_ptr)] + /// use std::ptr::NonNull; + /// + /// let a = [0; 5]; + /// let ptr1: NonNull = NonNull::from(&a[1]); + /// let ptr2: NonNull = NonNull::from(&a[3]); + /// unsafe { + /// assert_eq!(ptr2.sub_ptr(ptr1), 2); + /// assert_eq!(ptr1.add(2), ptr2); + /// assert_eq!(ptr2.sub(2), ptr1); + /// assert_eq!(ptr2.sub_ptr(ptr2), 0); + /// } + /// + /// // This would be incorrect, as the pointers are not correctly ordered: + /// // ptr1.sub_ptr(ptr2) + /// ``` + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[unstable(feature = "ptr_sub_ptr", issue = "95892")] + #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + pub const unsafe fn sub_ptr(self, subtracted: NonNull) -> usize + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `sub_ptr`. + unsafe { self.as_ptr().sub_ptr(subtracted.as_ptr()) } + } + + /// Calculates the distance between two pointers within the same allocation, *where it's known that + /// `self` is equal to or greater than `origin`*. The returned value is in + /// units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`sub_ptr`][NonNull::sub_ptr] on it. See that method for + /// documentation and safety requirements. + /// + /// For non-`Sized` pointees this operation considers only the data pointers, + /// ignoring the metadata. + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[unstable(feature = "ptr_sub_ptr", issue = "95892")] + #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + pub const unsafe fn byte_sub_ptr(self, origin: NonNull) -> usize { + // SAFETY: the caller must uphold the safety contract for `byte_sub_ptr`. + unsafe { self.as_ptr().byte_sub_ptr(origin.as_ptr()) } + } + + /// Reads the value from `self` without moving it. This leaves the + /// memory in `self` unchanged. + /// + /// See [`ptr::read`] for safety concerns and examples. + /// + /// [`ptr::read`]: crate::ptr::read() + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")] + pub const unsafe fn read(self) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `read`. + unsafe { ptr::read(self.as_ptr()) } + } + + /// Performs a volatile read of the value from `self` without moving it. This + /// leaves the memory in `self` unchanged. + /// + /// Volatile operations are intended to act on I/O memory, and are guaranteed + /// to not be elided or reordered by the compiler across other volatile + /// operations. + /// + /// See [`ptr::read_volatile`] for safety concerns and examples. + /// + /// [`ptr::read_volatile`]: crate::ptr::read_volatile() + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + pub unsafe fn read_volatile(self) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `read_volatile`. + unsafe { ptr::read_volatile(self.as_ptr()) } + } + + /// Reads the value from `self` without moving it. This leaves the + /// memory in `self` unchanged. + /// + /// Unlike `read`, the pointer may be unaligned. + /// + /// See [`ptr::read_unaligned`] for safety concerns and examples. + /// + /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned() + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")] + pub const unsafe fn read_unaligned(self) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `read_unaligned`. + unsafe { ptr::read_unaligned(self.as_ptr()) } + } + + /// Copies `count * size_of` bytes from `self` to `dest`. The source + /// and destination may overlap. + /// + /// NOTE: this has the *same* argument order as [`ptr::copy`]. + /// + /// See [`ptr::copy`] for safety concerns and examples. + /// + /// [`ptr::copy`]: crate::ptr::copy() + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] + pub const unsafe fn copy_to(self, dest: NonNull, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `copy`. + unsafe { ptr::copy(self.as_ptr(), dest.as_ptr(), count) } + } + + /// Copies `count * size_of` bytes from `self` to `dest`. The source + /// and destination may *not* overlap. + /// + /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`]. + /// + /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. + /// + /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] + pub const unsafe fn copy_to_nonoverlapping(self, dest: NonNull, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `copy_nonoverlapping`. + unsafe { ptr::copy_nonoverlapping(self.as_ptr(), dest.as_ptr(), count) } + } + + /// Copies `count * size_of` bytes from `src` to `self`. The source + /// and destination may overlap. + /// + /// NOTE: this has the *opposite* argument order of [`ptr::copy`]. + /// + /// See [`ptr::copy`] for safety concerns and examples. + /// + /// [`ptr::copy`]: crate::ptr::copy() + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] + pub const unsafe fn copy_from(self, src: NonNull, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `copy`. + unsafe { ptr::copy(src.as_ptr(), self.as_ptr(), count) } + } + + /// Copies `count * size_of` bytes from `src` to `self`. The source + /// and destination may *not* overlap. + /// + /// NOTE: this has the *opposite* argument order of [`ptr::copy_nonoverlapping`]. + /// + /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. + /// + /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] + pub const unsafe fn copy_from_nonoverlapping(self, src: NonNull, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `copy_nonoverlapping`. + unsafe { ptr::copy_nonoverlapping(src.as_ptr(), self.as_ptr(), count) } + } + + /// Executes the destructor (if any) of the pointed-to value. + /// + /// See [`ptr::drop_in_place`] for safety concerns and examples. + /// + /// [`ptr::drop_in_place`]: crate::ptr::drop_in_place() + #[inline(always)] + #[stable(feature = "non_null_convenience", since = "1.80.0")] + pub unsafe fn drop_in_place(self) { + // SAFETY: the caller must uphold the safety contract for `drop_in_place`. + unsafe { ptr::drop_in_place(self.as_ptr()) } + } + + /// Overwrites a memory location with the given value without reading or + /// dropping the old value. + /// + /// See [`ptr::write`] for safety concerns and examples. + /// + /// [`ptr::write`]: crate::ptr::write() + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] + pub const unsafe fn write(self, val: T) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `write`. + unsafe { ptr::write(self.as_ptr(), val) } + } + + /// Invokes memset on the specified pointer, setting `count * size_of::()` + /// bytes of memory starting at `self` to `val`. + /// + /// See [`ptr::write_bytes`] for safety concerns and examples. + /// + /// [`ptr::write_bytes`]: crate::ptr::write_bytes() + #[inline(always)] + #[doc(alias = "memset")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] + pub const unsafe fn write_bytes(self, val: u8, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `write_bytes`. + unsafe { ptr::write_bytes(self.as_ptr(), val, count) } + } + + /// Performs a volatile write of a memory location with the given value without + /// reading or dropping the old value. + /// + /// Volatile operations are intended to act on I/O memory, and are guaranteed + /// to not be elided or reordered by the compiler across other volatile + /// operations. + /// + /// See [`ptr::write_volatile`] for safety concerns and examples. + /// + /// [`ptr::write_volatile`]: crate::ptr::write_volatile() + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + pub unsafe fn write_volatile(self, val: T) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `write_volatile`. + unsafe { ptr::write_volatile(self.as_ptr(), val) } + } + + /// Overwrites a memory location with the given value without reading or + /// dropping the old value. + /// + /// Unlike `write`, the pointer may be unaligned. + /// + /// See [`ptr::write_unaligned`] for safety concerns and examples. + /// + /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned() + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] + pub const unsafe fn write_unaligned(self, val: T) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `write_unaligned`. + unsafe { ptr::write_unaligned(self.as_ptr(), val) } + } + + /// Replaces the value at `self` with `src`, returning the old + /// value, without dropping either. + /// + /// See [`ptr::replace`] for safety concerns and examples. + /// + /// [`ptr::replace`]: crate::ptr::replace() + #[inline(always)] + #[stable(feature = "non_null_convenience", since = "1.80.0")] + pub unsafe fn replace(self, src: T) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `replace`. + unsafe { ptr::replace(self.as_ptr(), src) } + } + + /// Swaps the values at two mutable locations of the same type, without + /// deinitializing either. They may overlap, unlike `mem::swap` which is + /// otherwise equivalent. + /// + /// See [`ptr::swap`] for safety concerns and examples. + /// + /// [`ptr::swap`]: crate::ptr::swap() + #[inline(always)] + #[stable(feature = "non_null_convenience", since = "1.80.0")] + #[rustc_const_unstable(feature = "const_swap", issue = "83163")] + pub const unsafe fn swap(self, with: NonNull) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `swap`. + unsafe { ptr::swap(self.as_ptr(), with.as_ptr()) } + } + + /// Computes the offset that needs to be applied to the pointer in order to make it aligned to + /// `align`. + /// + /// If it is not possible to align the pointer, the implementation returns + /// `usize::MAX`. + /// + /// The offset is expressed in number of `T` elements, and not bytes. + /// + /// There are no guarantees whatsoever that offsetting the pointer will not overflow or go + /// beyond the allocation that the pointer points into. It is up to the caller to ensure that + /// the returned offset is correct in all terms other than alignment. + /// + /// When this is called during compile-time evaluation (which is unstable), the implementation + /// may return `usize::MAX` in cases where that can never happen at runtime. This is because the + /// actual alignment of pointers is not known yet during compile-time, so an offset with + /// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8; + /// N]` might be allocated at an odd or an even address, but at compile-time this is not yet + /// known, so the execution has to be correct for either choice. It is therefore impossible to + /// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual + /// for unstable APIs.) + /// + /// # Panics + /// + /// The function panics if `align` is not a power-of-two. + /// + /// # Examples + /// + /// Accessing adjacent `u8` as `u16` + /// + /// ``` + /// use std::mem::align_of; + /// use std::ptr::NonNull; + /// + /// # unsafe { + /// let x = [5_u8, 6, 7, 8, 9]; + /// let ptr = NonNull::new(x.as_ptr() as *mut u8).unwrap(); + /// let offset = ptr.align_offset(align_of::()); + /// + /// if offset < x.len() - 1 { + /// let u16_ptr = ptr.add(offset).cast::(); + /// assert!(u16_ptr.read() == u16::from_ne_bytes([5, 6]) || u16_ptr.read() == u16::from_ne_bytes([6, 7])); + /// } else { + /// // while the pointer can be aligned via `offset`, it would point + /// // outside the allocation + /// } + /// # } + /// ``` + #[inline] + #[must_use] + #[stable(feature = "non_null_convenience", since = "1.80.0")] + pub fn align_offset(self, align: usize) -> usize + where + T: Sized, + { + if !align.is_power_of_two() { + panic!("align_offset: align is not a power-of-two"); + } + + { + // SAFETY: `align` has been checked to be a power of 2 above. + unsafe { ptr::align_offset(self.as_ptr(), align) } + } + } + + /// Returns whether the pointer is properly aligned for `T`. + /// + /// # Examples + /// + /// ``` + /// use std::ptr::NonNull; + /// + /// // On some platforms, the alignment of i32 is less than 4. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// + /// let data = AlignedI32(42); + /// let ptr = NonNull::::from(&data); + /// + /// assert!(ptr.is_aligned()); + /// assert!(!NonNull::new(ptr.as_ptr().wrapping_byte_add(1)).unwrap().is_aligned()); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "pointer_is_aligned", since = "1.79.0")] + pub fn is_aligned(self) -> bool + where + T: Sized, + { + self.as_ptr().is_aligned() + } + + /// Returns whether the pointer is aligned to `align`. + /// + /// For non-`Sized` pointees this operation considers only the data pointer, + /// ignoring the metadata. + /// + /// # Panics + /// + /// The function panics if `align` is not a power-of-two (this includes 0). + /// + /// # Examples + /// + /// ``` + /// #![feature(pointer_is_aligned_to)] + /// + /// // On some platforms, the alignment of i32 is less than 4. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// + /// let data = AlignedI32(42); + /// let ptr = &data as *const AlignedI32; + /// + /// assert!(ptr.is_aligned_to(1)); + /// assert!(ptr.is_aligned_to(2)); + /// assert!(ptr.is_aligned_to(4)); + /// + /// assert!(ptr.wrapping_byte_add(2).is_aligned_to(2)); + /// assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4)); + /// + /// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8)); + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "pointer_is_aligned_to", issue = "96284")] + pub fn is_aligned_to(self, align: usize) -> bool { + self.as_ptr().is_aligned_to(align) + } +} + +impl NonNull<[T]> { + /// Creates a non-null raw slice from a thin pointer and a length. + /// + /// The `len` argument is the number of **elements**, not the number of bytes. + /// + /// This function is safe, but dereferencing the return value is unsafe. + /// See the documentation of [`slice::from_raw_parts`] for slice safety requirements. + /// + /// # Examples + /// + /// ```rust + /// use std::ptr::NonNull; + /// + /// // create a slice pointer when starting out with a pointer to the first element + /// let mut x = [5, 6, 7]; + /// let nonnull_pointer = NonNull::new(x.as_mut_ptr()).unwrap(); + /// let slice = NonNull::slice_from_raw_parts(nonnull_pointer, 3); + /// assert_eq!(unsafe { slice.as_ref()[2] }, 7); + /// ``` + /// + /// (Note that this example artificially demonstrates a use of this method, + /// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.) + #[stable(feature = "nonnull_slice_from_raw_parts", since = "1.70.0")] + #[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")] + #[must_use] + #[inline] + pub const fn slice_from_raw_parts(data: NonNull, len: usize) -> Self { + // SAFETY: `data` is a `NonNull` pointer which is necessarily non-null + unsafe { Self::new_unchecked(super::slice_from_raw_parts_mut(data.as_ptr(), len)) } + } + + /// Returns the length of a non-null raw slice. + /// + /// The returned value is the number of **elements**, not the number of bytes. + /// + /// This function is safe, even when the non-null raw slice cannot be dereferenced to a slice + /// because the pointer does not have a valid address. + /// + /// # Examples + /// + /// ```rust + /// use std::ptr::NonNull; + /// + /// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3); + /// assert_eq!(slice.len(), 3); + /// ``` + #[stable(feature = "slice_ptr_len_nonnull", since = "1.63.0")] + #[rustc_const_stable(feature = "const_slice_ptr_len_nonnull", since = "1.63.0")] + #[must_use] + #[inline] + pub const fn len(self) -> usize { + self.as_ptr().len() + } + + /// Returns `true` if the non-null raw slice has a length of 0. + /// + /// # Examples + /// + /// ```rust + /// use std::ptr::NonNull; + /// + /// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3); + /// assert!(!slice.is_empty()); + /// ``` + #[stable(feature = "slice_ptr_is_empty_nonnull", since = "1.79.0")] + #[rustc_const_stable(feature = "const_slice_ptr_is_empty_nonnull", since = "1.79.0")] + #[must_use] + #[inline] + pub const fn is_empty(self) -> bool { + self.len() == 0 + } + + /// Returns a non-null pointer to the slice's buffer. + /// + /// # Examples + /// + /// ```rust + /// #![feature(slice_ptr_get)] + /// use std::ptr::NonNull; + /// + /// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3); + /// assert_eq!(slice.as_non_null_ptr(), NonNull::::dangling()); + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "slice_ptr_get", issue = "74265")] + pub const fn as_non_null_ptr(self) -> NonNull { + self.cast() + } + + /// Returns a raw pointer to the slice's buffer. + /// + /// # Examples + /// + /// ```rust + /// #![feature(slice_ptr_get)] + /// use std::ptr::NonNull; + /// + /// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3); + /// assert_eq!(slice.as_mut_ptr(), NonNull::::dangling().as_ptr()); + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "slice_ptr_get", issue = "74265")] + #[rustc_never_returns_null_ptr] + pub const fn as_mut_ptr(self) -> *mut T { + self.as_non_null_ptr().as_ptr() + } + + /// Returns a shared reference to a slice of possibly uninitialized values. In contrast to + /// [`as_ref`], this does not require that the value has to be initialized. + /// + /// For the mutable counterpart see [`as_uninit_slice_mut`]. + /// + /// [`as_ref`]: NonNull::as_ref + /// [`as_uninit_slice_mut`]: NonNull::as_uninit_slice_mut + /// + /// # Safety + /// + /// When calling this method, you have to ensure that all of the following is true: + /// + /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::()` many bytes, + /// and it must be properly aligned. This means in particular: + /// + /// * The entire memory range of this slice must be contained within a single allocated object! + /// Slices can never span across multiple allocated objects. + /// + /// * The pointer must be aligned even for zero-length slices. One + /// reason for this is that enum layout optimizations may rely on references + /// (including slices of any length) being aligned and non-null to distinguish + /// them from other data. You can obtain a pointer that is usable as `data` + /// for zero-length slices using [`NonNull::dangling()`]. + /// + /// * The total size `ptr.len() * mem::size_of::()` of the slice must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, while this reference exists, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// + /// See also [`slice::from_raw_parts`]. + /// + /// [valid]: crate::ptr#safety + #[inline] + #[must_use] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub const unsafe fn as_uninit_slice<'a>(self) -> &'a [MaybeUninit] { + // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`. + unsafe { slice::from_raw_parts(self.cast().as_ptr(), self.len()) } + } + + /// Returns a unique reference to a slice of possibly uninitialized values. In contrast to + /// [`as_mut`], this does not require that the value has to be initialized. + /// + /// For the shared counterpart see [`as_uninit_slice`]. + /// + /// [`as_mut`]: NonNull::as_mut + /// [`as_uninit_slice`]: NonNull::as_uninit_slice + /// + /// # Safety + /// + /// When calling this method, you have to ensure that all of the following is true: + /// + /// * The pointer must be [valid] for reads and writes for `ptr.len() * mem::size_of::()` + /// many bytes, and it must be properly aligned. This means in particular: + /// + /// * The entire memory range of this slice must be contained within a single allocated object! + /// Slices can never span across multiple allocated objects. + /// + /// * The pointer must be aligned even for zero-length slices. One + /// reason for this is that enum layout optimizations may rely on references + /// (including slices of any length) being aligned and non-null to distinguish + /// them from other data. You can obtain a pointer that is usable as `data` + /// for zero-length slices using [`NonNull::dangling()`]. + /// + /// * The total size `ptr.len() * mem::size_of::()` of the slice must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, while this reference exists, the memory the pointer points to must + /// not get accessed (read or written) through any other pointer. + /// + /// This applies even if the result of this method is unused! + /// + /// See also [`slice::from_raw_parts_mut`]. + /// + /// [valid]: crate::ptr#safety + /// + /// # Examples + /// + /// ```rust + /// #![feature(allocator_api, ptr_as_uninit)] + /// + /// use std::alloc::{Allocator, Layout, Global}; + /// use std::mem::MaybeUninit; + /// use std::ptr::NonNull; + /// + /// let memory: NonNull<[u8]> = Global.allocate(Layout::new::<[u8; 32]>())?; + /// // This is safe as `memory` is valid for reads and writes for `memory.len()` many bytes. + /// // Note that calling `memory.as_mut()` is not allowed here as the content may be uninitialized. + /// # #[allow(unused_variables)] + /// let slice: &mut [MaybeUninit] = unsafe { memory.as_uninit_slice_mut() }; + /// # // Prevent leaks for Miri. + /// # unsafe { Global.deallocate(memory.cast(), Layout::new::<[u8; 32]>()); } + /// # Ok::<_, std::alloc::AllocError>(()) + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub const unsafe fn as_uninit_slice_mut<'a>(self) -> &'a mut [MaybeUninit] { + // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`. + unsafe { slice::from_raw_parts_mut(self.cast().as_ptr(), self.len()) } + } + + /// Returns a raw pointer to an element or subslice, without doing bounds + /// checking. + /// + /// Calling this method with an out-of-bounds index or when `self` is not dereferenceable + /// is *[undefined behavior]* even if the resulting pointer is not used. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_ptr_get)] + /// use std::ptr::NonNull; + /// + /// let x = &mut [1, 2, 4]; + /// let x = NonNull::slice_from_raw_parts(NonNull::new(x.as_mut_ptr()).unwrap(), x.len()); + /// + /// unsafe { + /// assert_eq!(x.get_unchecked_mut(1).as_ptr(), x.as_non_null_ptr().as_ptr().add(1)); + /// } + /// ``` + #[unstable(feature = "slice_ptr_get", issue = "74265")] + #[inline] + pub unsafe fn get_unchecked_mut(self, index: I) -> NonNull + where + I: SliceIndex<[T]>, + { + // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. + // As a consequence, the resulting pointer cannot be null. + unsafe { NonNull::new_unchecked(self.as_ptr().get_unchecked_mut(index)) } + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl Clone for NonNull { + #[inline(always)] + fn clone(&self) -> Self { + *self + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl Copy for NonNull {} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl CoerceUnsized> for NonNull where T: Unsize {} + +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl DispatchFromDyn> for NonNull where T: Unsize {} + +#[stable(feature = "pin", since = "1.33.0")] +unsafe impl PinCoerceUnsized for NonNull {} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl fmt::Debug for NonNull { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&self.as_ptr(), f) + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl fmt::Pointer for NonNull { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&self.as_ptr(), f) + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl Eq for NonNull {} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl PartialEq for NonNull { + #[inline] + #[allow(ambiguous_wide_pointer_comparisons)] + fn eq(&self, other: &Self) -> bool { + self.as_ptr() == other.as_ptr() + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl Ord for NonNull { + #[inline] + #[allow(ambiguous_wide_pointer_comparisons)] + fn cmp(&self, other: &Self) -> Ordering { + self.as_ptr().cmp(&other.as_ptr()) + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl PartialOrd for NonNull { + #[inline] + #[allow(ambiguous_wide_pointer_comparisons)] + fn partial_cmp(&self, other: &Self) -> Option { + self.as_ptr().partial_cmp(&other.as_ptr()) + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl hash::Hash for NonNull { + #[inline] + fn hash(&self, state: &mut H) { + self.as_ptr().hash(state) + } +} + +#[unstable(feature = "ptr_internals", issue = "none")] +impl From> for NonNull { + #[inline] + fn from(unique: Unique) -> Self { + unique.as_non_null_ptr() + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl From<&mut T> for NonNull { + /// Converts a `&mut T` to a `NonNull`. + /// + /// This conversion is safe and infallible since references cannot be null. + #[inline] + fn from(r: &mut T) -> Self { + NonNull::from_mut(r) + } +} + +#[stable(feature = "nonnull", since = "1.25.0")] +impl From<&T> for NonNull { + /// Converts a `&T` to a `NonNull`. + /// + /// This conversion is safe and infallible since references cannot be null. + #[inline] + fn from(r: &T) -> Self { + NonNull::from_ref(r) + } +} diff --git a/CoqOfRust/core/ptr/unique.rs b/CoqOfRust/core/ptr/unique.rs new file mode 100644 index 000000000..ebdc918a7 --- /dev/null +++ b/CoqOfRust/core/ptr/unique.rs @@ -0,0 +1,209 @@ +use crate::fmt; +use crate::marker::{PhantomData, Unsize}; +use crate::ops::{CoerceUnsized, DispatchFromDyn}; +use crate::pin::PinCoerceUnsized; +use crate::ptr::NonNull; + +/// 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`, `Vec`, `String`, and `HashMap`. +/// +/// Unlike `*mut T`, `Unique` behaves "as if" it were an instance of `T`. +/// It implements `Send`/`Sync` if `T` is `Send`/`Sync`. It also implies +/// the kind of strong aliasing guarantees an instance of `T` can expect: +/// the referent of the pointer should not be modified without a unique path to +/// its owning Unique. +/// +/// If you're uncertain of whether it's correct to use `Unique` for your purposes, +/// consider using `NonNull`, which has weaker semantics. +/// +/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer +/// is never dereferenced. This is so that enums may use this forbidden value +/// as a discriminant -- `Option>` has the same size as `Unique`. +/// However the pointer may still dangle if it isn't dereferenced. +/// +/// Unlike `*mut T`, `Unique` is covariant over `T`. This should always be correct +/// for any type which upholds Unique's aliasing requirements. +#[unstable( + feature = "ptr_internals", + issue = "none", + reason = "use `NonNull` instead and consider `PhantomData` \ + (if you also use `#[may_dangle]`), `Send`, and/or `Sync`" +)] +#[doc(hidden)] +#[repr(transparent)] +// Lang item used experimentally by Miri to define the semantics of `Unique`. +#[lang = "ptr_unique"] +pub struct Unique { + pointer: NonNull, + // NOTE: this marker has no consequences for variance, but is necessary + // for dropck to understand that we logically own a `T`. + // + // For details, see: + // https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data + _marker: PhantomData, +} + +/// `Unique` pointers are `Send` if `T` is `Send` because the data they +/// reference is unaliased. Note that this aliasing invariant is +/// unenforced by the type system; the abstraction using the +/// `Unique` must enforce it. +#[unstable(feature = "ptr_internals", issue = "none")] +unsafe impl Send for Unique {} + +/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they +/// reference is unaliased. Note that this aliasing invariant is +/// unenforced by the type system; the abstraction using the +/// `Unique` must enforce it. +#[unstable(feature = "ptr_internals", issue = "none")] +unsafe impl Sync for Unique {} + +#[unstable(feature = "ptr_internals", issue = "none")] +impl Unique { + /// Creates a new `Unique` that is dangling, but well-aligned. + /// + /// This is useful for initializing types which lazily allocate, like + /// `Vec::new` does. + /// + /// Note that the pointer value may potentially represent a valid pointer to + /// a `T`, which means this must not be used as a "not yet initialized" + /// sentinel value. Types that lazily allocate must track initialization by + /// some other means. + #[must_use] + #[inline] + pub const fn dangling() -> Self { + // FIXME(const-hack) replace with `From` + Unique { pointer: NonNull::dangling(), _marker: PhantomData } + } +} + +#[unstable(feature = "ptr_internals", issue = "none")] +impl Unique { + /// Creates a new `Unique`. + /// + /// # Safety + /// + /// `ptr` must be non-null. + #[inline] + pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { + // SAFETY: the caller must guarantee that `ptr` is non-null. + unsafe { Unique { pointer: NonNull::new_unchecked(ptr), _marker: PhantomData } } + } + + /// Creates a new `Unique` if `ptr` is non-null. + #[inline] + // rustc_const_unstable attribute can be removed when `const_nonnull_new` is stable + #[rustc_const_unstable(feature = "ptr_internals", issue = "none")] + pub const fn new(ptr: *mut T) -> Option { + if let Some(pointer) = NonNull::new(ptr) { + Some(Unique { pointer, _marker: PhantomData }) + } else { + None + } + } + + /// Acquires the underlying `*mut` pointer. + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub const fn as_ptr(self) -> *mut T { + self.pointer.as_ptr() + } + + /// Acquires the underlying `*mut` pointer. + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub const fn as_non_null_ptr(self) -> NonNull { + self.pointer + } + + /// Dereferences the content. + /// + /// The resulting lifetime is bound to self so this behaves "as if" + /// it were actually an instance of T that is getting borrowed. If a longer + /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`. + #[must_use] + #[inline] + pub const unsafe fn as_ref(&self) -> &T { + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a reference. + unsafe { self.pointer.as_ref() } + } + + /// Mutably dereferences the content. + /// + /// The resulting lifetime is bound to self so this behaves "as if" + /// it were actually an instance of T that is getting borrowed. If a longer + /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`. + #[must_use] + #[inline] + pub const unsafe fn as_mut(&mut self) -> &mut T { + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a mutable reference. + unsafe { self.pointer.as_mut() } + } + + /// Casts to a pointer of another type. + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub const fn cast(self) -> Unique { + // FIXME(const-hack): replace with `From` + // SAFETY: is `NonNull` + Unique { pointer: self.pointer.cast(), _marker: PhantomData } + } +} + +#[unstable(feature = "ptr_internals", issue = "none")] +impl Clone for Unique { + #[inline] + fn clone(&self) -> Self { + *self + } +} + +#[unstable(feature = "ptr_internals", issue = "none")] +impl Copy for Unique {} + +#[unstable(feature = "ptr_internals", issue = "none")] +impl CoerceUnsized> for Unique where T: Unsize {} + +#[unstable(feature = "ptr_internals", issue = "none")] +impl DispatchFromDyn> for Unique where T: Unsize {} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Unique {} + +#[unstable(feature = "ptr_internals", issue = "none")] +impl fmt::Debug for Unique { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&self.as_ptr(), f) + } +} + +#[unstable(feature = "ptr_internals", issue = "none")] +impl fmt::Pointer for Unique { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&self.as_ptr(), f) + } +} + +#[unstable(feature = "ptr_internals", issue = "none")] +impl From<&mut T> for Unique { + /// Converts a `&mut T` to a `Unique`. + /// + /// This conversion is infallible since references cannot be null. + #[inline] + fn from(reference: &mut T) -> Self { + Self::from(NonNull::from(reference)) + } +} + +#[unstable(feature = "ptr_internals", issue = "none")] +impl From> for Unique { + /// Converts a `NonNull` to a `Unique`. + /// + /// This conversion is infallible since `NonNull` cannot be null. + #[inline] + fn from(pointer: NonNull) -> Self { + Unique { pointer, _marker: PhantomData } + } +} diff --git a/CoqOfRust/core/random.rs b/CoqOfRust/core/random.rs new file mode 100644 index 000000000..051fe2608 --- /dev/null +++ b/CoqOfRust/core/random.rs @@ -0,0 +1,62 @@ +//! Random value generation. +//! +//! The [`Random`] trait allows generating a random value for a type using a +//! given [`RandomSource`]. + +/// A source of randomness. +#[unstable(feature = "random", issue = "130703")] +pub trait RandomSource { + /// Fills `bytes` with random bytes. + fn fill_bytes(&mut self, bytes: &mut [u8]); +} + +/// A trait for getting a random value for a type. +/// +/// **Warning:** Be careful when manipulating random values! The +/// [`random`](Random::random) method on integers samples them with a uniform +/// distribution, so a value of 1 is just as likely as [`i32::MAX`]. By using +/// modulo operations, some of the resulting values can become more likely than +/// others. Use audited crates when in doubt. +#[unstable(feature = "random", issue = "130703")] +pub trait Random: Sized { + /// Generates a random value. + fn random(source: &mut (impl RandomSource + ?Sized)) -> Self; +} + +impl Random for bool { + fn random(source: &mut (impl RandomSource + ?Sized)) -> Self { + u8::random(source) & 1 == 1 + } +} + +macro_rules! impl_primitive { + ($t:ty) => { + impl Random for $t { + /// Generates a random value. + /// + /// **Warning:** Be careful when manipulating the resulting value! This + /// method samples according to a uniform distribution, so a value of 1 is + /// just as likely as [`MAX`](Self::MAX). By using modulo operations, some + /// values can become more likely than others. Use audited crates when in + /// doubt. + fn random(source: &mut (impl RandomSource + ?Sized)) -> Self { + let mut bytes = (0 as Self).to_ne_bytes(); + source.fill_bytes(&mut bytes); + Self::from_ne_bytes(bytes) + } + } + }; +} + +impl_primitive!(u8); +impl_primitive!(i8); +impl_primitive!(u16); +impl_primitive!(i16); +impl_primitive!(u32); +impl_primitive!(i32); +impl_primitive!(u64); +impl_primitive!(i64); +impl_primitive!(u128); +impl_primitive!(i128); +impl_primitive!(usize); +impl_primitive!(isize); diff --git a/CoqOfRust/core/range.rs b/CoqOfRust/core/range.rs new file mode 100644 index 000000000..427526fd1 --- /dev/null +++ b/CoqOfRust/core/range.rs @@ -0,0 +1,492 @@ +//! # Experimental replacement range types +//! +//! The types within this module are meant to replace the existing +//! `Range`, `RangeInclusive`, and `RangeFrom` types in a future edition. +//! +//! ``` +//! #![feature(new_range_api)] +//! use core::range::{Range, RangeFrom, RangeInclusive}; +//! +//! let arr = [0, 1, 2, 3, 4]; +//! assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +//! assert_eq!(arr[ .. 3 ], [0, 1, 2 ]); +//! assert_eq!(arr[ ..=3 ], [0, 1, 2, 3 ]); +//! assert_eq!(arr[ RangeFrom::from(1.. )], [ 1, 2, 3, 4]); +//! assert_eq!(arr[ Range::from(1..3 )], [ 1, 2 ]); +//! assert_eq!(arr[RangeInclusive::from(1..=3)], [ 1, 2, 3 ]); +//! ``` + +use crate::fmt; +use crate::hash::Hash; + +mod iter; + +#[unstable(feature = "new_range_api", issue = "125687")] +pub mod legacy; + +use Bound::{Excluded, Included, Unbounded}; +#[doc(inline)] +pub use iter::{IterRange, IterRangeFrom, IterRangeInclusive}; + +#[doc(inline)] +pub use crate::iter::Step; +#[doc(inline)] +pub use crate::ops::{Bound, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive}; + +/// A (half-open) range bounded inclusively below and exclusively above +/// (`start..end` in a future edition). +/// +/// The range `start..end` contains all values with `start <= x < end`. +/// It is empty if `start >= end`. +/// +/// # Examples +/// +/// ``` +/// #![feature(new_range_api)] +/// use core::range::Range; +/// +/// assert_eq!(Range::from(3..5), Range { start: 3, end: 5 }); +/// assert_eq!(3 + 4 + 5, Range::from(3..6).into_iter().sum()); +/// ``` +#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)] +#[unstable(feature = "new_range_api", issue = "125687")] +pub struct Range { + /// The lower bound of the range (inclusive). + #[unstable(feature = "new_range_api", issue = "125687")] + pub start: Idx, + /// The upper bound of the range (exclusive). + #[unstable(feature = "new_range_api", issue = "125687")] + pub end: Idx, +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl fmt::Debug for Range { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + self.start.fmt(fmt)?; + write!(fmt, "..")?; + self.end.fmt(fmt)?; + Ok(()) + } +} + +impl Range { + /// Creates an iterator over the elements within this range. + /// + /// Shorthand for `.clone().into_iter()` + /// + /// # Examples + /// + /// ``` + /// #![feature(new_range_api)] + /// use core::range::Range; + /// + /// let mut i = Range::from(3..9).iter().map(|n| n*n); + /// assert_eq!(i.next(), Some(9)); + /// assert_eq!(i.next(), Some(16)); + /// assert_eq!(i.next(), Some(25)); + /// ``` + #[unstable(feature = "new_range_api", issue = "125687")] + #[inline] + pub fn iter(&self) -> IterRange { + self.clone().into_iter() + } +} + +impl> Range { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_range_api)] + /// use core::range::Range; + /// + /// assert!(!Range::from(3..5).contains(&2)); + /// assert!( Range::from(3..5).contains(&3)); + /// assert!( Range::from(3..5).contains(&4)); + /// assert!(!Range::from(3..5).contains(&5)); + /// + /// assert!(!Range::from(3..3).contains(&3)); + /// assert!(!Range::from(3..2).contains(&3)); + /// + /// assert!( Range::from(0.0..1.0).contains(&0.5)); + /// assert!(!Range::from(0.0..1.0).contains(&f32::NAN)); + /// assert!(!Range::from(0.0..f32::NAN).contains(&0.5)); + /// assert!(!Range::from(f32::NAN..1.0).contains(&0.5)); + /// ``` + #[inline] + #[unstable(feature = "new_range_api", issue = "125687")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } + + /// Returns `true` if the range contains no items. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_range_api)] + /// use core::range::Range; + /// + /// assert!(!Range::from(3..5).is_empty()); + /// assert!( Range::from(3..3).is_empty()); + /// assert!( Range::from(3..2).is_empty()); + /// ``` + /// + /// The range is empty if either side is incomparable: + /// + /// ``` + /// #![feature(new_range_api)] + /// use core::range::Range; + /// + /// assert!(!Range::from(3.0..5.0).is_empty()); + /// assert!( Range::from(3.0..f32::NAN).is_empty()); + /// assert!( Range::from(f32::NAN..5.0).is_empty()); + /// ``` + #[inline] + #[unstable(feature = "new_range_api", issue = "125687")] + pub fn is_empty(&self) -> bool { + !(self.start < self.end) + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl RangeBounds for Range { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl RangeBounds for Range<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Excluded(self.end) + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl From> for legacy::Range { + #[inline] + fn from(value: Range) -> Self { + Self { start: value.start, end: value.end } + } +} +#[unstable(feature = "new_range_api", issue = "125687")] +impl From> for Range { + #[inline] + fn from(value: legacy::Range) -> Self { + Self { start: value.start, end: value.end } + } +} + +/// A range bounded inclusively below and above (`start..=end`). +/// +/// The `RangeInclusive` `start..=end` contains all values with `x >= start` +/// and `x <= end`. It is empty unless `start <= end`. +/// +/// # Examples +/// +/// The `start..=end` syntax is a `RangeInclusive`: +/// +/// ``` +/// #![feature(new_range_api)] +/// use core::range::RangeInclusive; +/// +/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, end: 5 }); +/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum()); +/// ``` +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[unstable(feature = "new_range_api", issue = "125687")] +pub struct RangeInclusive { + /// The lower bound of the range (inclusive). + #[unstable(feature = "new_range_api", issue = "125687")] + pub start: Idx, + /// The upper bound of the range (inclusive). + #[unstable(feature = "new_range_api", issue = "125687")] + pub end: Idx, +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl fmt::Debug for RangeInclusive { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + self.start.fmt(fmt)?; + write!(fmt, "..=")?; + self.end.fmt(fmt)?; + Ok(()) + } +} + +impl> RangeInclusive { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_range_api)] + /// use core::range::RangeInclusive; + /// + /// assert!(!RangeInclusive::from(3..=5).contains(&2)); + /// assert!( RangeInclusive::from(3..=5).contains(&3)); + /// assert!( RangeInclusive::from(3..=5).contains(&4)); + /// assert!( RangeInclusive::from(3..=5).contains(&5)); + /// assert!(!RangeInclusive::from(3..=5).contains(&6)); + /// + /// assert!( RangeInclusive::from(3..=3).contains(&3)); + /// assert!(!RangeInclusive::from(3..=2).contains(&3)); + /// + /// assert!( RangeInclusive::from(0.0..=1.0).contains(&1.0)); + /// assert!(!RangeInclusive::from(0.0..=1.0).contains(&f32::NAN)); + /// assert!(!RangeInclusive::from(0.0..=f32::NAN).contains(&0.0)); + /// assert!(!RangeInclusive::from(f32::NAN..=1.0).contains(&1.0)); + /// ``` + #[inline] + #[unstable(feature = "new_range_api", issue = "125687")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } + + /// Returns `true` if the range contains no items. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_range_api)] + /// use core::range::RangeInclusive; + /// + /// assert!(!RangeInclusive::from(3..=5).is_empty()); + /// assert!(!RangeInclusive::from(3..=3).is_empty()); + /// assert!( RangeInclusive::from(3..=2).is_empty()); + /// ``` + /// + /// The range is empty if either side is incomparable: + /// + /// ``` + /// #![feature(new_range_api)] + /// use core::range::RangeInclusive; + /// + /// assert!(!RangeInclusive::from(3.0..=5.0).is_empty()); + /// assert!( RangeInclusive::from(3.0..=f32::NAN).is_empty()); + /// assert!( RangeInclusive::from(f32::NAN..=5.0).is_empty()); + /// ``` + #[unstable(feature = "new_range_api", issue = "125687")] + #[inline] + pub fn is_empty(&self) -> bool { + !(self.start <= self.end) + } +} + +impl RangeInclusive { + /// Creates an iterator over the elements within this range. + /// + /// Shorthand for `.clone().into_iter()` + /// + /// # Examples + /// + /// ``` + /// #![feature(new_range_api)] + /// use core::range::RangeInclusive; + /// + /// let mut i = RangeInclusive::from(3..=8).iter().map(|n| n*n); + /// assert_eq!(i.next(), Some(9)); + /// assert_eq!(i.next(), Some(16)); + /// assert_eq!(i.next(), Some(25)); + /// ``` + #[unstable(feature = "new_range_api", issue = "125687")] + #[inline] + pub fn iter(&self) -> IterRangeInclusive { + self.clone().into_iter() + } +} + +impl RangeInclusive { + /// Converts to an exclusive `Range` for `SliceIndex` implementations. + /// The caller is responsible for dealing with `end == usize::MAX`. + #[inline] + pub(crate) const fn into_slice_range(self) -> Range { + Range { start: self.start, end: self.end + 1 } + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl RangeBounds for RangeInclusive { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + Included(&self.end) + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl RangeBounds for RangeInclusive<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Included(self.end) + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl From> for legacy::RangeInclusive { + #[inline] + fn from(value: RangeInclusive) -> Self { + Self::new(value.start, value.end) + } +} +#[unstable(feature = "new_range_api", issue = "125687")] +impl From> for RangeInclusive { + #[inline] + fn from(value: legacy::RangeInclusive) -> Self { + assert!( + !value.exhausted, + "attempted to convert from an exhausted `legacy::RangeInclusive` (unspecified behavior)" + ); + + let (start, end) = value.into_inner(); + RangeInclusive { start, end } + } +} + +/// A range only bounded inclusively below (`start..`). +/// +/// The `RangeFrom` `start..` contains all values with `x >= start`. +/// +/// *Note*: Overflow in the [`Iterator`] implementation (when the contained +/// data type reaches its numerical limit) is allowed to panic, wrap, or +/// saturate. This behavior is defined by the implementation of the [`Step`] +/// trait. For primitive integers, this follows the normal rules, and respects +/// the overflow checks profile (panic in debug, wrap in release). Note also +/// that overflow happens earlier than you might assume: the overflow happens +/// in the call to `next` that yields the maximum value, as the range must be +/// set to a state to yield the next value. +/// +/// [`Step`]: crate::iter::Step +/// +/// # Examples +/// +/// The `start..` syntax is a `RangeFrom`: +/// +/// ``` +/// #![feature(new_range_api)] +/// use core::range::RangeFrom; +/// +/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 }); +/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum()); +/// ``` +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[unstable(feature = "new_range_api", issue = "125687")] +pub struct RangeFrom { + /// The lower bound of the range (inclusive). + #[unstable(feature = "new_range_api", issue = "125687")] + pub start: Idx, +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl fmt::Debug for RangeFrom { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + self.start.fmt(fmt)?; + write!(fmt, "..")?; + Ok(()) + } +} + +impl RangeFrom { + /// Creates an iterator over the elements within this range. + /// + /// Shorthand for `.clone().into_iter()` + /// + /// # Examples + /// + /// ``` + /// #![feature(new_range_api)] + /// use core::range::RangeFrom; + /// + /// let mut i = RangeFrom::from(3..).iter().map(|n| n*n); + /// assert_eq!(i.next(), Some(9)); + /// assert_eq!(i.next(), Some(16)); + /// assert_eq!(i.next(), Some(25)); + /// ``` + #[unstable(feature = "new_range_api", issue = "125687")] + #[inline] + pub fn iter(&self) -> IterRangeFrom { + self.clone().into_iter() + } +} + +impl> RangeFrom { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_range_api)] + /// use core::range::RangeFrom; + /// + /// assert!(!RangeFrom::from(3..).contains(&2)); + /// assert!( RangeFrom::from(3..).contains(&3)); + /// assert!( RangeFrom::from(3..).contains(&1_000_000_000)); + /// + /// assert!( RangeFrom::from(0.0..).contains(&0.5)); + /// assert!(!RangeFrom::from(0.0..).contains(&f32::NAN)); + /// assert!(!RangeFrom::from(f32::NAN..).contains(&0.5)); + /// ``` + #[inline] + #[unstable(feature = "new_range_api", issue = "125687")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl RangeBounds for RangeFrom { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + Unbounded + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl RangeBounds for RangeFrom<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Unbounded + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl From> for legacy::RangeFrom { + #[inline] + fn from(value: RangeFrom) -> Self { + Self { start: value.start } + } +} +#[unstable(feature = "new_range_api", issue = "125687")] +impl From> for RangeFrom { + #[inline] + fn from(value: legacy::RangeFrom) -> Self { + Self { start: value.start } + } +} diff --git a/CoqOfRust/core/range/iter.rs b/CoqOfRust/core/range/iter.rs new file mode 100644 index 000000000..1e261d8c1 --- /dev/null +++ b/CoqOfRust/core/range/iter.rs @@ -0,0 +1,339 @@ +use crate::iter::{ + FusedIterator, Step, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, TrustedStep, +}; +use crate::num::NonZero; +use crate::range::{Range, RangeFrom, RangeInclusive, legacy}; + +/// By-value [`Range`] iterator. +#[unstable(feature = "new_range_api", issue = "125687")] +#[derive(Debug, Clone)] +pub struct IterRange
(legacy::Range); + +impl IterRange { + /// Returns the remainder of the range being iterated over. + pub fn remainder(self) -> Range { + Range { start: self.0.start, end: self.0.end } + } +} + +/// Safety: This macro must only be used on types that are `Copy` and result in ranges +/// which have an exact `size_hint()` where the upper bound must not be `None`. +macro_rules! unsafe_range_trusted_random_access_impl { + ($($t:ty)*) => ($( + #[doc(hidden)] + #[unstable(feature = "trusted_random_access", issue = "none")] + unsafe impl TrustedRandomAccess for IterRange<$t> {} + + #[doc(hidden)] + #[unstable(feature = "trusted_random_access", issue = "none")] + unsafe impl TrustedRandomAccessNoCoerce for IterRange<$t> { + const MAY_HAVE_SIDE_EFFECT: bool = false; + } + )*) +} + +unsafe_range_trusted_random_access_impl! { + usize u8 u16 + isize i8 i16 +} + +#[cfg(target_pointer_width = "32")] +unsafe_range_trusted_random_access_impl! { + u32 i32 +} + +#[cfg(target_pointer_width = "64")] +unsafe_range_trusted_random_access_impl! { + u32 i32 + u64 i64 +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl Iterator for IterRange { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + self.0.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + + #[inline] + fn count(self) -> usize { + self.0.count() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.0.nth(n) + } + + #[inline] + fn last(self) -> Option { + self.0.last() + } + + #[inline] + fn min(self) -> Option + where + A: Ord, + { + self.0.min() + } + + #[inline] + fn max(self) -> Option + where + A: Ord, + { + self.0.max() + } + + #[inline] + fn is_sorted(self) -> bool { + true + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.0.advance_by(n) + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccessNoCoerce, + { + // SAFETY: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + // Additionally Self: TrustedRandomAccess is only implemented for Copy types + // which means even repeated reads of the same index would be safe. + unsafe { Step::forward_unchecked(self.0.start.clone(), idx) } + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl DoubleEndedIterator for IterRange { + #[inline] + fn next_back(&mut self) -> Option { + self.0.next_back() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.0.nth_back(n) + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.0.advance_back_by(n) + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IterRange {} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl FusedIterator for IterRange {} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl IntoIterator for Range { + type Item = A; + type IntoIter = IterRange; + + fn into_iter(self) -> Self::IntoIter { + IterRange(self.into()) + } +} + +/// By-value [`RangeInclusive`] iterator. +#[unstable(feature = "new_range_api", issue = "125687")] +#[derive(Debug, Clone)] +pub struct IterRangeInclusive(legacy::RangeInclusive); + +impl IterRangeInclusive { + /// Returns the remainder of the range being iterated over. + /// + /// If the iterator is exhausted or empty, returns `None`. + pub fn remainder(self) -> Option> { + if self.0.is_empty() { + return None; + } + + Some(RangeInclusive { start: self.0.start, end: self.0.end }) + } +} + +#[unstable(feature = "trusted_random_access", issue = "none")] +impl Iterator for IterRangeInclusive { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + self.0.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + + #[inline] + fn count(self) -> usize { + self.0.count() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.0.nth(n) + } + + #[inline] + fn last(self) -> Option { + self.0.last() + } + + #[inline] + fn min(self) -> Option + where + A: Ord, + { + self.0.min() + } + + #[inline] + fn max(self) -> Option + where + A: Ord, + { + self.0.max() + } + + #[inline] + fn is_sorted(self) -> bool { + true + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.0.advance_by(n) + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl DoubleEndedIterator for IterRangeInclusive { + #[inline] + fn next_back(&mut self) -> Option { + self.0.next_back() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.0.nth_back(n) + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.0.advance_back_by(n) + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IterRangeInclusive {} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl FusedIterator for IterRangeInclusive {} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl IntoIterator for RangeInclusive { + type Item = A; + type IntoIter = IterRangeInclusive; + + fn into_iter(self) -> Self::IntoIter { + IterRangeInclusive(self.into()) + } +} + +// These macros generate `ExactSizeIterator` impls for various range types. +// +// * `ExactSizeIterator::len` is required to always return an exact `usize`, +// so no range can be longer than `usize::MAX`. +// * For integer types in `Range<_>` this is the case for types narrower than or as wide as `usize`. +// For integer types in `RangeInclusive<_>` +// this is the case for types *strictly narrower* than `usize` +// since e.g. `(0..=u64::MAX).len()` would be `u64::MAX + 1`. +macro_rules! range_exact_iter_impl { + ($($t:ty)*) => ($( + #[unstable(feature = "new_range_api", issue = "125687")] + impl ExactSizeIterator for IterRange<$t> { } + )*) +} + +macro_rules! range_incl_exact_iter_impl { + ($($t:ty)*) => ($( + #[unstable(feature = "new_range_api", issue = "125687")] + impl ExactSizeIterator for IterRangeInclusive<$t> { } + )*) +} + +range_exact_iter_impl! { + usize u8 u16 + isize i8 i16 +} + +range_incl_exact_iter_impl! { + u8 + i8 +} + +/// By-value [`RangeFrom`] iterator. +#[unstable(feature = "new_range_api", issue = "125687")] +#[derive(Debug, Clone)] +pub struct IterRangeFrom(legacy::RangeFrom); + +impl IterRangeFrom { + /// Returns the remainder of the range being iterated over. + pub fn remainder(self) -> RangeFrom { + RangeFrom { start: self.0.start } + } +} + +#[unstable(feature = "trusted_random_access", issue = "none")] +impl Iterator for IterRangeFrom { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { + self.0.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.0.nth(n) + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IterRangeFrom {} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl FusedIterator for IterRangeFrom {} + +#[unstable(feature = "new_range_api", issue = "125687")] +impl IntoIterator for RangeFrom { + type Item = A; + type IntoIter = IterRangeFrom; + + fn into_iter(self) -> Self::IntoIter { + IterRangeFrom(self.into()) + } +} diff --git a/CoqOfRust/core/range/legacy.rs b/CoqOfRust/core/range/legacy.rs new file mode 100644 index 000000000..6723c4903 --- /dev/null +++ b/CoqOfRust/core/range/legacy.rs @@ -0,0 +1,10 @@ +//! # Legacy range types +//! +//! The types within this module will be replaced by the types +//! [`Range`], [`RangeInclusive`], and [`RangeFrom`] in the parent +//! module, [`core::range`]. +//! +//! The types here are equivalent to those in [`core::ops`]. + +#[doc(inline)] +pub use crate::ops::{Range, RangeFrom, RangeInclusive}; diff --git a/CoqOfRust/core/result.rs b/CoqOfRust/core/result.rs new file mode 100644 index 000000000..9c7be618b --- /dev/null +++ b/CoqOfRust/core/result.rs @@ -0,0 +1,2025 @@ +//! Error handling with the `Result` type. +//! +//! [`Result`][`Result`] is the type used for returning and propagating +//! errors. It is an enum with the variants, [`Ok(T)`], representing +//! success and containing a value, and [`Err(E)`], representing error +//! and containing an error value. +//! +//! ``` +//! # #[allow(dead_code)] +//! enum Result { +//! Ok(T), +//! Err(E), +//! } +//! ``` +//! +//! Functions return [`Result`] whenever errors are expected and +//! recoverable. In the `std` crate, [`Result`] is most prominently used +//! for [I/O](../../std/io/index.html). +//! +//! A simple function returning [`Result`] might be +//! defined and used like so: +//! +//! ``` +//! #[derive(Debug)] +//! enum Version { Version1, Version2 } +//! +//! fn parse_version(header: &[u8]) -> Result { +//! match header.get(0) { +//! None => Err("invalid header length"), +//! Some(&1) => Ok(Version::Version1), +//! Some(&2) => Ok(Version::Version2), +//! Some(_) => Err("invalid version"), +//! } +//! } +//! +//! let version = parse_version(&[1, 2, 3, 4]); +//! match version { +//! Ok(v) => println!("working with version: {v:?}"), +//! Err(e) => println!("error parsing header: {e:?}"), +//! } +//! ``` +//! +//! Pattern matching on [`Result`]s is clear and straightforward for +//! simple cases, but [`Result`] comes with some convenience methods +//! that make working with it more succinct. +//! +//! ``` +//! // The `is_ok` and `is_err` methods do what they say. +//! let good_result: Result = Ok(10); +//! let bad_result: Result = Err(10); +//! assert!(good_result.is_ok() && !good_result.is_err()); +//! assert!(bad_result.is_err() && !bad_result.is_ok()); +//! +//! // `map` and `map_err` consume the `Result` and produce another. +//! let good_result: Result = good_result.map(|i| i + 1); +//! let bad_result: Result = bad_result.map_err(|i| i - 1); +//! assert_eq!(good_result, Ok(11)); +//! assert_eq!(bad_result, Err(9)); +//! +//! // Use `and_then` to continue the computation. +//! let good_result: Result = good_result.and_then(|i| Ok(i == 11)); +//! assert_eq!(good_result, Ok(true)); +//! +//! // Use `or_else` to handle the error. +//! let bad_result: Result = bad_result.or_else(|i| Ok(i + 20)); +//! assert_eq!(bad_result, Ok(29)); +//! +//! // Consume the result and return the contents with `unwrap`. +//! let final_awesome_result = good_result.unwrap(); +//! assert!(final_awesome_result) +//! ``` +//! +//! # Results must be used +//! +//! A common problem with using return values to indicate errors is +//! that it is easy to ignore the return value, thus failing to handle +//! the error. [`Result`] is annotated with the `#[must_use]` attribute, +//! which will cause the compiler to issue a warning when a Result +//! value is ignored. This makes [`Result`] especially useful with +//! functions that may encounter errors but don't otherwise return a +//! useful value. +//! +//! Consider the [`write_all`] method defined for I/O types +//! by the [`Write`] trait: +//! +//! ``` +//! use std::io; +//! +//! trait Write { +//! fn write_all(&mut self, bytes: &[u8]) -> Result<(), io::Error>; +//! } +//! ``` +//! +//! *Note: The actual definition of [`Write`] uses [`io::Result`], which +//! is just a synonym for [Result].* +//! +//! This method doesn't produce a value, but the write may +//! fail. It's crucial to handle the error case, and *not* write +//! something like this: +//! +//! ```no_run +//! # #![allow(unused_must_use)] // \o/ +//! use std::fs::File; +//! use std::io::prelude::*; +//! +//! let mut file = File::create("valuable_data.txt").unwrap(); +//! // If `write_all` errors, then we'll never know, because the return +//! // value is ignored. +//! file.write_all(b"important message"); +//! ``` +//! +//! If you *do* write that in Rust, the compiler will give you a +//! warning (by default, controlled by the `unused_must_use` lint). +//! +//! You might instead, if you don't want to handle the error, simply +//! assert success with [`expect`]. This will panic if the +//! write fails, providing a marginally useful message indicating why: +//! +//! ```no_run +//! use std::fs::File; +//! use std::io::prelude::*; +//! +//! let mut file = File::create("valuable_data.txt").unwrap(); +//! file.write_all(b"important message").expect("failed to write message"); +//! ``` +//! +//! You might also simply assert success: +//! +//! ```no_run +//! # use std::fs::File; +//! # use std::io::prelude::*; +//! # let mut file = File::create("valuable_data.txt").unwrap(); +//! assert!(file.write_all(b"important message").is_ok()); +//! ``` +//! +//! Or propagate the error up the call stack with [`?`]: +//! +//! ``` +//! # use std::fs::File; +//! # use std::io::prelude::*; +//! # use std::io; +//! # #[allow(dead_code)] +//! fn write_message() -> io::Result<()> { +//! let mut file = File::create("valuable_data.txt")?; +//! file.write_all(b"important message")?; +//! Ok(()) +//! } +//! ``` +//! +//! # The question mark operator, `?` +//! +//! When writing code that calls many functions that return the +//! [`Result`] type, the error handling can be tedious. The question mark +//! operator, [`?`], hides some of the boilerplate of propagating errors +//! up the call stack. +//! +//! It replaces this: +//! +//! ``` +//! # #![allow(dead_code)] +//! use std::fs::File; +//! use std::io::prelude::*; +//! use std::io; +//! +//! struct Info { +//! name: String, +//! age: i32, +//! rating: i32, +//! } +//! +//! fn write_info(info: &Info) -> io::Result<()> { +//! // Early return on error +//! let mut file = match File::create("my_best_friends.txt") { +//! Err(e) => return Err(e), +//! Ok(f) => f, +//! }; +//! if let Err(e) = file.write_all(format!("name: {}\n", info.name).as_bytes()) { +//! return Err(e) +//! } +//! if let Err(e) = file.write_all(format!("age: {}\n", info.age).as_bytes()) { +//! return Err(e) +//! } +//! if let Err(e) = file.write_all(format!("rating: {}\n", info.rating).as_bytes()) { +//! return Err(e) +//! } +//! Ok(()) +//! } +//! ``` +//! +//! With this: +//! +//! ``` +//! # #![allow(dead_code)] +//! use std::fs::File; +//! use std::io::prelude::*; +//! use std::io; +//! +//! struct Info { +//! name: String, +//! age: i32, +//! rating: i32, +//! } +//! +//! fn write_info(info: &Info) -> io::Result<()> { +//! let mut file = File::create("my_best_friends.txt")?; +//! // Early return on error +//! file.write_all(format!("name: {}\n", info.name).as_bytes())?; +//! file.write_all(format!("age: {}\n", info.age).as_bytes())?; +//! file.write_all(format!("rating: {}\n", info.rating).as_bytes())?; +//! Ok(()) +//! } +//! ``` +//! +//! *It's much nicer!* +//! +//! Ending the expression with [`?`] will result in the [`Ok`]'s unwrapped value, unless the result +//! is [`Err`], in which case [`Err`] is returned early from the enclosing function. +//! +//! [`?`] can be used in functions that return [`Result`] because of the +//! early return of [`Err`] that it provides. +//! +//! [`expect`]: Result::expect +//! [`Write`]: ../../std/io/trait.Write.html "io::Write" +//! [`write_all`]: ../../std/io/trait.Write.html#method.write_all "io::Write::write_all" +//! [`io::Result`]: ../../std/io/type.Result.html "io::Result" +//! [`?`]: crate::ops::Try +//! [`Ok(T)`]: Ok +//! [`Err(E)`]: Err +//! [io::Error]: ../../std/io/struct.Error.html "io::Error" +//! +//! # Representation +//! +//! In some cases, [`Result`] will gain the same size, alignment, and ABI +//! guarantees as [`Option`] has. One of either the `T` or `E` type must be a +//! type that qualifies for the `Option` [representation guarantees][opt-rep], +//! and the *other* type must meet all of the following conditions: +//! * Is a zero-sized type with alignment 1 (a "1-ZST"). +//! * Has no fields. +//! * Does not have the `#[non_exhaustive]` attribute. +//! +//! For example, `NonZeroI32` qualifies for the `Option` representation +//! guarantees, and `()` is a zero-sized type with alignment 1, no fields, and +//! it isn't `non_exhaustive`. This means that both `Result` and +//! `Result<(), NonZeroI32>` have the same size, alignment, and ABI guarantees +//! as `Option`. The only difference is the implied semantics: +//! * `Option` is "a non-zero i32 might be present" +//! * `Result` is "a non-zero i32 success result, if any" +//! * `Result<(), NonZeroI32>` is "a non-zero i32 error result, if any" +//! +//! [opt-rep]: ../option/index.html#representation "Option Representation" +//! +//! # Method overview +//! +//! In addition to working with pattern matching, [`Result`] provides a +//! wide variety of different methods. +//! +//! ## Querying the variant +//! +//! The [`is_ok`] and [`is_err`] methods return [`true`] if the [`Result`] +//! is [`Ok`] or [`Err`], respectively. +//! +//! [`is_err`]: Result::is_err +//! [`is_ok`]: Result::is_ok +//! +//! ## Adapters for working with references +//! +//! * [`as_ref`] converts from `&Result` to `Result<&T, &E>` +//! * [`as_mut`] converts from `&mut Result` to `Result<&mut T, &mut E>` +//! * [`as_deref`] converts from `&Result` to `Result<&T::Target, &E>` +//! * [`as_deref_mut`] converts from `&mut Result` to +//! `Result<&mut T::Target, &mut E>` +//! +//! [`as_deref`]: Result::as_deref +//! [`as_deref_mut`]: Result::as_deref_mut +//! [`as_mut`]: Result::as_mut +//! [`as_ref`]: Result::as_ref +//! +//! ## Extracting contained values +//! +//! These methods extract the contained value in a [`Result`] when it +//! is the [`Ok`] variant. If the [`Result`] is [`Err`]: +//! +//! * [`expect`] panics with a provided custom message +//! * [`unwrap`] panics with a generic message +//! * [`unwrap_or`] returns the provided default value +//! * [`unwrap_or_default`] returns the default value of the type `T` +//! (which must implement the [`Default`] trait) +//! * [`unwrap_or_else`] returns the result of evaluating the provided +//! function +//! +//! The panicking methods [`expect`] and [`unwrap`] require `E` to +//! implement the [`Debug`] trait. +//! +//! [`Debug`]: crate::fmt::Debug +//! [`expect`]: Result::expect +//! [`unwrap`]: Result::unwrap +//! [`unwrap_or`]: Result::unwrap_or +//! [`unwrap_or_default`]: Result::unwrap_or_default +//! [`unwrap_or_else`]: Result::unwrap_or_else +//! +//! These methods extract the contained value in a [`Result`] when it +//! is the [`Err`] variant. They require `T` to implement the [`Debug`] +//! trait. If the [`Result`] is [`Ok`]: +//! +//! * [`expect_err`] panics with a provided custom message +//! * [`unwrap_err`] panics with a generic message +//! +//! [`Debug`]: crate::fmt::Debug +//! [`expect_err`]: Result::expect_err +//! [`unwrap_err`]: Result::unwrap_err +//! +//! ## Transforming contained values +//! +//! These methods transform [`Result`] to [`Option`]: +//! +//! * [`err`][Result::err] transforms [`Result`] into [`Option`], +//! mapping [`Err(e)`] to [`Some(e)`] and [`Ok(v)`] to [`None`] +//! * [`ok`][Result::ok] transforms [`Result`] into [`Option`], +//! mapping [`Ok(v)`] to [`Some(v)`] and [`Err(e)`] to [`None`] +//! * [`transpose`] transposes a [`Result`] of an [`Option`] into an +//! [`Option`] of a [`Result`] +//! +// Do NOT add link reference definitions for `err` or `ok`, because they +// will generate numerous incorrect URLs for `Err` and `Ok` elsewhere, due +// to case folding. +//! +//! [`Err(e)`]: Err +//! [`Ok(v)`]: Ok +//! [`Some(e)`]: Option::Some +//! [`Some(v)`]: Option::Some +//! [`transpose`]: Result::transpose +//! +//! This method transforms the contained value of the [`Ok`] variant: +//! +//! * [`map`] transforms [`Result`] into [`Result`] by applying +//! the provided function to the contained value of [`Ok`] and leaving +//! [`Err`] values unchanged +//! +//! [`map`]: Result::map +//! +//! This method transforms the contained value of the [`Err`] variant: +//! +//! * [`map_err`] transforms [`Result`] into [`Result`] by +//! applying the provided function to the contained value of [`Err`] and +//! leaving [`Ok`] values unchanged +//! +//! [`map_err`]: Result::map_err +//! +//! These methods transform a [`Result`] into a value of a possibly +//! different type `U`: +//! +//! * [`map_or`] applies the provided function to the contained value of +//! [`Ok`], or returns the provided default value if the [`Result`] is +//! [`Err`] +//! * [`map_or_else`] applies the provided function to the contained value +//! of [`Ok`], or applies the provided default fallback function to the +//! contained value of [`Err`] +//! +//! [`map_or`]: Result::map_or +//! [`map_or_else`]: Result::map_or_else +//! +//! ## Boolean operators +//! +//! These methods treat the [`Result`] as a boolean value, where [`Ok`] +//! acts like [`true`] and [`Err`] acts like [`false`]. There are two +//! categories of these methods: ones that take a [`Result`] as input, and +//! ones that take a function as input (to be lazily evaluated). +//! +//! The [`and`] and [`or`] methods take another [`Result`] as input, and +//! produce a [`Result`] as output. The [`and`] method can produce a +//! [`Result`] value having a different inner type `U` than +//! [`Result`]. The [`or`] method can produce a [`Result`] +//! value having a different error type `F` than [`Result`]. +//! +//! | method | self | input | output | +//! |---------|----------|-----------|----------| +//! | [`and`] | `Err(e)` | (ignored) | `Err(e)` | +//! | [`and`] | `Ok(x)` | `Err(d)` | `Err(d)` | +//! | [`and`] | `Ok(x)` | `Ok(y)` | `Ok(y)` | +//! | [`or`] | `Err(e)` | `Err(d)` | `Err(d)` | +//! | [`or`] | `Err(e)` | `Ok(y)` | `Ok(y)` | +//! | [`or`] | `Ok(x)` | (ignored) | `Ok(x)` | +//! +//! [`and`]: Result::and +//! [`or`]: Result::or +//! +//! The [`and_then`] and [`or_else`] methods take a function as input, and +//! only evaluate the function when they need to produce a new value. The +//! [`and_then`] method can produce a [`Result`] value having a +//! different inner type `U` than [`Result`]. The [`or_else`] method +//! can produce a [`Result`] value having a different error type `F` +//! than [`Result`]. +//! +//! | method | self | function input | function result | output | +//! |--------------|----------|----------------|-----------------|----------| +//! | [`and_then`] | `Err(e)` | (not provided) | (not evaluated) | `Err(e)` | +//! | [`and_then`] | `Ok(x)` | `x` | `Err(d)` | `Err(d)` | +//! | [`and_then`] | `Ok(x)` | `x` | `Ok(y)` | `Ok(y)` | +//! | [`or_else`] | `Err(e)` | `e` | `Err(d)` | `Err(d)` | +//! | [`or_else`] | `Err(e)` | `e` | `Ok(y)` | `Ok(y)` | +//! | [`or_else`] | `Ok(x)` | (not provided) | (not evaluated) | `Ok(x)` | +//! +//! [`and_then`]: Result::and_then +//! [`or_else`]: Result::or_else +//! +//! ## Comparison operators +//! +//! If `T` and `E` both implement [`PartialOrd`] then [`Result`] will +//! derive its [`PartialOrd`] implementation. With this order, an [`Ok`] +//! compares as less than any [`Err`], while two [`Ok`] or two [`Err`] +//! compare as their contained values would in `T` or `E` respectively. If `T` +//! and `E` both also implement [`Ord`], then so does [`Result`]. +//! +//! ``` +//! assert!(Ok(1) < Err(0)); +//! let x: Result = Ok(0); +//! let y = Ok(1); +//! assert!(x < y); +//! let x: Result<(), i32> = Err(0); +//! let y = Err(1); +//! assert!(x < y); +//! ``` +//! +//! ## Iterating over `Result` +//! +//! A [`Result`] can be iterated over. This can be helpful if you need an +//! iterator that is conditionally empty. The iterator will either produce +//! a single value (when the [`Result`] is [`Ok`]), or produce no values +//! (when the [`Result`] is [`Err`]). For example, [`into_iter`] acts like +//! [`once(v)`] if the [`Result`] is [`Ok(v)`], and like [`empty()`] if the +//! [`Result`] is [`Err`]. +//! +//! [`Ok(v)`]: Ok +//! [`empty()`]: crate::iter::empty +//! [`once(v)`]: crate::iter::once +//! +//! Iterators over [`Result`] come in three types: +//! +//! * [`into_iter`] consumes the [`Result`] and produces the contained +//! value +//! * [`iter`] produces an immutable reference of type `&T` to the +//! contained value +//! * [`iter_mut`] produces a mutable reference of type `&mut T` to the +//! contained value +//! +//! See [Iterating over `Option`] for examples of how this can be useful. +//! +//! [Iterating over `Option`]: crate::option#iterating-over-option +//! [`into_iter`]: Result::into_iter +//! [`iter`]: Result::iter +//! [`iter_mut`]: Result::iter_mut +//! +//! You might want to use an iterator chain to do multiple instances of an +//! operation that can fail, but would like to ignore failures while +//! continuing to process the successful results. In this example, we take +//! advantage of the iterable nature of [`Result`] to select only the +//! [`Ok`] values using [`flatten`][Iterator::flatten]. +//! +//! ``` +//! # use std::str::FromStr; +//! let mut results = vec![]; +//! let mut errs = vec![]; +//! let nums: Vec<_> = ["17", "not a number", "99", "-27", "768"] +//! .into_iter() +//! .map(u8::from_str) +//! // Save clones of the raw `Result` values to inspect +//! .inspect(|x| results.push(x.clone())) +//! // Challenge: explain how this captures only the `Err` values +//! .inspect(|x| errs.extend(x.clone().err())) +//! .flatten() +//! .collect(); +//! assert_eq!(errs.len(), 3); +//! assert_eq!(nums, [17, 99]); +//! println!("results {results:?}"); +//! println!("errs {errs:?}"); +//! println!("nums {nums:?}"); +//! ``` +//! +//! ## Collecting into `Result` +//! +//! [`Result`] implements the [`FromIterator`][impl-FromIterator] trait, +//! which allows an iterator over [`Result`] values to be collected into a +//! [`Result`] of a collection of each contained value of the original +//! [`Result`] values, or [`Err`] if any of the elements was [`Err`]. +//! +//! [impl-FromIterator]: Result#impl-FromIterator%3CResult%3CA,+E%3E%3E-for-Result%3CV,+E%3E +//! +//! ``` +//! let v = [Ok(2), Ok(4), Err("err!"), Ok(8)]; +//! let res: Result, &str> = v.into_iter().collect(); +//! assert_eq!(res, Err("err!")); +//! let v = [Ok(2), Ok(4), Ok(8)]; +//! let res: Result, &str> = v.into_iter().collect(); +//! assert_eq!(res, Ok(vec![2, 4, 8])); +//! ``` +//! +//! [`Result`] also implements the [`Product`][impl-Product] and +//! [`Sum`][impl-Sum] traits, allowing an iterator over [`Result`] values +//! to provide the [`product`][Iterator::product] and +//! [`sum`][Iterator::sum] methods. +//! +//! [impl-Product]: Result#impl-Product%3CResult%3CU,+E%3E%3E-for-Result%3CT,+E%3E +//! [impl-Sum]: Result#impl-Sum%3CResult%3CU,+E%3E%3E-for-Result%3CT,+E%3E +//! +//! ``` +//! let v = [Err("error!"), Ok(1), Ok(2), Ok(3), Err("foo")]; +//! let res: Result = v.into_iter().sum(); +//! assert_eq!(res, Err("error!")); +//! let v = [Ok(1), Ok(2), Ok(21)]; +//! let res: Result = v.into_iter().product(); +//! assert_eq!(res, Ok(42)); +//! ``` + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::iter::{self, FusedIterator, TrustedLen}; +use crate::ops::{self, ControlFlow, Deref, DerefMut}; +use crate::{convert, fmt, hint}; + +/// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]). +/// +/// See the [module documentation](self) for details. +#[doc(search_unbox)] +#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] +#[must_use = "this `Result` may be an `Err` variant, which should be handled"] +#[rustc_diagnostic_item = "Result"] +#[stable(feature = "rust1", since = "1.0.0")] +pub enum Result { + /// Contains the success value + #[lang = "Ok"] + #[stable(feature = "rust1", since = "1.0.0")] + Ok(#[stable(feature = "rust1", since = "1.0.0")] T), + + /// Contains the error value + #[lang = "Err"] + #[stable(feature = "rust1", since = "1.0.0")] + Err(#[stable(feature = "rust1", since = "1.0.0")] E), +} + +///////////////////////////////////////////////////////////////////////////// +// Type implementation +///////////////////////////////////////////////////////////////////////////// + +impl Result { + ///////////////////////////////////////////////////////////////////////// + // Querying the contained values + ///////////////////////////////////////////////////////////////////////// + + /// Returns `true` if the result is [`Ok`]. + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok(-3); + /// assert_eq!(x.is_ok(), true); + /// + /// let x: Result = Err("Some error message"); + /// assert_eq!(x.is_ok(), false); + /// ``` + #[must_use = "if you intended to assert that this is ok, consider `.unwrap()` instead"] + #[rustc_const_stable(feature = "const_result_basics", since = "1.48.0")] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn is_ok(&self) -> bool { + matches!(*self, Ok(_)) + } + + /// Returns `true` if the result is [`Ok`] and the value inside of it matches a predicate. + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok(2); + /// assert_eq!(x.is_ok_and(|x| x > 1), true); + /// + /// let x: Result = Ok(0); + /// assert_eq!(x.is_ok_and(|x| x > 1), false); + /// + /// let x: Result = Err("hey"); + /// assert_eq!(x.is_ok_and(|x| x > 1), false); + /// ``` + #[must_use] + #[inline] + #[stable(feature = "is_some_and", since = "1.70.0")] + pub fn is_ok_and(self, f: impl FnOnce(T) -> bool) -> bool { + match self { + Err(_) => false, + Ok(x) => f(x), + } + } + + /// Returns `true` if the result is [`Err`]. + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok(-3); + /// assert_eq!(x.is_err(), false); + /// + /// let x: Result = Err("Some error message"); + /// assert_eq!(x.is_err(), true); + /// ``` + #[must_use = "if you intended to assert that this is err, consider `.unwrap_err()` instead"] + #[rustc_const_stable(feature = "const_result_basics", since = "1.48.0")] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn is_err(&self) -> bool { + !self.is_ok() + } + + /// Returns `true` if the result is [`Err`] and the value inside of it matches a predicate. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// let x: Result = Err(Error::new(ErrorKind::NotFound, "!")); + /// assert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), true); + /// + /// let x: Result = Err(Error::new(ErrorKind::PermissionDenied, "!")); + /// assert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), false); + /// + /// let x: Result = Ok(123); + /// assert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), false); + /// ``` + #[must_use] + #[inline] + #[stable(feature = "is_some_and", since = "1.70.0")] + pub fn is_err_and(self, f: impl FnOnce(E) -> bool) -> bool { + match self { + Ok(_) => false, + Err(e) => f(e), + } + } + + ///////////////////////////////////////////////////////////////////////// + // Adapter for each variant + ///////////////////////////////////////////////////////////////////////// + + /// Converts from `Result` to [`Option`]. + /// + /// Converts `self` into an [`Option`], consuming `self`, + /// and discarding the error, if any. + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok(2); + /// assert_eq!(x.ok(), Some(2)); + /// + /// let x: Result = Err("Nothing here"); + /// assert_eq!(x.ok(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "result_ok_method")] + pub fn ok(self) -> Option { + match self { + Ok(x) => Some(x), + Err(_) => None, + } + } + + /// Converts from `Result` to [`Option`]. + /// + /// Converts `self` into an [`Option`], consuming `self`, + /// and discarding the success value, if any. + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok(2); + /// assert_eq!(x.err(), None); + /// + /// let x: Result = Err("Nothing here"); + /// assert_eq!(x.err(), Some("Nothing here")); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn err(self) -> Option { + match self { + Ok(_) => None, + Err(x) => Some(x), + } + } + + ///////////////////////////////////////////////////////////////////////// + // Adapter for working with references + ///////////////////////////////////////////////////////////////////////// + + /// Converts from `&Result` to `Result<&T, &E>`. + /// + /// Produces a new `Result`, containing a reference + /// into the original, leaving the original in place. + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok(2); + /// assert_eq!(x.as_ref(), Ok(&2)); + /// + /// let x: Result = Err("Error"); + /// assert_eq!(x.as_ref(), Err(&"Error")); + /// ``` + #[inline] + #[rustc_const_stable(feature = "const_result_basics", since = "1.48.0")] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn as_ref(&self) -> Result<&T, &E> { + match *self { + Ok(ref x) => Ok(x), + Err(ref x) => Err(x), + } + } + + /// Converts from `&mut Result` to `Result<&mut T, &mut E>`. + /// + /// # Examples + /// + /// ``` + /// fn mutate(r: &mut Result) { + /// match r.as_mut() { + /// Ok(v) => *v = 42, + /// Err(e) => *e = 0, + /// } + /// } + /// + /// let mut x: Result = Ok(2); + /// mutate(&mut x); + /// assert_eq!(x.unwrap(), 42); + /// + /// let mut x: Result = Err(13); + /// mutate(&mut x); + /// assert_eq!(x.unwrap_err(), 0); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] + pub const fn as_mut(&mut self) -> Result<&mut T, &mut E> { + match *self { + Ok(ref mut x) => Ok(x), + Err(ref mut x) => Err(x), + } + } + + ///////////////////////////////////////////////////////////////////////// + // Transforming contained values + ///////////////////////////////////////////////////////////////////////// + + /// Maps a `Result` to `Result` by applying a function to a + /// contained [`Ok`] value, leaving an [`Err`] value untouched. + /// + /// This function can be used to compose the results of two functions. + /// + /// # Examples + /// + /// Print the numbers on each line of a string multiplied by two. + /// + /// ``` + /// let line = "1\n2\n3\n4\n"; + /// + /// for num in line.lines() { + /// match num.parse::().map(|i| i * 2) { + /// Ok(n) => println!("{n}"), + /// Err(..) => {} + /// } + /// } + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn map U>(self, op: F) -> Result { + match self { + Ok(t) => Ok(op(t)), + Err(e) => Err(e), + } + } + + /// Returns the provided default (if [`Err`]), or + /// applies a function to the contained value (if [`Ok`]). + /// + /// Arguments passed to `map_or` are eagerly evaluated; if you are passing + /// the result of a function call, it is recommended to use [`map_or_else`], + /// which is lazily evaluated. + /// + /// [`map_or_else`]: Result::map_or_else + /// + /// # Examples + /// + /// ``` + /// let x: Result<_, &str> = Ok("foo"); + /// assert_eq!(x.map_or(42, |v| v.len()), 3); + /// + /// let x: Result<&str, _> = Err("bar"); + /// assert_eq!(x.map_or(42, |v| v.len()), 42); + /// ``` + #[inline] + #[stable(feature = "result_map_or", since = "1.41.0")] + #[must_use = "if you don't need the returned value, use `if let` instead"] + pub fn map_or U>(self, default: U, f: F) -> U { + match self { + Ok(t) => f(t), + Err(_) => default, + } + } + + /// Maps a `Result` to `U` by applying fallback function `default` to + /// a contained [`Err`] value, or function `f` to a contained [`Ok`] value. + /// + /// This function can be used to unpack a successful result + /// while handling an error. + /// + /// + /// # Examples + /// + /// ``` + /// let k = 21; + /// + /// let x : Result<_, &str> = Ok("foo"); + /// assert_eq!(x.map_or_else(|e| k * 2, |v| v.len()), 3); + /// + /// let x : Result<&str, _> = Err("bar"); + /// assert_eq!(x.map_or_else(|e| k * 2, |v| v.len()), 42); + /// ``` + #[inline] + #[stable(feature = "result_map_or_else", since = "1.41.0")] + pub fn map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { + match self { + Ok(t) => f(t), + Err(e) => default(e), + } + } + + /// Maps a `Result` to `Result` by applying a function to a + /// contained [`Err`] value, leaving an [`Ok`] value untouched. + /// + /// This function can be used to pass through a successful result while handling + /// an error. + /// + /// + /// # Examples + /// + /// ``` + /// fn stringify(x: u32) -> String { format!("error code: {x}") } + /// + /// let x: Result = Ok(2); + /// assert_eq!(x.map_err(stringify), Ok(2)); + /// + /// let x: Result = Err(13); + /// assert_eq!(x.map_err(stringify), Err("error code: 13".to_string())); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn map_err F>(self, op: O) -> Result { + match self { + Ok(t) => Ok(t), + Err(e) => Err(op(e)), + } + } + + /// Calls a function with a reference to the contained value if [`Ok`]. + /// + /// Returns the original result. + /// + /// # Examples + /// + /// ``` + /// let x: u8 = "4" + /// .parse::() + /// .inspect(|x| println!("original: {x}")) + /// .map(|x| x.pow(3)) + /// .expect("failed to parse number"); + /// ``` + #[inline] + #[stable(feature = "result_option_inspect", since = "1.76.0")] + pub fn inspect(self, f: F) -> Self { + if let Ok(ref t) = self { + f(t); + } + + self + } + + /// Calls a function with a reference to the contained value if [`Err`]. + /// + /// Returns the original result. + /// + /// # Examples + /// + /// ``` + /// use std::{fs, io}; + /// + /// fn read() -> io::Result { + /// fs::read_to_string("address.txt") + /// .inspect_err(|e| eprintln!("failed to read file: {e}")) + /// } + /// ``` + #[inline] + #[stable(feature = "result_option_inspect", since = "1.76.0")] + pub fn inspect_err(self, f: F) -> Self { + if let Err(ref e) = self { + f(e); + } + + self + } + + /// Converts from `Result` (or `&Result`) to `Result<&::Target, &E>`. + /// + /// Coerces the [`Ok`] variant of the original [`Result`] via [`Deref`](crate::ops::Deref) + /// and returns the new [`Result`]. + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok("hello".to_string()); + /// let y: Result<&str, &u32> = Ok("hello"); + /// assert_eq!(x.as_deref(), y); + /// + /// let x: Result = Err(42); + /// let y: Result<&str, &u32> = Err(&42); + /// assert_eq!(x.as_deref(), y); + /// ``` + #[inline] + #[stable(feature = "inner_deref", since = "1.47.0")] + pub fn as_deref(&self) -> Result<&T::Target, &E> + where + T: Deref, + { + self.as_ref().map(|t| t.deref()) + } + + /// Converts from `Result` (or `&mut Result`) to `Result<&mut ::Target, &mut E>`. + /// + /// Coerces the [`Ok`] variant of the original [`Result`] via [`DerefMut`](crate::ops::DerefMut) + /// and returns the new [`Result`]. + /// + /// # Examples + /// + /// ``` + /// let mut s = "HELLO".to_string(); + /// let mut x: Result = Ok("hello".to_string()); + /// let y: Result<&mut str, &mut u32> = Ok(&mut s); + /// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y); + /// + /// let mut i = 42; + /// let mut x: Result = Err(42); + /// let y: Result<&mut str, &mut u32> = Err(&mut i); + /// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y); + /// ``` + #[inline] + #[stable(feature = "inner_deref", since = "1.47.0")] + pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> + where + T: DerefMut, + { + self.as_mut().map(|t| t.deref_mut()) + } + + ///////////////////////////////////////////////////////////////////////// + // Iterator constructors + ///////////////////////////////////////////////////////////////////////// + + /// Returns an iterator over the possibly contained value. + /// + /// The iterator yields one value if the result is [`Result::Ok`], otherwise none. + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok(7); + /// assert_eq!(x.iter().next(), Some(&7)); + /// + /// let x: Result = Err("nothing!"); + /// assert_eq!(x.iter().next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter(&self) -> Iter<'_, T> { + Iter { inner: self.as_ref().ok() } + } + + /// Returns a mutable iterator over the possibly contained value. + /// + /// The iterator yields one value if the result is [`Result::Ok`], otherwise none. + /// + /// # Examples + /// + /// ``` + /// let mut x: Result = Ok(7); + /// match x.iter_mut().next() { + /// Some(v) => *v = 40, + /// None => {}, + /// } + /// assert_eq!(x, Ok(40)); + /// + /// let mut x: Result = Err("nothing!"); + /// assert_eq!(x.iter_mut().next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter_mut(&mut self) -> IterMut<'_, T> { + IterMut { inner: self.as_mut().ok() } + } + + ///////////////////////////////////////////////////////////////////////// + // Extract a value + ///////////////////////////////////////////////////////////////////////// + + /// Returns the contained [`Ok`] value, consuming the `self` value. + /// + /// Because this function may panic, its use is generally discouraged. + /// Instead, prefer to use pattern matching and handle the [`Err`] + /// case explicitly, or call [`unwrap_or`], [`unwrap_or_else`], or + /// [`unwrap_or_default`]. + /// + /// [`unwrap_or`]: Result::unwrap_or + /// [`unwrap_or_else`]: Result::unwrap_or_else + /// [`unwrap_or_default`]: Result::unwrap_or_default + /// + /// # Panics + /// + /// Panics if the value is an [`Err`], with a panic message including the + /// passed message, and the content of the [`Err`]. + /// + /// + /// # Examples + /// + /// ```should_panic + /// let x: Result = Err("emergency failure"); + /// x.expect("Testing expect"); // panics with `Testing expect: emergency failure` + /// ``` + /// + /// # Recommended Message Style + /// + /// We recommend that `expect` messages are used to describe the reason you + /// _expect_ the `Result` should be `Ok`. + /// + /// ```should_panic + /// let path = std::env::var("IMPORTANT_PATH") + /// .expect("env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`"); + /// ``` + /// + /// **Hint**: If you're having trouble remembering how to phrase expect + /// error messages remember to focus on the word "should" as in "env + /// variable should be set by blah" or "the given binary should be available + /// and executable by the current user". + /// + /// For more detail on expect message styles and the reasoning behind our recommendation please + /// refer to the section on ["Common Message + /// Styles"](../../std/error/index.html#common-message-styles) in the + /// [`std::error`](../../std/error/index.html) module docs. + #[inline] + #[track_caller] + #[stable(feature = "result_expect", since = "1.4.0")] + pub fn expect(self, msg: &str) -> T + where + E: fmt::Debug, + { + match self { + Ok(t) => t, + Err(e) => unwrap_failed(msg, &e), + } + } + + /// Returns the contained [`Ok`] value, consuming the `self` value. + /// + /// Because this function may panic, its use is generally discouraged. + /// Instead, prefer to use pattern matching and handle the [`Err`] + /// case explicitly, or call [`unwrap_or`], [`unwrap_or_else`], or + /// [`unwrap_or_default`]. + /// + /// [`unwrap_or`]: Result::unwrap_or + /// [`unwrap_or_else`]: Result::unwrap_or_else + /// [`unwrap_or_default`]: Result::unwrap_or_default + /// + /// # Panics + /// + /// Panics if the value is an [`Err`], with a panic message provided by the + /// [`Err`]'s value. + /// + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let x: Result = Ok(2); + /// assert_eq!(x.unwrap(), 2); + /// ``` + /// + /// ```should_panic + /// let x: Result = Err("emergency failure"); + /// x.unwrap(); // panics with `emergency failure` + /// ``` + #[inline(always)] + #[track_caller] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn unwrap(self) -> T + where + E: fmt::Debug, + { + match self { + Ok(t) => t, + Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e), + } + } + + /// Returns the contained [`Ok`] value or a default + /// + /// Consumes the `self` argument then, if [`Ok`], returns the contained + /// value, otherwise if [`Err`], returns the default value for that + /// type. + /// + /// # Examples + /// + /// Converts a string to an integer, turning poorly-formed strings + /// into 0 (the default value for integers). [`parse`] converts + /// a string to any other type that implements [`FromStr`], returning an + /// [`Err`] on error. + /// + /// ``` + /// let good_year_from_input = "1909"; + /// let bad_year_from_input = "190blarg"; + /// let good_year = good_year_from_input.parse().unwrap_or_default(); + /// let bad_year = bad_year_from_input.parse().unwrap_or_default(); + /// + /// assert_eq!(1909, good_year); + /// assert_eq!(0, bad_year); + /// ``` + /// + /// [`parse`]: str::parse + /// [`FromStr`]: crate::str::FromStr + #[inline] + #[stable(feature = "result_unwrap_or_default", since = "1.16.0")] + pub fn unwrap_or_default(self) -> T + where + T: Default, + { + match self { + Ok(x) => x, + Err(_) => Default::default(), + } + } + + /// Returns the contained [`Err`] value, consuming the `self` value. + /// + /// # Panics + /// + /// Panics if the value is an [`Ok`], with a panic message including the + /// passed message, and the content of the [`Ok`]. + /// + /// + /// # Examples + /// + /// ```should_panic + /// let x: Result = Ok(10); + /// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10` + /// ``` + #[inline] + #[track_caller] + #[stable(feature = "result_expect_err", since = "1.17.0")] + pub fn expect_err(self, msg: &str) -> E + where + T: fmt::Debug, + { + match self { + Ok(t) => unwrap_failed(msg, &t), + Err(e) => e, + } + } + + /// Returns the contained [`Err`] value, consuming the `self` value. + /// + /// # Panics + /// + /// Panics if the value is an [`Ok`], with a custom panic message provided + /// by the [`Ok`]'s value. + /// + /// # Examples + /// + /// ```should_panic + /// let x: Result = Ok(2); + /// x.unwrap_err(); // panics with `2` + /// ``` + /// + /// ``` + /// let x: Result = Err("emergency failure"); + /// assert_eq!(x.unwrap_err(), "emergency failure"); + /// ``` + #[inline] + #[track_caller] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn unwrap_err(self) -> E + where + T: fmt::Debug, + { + match self { + Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", &t), + Err(e) => e, + } + } + + /// Returns the contained [`Ok`] value, but never panics. + /// + /// Unlike [`unwrap`], this method is known to never panic on the + /// result types it is implemented for. Therefore, it can be used + /// instead of `unwrap` as a maintainability safeguard that will fail + /// to compile if the error type of the `Result` is later changed + /// to an error that can actually occur. + /// + /// [`unwrap`]: Result::unwrap + /// + /// # Examples + /// + /// ``` + /// # #![feature(never_type)] + /// # #![feature(unwrap_infallible)] + /// + /// fn only_good_news() -> Result { + /// Ok("this is fine".into()) + /// } + /// + /// let s: String = only_good_news().into_ok(); + /// println!("{s}"); + /// ``` + #[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")] + #[inline] + pub fn into_ok(self) -> T + where + E: Into, + { + match self { + Ok(x) => x, + Err(e) => e.into(), + } + } + + /// Returns the contained [`Err`] value, but never panics. + /// + /// Unlike [`unwrap_err`], this method is known to never panic on the + /// result types it is implemented for. Therefore, it can be used + /// instead of `unwrap_err` as a maintainability safeguard that will fail + /// to compile if the ok type of the `Result` is later changed + /// to a type that can actually occur. + /// + /// [`unwrap_err`]: Result::unwrap_err + /// + /// # Examples + /// + /// ``` + /// # #![feature(never_type)] + /// # #![feature(unwrap_infallible)] + /// + /// fn only_bad_news() -> Result { + /// Err("Oops, it failed".into()) + /// } + /// + /// let error: String = only_bad_news().into_err(); + /// println!("{error}"); + /// ``` + #[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")] + #[inline] + pub fn into_err(self) -> E + where + T: Into, + { + match self { + Ok(x) => x.into(), + Err(e) => e, + } + } + + //////////////////////////////////////////////////////////////////////// + // Boolean operations on the values, eager and lazy + ///////////////////////////////////////////////////////////////////////// + + /// Returns `res` if the result is [`Ok`], otherwise returns the [`Err`] value of `self`. + /// + /// Arguments passed to `and` are eagerly evaluated; if you are passing the + /// result of a function call, it is recommended to use [`and_then`], which is + /// lazily evaluated. + /// + /// [`and_then`]: Result::and_then + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok(2); + /// let y: Result<&str, &str> = Err("late error"); + /// assert_eq!(x.and(y), Err("late error")); + /// + /// let x: Result = Err("early error"); + /// let y: Result<&str, &str> = Ok("foo"); + /// assert_eq!(x.and(y), Err("early error")); + /// + /// let x: Result = Err("not a 2"); + /// let y: Result<&str, &str> = Err("late error"); + /// assert_eq!(x.and(y), Err("not a 2")); + /// + /// let x: Result = Ok(2); + /// let y: Result<&str, &str> = Ok("different result type"); + /// assert_eq!(x.and(y), Ok("different result type")); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn and(self, res: Result) -> Result { + match self { + Ok(_) => res, + Err(e) => Err(e), + } + } + + /// Calls `op` if the result is [`Ok`], otherwise returns the [`Err`] value of `self`. + /// + /// + /// This function can be used for control flow based on `Result` values. + /// + /// # Examples + /// + /// ``` + /// fn sq_then_to_string(x: u32) -> Result { + /// x.checked_mul(x).map(|sq| sq.to_string()).ok_or("overflowed") + /// } + /// + /// assert_eq!(Ok(2).and_then(sq_then_to_string), Ok(4.to_string())); + /// assert_eq!(Ok(1_000_000).and_then(sq_then_to_string), Err("overflowed")); + /// assert_eq!(Err("not a number").and_then(sq_then_to_string), Err("not a number")); + /// ``` + /// + /// Often used to chain fallible operations that may return [`Err`]. + /// + /// ``` + /// use std::{io::ErrorKind, path::Path}; + /// + /// // Note: on Windows "/" maps to "C:\" + /// let root_modified_time = Path::new("/").metadata().and_then(|md| md.modified()); + /// assert!(root_modified_time.is_ok()); + /// + /// let should_fail = Path::new("/bad/path").metadata().and_then(|md| md.modified()); + /// assert!(should_fail.is_err()); + /// assert_eq!(should_fail.unwrap_err().kind(), ErrorKind::NotFound); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("flat_map", "flatmap")] + pub fn and_then Result>(self, op: F) -> Result { + match self { + Ok(t) => op(t), + Err(e) => Err(e), + } + } + + /// Returns `res` if the result is [`Err`], otherwise returns the [`Ok`] value of `self`. + /// + /// Arguments passed to `or` are eagerly evaluated; if you are passing the + /// result of a function call, it is recommended to use [`or_else`], which is + /// lazily evaluated. + /// + /// [`or_else`]: Result::or_else + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok(2); + /// let y: Result = Err("late error"); + /// assert_eq!(x.or(y), Ok(2)); + /// + /// let x: Result = Err("early error"); + /// let y: Result = Ok(2); + /// assert_eq!(x.or(y), Ok(2)); + /// + /// let x: Result = Err("not a 2"); + /// let y: Result = Err("late error"); + /// assert_eq!(x.or(y), Err("late error")); + /// + /// let x: Result = Ok(2); + /// let y: Result = Ok(100); + /// assert_eq!(x.or(y), Ok(2)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn or(self, res: Result) -> Result { + match self { + Ok(v) => Ok(v), + Err(_) => res, + } + } + + /// Calls `op` if the result is [`Err`], otherwise returns the [`Ok`] value of `self`. + /// + /// This function can be used for control flow based on result values. + /// + /// + /// # Examples + /// + /// ``` + /// fn sq(x: u32) -> Result { Ok(x * x) } + /// fn err(x: u32) -> Result { Err(x) } + /// + /// assert_eq!(Ok(2).or_else(sq).or_else(sq), Ok(2)); + /// assert_eq!(Ok(2).or_else(err).or_else(sq), Ok(2)); + /// assert_eq!(Err(3).or_else(sq).or_else(err), Ok(9)); + /// assert_eq!(Err(3).or_else(err).or_else(err), Err(3)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn or_else Result>(self, op: O) -> Result { + match self { + Ok(t) => Ok(t), + Err(e) => op(e), + } + } + + /// Returns the contained [`Ok`] value or a provided default. + /// + /// Arguments passed to `unwrap_or` are eagerly evaluated; if you are passing + /// the result of a function call, it is recommended to use [`unwrap_or_else`], + /// which is lazily evaluated. + /// + /// [`unwrap_or_else`]: Result::unwrap_or_else + /// + /// # Examples + /// + /// ``` + /// let default = 2; + /// let x: Result = Ok(9); + /// assert_eq!(x.unwrap_or(default), 9); + /// + /// let x: Result = Err("error"); + /// assert_eq!(x.unwrap_or(default), default); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn unwrap_or(self, default: T) -> T { + match self { + Ok(t) => t, + Err(_) => default, + } + } + + /// Returns the contained [`Ok`] value or computes it from a closure. + /// + /// + /// # Examples + /// + /// ``` + /// fn count(x: &str) -> usize { x.len() } + /// + /// assert_eq!(Ok(2).unwrap_or_else(count), 2); + /// assert_eq!(Err("foo").unwrap_or_else(count), 3); + /// ``` + #[inline] + #[track_caller] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn unwrap_or_else T>(self, op: F) -> T { + match self { + Ok(t) => t, + Err(e) => op(e), + } + } + + /// Returns the contained [`Ok`] value, consuming the `self` value, + /// without checking that the value is not an [`Err`]. + /// + /// # Safety + /// + /// Calling this method on an [`Err`] is *[undefined behavior]*. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok(2); + /// assert_eq!(unsafe { x.unwrap_unchecked() }, 2); + /// ``` + /// + /// ```no_run + /// let x: Result = Err("emergency failure"); + /// unsafe { x.unwrap_unchecked(); } // Undefined behavior! + /// ``` + #[inline] + #[track_caller] + #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] + pub unsafe fn unwrap_unchecked(self) -> T { + match self { + Ok(t) => t, + // SAFETY: the safety contract must be upheld by the caller. + Err(_) => unsafe { hint::unreachable_unchecked() }, + } + } + + /// Returns the contained [`Err`] value, consuming the `self` value, + /// without checking that the value is not an [`Ok`]. + /// + /// # Safety + /// + /// Calling this method on an [`Ok`] is *[undefined behavior]*. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ```no_run + /// let x: Result = Ok(2); + /// unsafe { x.unwrap_err_unchecked() }; // Undefined behavior! + /// ``` + /// + /// ``` + /// let x: Result = Err("emergency failure"); + /// assert_eq!(unsafe { x.unwrap_err_unchecked() }, "emergency failure"); + /// ``` + #[inline] + #[track_caller] + #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] + pub unsafe fn unwrap_err_unchecked(self) -> E { + match self { + // SAFETY: the safety contract must be upheld by the caller. + Ok(_) => unsafe { hint::unreachable_unchecked() }, + Err(e) => e, + } + } +} + +impl Result<&T, E> { + /// Maps a `Result<&T, E>` to a `Result` by copying the contents of the + /// `Ok` part. + /// + /// # Examples + /// + /// ``` + /// let val = 12; + /// let x: Result<&i32, i32> = Ok(&val); + /// assert_eq!(x, Ok(&12)); + /// let copied = x.copied(); + /// assert_eq!(copied, Ok(12)); + /// ``` + #[inline] + #[stable(feature = "result_copied", since = "1.59.0")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + pub const fn copied(self) -> Result + where + T: Copy, + { + // FIXME(const-hack): this implementation, which sidesteps using `Result::map` since it's not const + // ready yet, should be reverted when possible to avoid code repetition + match self { + Ok(&v) => Ok(v), + Err(e) => Err(e), + } + } + + /// Maps a `Result<&T, E>` to a `Result` by cloning the contents of the + /// `Ok` part. + /// + /// # Examples + /// + /// ``` + /// let val = 12; + /// let x: Result<&i32, i32> = Ok(&val); + /// assert_eq!(x, Ok(&12)); + /// let cloned = x.cloned(); + /// assert_eq!(cloned, Ok(12)); + /// ``` + #[inline] + #[stable(feature = "result_cloned", since = "1.59.0")] + pub fn cloned(self) -> Result + where + T: Clone, + { + self.map(|t| t.clone()) + } +} + +impl Result<&mut T, E> { + /// Maps a `Result<&mut T, E>` to a `Result` by copying the contents of the + /// `Ok` part. + /// + /// # Examples + /// + /// ``` + /// let mut val = 12; + /// let x: Result<&mut i32, i32> = Ok(&mut val); + /// assert_eq!(x, Ok(&mut 12)); + /// let copied = x.copied(); + /// assert_eq!(copied, Ok(12)); + /// ``` + #[inline] + #[stable(feature = "result_copied", since = "1.59.0")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + pub const fn copied(self) -> Result + where + T: Copy, + { + // FIXME(const-hack): this implementation, which sidesteps using `Result::map` since it's not const + // ready yet, should be reverted when possible to avoid code repetition + match self { + Ok(&mut v) => Ok(v), + Err(e) => Err(e), + } + } + + /// Maps a `Result<&mut T, E>` to a `Result` by cloning the contents of the + /// `Ok` part. + /// + /// # Examples + /// + /// ``` + /// let mut val = 12; + /// let x: Result<&mut i32, i32> = Ok(&mut val); + /// assert_eq!(x, Ok(&mut 12)); + /// let cloned = x.cloned(); + /// assert_eq!(cloned, Ok(12)); + /// ``` + #[inline] + #[stable(feature = "result_cloned", since = "1.59.0")] + pub fn cloned(self) -> Result + where + T: Clone, + { + self.map(|t| t.clone()) + } +} + +impl Result, E> { + /// Transposes a `Result` of an `Option` into an `Option` of a `Result`. + /// + /// `Ok(None)` will be mapped to `None`. + /// `Ok(Some(_))` and `Err(_)` will be mapped to `Some(Ok(_))` and `Some(Err(_))`. + /// + /// # Examples + /// + /// ``` + /// #[derive(Debug, Eq, PartialEq)] + /// struct SomeErr; + /// + /// let x: Result, SomeErr> = Ok(Some(5)); + /// let y: Option> = Some(Ok(5)); + /// assert_eq!(x.transpose(), y); + /// ``` + #[inline] + #[stable(feature = "transpose_result", since = "1.33.0")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + pub const fn transpose(self) -> Option> { + match self { + Ok(Some(x)) => Some(Ok(x)), + Ok(None) => None, + Err(e) => Some(Err(e)), + } + } +} + +impl Result, E> { + /// Converts from `Result, E>` to `Result` + /// + /// # Examples + /// + /// ``` + /// #![feature(result_flattening)] + /// let x: Result, u32> = Ok(Ok("hello")); + /// assert_eq!(Ok("hello"), x.flatten()); + /// + /// let x: Result, u32> = Ok(Err(6)); + /// assert_eq!(Err(6), x.flatten()); + /// + /// let x: Result, u32> = Err(6); + /// assert_eq!(Err(6), x.flatten()); + /// ``` + /// + /// Flattening only removes one level of nesting at a time: + /// + /// ``` + /// #![feature(result_flattening)] + /// let x: Result, u32>, u32> = Ok(Ok(Ok("hello"))); + /// assert_eq!(Ok(Ok("hello")), x.flatten()); + /// assert_eq!(Ok("hello"), x.flatten().flatten()); + /// ``` + #[inline] + #[unstable(feature = "result_flattening", issue = "70142")] + #[rustc_const_unstable(feature = "result_flattening", issue = "70142")] + pub const fn flatten(self) -> Result { + // FIXME(const-hack): could be written with `and_then` + match self { + Ok(inner) => inner, + Err(e) => Err(e), + } + } +} + +// This is a separate function to reduce the code size of the methods +#[cfg(not(feature = "panic_immediate_abort"))] +#[inline(never)] +#[cold] +#[track_caller] +fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! { + panic!("{msg}: {error:?}") +} + +// This is a separate function to avoid constructing a `dyn Debug` +// that gets immediately thrown away, since vtables don't get cleaned up +// by dead code elimination if a trait object is constructed even if it goes +// unused +#[cfg(feature = "panic_immediate_abort")] +#[inline] +#[cold] +#[track_caller] +fn unwrap_failed(_msg: &str, _error: &T) -> ! { + panic!() +} + +///////////////////////////////////////////////////////////////////////////// +// Trait implementations +///////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Result +where + T: Clone, + E: Clone, +{ + #[inline] + fn clone(&self) -> Self { + match self { + Ok(x) => Ok(x.clone()), + Err(x) => Err(x.clone()), + } + } + + #[inline] + fn clone_from(&mut self, source: &Self) { + match (self, source) { + (Ok(to), Ok(from)) => to.clone_from(from), + (Err(to), Err(from)) => to.clone_from(from), + (to, from) => *to = from.clone(), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for Result { + type Item = T; + type IntoIter = IntoIter; + + /// Returns a consuming iterator over the possibly contained value. + /// + /// The iterator yields one value if the result is [`Result::Ok`], otherwise none. + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok(5); + /// let v: Vec = x.into_iter().collect(); + /// assert_eq!(v, [5]); + /// + /// let x: Result = Err("nothing!"); + /// let v: Vec = x.into_iter().collect(); + /// assert_eq!(v, []); + /// ``` + #[inline] + fn into_iter(self) -> IntoIter { + IntoIter { inner: self.ok() } + } +} + +#[stable(since = "1.4.0", feature = "result_iter")] +impl<'a, T, E> IntoIterator for &'a Result { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +#[stable(since = "1.4.0", feature = "result_iter")] +impl<'a, T, E> IntoIterator for &'a mut Result { + type Item = &'a mut T; + type IntoIter = IterMut<'a, T>; + + fn into_iter(self) -> IterMut<'a, T> { + self.iter_mut() + } +} + +///////////////////////////////////////////////////////////////////////////// +// The Result Iterators +///////////////////////////////////////////////////////////////////////////// + +/// An iterator over a reference to the [`Ok`] variant of a [`Result`]. +/// +/// The iterator yields one value if the result is [`Ok`], otherwise none. +/// +/// Created by [`Result::iter`]. +#[derive(Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Iter<'a, T: 'a> { + inner: Option<&'a T>, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + + #[inline] + fn next(&mut self) -> Option<&'a T> { + self.inner.take() + } + #[inline] + fn size_hint(&self) -> (usize, Option) { + let n = if self.inner.is_some() { 1 } else { 0 }; + (n, Some(n)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for Iter<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a T> { + self.inner.take() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Iter<'_, T> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Iter<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Iter<'_, A> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Iter<'_, T> { + #[inline] + fn clone(&self) -> Self { + Iter { inner: self.inner } + } +} + +/// An iterator over a mutable reference to the [`Ok`] variant of a [`Result`]. +/// +/// Created by [`Result::iter_mut`]. +#[derive(Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IterMut<'a, T: 'a> { + inner: Option<&'a mut T>, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for IterMut<'a, T> { + type Item = &'a mut T; + + #[inline] + fn next(&mut self) -> Option<&'a mut T> { + self.inner.take() + } + #[inline] + fn size_hint(&self) -> (usize, Option) { + let n = if self.inner.is_some() { 1 } else { 0 }; + (n, Some(n)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a mut T> { + self.inner.take() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IterMut<'_, T> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IterMut<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IterMut<'_, A> {} + +/// An iterator over the value in a [`Ok`] variant of a [`Result`]. +/// +/// The iterator yields one value if the result is [`Ok`], otherwise none. +/// +/// This struct is created by the [`into_iter`] method on +/// [`Result`] (provided by the [`IntoIterator`] trait). +/// +/// [`into_iter`]: IntoIterator::into_iter +#[derive(Clone, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IntoIter { + inner: Option, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.inner.take() + } + #[inline] + fn size_hint(&self) -> (usize, Option) { + let n = if self.inner.is_some() { 1 } else { 0 }; + (n, Some(n)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + self.inner.take() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIter {} + +///////////////////////////////////////////////////////////////////////////// +// FromIterator +///////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "rust1", since = "1.0.0")] +impl> FromIterator> for Result { + /// Takes each element in the `Iterator`: if it is an `Err`, no further + /// elements are taken, and the `Err` is returned. Should no `Err` occur, a + /// container with the values of each `Result` is returned. + /// + /// Here is an example which increments every integer in a vector, + /// checking for overflow: + /// + /// ``` + /// let v = vec![1, 2]; + /// let res: Result, &'static str> = v.iter().map(|x: &u32| + /// x.checked_add(1).ok_or("Overflow!") + /// ).collect(); + /// assert_eq!(res, Ok(vec![2, 3])); + /// ``` + /// + /// Here is another example that tries to subtract one from another list + /// of integers, this time checking for underflow: + /// + /// ``` + /// let v = vec![1, 2, 0]; + /// let res: Result, &'static str> = v.iter().map(|x: &u32| + /// x.checked_sub(1).ok_or("Underflow!") + /// ).collect(); + /// assert_eq!(res, Err("Underflow!")); + /// ``` + /// + /// Here is a variation on the previous example, showing that no + /// further elements are taken from `iter` after the first `Err`. + /// + /// ``` + /// let v = vec![3, 2, 1, 10]; + /// let mut shared = 0; + /// let res: Result, &'static str> = v.iter().map(|x: &u32| { + /// shared += x; + /// x.checked_sub(2).ok_or("Underflow!") + /// }).collect(); + /// assert_eq!(res, Err("Underflow!")); + /// assert_eq!(shared, 6); + /// ``` + /// + /// Since the third element caused an underflow, no further elements were taken, + /// so the final value of `shared` is 6 (= `3 + 2 + 1`), not 16. + #[inline] + fn from_iter>>(iter: I) -> Result { + iter::try_process(iter.into_iter(), |i| i.collect()) + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl ops::Try for Result { + type Output = T; + type Residual = Result; + + #[inline] + fn from_output(output: Self::Output) -> Self { + Ok(output) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + Ok(v) => ControlFlow::Continue(v), + Err(e) => ControlFlow::Break(Err(e)), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl> ops::FromResidual> for Result { + #[inline] + #[track_caller] + fn from_residual(residual: Result) -> Self { + match residual { + Err(e) => Err(From::from(e)), + } + } +} +#[diagnostic::do_not_recommend] +#[unstable(feature = "try_trait_v2_yeet", issue = "96374")] +impl> ops::FromResidual> for Result { + #[inline] + fn from_residual(ops::Yeet(e): ops::Yeet) -> Self { + Err(From::from(e)) + } +} + +#[unstable(feature = "try_trait_v2_residual", issue = "91285")] +impl ops::Residual for Result { + type TryType = Result; +} diff --git a/CoqOfRust/core/slice/ascii.rs b/CoqOfRust/core/slice/ascii.rs new file mode 100644 index 000000000..7cdb89658 --- /dev/null +++ b/CoqOfRust/core/slice/ascii.rs @@ -0,0 +1,457 @@ +//! Operations on ASCII `[u8]`. + +use core::ascii::EscapeDefault; + +use crate::fmt::{self, Write}; +use crate::intrinsics::const_eval_select; +use crate::{ascii, iter, mem, ops}; + +#[cfg(not(test))] +impl [u8] { + /// Checks if all bytes in this slice are within the ASCII range. + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_slice_is_ascii", since = "1.74.0")] + #[must_use] + #[inline] + pub const fn is_ascii(&self) -> bool { + is_ascii(self) + } + + /// If this slice [`is_ascii`](Self::is_ascii), returns it as a slice of + /// [ASCII characters](`ascii::Char`), otherwise returns `None`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub const fn as_ascii(&self) -> Option<&[ascii::Char]> { + if self.is_ascii() { + // SAFETY: Just checked that it's ASCII + Some(unsafe { self.as_ascii_unchecked() }) + } else { + None + } + } + + /// Converts this slice of bytes into a slice of ASCII characters, + /// without checking whether they're valid. + /// + /// # Safety + /// + /// Every byte in the slice must be in `0..=127`, or else this is UB. + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub const unsafe fn as_ascii_unchecked(&self) -> &[ascii::Char] { + let byte_ptr: *const [u8] = self; + let ascii_ptr = byte_ptr as *const [ascii::Char]; + // SAFETY: The caller promised all the bytes are ASCII + unsafe { &*ascii_ptr } + } + + /// Checks that two slices are an ASCII case-insensitive match. + /// + /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, + /// but without allocating and copying temporaries. + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_unstable(feature = "const_eq_ignore_ascii_case", issue = "131719")] + #[must_use] + #[inline] + pub const fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool { + if self.len() != other.len() { + return false; + } + + // FIXME(const-hack): This implementation can be reverted when + // `core::iter::zip` is allowed in const. The original implementation: + // self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b)) + let mut a = self; + let mut b = other; + + while let ([first_a, rest_a @ ..], [first_b, rest_b @ ..]) = (a, b) { + if first_a.eq_ignore_ascii_case(&first_b) { + a = rest_a; + b = rest_b; + } else { + return false; + } + } + + true + } + + /// Converts this slice to its ASCII upper case equivalent in-place. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new uppercased value without modifying the existing one, use + /// [`to_ascii_uppercase`]. + /// + /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] + #[inline] + pub const fn make_ascii_uppercase(&mut self) { + // FIXME(const-hack): We would like to simply iterate using `for` loops but this isn't currently allowed in constant expressions. + let mut i = 0; + while i < self.len() { + let byte = &mut self[i]; + byte.make_ascii_uppercase(); + i += 1; + } + } + + /// Converts this slice to its ASCII lower case equivalent in-place. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new lowercased value without modifying the existing one, use + /// [`to_ascii_lowercase`]. + /// + /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] + #[inline] + pub const fn make_ascii_lowercase(&mut self) { + // FIXME(const-hack): We would like to simply iterate using `for` loops but this isn't currently allowed in constant expressions. + let mut i = 0; + while i < self.len() { + let byte = &mut self[i]; + byte.make_ascii_lowercase(); + i += 1; + } + } + + /// Returns an iterator that produces an escaped version of this slice, + /// treating it as an ASCII string. + /// + /// # Examples + /// + /// ``` + /// + /// let s = b"0\t\r\n'\"\\\x9d"; + /// let escaped = s.escape_ascii().to_string(); + /// assert_eq!(escaped, "0\\t\\r\\n\\'\\\"\\\\\\x9d"); + /// ``` + #[must_use = "this returns the escaped bytes as an iterator, \ + without modifying the original"] + #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] + pub fn escape_ascii(&self) -> EscapeAscii<'_> { + EscapeAscii { inner: self.iter().flat_map(EscapeByte) } + } + + /// Returns a byte slice with leading ASCII whitespace bytes removed. + /// + /// 'Whitespace' refers to the definition used by + /// [`u8::is_ascii_whitespace`]. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(b" \t hello world\n".trim_ascii_start(), b"hello world\n"); + /// assert_eq!(b" ".trim_ascii_start(), b""); + /// assert_eq!(b"".trim_ascii_start(), b""); + /// ``` + #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")] + #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")] + #[inline] + pub const fn trim_ascii_start(&self) -> &[u8] { + let mut bytes = self; + // Note: A pattern matching based approach (instead of indexing) allows + // making the function const. + while let [first, rest @ ..] = bytes { + if first.is_ascii_whitespace() { + bytes = rest; + } else { + break; + } + } + bytes + } + + /// Returns a byte slice with trailing ASCII whitespace bytes removed. + /// + /// 'Whitespace' refers to the definition used by + /// [`u8::is_ascii_whitespace`]. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(b"\r hello world\n ".trim_ascii_end(), b"\r hello world"); + /// assert_eq!(b" ".trim_ascii_end(), b""); + /// assert_eq!(b"".trim_ascii_end(), b""); + /// ``` + #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")] + #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")] + #[inline] + pub const fn trim_ascii_end(&self) -> &[u8] { + let mut bytes = self; + // Note: A pattern matching based approach (instead of indexing) allows + // making the function const. + while let [rest @ .., last] = bytes { + if last.is_ascii_whitespace() { + bytes = rest; + } else { + break; + } + } + bytes + } + + /// Returns a byte slice with leading and trailing ASCII whitespace bytes + /// removed. + /// + /// 'Whitespace' refers to the definition used by + /// [`u8::is_ascii_whitespace`]. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(b"\r hello world\n ".trim_ascii(), b"hello world"); + /// assert_eq!(b" ".trim_ascii(), b""); + /// assert_eq!(b"".trim_ascii(), b""); + /// ``` + #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")] + #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")] + #[inline] + pub const fn trim_ascii(&self) -> &[u8] { + self.trim_ascii_start().trim_ascii_end() + } +} + +impl_fn_for_zst! { + #[derive(Clone)] + struct EscapeByte impl Fn = |byte: &u8| -> ascii::EscapeDefault { + ascii::escape_default(*byte) + }; +} + +/// An iterator over the escaped version of a byte slice. +/// +/// This `struct` is created by the [`slice::escape_ascii`] method. See its +/// documentation for more information. +#[stable(feature = "inherent_ascii_escape", since = "1.60.0")] +#[derive(Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct EscapeAscii<'a> { + inner: iter::FlatMap, ascii::EscapeDefault, EscapeByte>, +} + +#[stable(feature = "inherent_ascii_escape", since = "1.60.0")] +impl<'a> iter::Iterator for EscapeAscii<'a> { + type Item = u8; + #[inline] + fn next(&mut self) -> Option { + self.inner.next() + } + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Fold: FnMut(Acc, Self::Item) -> R, + R: ops::Try, + { + self.inner.try_fold(init, fold) + } + #[inline] + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.inner.fold(init, fold) + } + #[inline] + fn last(mut self) -> Option { + self.next_back() + } +} + +#[stable(feature = "inherent_ascii_escape", since = "1.60.0")] +impl<'a> iter::DoubleEndedIterator for EscapeAscii<'a> { + fn next_back(&mut self) -> Option { + self.inner.next_back() + } +} +#[stable(feature = "inherent_ascii_escape", since = "1.60.0")] +impl<'a> iter::FusedIterator for EscapeAscii<'a> {} +#[stable(feature = "inherent_ascii_escape", since = "1.60.0")] +impl<'a> fmt::Display for EscapeAscii<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // disassemble iterator, including front/back parts of flatmap in case it has been partially consumed + let (front, slice, back) = self.clone().inner.into_parts(); + let front = front.unwrap_or(EscapeDefault::empty()); + let mut bytes = slice.unwrap_or_default().as_slice(); + let back = back.unwrap_or(EscapeDefault::empty()); + + // usually empty, so the formatter won't have to do any work + for byte in front { + f.write_char(byte as char)?; + } + + fn needs_escape(b: u8) -> bool { + b > 0x7E || b < 0x20 || b == b'\\' || b == b'\'' || b == b'"' + } + + while bytes.len() > 0 { + // fast path for the printable, non-escaped subset of ascii + let prefix = bytes.iter().take_while(|&&b| !needs_escape(b)).count(); + // SAFETY: prefix length was derived by counting bytes in the same splice, so it's in-bounds + let (prefix, remainder) = unsafe { bytes.split_at_unchecked(prefix) }; + // SAFETY: prefix is a valid utf8 sequence, as it's a subset of ASCII + let prefix = unsafe { crate::str::from_utf8_unchecked(prefix) }; + + f.write_str(prefix)?; // the fast part + + bytes = remainder; + + if let Some(&b) = bytes.first() { + // guaranteed to be non-empty, better to write it as a str + f.write_str(ascii::escape_default(b).as_str())?; + bytes = &bytes[1..]; + } + } + + // also usually empty + for byte in back { + f.write_char(byte as char)?; + } + Ok(()) + } +} +#[stable(feature = "inherent_ascii_escape", since = "1.60.0")] +impl<'a> fmt::Debug for EscapeAscii<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("EscapeAscii").finish_non_exhaustive() + } +} + +/// Returns `true` if any byte in the word `v` is nonascii (>= 128). Snarfed +/// from `../str/mod.rs`, which does something similar for utf8 validation. +#[inline] +const fn contains_nonascii(v: usize) -> bool { + const NONASCII_MASK: usize = usize::repeat_u8(0x80); + (NONASCII_MASK & v) != 0 +} + +/// ASCII test *without* the chunk-at-a-time optimizations. +/// +/// This is carefully structured to produce nice small code -- it's smaller in +/// `-O` than what the "obvious" ways produces under `-C opt-level=s`. If you +/// touch it, be sure to run (and update if needed) the assembly test. +#[unstable(feature = "str_internals", issue = "none")] +#[doc(hidden)] +#[inline] +pub const fn is_ascii_simple(mut bytes: &[u8]) -> bool { + while let [rest @ .., last] = bytes { + if !last.is_ascii() { + break; + } + bytes = rest; + } + bytes.is_empty() +} + +/// Optimized ASCII test that will use usize-at-a-time operations instead of +/// byte-at-a-time operations (when possible). +/// +/// The algorithm we use here is pretty simple. If `s` is too short, we just +/// check each byte and be done with it. Otherwise: +/// +/// - Read the first word with an unaligned load. +/// - Align the pointer, read subsequent words until end with aligned loads. +/// - Read the last `usize` from `s` with an unaligned load. +/// +/// If any of these loads produces something for which `contains_nonascii` +/// (above) returns true, then we know the answer is false. +#[inline] +#[rustc_allow_const_fn_unstable(const_eval_select)] // fallback impl has same behavior +const fn is_ascii(s: &[u8]) -> bool { + // The runtime version behaves the same as the compiletime version, it's + // just more optimized. + const_eval_select!( + @capture { s: &[u8] } -> bool: + if const { + is_ascii_simple(s) + } else { + const USIZE_SIZE: usize = mem::size_of::(); + + let len = s.len(); + let align_offset = s.as_ptr().align_offset(USIZE_SIZE); + + // If we wouldn't gain anything from the word-at-a-time implementation, fall + // back to a scalar loop. + // + // We also do this for architectures where `size_of::()` isn't + // sufficient alignment for `usize`, because it's a weird edge case. + if len < USIZE_SIZE || len < align_offset || USIZE_SIZE < mem::align_of::() { + return is_ascii_simple(s); + } + + // We always read the first word unaligned, which means `align_offset` is + // 0, we'd read the same value again for the aligned read. + let offset_to_aligned = if align_offset == 0 { USIZE_SIZE } else { align_offset }; + + let start = s.as_ptr(); + // SAFETY: We verify `len < USIZE_SIZE` above. + let first_word = unsafe { (start as *const usize).read_unaligned() }; + + if contains_nonascii(first_word) { + return false; + } + // We checked this above, somewhat implicitly. Note that `offset_to_aligned` + // is either `align_offset` or `USIZE_SIZE`, both of are explicitly checked + // above. + debug_assert!(offset_to_aligned <= len); + + // SAFETY: word_ptr is the (properly aligned) usize ptr we use to read the + // middle chunk of the slice. + let mut word_ptr = unsafe { start.add(offset_to_aligned) as *const usize }; + + // `byte_pos` is the byte index of `word_ptr`, used for loop end checks. + let mut byte_pos = offset_to_aligned; + + // Paranoia check about alignment, since we're about to do a bunch of + // unaligned loads. In practice this should be impossible barring a bug in + // `align_offset` though. + // While this method is allowed to spuriously fail in CTFE, if it doesn't + // have alignment information it should have given a `usize::MAX` for + // `align_offset` earlier, sending things through the scalar path instead of + // this one, so this check should pass if it's reachable. + debug_assert!(word_ptr.is_aligned_to(mem::align_of::())); + + // Read subsequent words until the last aligned word, excluding the last + // aligned word by itself to be done in tail check later, to ensure that + // tail is always one `usize` at most to extra branch `byte_pos == len`. + while byte_pos < len - USIZE_SIZE { + // Sanity check that the read is in bounds + debug_assert!(byte_pos + USIZE_SIZE <= len); + // And that our assumptions about `byte_pos` hold. + debug_assert!(word_ptr.cast::() == start.wrapping_add(byte_pos)); + + // SAFETY: We know `word_ptr` is properly aligned (because of + // `align_offset`), and we know that we have enough bytes between `word_ptr` and the end + let word = unsafe { word_ptr.read() }; + if contains_nonascii(word) { + return false; + } + + byte_pos += USIZE_SIZE; + // SAFETY: We know that `byte_pos <= len - USIZE_SIZE`, which means that + // after this `add`, `word_ptr` will be at most one-past-the-end. + word_ptr = unsafe { word_ptr.add(1) }; + } + + // Sanity check to ensure there really is only one `usize` left. This should + // be guaranteed by our loop condition. + debug_assert!(byte_pos <= len && len - byte_pos <= USIZE_SIZE); + + // SAFETY: This relies on `len >= USIZE_SIZE`, which we check at the start. + let last_word = unsafe { (start.add(len - USIZE_SIZE) as *const usize).read_unaligned() }; + + !contains_nonascii(last_word) + } + ) +} diff --git a/CoqOfRust/core/slice/cmp.rs b/CoqOfRust/core/slice/cmp.rs new file mode 100644 index 000000000..9cb00644e --- /dev/null +++ b/CoqOfRust/core/slice/cmp.rs @@ -0,0 +1,285 @@ +//! Comparison traits for `[T]`. + +use super::{from_raw_parts, memchr}; +use crate::cmp::{self, BytewiseEq, Ordering}; +use crate::intrinsics::compare_bytes; +use crate::num::NonZero; +use crate::{ascii, mem}; + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[U]> for [T] +where + T: PartialEq, +{ + fn eq(&self, other: &[U]) -> bool { + SlicePartialEq::equal(self, other) + } + + fn ne(&self, other: &[U]) -> bool { + SlicePartialEq::not_equal(self, other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for [T] {} + +/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison). +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for [T] { + fn cmp(&self, other: &[T]) -> Ordering { + SliceOrd::compare(self, other) + } +} + +/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison). +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for [T] { + fn partial_cmp(&self, other: &[T]) -> Option { + SlicePartialOrd::partial_compare(self, other) + } +} + +#[doc(hidden)] +// intermediate trait for specialization of slice's PartialEq +trait SlicePartialEq { + fn equal(&self, other: &[B]) -> bool; + + fn not_equal(&self, other: &[B]) -> bool { + !self.equal(other) + } +} + +// Generic slice equality +impl SlicePartialEq for [A] +where + A: PartialEq, +{ + default fn equal(&self, other: &[B]) -> bool { + if self.len() != other.len() { + return false; + } + + // Implemented as explicit indexing rather + // than zipped iterators for performance reasons. + // See PR https://github.com/rust-lang/rust/pull/116846 + for idx in 0..self.len() { + // bound checks are optimized away + if self[idx] != other[idx] { + return false; + } + } + + true + } +} + +// When each element can be compared byte-wise, we can compare all the bytes +// from the whole size in one call to the intrinsics. +impl SlicePartialEq for [A] +where + A: BytewiseEq, +{ + fn equal(&self, other: &[B]) -> bool { + if self.len() != other.len() { + return false; + } + + // SAFETY: `self` and `other` are references and are thus guaranteed to be valid. + // The two slices have been checked to have the same size above. + unsafe { + let size = mem::size_of_val(self); + compare_bytes(self.as_ptr() as *const u8, other.as_ptr() as *const u8, size) == 0 + } + } +} + +#[doc(hidden)] +// intermediate trait for specialization of slice's PartialOrd +trait SlicePartialOrd: Sized { + fn partial_compare(left: &[Self], right: &[Self]) -> Option; +} + +impl SlicePartialOrd for A { + default fn partial_compare(left: &[A], right: &[A]) -> Option { + let l = cmp::min(left.len(), right.len()); + + // Slice to the loop iteration range to enable bound check + // elimination in the compiler + let lhs = &left[..l]; + let rhs = &right[..l]; + + for i in 0..l { + match lhs[i].partial_cmp(&rhs[i]) { + Some(Ordering::Equal) => (), + non_eq => return non_eq, + } + } + + left.len().partial_cmp(&right.len()) + } +} + +// This is the impl that we would like to have. Unfortunately it's not sound. +// See `partial_ord_slice.rs`. +/* +impl SlicePartialOrd for A +where + A: Ord, +{ + default fn partial_compare(left: &[A], right: &[A]) -> Option { + Some(SliceOrd::compare(left, right)) + } +} +*/ + +impl SlicePartialOrd for A { + fn partial_compare(left: &[A], right: &[A]) -> Option { + Some(SliceOrd::compare(left, right)) + } +} + +#[rustc_specialization_trait] +trait AlwaysApplicableOrd: SliceOrd + Ord {} + +macro_rules! always_applicable_ord { + ($([$($p:tt)*] $t:ty,)*) => { + $(impl<$($p)*> AlwaysApplicableOrd for $t {})* + } +} + +always_applicable_ord! { + [] u8, [] u16, [] u32, [] u64, [] u128, [] usize, + [] i8, [] i16, [] i32, [] i64, [] i128, [] isize, + [] bool, [] char, + [T: ?Sized] *const T, [T: ?Sized] *mut T, + [T: AlwaysApplicableOrd] &T, + [T: AlwaysApplicableOrd] &mut T, + [T: AlwaysApplicableOrd] Option, +} + +#[doc(hidden)] +// intermediate trait for specialization of slice's Ord +trait SliceOrd: Sized { + fn compare(left: &[Self], right: &[Self]) -> Ordering; +} + +impl SliceOrd for A { + default fn compare(left: &[Self], right: &[Self]) -> Ordering { + let l = cmp::min(left.len(), right.len()); + + // Slice to the loop iteration range to enable bound check + // elimination in the compiler + let lhs = &left[..l]; + let rhs = &right[..l]; + + for i in 0..l { + match lhs[i].cmp(&rhs[i]) { + Ordering::Equal => (), + non_eq => return non_eq, + } + } + + left.len().cmp(&right.len()) + } +} + +/// Marks that a type should be treated as an unsigned byte for comparisons. +/// +/// # Safety +/// * The type must be readable as an `u8`, meaning it has to have the same +/// layout as `u8` and always be initialized. +/// * For every `x` and `y` of this type, `Ord(x, y)` must return the same +/// value as `Ord::cmp(transmute::<_, u8>(x), transmute::<_, u8>(y))`. +#[rustc_specialization_trait] +unsafe trait UnsignedBytewiseOrd {} + +unsafe impl UnsignedBytewiseOrd for bool {} +unsafe impl UnsignedBytewiseOrd for u8 {} +unsafe impl UnsignedBytewiseOrd for NonZero {} +unsafe impl UnsignedBytewiseOrd for Option> {} +unsafe impl UnsignedBytewiseOrd for ascii::Char {} + +// `compare_bytes` compares a sequence of unsigned bytes lexicographically, so +// use it if the requirements for `UnsignedBytewiseOrd` are fulfilled. +impl SliceOrd for A { + #[inline] + fn compare(left: &[Self], right: &[Self]) -> Ordering { + // Since the length of a slice is always less than or equal to + // isize::MAX, this never underflows. + let diff = left.len() as isize - right.len() as isize; + // This comparison gets optimized away (on x86_64 and ARM) because the + // subtraction updates flags. + let len = if left.len() < right.len() { left.len() } else { right.len() }; + let left = left.as_ptr().cast(); + let right = right.as_ptr().cast(); + // SAFETY: `left` and `right` are references and are thus guaranteed to + // be valid. `UnsignedBytewiseOrd` is only implemented for types that + // are valid u8s and can be compared the same way. We use the minimum + // of both lengths which guarantees that both regions are valid for + // reads in that interval. + let mut order = unsafe { compare_bytes(left, right, len) as isize }; + if order == 0 { + order = diff; + } + order.cmp(&0) + } +} + +pub(super) trait SliceContains: Sized { + fn slice_contains(&self, x: &[Self]) -> bool; +} + +impl SliceContains for T +where + T: PartialEq, +{ + default fn slice_contains(&self, x: &[Self]) -> bool { + x.iter().any(|y| *y == *self) + } +} + +impl SliceContains for u8 { + #[inline] + fn slice_contains(&self, x: &[Self]) -> bool { + memchr::memchr(*self, x).is_some() + } +} + +impl SliceContains for i8 { + #[inline] + fn slice_contains(&self, x: &[Self]) -> bool { + let byte = *self as u8; + // SAFETY: `i8` and `u8` have the same memory layout, thus casting `x.as_ptr()` + // as `*const u8` is safe. The `x.as_ptr()` comes from a reference and is thus guaranteed + // to be valid for reads for the length of the slice `x.len()`, which cannot be larger + // than `isize::MAX`. The returned slice is never mutated. + let bytes: &[u8] = unsafe { from_raw_parts(x.as_ptr() as *const u8, x.len()) }; + memchr::memchr(byte, bytes).is_some() + } +} + +macro_rules! impl_slice_contains { + ($($t:ty),*) => { + $( + impl SliceContains for $t { + #[inline] + fn slice_contains(&self, arr: &[$t]) -> bool { + // Make our LANE_COUNT 4x the normal lane count (aiming for 128 bit vectors). + // The compiler will nicely unroll it. + const LANE_COUNT: usize = 4 * (128 / (mem::size_of::<$t>() * 8)); + // SIMD + let mut chunks = arr.chunks_exact(LANE_COUNT); + for chunk in &mut chunks { + if chunk.iter().fold(false, |acc, x| acc | (*x == *self)) { + return true; + } + } + // Scalar remainder + return chunks.remainder().iter().any(|x| *x == *self); + } + } + )* + }; +} + +impl_slice_contains!(u16, u32, u64, i16, i32, i64, f32, f64, usize, isize); diff --git a/CoqOfRust/core/slice/index.rs b/CoqOfRust/core/slice/index.rs new file mode 100644 index 000000000..aafa19c0d --- /dev/null +++ b/CoqOfRust/core/slice/index.rs @@ -0,0 +1,1029 @@ +//! Indexing implementations for `[T]`. + +use crate::panic::const_panic; +use crate::ub_checks::assert_unsafe_precondition; +use crate::{ops, range}; + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Index for [T] +where + I: SliceIndex<[T]>, +{ + type Output = I::Output; + + #[inline(always)] + fn index(&self, index: I) -> &I::Output { + index.index(self) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::IndexMut for [T] +where + I: SliceIndex<[T]>, +{ + #[inline(always)] + fn index_mut(&mut self, index: I) -> &mut I::Output { + index.index_mut(self) + } +} + +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +const fn slice_start_index_len_fail(index: usize, len: usize) -> ! { + const_panic!( + "slice start index is out of range for slice", + "range start index {index} out of range for slice of length {len}", + index: usize, + len: usize, + ) +} + +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +const fn slice_end_index_len_fail(index: usize, len: usize) -> ! { + const_panic!( + "slice end index is out of range for slice", + "range end index {index} out of range for slice of length {len}", + index: usize, + len: usize, + ) +} + +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +const fn slice_index_order_fail(index: usize, end: usize) -> ! { + const_panic!( + "slice index start is larger than end", + "slice index starts at {index} but ends at {end}", + index: usize, + end: usize, + ) +} + +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +const fn slice_start_index_overflow_fail() -> ! { + panic!("attempted to index slice from after maximum usize"); +} + +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +const fn slice_end_index_overflow_fail() -> ! { + panic!("attempted to index slice up to maximum usize"); +} + +// The UbChecks are great for catching bugs in the unsafe methods, but including +// them in safe indexing is unnecessary and hurts inlining and debug runtime perf. +// Both the safe and unsafe public methods share these helpers, +// which use intrinsics directly to get *no* extra checks. + +#[inline(always)] +const unsafe fn get_noubcheck(ptr: *const [T], index: usize) -> *const T { + let ptr = ptr as *const T; + // SAFETY: The caller already checked these preconditions + unsafe { crate::intrinsics::offset(ptr, index) } +} + +#[inline(always)] +const unsafe fn get_mut_noubcheck(ptr: *mut [T], index: usize) -> *mut T { + let ptr = ptr as *mut T; + // SAFETY: The caller already checked these preconditions + unsafe { crate::intrinsics::offset(ptr, index) } +} + +#[inline(always)] +const unsafe fn get_offset_len_noubcheck( + ptr: *const [T], + offset: usize, + len: usize, +) -> *const [T] { + // SAFETY: The caller already checked these preconditions + let ptr = unsafe { get_noubcheck(ptr, offset) }; + crate::intrinsics::aggregate_raw_ptr(ptr, len) +} + +#[inline(always)] +const unsafe fn get_offset_len_mut_noubcheck( + ptr: *mut [T], + offset: usize, + len: usize, +) -> *mut [T] { + // SAFETY: The caller already checked these preconditions + let ptr = unsafe { get_mut_noubcheck(ptr, offset) }; + crate::intrinsics::aggregate_raw_ptr(ptr, len) +} + +mod private_slice_index { + use super::{ops, range}; + + #[stable(feature = "slice_get_slice", since = "1.28.0")] + pub trait Sealed {} + + #[stable(feature = "slice_get_slice", since = "1.28.0")] + impl Sealed for usize {} + #[stable(feature = "slice_get_slice", since = "1.28.0")] + impl Sealed for ops::Range {} + #[stable(feature = "slice_get_slice", since = "1.28.0")] + impl Sealed for ops::RangeTo {} + #[stable(feature = "slice_get_slice", since = "1.28.0")] + impl Sealed for ops::RangeFrom {} + #[stable(feature = "slice_get_slice", since = "1.28.0")] + impl Sealed for ops::RangeFull {} + #[stable(feature = "slice_get_slice", since = "1.28.0")] + impl Sealed for ops::RangeInclusive {} + #[stable(feature = "slice_get_slice", since = "1.28.0")] + impl Sealed for ops::RangeToInclusive {} + #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")] + impl Sealed for (ops::Bound, ops::Bound) {} + + #[unstable(feature = "new_range_api", issue = "125687")] + impl Sealed for range::Range {} + #[unstable(feature = "new_range_api", issue = "125687")] + impl Sealed for range::RangeInclusive {} + #[unstable(feature = "new_range_api", issue = "125687")] + impl Sealed for range::RangeFrom {} + + impl Sealed for ops::IndexRange {} +} + +/// A helper trait used for indexing operations. +/// +/// Implementations of this trait have to promise that if the argument +/// to `get_unchecked(_mut)` is a safe reference, then so is the result. +#[stable(feature = "slice_get_slice", since = "1.28.0")] +#[rustc_diagnostic_item = "SliceIndex"] +#[rustc_on_unimplemented( + on(T = "str", label = "string indices are ranges of `usize`",), + on( + all(any(T = "str", T = "&str", T = "alloc::string::String"), _Self = "{integer}"), + note = "you can use `.chars().nth()` or `.bytes().nth()`\n\ + for more information, see chapter 8 in The Book: \ + " + ), + message = "the type `{T}` cannot be indexed by `{Self}`", + label = "slice indices are of type `usize` or ranges of `usize`" +)] +pub unsafe trait SliceIndex: private_slice_index::Sealed { + /// The output type returned by methods. + #[stable(feature = "slice_get_slice", since = "1.28.0")] + type Output: ?Sized; + + /// Returns a shared reference to the output at this location, if in + /// bounds. + #[unstable(feature = "slice_index_methods", issue = "none")] + fn get(self, slice: &T) -> Option<&Self::Output>; + + /// Returns a mutable reference to the output at this location, if in + /// bounds. + #[unstable(feature = "slice_index_methods", issue = "none")] + fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>; + + /// Returns a pointer to the output at this location, without + /// performing any bounds checking. + /// + /// Calling this method with an out-of-bounds index or a dangling `slice` pointer + /// is *[undefined behavior]* even if the resulting pointer is not used. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + #[unstable(feature = "slice_index_methods", issue = "none")] + unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output; + + /// Returns a mutable pointer to the output at this location, without + /// performing any bounds checking. + /// + /// Calling this method with an out-of-bounds index or a dangling `slice` pointer + /// is *[undefined behavior]* even if the resulting pointer is not used. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + #[unstable(feature = "slice_index_methods", issue = "none")] + unsafe fn get_unchecked_mut(self, slice: *mut T) -> *mut Self::Output; + + /// Returns a shared reference to the output at this location, panicking + /// if out of bounds. + #[unstable(feature = "slice_index_methods", issue = "none")] + #[track_caller] + fn index(self, slice: &T) -> &Self::Output; + + /// Returns a mutable reference to the output at this location, panicking + /// if out of bounds. + #[unstable(feature = "slice_index_methods", issue = "none")] + #[track_caller] + fn index_mut(self, slice: &mut T) -> &mut Self::Output; +} + +/// The methods `index` and `index_mut` panic if the index is out of bounds. +#[stable(feature = "slice_get_slice_impls", since = "1.15.0")] +unsafe impl SliceIndex<[T]> for usize { + type Output = T; + + #[inline] + fn get(self, slice: &[T]) -> Option<&T> { + // SAFETY: `self` is checked to be in bounds. + if self < slice.len() { unsafe { Some(&*get_noubcheck(slice, self)) } } else { None } + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut T> { + if self < slice.len() { + // SAFETY: `self` is checked to be in bounds. + unsafe { Some(&mut *get_mut_noubcheck(slice, self)) } + } else { + None + } + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const T { + assert_unsafe_precondition!( + check_language_ub, + "slice::get_unchecked requires that the index is within the slice", + (this: usize = self, len: usize = slice.len()) => this < len + ); + // SAFETY: the caller guarantees that `slice` is not dangling, so it + // cannot be longer than `isize::MAX`. They also guarantee that + // `self` is in bounds of `slice` so `self` cannot overflow an `isize`, + // so the call to `add` is safe. + unsafe { + // Use intrinsics::assume instead of hint::assert_unchecked so that we don't check the + // precondition of this function twice. + crate::intrinsics::assume(self < slice.len()); + get_noubcheck(slice, self) + } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T { + assert_unsafe_precondition!( + check_library_ub, + "slice::get_unchecked_mut requires that the index is within the slice", + (this: usize = self, len: usize = slice.len()) => this < len + ); + // SAFETY: see comments for `get_unchecked` above. + unsafe { get_mut_noubcheck(slice, self) } + } + + #[inline] + fn index(self, slice: &[T]) -> &T { + // N.B., use intrinsic indexing + &(*slice)[self] + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut T { + // N.B., use intrinsic indexing + &mut (*slice)[self] + } +} + +/// Because `IndexRange` guarantees `start <= end`, fewer checks are needed here +/// than there are for a general `Range` (which might be `100..3`). +unsafe impl SliceIndex<[T]> for ops::IndexRange { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&[T]> { + if self.end() <= slice.len() { + // SAFETY: `self` is checked to be valid and in bounds above. + unsafe { Some(&*get_offset_len_noubcheck(slice, self.start(), self.len())) } + } else { + None + } + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { + if self.end() <= slice.len() { + // SAFETY: `self` is checked to be valid and in bounds above. + unsafe { Some(&mut *get_offset_len_mut_noubcheck(slice, self.start(), self.len())) } + } else { + None + } + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + assert_unsafe_precondition!( + check_library_ub, + "slice::get_unchecked requires that the index is within the slice", + (end: usize = self.end(), len: usize = slice.len()) => end <= len + ); + // SAFETY: the caller guarantees that `slice` is not dangling, so it + // cannot be longer than `isize::MAX`. They also guarantee that + // `self` is in bounds of `slice` so `self` cannot overflow an `isize`, + // so the call to `add` is safe. + unsafe { get_offset_len_noubcheck(slice, self.start(), self.len()) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { + assert_unsafe_precondition!( + check_library_ub, + "slice::get_unchecked_mut requires that the index is within the slice", + (end: usize = self.end(), len: usize = slice.len()) => end <= len + ); + + // SAFETY: see comments for `get_unchecked` above. + unsafe { get_offset_len_mut_noubcheck(slice, self.start(), self.len()) } + } + + #[inline] + fn index(self, slice: &[T]) -> &[T] { + if self.end() <= slice.len() { + // SAFETY: `self` is checked to be valid and in bounds above. + unsafe { &*get_offset_len_noubcheck(slice, self.start(), self.len()) } + } else { + slice_end_index_len_fail(self.end(), slice.len()) + } + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut [T] { + if self.end() <= slice.len() { + // SAFETY: `self` is checked to be valid and in bounds above. + unsafe { &mut *get_offset_len_mut_noubcheck(slice, self.start(), self.len()) } + } else { + slice_end_index_len_fail(self.end(), slice.len()) + } + } +} + +/// The methods `index` and `index_mut` panic if: +/// - the start of the range is greater than the end of the range or +/// - the end of the range is out of bounds. +#[stable(feature = "slice_get_slice_impls", since = "1.15.0")] +unsafe impl SliceIndex<[T]> for ops::Range { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&[T]> { + // Using checked_sub is a safe way to get `SubUnchecked` in MIR + if let Some(new_len) = usize::checked_sub(self.end, self.start) + && self.end <= slice.len() + { + // SAFETY: `self` is checked to be valid and in bounds above. + unsafe { Some(&*get_offset_len_noubcheck(slice, self.start, new_len)) } + } else { + None + } + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { + if let Some(new_len) = usize::checked_sub(self.end, self.start) + && self.end <= slice.len() + { + // SAFETY: `self` is checked to be valid and in bounds above. + unsafe { Some(&mut *get_offset_len_mut_noubcheck(slice, self.start, new_len)) } + } else { + None + } + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + assert_unsafe_precondition!( + check_library_ub, + "slice::get_unchecked requires that the range is within the slice", + ( + start: usize = self.start, + end: usize = self.end, + len: usize = slice.len() + ) => end >= start && end <= len + ); + + // SAFETY: the caller guarantees that `slice` is not dangling, so it + // cannot be longer than `isize::MAX`. They also guarantee that + // `self` is in bounds of `slice` so `self` cannot overflow an `isize`, + // so the call to `add` is safe and the length calculation cannot overflow. + unsafe { + // Using the intrinsic avoids a superfluous UB check, + // since the one on this method already checked `end >= start`. + let new_len = crate::intrinsics::unchecked_sub(self.end, self.start); + get_offset_len_noubcheck(slice, self.start, new_len) + } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { + assert_unsafe_precondition!( + check_library_ub, + "slice::get_unchecked_mut requires that the range is within the slice", + ( + start: usize = self.start, + end: usize = self.end, + len: usize = slice.len() + ) => end >= start && end <= len + ); + // SAFETY: see comments for `get_unchecked` above. + unsafe { + let new_len = crate::intrinsics::unchecked_sub(self.end, self.start); + get_offset_len_mut_noubcheck(slice, self.start, new_len) + } + } + + #[inline(always)] + fn index(self, slice: &[T]) -> &[T] { + // Using checked_sub is a safe way to get `SubUnchecked` in MIR + let Some(new_len) = usize::checked_sub(self.end, self.start) else { + slice_index_order_fail(self.start, self.end) + }; + if self.end > slice.len() { + slice_end_index_len_fail(self.end, slice.len()); + } + // SAFETY: `self` is checked to be valid and in bounds above. + unsafe { &*get_offset_len_noubcheck(slice, self.start, new_len) } + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut [T] { + let Some(new_len) = usize::checked_sub(self.end, self.start) else { + slice_index_order_fail(self.start, self.end) + }; + if self.end > slice.len() { + slice_end_index_len_fail(self.end, slice.len()); + } + // SAFETY: `self` is checked to be valid and in bounds above. + unsafe { &mut *get_offset_len_mut_noubcheck(slice, self.start, new_len) } + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +unsafe impl SliceIndex<[T]> for range::Range { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&[T]> { + ops::Range::from(self).get(slice) + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { + ops::Range::from(self).get_mut(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { ops::Range::from(self).get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { ops::Range::from(self).get_unchecked_mut(slice) } + } + + #[inline(always)] + fn index(self, slice: &[T]) -> &[T] { + ops::Range::from(self).index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut [T] { + ops::Range::from(self).index_mut(slice) + } +} + +/// The methods `index` and `index_mut` panic if the end of the range is out of bounds. +#[stable(feature = "slice_get_slice_impls", since = "1.15.0")] +unsafe impl SliceIndex<[T]> for ops::RangeTo { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&[T]> { + (0..self.end).get(slice) + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { + (0..self.end).get_mut(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (0..self.end).get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (0..self.end).get_unchecked_mut(slice) } + } + + #[inline(always)] + fn index(self, slice: &[T]) -> &[T] { + (0..self.end).index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut [T] { + (0..self.end).index_mut(slice) + } +} + +/// The methods `index` and `index_mut` panic if the start of the range is out of bounds. +#[stable(feature = "slice_get_slice_impls", since = "1.15.0")] +unsafe impl SliceIndex<[T]> for ops::RangeFrom { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&[T]> { + (self.start..slice.len()).get(slice) + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { + (self.start..slice.len()).get_mut(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (self.start..slice.len()).get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (self.start..slice.len()).get_unchecked_mut(slice) } + } + + #[inline] + fn index(self, slice: &[T]) -> &[T] { + if self.start > slice.len() { + slice_start_index_len_fail(self.start, slice.len()); + } + // SAFETY: `self` is checked to be valid and in bounds above. + unsafe { &*self.get_unchecked(slice) } + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut [T] { + if self.start > slice.len() { + slice_start_index_len_fail(self.start, slice.len()); + } + // SAFETY: `self` is checked to be valid and in bounds above. + unsafe { &mut *self.get_unchecked_mut(slice) } + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +unsafe impl SliceIndex<[T]> for range::RangeFrom { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&[T]> { + ops::RangeFrom::from(self).get(slice) + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { + ops::RangeFrom::from(self).get_mut(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { ops::RangeFrom::from(self).get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { ops::RangeFrom::from(self).get_unchecked_mut(slice) } + } + + #[inline] + fn index(self, slice: &[T]) -> &[T] { + ops::RangeFrom::from(self).index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut [T] { + ops::RangeFrom::from(self).index_mut(slice) + } +} + +#[stable(feature = "slice_get_slice_impls", since = "1.15.0")] +unsafe impl SliceIndex<[T]> for ops::RangeFull { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&[T]> { + Some(slice) + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { + Some(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + slice + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { + slice + } + + #[inline] + fn index(self, slice: &[T]) -> &[T] { + slice + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut [T] { + slice + } +} + +/// The methods `index` and `index_mut` panic if: +/// - the end of the range is `usize::MAX` or +/// - the start of the range is greater than the end of the range or +/// - the end of the range is out of bounds. +#[stable(feature = "inclusive_range", since = "1.26.0")] +unsafe impl SliceIndex<[T]> for ops::RangeInclusive { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&[T]> { + if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) } + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { + if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) } + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { self.into_slice_range().get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { self.into_slice_range().get_unchecked_mut(slice) } + } + + #[inline] + fn index(self, slice: &[T]) -> &[T] { + if *self.end() == usize::MAX { + slice_end_index_overflow_fail(); + } + self.into_slice_range().index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut [T] { + if *self.end() == usize::MAX { + slice_end_index_overflow_fail(); + } + self.into_slice_range().index_mut(slice) + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +unsafe impl SliceIndex<[T]> for range::RangeInclusive { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&[T]> { + ops::RangeInclusive::from(self).get(slice) + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { + ops::RangeInclusive::from(self).get_mut(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { ops::RangeInclusive::from(self).get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { ops::RangeInclusive::from(self).get_unchecked_mut(slice) } + } + + #[inline] + fn index(self, slice: &[T]) -> &[T] { + ops::RangeInclusive::from(self).index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut [T] { + ops::RangeInclusive::from(self).index_mut(slice) + } +} + +/// The methods `index` and `index_mut` panic if the end of the range is out of bounds. +#[stable(feature = "inclusive_range", since = "1.26.0")] +unsafe impl SliceIndex<[T]> for ops::RangeToInclusive { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&[T]> { + (0..=self.end).get(slice) + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { + (0..=self.end).get_mut(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (0..=self.end).get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (0..=self.end).get_unchecked_mut(slice) } + } + + #[inline] + fn index(self, slice: &[T]) -> &[T] { + (0..=self.end).index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut [T] { + (0..=self.end).index_mut(slice) + } +} + +/// Performs bounds checking of a range. +/// +/// This method is similar to [`Index::index`] for slices, but it returns a +/// [`Range`] equivalent to `range`. You can use this method to turn any range +/// into `start` and `end` values. +/// +/// `bounds` is the range of the slice to use for bounds checking. It should +/// be a [`RangeTo`] range that ends at the length of the slice. +/// +/// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and +/// [`slice::get_unchecked_mut`] for slices with the given range. +/// +/// [`Range`]: ops::Range +/// [`RangeTo`]: ops::RangeTo +/// [`slice::get_unchecked`]: slice::get_unchecked +/// [`slice::get_unchecked_mut`]: slice::get_unchecked_mut +/// +/// # Panics +/// +/// Panics if `range` would be out of bounds. +/// +/// # Examples +/// +/// ``` +/// #![feature(slice_range)] +/// +/// use std::slice; +/// +/// let v = [10, 40, 30]; +/// assert_eq!(1..2, slice::range(1..2, ..v.len())); +/// assert_eq!(0..2, slice::range(..2, ..v.len())); +/// assert_eq!(1..3, slice::range(1.., ..v.len())); +/// ``` +/// +/// Panics when [`Index::index`] would panic: +/// +/// ```should_panic +/// #![feature(slice_range)] +/// +/// use std::slice; +/// +/// let _ = slice::range(2..1, ..3); +/// ``` +/// +/// ```should_panic +/// #![feature(slice_range)] +/// +/// use std::slice; +/// +/// let _ = slice::range(1..4, ..3); +/// ``` +/// +/// ```should_panic +/// #![feature(slice_range)] +/// +/// use std::slice; +/// +/// let _ = slice::range(1..=usize::MAX, ..3); +/// ``` +/// +/// [`Index::index`]: ops::Index::index +#[track_caller] +#[unstable(feature = "slice_range", issue = "76393")] +#[must_use] +pub fn range(range: R, bounds: ops::RangeTo) -> ops::Range +where + R: ops::RangeBounds, +{ + let len = bounds.end; + + let start = match range.start_bound() { + ops::Bound::Included(&start) => start, + ops::Bound::Excluded(start) => { + start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail()) + } + ops::Bound::Unbounded => 0, + }; + + let end = match range.end_bound() { + ops::Bound::Included(end) => { + end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail()) + } + ops::Bound::Excluded(&end) => end, + ops::Bound::Unbounded => len, + }; + + if start > end { + slice_index_order_fail(start, end); + } + if end > len { + slice_end_index_len_fail(end, len); + } + + ops::Range { start, end } +} + +/// Performs bounds checking of a range without panicking. +/// +/// This is a version of [`range()`] that returns [`None`] instead of panicking. +/// +/// # Examples +/// +/// ``` +/// #![feature(slice_range)] +/// +/// use std::slice; +/// +/// let v = [10, 40, 30]; +/// assert_eq!(Some(1..2), slice::try_range(1..2, ..v.len())); +/// assert_eq!(Some(0..2), slice::try_range(..2, ..v.len())); +/// assert_eq!(Some(1..3), slice::try_range(1.., ..v.len())); +/// ``` +/// +/// Returns [`None`] when [`Index::index`] would panic: +/// +/// ``` +/// #![feature(slice_range)] +/// +/// use std::slice; +/// +/// assert_eq!(None, slice::try_range(2..1, ..3)); +/// assert_eq!(None, slice::try_range(1..4, ..3)); +/// assert_eq!(None, slice::try_range(1..=usize::MAX, ..3)); +/// ``` +/// +/// [`Index::index`]: ops::Index::index +#[unstable(feature = "slice_range", issue = "76393")] +#[must_use] +pub fn try_range(range: R, bounds: ops::RangeTo) -> Option> +where + R: ops::RangeBounds, +{ + let len = bounds.end; + + let start = match range.start_bound() { + ops::Bound::Included(&start) => start, + ops::Bound::Excluded(start) => start.checked_add(1)?, + ops::Bound::Unbounded => 0, + }; + + let end = match range.end_bound() { + ops::Bound::Included(end) => end.checked_add(1)?, + ops::Bound::Excluded(&end) => end, + ops::Bound::Unbounded => len, + }; + + if start > end || end > len { None } else { Some(ops::Range { start, end }) } +} + +/// Converts a pair of `ops::Bound`s into `ops::Range` without performing any +/// bounds checking or (in debug) overflow checking. +pub(crate) fn into_range_unchecked( + len: usize, + (start, end): (ops::Bound, ops::Bound), +) -> ops::Range { + use ops::Bound; + let start = match start { + Bound::Included(i) => i, + Bound::Excluded(i) => i + 1, + Bound::Unbounded => 0, + }; + let end = match end { + Bound::Included(i) => i + 1, + Bound::Excluded(i) => i, + Bound::Unbounded => len, + }; + start..end +} + +/// Converts pair of `ops::Bound`s into `ops::Range`. +/// Returns `None` on overflowing indices. +pub(crate) fn into_range( + len: usize, + (start, end): (ops::Bound, ops::Bound), +) -> Option> { + use ops::Bound; + let start = match start { + Bound::Included(start) => start, + Bound::Excluded(start) => start.checked_add(1)?, + Bound::Unbounded => 0, + }; + + let end = match end { + Bound::Included(end) => end.checked_add(1)?, + Bound::Excluded(end) => end, + Bound::Unbounded => len, + }; + + // Don't bother with checking `start < end` and `end <= len` + // since these checks are handled by `Range` impls + + Some(start..end) +} + +/// Converts pair of `ops::Bound`s into `ops::Range`. +/// Panics on overflowing indices. +pub(crate) fn into_slice_range( + len: usize, + (start, end): (ops::Bound, ops::Bound), +) -> ops::Range { + use ops::Bound; + let start = match start { + Bound::Included(start) => start, + Bound::Excluded(start) => { + start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail()) + } + Bound::Unbounded => 0, + }; + + let end = match end { + Bound::Included(end) => { + end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail()) + } + Bound::Excluded(end) => end, + Bound::Unbounded => len, + }; + + // Don't bother with checking `start < end` and `end <= len` + // since these checks are handled by `Range` impls + + start..end +} + +#[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")] +unsafe impl SliceIndex<[T]> for (ops::Bound, ops::Bound) { + type Output = [T]; + + #[inline] + fn get(self, slice: &[T]) -> Option<&Self::Output> { + into_range(slice.len(), self)?.get(slice) + } + + #[inline] + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + into_range(slice.len(), self)?.get_mut(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { into_range_unchecked(slice.len(), self).get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { into_range_unchecked(slice.len(), self).get_unchecked_mut(slice) } + } + + #[inline] + fn index(self, slice: &[T]) -> &Self::Output { + into_slice_range(slice.len(), self).index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + into_slice_range(slice.len(), self).index_mut(slice) + } +} diff --git a/CoqOfRust/core/slice/iter.rs b/CoqOfRust/core/slice/iter.rs new file mode 100644 index 000000000..c5746157d --- /dev/null +++ b/CoqOfRust/core/slice/iter.rs @@ -0,0 +1,3466 @@ +//! Definitions of a bunch of iterators for `[T]`. + +#[macro_use] // import iterator! and forward_iterator! +mod macros; + +use super::{from_raw_parts, from_raw_parts_mut}; +use crate::hint::assert_unchecked; +use crate::iter::{ + FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, UncheckedIterator, +}; +use crate::marker::PhantomData; +use crate::mem::{self, SizedTypeProperties}; +use crate::num::NonZero; +use crate::ptr::{NonNull, without_provenance, without_provenance_mut}; +use crate::{cmp, fmt}; + +#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] +impl !Iterator for [T] {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> IntoIterator for &'a [T] { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> IntoIterator for &'a mut [T] { + type Item = &'a mut T; + type IntoIter = IterMut<'a, T>; + + fn into_iter(self) -> IterMut<'a, T> { + self.iter_mut() + } +} + +/// Immutable slice iterator +/// +/// This struct is created by the [`iter`] method on [slices]. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// // First, we declare a type which has `iter` method to get the `Iter` struct (`&[usize]` here): +/// let slice = &[1, 2, 3]; +/// +/// // Then, we iterate over it: +/// for element in slice.iter() { +/// println!("{element}"); +/// } +/// ``` +/// +/// [`iter`]: slice::iter +/// [slices]: slice +#[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[rustc_diagnostic_item = "SliceIter"] +pub struct Iter<'a, T: 'a> { + /// The pointer to the next element to return, or the past-the-end location + /// if the iterator is empty. + /// + /// This address will be used for all ZST elements, never changed. + ptr: NonNull, + /// For non-ZSTs, the non-null pointer to the past-the-end element. + /// + /// For ZSTs, this is `ptr::dangling(len)`. + end_or_len: *const T, + _marker: PhantomData<&'a T>, +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for Iter<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Iter").field(&self.as_slice()).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for Iter<'_, T> {} +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for Iter<'_, T> {} + +impl<'a, T> Iter<'a, T> { + #[inline] + pub(super) fn new(slice: &'a [T]) -> Self { + let len = slice.len(); + let ptr: NonNull = NonNull::from(slice).cast(); + // SAFETY: Similar to `IterMut::new`. + unsafe { + let end_or_len = + if T::IS_ZST { without_provenance(len) } else { ptr.as_ptr().add(len) }; + + Self { ptr, end_or_len, _marker: PhantomData } + } + } + + /// Views the underlying data as a subslice of the original data. + /// + /// This has the same lifetime as the original slice, and so the + /// iterator can continue to be used while this exists. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // First, we declare a type which has the `iter` method to get the `Iter` + /// // struct (`&[usize]` here): + /// let slice = &[1, 2, 3]; + /// + /// // Then, we get the iterator: + /// let mut iter = slice.iter(); + /// // So if we print what `as_slice` method returns here, we have "[1, 2, 3]": + /// println!("{:?}", iter.as_slice()); + /// + /// // Next, we move to the second element of the slice: + /// iter.next(); + /// // Now `as_slice` returns "[2, 3]": + /// println!("{:?}", iter.as_slice()); + /// ``` + #[must_use] + #[stable(feature = "iter_to_slice", since = "1.4.0")] + #[inline] + pub fn as_slice(&self) -> &'a [T] { + self.make_slice() + } +} + +iterator! {struct Iter -> *const T, &'a T, const, {/* no mut */}, as_ref, { + fn is_sorted_by(self, mut compare: F) -> bool + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> bool, + { + self.as_slice().is_sorted_by(|a, b| compare(&a, &b)) + } +}} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Iter<'_, T> { + #[inline] + fn clone(&self) -> Self { + Iter { ptr: self.ptr, end_or_len: self.end_or_len, _marker: self._marker } + } +} + +#[stable(feature = "slice_iter_as_ref", since = "1.13.0")] +impl AsRef<[T]> for Iter<'_, T> { + #[inline] + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +/// Mutable slice iterator. +/// +/// This struct is created by the [`iter_mut`] method on [slices]. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// // First, we declare a type which has `iter_mut` method to get the `IterMut` +/// // struct (`&[usize]` here): +/// let mut slice = &mut [1, 2, 3]; +/// +/// // Then, we iterate over it and increment each element value: +/// for element in slice.iter_mut() { +/// *element += 1; +/// } +/// +/// // We now have "[2, 3, 4]": +/// println!("{slice:?}"); +/// ``` +/// +/// [`iter_mut`]: slice::iter_mut +/// [slices]: slice +#[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct IterMut<'a, T: 'a> { + /// The pointer to the next element to return, or the past-the-end location + /// if the iterator is empty. + /// + /// This address will be used for all ZST elements, never changed. + ptr: NonNull, + /// For non-ZSTs, the non-null pointer to the past-the-end element. + /// + /// For ZSTs, this is `ptr::without_provenance_mut(len)`. + end_or_len: *mut T, + _marker: PhantomData<&'a mut T>, +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for IterMut<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IterMut").field(&self.make_slice()).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for IterMut<'_, T> {} +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for IterMut<'_, T> {} + +impl<'a, T> IterMut<'a, T> { + #[inline] + pub(super) fn new(slice: &'a mut [T]) -> Self { + let len = slice.len(); + let ptr: NonNull = NonNull::from(slice).cast(); + // SAFETY: There are several things here: + // + // `ptr` has been obtained by `slice.as_ptr()` where `slice` is a valid + // reference thus it is non-NUL and safe to use and pass to + // `NonNull::new_unchecked` . + // + // Adding `slice.len()` to the starting pointer gives a pointer + // at the end of `slice`. `end` will never be dereferenced, only checked + // for direct pointer equality with `ptr` to check if the iterator is + // done. + // + // In the case of a ZST, the end pointer is just the length. It's never + // used as a pointer at all, and thus it's fine to have no provenance. + // + // See the `next_unchecked!` and `is_empty!` macros as well as the + // `post_inc_start` method for more information. + unsafe { + let end_or_len = + if T::IS_ZST { without_provenance_mut(len) } else { ptr.as_ptr().add(len) }; + + Self { ptr, end_or_len, _marker: PhantomData } + } + } + + /// Views the underlying data as a subslice of the original data. + /// + /// To avoid creating `&mut` references that alias, this is forced + /// to consume the iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // First, we declare a type which has `iter_mut` method to get the `IterMut` + /// // struct (`&[usize]` here): + /// let mut slice = &mut [1, 2, 3]; + /// + /// { + /// // Then, we get the iterator: + /// let mut iter = slice.iter_mut(); + /// // We move to next element: + /// iter.next(); + /// // So if we print what `into_slice` method returns here, we have "[2, 3]": + /// println!("{:?}", iter.into_slice()); + /// } + /// + /// // Now let's modify a value of the slice: + /// { + /// // First we get back the iterator: + /// let mut iter = slice.iter_mut(); + /// // We change the value of the first element of the slice returned by the `next` method: + /// *iter.next().unwrap() += 1; + /// } + /// // Now slice is "[2, 2, 3]": + /// println!("{slice:?}"); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "iter_to_slice", since = "1.4.0")] + pub fn into_slice(self) -> &'a mut [T] { + // SAFETY: the iterator was created from a mutable slice with pointer + // `self.ptr` and length `len!(self)`. This guarantees that all the prerequisites + // for `from_raw_parts_mut` are fulfilled. + unsafe { from_raw_parts_mut(self.ptr.as_ptr(), len!(self)) } + } + + /// Views the underlying data as a subslice of the original data. + /// + /// To avoid creating `&mut [T]` references that alias, the returned slice + /// borrows its lifetime from the iterator the method is applied on. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut slice: &mut [usize] = &mut [1, 2, 3]; + /// + /// // First, we get the iterator: + /// let mut iter = slice.iter_mut(); + /// // So if we check what the `as_slice` method returns here, we have "[1, 2, 3]": + /// assert_eq!(iter.as_slice(), &[1, 2, 3]); + /// + /// // Next, we move to the second element of the slice: + /// iter.next(); + /// // Now `as_slice` returns "[2, 3]": + /// assert_eq!(iter.as_slice(), &[2, 3]); + /// ``` + #[must_use] + #[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")] + #[inline] + pub fn as_slice(&self) -> &[T] { + self.make_slice() + } + + /// Views the underlying data as a mutable subslice of the original data. + /// + /// To avoid creating `&mut [T]` references that alias, the returned slice + /// borrows its lifetime from the iterator the method is applied on. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(slice_iter_mut_as_mut_slice)] + /// + /// let mut slice: &mut [usize] = &mut [1, 2, 3]; + /// + /// // First, we get the iterator: + /// let mut iter = slice.iter_mut(); + /// // Then, we get a mutable slice from it: + /// let mut_slice = iter.as_mut_slice(); + /// // So if we check what the `as_mut_slice` method returned, we have "[1, 2, 3]": + /// assert_eq!(mut_slice, &mut [1, 2, 3]); + /// + /// // We can use it to mutate the slice: + /// mut_slice[0] = 4; + /// mut_slice[2] = 5; + /// + /// // Next, we can move to the second element of the slice, checking that + /// // it yields the value we just wrote: + /// assert_eq!(iter.next(), Some(&mut 4)); + /// // Now `as_mut_slice` returns "[2, 5]": + /// assert_eq!(iter.as_mut_slice(), &mut [2, 5]); + /// ``` + #[must_use] + // FIXME: Uncomment the `AsMut<[T]>` impl when this gets stabilized. + #[unstable(feature = "slice_iter_mut_as_mut_slice", issue = "93079")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: the iterator was created from a mutable slice with pointer + // `self.ptr` and length `len!(self)`. This guarantees that all the prerequisites + // for `from_raw_parts_mut` are fulfilled. + unsafe { from_raw_parts_mut(self.ptr.as_ptr(), len!(self)) } + } +} + +#[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")] +impl AsRef<[T]> for IterMut<'_, T> { + #[inline] + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +// #[stable(feature = "slice_iter_mut_as_mut_slice", since = "FIXME")] +// impl AsMut<[T]> for IterMut<'_, T> { +// fn as_mut(&mut self) -> &mut [T] { +// self.as_mut_slice() +// } +// } + +iterator! {struct IterMut -> *mut T, &'a mut T, mut, {mut}, as_mut, {}} + +/// An internal abstraction over the splitting iterators, so that +/// splitn, splitn_mut etc can be implemented once. +#[doc(hidden)] +pub(super) trait SplitIter: DoubleEndedIterator { + /// Marks the underlying iterator as complete, extracting the remaining + /// portion of the slice. + fn finish(&mut self) -> Option; +} + +/// An iterator over subslices separated by elements that match a predicate +/// function. +/// +/// This struct is created by the [`split`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let slice = [10, 40, 33, 20]; +/// let mut iter = slice.split(|num| num % 3 == 0); +/// assert_eq!(iter.next(), Some(&[10, 40][..])); +/// assert_eq!(iter.next(), Some(&[20][..])); +/// assert_eq!(iter.next(), None); +/// ``` +/// +/// [`split`]: slice::split +/// [slices]: slice +#[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct Split<'a, T: 'a, P> +where + P: FnMut(&T) -> bool, +{ + // Used for `SplitWhitespace` and `SplitAsciiWhitespace` `as_str` methods + pub(crate) v: &'a [T], + pred: P, + // Used for `SplitAsciiWhitespace` `as_str` method + pub(crate) finished: bool, +} + +impl<'a, T: 'a, P: FnMut(&T) -> bool> Split<'a, T, P> { + #[inline] + pub(super) fn new(slice: &'a [T], pred: P) -> Self { + Self { v: slice, pred, finished: false } + } + /// Returns a slice which contains items not yet handled by split. + /// # Example + /// + /// ``` + /// #![feature(split_as_slice)] + /// let slice = [1,2,3,4,5]; + /// let mut split = slice.split(|v| v % 2 == 0); + /// assert!(split.next().is_some()); + /// assert_eq!(split.as_slice(), &[3,4,5]); + /// ``` + #[unstable(feature = "split_as_slice", issue = "96137")] + pub fn as_slice(&self) -> &'a [T] { + if self.finished { &[] } else { &self.v } + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for Split<'_, T, P> +where + P: FnMut(&T) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Split").field("v", &self.v).field("finished", &self.finished).finish() + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Split<'_, T, P> +where + P: Clone + FnMut(&T) -> bool, +{ + fn clone(&self) -> Self { + Split { v: self.v, pred: self.pred.clone(), finished: self.finished } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, P> Iterator for Split<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + type Item = &'a [T]; + + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + if self.finished { + return None; + } + + match self.v.iter().position(|x| (self.pred)(x)) { + None => self.finish(), + Some(idx) => { + let (left, right) = + // SAFETY: if v.iter().position returns Some(idx), that + // idx is definitely a valid index for v + unsafe { (self.v.get_unchecked(..idx), self.v.get_unchecked(idx + 1..)) }; + let ret = Some(left); + self.v = right; + ret + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.finished { + (0, Some(0)) + } else { + // If the predicate doesn't match anything, we yield one slice. + // If it matches every element, we yield `len() + 1` empty slices. + (1, Some(self.v.len() + 1)) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, P> DoubleEndedIterator for Split<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + if self.finished { + return None; + } + + match self.v.iter().rposition(|x| (self.pred)(x)) { + None => self.finish(), + Some(idx) => { + let (left, right) = + // SAFETY: if v.iter().rposition returns Some(idx), then + // idx is definitely a valid index for v + unsafe { (self.v.get_unchecked(..idx), self.v.get_unchecked(idx + 1..)) }; + let ret = Some(right); + self.v = left; + ret + } + } + } +} + +impl<'a, T, P> SplitIter for Split<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + #[inline] + fn finish(&mut self) -> Option<&'a [T]> { + if self.finished { + None + } else { + self.finished = true; + Some(self.v) + } + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Split<'_, T, P> where P: FnMut(&T) -> bool {} + +/// An iterator over subslices separated by elements that match a predicate +/// function. Unlike `Split`, it contains the matched part as a terminator +/// of the subslice. +/// +/// This struct is created by the [`split_inclusive`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let slice = [10, 40, 33, 20]; +/// let mut iter = slice.split_inclusive(|num| num % 3 == 0); +/// assert_eq!(iter.next(), Some(&[10, 40, 33][..])); +/// assert_eq!(iter.next(), Some(&[20][..])); +/// assert_eq!(iter.next(), None); +/// ``` +/// +/// [`split_inclusive`]: slice::split_inclusive +/// [slices]: slice +#[stable(feature = "split_inclusive", since = "1.51.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct SplitInclusive<'a, T: 'a, P> +where + P: FnMut(&T) -> bool, +{ + v: &'a [T], + pred: P, + finished: bool, +} + +impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitInclusive<'a, T, P> { + #[inline] + pub(super) fn new(slice: &'a [T], pred: P) -> Self { + let finished = slice.is_empty(); + Self { v: slice, pred, finished } + } +} + +#[stable(feature = "split_inclusive", since = "1.51.0")] +impl fmt::Debug for SplitInclusive<'_, T, P> +where + P: FnMut(&T) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SplitInclusive") + .field("v", &self.v) + .field("finished", &self.finished) + .finish() + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "split_inclusive", since = "1.51.0")] +impl Clone for SplitInclusive<'_, T, P> +where + P: Clone + FnMut(&T) -> bool, +{ + fn clone(&self) -> Self { + SplitInclusive { v: self.v, pred: self.pred.clone(), finished: self.finished } + } +} + +#[stable(feature = "split_inclusive", since = "1.51.0")] +impl<'a, T, P> Iterator for SplitInclusive<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + type Item = &'a [T]; + + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + if self.finished { + return None; + } + + let idx = + self.v.iter().position(|x| (self.pred)(x)).map(|idx| idx + 1).unwrap_or(self.v.len()); + if idx == self.v.len() { + self.finished = true; + } + let ret = Some(&self.v[..idx]); + self.v = &self.v[idx..]; + ret + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.finished { + (0, Some(0)) + } else { + // If the predicate doesn't match anything, we yield one slice. + // If it matches every element, we yield `len()` one-element slices, + // or a single empty slice. + (1, Some(cmp::max(1, self.v.len()))) + } + } +} + +#[stable(feature = "split_inclusive", since = "1.51.0")] +impl<'a, T, P> DoubleEndedIterator for SplitInclusive<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + if self.finished { + return None; + } + + // The last index of self.v is already checked and found to match + // by the last iteration, so we start searching a new match + // one index to the left. + let remainder = if self.v.is_empty() { &[] } else { &self.v[..(self.v.len() - 1)] }; + let idx = remainder.iter().rposition(|x| (self.pred)(x)).map(|idx| idx + 1).unwrap_or(0); + if idx == 0 { + self.finished = true; + } + let ret = Some(&self.v[idx..]); + self.v = &self.v[..idx]; + ret + } +} + +#[stable(feature = "split_inclusive", since = "1.51.0")] +impl FusedIterator for SplitInclusive<'_, T, P> where P: FnMut(&T) -> bool {} + +/// An iterator over the mutable subslices of the vector which are separated +/// by elements that match `pred`. +/// +/// This struct is created by the [`split_mut`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let mut v = [10, 40, 30, 20, 60, 50]; +/// let iter = v.split_mut(|num| *num % 3 == 0); +/// ``` +/// +/// [`split_mut`]: slice::split_mut +/// [slices]: slice +#[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct SplitMut<'a, T: 'a, P> +where + P: FnMut(&T) -> bool, +{ + v: &'a mut [T], + pred: P, + finished: bool, +} + +impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitMut<'a, T, P> { + #[inline] + pub(super) fn new(slice: &'a mut [T], pred: P) -> Self { + Self { v: slice, pred, finished: false } + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for SplitMut<'_, T, P> +where + P: FnMut(&T) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SplitMut").field("v", &self.v).field("finished", &self.finished).finish() + } +} + +impl<'a, T, P> SplitIter for SplitMut<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + #[inline] + fn finish(&mut self) -> Option<&'a mut [T]> { + if self.finished { + None + } else { + self.finished = true; + Some(mem::take(&mut self.v)) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, P> Iterator for SplitMut<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + type Item = &'a mut [T]; + + #[inline] + fn next(&mut self) -> Option<&'a mut [T]> { + if self.finished { + return None; + } + + match self.v.iter().position(|x| (self.pred)(x)) { + None => self.finish(), + Some(idx) => { + let tmp = mem::take(&mut self.v); + // idx is the index of the element we are splitting on. We want to set self to the + // region after idx, and return the subslice before and not including idx. + // So first we split after idx + let (head, tail) = tmp.split_at_mut(idx + 1); + self.v = tail; + // Then return the subslice up to but not including the found element + Some(&mut head[..idx]) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.finished { + (0, Some(0)) + } else { + // If the predicate doesn't match anything, we yield one slice. + // If it matches every element, we yield `len() + 1` empty slices. + (1, Some(self.v.len() + 1)) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + #[inline] + fn next_back(&mut self) -> Option<&'a mut [T]> { + if self.finished { + return None; + } + + let idx_opt = { + // work around borrowck limitations + let pred = &mut self.pred; + self.v.iter().rposition(|x| (*pred)(x)) + }; + match idx_opt { + None => self.finish(), + Some(idx) => { + let tmp = mem::take(&mut self.v); + let (head, tail) = tmp.split_at_mut(idx); + self.v = head; + Some(&mut tail[1..]) + } + } + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for SplitMut<'_, T, P> where P: FnMut(&T) -> bool {} + +/// An iterator over the mutable subslices of the vector which are separated +/// by elements that match `pred`. Unlike `SplitMut`, it contains the matched +/// parts in the ends of the subslices. +/// +/// This struct is created by the [`split_inclusive_mut`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let mut v = [10, 40, 30, 20, 60, 50]; +/// let iter = v.split_inclusive_mut(|num| *num % 3 == 0); +/// ``` +/// +/// [`split_inclusive_mut`]: slice::split_inclusive_mut +/// [slices]: slice +#[stable(feature = "split_inclusive", since = "1.51.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct SplitInclusiveMut<'a, T: 'a, P> +where + P: FnMut(&T) -> bool, +{ + v: &'a mut [T], + pred: P, + finished: bool, +} + +impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitInclusiveMut<'a, T, P> { + #[inline] + pub(super) fn new(slice: &'a mut [T], pred: P) -> Self { + let finished = slice.is_empty(); + Self { v: slice, pred, finished } + } +} + +#[stable(feature = "split_inclusive", since = "1.51.0")] +impl fmt::Debug for SplitInclusiveMut<'_, T, P> +where + P: FnMut(&T) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SplitInclusiveMut") + .field("v", &self.v) + .field("finished", &self.finished) + .finish() + } +} + +#[stable(feature = "split_inclusive", since = "1.51.0")] +impl<'a, T, P> Iterator for SplitInclusiveMut<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + type Item = &'a mut [T]; + + #[inline] + fn next(&mut self) -> Option<&'a mut [T]> { + if self.finished { + return None; + } + + let idx_opt = { + // work around borrowck limitations + let pred = &mut self.pred; + self.v.iter().position(|x| (*pred)(x)) + }; + let idx = idx_opt.map(|idx| idx + 1).unwrap_or(self.v.len()); + if idx == self.v.len() { + self.finished = true; + } + let tmp = mem::take(&mut self.v); + let (head, tail) = tmp.split_at_mut(idx); + self.v = tail; + Some(head) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.finished { + (0, Some(0)) + } else { + // If the predicate doesn't match anything, we yield one slice. + // If it matches every element, we yield `len()` one-element slices, + // or a single empty slice. + (1, Some(cmp::max(1, self.v.len()))) + } + } +} + +#[stable(feature = "split_inclusive", since = "1.51.0")] +impl<'a, T, P> DoubleEndedIterator for SplitInclusiveMut<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + #[inline] + fn next_back(&mut self) -> Option<&'a mut [T]> { + if self.finished { + return None; + } + + let idx_opt = if self.v.is_empty() { + None + } else { + // work around borrowck limitations + let pred = &mut self.pred; + + // The last index of self.v is already checked and found to match + // by the last iteration, so we start searching a new match + // one index to the left. + let remainder = &self.v[..(self.v.len() - 1)]; + remainder.iter().rposition(|x| (*pred)(x)) + }; + let idx = idx_opt.map(|idx| idx + 1).unwrap_or(0); + if idx == 0 { + self.finished = true; + } + let tmp = mem::take(&mut self.v); + let (head, tail) = tmp.split_at_mut(idx); + self.v = head; + Some(tail) + } +} + +#[stable(feature = "split_inclusive", since = "1.51.0")] +impl FusedIterator for SplitInclusiveMut<'_, T, P> where P: FnMut(&T) -> bool {} + +/// An iterator over subslices separated by elements that match a predicate +/// function, starting from the end of the slice. +/// +/// This struct is created by the [`rsplit`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let slice = [11, 22, 33, 0, 44, 55]; +/// let mut iter = slice.rsplit(|num| *num == 0); +/// assert_eq!(iter.next(), Some(&[44, 55][..])); +/// assert_eq!(iter.next(), Some(&[11, 22, 33][..])); +/// assert_eq!(iter.next(), None); +/// ``` +/// +/// [`rsplit`]: slice::rsplit +/// [slices]: slice +#[stable(feature = "slice_rsplit", since = "1.27.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct RSplit<'a, T: 'a, P> +where + P: FnMut(&T) -> bool, +{ + inner: Split<'a, T, P>, +} + +impl<'a, T: 'a, P: FnMut(&T) -> bool> RSplit<'a, T, P> { + #[inline] + pub(super) fn new(slice: &'a [T], pred: P) -> Self { + Self { inner: Split::new(slice, pred) } + } +} + +#[stable(feature = "slice_rsplit", since = "1.27.0")] +impl fmt::Debug for RSplit<'_, T, P> +where + P: FnMut(&T) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RSplit") + .field("v", &self.inner.v) + .field("finished", &self.inner.finished) + .finish() + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "slice_rsplit", since = "1.27.0")] +impl Clone for RSplit<'_, T, P> +where + P: Clone + FnMut(&T) -> bool, +{ + fn clone(&self) -> Self { + RSplit { inner: self.inner.clone() } + } +} + +#[stable(feature = "slice_rsplit", since = "1.27.0")] +impl<'a, T, P> Iterator for RSplit<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + type Item = &'a [T]; + + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + self.inner.next_back() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +#[stable(feature = "slice_rsplit", since = "1.27.0")] +impl<'a, T, P> DoubleEndedIterator for RSplit<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + self.inner.next() + } +} + +#[stable(feature = "slice_rsplit", since = "1.27.0")] +impl<'a, T, P> SplitIter for RSplit<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + #[inline] + fn finish(&mut self) -> Option<&'a [T]> { + self.inner.finish() + } +} + +#[stable(feature = "slice_rsplit", since = "1.27.0")] +impl FusedIterator for RSplit<'_, T, P> where P: FnMut(&T) -> bool {} + +/// An iterator over the subslices of the vector which are separated +/// by elements that match `pred`, starting from the end of the slice. +/// +/// This struct is created by the [`rsplit_mut`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let mut slice = [11, 22, 33, 0, 44, 55]; +/// let iter = slice.rsplit_mut(|num| *num == 0); +/// ``` +/// +/// [`rsplit_mut`]: slice::rsplit_mut +/// [slices]: slice +#[stable(feature = "slice_rsplit", since = "1.27.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct RSplitMut<'a, T: 'a, P> +where + P: FnMut(&T) -> bool, +{ + inner: SplitMut<'a, T, P>, +} + +impl<'a, T: 'a, P: FnMut(&T) -> bool> RSplitMut<'a, T, P> { + #[inline] + pub(super) fn new(slice: &'a mut [T], pred: P) -> Self { + Self { inner: SplitMut::new(slice, pred) } + } +} + +#[stable(feature = "slice_rsplit", since = "1.27.0")] +impl fmt::Debug for RSplitMut<'_, T, P> +where + P: FnMut(&T) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RSplitMut") + .field("v", &self.inner.v) + .field("finished", &self.inner.finished) + .finish() + } +} + +#[stable(feature = "slice_rsplit", since = "1.27.0")] +impl<'a, T, P> SplitIter for RSplitMut<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + #[inline] + fn finish(&mut self) -> Option<&'a mut [T]> { + self.inner.finish() + } +} + +#[stable(feature = "slice_rsplit", since = "1.27.0")] +impl<'a, T, P> Iterator for RSplitMut<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + type Item = &'a mut [T]; + + #[inline] + fn next(&mut self) -> Option<&'a mut [T]> { + self.inner.next_back() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +#[stable(feature = "slice_rsplit", since = "1.27.0")] +impl<'a, T, P> DoubleEndedIterator for RSplitMut<'a, T, P> +where + P: FnMut(&T) -> bool, +{ + #[inline] + fn next_back(&mut self) -> Option<&'a mut [T]> { + self.inner.next() + } +} + +#[stable(feature = "slice_rsplit", since = "1.27.0")] +impl FusedIterator for RSplitMut<'_, T, P> where P: FnMut(&T) -> bool {} + +/// An private iterator over subslices separated by elements that +/// match a predicate function, splitting at most a fixed number of +/// times. +#[derive(Debug)] +struct GenericSplitN { + iter: I, + count: usize, +} + +impl> Iterator for GenericSplitN { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + match self.count { + 0 => None, + 1 => { + self.count -= 1; + self.iter.finish() + } + _ => { + self.count -= 1; + self.iter.next() + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (lower, upper_opt) = self.iter.size_hint(); + ( + cmp::min(self.count, lower), + Some(upper_opt.map_or(self.count, |upper| cmp::min(self.count, upper))), + ) + } +} + +/// An iterator over subslices separated by elements that match a predicate +/// function, limited to a given number of splits. +/// +/// This struct is created by the [`splitn`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let slice = [10, 40, 30, 20, 60, 50]; +/// let mut iter = slice.splitn(2, |num| *num % 3 == 0); +/// assert_eq!(iter.next(), Some(&[10, 40][..])); +/// assert_eq!(iter.next(), Some(&[20, 60, 50][..])); +/// assert_eq!(iter.next(), None); +/// ``` +/// +/// [`splitn`]: slice::splitn +/// [slices]: slice +#[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct SplitN<'a, T: 'a, P> +where + P: FnMut(&T) -> bool, +{ + inner: GenericSplitN>, +} + +impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitN<'a, T, P> { + #[inline] + pub(super) fn new(s: Split<'a, T, P>, n: usize) -> Self { + Self { inner: GenericSplitN { iter: s, count: n } } + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for SplitN<'_, T, P> +where + P: FnMut(&T) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SplitN").field("inner", &self.inner).finish() + } +} + +/// An iterator over subslices separated by elements that match a +/// predicate function, limited to a given number of splits, starting +/// from the end of the slice. +/// +/// This struct is created by the [`rsplitn`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let slice = [10, 40, 30, 20, 60, 50]; +/// let mut iter = slice.rsplitn(2, |num| *num % 3 == 0); +/// assert_eq!(iter.next(), Some(&[50][..])); +/// assert_eq!(iter.next(), Some(&[10, 40, 30, 20][..])); +/// assert_eq!(iter.next(), None); +/// ``` +/// +/// [`rsplitn`]: slice::rsplitn +/// [slices]: slice +#[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct RSplitN<'a, T: 'a, P> +where + P: FnMut(&T) -> bool, +{ + inner: GenericSplitN>, +} + +impl<'a, T: 'a, P: FnMut(&T) -> bool> RSplitN<'a, T, P> { + #[inline] + pub(super) fn new(s: RSplit<'a, T, P>, n: usize) -> Self { + Self { inner: GenericSplitN { iter: s, count: n } } + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for RSplitN<'_, T, P> +where + P: FnMut(&T) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RSplitN").field("inner", &self.inner).finish() + } +} + +/// An iterator over subslices separated by elements that match a predicate +/// function, limited to a given number of splits. +/// +/// This struct is created by the [`splitn_mut`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let mut slice = [10, 40, 30, 20, 60, 50]; +/// let iter = slice.splitn_mut(2, |num| *num % 3 == 0); +/// ``` +/// +/// [`splitn_mut`]: slice::splitn_mut +/// [slices]: slice +#[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct SplitNMut<'a, T: 'a, P> +where + P: FnMut(&T) -> bool, +{ + inner: GenericSplitN>, +} + +impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitNMut<'a, T, P> { + #[inline] + pub(super) fn new(s: SplitMut<'a, T, P>, n: usize) -> Self { + Self { inner: GenericSplitN { iter: s, count: n } } + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for SplitNMut<'_, T, P> +where + P: FnMut(&T) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SplitNMut").field("inner", &self.inner).finish() + } +} + +/// An iterator over subslices separated by elements that match a +/// predicate function, limited to a given number of splits, starting +/// from the end of the slice. +/// +/// This struct is created by the [`rsplitn_mut`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let mut slice = [10, 40, 30, 20, 60, 50]; +/// let iter = slice.rsplitn_mut(2, |num| *num % 3 == 0); +/// ``` +/// +/// [`rsplitn_mut`]: slice::rsplitn_mut +/// [slices]: slice +#[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct RSplitNMut<'a, T: 'a, P> +where + P: FnMut(&T) -> bool, +{ + inner: GenericSplitN>, +} + +impl<'a, T: 'a, P: FnMut(&T) -> bool> RSplitNMut<'a, T, P> { + #[inline] + pub(super) fn new(s: RSplitMut<'a, T, P>, n: usize) -> Self { + Self { inner: GenericSplitN { iter: s, count: n } } + } +} + +#[stable(feature = "core_impl_debug", since = "1.9.0")] +impl fmt::Debug for RSplitNMut<'_, T, P> +where + P: FnMut(&T) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RSplitNMut").field("inner", &self.inner).finish() + } +} + +forward_iterator! { SplitN: T, &'a [T] } +forward_iterator! { RSplitN: T, &'a [T] } +forward_iterator! { SplitNMut: T, &'a mut [T] } +forward_iterator! { RSplitNMut: T, &'a mut [T] } + +/// An iterator over overlapping subslices of length `size`. +/// +/// This struct is created by the [`windows`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let slice = ['r', 'u', 's', 't']; +/// let mut iter = slice.windows(2); +/// assert_eq!(iter.next(), Some(&['r', 'u'][..])); +/// assert_eq!(iter.next(), Some(&['u', 's'][..])); +/// assert_eq!(iter.next(), Some(&['s', 't'][..])); +/// assert_eq!(iter.next(), None); +/// ``` +/// +/// [`windows`]: slice::windows +/// [slices]: slice +#[derive(Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct Windows<'a, T: 'a> { + v: &'a [T], + size: NonZero, +} + +impl<'a, T: 'a> Windows<'a, T> { + #[inline] + pub(super) fn new(slice: &'a [T], size: NonZero) -> Self { + Self { v: slice, size } + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Windows<'_, T> { + fn clone(&self) -> Self { + Windows { v: self.v, size: self.size } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for Windows<'a, T> { + type Item = &'a [T]; + + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + if self.size.get() > self.v.len() { + None + } else { + let ret = Some(&self.v[..self.size.get()]); + self.v = &self.v[1..]; + ret + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.size.get() > self.v.len() { + (0, Some(0)) + } else { + let size = self.v.len() - self.size.get() + 1; + (size, Some(size)) + } + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.size.get().overflowing_add(n); + if end > self.v.len() || overflow { + self.v = &[]; + None + } else { + let nth = &self.v[n..end]; + self.v = &self.v[n + 1..]; + Some(nth) + } + } + + #[inline] + fn last(self) -> Option { + if self.size.get() > self.v.len() { + None + } else { + let start = self.v.len() - self.size.get(); + Some(&self.v[start..]) + } + } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + // SAFETY: since the caller guarantees that `i` is in bounds, + // which means that `i` cannot overflow an `isize`, and the + // slice created by `from_raw_parts` is a subslice of `self.v` + // thus is guaranteed to be valid for the lifetime `'a` of `self.v`. + unsafe { from_raw_parts(self.v.as_ptr().add(idx), self.size.get()) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for Windows<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + if self.size.get() > self.v.len() { + None + } else { + let ret = Some(&self.v[self.v.len() - self.size.get()..]); + self.v = &self.v[..self.v.len() - 1]; + ret + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.v.len().overflowing_sub(n); + if end < self.size.get() || overflow { + self.v = &[]; + None + } else { + let ret = &self.v[end - self.size.get()..end]; + self.v = &self.v[..end - 1]; + Some(ret) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Windows<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Windows<'_, T> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Windows<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccess for Windows<'a, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccessNoCoerce for Windows<'a, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a +/// time), starting at the beginning of the slice. +/// +/// When the slice len is not evenly divided by the chunk size, the last slice +/// of the iteration will be the remainder. +/// +/// This struct is created by the [`chunks`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let slice = ['l', 'o', 'r', 'e', 'm']; +/// let mut iter = slice.chunks(2); +/// assert_eq!(iter.next(), Some(&['l', 'o'][..])); +/// assert_eq!(iter.next(), Some(&['r', 'e'][..])); +/// assert_eq!(iter.next(), Some(&['m'][..])); +/// assert_eq!(iter.next(), None); +/// ``` +/// +/// [`chunks`]: slice::chunks +/// [slices]: slice +#[derive(Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct Chunks<'a, T: 'a> { + v: &'a [T], + chunk_size: usize, +} + +impl<'a, T: 'a> Chunks<'a, T> { + #[inline] + pub(super) fn new(slice: &'a [T], size: usize) -> Self { + Self { v: slice, chunk_size: size } + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Chunks<'_, T> { + fn clone(&self) -> Self { + Chunks { v: self.v, chunk_size: self.chunk_size } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for Chunks<'a, T> { + type Item = &'a [T]; + + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + if self.v.is_empty() { + None + } else { + let chunksz = cmp::min(self.v.len(), self.chunk_size); + let (fst, snd) = self.v.split_at(chunksz); + self.v = snd; + Some(fst) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.v.is_empty() { + (0, Some(0)) + } else { + let n = self.v.len() / self.chunk_size; + let rem = self.v.len() % self.chunk_size; + let n = if rem > 0 { n + 1 } else { n }; + (n, Some(n)) + } + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + let (start, overflow) = n.overflowing_mul(self.chunk_size); + if start >= self.v.len() || overflow { + self.v = &[]; + None + } else { + let end = match start.checked_add(self.chunk_size) { + Some(sum) => cmp::min(self.v.len(), sum), + None => self.v.len(), + }; + let nth = &self.v[start..end]; + self.v = &self.v[end..]; + Some(nth) + } + } + + #[inline] + fn last(self) -> Option { + if self.v.is_empty() { + None + } else { + let start = (self.v.len() - 1) / self.chunk_size * self.chunk_size; + Some(&self.v[start..]) + } + } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + let start = idx * self.chunk_size; + // SAFETY: the caller guarantees that `i` is in bounds, + // which means that `start` must be in bounds of the + // underlying `self.v` slice, and we made sure that `len` + // is also in bounds of `self.v`. Thus, `start` cannot overflow + // an `isize`, and the slice constructed by `from_raw_parts` + // is a subslice of `self.v` which is guaranteed to be valid + // for the lifetime `'a` of `self.v`. + unsafe { + let len = cmp::min(self.v.len().unchecked_sub(start), self.chunk_size); + from_raw_parts(self.v.as_ptr().add(start), len) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + if self.v.is_empty() { + None + } else { + let remainder = self.v.len() % self.chunk_size; + let chunksz = if remainder != 0 { remainder } else { self.chunk_size }; + // SAFETY: split_at_unchecked requires the argument be less than or + // equal to the length. This is guaranteed, but subtle: `chunksz` + // will always either be `self.v.len() % self.chunk_size`, which + // will always evaluate to strictly less than `self.v.len()` (or + // panic, in the case that `self.chunk_size` is zero), or it can be + // `self.chunk_size`, in the case that the length is exactly + // divisible by the chunk size. + // + // While it seems like using `self.chunk_size` in this case could + // lead to a value greater than `self.v.len()`, it cannot: if + // `self.chunk_size` were greater than `self.v.len()`, then + // `self.v.len() % self.chunk_size` would return nonzero (note that + // in this branch of the `if`, we already know that `self.v` is + // non-empty). + let (fst, snd) = unsafe { self.v.split_at_unchecked(self.v.len() - chunksz) }; + self.v = fst; + Some(snd) + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &[]; + None + } else { + let start = (len - 1 - n) * self.chunk_size; + let end = match start.checked_add(self.chunk_size) { + Some(res) => cmp::min(self.v.len(), res), + None => self.v.len(), + }; + let nth_back = &self.v[start..end]; + self.v = &self.v[..start]; + Some(nth_back) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Chunks<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Chunks<'_, T> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Chunks<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccess for Chunks<'a, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccessNoCoerce for Chunks<'a, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +/// An iterator over a slice in (non-overlapping) mutable chunks (`chunk_size` +/// elements at a time), starting at the beginning of the slice. +/// +/// When the slice len is not evenly divided by the chunk size, the last slice +/// of the iteration will be the remainder. +/// +/// This struct is created by the [`chunks_mut`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let mut slice = ['l', 'o', 'r', 'e', 'm']; +/// let iter = slice.chunks_mut(2); +/// ``` +/// +/// [`chunks_mut`]: slice::chunks_mut +/// [slices]: slice +#[derive(Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct ChunksMut<'a, T: 'a> { + /// # Safety + /// This slice pointer must point at a valid region of `T` with at least length `v.len()`. Normally, + /// those requirements would mean that we could instead use a `&mut [T]` here, but we cannot + /// because `__iterator_get_unchecked` needs to return `&mut [T]`, which guarantees certain aliasing + /// properties that we cannot uphold if we hold on to the full original `&mut [T]`. Wrapping a raw + /// slice instead lets us hand out non-overlapping `&mut [T]` subslices of the slice we wrap. + v: *mut [T], + chunk_size: usize, + _marker: PhantomData<&'a mut T>, +} + +impl<'a, T: 'a> ChunksMut<'a, T> { + #[inline] + pub(super) fn new(slice: &'a mut [T], size: usize) -> Self { + Self { v: slice, chunk_size: size, _marker: PhantomData } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for ChunksMut<'a, T> { + type Item = &'a mut [T]; + + #[inline] + fn next(&mut self) -> Option<&'a mut [T]> { + if self.v.is_empty() { + None + } else { + let sz = cmp::min(self.v.len(), self.chunk_size); + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (head, tail) = unsafe { self.v.split_at_mut(sz) }; + self.v = tail; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *head }) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.v.is_empty() { + (0, Some(0)) + } else { + let n = self.v.len() / self.chunk_size; + let rem = self.v.len() % self.chunk_size; + let n = if rem > 0 { n + 1 } else { n }; + (n, Some(n)) + } + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option<&'a mut [T]> { + let (start, overflow) = n.overflowing_mul(self.chunk_size); + if start >= self.v.len() || overflow { + self.v = &mut []; + None + } else { + let end = match start.checked_add(self.chunk_size) { + Some(sum) => cmp::min(self.v.len(), sum), + None => self.v.len(), + }; + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (head, tail) = unsafe { self.v.split_at_mut(end) }; + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (_, nth) = unsafe { head.split_at_mut(start) }; + self.v = tail; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *nth }) + } + } + + #[inline] + fn last(self) -> Option { + if self.v.is_empty() { + None + } else { + let start = (self.v.len() - 1) / self.chunk_size * self.chunk_size; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *self.v.get_unchecked_mut(start..) }) + } + } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + let start = idx * self.chunk_size; + // SAFETY: see comments for `Chunks::__iterator_get_unchecked` and `self.v`. + // + // Also note that the caller also guarantees that we're never called + // with the same index again, and that no other methods that will + // access this subslice are called, so it is valid for the returned + // slice to be mutable. + unsafe { + let len = cmp::min(self.v.len().unchecked_sub(start), self.chunk_size); + from_raw_parts_mut(self.v.as_mut_ptr().add(start), len) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a mut [T]> { + if self.v.is_empty() { + None + } else { + let remainder = self.v.len() % self.chunk_size; + let sz = if remainder != 0 { remainder } else { self.chunk_size }; + let len = self.v.len(); + // SAFETY: Similar to `Chunks::next_back` + let (head, tail) = unsafe { self.v.split_at_mut_unchecked(len - sz) }; + self.v = head; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *tail }) + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &mut []; + None + } else { + let start = (len - 1 - n) * self.chunk_size; + let end = match start.checked_add(self.chunk_size) { + Some(res) => cmp::min(self.v.len(), res), + None => self.v.len(), + }; + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (temp, _tail) = unsafe { self.v.split_at_mut(end) }; + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (head, nth_back) = unsafe { temp.split_at_mut(start) }; + self.v = head; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *nth_back }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for ChunksMut<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ChunksMut<'_, T> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for ChunksMut<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccessNoCoerce for ChunksMut<'a, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for ChunksMut<'_, T> where T: Send {} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for ChunksMut<'_, T> where T: Sync {} + +/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a +/// time), starting at the beginning of the slice. +/// +/// When the slice len is not evenly divided by the chunk size, the last +/// up to `chunk_size-1` elements will be omitted but can be retrieved from +/// the [`remainder`] function from the iterator. +/// +/// This struct is created by the [`chunks_exact`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let slice = ['l', 'o', 'r', 'e', 'm']; +/// let mut iter = slice.chunks_exact(2); +/// assert_eq!(iter.next(), Some(&['l', 'o'][..])); +/// assert_eq!(iter.next(), Some(&['r', 'e'][..])); +/// assert_eq!(iter.next(), None); +/// ``` +/// +/// [`chunks_exact`]: slice::chunks_exact +/// [`remainder`]: ChunksExact::remainder +/// [slices]: slice +#[derive(Debug)] +#[stable(feature = "chunks_exact", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct ChunksExact<'a, T: 'a> { + v: &'a [T], + rem: &'a [T], + chunk_size: usize, +} + +impl<'a, T> ChunksExact<'a, T> { + #[inline] + pub(super) fn new(slice: &'a [T], chunk_size: usize) -> Self { + let rem = slice.len() % chunk_size; + let fst_len = slice.len() - rem; + // SAFETY: 0 <= fst_len <= slice.len() by construction above + let (fst, snd) = unsafe { slice.split_at_unchecked(fst_len) }; + Self { v: fst, rem: snd, chunk_size } + } + + /// Returns the remainder of the original slice that is not going to be + /// returned by the iterator. The returned slice has at most `chunk_size-1` + /// elements. + /// + /// # Example + /// + /// ``` + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.chunks_exact(2); + /// assert_eq!(iter.remainder(), &['m'][..]); + /// assert_eq!(iter.next(), Some(&['l', 'o'][..])); + /// assert_eq!(iter.remainder(), &['m'][..]); + /// assert_eq!(iter.next(), Some(&['r', 'e'][..])); + /// assert_eq!(iter.remainder(), &['m'][..]); + /// assert_eq!(iter.next(), None); + /// assert_eq!(iter.remainder(), &['m'][..]); + /// ``` + #[must_use] + #[stable(feature = "chunks_exact", since = "1.31.0")] + pub fn remainder(&self) -> &'a [T] { + self.rem + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "chunks_exact", since = "1.31.0")] +impl Clone for ChunksExact<'_, T> { + fn clone(&self) -> Self { + ChunksExact { v: self.v, rem: self.rem, chunk_size: self.chunk_size } + } +} + +#[stable(feature = "chunks_exact", since = "1.31.0")] +impl<'a, T> Iterator for ChunksExact<'a, T> { + type Item = &'a [T]; + + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + if self.v.len() < self.chunk_size { + None + } else { + let (fst, snd) = self.v.split_at(self.chunk_size); + self.v = snd; + Some(fst) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let n = self.v.len() / self.chunk_size; + (n, Some(n)) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + let (start, overflow) = n.overflowing_mul(self.chunk_size); + if start >= self.v.len() || overflow { + self.v = &[]; + None + } else { + let (_, snd) = self.v.split_at(start); + self.v = snd; + self.next() + } + } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + let start = idx * self.chunk_size; + // SAFETY: mostly identical to `Chunks::__iterator_get_unchecked`. + unsafe { from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) } + } +} + +#[stable(feature = "chunks_exact", since = "1.31.0")] +impl<'a, T> DoubleEndedIterator for ChunksExact<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + if self.v.len() < self.chunk_size { + None + } else { + let (fst, snd) = self.v.split_at(self.v.len() - self.chunk_size); + self.v = fst; + Some(snd) + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &[]; + None + } else { + let start = (len - 1 - n) * self.chunk_size; + let end = start + self.chunk_size; + let nth_back = &self.v[start..end]; + self.v = &self.v[..start]; + Some(nth_back) + } + } +} + +#[stable(feature = "chunks_exact", since = "1.31.0")] +impl ExactSizeIterator for ChunksExact<'_, T> { + fn is_empty(&self) -> bool { + self.v.is_empty() + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ChunksExact<'_, T> {} + +#[stable(feature = "chunks_exact", since = "1.31.0")] +impl FusedIterator for ChunksExact<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccess for ChunksExact<'a, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccessNoCoerce for ChunksExact<'a, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +/// An iterator over a slice in (non-overlapping) mutable chunks (`chunk_size` +/// elements at a time), starting at the beginning of the slice. +/// +/// When the slice len is not evenly divided by the chunk size, the last up to +/// `chunk_size-1` elements will be omitted but can be retrieved from the +/// [`into_remainder`] function from the iterator. +/// +/// This struct is created by the [`chunks_exact_mut`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let mut slice = ['l', 'o', 'r', 'e', 'm']; +/// let iter = slice.chunks_exact_mut(2); +/// ``` +/// +/// [`chunks_exact_mut`]: slice::chunks_exact_mut +/// [`into_remainder`]: ChunksExactMut::into_remainder +/// [slices]: slice +#[derive(Debug)] +#[stable(feature = "chunks_exact", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct ChunksExactMut<'a, T: 'a> { + /// # Safety + /// This slice pointer must point at a valid region of `T` with at least length `v.len()`. Normally, + /// those requirements would mean that we could instead use a `&mut [T]` here, but we cannot + /// because `__iterator_get_unchecked` needs to return `&mut [T]`, which guarantees certain aliasing + /// properties that we cannot uphold if we hold on to the full original `&mut [T]`. Wrapping a raw + /// slice instead lets us hand out non-overlapping `&mut [T]` subslices of the slice we wrap. + v: *mut [T], + rem: &'a mut [T], // The iterator never yields from here, so this can be unique + chunk_size: usize, + _marker: PhantomData<&'a mut T>, +} + +impl<'a, T> ChunksExactMut<'a, T> { + #[inline] + pub(super) fn new(slice: &'a mut [T], chunk_size: usize) -> Self { + let rem = slice.len() % chunk_size; + let fst_len = slice.len() - rem; + // SAFETY: 0 <= fst_len <= slice.len() by construction above + let (fst, snd) = unsafe { slice.split_at_mut_unchecked(fst_len) }; + Self { v: fst, rem: snd, chunk_size, _marker: PhantomData } + } + + /// Returns the remainder of the original slice that is not going to be + /// returned by the iterator. The returned slice has at most `chunk_size-1` + /// elements. + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "chunks_exact", since = "1.31.0")] + pub fn into_remainder(self) -> &'a mut [T] { + self.rem + } +} + +#[stable(feature = "chunks_exact", since = "1.31.0")] +impl<'a, T> Iterator for ChunksExactMut<'a, T> { + type Item = &'a mut [T]; + + #[inline] + fn next(&mut self) -> Option<&'a mut [T]> { + if self.v.len() < self.chunk_size { + None + } else { + // SAFETY: self.chunk_size is inbounds because we compared above against self.v.len() + let (head, tail) = unsafe { self.v.split_at_mut(self.chunk_size) }; + self.v = tail; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *head }) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let n = self.v.len() / self.chunk_size; + (n, Some(n)) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option<&'a mut [T]> { + let (start, overflow) = n.overflowing_mul(self.chunk_size); + if start >= self.v.len() || overflow { + self.v = &mut []; + None + } else { + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (_, snd) = unsafe { self.v.split_at_mut(start) }; + self.v = snd; + self.next() + } + } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + let start = idx * self.chunk_size; + // SAFETY: see comments for `Chunks::__iterator_get_unchecked` and `self.v`. + unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) } + } +} + +#[stable(feature = "chunks_exact", since = "1.31.0")] +impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a mut [T]> { + if self.v.len() < self.chunk_size { + None + } else { + // SAFETY: This subtraction is inbounds because of the check above + let (head, tail) = unsafe { self.v.split_at_mut(self.v.len() - self.chunk_size) }; + self.v = head; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *tail }) + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &mut []; + None + } else { + let start = (len - 1 - n) * self.chunk_size; + let end = start + self.chunk_size; + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (temp, _tail) = unsafe { mem::replace(&mut self.v, &mut []).split_at_mut(end) }; + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (head, nth_back) = unsafe { temp.split_at_mut(start) }; + self.v = head; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *nth_back }) + } + } +} + +#[stable(feature = "chunks_exact", since = "1.31.0")] +impl ExactSizeIterator for ChunksExactMut<'_, T> { + fn is_empty(&self) -> bool { + self.v.is_empty() + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ChunksExactMut<'_, T> {} + +#[stable(feature = "chunks_exact", since = "1.31.0")] +impl FusedIterator for ChunksExactMut<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccessNoCoerce for ChunksExactMut<'a, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +#[stable(feature = "chunks_exact", since = "1.31.0")] +unsafe impl Send for ChunksExactMut<'_, T> where T: Send {} + +#[stable(feature = "chunks_exact", since = "1.31.0")] +unsafe impl Sync for ChunksExactMut<'_, T> where T: Sync {} + +/// A windowed iterator over a slice in overlapping chunks (`N` elements at a +/// time), starting at the beginning of the slice +/// +/// This struct is created by the [`array_windows`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// #![feature(array_windows)] +/// +/// let slice = [0, 1, 2, 3]; +/// let mut iter = slice.array_windows::<2>(); +/// assert_eq!(iter.next(), Some(&[0, 1])); +/// assert_eq!(iter.next(), Some(&[1, 2])); +/// assert_eq!(iter.next(), Some(&[2, 3])); +/// assert_eq!(iter.next(), None); +/// ``` +/// +/// [`array_windows`]: slice::array_windows +/// [slices]: slice +#[derive(Debug, Clone, Copy)] +#[unstable(feature = "array_windows", issue = "75027")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct ArrayWindows<'a, T: 'a, const N: usize> { + slice_head: *const T, + num: usize, + marker: PhantomData<&'a [T; N]>, +} + +impl<'a, T: 'a, const N: usize> ArrayWindows<'a, T, N> { + #[inline] + pub(super) fn new(slice: &'a [T]) -> Self { + let num_windows = slice.len().saturating_sub(N - 1); + Self { slice_head: slice.as_ptr(), num: num_windows, marker: PhantomData } + } +} + +#[unstable(feature = "array_windows", issue = "75027")] +impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> { + type Item = &'a [T; N]; + + #[inline] + fn next(&mut self) -> Option { + if self.num == 0 { + return None; + } + // SAFETY: + // This is safe because it's indexing into a slice guaranteed to be length > N. + let ret = unsafe { &*self.slice_head.cast::<[T; N]>() }; + // SAFETY: Guaranteed that there are at least 1 item remaining otherwise + // earlier branch would've been hit + self.slice_head = unsafe { self.slice_head.add(1) }; + + self.num -= 1; + Some(ret) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (self.num, Some(self.num)) + } + + #[inline] + fn count(self) -> usize { + self.num + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + if self.num <= n { + self.num = 0; + return None; + } + // SAFETY: + // This is safe because it's indexing into a slice guaranteed to be length > N. + let ret = unsafe { &*self.slice_head.add(n).cast::<[T; N]>() }; + // SAFETY: Guaranteed that there are at least n items remaining + self.slice_head = unsafe { self.slice_head.add(n + 1) }; + + self.num -= n + 1; + Some(ret) + } + + #[inline] + fn last(mut self) -> Option { + self.nth(self.num.checked_sub(1)?) + } +} + +#[unstable(feature = "array_windows", issue = "75027")] +impl<'a, T, const N: usize> DoubleEndedIterator for ArrayWindows<'a, T, N> { + #[inline] + fn next_back(&mut self) -> Option<&'a [T; N]> { + if self.num == 0 { + return None; + } + // SAFETY: Guaranteed that there are n items remaining, n-1 for 0-indexing. + let ret = unsafe { &*self.slice_head.add(self.num - 1).cast::<[T; N]>() }; + self.num -= 1; + Some(ret) + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option<&'a [T; N]> { + if self.num <= n { + self.num = 0; + return None; + } + // SAFETY: Guaranteed that there are n items remaining, n-1 for 0-indexing. + let ret = unsafe { &*self.slice_head.add(self.num - (n + 1)).cast::<[T; N]>() }; + self.num -= n + 1; + Some(ret) + } +} + +#[unstable(feature = "array_windows", issue = "75027")] +impl ExactSizeIterator for ArrayWindows<'_, T, N> { + fn is_empty(&self) -> bool { + self.num == 0 + } +} + +/// An iterator over a slice in (non-overlapping) chunks (`N` elements at a +/// time), starting at the beginning of the slice. +/// +/// When the slice len is not evenly divided by the chunk size, the last +/// up to `N-1` elements will be omitted but can be retrieved from +/// the [`remainder`] function from the iterator. +/// +/// This struct is created by the [`array_chunks`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// #![feature(array_chunks)] +/// +/// let slice = ['l', 'o', 'r', 'e', 'm']; +/// let mut iter = slice.array_chunks::<2>(); +/// assert_eq!(iter.next(), Some(&['l', 'o'])); +/// assert_eq!(iter.next(), Some(&['r', 'e'])); +/// assert_eq!(iter.next(), None); +/// ``` +/// +/// [`array_chunks`]: slice::array_chunks +/// [`remainder`]: ArrayChunks::remainder +/// [slices]: slice +#[derive(Debug)] +#[unstable(feature = "array_chunks", issue = "74985")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct ArrayChunks<'a, T: 'a, const N: usize> { + iter: Iter<'a, [T; N]>, + rem: &'a [T], +} + +impl<'a, T, const N: usize> ArrayChunks<'a, T, N> { + #[inline] + pub(super) fn new(slice: &'a [T]) -> Self { + let (array_slice, rem) = slice.as_chunks(); + Self { iter: array_slice.iter(), rem } + } + + /// Returns the remainder of the original slice that is not going to be + /// returned by the iterator. The returned slice has at most `N-1` + /// elements. + #[must_use] + #[unstable(feature = "array_chunks", issue = "74985")] + pub fn remainder(&self) -> &'a [T] { + self.rem + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[unstable(feature = "array_chunks", issue = "74985")] +impl Clone for ArrayChunks<'_, T, N> { + fn clone(&self) -> Self { + ArrayChunks { iter: self.iter.clone(), rem: self.rem } + } +} + +#[unstable(feature = "array_chunks", issue = "74985")] +impl<'a, T, const N: usize> Iterator for ArrayChunks<'a, T, N> { + type Item = &'a [T; N]; + + #[inline] + fn next(&mut self) -> Option<&'a [T; N]> { + self.iter.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + #[inline] + fn count(self) -> usize { + self.iter.count() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.iter.nth(n) + } + + #[inline] + fn last(self) -> Option { + self.iter.last() + } + + unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> &'a [T; N] { + // SAFETY: The safety guarantees of `__iterator_get_unchecked` are + // transferred to the caller. + unsafe { self.iter.__iterator_get_unchecked(i) } + } +} + +#[unstable(feature = "array_chunks", issue = "74985")] +impl<'a, T, const N: usize> DoubleEndedIterator for ArrayChunks<'a, T, N> { + #[inline] + fn next_back(&mut self) -> Option<&'a [T; N]> { + self.iter.next_back() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.iter.nth_back(n) + } +} + +#[unstable(feature = "array_chunks", issue = "74985")] +impl ExactSizeIterator for ArrayChunks<'_, T, N> { + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ArrayChunks<'_, T, N> {} + +#[unstable(feature = "array_chunks", issue = "74985")] +impl FusedIterator for ArrayChunks<'_, T, N> {} + +#[doc(hidden)] +#[unstable(feature = "array_chunks", issue = "74985")] +unsafe impl<'a, T, const N: usize> TrustedRandomAccess for ArrayChunks<'a, T, N> {} + +#[doc(hidden)] +#[unstable(feature = "array_chunks", issue = "74985")] +unsafe impl<'a, T, const N: usize> TrustedRandomAccessNoCoerce for ArrayChunks<'a, T, N> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +/// An iterator over a slice in (non-overlapping) mutable chunks (`N` elements +/// at a time), starting at the beginning of the slice. +/// +/// When the slice len is not evenly divided by the chunk size, the last +/// up to `N-1` elements will be omitted but can be retrieved from +/// the [`into_remainder`] function from the iterator. +/// +/// This struct is created by the [`array_chunks_mut`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// #![feature(array_chunks)] +/// +/// let mut slice = ['l', 'o', 'r', 'e', 'm']; +/// let iter = slice.array_chunks_mut::<2>(); +/// ``` +/// +/// [`array_chunks_mut`]: slice::array_chunks_mut +/// [`into_remainder`]: ../../std/slice/struct.ArrayChunksMut.html#method.into_remainder +/// [slices]: slice +#[derive(Debug)] +#[unstable(feature = "array_chunks", issue = "74985")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct ArrayChunksMut<'a, T: 'a, const N: usize> { + iter: IterMut<'a, [T; N]>, + rem: &'a mut [T], +} + +impl<'a, T, const N: usize> ArrayChunksMut<'a, T, N> { + #[inline] + pub(super) fn new(slice: &'a mut [T]) -> Self { + let (array_slice, rem) = slice.as_chunks_mut(); + Self { iter: array_slice.iter_mut(), rem } + } + + /// Returns the remainder of the original slice that is not going to be + /// returned by the iterator. The returned slice has at most `N-1` + /// elements. + #[must_use = "`self` will be dropped if the result is not used"] + #[unstable(feature = "array_chunks", issue = "74985")] + pub fn into_remainder(self) -> &'a mut [T] { + self.rem + } +} + +#[unstable(feature = "array_chunks", issue = "74985")] +impl<'a, T, const N: usize> Iterator for ArrayChunksMut<'a, T, N> { + type Item = &'a mut [T; N]; + + #[inline] + fn next(&mut self) -> Option<&'a mut [T; N]> { + self.iter.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + #[inline] + fn count(self) -> usize { + self.iter.count() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.iter.nth(n) + } + + #[inline] + fn last(self) -> Option { + self.iter.last() + } + + unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> &'a mut [T; N] { + // SAFETY: The safety guarantees of `__iterator_get_unchecked` are transferred to + // the caller. + unsafe { self.iter.__iterator_get_unchecked(i) } + } +} + +#[unstable(feature = "array_chunks", issue = "74985")] +impl<'a, T, const N: usize> DoubleEndedIterator for ArrayChunksMut<'a, T, N> { + #[inline] + fn next_back(&mut self) -> Option<&'a mut [T; N]> { + self.iter.next_back() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.iter.nth_back(n) + } +} + +#[unstable(feature = "array_chunks", issue = "74985")] +impl ExactSizeIterator for ArrayChunksMut<'_, T, N> { + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ArrayChunksMut<'_, T, N> {} + +#[unstable(feature = "array_chunks", issue = "74985")] +impl FusedIterator for ArrayChunksMut<'_, T, N> {} + +#[doc(hidden)] +#[unstable(feature = "array_chunks", issue = "74985")] +unsafe impl<'a, T, const N: usize> TrustedRandomAccess for ArrayChunksMut<'a, T, N> {} + +#[doc(hidden)] +#[unstable(feature = "array_chunks", issue = "74985")] +unsafe impl<'a, T, const N: usize> TrustedRandomAccessNoCoerce for ArrayChunksMut<'a, T, N> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a +/// time), starting at the end of the slice. +/// +/// When the slice len is not evenly divided by the chunk size, the last slice +/// of the iteration will be the remainder. +/// +/// This struct is created by the [`rchunks`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let slice = ['l', 'o', 'r', 'e', 'm']; +/// let mut iter = slice.rchunks(2); +/// assert_eq!(iter.next(), Some(&['e', 'm'][..])); +/// assert_eq!(iter.next(), Some(&['o', 'r'][..])); +/// assert_eq!(iter.next(), Some(&['l'][..])); +/// assert_eq!(iter.next(), None); +/// ``` +/// +/// [`rchunks`]: slice::rchunks +/// [slices]: slice +#[derive(Debug)] +#[stable(feature = "rchunks", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct RChunks<'a, T: 'a> { + v: &'a [T], + chunk_size: usize, +} + +impl<'a, T: 'a> RChunks<'a, T> { + #[inline] + pub(super) fn new(slice: &'a [T], size: usize) -> Self { + Self { v: slice, chunk_size: size } + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "rchunks", since = "1.31.0")] +impl Clone for RChunks<'_, T> { + fn clone(&self) -> Self { + RChunks { v: self.v, chunk_size: self.chunk_size } + } +} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl<'a, T> Iterator for RChunks<'a, T> { + type Item = &'a [T]; + + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + if self.v.is_empty() { + None + } else { + let len = self.v.len(); + let chunksz = cmp::min(len, self.chunk_size); + // SAFETY: split_at_unchecked just requires the argument be less + // than the length. This could only happen if the expression `len - + // chunksz` overflows. This could only happen if `chunksz > len`, + // which is impossible as we initialize it as the `min` of `len` and + // `self.chunk_size`. + let (fst, snd) = unsafe { self.v.split_at_unchecked(len - chunksz) }; + self.v = fst; + Some(snd) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.v.is_empty() { + (0, Some(0)) + } else { + let n = self.v.len() / self.chunk_size; + let rem = self.v.len() % self.chunk_size; + let n = if rem > 0 { n + 1 } else { n }; + (n, Some(n)) + } + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = n.overflowing_mul(self.chunk_size); + if end >= self.v.len() || overflow { + self.v = &[]; + None + } else { + // Can't underflow because of the check above + let end = self.v.len() - end; + let start = match end.checked_sub(self.chunk_size) { + Some(sum) => sum, + None => 0, + }; + let nth = &self.v[start..end]; + self.v = &self.v[0..start]; + Some(nth) + } + } + + #[inline] + fn last(self) -> Option { + if self.v.is_empty() { + None + } else { + let rem = self.v.len() % self.chunk_size; + let end = if rem == 0 { self.chunk_size } else { rem }; + Some(&self.v[0..end]) + } + } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + let end = self.v.len() - idx * self.chunk_size; + let start = match end.checked_sub(self.chunk_size) { + None => 0, + Some(start) => start, + }; + // SAFETY: mostly identical to `Chunks::__iterator_get_unchecked`. + unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) } + } +} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl<'a, T> DoubleEndedIterator for RChunks<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + if self.v.is_empty() { + None + } else { + let remainder = self.v.len() % self.chunk_size; + let chunksz = if remainder != 0 { remainder } else { self.chunk_size }; + // SAFETY: similar to Chunks::next_back + let (fst, snd) = unsafe { self.v.split_at_unchecked(chunksz) }; + self.v = snd; + Some(fst) + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &[]; + None + } else { + // can't underflow because `n < len` + let offset_from_end = (len - 1 - n) * self.chunk_size; + let end = self.v.len() - offset_from_end; + let start = end.saturating_sub(self.chunk_size); + let nth_back = &self.v[start..end]; + self.v = &self.v[end..]; + Some(nth_back) + } + } +} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl ExactSizeIterator for RChunks<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for RChunks<'_, T> {} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl FusedIterator for RChunks<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccess for RChunks<'a, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunks<'a, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +/// An iterator over a slice in (non-overlapping) mutable chunks (`chunk_size` +/// elements at a time), starting at the end of the slice. +/// +/// When the slice len is not evenly divided by the chunk size, the last slice +/// of the iteration will be the remainder. +/// +/// This struct is created by the [`rchunks_mut`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let mut slice = ['l', 'o', 'r', 'e', 'm']; +/// let iter = slice.rchunks_mut(2); +/// ``` +/// +/// [`rchunks_mut`]: slice::rchunks_mut +/// [slices]: slice +#[derive(Debug)] +#[stable(feature = "rchunks", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct RChunksMut<'a, T: 'a> { + /// # Safety + /// This slice pointer must point at a valid region of `T` with at least length `v.len()`. Normally, + /// those requirements would mean that we could instead use a `&mut [T]` here, but we cannot + /// because `__iterator_get_unchecked` needs to return `&mut [T]`, which guarantees certain aliasing + /// properties that we cannot uphold if we hold on to the full original `&mut [T]`. Wrapping a raw + /// slice instead lets us hand out non-overlapping `&mut [T]` subslices of the slice we wrap. + v: *mut [T], + chunk_size: usize, + _marker: PhantomData<&'a mut T>, +} + +impl<'a, T: 'a> RChunksMut<'a, T> { + #[inline] + pub(super) fn new(slice: &'a mut [T], size: usize) -> Self { + Self { v: slice, chunk_size: size, _marker: PhantomData } + } +} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl<'a, T> Iterator for RChunksMut<'a, T> { + type Item = &'a mut [T]; + + #[inline] + fn next(&mut self) -> Option<&'a mut [T]> { + if self.v.is_empty() { + None + } else { + let sz = cmp::min(self.v.len(), self.chunk_size); + let len = self.v.len(); + // SAFETY: split_at_mut_unchecked just requires the argument be less + // than the length. This could only happen if the expression + // `len - sz` overflows. This could only happen if `sz > + // len`, which is impossible as we initialize it as the `min` of + // `self.v.len()` (e.g. `len`) and `self.chunk_size`. + let (head, tail) = unsafe { self.v.split_at_mut_unchecked(len - sz) }; + self.v = head; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *tail }) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.v.is_empty() { + (0, Some(0)) + } else { + let n = self.v.len() / self.chunk_size; + let rem = self.v.len() % self.chunk_size; + let n = if rem > 0 { n + 1 } else { n }; + (n, Some(n)) + } + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option<&'a mut [T]> { + let (end, overflow) = n.overflowing_mul(self.chunk_size); + if end >= self.v.len() || overflow { + self.v = &mut []; + None + } else { + // Can't underflow because of the check above + let end = self.v.len() - end; + let start = match end.checked_sub(self.chunk_size) { + Some(sum) => sum, + None => 0, + }; + // SAFETY: This type ensures that self.v is a valid pointer with a correct len. + // Therefore the bounds check in split_at_mut guarantees the split point is inbounds. + let (head, tail) = unsafe { self.v.split_at_mut(start) }; + // SAFETY: This type ensures that self.v is a valid pointer with a correct len. + // Therefore the bounds check in split_at_mut guarantees the split point is inbounds. + let (nth, _) = unsafe { tail.split_at_mut(end - start) }; + self.v = head; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *nth }) + } + } + + #[inline] + fn last(self) -> Option { + if self.v.is_empty() { + None + } else { + let rem = self.v.len() % self.chunk_size; + let end = if rem == 0 { self.chunk_size } else { rem }; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *self.v.get_unchecked_mut(0..end) }) + } + } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + let end = self.v.len() - idx * self.chunk_size; + let start = match end.checked_sub(self.chunk_size) { + None => 0, + Some(start) => start, + }; + // SAFETY: see comments for `RChunks::__iterator_get_unchecked` and + // `ChunksMut::__iterator_get_unchecked`, `self.v`. + unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) } + } +} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a mut [T]> { + if self.v.is_empty() { + None + } else { + let remainder = self.v.len() % self.chunk_size; + let sz = if remainder != 0 { remainder } else { self.chunk_size }; + // SAFETY: Similar to `Chunks::next_back` + let (head, tail) = unsafe { self.v.split_at_mut_unchecked(sz) }; + self.v = tail; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *head }) + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &mut []; + None + } else { + // can't underflow because `n < len` + let offset_from_end = (len - 1 - n) * self.chunk_size; + let end = self.v.len() - offset_from_end; + let start = end.saturating_sub(self.chunk_size); + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (tmp, tail) = unsafe { self.v.split_at_mut(end) }; + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (_, nth_back) = unsafe { tmp.split_at_mut(start) }; + self.v = tail; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *nth_back }) + } + } +} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl ExactSizeIterator for RChunksMut<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for RChunksMut<'_, T> {} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl FusedIterator for RChunksMut<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccess for RChunksMut<'a, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunksMut<'a, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +#[stable(feature = "rchunks", since = "1.31.0")] +unsafe impl Send for RChunksMut<'_, T> where T: Send {} + +#[stable(feature = "rchunks", since = "1.31.0")] +unsafe impl Sync for RChunksMut<'_, T> where T: Sync {} + +/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a +/// time), starting at the end of the slice. +/// +/// When the slice len is not evenly divided by the chunk size, the last +/// up to `chunk_size-1` elements will be omitted but can be retrieved from +/// the [`remainder`] function from the iterator. +/// +/// This struct is created by the [`rchunks_exact`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let slice = ['l', 'o', 'r', 'e', 'm']; +/// let mut iter = slice.rchunks_exact(2); +/// assert_eq!(iter.next(), Some(&['e', 'm'][..])); +/// assert_eq!(iter.next(), Some(&['o', 'r'][..])); +/// assert_eq!(iter.next(), None); +/// ``` +/// +/// [`rchunks_exact`]: slice::rchunks_exact +/// [`remainder`]: RChunksExact::remainder +/// [slices]: slice +#[derive(Debug)] +#[stable(feature = "rchunks", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct RChunksExact<'a, T: 'a> { + v: &'a [T], + rem: &'a [T], + chunk_size: usize, +} + +impl<'a, T> RChunksExact<'a, T> { + #[inline] + pub(super) fn new(slice: &'a [T], chunk_size: usize) -> Self { + let rem = slice.len() % chunk_size; + // SAFETY: 0 <= rem <= slice.len() by construction above + let (fst, snd) = unsafe { slice.split_at_unchecked(rem) }; + Self { v: snd, rem: fst, chunk_size } + } + + /// Returns the remainder of the original slice that is not going to be + /// returned by the iterator. The returned slice has at most `chunk_size-1` + /// elements. + /// + /// # Example + /// + /// ``` + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.rchunks_exact(2); + /// assert_eq!(iter.remainder(), &['l'][..]); + /// assert_eq!(iter.next(), Some(&['e', 'm'][..])); + /// assert_eq!(iter.remainder(), &['l'][..]); + /// assert_eq!(iter.next(), Some(&['o', 'r'][..])); + /// assert_eq!(iter.remainder(), &['l'][..]); + /// assert_eq!(iter.next(), None); + /// assert_eq!(iter.remainder(), &['l'][..]); + /// ``` + #[must_use] + #[stable(feature = "rchunks", since = "1.31.0")] + pub fn remainder(&self) -> &'a [T] { + self.rem + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "rchunks", since = "1.31.0")] +impl<'a, T> Clone for RChunksExact<'a, T> { + fn clone(&self) -> RChunksExact<'a, T> { + RChunksExact { v: self.v, rem: self.rem, chunk_size: self.chunk_size } + } +} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl<'a, T> Iterator for RChunksExact<'a, T> { + type Item = &'a [T]; + + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + if self.v.len() < self.chunk_size { + None + } else { + let (fst, snd) = self.v.split_at(self.v.len() - self.chunk_size); + self.v = fst; + Some(snd) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let n = self.v.len() / self.chunk_size; + (n, Some(n)) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = n.overflowing_mul(self.chunk_size); + if end >= self.v.len() || overflow { + self.v = &[]; + None + } else { + let (fst, _) = self.v.split_at(self.v.len() - end); + self.v = fst; + self.next() + } + } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + let end = self.v.len() - idx * self.chunk_size; + let start = end - self.chunk_size; + // SAFETY: mostly identical to `Chunks::__iterator_get_unchecked`. + unsafe { from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) } + } +} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + if self.v.len() < self.chunk_size { + None + } else { + let (fst, snd) = self.v.split_at(self.chunk_size); + self.v = snd; + Some(fst) + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &[]; + None + } else { + // now that we know that `n` corresponds to a chunk, + // none of these operations can underflow/overflow + let offset = (len - n) * self.chunk_size; + let start = self.v.len() - offset; + let end = start + self.chunk_size; + let nth_back = &self.v[start..end]; + self.v = &self.v[end..]; + Some(nth_back) + } + } +} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl<'a, T> ExactSizeIterator for RChunksExact<'a, T> { + fn is_empty(&self) -> bool { + self.v.is_empty() + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for RChunksExact<'_, T> {} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl FusedIterator for RChunksExact<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccess for RChunksExact<'a, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunksExact<'a, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +/// An iterator over a slice in (non-overlapping) mutable chunks (`chunk_size` +/// elements at a time), starting at the end of the slice. +/// +/// When the slice len is not evenly divided by the chunk size, the last up to +/// `chunk_size-1` elements will be omitted but can be retrieved from the +/// [`into_remainder`] function from the iterator. +/// +/// This struct is created by the [`rchunks_exact_mut`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let mut slice = ['l', 'o', 'r', 'e', 'm']; +/// let iter = slice.rchunks_exact_mut(2); +/// ``` +/// +/// [`rchunks_exact_mut`]: slice::rchunks_exact_mut +/// [`into_remainder`]: RChunksExactMut::into_remainder +/// [slices]: slice +#[derive(Debug)] +#[stable(feature = "rchunks", since = "1.31.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct RChunksExactMut<'a, T: 'a> { + /// # Safety + /// This slice pointer must point at a valid region of `T` with at least length `v.len()`. Normally, + /// those requirements would mean that we could instead use a `&mut [T]` here, but we cannot + /// because `__iterator_get_unchecked` needs to return `&mut [T]`, which guarantees certain aliasing + /// properties that we cannot uphold if we hold on to the full original `&mut [T]`. Wrapping a raw + /// slice instead lets us hand out non-overlapping `&mut [T]` subslices of the slice we wrap. + v: *mut [T], + rem: &'a mut [T], + chunk_size: usize, +} + +impl<'a, T> RChunksExactMut<'a, T> { + #[inline] + pub(super) fn new(slice: &'a mut [T], chunk_size: usize) -> Self { + let rem = slice.len() % chunk_size; + // SAFETY: 0 <= rem <= slice.len() by construction above + let (fst, snd) = unsafe { slice.split_at_mut_unchecked(rem) }; + Self { v: snd, rem: fst, chunk_size } + } + + /// Returns the remainder of the original slice that is not going to be + /// returned by the iterator. The returned slice has at most `chunk_size-1` + /// elements. + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "rchunks", since = "1.31.0")] + pub fn into_remainder(self) -> &'a mut [T] { + self.rem + } +} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl<'a, T> Iterator for RChunksExactMut<'a, T> { + type Item = &'a mut [T]; + + #[inline] + fn next(&mut self) -> Option<&'a mut [T]> { + if self.v.len() < self.chunk_size { + None + } else { + let len = self.v.len(); + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (head, tail) = unsafe { self.v.split_at_mut(len - self.chunk_size) }; + self.v = head; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *tail }) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let n = self.v.len() / self.chunk_size; + (n, Some(n)) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option<&'a mut [T]> { + let (end, overflow) = n.overflowing_mul(self.chunk_size); + if end >= self.v.len() || overflow { + self.v = &mut []; + None + } else { + let len = self.v.len(); + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (fst, _) = unsafe { self.v.split_at_mut(len - end) }; + self.v = fst; + self.next() + } + } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + let end = self.v.len() - idx * self.chunk_size; + let start = end - self.chunk_size; + // SAFETY: see comments for `RChunksMut::__iterator_get_unchecked` and `self.v`. + unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) } + } +} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a mut [T]> { + if self.v.len() < self.chunk_size { + None + } else { + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (head, tail) = unsafe { self.v.split_at_mut(self.chunk_size) }; + self.v = tail; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *head }) + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &mut []; + None + } else { + // now that we know that `n` corresponds to a chunk, + // none of these operations can underflow/overflow + let offset = (len - n) * self.chunk_size; + let start = self.v.len() - offset; + let end = start + self.chunk_size; + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (tmp, tail) = unsafe { self.v.split_at_mut(end) }; + // SAFETY: The self.v contract ensures that any split_at_mut is valid. + let (_, nth_back) = unsafe { tmp.split_at_mut(start) }; + self.v = tail; + // SAFETY: Nothing else points to or will point to the contents of this slice. + Some(unsafe { &mut *nth_back }) + } + } +} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl ExactSizeIterator for RChunksExactMut<'_, T> { + fn is_empty(&self) -> bool { + self.v.is_empty() + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for RChunksExactMut<'_, T> {} + +#[stable(feature = "rchunks", since = "1.31.0")] +impl FusedIterator for RChunksExactMut<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunksExactMut<'a, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +#[stable(feature = "rchunks", since = "1.31.0")] +unsafe impl Send for RChunksExactMut<'_, T> where T: Send {} + +#[stable(feature = "rchunks", since = "1.31.0")] +unsafe impl Sync for RChunksExactMut<'_, T> where T: Sync {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccessNoCoerce for Iter<'a, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<'a, T> TrustedRandomAccessNoCoerce for IterMut<'a, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +/// An iterator over slice in (non-overlapping) chunks separated by a predicate. +/// +/// This struct is created by the [`chunk_by`] method on [slices]. +/// +/// [`chunk_by`]: slice::chunk_by +/// [slices]: slice +#[stable(feature = "slice_group_by", since = "1.77.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct ChunkBy<'a, T: 'a, P> { + slice: &'a [T], + predicate: P, +} + +#[stable(feature = "slice_group_by", since = "1.77.0")] +impl<'a, T: 'a, P> ChunkBy<'a, T, P> { + pub(super) fn new(slice: &'a [T], predicate: P) -> Self { + ChunkBy { slice, predicate } + } +} + +#[stable(feature = "slice_group_by", since = "1.77.0")] +impl<'a, T: 'a, P> Iterator for ChunkBy<'a, T, P> +where + P: FnMut(&T, &T) -> bool, +{ + type Item = &'a [T]; + + #[inline] + fn next(&mut self) -> Option { + if self.slice.is_empty() { + None + } else { + let mut len = 1; + let mut iter = self.slice.windows(2); + while let Some([l, r]) = iter.next() { + if (self.predicate)(l, r) { len += 1 } else { break } + } + let (head, tail) = self.slice.split_at(len); + self.slice = tail; + Some(head) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.slice.is_empty() { (0, Some(0)) } else { (1, Some(self.slice.len())) } + } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } +} + +#[stable(feature = "slice_group_by", since = "1.77.0")] +impl<'a, T: 'a, P> DoubleEndedIterator for ChunkBy<'a, T, P> +where + P: FnMut(&T, &T) -> bool, +{ + #[inline] + fn next_back(&mut self) -> Option { + if self.slice.is_empty() { + None + } else { + let mut len = 1; + let mut iter = self.slice.windows(2); + while let Some([l, r]) = iter.next_back() { + if (self.predicate)(l, r) { len += 1 } else { break } + } + let (head, tail) = self.slice.split_at(self.slice.len() - len); + self.slice = head; + Some(tail) + } + } +} + +#[stable(feature = "slice_group_by", since = "1.77.0")] +impl<'a, T: 'a, P> FusedIterator for ChunkBy<'a, T, P> where P: FnMut(&T, &T) -> bool {} + +#[stable(feature = "slice_group_by", since = "1.77.0")] +impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for ChunkBy<'a, T, P> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ChunkBy").field("slice", &self.slice).finish() + } +} + +/// An iterator over slice in (non-overlapping) mutable chunks separated +/// by a predicate. +/// +/// This struct is created by the [`chunk_by_mut`] method on [slices]. +/// +/// [`chunk_by_mut`]: slice::chunk_by_mut +/// [slices]: slice +#[stable(feature = "slice_group_by", since = "1.77.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct ChunkByMut<'a, T: 'a, P> { + slice: &'a mut [T], + predicate: P, +} + +#[stable(feature = "slice_group_by", since = "1.77.0")] +impl<'a, T: 'a, P> ChunkByMut<'a, T, P> { + pub(super) fn new(slice: &'a mut [T], predicate: P) -> Self { + ChunkByMut { slice, predicate } + } +} + +#[stable(feature = "slice_group_by", since = "1.77.0")] +impl<'a, T: 'a, P> Iterator for ChunkByMut<'a, T, P> +where + P: FnMut(&T, &T) -> bool, +{ + type Item = &'a mut [T]; + + #[inline] + fn next(&mut self) -> Option { + if self.slice.is_empty() { + None + } else { + let mut len = 1; + let mut iter = self.slice.windows(2); + while let Some([l, r]) = iter.next() { + if (self.predicate)(l, r) { len += 1 } else { break } + } + let slice = mem::take(&mut self.slice); + let (head, tail) = slice.split_at_mut(len); + self.slice = tail; + Some(head) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.slice.is_empty() { (0, Some(0)) } else { (1, Some(self.slice.len())) } + } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } +} + +#[stable(feature = "slice_group_by", since = "1.77.0")] +impl<'a, T: 'a, P> DoubleEndedIterator for ChunkByMut<'a, T, P> +where + P: FnMut(&T, &T) -> bool, +{ + #[inline] + fn next_back(&mut self) -> Option { + if self.slice.is_empty() { + None + } else { + let mut len = 1; + let mut iter = self.slice.windows(2); + while let Some([l, r]) = iter.next_back() { + if (self.predicate)(l, r) { len += 1 } else { break } + } + let slice = mem::take(&mut self.slice); + let (head, tail) = slice.split_at_mut(slice.len() - len); + self.slice = head; + Some(tail) + } + } +} + +#[stable(feature = "slice_group_by", since = "1.77.0")] +impl<'a, T: 'a, P> FusedIterator for ChunkByMut<'a, T, P> where P: FnMut(&T, &T) -> bool {} + +#[stable(feature = "slice_group_by", since = "1.77.0")] +impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for ChunkByMut<'a, T, P> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ChunkByMut").field("slice", &self.slice).finish() + } +} diff --git a/CoqOfRust/core/slice/iter/macros.rs b/CoqOfRust/core/slice/iter/macros.rs new file mode 100644 index 000000000..830debe02 --- /dev/null +++ b/CoqOfRust/core/slice/iter/macros.rs @@ -0,0 +1,487 @@ +//! Macros used by iterators of slice. + +/// Convenience & performance macro for consuming the `end_or_len` field, by +/// giving a `(&mut) usize` or `(&mut) NonNull` depending whether `T` is +/// or is not a ZST respectively. +/// +/// Internally, this reads the `end` through a pointer-to-`NonNull` so that +/// it'll get the appropriate non-null metadata in the backend without needing +/// to call `assume` manually. +macro_rules! if_zst { + (mut $this:ident, $len:ident => $zst_body:expr, $end:ident => $other_body:expr,) => {{ + #![allow(unused_unsafe)] // we're sometimes used within an unsafe block + + if T::IS_ZST { + // SAFETY: for ZSTs, the pointer is storing a provenance-free length, + // so consuming and updating it as a `usize` is fine. + let $len = unsafe { &mut *(&raw mut $this.end_or_len).cast::() }; + $zst_body + } else { + // SAFETY: for non-ZSTs, the type invariant ensures it cannot be null + let $end = unsafe { &mut *(&raw mut $this.end_or_len).cast::>() }; + $other_body + } + }}; + ($this:ident, $len:ident => $zst_body:expr, $end:ident => $other_body:expr,) => {{ + #![allow(unused_unsafe)] // we're sometimes used within an unsafe block + + if T::IS_ZST { + let $len = $this.end_or_len.addr(); + $zst_body + } else { + // SAFETY: for non-ZSTs, the type invariant ensures it cannot be null + let $end = unsafe { *(&raw const $this.end_or_len).cast::>() }; + $other_body + } + }}; +} + +// Inlining is_empty and len makes a huge performance difference +macro_rules! is_empty { + ($self: ident) => { + if_zst!($self, + len => len == 0, + end => $self.ptr == end, + ) + }; +} + +macro_rules! len { + ($self: ident) => {{ + if_zst!($self, + len => len, + end => { + // To get rid of some bounds checks (see `position`), we use ptr_sub instead of + // offset_from (Tested by `codegen/slice-position-bounds-check`.) + // SAFETY: by the type invariant pointers are aligned and `start <= end` + unsafe { end.sub_ptr($self.ptr) } + }, + ) + }}; +} + +// The shared definition of the `Iter` and `IterMut` iterators +macro_rules! iterator { + ( + struct $name:ident -> $ptr:ty, + $elem:ty, + $raw_mut:tt, + {$( $mut_:tt )?}, + $into_ref:ident, + {$($extra:tt)*} + ) => { + impl<'a, T> $name<'a, T> { + /// Returns the last element and moves the end of the iterator backwards by 1. + /// + /// # Safety + /// + /// The iterator must not be empty + #[inline] + unsafe fn next_back_unchecked(&mut self) -> $elem { + // SAFETY: the caller promised it's not empty, so + // the offsetting is in-bounds and there's an element to return. + unsafe { self.pre_dec_end(1).$into_ref() } + } + + // Helper function for creating a slice from the iterator. + #[inline(always)] + fn make_slice(&self) -> &'a [T] { + // SAFETY: the iterator was created from a slice with pointer + // `self.ptr` and length `len!(self)`. This guarantees that all + // the prerequisites for `from_raw_parts` are fulfilled. + unsafe { from_raw_parts(self.ptr.as_ptr(), len!(self)) } + } + + // Helper function for moving the start of the iterator forwards by `offset` elements, + // returning the old start. + // Unsafe because the offset must not exceed `self.len()`. + #[inline(always)] + unsafe fn post_inc_start(&mut self, offset: usize) -> NonNull { + let old = self.ptr; + + // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`, + // so this new pointer is inside `self` and thus guaranteed to be non-null. + unsafe { + if_zst!(mut self, + // Using the intrinsic directly avoids emitting a UbCheck + len => *len = crate::intrinsics::unchecked_sub(*len, offset), + _end => self.ptr = self.ptr.add(offset), + ); + } + old + } + + // Helper function for moving the end of the iterator backwards by `offset` elements, + // returning the new end. + // Unsafe because the offset must not exceed `self.len()`. + #[inline(always)] + unsafe fn pre_dec_end(&mut self, offset: usize) -> NonNull { + if_zst!(mut self, + // SAFETY: By our precondition, `offset` can be at most the + // current length, so the subtraction can never overflow. + len => unsafe { + // Using the intrinsic directly avoids emitting a UbCheck + *len = crate::intrinsics::unchecked_sub(*len, offset); + self.ptr + }, + // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`, + // which is guaranteed to not overflow an `isize`. Also, the resulting pointer + // is in bounds of `slice`, which fulfills the other requirements for `offset`. + end => unsafe { + *end = end.sub(offset); + *end + }, + ) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl ExactSizeIterator for $name<'_, T> { + #[inline(always)] + fn len(&self) -> usize { + len!(self) + } + + #[inline(always)] + fn is_empty(&self) -> bool { + is_empty!(self) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, T> Iterator for $name<'a, T> { + type Item = $elem; + + #[inline] + fn next(&mut self) -> Option<$elem> { + // could be implemented with slices, but this avoids bounds checks + + // SAFETY: The call to `next_unchecked` is + // safe since we check if the iterator is empty first. + unsafe { + if is_empty!(self) { + None + } else { + Some(self.next_unchecked()) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let exact = len!(self); + (exact, Some(exact)) + } + + #[inline] + fn count(self) -> usize { + len!(self) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option<$elem> { + if n >= len!(self) { + // This iterator is now empty. + if_zst!(mut self, + len => *len = 0, + end => self.ptr = *end, + ); + return None; + } + // SAFETY: We are in bounds. `post_inc_start` does the right thing even for ZSTs. + unsafe { + self.post_inc_start(n); + Some(self.next_unchecked()) + } + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + let advance = cmp::min(len!(self), n); + // SAFETY: By construction, `advance` does not exceed `self.len()`. + unsafe { self.post_inc_start(advance) }; + NonZero::new(n - advance).map_or(Ok(()), Err) + } + + #[inline] + fn last(mut self) -> Option<$elem> { + self.next_back() + } + + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + // this implementation consists of the following optimizations compared to the + // default implementation: + // - do-while loop, as is llvm's preferred loop shape, + // see https://releases.llvm.org/16.0.0/docs/LoopTerminology.html#more-canonical-loops + // - bumps an index instead of a pointer since the latter case inhibits + // some optimizations, see #111603 + // - avoids Option wrapping/matching + if is_empty!(self) { + return init; + } + let mut acc = init; + let mut i = 0; + let len = len!(self); + loop { + // SAFETY: the loop iterates `i in 0..len`, which always is in bounds of + // the slice allocation + acc = f(acc, unsafe { & $( $mut_ )? *self.ptr.add(i).as_ptr() }); + // SAFETY: `i` can't overflow since it'll only reach usize::MAX if the + // slice had that length, in which case we'll break out of the loop + // after the increment + i = unsafe { i.unchecked_add(1) }; + if i == len { + break; + } + } + acc + } + + // We override the default implementation, which uses `try_fold`, + // because this simple implementation generates less LLVM IR and is + // faster to compile. + #[inline] + fn for_each(mut self, mut f: F) + where + Self: Sized, + F: FnMut(Self::Item), + { + while let Some(x) = self.next() { + f(x); + } + } + + // We override the default implementation, which uses `try_fold`, + // because this simple implementation generates less LLVM IR and is + // faster to compile. + #[inline] + fn all(&mut self, mut f: F) -> bool + where + Self: Sized, + F: FnMut(Self::Item) -> bool, + { + while let Some(x) = self.next() { + if !f(x) { + return false; + } + } + true + } + + // We override the default implementation, which uses `try_fold`, + // because this simple implementation generates less LLVM IR and is + // faster to compile. + #[inline] + fn any(&mut self, mut f: F) -> bool + where + Self: Sized, + F: FnMut(Self::Item) -> bool, + { + while let Some(x) = self.next() { + if f(x) { + return true; + } + } + false + } + + // We override the default implementation, which uses `try_fold`, + // because this simple implementation generates less LLVM IR and is + // faster to compile. + #[inline] + fn find

(&mut self, mut predicate: P) -> Option + where + Self: Sized, + P: FnMut(&Self::Item) -> bool, + { + while let Some(x) = self.next() { + if predicate(&x) { + return Some(x); + } + } + None + } + + // We override the default implementation, which uses `try_fold`, + // because this simple implementation generates less LLVM IR and is + // faster to compile. + #[inline] + fn find_map(&mut self, mut f: F) -> Option + where + Self: Sized, + F: FnMut(Self::Item) -> Option, + { + while let Some(x) = self.next() { + if let Some(y) = f(x) { + return Some(y); + } + } + None + } + + // We override the default implementation, which uses `try_fold`, + // because this simple implementation generates less LLVM IR and is + // faster to compile. Also, the `assume` avoids a bounds check. + #[inline] + #[rustc_inherit_overflow_checks] + fn position

(&mut self, mut predicate: P) -> Option where + Self: Sized, + P: FnMut(Self::Item) -> bool, + { + let n = len!(self); + let mut i = 0; + while let Some(x) = self.next() { + if predicate(x) { + // SAFETY: we are guaranteed to be in bounds by the loop invariant: + // when `i >= n`, `self.next()` returns `None` and the loop breaks. + unsafe { assert_unchecked(i < n) }; + return Some(i); + } + i += 1; + } + None + } + + // We override the default implementation, which uses `try_fold`, + // because this simple implementation generates less LLVM IR and is + // faster to compile. Also, the `assume` avoids a bounds check. + #[inline] + fn rposition

(&mut self, mut predicate: P) -> Option where + P: FnMut(Self::Item) -> bool, + Self: Sized + ExactSizeIterator + DoubleEndedIterator + { + let n = len!(self); + let mut i = n; + while let Some(x) = self.next_back() { + i -= 1; + if predicate(x) { + // SAFETY: `i` must be lower than `n` since it starts at `n` + // and is only decreasing. + unsafe { assert_unchecked(i < n) }; + return Some(i); + } + } + None + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + // SAFETY: the caller must guarantee that `i` is in bounds of + // the underlying slice, so `i` cannot overflow an `isize`, and + // the returned references is guaranteed to refer to an element + // of the slice and thus guaranteed to be valid. + // + // Also note that the caller also guarantees that we're never + // called with the same index again, and that no other methods + // that will access this subslice are called, so it is valid + // for the returned reference to be mutable in the case of + // `IterMut` + unsafe { & $( $mut_ )? * self.ptr.as_ptr().add(idx) } + } + + $($extra)* + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, T> DoubleEndedIterator for $name<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<$elem> { + // could be implemented with slices, but this avoids bounds checks + + // SAFETY: The call to `next_back_unchecked` + // is safe since we check if the iterator is empty first. + unsafe { + if is_empty!(self) { + None + } else { + Some(self.next_back_unchecked()) + } + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option<$elem> { + if n >= len!(self) { + // This iterator is now empty. + if_zst!(mut self, + len => *len = 0, + end => *end = self.ptr, + ); + return None; + } + // SAFETY: We are in bounds. `pre_dec_end` does the right thing even for ZSTs. + unsafe { + self.pre_dec_end(n); + Some(self.next_back_unchecked()) + } + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + let advance = cmp::min(len!(self), n); + // SAFETY: By construction, `advance` does not exceed `self.len()`. + unsafe { self.pre_dec_end(advance) }; + NonZero::new(n - advance).map_or(Ok(()), Err) + } + } + + #[stable(feature = "fused", since = "1.26.0")] + impl FusedIterator for $name<'_, T> {} + + #[unstable(feature = "trusted_len", issue = "37572")] + unsafe impl TrustedLen for $name<'_, T> {} + + impl<'a, T> UncheckedIterator for $name<'a, T> { + #[inline] + unsafe fn next_unchecked(&mut self) -> $elem { + // SAFETY: The caller promised there's at least one more item. + unsafe { + self.post_inc_start(1).$into_ref() + } + } + } + + #[stable(feature = "default_iters", since = "1.70.0")] + impl Default for $name<'_, T> { + /// Creates an empty slice iterator. + /// + /// ``` + #[doc = concat!("# use core::slice::", stringify!($name), ";")] + #[doc = concat!("let iter: ", stringify!($name<'_, u8>), " = Default::default();")] + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + (& $( $mut_ )? []).into_iter() + } + } + } +} + +macro_rules! forward_iterator { + ($name:ident: $elem:ident, $iter_of:ty) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, $elem, P> Iterator for $name<'a, $elem, P> + where + P: FnMut(&T) -> bool, + { + type Item = $iter_of; + + #[inline] + fn next(&mut self) -> Option<$iter_of> { + self.inner.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + } + + #[stable(feature = "fused", since = "1.26.0")] + impl<'a, $elem, P> FusedIterator for $name<'a, $elem, P> where P: FnMut(&T) -> bool {} + }; +} diff --git a/CoqOfRust/core/slice/memchr.rs b/CoqOfRust/core/slice/memchr.rs new file mode 100644 index 000000000..98db7aaf5 --- /dev/null +++ b/CoqOfRust/core/slice/memchr.rs @@ -0,0 +1,162 @@ +// Original implementation taken from rust-memchr. +// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch + +use crate::intrinsics::const_eval_select; +use crate::mem; + +const LO_USIZE: usize = usize::repeat_u8(0x01); +const HI_USIZE: usize = usize::repeat_u8(0x80); +const USIZE_BYTES: usize = mem::size_of::(); + +/// Returns `true` if `x` contains any zero byte. +/// +/// From *Matters Computational*, J. Arndt: +/// +/// "The idea is to subtract one from each of the bytes and then look for +/// bytes where the borrow propagated all the way to the most significant +/// bit." +#[inline] +const fn contains_zero_byte(x: usize) -> bool { + x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0 +} + +/// Returns the first index matching the byte `x` in `text`. +#[inline] +#[must_use] +pub const fn memchr(x: u8, text: &[u8]) -> Option { + // Fast path for small slices. + if text.len() < 2 * USIZE_BYTES { + return memchr_naive(x, text); + } + + memchr_aligned(x, text) +} + +#[inline] +const fn memchr_naive(x: u8, text: &[u8]) -> Option { + let mut i = 0; + + // FIXME(const-hack): Replace with `text.iter().pos(|c| *c == x)`. + while i < text.len() { + if text[i] == x { + return Some(i); + } + + i += 1; + } + + None +} + +#[rustc_allow_const_fn_unstable(const_eval_select)] // fallback impl has same behavior +const fn memchr_aligned(x: u8, text: &[u8]) -> Option { + // The runtime version behaves the same as the compiletime version, it's + // just more optimized. + const_eval_select!( + @capture { x: u8, text: &[u8] } -> Option: + if const { + memchr_naive(x, text) + } else { + // Scan for a single byte value by reading two `usize` words at a time. + // + // Split `text` in three parts + // - unaligned initial part, before the first word aligned address in text + // - body, scan by 2 words at a time + // - the last remaining part, < 2 word size + + // search up to an aligned boundary + let len = text.len(); + let ptr = text.as_ptr(); + let mut offset = ptr.align_offset(USIZE_BYTES); + + if offset > 0 { + offset = offset.min(len); + let slice = &text[..offset]; + if let Some(index) = memchr_naive(x, slice) { + return Some(index); + } + } + + // search the body of the text + let repeated_x = usize::repeat_u8(x); + while offset <= len - 2 * USIZE_BYTES { + // SAFETY: the while's predicate guarantees a distance of at least 2 * usize_bytes + // between the offset and the end of the slice. + unsafe { + let u = *(ptr.add(offset) as *const usize); + let v = *(ptr.add(offset + USIZE_BYTES) as *const usize); + + // break if there is a matching byte + let zu = contains_zero_byte(u ^ repeated_x); + let zv = contains_zero_byte(v ^ repeated_x); + if zu || zv { + break; + } + } + offset += USIZE_BYTES * 2; + } + + // Find the byte after the point the body loop stopped. + // FIXME(const-hack): Use `?` instead. + // FIXME(const-hack, fee1-dead): use range slicing + let slice = + // SAFETY: offset is within bounds + unsafe { super::from_raw_parts(text.as_ptr().add(offset), text.len() - offset) }; + if let Some(i) = memchr_naive(x, slice) { Some(offset + i) } else { None } + } + ) +} + +/// Returns the last index matching the byte `x` in `text`. +#[must_use] +pub fn memrchr(x: u8, text: &[u8]) -> Option { + // Scan for a single byte value by reading two `usize` words at a time. + // + // Split `text` in three parts: + // - unaligned tail, after the last word aligned address in text, + // - body, scanned by 2 words at a time, + // - the first remaining bytes, < 2 word size. + let len = text.len(); + let ptr = text.as_ptr(); + type Chunk = usize; + + let (min_aligned_offset, max_aligned_offset) = { + // We call this just to obtain the length of the prefix and suffix. + // In the middle we always process two chunks at once. + // SAFETY: transmuting `[u8]` to `[usize]` is safe except for size differences + // which are handled by `align_to`. + let (prefix, _, suffix) = unsafe { text.align_to::<(Chunk, Chunk)>() }; + (prefix.len(), len - suffix.len()) + }; + + let mut offset = max_aligned_offset; + if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) { + return Some(offset + index); + } + + // Search the body of the text, make sure we don't cross min_aligned_offset. + // offset is always aligned, so just testing `>` is sufficient and avoids possible + // overflow. + let repeated_x = usize::repeat_u8(x); + let chunk_bytes = mem::size_of::(); + + while offset > min_aligned_offset { + // SAFETY: offset starts at len - suffix.len(), as long as it is greater than + // min_aligned_offset (prefix.len()) the remaining distance is at least 2 * chunk_bytes. + unsafe { + let u = *(ptr.add(offset - 2 * chunk_bytes) as *const Chunk); + let v = *(ptr.add(offset - chunk_bytes) as *const Chunk); + + // Break if there is a matching byte. + let zu = contains_zero_byte(u ^ repeated_x); + let zv = contains_zero_byte(v ^ repeated_x); + if zu || zv { + break; + } + } + offset -= 2 * chunk_bytes; + } + + // Find the byte before the point the body loop stopped. + text[..offset].iter().rposition(|elt| *elt == x) +} diff --git a/CoqOfRust/core/slice/mod.rs b/CoqOfRust/core/slice/mod.rs new file mode 100644 index 000000000..191eaccff --- /dev/null +++ b/CoqOfRust/core/slice/mod.rs @@ -0,0 +1,5137 @@ +//! Slice management and manipulation. +//! +//! For more details see [`std::slice`]. +//! +//! [`std::slice`]: ../../std/slice/index.html + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::cmp::Ordering::{self, Equal, Greater, Less}; +use crate::intrinsics::{exact_div, select_unpredictable, unchecked_sub}; +use crate::mem::{self, SizedTypeProperties}; +use crate::num::NonZero; +use crate::ops::{Bound, OneSidedRange, Range, RangeBounds, RangeInclusive}; +use crate::panic::const_panic; +use crate::simd::{self, Simd}; +use crate::ub_checks::assert_unsafe_precondition; +use crate::{fmt, hint, ptr, range, slice}; + +#[unstable( + feature = "slice_internals", + issue = "none", + reason = "exposed from core to be reused in std; use the memchr crate" +)] +/// Pure Rust memchr implementation, taken from rust-memchr +pub mod memchr; + +#[unstable( + feature = "slice_internals", + issue = "none", + reason = "exposed from core to be reused in std;" +)] +#[doc(hidden)] +pub mod sort; + +mod ascii; +mod cmp; +pub(crate) mod index; +mod iter; +mod raw; +mod rotate; +mod specialize; + +#[stable(feature = "inherent_ascii_escape", since = "1.60.0")] +pub use ascii::EscapeAscii; +#[unstable(feature = "str_internals", issue = "none")] +#[doc(hidden)] +pub use ascii::is_ascii_simple; +#[stable(feature = "slice_get_slice", since = "1.28.0")] +pub use index::SliceIndex; +#[unstable(feature = "slice_range", issue = "76393")] +pub use index::{range, try_range}; +#[unstable(feature = "array_windows", issue = "75027")] +pub use iter::ArrayWindows; +#[unstable(feature = "array_chunks", issue = "74985")] +pub use iter::{ArrayChunks, ArrayChunksMut}; +#[stable(feature = "slice_group_by", since = "1.77.0")] +pub use iter::{ChunkBy, ChunkByMut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use iter::{Chunks, ChunksMut, Windows}; +#[stable(feature = "chunks_exact", since = "1.31.0")] +pub use iter::{ChunksExact, ChunksExactMut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use iter::{Iter, IterMut}; +#[stable(feature = "rchunks", since = "1.31.0")] +pub use iter::{RChunks, RChunksExact, RChunksExactMut, RChunksMut}; +#[stable(feature = "slice_rsplit", since = "1.27.0")] +pub use iter::{RSplit, RSplitMut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use iter::{RSplitN, RSplitNMut, Split, SplitMut, SplitN, SplitNMut}; +#[stable(feature = "split_inclusive", since = "1.51.0")] +pub use iter::{SplitInclusive, SplitInclusiveMut}; +#[stable(feature = "from_ref", since = "1.28.0")] +pub use raw::{from_mut, from_ref}; +#[unstable(feature = "slice_from_ptr_range", issue = "89792")] +pub use raw::{from_mut_ptr_range, from_ptr_range}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use raw::{from_raw_parts, from_raw_parts_mut}; + +/// Calculates the direction and split point of a one-sided range. +/// +/// This is a helper function for `take` and `take_mut` that returns +/// the direction of the split (front or back) as well as the index at +/// which to split. Returns `None` if the split index would overflow. +#[inline] +fn split_point_of(range: impl OneSidedRange) -> Option<(Direction, usize)> { + use Bound::*; + + Some(match (range.start_bound(), range.end_bound()) { + (Unbounded, Excluded(i)) => (Direction::Front, *i), + (Unbounded, Included(i)) => (Direction::Front, i.checked_add(1)?), + (Excluded(i), Unbounded) => (Direction::Back, i.checked_add(1)?), + (Included(i), Unbounded) => (Direction::Back, *i), + _ => unreachable!(), + }) +} + +enum Direction { + Front, + Back, +} + +#[cfg(not(test))] +impl [T] { + /// Returns the number of elements in the slice. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// assert_eq!(a.len(), 3); + /// ``` + #[lang = "slice_len_fn"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_slice_len", since = "1.39.0")] + #[inline] + #[must_use] + pub const fn len(&self) -> usize { + ptr::metadata(self) + } + + /// Returns `true` if the slice has a length of 0. + /// + /// # Examples + /// + /// ``` + /// let a = [1, 2, 3]; + /// assert!(!a.is_empty()); + /// + /// let b: &[i32] = &[]; + /// assert!(b.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_slice_is_empty", since = "1.39.0")] + #[inline] + #[must_use] + pub const fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Returns the first element of the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert_eq!(Some(&10), v.first()); + /// + /// let w: &[i32] = &[]; + /// assert_eq!(None, w.first()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")] + #[inline] + #[must_use] + pub const fn first(&self) -> Option<&T> { + if let [first, ..] = self { Some(first) } else { None } + } + + /// Returns a mutable reference to the first element of the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [0, 1, 2]; + /// + /// if let Some(first) = x.first_mut() { + /// *first = 5; + /// } + /// assert_eq!(x, &[5, 1, 2]); + /// + /// let y: &mut [i32] = &mut []; + /// assert_eq!(None, y.first_mut()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] + #[inline] + #[must_use] + pub const fn first_mut(&mut self) -> Option<&mut T> { + if let [first, ..] = self { Some(first) } else { None } + } + + /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let x = &[0, 1, 2]; + /// + /// if let Some((first, elements)) = x.split_first() { + /// assert_eq!(first, &0); + /// assert_eq!(elements, &[1, 2]); + /// } + /// ``` + #[stable(feature = "slice_splits", since = "1.5.0")] + #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")] + #[inline] + #[must_use] + pub const fn split_first(&self) -> Option<(&T, &[T])> { + if let [first, tail @ ..] = self { Some((first, tail)) } else { None } + } + + /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [0, 1, 2]; + /// + /// if let Some((first, elements)) = x.split_first_mut() { + /// *first = 3; + /// elements[0] = 4; + /// elements[1] = 5; + /// } + /// assert_eq!(x, &[3, 4, 5]); + /// ``` + #[stable(feature = "slice_splits", since = "1.5.0")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] + #[inline] + #[must_use] + pub const fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { + if let [first, tail @ ..] = self { Some((first, tail)) } else { None } + } + + /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let x = &[0, 1, 2]; + /// + /// if let Some((last, elements)) = x.split_last() { + /// assert_eq!(last, &2); + /// assert_eq!(elements, &[0, 1]); + /// } + /// ``` + #[stable(feature = "slice_splits", since = "1.5.0")] + #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")] + #[inline] + #[must_use] + pub const fn split_last(&self) -> Option<(&T, &[T])> { + if let [init @ .., last] = self { Some((last, init)) } else { None } + } + + /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [0, 1, 2]; + /// + /// if let Some((last, elements)) = x.split_last_mut() { + /// *last = 3; + /// elements[0] = 4; + /// elements[1] = 5; + /// } + /// assert_eq!(x, &[4, 5, 3]); + /// ``` + #[stable(feature = "slice_splits", since = "1.5.0")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] + #[inline] + #[must_use] + pub const fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { + if let [init @ .., last] = self { Some((last, init)) } else { None } + } + + /// Returns the last element of the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert_eq!(Some(&30), v.last()); + /// + /// let w: &[i32] = &[]; + /// assert_eq!(None, w.last()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")] + #[inline] + #[must_use] + pub const fn last(&self) -> Option<&T> { + if let [.., last] = self { Some(last) } else { None } + } + + /// Returns a mutable reference to the last item in the slice, or `None` if it is empty. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [0, 1, 2]; + /// + /// if let Some(last) = x.last_mut() { + /// *last = 10; + /// } + /// assert_eq!(x, &[0, 1, 10]); + /// + /// let y: &mut [i32] = &mut []; + /// assert_eq!(None, y.last_mut()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] + #[inline] + #[must_use] + pub const fn last_mut(&mut self) -> Option<&mut T> { + if let [.., last] = self { Some(last) } else { None } + } + + /// Returns an array reference to the first `N` items in the slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. + /// + /// # Examples + /// + /// ``` + /// let u = [10, 40, 30]; + /// assert_eq!(Some(&[10, 40]), u.first_chunk::<2>()); + /// + /// let v: &[i32] = &[10]; + /// assert_eq!(None, v.first_chunk::<2>()); + /// + /// let w: &[i32] = &[]; + /// assert_eq!(Some(&[]), w.first_chunk::<0>()); + /// ``` + #[inline] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] + pub const fn first_chunk(&self) -> Option<&[T; N]> { + if self.len() < N { + None + } else { + // SAFETY: We explicitly check for the correct number of elements, + // and do not let the reference outlive the slice. + Some(unsafe { &*(self.as_ptr().cast::<[T; N]>()) }) + } + } + + /// Returns a mutable array reference to the first `N` items in the slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [0, 1, 2]; + /// + /// if let Some(first) = x.first_chunk_mut::<2>() { + /// first[0] = 5; + /// first[1] = 4; + /// } + /// assert_eq!(x, &[5, 4, 2]); + /// + /// assert_eq!(None, x.first_chunk_mut::<4>()); + /// ``` + #[inline] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] + pub const fn first_chunk_mut(&mut self) -> Option<&mut [T; N]> { + if self.len() < N { + None + } else { + // SAFETY: We explicitly check for the correct number of elements, + // do not let the reference outlive the slice, + // and require exclusive access to the entire slice to mutate the chunk. + Some(unsafe { &mut *(self.as_mut_ptr().cast::<[T; N]>()) }) + } + } + + /// Returns an array reference to the first `N` items in the slice and the remaining slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. + /// + /// # Examples + /// + /// ``` + /// let x = &[0, 1, 2]; + /// + /// if let Some((first, elements)) = x.split_first_chunk::<2>() { + /// assert_eq!(first, &[0, 1]); + /// assert_eq!(elements, &[2]); + /// } + /// + /// assert_eq!(None, x.split_first_chunk::<4>()); + /// ``` + #[inline] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] + pub const fn split_first_chunk(&self) -> Option<(&[T; N], &[T])> { + if self.len() < N { + None + } else { + // SAFETY: We manually verified the bounds of the split. + let (first, tail) = unsafe { self.split_at_unchecked(N) }; + + // SAFETY: We explicitly check for the correct number of elements, + // and do not let the references outlive the slice. + Some((unsafe { &*(first.as_ptr().cast::<[T; N]>()) }, tail)) + } + } + + /// Returns a mutable array reference to the first `N` items in the slice and the remaining + /// slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [0, 1, 2]; + /// + /// if let Some((first, elements)) = x.split_first_chunk_mut::<2>() { + /// first[0] = 3; + /// first[1] = 4; + /// elements[0] = 5; + /// } + /// assert_eq!(x, &[3, 4, 5]); + /// + /// assert_eq!(None, x.split_first_chunk_mut::<4>()); + /// ``` + #[inline] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] + pub const fn split_first_chunk_mut( + &mut self, + ) -> Option<(&mut [T; N], &mut [T])> { + if self.len() < N { + None + } else { + // SAFETY: We manually verified the bounds of the split. + let (first, tail) = unsafe { self.split_at_mut_unchecked(N) }; + + // SAFETY: We explicitly check for the correct number of elements, + // do not let the reference outlive the slice, + // and enforce exclusive mutability of the chunk by the split. + Some((unsafe { &mut *(first.as_mut_ptr().cast::<[T; N]>()) }, tail)) + } + } + + /// Returns an array reference to the last `N` items in the slice and the remaining slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. + /// + /// # Examples + /// + /// ``` + /// let x = &[0, 1, 2]; + /// + /// if let Some((elements, last)) = x.split_last_chunk::<2>() { + /// assert_eq!(elements, &[0]); + /// assert_eq!(last, &[1, 2]); + /// } + /// + /// assert_eq!(None, x.split_last_chunk::<4>()); + /// ``` + #[inline] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] + pub const fn split_last_chunk(&self) -> Option<(&[T], &[T; N])> { + if self.len() < N { + None + } else { + // SAFETY: We manually verified the bounds of the split. + let (init, last) = unsafe { self.split_at_unchecked(self.len() - N) }; + + // SAFETY: We explicitly check for the correct number of elements, + // and do not let the references outlive the slice. + Some((init, unsafe { &*(last.as_ptr().cast::<[T; N]>()) })) + } + } + + /// Returns a mutable array reference to the last `N` items in the slice and the remaining + /// slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [0, 1, 2]; + /// + /// if let Some((elements, last)) = x.split_last_chunk_mut::<2>() { + /// last[0] = 3; + /// last[1] = 4; + /// elements[0] = 5; + /// } + /// assert_eq!(x, &[5, 3, 4]); + /// + /// assert_eq!(None, x.split_last_chunk_mut::<4>()); + /// ``` + #[inline] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] + pub const fn split_last_chunk_mut( + &mut self, + ) -> Option<(&mut [T], &mut [T; N])> { + if self.len() < N { + None + } else { + // SAFETY: We manually verified the bounds of the split. + let (init, last) = unsafe { self.split_at_mut_unchecked(self.len() - N) }; + + // SAFETY: We explicitly check for the correct number of elements, + // do not let the reference outlive the slice, + // and enforce exclusive mutability of the chunk by the split. + Some((init, unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) })) + } + } + + /// Returns an array reference to the last `N` items in the slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. + /// + /// # Examples + /// + /// ``` + /// let u = [10, 40, 30]; + /// assert_eq!(Some(&[40, 30]), u.last_chunk::<2>()); + /// + /// let v: &[i32] = &[10]; + /// assert_eq!(None, v.last_chunk::<2>()); + /// + /// let w: &[i32] = &[]; + /// assert_eq!(Some(&[]), w.last_chunk::<0>()); + /// ``` + #[inline] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "const_slice_last_chunk", since = "1.80.0")] + pub const fn last_chunk(&self) -> Option<&[T; N]> { + if self.len() < N { + None + } else { + // SAFETY: We manually verified the bounds of the slice. + // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. + let last = unsafe { self.split_at_unchecked(self.len() - N).1 }; + + // SAFETY: We explicitly check for the correct number of elements, + // and do not let the references outlive the slice. + Some(unsafe { &*(last.as_ptr().cast::<[T; N]>()) }) + } + } + + /// Returns a mutable array reference to the last `N` items in the slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [0, 1, 2]; + /// + /// if let Some(last) = x.last_chunk_mut::<2>() { + /// last[0] = 10; + /// last[1] = 20; + /// } + /// assert_eq!(x, &[0, 10, 20]); + /// + /// assert_eq!(None, x.last_chunk_mut::<4>()); + /// ``` + #[inline] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] + pub const fn last_chunk_mut(&mut self) -> Option<&mut [T; N]> { + if self.len() < N { + None + } else { + // SAFETY: We manually verified the bounds of the slice. + // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. + let last = unsafe { self.split_at_mut_unchecked(self.len() - N).1 }; + + // SAFETY: We explicitly check for the correct number of elements, + // do not let the reference outlive the slice, + // and require exclusive access to the entire slice to mutate the chunk. + Some(unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) }) + } + } + + /// Returns a reference to an element or subslice depending on the type of + /// index. + /// + /// - If given a position, returns a reference to the element at that + /// position or `None` if out of bounds. + /// - If given a range, returns the subslice corresponding to that range, + /// or `None` if out of bounds. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert_eq!(Some(&40), v.get(1)); + /// assert_eq!(Some(&[10, 40][..]), v.get(0..2)); + /// assert_eq!(None, v.get(3)); + /// assert_eq!(None, v.get(0..4)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[must_use] + pub fn get(&self, index: I) -> Option<&I::Output> + where + I: SliceIndex, + { + index.get(self) + } + + /// Returns a mutable reference to an element or subslice depending on the + /// type of index (see [`get`]) or `None` if the index is out of bounds. + /// + /// [`get`]: slice::get + /// + /// # Examples + /// + /// ``` + /// let x = &mut [0, 1, 2]; + /// + /// if let Some(elem) = x.get_mut(1) { + /// *elem = 42; + /// } + /// assert_eq!(x, &[0, 42, 2]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[must_use] + pub fn get_mut(&mut self, index: I) -> Option<&mut I::Output> + where + I: SliceIndex, + { + index.get_mut(self) + } + + /// Returns a reference to an element or subslice, without doing bounds + /// checking. + /// + /// For a safe alternative see [`get`]. + /// + /// # Safety + /// + /// Calling this method with an out-of-bounds index is *[undefined behavior]* + /// even if the resulting reference is not used. + /// + /// You can think of this like `.get(index).unwrap_unchecked()`. It's UB + /// to call `.get_unchecked(len)`, even if you immediately convert to a + /// pointer. And it's UB to call `.get_unchecked(..len + 1)`, + /// `.get_unchecked(..=len)`, or similar. + /// + /// [`get`]: slice::get + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ``` + /// let x = &[1, 2, 4]; + /// + /// unsafe { + /// assert_eq!(x.get_unchecked(1), &2); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[must_use] + pub unsafe fn get_unchecked(&self, index: I) -> &I::Output + where + I: SliceIndex, + { + // SAFETY: the caller must uphold most of the safety requirements for `get_unchecked`; + // the slice is dereferenceable because `self` is a safe reference. + // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. + unsafe { &*index.get_unchecked(self) } + } + + /// Returns a mutable reference to an element or subslice, without doing + /// bounds checking. + /// + /// For a safe alternative see [`get_mut`]. + /// + /// # Safety + /// + /// Calling this method with an out-of-bounds index is *[undefined behavior]* + /// even if the resulting reference is not used. + /// + /// You can think of this like `.get_mut(index).unwrap_unchecked()`. It's + /// UB to call `.get_unchecked_mut(len)`, even if you immediately convert + /// to a pointer. And it's UB to call `.get_unchecked_mut(..len + 1)`, + /// `.get_unchecked_mut(..=len)`, or similar. + /// + /// [`get_mut`]: slice::get_mut + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ``` + /// let x = &mut [1, 2, 4]; + /// + /// unsafe { + /// let elem = x.get_unchecked_mut(1); + /// *elem = 13; + /// } + /// assert_eq!(x, &[1, 13, 4]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[must_use] + pub unsafe fn get_unchecked_mut(&mut self, index: I) -> &mut I::Output + where + I: SliceIndex, + { + // SAFETY: the caller must uphold the safety requirements for `get_unchecked_mut`; + // the slice is dereferenceable because `self` is a safe reference. + // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. + unsafe { &mut *index.get_unchecked_mut(self) } + } + + /// Returns a raw pointer to the slice's buffer. + /// + /// The caller must ensure that the slice outlives the pointer this + /// function returns, or else it will end up dangling. + /// + /// The caller must also ensure that the memory the pointer (non-transitively) points to + /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer + /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. + /// + /// Modifying the container referenced by this slice may cause its buffer + /// to be reallocated, which would also make any pointers to it invalid. + /// + /// # Examples + /// + /// ``` + /// let x = &[1, 2, 4]; + /// let x_ptr = x.as_ptr(); + /// + /// unsafe { + /// for i in 0..x.len() { + /// assert_eq!(x.get_unchecked(i), &*x_ptr.add(i)); + /// } + /// } + /// ``` + /// + /// [`as_mut_ptr`]: slice::as_mut_ptr + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")] + #[rustc_never_returns_null_ptr] + #[rustc_as_ptr] + #[inline(always)] + #[must_use] + pub const fn as_ptr(&self) -> *const T { + self as *const [T] as *const T + } + + /// Returns an unsafe mutable pointer to the slice's buffer. + /// + /// The caller must ensure that the slice outlives the pointer this + /// function returns, or else it will end up dangling. + /// + /// Modifying the container referenced by this slice may cause its buffer + /// to be reallocated, which would also make any pointers to it invalid. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [1, 2, 4]; + /// let x_ptr = x.as_mut_ptr(); + /// + /// unsafe { + /// for i in 0..x.len() { + /// *x_ptr.add(i) += 2; + /// } + /// } + /// assert_eq!(x, &[3, 4, 6]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[rustc_never_returns_null_ptr] + #[rustc_as_ptr] + #[inline(always)] + #[must_use] + pub const fn as_mut_ptr(&mut self) -> *mut T { + self as *mut [T] as *mut T + } + + /// Returns the two raw pointers spanning the slice. + /// + /// The returned range is half-open, which means that the end pointer + /// points *one past* the last element of the slice. This way, an empty + /// slice is represented by two equal pointers, and the difference between + /// the two pointers represents the size of the slice. + /// + /// See [`as_ptr`] for warnings on using these pointers. The end pointer + /// requires extra caution, as it does not point to a valid element in the + /// slice. + /// + /// This function is useful for interacting with foreign interfaces which + /// use two pointers to refer to a range of elements in memory, as is + /// common in C++. + /// + /// It can also be useful to check if a pointer to an element refers to an + /// element of this slice: + /// + /// ``` + /// let a = [1, 2, 3]; + /// let x = &a[1] as *const _; + /// let y = &5 as *const _; + /// + /// assert!(a.as_ptr_range().contains(&x)); + /// assert!(!a.as_ptr_range().contains(&y)); + /// ``` + /// + /// [`as_ptr`]: slice::as_ptr + #[stable(feature = "slice_ptr_range", since = "1.48.0")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[inline] + #[must_use] + pub const fn as_ptr_range(&self) -> Range<*const T> { + let start = self.as_ptr(); + // SAFETY: The `add` here is safe, because: + // + // - Both pointers are part of the same object, as pointing directly + // past the object also counts. + // + // - The size of the slice is never larger than `isize::MAX` bytes, as + // noted here: + // - https://github.com/rust-lang/unsafe-code-guidelines/issues/102#issuecomment-473340447 + // - https://doc.rust-lang.org/reference/behavior-considered-undefined.html + // - https://doc.rust-lang.org/core/slice/fn.from_raw_parts.html#safety + // (This doesn't seem normative yet, but the very same assumption is + // made in many places, including the Index implementation of slices.) + // + // - There is no wrapping around involved, as slices do not wrap past + // the end of the address space. + // + // See the documentation of [`pointer::add`]. + let end = unsafe { start.add(self.len()) }; + start..end + } + + /// Returns the two unsafe mutable pointers spanning the slice. + /// + /// The returned range is half-open, which means that the end pointer + /// points *one past* the last element of the slice. This way, an empty + /// slice is represented by two equal pointers, and the difference between + /// the two pointers represents the size of the slice. + /// + /// See [`as_mut_ptr`] for warnings on using these pointers. The end + /// pointer requires extra caution, as it does not point to a valid element + /// in the slice. + /// + /// This function is useful for interacting with foreign interfaces which + /// use two pointers to refer to a range of elements in memory, as is + /// common in C++. + /// + /// [`as_mut_ptr`]: slice::as_mut_ptr + #[stable(feature = "slice_ptr_range", since = "1.48.0")] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[inline] + #[must_use] + pub const fn as_mut_ptr_range(&mut self) -> Range<*mut T> { + let start = self.as_mut_ptr(); + // SAFETY: See as_ptr_range() above for why `add` here is safe. + let end = unsafe { start.add(self.len()) }; + start..end + } + + /// Gets a reference to the underlying array. + /// + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_array(&self) -> Option<&[T; N]> { + if self.len() == N { + let ptr = self.as_ptr() as *const [T; N]; + + // SAFETY: The underlying array of a slice can be reinterpreted as an actual array `[T; N]` if `N` is not greater than the slice's length. + let me = unsafe { &*ptr }; + Some(me) + } else { + None + } + } + + /// Gets a mutable reference to the slice's underlying array. + /// + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_mut_array(&mut self) -> Option<&mut [T; N]> { + if self.len() == N { + let ptr = self.as_mut_ptr() as *mut [T; N]; + + // SAFETY: The underlying array of a slice can be reinterpreted as an actual array `[T; N]` if `N` is not greater than the slice's length. + let me = unsafe { &mut *ptr }; + Some(me) + } else { + None + } + } + + /// Swaps two elements in the slice. + /// + /// If `a` equals to `b`, it's guaranteed that elements won't change value. + /// + /// # Arguments + /// + /// * a - The index of the first element + /// * b - The index of the second element + /// + /// # Panics + /// + /// Panics if `a` or `b` are out of bounds. + /// + /// # Examples + /// + /// ``` + /// let mut v = ["a", "b", "c", "d", "e"]; + /// v.swap(2, 4); + /// assert!(v == ["a", "b", "e", "d", "c"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_swap", issue = "83163")] + #[inline] + #[track_caller] + pub const fn swap(&mut self, a: usize, b: usize) { + // FIXME: use swap_unchecked here (https://github.com/rust-lang/rust/pull/88540#issuecomment-944344343) + // Can't take two mutable loans from one vector, so instead use raw pointers. + let pa = &raw mut self[a]; + let pb = &raw mut self[b]; + // SAFETY: `pa` and `pb` have been created from safe mutable references and refer + // to elements in the slice and therefore are guaranteed to be valid and aligned. + // Note that accessing the elements behind `a` and `b` is checked and will + // panic when out of bounds. + unsafe { + ptr::swap(pa, pb); + } + } + + /// Swaps two elements in the slice, without doing bounds checking. + /// + /// For a safe alternative see [`swap`]. + /// + /// # Arguments + /// + /// * a - The index of the first element + /// * b - The index of the second element + /// + /// # Safety + /// + /// Calling this method with an out-of-bounds index is *[undefined behavior]*. + /// The caller has to ensure that `a < self.len()` and `b < self.len()`. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_swap_unchecked)] + /// + /// let mut v = ["a", "b", "c", "d"]; + /// // SAFETY: we know that 1 and 3 are both indices of the slice + /// unsafe { v.swap_unchecked(1, 3) }; + /// assert!(v == ["a", "d", "c", "b"]); + /// ``` + /// + /// [`swap`]: slice::swap + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + #[unstable(feature = "slice_swap_unchecked", issue = "88539")] + #[rustc_const_unstable(feature = "slice_swap_unchecked", issue = "88539")] + pub const unsafe fn swap_unchecked(&mut self, a: usize, b: usize) { + assert_unsafe_precondition!( + check_library_ub, + "slice::swap_unchecked requires that the indices are within the slice", + ( + len: usize = self.len(), + a: usize = a, + b: usize = b, + ) => a < len && b < len, + ); + + let ptr = self.as_mut_ptr(); + // SAFETY: caller has to guarantee that `a < self.len()` and `b < self.len()` + unsafe { + ptr::swap(ptr.add(a), ptr.add(b)); + } + } + + /// Reverses the order of elements in the slice, in place. + /// + /// # Examples + /// + /// ``` + /// let mut v = [1, 2, 3]; + /// v.reverse(); + /// assert!(v == [3, 2, 1]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn reverse(&mut self) { + let half_len = self.len() / 2; + let Range { start, end } = self.as_mut_ptr_range(); + + // These slices will skip the middle item for an odd length, + // since that one doesn't need to move. + let (front_half, back_half) = + // SAFETY: Both are subparts of the original slice, so the memory + // range is valid, and they don't overlap because they're each only + // half (or less) of the original slice. + unsafe { + ( + slice::from_raw_parts_mut(start, half_len), + slice::from_raw_parts_mut(end.sub(half_len), half_len), + ) + }; + + // Introducing a function boundary here means that the two halves + // get `noalias` markers, allowing better optimization as LLVM + // knows that they're disjoint, unlike in the original slice. + revswap(front_half, back_half, half_len); + + #[inline] + fn revswap(a: &mut [T], b: &mut [T], n: usize) { + debug_assert!(a.len() == n); + debug_assert!(b.len() == n); + + // Because this function is first compiled in isolation, + // this check tells LLVM that the indexing below is + // in-bounds. Then after inlining -- once the actual + // lengths of the slices are known -- it's removed. + let (a, b) = (&mut a[..n], &mut b[..n]); + + let mut i = 0; + while i < n { + mem::swap(&mut a[i], &mut b[n - 1 - i]); + i += 1; + } + } + } + + /// Returns an iterator over the slice. + /// + /// The iterator yields all items from start to end. + /// + /// # Examples + /// + /// ``` + /// let x = &[1, 2, 4]; + /// let mut iterator = x.iter(); + /// + /// assert_eq!(iterator.next(), Some(&1)); + /// assert_eq!(iterator.next(), Some(&2)); + /// assert_eq!(iterator.next(), Some(&4)); + /// assert_eq!(iterator.next(), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg_attr(not(test), rustc_diagnostic_item = "slice_iter")] + pub fn iter(&self) -> Iter<'_, T> { + Iter::new(self) + } + + /// Returns an iterator that allows modifying each value. + /// + /// The iterator yields all items from start to end. + /// + /// # Examples + /// + /// ``` + /// let x = &mut [1, 2, 4]; + /// for elem in x.iter_mut() { + /// *elem += 2; + /// } + /// assert_eq!(x, &[3, 4, 6]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn iter_mut(&mut self) -> IterMut<'_, T> { + IterMut::new(self) + } + + /// Returns an iterator over all contiguous windows of length + /// `size`. The windows overlap. If the slice is shorter than + /// `size`, the iterator returns no values. + /// + /// # Panics + /// + /// Panics if `size` is zero. + /// + /// # Examples + /// + /// ``` + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.windows(3); + /// assert_eq!(iter.next().unwrap(), &['l', 'o', 'r']); + /// assert_eq!(iter.next().unwrap(), &['o', 'r', 'e']); + /// assert_eq!(iter.next().unwrap(), &['r', 'e', 'm']); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// If the slice is shorter than `size`: + /// + /// ``` + /// let slice = ['f', 'o', 'o']; + /// let mut iter = slice.windows(4); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// There's no `windows_mut`, as that existing would let safe code violate the + /// "only one `&mut` at a time to the same thing" rule. However, you can sometimes + /// use [`Cell::as_slice_of_cells`](crate::cell::Cell::as_slice_of_cells) in + /// conjunction with `windows` to accomplish something similar: + /// ``` + /// use std::cell::Cell; + /// + /// let mut array = ['R', 'u', 's', 't', ' ', '2', '0', '1', '5']; + /// let slice = &mut array[..]; + /// let slice_of_cells: &[Cell] = Cell::from_mut(slice).as_slice_of_cells(); + /// for w in slice_of_cells.windows(3) { + /// Cell::swap(&w[0], &w[2]); + /// } + /// assert_eq!(array, ['s', 't', ' ', '2', '0', '1', '5', 'u', 'R']); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[track_caller] + pub fn windows(&self, size: usize) -> Windows<'_, T> { + let size = NonZero::new(size).expect("window size must be non-zero"); + Windows::new(self, size) + } + + /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the + /// beginning of the slice. + /// + /// The chunks are slices and do not overlap. If `chunk_size` does not divide the length of the + /// slice, then the last chunk will not have length `chunk_size`. + /// + /// See [`chunks_exact`] for a variant of this iterator that returns chunks of always exactly + /// `chunk_size` elements, and [`rchunks`] for the same iterator but starting at the end of the + /// slice. + /// + /// # Panics + /// + /// Panics if `chunk_size` is zero. + /// + /// # Examples + /// + /// ``` + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.chunks(2); + /// assert_eq!(iter.next().unwrap(), &['l', 'o']); + /// assert_eq!(iter.next().unwrap(), &['r', 'e']); + /// assert_eq!(iter.next().unwrap(), &['m']); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// [`chunks_exact`]: slice::chunks_exact + /// [`rchunks`]: slice::rchunks + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[track_caller] + pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> { + assert!(chunk_size != 0, "chunk size must be non-zero"); + Chunks::new(self, chunk_size) + } + + /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the + /// beginning of the slice. + /// + /// The chunks are mutable slices, and do not overlap. If `chunk_size` does not divide the + /// length of the slice, then the last chunk will not have length `chunk_size`. + /// + /// See [`chunks_exact_mut`] for a variant of this iterator that returns chunks of always + /// exactly `chunk_size` elements, and [`rchunks_mut`] for the same iterator but starting at + /// the end of the slice. + /// + /// # Panics + /// + /// Panics if `chunk_size` is zero. + /// + /// # Examples + /// + /// ``` + /// let v = &mut [0, 0, 0, 0, 0]; + /// let mut count = 1; + /// + /// for chunk in v.chunks_mut(2) { + /// for elem in chunk.iter_mut() { + /// *elem += count; + /// } + /// count += 1; + /// } + /// assert_eq!(v, &[1, 1, 2, 2, 3]); + /// ``` + /// + /// [`chunks_exact_mut`]: slice::chunks_exact_mut + /// [`rchunks_mut`]: slice::rchunks_mut + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[track_caller] + pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> { + assert!(chunk_size != 0, "chunk size must be non-zero"); + ChunksMut::new(self, chunk_size) + } + + /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the + /// beginning of the slice. + /// + /// The chunks are slices and do not overlap. If `chunk_size` does not divide the length of the + /// slice, then the last up to `chunk_size-1` elements will be omitted and can be retrieved + /// from the `remainder` function of the iterator. + /// + /// Due to each chunk having exactly `chunk_size` elements, the compiler can often optimize the + /// resulting code better than in the case of [`chunks`]. + /// + /// See [`chunks`] for a variant of this iterator that also returns the remainder as a smaller + /// chunk, and [`rchunks_exact`] for the same iterator but starting at the end of the slice. + /// + /// # Panics + /// + /// Panics if `chunk_size` is zero. + /// + /// # Examples + /// + /// ``` + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.chunks_exact(2); + /// assert_eq!(iter.next().unwrap(), &['l', 'o']); + /// assert_eq!(iter.next().unwrap(), &['r', 'e']); + /// assert!(iter.next().is_none()); + /// assert_eq!(iter.remainder(), &['m']); + /// ``` + /// + /// [`chunks`]: slice::chunks + /// [`rchunks_exact`]: slice::rchunks_exact + #[stable(feature = "chunks_exact", since = "1.31.0")] + #[inline] + #[track_caller] + pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> { + assert!(chunk_size != 0, "chunk size must be non-zero"); + ChunksExact::new(self, chunk_size) + } + + /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the + /// beginning of the slice. + /// + /// The chunks are mutable slices, and do not overlap. If `chunk_size` does not divide the + /// length of the slice, then the last up to `chunk_size-1` elements will be omitted and can be + /// retrieved from the `into_remainder` function of the iterator. + /// + /// Due to each chunk having exactly `chunk_size` elements, the compiler can often optimize the + /// resulting code better than in the case of [`chunks_mut`]. + /// + /// See [`chunks_mut`] for a variant of this iterator that also returns the remainder as a + /// smaller chunk, and [`rchunks_exact_mut`] for the same iterator but starting at the end of + /// the slice. + /// + /// # Panics + /// + /// Panics if `chunk_size` is zero. + /// + /// # Examples + /// + /// ``` + /// let v = &mut [0, 0, 0, 0, 0]; + /// let mut count = 1; + /// + /// for chunk in v.chunks_exact_mut(2) { + /// for elem in chunk.iter_mut() { + /// *elem += count; + /// } + /// count += 1; + /// } + /// assert_eq!(v, &[1, 1, 2, 2, 0]); + /// ``` + /// + /// [`chunks_mut`]: slice::chunks_mut + /// [`rchunks_exact_mut`]: slice::rchunks_exact_mut + #[stable(feature = "chunks_exact", since = "1.31.0")] + #[inline] + #[track_caller] + pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> { + assert!(chunk_size != 0, "chunk size must be non-zero"); + ChunksExactMut::new(self, chunk_size) + } + + /// Splits the slice into a slice of `N`-element arrays, + /// assuming that there's no remainder. + /// + /// # Safety + /// + /// This may only be called when + /// - The slice splits exactly into `N`-element chunks (aka `self.len() % N == 0`). + /// - `N != 0`. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_as_chunks)] + /// let slice: &[char] = &['l', 'o', 'r', 'e', 'm', '!']; + /// let chunks: &[[char; 1]] = + /// // SAFETY: 1-element chunks never have remainder + /// unsafe { slice.as_chunks_unchecked() }; + /// assert_eq!(chunks, &[['l'], ['o'], ['r'], ['e'], ['m'], ['!']]); + /// let chunks: &[[char; 3]] = + /// // SAFETY: The slice length (6) is a multiple of 3 + /// unsafe { slice.as_chunks_unchecked() }; + /// assert_eq!(chunks, &[['l', 'o', 'r'], ['e', 'm', '!']]); + /// + /// // These would be unsound: + /// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked() // The slice length is not a multiple of 5 + /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked() // Zero-length chunks are never allowed + /// ``` + #[unstable(feature = "slice_as_chunks", issue = "74985")] + #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")] + #[inline] + #[must_use] + pub const unsafe fn as_chunks_unchecked(&self) -> &[[T; N]] { + assert_unsafe_precondition!( + check_language_ub, + "slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks", + (n: usize = N, len: usize = self.len()) => n != 0 && len % n == 0, + ); + // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length + let new_len = unsafe { exact_div(self.len(), N) }; + // SAFETY: We cast a slice of `new_len * N` elements into + // a slice of `new_len` many `N` elements chunks. + unsafe { from_raw_parts(self.as_ptr().cast(), new_len) } + } + + /// Splits the slice into a slice of `N`-element arrays, + /// starting at the beginning of the slice, + /// and a remainder slice with length strictly less than `N`. + /// + /// # Panics + /// + /// Panics if `N` is zero. This check will most probably get changed to a compile time + /// error before this method gets stabilized. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_as_chunks)] + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let (chunks, remainder) = slice.as_chunks(); + /// assert_eq!(chunks, &[['l', 'o'], ['r', 'e']]); + /// assert_eq!(remainder, &['m']); + /// ``` + /// + /// If you expect the slice to be an exact multiple, you can combine + /// `let`-`else` with an empty slice pattern: + /// ``` + /// #![feature(slice_as_chunks)] + /// let slice = ['R', 'u', 's', 't']; + /// let (chunks, []) = slice.as_chunks::<2>() else { + /// panic!("slice didn't have even length") + /// }; + /// assert_eq!(chunks, &[['R', 'u'], ['s', 't']]); + /// ``` + #[unstable(feature = "slice_as_chunks", issue = "74985")] + #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")] + #[inline] + #[track_caller] + #[must_use] + pub const fn as_chunks(&self) -> (&[[T; N]], &[T]) { + assert!(N != 0, "chunk size must be non-zero"); + let len_rounded_down = self.len() / N * N; + // SAFETY: The rounded-down value is always the same or smaller than the + // original length, and thus must be in-bounds of the slice. + let (multiple_of_n, remainder) = unsafe { self.split_at_unchecked(len_rounded_down) }; + // SAFETY: We already panicked for zero, and ensured by construction + // that the length of the subslice is a multiple of N. + let array_slice = unsafe { multiple_of_n.as_chunks_unchecked() }; + (array_slice, remainder) + } + + /// Splits the slice into a slice of `N`-element arrays, + /// starting at the end of the slice, + /// and a remainder slice with length strictly less than `N`. + /// + /// # Panics + /// + /// Panics if `N` is zero. This check will most probably get changed to a compile time + /// error before this method gets stabilized. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_as_chunks)] + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let (remainder, chunks) = slice.as_rchunks(); + /// assert_eq!(remainder, &['l']); + /// assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]); + /// ``` + #[unstable(feature = "slice_as_chunks", issue = "74985")] + #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")] + #[inline] + #[track_caller] + #[must_use] + pub const fn as_rchunks(&self) -> (&[T], &[[T; N]]) { + assert!(N != 0, "chunk size must be non-zero"); + let len = self.len() / N; + let (remainder, multiple_of_n) = self.split_at(self.len() - len * N); + // SAFETY: We already panicked for zero, and ensured by construction + // that the length of the subslice is a multiple of N. + let array_slice = unsafe { multiple_of_n.as_chunks_unchecked() }; + (remainder, array_slice) + } + + /// Returns an iterator over `N` elements of the slice at a time, starting at the + /// beginning of the slice. + /// + /// The chunks are array references and do not overlap. If `N` does not divide the + /// length of the slice, then the last up to `N-1` elements will be omitted and can be + /// retrieved from the `remainder` function of the iterator. + /// + /// This method is the const generic equivalent of [`chunks_exact`]. + /// + /// # Panics + /// + /// Panics if `N` is zero. This check will most probably get changed to a compile time + /// error before this method gets stabilized. + /// + /// # Examples + /// + /// ``` + /// #![feature(array_chunks)] + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.array_chunks(); + /// assert_eq!(iter.next().unwrap(), &['l', 'o']); + /// assert_eq!(iter.next().unwrap(), &['r', 'e']); + /// assert!(iter.next().is_none()); + /// assert_eq!(iter.remainder(), &['m']); + /// ``` + /// + /// [`chunks_exact`]: slice::chunks_exact + #[unstable(feature = "array_chunks", issue = "74985")] + #[inline] + #[track_caller] + pub fn array_chunks(&self) -> ArrayChunks<'_, T, N> { + assert!(N != 0, "chunk size must be non-zero"); + ArrayChunks::new(self) + } + + /// Splits the slice into a slice of `N`-element arrays, + /// assuming that there's no remainder. + /// + /// # Safety + /// + /// This may only be called when + /// - The slice splits exactly into `N`-element chunks (aka `self.len() % N == 0`). + /// - `N != 0`. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_as_chunks)] + /// let slice: &mut [char] = &mut ['l', 'o', 'r', 'e', 'm', '!']; + /// let chunks: &mut [[char; 1]] = + /// // SAFETY: 1-element chunks never have remainder + /// unsafe { slice.as_chunks_unchecked_mut() }; + /// chunks[0] = ['L']; + /// assert_eq!(chunks, &[['L'], ['o'], ['r'], ['e'], ['m'], ['!']]); + /// let chunks: &mut [[char; 3]] = + /// // SAFETY: The slice length (6) is a multiple of 3 + /// unsafe { slice.as_chunks_unchecked_mut() }; + /// chunks[1] = ['a', 'x', '?']; + /// assert_eq!(slice, &['L', 'o', 'r', 'a', 'x', '?']); + /// + /// // These would be unsound: + /// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked_mut() // The slice length is not a multiple of 5 + /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked_mut() // Zero-length chunks are never allowed + /// ``` + #[unstable(feature = "slice_as_chunks", issue = "74985")] + #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")] + #[inline] + #[must_use] + pub const unsafe fn as_chunks_unchecked_mut(&mut self) -> &mut [[T; N]] { + assert_unsafe_precondition!( + check_language_ub, + "slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks", + (n: usize = N, len: usize = self.len()) => n != 0 && len % n == 0 + ); + // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length + let new_len = unsafe { exact_div(self.len(), N) }; + // SAFETY: We cast a slice of `new_len * N` elements into + // a slice of `new_len` many `N` elements chunks. + unsafe { from_raw_parts_mut(self.as_mut_ptr().cast(), new_len) } + } + + /// Splits the slice into a slice of `N`-element arrays, + /// starting at the beginning of the slice, + /// and a remainder slice with length strictly less than `N`. + /// + /// # Panics + /// + /// Panics if `N` is zero. This check will most probably get changed to a compile time + /// error before this method gets stabilized. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_as_chunks)] + /// let v = &mut [0, 0, 0, 0, 0]; + /// let mut count = 1; + /// + /// let (chunks, remainder) = v.as_chunks_mut(); + /// remainder[0] = 9; + /// for chunk in chunks { + /// *chunk = [count; 2]; + /// count += 1; + /// } + /// assert_eq!(v, &[1, 1, 2, 2, 9]); + /// ``` + #[unstable(feature = "slice_as_chunks", issue = "74985")] + #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")] + #[inline] + #[track_caller] + #[must_use] + pub const fn as_chunks_mut(&mut self) -> (&mut [[T; N]], &mut [T]) { + assert!(N != 0, "chunk size must be non-zero"); + let len_rounded_down = self.len() / N * N; + // SAFETY: The rounded-down value is always the same or smaller than the + // original length, and thus must be in-bounds of the slice. + let (multiple_of_n, remainder) = unsafe { self.split_at_mut_unchecked(len_rounded_down) }; + // SAFETY: We already panicked for zero, and ensured by construction + // that the length of the subslice is a multiple of N. + let array_slice = unsafe { multiple_of_n.as_chunks_unchecked_mut() }; + (array_slice, remainder) + } + + /// Splits the slice into a slice of `N`-element arrays, + /// starting at the end of the slice, + /// and a remainder slice with length strictly less than `N`. + /// + /// # Panics + /// + /// Panics if `N` is zero. This check will most probably get changed to a compile time + /// error before this method gets stabilized. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_as_chunks)] + /// let v = &mut [0, 0, 0, 0, 0]; + /// let mut count = 1; + /// + /// let (remainder, chunks) = v.as_rchunks_mut(); + /// remainder[0] = 9; + /// for chunk in chunks { + /// *chunk = [count; 2]; + /// count += 1; + /// } + /// assert_eq!(v, &[9, 1, 1, 2, 2]); + /// ``` + #[unstable(feature = "slice_as_chunks", issue = "74985")] + #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")] + #[inline] + #[track_caller] + #[must_use] + pub const fn as_rchunks_mut(&mut self) -> (&mut [T], &mut [[T; N]]) { + assert!(N != 0, "chunk size must be non-zero"); + let len = self.len() / N; + let (remainder, multiple_of_n) = self.split_at_mut(self.len() - len * N); + // SAFETY: We already panicked for zero, and ensured by construction + // that the length of the subslice is a multiple of N. + let array_slice = unsafe { multiple_of_n.as_chunks_unchecked_mut() }; + (remainder, array_slice) + } + + /// Returns an iterator over `N` elements of the slice at a time, starting at the + /// beginning of the slice. + /// + /// The chunks are mutable array references and do not overlap. If `N` does not divide + /// the length of the slice, then the last up to `N-1` elements will be omitted and + /// can be retrieved from the `into_remainder` function of the iterator. + /// + /// This method is the const generic equivalent of [`chunks_exact_mut`]. + /// + /// # Panics + /// + /// Panics if `N` is zero. This check will most probably get changed to a compile time + /// error before this method gets stabilized. + /// + /// # Examples + /// + /// ``` + /// #![feature(array_chunks)] + /// let v = &mut [0, 0, 0, 0, 0]; + /// let mut count = 1; + /// + /// for chunk in v.array_chunks_mut() { + /// *chunk = [count; 2]; + /// count += 1; + /// } + /// assert_eq!(v, &[1, 1, 2, 2, 0]); + /// ``` + /// + /// [`chunks_exact_mut`]: slice::chunks_exact_mut + #[unstable(feature = "array_chunks", issue = "74985")] + #[inline] + #[track_caller] + pub fn array_chunks_mut(&mut self) -> ArrayChunksMut<'_, T, N> { + assert!(N != 0, "chunk size must be non-zero"); + ArrayChunksMut::new(self) + } + + /// Returns an iterator over overlapping windows of `N` elements of a slice, + /// starting at the beginning of the slice. + /// + /// This is the const generic equivalent of [`windows`]. + /// + /// If `N` is greater than the size of the slice, it will return no windows. + /// + /// # Panics + /// + /// Panics if `N` is zero. This check will most probably get changed to a compile time + /// error before this method gets stabilized. + /// + /// # Examples + /// + /// ``` + /// #![feature(array_windows)] + /// let slice = [0, 1, 2, 3]; + /// let mut iter = slice.array_windows(); + /// assert_eq!(iter.next().unwrap(), &[0, 1]); + /// assert_eq!(iter.next().unwrap(), &[1, 2]); + /// assert_eq!(iter.next().unwrap(), &[2, 3]); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// [`windows`]: slice::windows + #[unstable(feature = "array_windows", issue = "75027")] + #[inline] + #[track_caller] + pub fn array_windows(&self) -> ArrayWindows<'_, T, N> { + assert!(N != 0, "window size must be non-zero"); + ArrayWindows::new(self) + } + + /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the end + /// of the slice. + /// + /// The chunks are slices and do not overlap. If `chunk_size` does not divide the length of the + /// slice, then the last chunk will not have length `chunk_size`. + /// + /// See [`rchunks_exact`] for a variant of this iterator that returns chunks of always exactly + /// `chunk_size` elements, and [`chunks`] for the same iterator but starting at the beginning + /// of the slice. + /// + /// # Panics + /// + /// Panics if `chunk_size` is zero. + /// + /// # Examples + /// + /// ``` + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.rchunks(2); + /// assert_eq!(iter.next().unwrap(), &['e', 'm']); + /// assert_eq!(iter.next().unwrap(), &['o', 'r']); + /// assert_eq!(iter.next().unwrap(), &['l']); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// [`rchunks_exact`]: slice::rchunks_exact + /// [`chunks`]: slice::chunks + #[stable(feature = "rchunks", since = "1.31.0")] + #[inline] + #[track_caller] + pub fn rchunks(&self, chunk_size: usize) -> RChunks<'_, T> { + assert!(chunk_size != 0, "chunk size must be non-zero"); + RChunks::new(self, chunk_size) + } + + /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the end + /// of the slice. + /// + /// The chunks are mutable slices, and do not overlap. If `chunk_size` does not divide the + /// length of the slice, then the last chunk will not have length `chunk_size`. + /// + /// See [`rchunks_exact_mut`] for a variant of this iterator that returns chunks of always + /// exactly `chunk_size` elements, and [`chunks_mut`] for the same iterator but starting at the + /// beginning of the slice. + /// + /// # Panics + /// + /// Panics if `chunk_size` is zero. + /// + /// # Examples + /// + /// ``` + /// let v = &mut [0, 0, 0, 0, 0]; + /// let mut count = 1; + /// + /// for chunk in v.rchunks_mut(2) { + /// for elem in chunk.iter_mut() { + /// *elem += count; + /// } + /// count += 1; + /// } + /// assert_eq!(v, &[3, 2, 2, 1, 1]); + /// ``` + /// + /// [`rchunks_exact_mut`]: slice::rchunks_exact_mut + /// [`chunks_mut`]: slice::chunks_mut + #[stable(feature = "rchunks", since = "1.31.0")] + #[inline] + #[track_caller] + pub fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<'_, T> { + assert!(chunk_size != 0, "chunk size must be non-zero"); + RChunksMut::new(self, chunk_size) + } + + /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the + /// end of the slice. + /// + /// The chunks are slices and do not overlap. If `chunk_size` does not divide the length of the + /// slice, then the last up to `chunk_size-1` elements will be omitted and can be retrieved + /// from the `remainder` function of the iterator. + /// + /// Due to each chunk having exactly `chunk_size` elements, the compiler can often optimize the + /// resulting code better than in the case of [`rchunks`]. + /// + /// See [`rchunks`] for a variant of this iterator that also returns the remainder as a smaller + /// chunk, and [`chunks_exact`] for the same iterator but starting at the beginning of the + /// slice. + /// + /// # Panics + /// + /// Panics if `chunk_size` is zero. + /// + /// # Examples + /// + /// ``` + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.rchunks_exact(2); + /// assert_eq!(iter.next().unwrap(), &['e', 'm']); + /// assert_eq!(iter.next().unwrap(), &['o', 'r']); + /// assert!(iter.next().is_none()); + /// assert_eq!(iter.remainder(), &['l']); + /// ``` + /// + /// [`chunks`]: slice::chunks + /// [`rchunks`]: slice::rchunks + /// [`chunks_exact`]: slice::chunks_exact + #[stable(feature = "rchunks", since = "1.31.0")] + #[inline] + #[track_caller] + pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T> { + assert!(chunk_size != 0, "chunk size must be non-zero"); + RChunksExact::new(self, chunk_size) + } + + /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the end + /// of the slice. + /// + /// The chunks are mutable slices, and do not overlap. If `chunk_size` does not divide the + /// length of the slice, then the last up to `chunk_size-1` elements will be omitted and can be + /// retrieved from the `into_remainder` function of the iterator. + /// + /// Due to each chunk having exactly `chunk_size` elements, the compiler can often optimize the + /// resulting code better than in the case of [`chunks_mut`]. + /// + /// See [`rchunks_mut`] for a variant of this iterator that also returns the remainder as a + /// smaller chunk, and [`chunks_exact_mut`] for the same iterator but starting at the beginning + /// of the slice. + /// + /// # Panics + /// + /// Panics if `chunk_size` is zero. + /// + /// # Examples + /// + /// ``` + /// let v = &mut [0, 0, 0, 0, 0]; + /// let mut count = 1; + /// + /// for chunk in v.rchunks_exact_mut(2) { + /// for elem in chunk.iter_mut() { + /// *elem += count; + /// } + /// count += 1; + /// } + /// assert_eq!(v, &[0, 2, 2, 1, 1]); + /// ``` + /// + /// [`chunks_mut`]: slice::chunks_mut + /// [`rchunks_mut`]: slice::rchunks_mut + /// [`chunks_exact_mut`]: slice::chunks_exact_mut + #[stable(feature = "rchunks", since = "1.31.0")] + #[inline] + #[track_caller] + pub fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T> { + assert!(chunk_size != 0, "chunk size must be non-zero"); + RChunksExactMut::new(self, chunk_size) + } + + /// Returns an iterator over the slice producing non-overlapping runs + /// of elements using the predicate to separate them. + /// + /// The predicate is called for every pair of consecutive elements, + /// meaning that it is called on `slice[0]` and `slice[1]`, + /// followed by `slice[1]` and `slice[2]`, and so on. + /// + /// # Examples + /// + /// ``` + /// let slice = &[1, 1, 1, 3, 3, 2, 2, 2]; + /// + /// let mut iter = slice.chunk_by(|a, b| a == b); + /// + /// assert_eq!(iter.next(), Some(&[1, 1, 1][..])); + /// assert_eq!(iter.next(), Some(&[3, 3][..])); + /// assert_eq!(iter.next(), Some(&[2, 2, 2][..])); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// This method can be used to extract the sorted subslices: + /// + /// ``` + /// let slice = &[1, 1, 2, 3, 2, 3, 2, 3, 4]; + /// + /// let mut iter = slice.chunk_by(|a, b| a <= b); + /// + /// assert_eq!(iter.next(), Some(&[1, 1, 2, 3][..])); + /// assert_eq!(iter.next(), Some(&[2, 3][..])); + /// assert_eq!(iter.next(), Some(&[2, 3, 4][..])); + /// assert_eq!(iter.next(), None); + /// ``` + #[stable(feature = "slice_group_by", since = "1.77.0")] + #[inline] + pub fn chunk_by(&self, pred: F) -> ChunkBy<'_, T, F> + where + F: FnMut(&T, &T) -> bool, + { + ChunkBy::new(self, pred) + } + + /// Returns an iterator over the slice producing non-overlapping mutable + /// runs of elements using the predicate to separate them. + /// + /// The predicate is called for every pair of consecutive elements, + /// meaning that it is called on `slice[0]` and `slice[1]`, + /// followed by `slice[1]` and `slice[2]`, and so on. + /// + /// # Examples + /// + /// ``` + /// let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2]; + /// + /// let mut iter = slice.chunk_by_mut(|a, b| a == b); + /// + /// assert_eq!(iter.next(), Some(&mut [1, 1, 1][..])); + /// assert_eq!(iter.next(), Some(&mut [3, 3][..])); + /// assert_eq!(iter.next(), Some(&mut [2, 2, 2][..])); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// This method can be used to extract the sorted subslices: + /// + /// ``` + /// let slice = &mut [1, 1, 2, 3, 2, 3, 2, 3, 4]; + /// + /// let mut iter = slice.chunk_by_mut(|a, b| a <= b); + /// + /// assert_eq!(iter.next(), Some(&mut [1, 1, 2, 3][..])); + /// assert_eq!(iter.next(), Some(&mut [2, 3][..])); + /// assert_eq!(iter.next(), Some(&mut [2, 3, 4][..])); + /// assert_eq!(iter.next(), None); + /// ``` + #[stable(feature = "slice_group_by", since = "1.77.0")] + #[inline] + pub fn chunk_by_mut(&mut self, pred: F) -> ChunkByMut<'_, T, F> + where + F: FnMut(&T, &T) -> bool, + { + ChunkByMut::new(self, pred) + } + + /// Divides one slice into two at an index. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// # Panics + /// + /// Panics if `mid > len`. For a non-panicking alternative see + /// [`split_at_checked`](slice::split_at_checked). + /// + /// # Examples + /// + /// ``` + /// let v = [1, 2, 3, 4, 5, 6]; + /// + /// { + /// let (left, right) = v.split_at(0); + /// assert_eq!(left, []); + /// assert_eq!(right, [1, 2, 3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_at(2); + /// assert_eq!(left, [1, 2]); + /// assert_eq!(right, [3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_at(6); + /// assert_eq!(left, [1, 2, 3, 4, 5, 6]); + /// assert_eq!(right, []); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_slice_split_at_not_mut", since = "1.71.0")] + #[inline] + #[track_caller] + #[must_use] + pub const fn split_at(&self, mid: usize) -> (&[T], &[T]) { + match self.split_at_checked(mid) { + Some(pair) => pair, + None => panic!("mid > len"), + } + } + + /// Divides one mutable slice into two at an index. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// # Panics + /// + /// Panics if `mid > len`. For a non-panicking alternative see + /// [`split_at_mut_checked`](slice::split_at_mut_checked). + /// + /// # Examples + /// + /// ``` + /// let mut v = [1, 0, 3, 0, 5, 6]; + /// let (left, right) = v.split_at_mut(2); + /// assert_eq!(left, [1, 0]); + /// assert_eq!(right, [3, 0, 5, 6]); + /// left[1] = 2; + /// right[1] = 4; + /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[track_caller] + #[must_use] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] + pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + match self.split_at_mut_checked(mid) { + Some(pair) => pair, + None => panic!("mid > len"), + } + } + + /// Divides one slice into two at an index, without doing bounds checking. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// For a safe alternative see [`split_at`]. + /// + /// # Safety + /// + /// Calling this method with an out-of-bounds index is *[undefined behavior]* + /// even if the resulting reference is not used. The caller has to ensure that + /// `0 <= mid <= self.len()`. + /// + /// [`split_at`]: slice::split_at + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ``` + /// let v = [1, 2, 3, 4, 5, 6]; + /// + /// unsafe { + /// let (left, right) = v.split_at_unchecked(0); + /// assert_eq!(left, []); + /// assert_eq!(right, [1, 2, 3, 4, 5, 6]); + /// } + /// + /// unsafe { + /// let (left, right) = v.split_at_unchecked(2); + /// assert_eq!(left, [1, 2]); + /// assert_eq!(right, [3, 4, 5, 6]); + /// } + /// + /// unsafe { + /// let (left, right) = v.split_at_unchecked(6); + /// assert_eq!(left, [1, 2, 3, 4, 5, 6]); + /// assert_eq!(right, []); + /// } + /// ``` + #[stable(feature = "slice_split_at_unchecked", since = "1.79.0")] + #[rustc_const_stable(feature = "const_slice_split_at_unchecked", since = "1.77.0")] + #[inline] + #[must_use] + pub const unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { + // FIXME(const-hack): the const function `from_raw_parts` is used to make this + // function const; previously the implementation used + // `(self.get_unchecked(..mid), self.get_unchecked(mid..))` + + let len = self.len(); + let ptr = self.as_ptr(); + + assert_unsafe_precondition!( + check_library_ub, + "slice::split_at_unchecked requires the index to be within the slice", + (mid: usize = mid, len: usize = len) => mid <= len, + ); + + // SAFETY: Caller has to check that `0 <= mid <= self.len()` + unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), unchecked_sub(len, mid))) } + } + + /// Divides one mutable slice into two at an index, without doing bounds checking. + /// + /// The first will contain all indices from `[0, mid)` (excluding + /// the index `mid` itself) and the second will contain all + /// indices from `[mid, len)` (excluding the index `len` itself). + /// + /// For a safe alternative see [`split_at_mut`]. + /// + /// # Safety + /// + /// Calling this method with an out-of-bounds index is *[undefined behavior]* + /// even if the resulting reference is not used. The caller has to ensure that + /// `0 <= mid <= self.len()`. + /// + /// [`split_at_mut`]: slice::split_at_mut + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ``` + /// let mut v = [1, 0, 3, 0, 5, 6]; + /// // scoped to restrict the lifetime of the borrows + /// unsafe { + /// let (left, right) = v.split_at_mut_unchecked(2); + /// assert_eq!(left, [1, 0]); + /// assert_eq!(right, [3, 0, 5, 6]); + /// left[1] = 2; + /// right[1] = 4; + /// } + /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); + /// ``` + #[stable(feature = "slice_split_at_unchecked", since = "1.79.0")] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] + #[inline] + #[must_use] + pub const unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + let len = self.len(); + let ptr = self.as_mut_ptr(); + + assert_unsafe_precondition!( + check_library_ub, + "slice::split_at_mut_unchecked requires the index to be within the slice", + (mid: usize = mid, len: usize = len) => mid <= len, + ); + + // SAFETY: Caller has to check that `0 <= mid <= self.len()`. + // + // `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference + // is fine. + unsafe { + ( + from_raw_parts_mut(ptr, mid), + from_raw_parts_mut(ptr.add(mid), unchecked_sub(len, mid)), + ) + } + } + + /// Divides one slice into two at an index, returning `None` if the slice is + /// too short. + /// + /// If `mid ≤ len` returns a pair of slices where the first will contain all + /// indices from `[0, mid)` (excluding the index `mid` itself) and the + /// second will contain all indices from `[mid, len)` (excluding the index + /// `len` itself). + /// + /// Otherwise, if `mid > len`, returns `None`. + /// + /// # Examples + /// + /// ``` + /// let v = [1, -2, 3, -4, 5, -6]; + /// + /// { + /// let (left, right) = v.split_at_checked(0).unwrap(); + /// assert_eq!(left, []); + /// assert_eq!(right, [1, -2, 3, -4, 5, -6]); + /// } + /// + /// { + /// let (left, right) = v.split_at_checked(2).unwrap(); + /// assert_eq!(left, [1, -2]); + /// assert_eq!(right, [3, -4, 5, -6]); + /// } + /// + /// { + /// let (left, right) = v.split_at_checked(6).unwrap(); + /// assert_eq!(left, [1, -2, 3, -4, 5, -6]); + /// assert_eq!(right, []); + /// } + /// + /// assert_eq!(None, v.split_at_checked(7)); + /// ``` + #[stable(feature = "split_at_checked", since = "1.80.0")] + #[rustc_const_stable(feature = "split_at_checked", since = "1.80.0")] + #[inline] + #[must_use] + pub const fn split_at_checked(&self, mid: usize) -> Option<(&[T], &[T])> { + if mid <= self.len() { + // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which + // fulfills the requirements of `split_at_unchecked`. + Some(unsafe { self.split_at_unchecked(mid) }) + } else { + None + } + } + + /// Divides one mutable slice into two at an index, returning `None` if the + /// slice is too short. + /// + /// If `mid ≤ len` returns a pair of slices where the first will contain all + /// indices from `[0, mid)` (excluding the index `mid` itself) and the + /// second will contain all indices from `[mid, len)` (excluding the index + /// `len` itself). + /// + /// Otherwise, if `mid > len`, returns `None`. + /// + /// # Examples + /// + /// ``` + /// let mut v = [1, 0, 3, 0, 5, 6]; + /// + /// if let Some((left, right)) = v.split_at_mut_checked(2) { + /// assert_eq!(left, [1, 0]); + /// assert_eq!(right, [3, 0, 5, 6]); + /// left[1] = 2; + /// right[1] = 4; + /// } + /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); + /// + /// assert_eq!(None, v.split_at_mut_checked(7)); + /// ``` + #[stable(feature = "split_at_checked", since = "1.80.0")] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] + #[inline] + #[must_use] + pub const fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut [T], &mut [T])> { + if mid <= self.len() { + // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which + // fulfills the requirements of `split_at_unchecked`. + Some(unsafe { self.split_at_mut_unchecked(mid) }) + } else { + None + } + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred`. The matched element is not contained in the subslices. + /// + /// # Examples + /// + /// ``` + /// let slice = [10, 40, 33, 20]; + /// let mut iter = slice.split(|num| num % 3 == 0); + /// + /// assert_eq!(iter.next().unwrap(), &[10, 40]); + /// assert_eq!(iter.next().unwrap(), &[20]); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// If the first element is matched, an empty slice will be the first item + /// returned by the iterator. Similarly, if the last element in the slice + /// is matched, an empty slice will be the last item returned by the + /// iterator: + /// + /// ``` + /// let slice = [10, 40, 33]; + /// let mut iter = slice.split(|num| num % 3 == 0); + /// + /// assert_eq!(iter.next().unwrap(), &[10, 40]); + /// assert_eq!(iter.next().unwrap(), &[]); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// If two matched elements are directly adjacent, an empty slice will be + /// present between them: + /// + /// ``` + /// let slice = [10, 6, 33, 20]; + /// let mut iter = slice.split(|num| num % 3 == 0); + /// + /// assert_eq!(iter.next().unwrap(), &[10]); + /// assert_eq!(iter.next().unwrap(), &[]); + /// assert_eq!(iter.next().unwrap(), &[20]); + /// assert!(iter.next().is_none()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split(&self, pred: F) -> Split<'_, T, F> + where + F: FnMut(&T) -> bool, + { + Split::new(self, pred) + } + + /// Returns an iterator over mutable subslices separated by elements that + /// match `pred`. The matched element is not contained in the subslices. + /// + /// # Examples + /// + /// ``` + /// let mut v = [10, 40, 30, 20, 60, 50]; + /// + /// for group in v.split_mut(|num| *num % 3 == 0) { + /// group[0] = 1; + /// } + /// assert_eq!(v, [1, 40, 30, 1, 60, 1]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split_mut(&mut self, pred: F) -> SplitMut<'_, T, F> + where + F: FnMut(&T) -> bool, + { + SplitMut::new(self, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred`. The matched element is contained in the end of the previous + /// subslice as a terminator. + /// + /// # Examples + /// + /// ``` + /// let slice = [10, 40, 33, 20]; + /// let mut iter = slice.split_inclusive(|num| num % 3 == 0); + /// + /// assert_eq!(iter.next().unwrap(), &[10, 40, 33]); + /// assert_eq!(iter.next().unwrap(), &[20]); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// If the last element of the slice is matched, + /// that element will be considered the terminator of the preceding slice. + /// That slice will be the last item returned by the iterator. + /// + /// ``` + /// let slice = [3, 10, 40, 33]; + /// let mut iter = slice.split_inclusive(|num| num % 3 == 0); + /// + /// assert_eq!(iter.next().unwrap(), &[3]); + /// assert_eq!(iter.next().unwrap(), &[10, 40, 33]); + /// assert!(iter.next().is_none()); + /// ``` + #[stable(feature = "split_inclusive", since = "1.51.0")] + #[inline] + pub fn split_inclusive(&self, pred: F) -> SplitInclusive<'_, T, F> + where + F: FnMut(&T) -> bool, + { + SplitInclusive::new(self, pred) + } + + /// Returns an iterator over mutable subslices separated by elements that + /// match `pred`. The matched element is contained in the previous + /// subslice as a terminator. + /// + /// # Examples + /// + /// ``` + /// let mut v = [10, 40, 30, 20, 60, 50]; + /// + /// for group in v.split_inclusive_mut(|num| *num % 3 == 0) { + /// let terminator_idx = group.len()-1; + /// group[terminator_idx] = 1; + /// } + /// assert_eq!(v, [10, 40, 1, 20, 1, 1]); + /// ``` + #[stable(feature = "split_inclusive", since = "1.51.0")] + #[inline] + pub fn split_inclusive_mut(&mut self, pred: F) -> SplitInclusiveMut<'_, T, F> + where + F: FnMut(&T) -> bool, + { + SplitInclusiveMut::new(self, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred`, starting at the end of the slice and working backwards. + /// The matched element is not contained in the subslices. + /// + /// # Examples + /// + /// ``` + /// let slice = [11, 22, 33, 0, 44, 55]; + /// let mut iter = slice.rsplit(|num| *num == 0); + /// + /// assert_eq!(iter.next().unwrap(), &[44, 55]); + /// assert_eq!(iter.next().unwrap(), &[11, 22, 33]); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// As with `split()`, if the first or last element is matched, an empty + /// slice will be the first (or last) item returned by the iterator. + /// + /// ``` + /// let v = &[0, 1, 1, 2, 3, 5, 8]; + /// let mut it = v.rsplit(|n| *n % 2 == 0); + /// assert_eq!(it.next().unwrap(), &[]); + /// assert_eq!(it.next().unwrap(), &[3, 5]); + /// assert_eq!(it.next().unwrap(), &[1, 1]); + /// assert_eq!(it.next().unwrap(), &[]); + /// assert_eq!(it.next(), None); + /// ``` + #[stable(feature = "slice_rsplit", since = "1.27.0")] + #[inline] + pub fn rsplit(&self, pred: F) -> RSplit<'_, T, F> + where + F: FnMut(&T) -> bool, + { + RSplit::new(self, pred) + } + + /// Returns an iterator over mutable subslices separated by elements that + /// match `pred`, starting at the end of the slice and working + /// backwards. The matched element is not contained in the subslices. + /// + /// # Examples + /// + /// ``` + /// let mut v = [100, 400, 300, 200, 600, 500]; + /// + /// let mut count = 0; + /// for group in v.rsplit_mut(|num| *num % 3 == 0) { + /// count += 1; + /// group[0] = count; + /// } + /// assert_eq!(v, [3, 400, 300, 2, 600, 1]); + /// ``` + /// + #[stable(feature = "slice_rsplit", since = "1.27.0")] + #[inline] + pub fn rsplit_mut(&mut self, pred: F) -> RSplitMut<'_, T, F> + where + F: FnMut(&T) -> bool, + { + RSplitMut::new(self, pred) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred`, limited to returning at most `n` items. The matched element is + /// not contained in the subslices. + /// + /// The last element returned, if any, will contain the remainder of the + /// slice. + /// + /// # Examples + /// + /// Print the slice split once by numbers divisible by 3 (i.e., `[10, 40]`, + /// `[20, 60, 50]`): + /// + /// ``` + /// let v = [10, 40, 30, 20, 60, 50]; + /// + /// for group in v.splitn(2, |num| *num % 3 == 0) { + /// println!("{group:?}"); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn splitn(&self, n: usize, pred: F) -> SplitN<'_, T, F> + where + F: FnMut(&T) -> bool, + { + SplitN::new(self.split(pred), n) + } + + /// Returns an iterator over mutable subslices separated by elements that match + /// `pred`, limited to returning at most `n` items. The matched element is + /// not contained in the subslices. + /// + /// The last element returned, if any, will contain the remainder of the + /// slice. + /// + /// # Examples + /// + /// ``` + /// let mut v = [10, 40, 30, 20, 60, 50]; + /// + /// for group in v.splitn_mut(2, |num| *num % 3 == 0) { + /// group[0] = 1; + /// } + /// assert_eq!(v, [1, 40, 30, 1, 60, 50]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn splitn_mut(&mut self, n: usize, pred: F) -> SplitNMut<'_, T, F> + where + F: FnMut(&T) -> bool, + { + SplitNMut::new(self.split_mut(pred), n) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred` limited to returning at most `n` items. This starts at the end of + /// the slice and works backwards. The matched element is not contained in + /// the subslices. + /// + /// The last element returned, if any, will contain the remainder of the + /// slice. + /// + /// # Examples + /// + /// Print the slice split once, starting from the end, by numbers divisible + /// by 3 (i.e., `[50]`, `[10, 40, 30, 20]`): + /// + /// ``` + /// let v = [10, 40, 30, 20, 60, 50]; + /// + /// for group in v.rsplitn(2, |num| *num % 3 == 0) { + /// println!("{group:?}"); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplitn(&self, n: usize, pred: F) -> RSplitN<'_, T, F> + where + F: FnMut(&T) -> bool, + { + RSplitN::new(self.rsplit(pred), n) + } + + /// Returns an iterator over subslices separated by elements that match + /// `pred` limited to returning at most `n` items. This starts at the end of + /// the slice and works backwards. The matched element is not contained in + /// the subslices. + /// + /// The last element returned, if any, will contain the remainder of the + /// slice. + /// + /// # Examples + /// + /// ``` + /// let mut s = [10, 40, 30, 20, 60, 50]; + /// + /// for group in s.rsplitn_mut(2, |num| *num % 3 == 0) { + /// group[0] = 1; + /// } + /// assert_eq!(s, [1, 40, 30, 20, 60, 1]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplitn_mut(&mut self, n: usize, pred: F) -> RSplitNMut<'_, T, F> + where + F: FnMut(&T) -> bool, + { + RSplitNMut::new(self.rsplit_mut(pred), n) + } + + /// Splits the slice on the first element that matches the specified + /// predicate. + /// + /// If any matching elements are present in the slice, returns the prefix + /// before the match and suffix after. The matching element itself is not + /// included. If no elements match, returns `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_split_once)] + /// let s = [1, 2, 3, 2, 4]; + /// assert_eq!(s.split_once(|&x| x == 2), Some(( + /// &[1][..], + /// &[3, 2, 4][..] + /// ))); + /// assert_eq!(s.split_once(|&x| x == 0), None); + /// ``` + #[unstable(feature = "slice_split_once", reason = "newly added", issue = "112811")] + #[inline] + pub fn split_once(&self, pred: F) -> Option<(&[T], &[T])> + where + F: FnMut(&T) -> bool, + { + let index = self.iter().position(pred)?; + Some((&self[..index], &self[index + 1..])) + } + + /// Splits the slice on the last element that matches the specified + /// predicate. + /// + /// If any matching elements are present in the slice, returns the prefix + /// before the match and suffix after. The matching element itself is not + /// included. If no elements match, returns `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_split_once)] + /// let s = [1, 2, 3, 2, 4]; + /// assert_eq!(s.rsplit_once(|&x| x == 2), Some(( + /// &[1, 2, 3][..], + /// &[4][..] + /// ))); + /// assert_eq!(s.rsplit_once(|&x| x == 0), None); + /// ``` + #[unstable(feature = "slice_split_once", reason = "newly added", issue = "112811")] + #[inline] + pub fn rsplit_once(&self, pred: F) -> Option<(&[T], &[T])> + where + F: FnMut(&T) -> bool, + { + let index = self.iter().rposition(pred)?; + Some((&self[..index], &self[index + 1..])) + } + + /// Returns `true` if the slice contains an element with the given value. + /// + /// This operation is *O*(*n*). + /// + /// Note that if you have a sorted slice, [`binary_search`] may be faster. + /// + /// [`binary_search`]: slice::binary_search + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert!(v.contains(&30)); + /// assert!(!v.contains(&50)); + /// ``` + /// + /// If you do not have a `&T`, but some other value that you can compare + /// with one (for example, `String` implements `PartialEq`), you can + /// use `iter().any`: + /// + /// ``` + /// let v = [String::from("hello"), String::from("world")]; // slice of `String` + /// assert!(v.iter().any(|e| e == "hello")); // search with `&str` + /// assert!(!v.iter().any(|e| e == "hi")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[must_use] + pub fn contains(&self, x: &T) -> bool + where + T: PartialEq, + { + cmp::SliceContains::slice_contains(x, self) + } + + /// Returns `true` if `needle` is a prefix of the slice or equal to the slice. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert!(v.starts_with(&[10])); + /// assert!(v.starts_with(&[10, 40])); + /// assert!(v.starts_with(&v)); + /// assert!(!v.starts_with(&[50])); + /// assert!(!v.starts_with(&[10, 50])); + /// ``` + /// + /// Always returns `true` if `needle` is an empty slice: + /// + /// ``` + /// let v = &[10, 40, 30]; + /// assert!(v.starts_with(&[])); + /// let v: &[u8] = &[]; + /// assert!(v.starts_with(&[])); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn starts_with(&self, needle: &[T]) -> bool + where + T: PartialEq, + { + let n = needle.len(); + self.len() >= n && needle == &self[..n] + } + + /// Returns `true` if `needle` is a suffix of the slice or equal to the slice. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert!(v.ends_with(&[30])); + /// assert!(v.ends_with(&[40, 30])); + /// assert!(v.ends_with(&v)); + /// assert!(!v.ends_with(&[50])); + /// assert!(!v.ends_with(&[50, 30])); + /// ``` + /// + /// Always returns `true` if `needle` is an empty slice: + /// + /// ``` + /// let v = &[10, 40, 30]; + /// assert!(v.ends_with(&[])); + /// let v: &[u8] = &[]; + /// assert!(v.ends_with(&[])); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn ends_with(&self, needle: &[T]) -> bool + where + T: PartialEq, + { + let (m, n) = (self.len(), needle.len()); + m >= n && needle == &self[m - n..] + } + + /// Returns a subslice with the prefix removed. + /// + /// If the slice starts with `prefix`, returns the subslice after the prefix, wrapped in `Some`. + /// If `prefix` is empty, simply returns the original slice. If `prefix` is equal to the + /// original slice, returns an empty slice. + /// + /// If the slice does not start with `prefix`, returns `None`. + /// + /// # Examples + /// + /// ``` + /// let v = &[10, 40, 30]; + /// assert_eq!(v.strip_prefix(&[10]), Some(&[40, 30][..])); + /// assert_eq!(v.strip_prefix(&[10, 40]), Some(&[30][..])); + /// assert_eq!(v.strip_prefix(&[10, 40, 30]), Some(&[][..])); + /// assert_eq!(v.strip_prefix(&[50]), None); + /// assert_eq!(v.strip_prefix(&[10, 50]), None); + /// + /// let prefix : &str = "he"; + /// assert_eq!(b"hello".strip_prefix(prefix.as_bytes()), + /// Some(b"llo".as_ref())); + /// ``` + #[must_use = "returns the subslice without modifying the original"] + #[stable(feature = "slice_strip", since = "1.51.0")] + pub fn strip_prefix + ?Sized>(&self, prefix: &P) -> Option<&[T]> + where + T: PartialEq, + { + // This function will need rewriting if and when SlicePattern becomes more sophisticated. + let prefix = prefix.as_slice(); + let n = prefix.len(); + if n <= self.len() { + let (head, tail) = self.split_at(n); + if head == prefix { + return Some(tail); + } + } + None + } + + /// Returns a subslice with the suffix removed. + /// + /// If the slice ends with `suffix`, returns the subslice before the suffix, wrapped in `Some`. + /// If `suffix` is empty, simply returns the original slice. If `suffix` is equal to the + /// original slice, returns an empty slice. + /// + /// If the slice does not end with `suffix`, returns `None`. + /// + /// # Examples + /// + /// ``` + /// let v = &[10, 40, 30]; + /// assert_eq!(v.strip_suffix(&[30]), Some(&[10, 40][..])); + /// assert_eq!(v.strip_suffix(&[40, 30]), Some(&[10][..])); + /// assert_eq!(v.strip_suffix(&[10, 40, 30]), Some(&[][..])); + /// assert_eq!(v.strip_suffix(&[50]), None); + /// assert_eq!(v.strip_suffix(&[50, 30]), None); + /// ``` + #[must_use = "returns the subslice without modifying the original"] + #[stable(feature = "slice_strip", since = "1.51.0")] + pub fn strip_suffix + ?Sized>(&self, suffix: &P) -> Option<&[T]> + where + T: PartialEq, + { + // This function will need rewriting if and when SlicePattern becomes more sophisticated. + let suffix = suffix.as_slice(); + let (len, n) = (self.len(), suffix.len()); + if n <= len { + let (head, tail) = self.split_at(len - n); + if tail == suffix { + return Some(head); + } + } + None + } + + /// Binary searches this slice for a given element. + /// If the slice is not sorted, the returned result is unspecified and + /// meaningless. + /// + /// If the value is found then [`Result::Ok`] is returned, containing the + /// index of the matching element. If there are multiple matches, then any + /// one of the matches could be returned. The index is chosen + /// deterministically, but is subject to change in future versions of Rust. + /// If the value is not found then [`Result::Err`] is returned, containing + /// the index where a matching element could be inserted while maintaining + /// sorted order. + /// + /// See also [`binary_search_by`], [`binary_search_by_key`], and [`partition_point`]. + /// + /// [`binary_search_by`]: slice::binary_search_by + /// [`binary_search_by_key`]: slice::binary_search_by_key + /// [`partition_point`]: slice::partition_point + /// + /// # Examples + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1, 4]`. + /// + /// ``` + /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// + /// assert_eq!(s.binary_search(&13), Ok(9)); + /// assert_eq!(s.binary_search(&4), Err(7)); + /// assert_eq!(s.binary_search(&100), Err(13)); + /// let r = s.binary_search(&1); + /// assert!(match r { Ok(1..=4) => true, _ => false, }); + /// ``` + /// + /// If you want to find that whole *range* of matching items, rather than + /// an arbitrary matching one, that can be done using [`partition_point`]: + /// ``` + /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// + /// let low = s.partition_point(|x| x < &1); + /// assert_eq!(low, 1); + /// let high = s.partition_point(|x| x <= &1); + /// assert_eq!(high, 5); + /// let r = s.binary_search(&1); + /// assert!((low..high).contains(&r.unwrap())); + /// + /// assert!(s[..low].iter().all(|&x| x < 1)); + /// assert!(s[low..high].iter().all(|&x| x == 1)); + /// assert!(s[high..].iter().all(|&x| x > 1)); + /// + /// // For something not found, the "range" of equal items is empty + /// assert_eq!(s.partition_point(|x| x < &11), 9); + /// assert_eq!(s.partition_point(|x| x <= &11), 9); + /// assert_eq!(s.binary_search(&11), Err(9)); + /// ``` + /// + /// If you want to insert an item to a sorted vector, while maintaining + /// sort order, consider using [`partition_point`]: + /// + /// ``` + /// let mut s = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let num = 42; + /// let idx = s.partition_point(|&x| x <= num); + /// // If `num` is unique, `s.partition_point(|&x| x < num)` (with `<`) is equivalent to + /// // `s.binary_search(&num).unwrap_or_else(|x| x)`, but using `<=` will allow `insert` + /// // to shift less elements. + /// s.insert(idx, num); + /// assert_eq!(s, [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn binary_search(&self, x: &T) -> Result + where + T: Ord, + { + self.binary_search_by(|p| p.cmp(x)) + } + + /// Binary searches this slice with a comparator function. + /// + /// The comparator function should return an order code that indicates + /// whether its argument is `Less`, `Equal` or `Greater` the desired + /// target. + /// If the slice is not sorted or if the comparator function does not + /// implement an order consistent with the sort order of the underlying + /// slice, the returned result is unspecified and meaningless. + /// + /// If the value is found then [`Result::Ok`] is returned, containing the + /// index of the matching element. If there are multiple matches, then any + /// one of the matches could be returned. The index is chosen + /// deterministically, but is subject to change in future versions of Rust. + /// If the value is not found then [`Result::Err`] is returned, containing + /// the index where a matching element could be inserted while maintaining + /// sorted order. + /// + /// See also [`binary_search`], [`binary_search_by_key`], and [`partition_point`]. + /// + /// [`binary_search`]: slice::binary_search + /// [`binary_search_by_key`]: slice::binary_search_by_key + /// [`partition_point`]: slice::partition_point + /// + /// # Examples + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1, 4]`. + /// + /// ``` + /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// + /// let seek = 13; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9)); + /// let seek = 4; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7)); + /// let seek = 100; + /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13)); + /// let seek = 1; + /// let r = s.binary_search_by(|probe| probe.cmp(&seek)); + /// assert!(match r { Ok(1..=4) => true, _ => false, }); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result + where + F: FnMut(&'a T) -> Ordering, + { + let mut size = self.len(); + if size == 0 { + return Err(0); + } + let mut base = 0usize; + + // This loop intentionally doesn't have an early exit if the comparison + // returns Equal. We want the number of loop iterations to depend *only* + // on the size of the input slice so that the CPU can reliably predict + // the loop count. + while size > 1 { + let half = size / 2; + let mid = base + half; + + // SAFETY: the call is made safe by the following inconstants: + // - `mid >= 0`: by definition + // - `mid < size`: `mid = size / 2 + size / 4 + size / 8 ...` + let cmp = f(unsafe { self.get_unchecked(mid) }); + + // Binary search interacts poorly with branch prediction, so force + // the compiler to use conditional moves if supported by the target + // architecture. + base = select_unpredictable(cmp == Greater, base, mid); + + // This is imprecise in the case where `size` is odd and the + // comparison returns Greater: the mid element still gets included + // by `size` even though it's known to be larger than the element + // being searched for. + // + // This is fine though: we gain more performance by keeping the + // loop iteration count invariant (and thus predictable) than we + // lose from considering one additional element. + size -= half; + } + + // SAFETY: base is always in [0, size) because base <= mid. + let cmp = f(unsafe { self.get_unchecked(base) }); + if cmp == Equal { + // SAFETY: same as the `get_unchecked` above. + unsafe { hint::assert_unchecked(base < self.len()) }; + Ok(base) + } else { + let result = base + (cmp == Less) as usize; + // SAFETY: same as the `get_unchecked` above. + // Note that this is `<=`, unlike the assume in the `Ok` path. + unsafe { hint::assert_unchecked(result <= self.len()) }; + Err(result) + } + } + + /// Binary searches this slice with a key extraction function. + /// + /// Assumes that the slice is sorted by the key, for instance with + /// [`sort_by_key`] using the same key extraction function. + /// If the slice is not sorted by the key, the returned result is + /// unspecified and meaningless. + /// + /// If the value is found then [`Result::Ok`] is returned, containing the + /// index of the matching element. If there are multiple matches, then any + /// one of the matches could be returned. The index is chosen + /// deterministically, but is subject to change in future versions of Rust. + /// If the value is not found then [`Result::Err`] is returned, containing + /// the index where a matching element could be inserted while maintaining + /// sorted order. + /// + /// See also [`binary_search`], [`binary_search_by`], and [`partition_point`]. + /// + /// [`sort_by_key`]: slice::sort_by_key + /// [`binary_search`]: slice::binary_search + /// [`binary_search_by`]: slice::binary_search_by + /// [`partition_point`]: slice::partition_point + /// + /// # Examples + /// + /// Looks up a series of four elements in a slice of pairs sorted by + /// their second elements. The first is found, with a uniquely + /// determined position; the second and third are not found; the + /// fourth could match any position in `[1, 4]`. + /// + /// ``` + /// let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1), + /// (1, 2), (2, 3), (4, 5), (5, 8), (3, 13), + /// (1, 21), (2, 34), (4, 55)]; + /// + /// assert_eq!(s.binary_search_by_key(&13, |&(a, b)| b), Ok(9)); + /// assert_eq!(s.binary_search_by_key(&4, |&(a, b)| b), Err(7)); + /// assert_eq!(s.binary_search_by_key(&100, |&(a, b)| b), Err(13)); + /// let r = s.binary_search_by_key(&1, |&(a, b)| b); + /// assert!(match r { Ok(1..=4) => true, _ => false, }); + /// ``` + // Lint rustdoc::broken_intra_doc_links is allowed as `slice::sort_by_key` is + // in crate `alloc`, and as such doesn't exists yet when building `core`: #74481. + // This breaks links when slice is displayed in core, but changing it to use relative links + // would break when the item is re-exported. So allow the core links to be broken for now. + #[allow(rustdoc::broken_intra_doc_links)] + #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")] + #[inline] + pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result + where + F: FnMut(&'a T) -> B, + B: Ord, + { + self.binary_search_by(|k| f(k).cmp(b)) + } + + /// Sorts the slice **without** preserving the initial order of equal elements. + /// + /// This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not + /// allocate), and *O*(*n* \* log(*n*)) worst-case. + /// + /// If the implementation of [`Ord`] for `T` does not implement a [total order] the resulting + /// order of elements in the slice is unspecified. All original elements will remain in the + /// slice and any possible modifications via interior mutability are observed in the input. Same + /// is true if the implementation of [`Ord`] for `T` panics. + /// + /// Sorting types that only implement [`PartialOrd`] such as [`f32`] and [`f64`] require + /// additional precautions. For example, `f32::NAN != f32::NAN`, which doesn't fulfill the + /// reflexivity requirement of [`Ord`]. By using an alternative comparison function with + /// `slice::sort_unstable_by` such as [`f32::total_cmp`] or [`f64::total_cmp`] that defines a + /// [total order] users can sort slices containing floating-point values. Alternatively, if all + /// values in the slice are guaranteed to be in a subset for which [`PartialOrd::partial_cmp`] + /// forms a [total order], it's possible to sort the slice with `sort_unstable_by(|a, b| + /// a.partial_cmp(b).unwrap())`. + /// + /// # Current implementation + /// + /// The current implementation is based on [ipnsort] by Lukas Bergdoll and Orson Peters, which + /// combines the fast average case of quicksort with the fast worst case of heapsort, achieving + /// linear time on fully sorted and reversed inputs. On inputs with k distinct elements, the + /// expected time to sort the data is *O*(*n* \* log(*k*)). + /// + /// It is typically faster than stable sorting, except in a few special cases, e.g., when the + /// slice is partially sorted. + /// + /// # Panics + /// + /// May panic if the implementation of [`Ord`] for `T` does not implement a [total order]. + /// + /// # Examples + /// + /// ``` + /// let mut v = [4, -5, 1, -3, 2]; + /// + /// v.sort_unstable(); + /// assert_eq!(v, [-5, -3, 1, 2, 4]); + /// ``` + /// + /// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort + /// [total order]: https://en.wikipedia.org/wiki/Total_order + #[stable(feature = "sort_unstable", since = "1.20.0")] + #[inline] + pub fn sort_unstable(&mut self) + where + T: Ord, + { + sort::unstable::sort(self, &mut T::lt); + } + + /// Sorts the slice with a comparison function, **without** preserving the initial order of + /// equal elements. + /// + /// This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not + /// allocate), and *O*(*n* \* log(*n*)) worst-case. + /// + /// If the comparison function `compare` does not implement a [total order] the resulting order + /// of elements in the slice is unspecified. All original elements will remain in the slice and + /// any possible modifications via interior mutability are observed in the input. Same is true + /// if `compare` panics. + /// + /// For example `|a, b| (a - b).cmp(a)` is a comparison function that is neither transitive nor + /// reflexive nor total, `a < b < c < a` with `a = 1, b = 2, c = 3`. For more information and + /// examples see the [`Ord`] documentation. + /// + /// # Current implementation + /// + /// The current implementation is based on [ipnsort] by Lukas Bergdoll and Orson Peters, which + /// combines the fast average case of quicksort with the fast worst case of heapsort, achieving + /// linear time on fully sorted and reversed inputs. On inputs with k distinct elements, the + /// expected time to sort the data is *O*(*n* \* log(*k*)). + /// + /// It is typically faster than stable sorting, except in a few special cases, e.g., when the + /// slice is partially sorted. + /// + /// # Panics + /// + /// May panic if `compare` does not implement a [total order]. + /// + /// # Examples + /// + /// ``` + /// let mut v = [4, -5, 1, -3, 2]; + /// v.sort_unstable_by(|a, b| a.cmp(b)); + /// assert_eq!(v, [-5, -3, 1, 2, 4]); + /// + /// // reverse sorting + /// v.sort_unstable_by(|a, b| b.cmp(a)); + /// assert_eq!(v, [4, 2, 1, -3, -5]); + /// ``` + /// + /// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort + /// [total order]: https://en.wikipedia.org/wiki/Total_order + #[stable(feature = "sort_unstable", since = "1.20.0")] + #[inline] + pub fn sort_unstable_by(&mut self, mut compare: F) + where + F: FnMut(&T, &T) -> Ordering, + { + sort::unstable::sort(self, &mut |a, b| compare(a, b) == Ordering::Less); + } + + /// Sorts the slice with a key extraction function, **without** preserving the initial order of + /// equal elements. + /// + /// This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not + /// allocate), and *O*(*n* \* log(*n*)) worst-case. + /// + /// If the implementation of [`Ord`] for `K` does not implement a [total order] the resulting + /// order of elements in the slice is unspecified. All original elements will remain in the + /// slice and any possible modifications via interior mutability are observed in the input. Same + /// is true if the implementation of [`Ord`] for `K` panics. + /// + /// # Current implementation + /// + /// The current implementation is based on [ipnsort] by Lukas Bergdoll and Orson Peters, which + /// combines the fast average case of quicksort with the fast worst case of heapsort, achieving + /// linear time on fully sorted and reversed inputs. On inputs with k distinct elements, the + /// expected time to sort the data is *O*(*n* \* log(*k*)). + /// + /// It is typically faster than stable sorting, except in a few special cases, e.g., when the + /// slice is partially sorted. + /// + /// # Panics + /// + /// May panic if the implementation of [`Ord`] for `K` does not implement a [total order]. + /// + /// # Examples + /// + /// ``` + /// let mut v = [4i32, -5, 1, -3, 2]; + /// + /// v.sort_unstable_by_key(|k| k.abs()); + /// assert_eq!(v, [1, 2, -3, 4, -5]); + /// ``` + /// + /// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort + /// [total order]: https://en.wikipedia.org/wiki/Total_order + #[stable(feature = "sort_unstable", since = "1.20.0")] + #[inline] + pub fn sort_unstable_by_key(&mut self, mut f: F) + where + F: FnMut(&T) -> K, + K: Ord, + { + sort::unstable::sort(self, &mut |a, b| f(a).lt(&f(b))); + } + + /// Reorders the slice such that the element at `index` after the reordering is at its final + /// sorted position. + /// + /// This reordering has the additional property that any value at position `i < index` will be + /// less than or equal to any value at a position `j > index`. Additionally, this reordering is + /// unstable (i.e. any number of equal elements may end up at position `index`), in-place (i.e. + /// does not allocate), and runs in *O*(*n*) time. This function is also known as "kth element" + /// in other libraries. + /// + /// It returns a triplet of the following from the reordered slice: the subslice prior to + /// `index`, the element at `index`, and the subslice after `index`; accordingly, the values in + /// those two subslices will respectively all be less-than-or-equal-to and + /// greater-than-or-equal-to the value of the element at `index`. + /// + /// # Current implementation + /// + /// The current algorithm is an introselect implementation based on [ipnsort] by Lukas Bergdoll + /// and Orson Peters, which is also the basis for [`sort_unstable`]. The fallback algorithm is + /// Median of Medians using Tukey's Ninther for pivot selection, which guarantees linear runtime + /// for all inputs. + /// + /// [`sort_unstable`]: slice::sort_unstable + /// + /// # Panics + /// + /// Panics when `index >= len()`, meaning it always panics on empty slices. + /// + /// May panic if the implementation of [`Ord`] for `T` does not implement a [total order]. + /// + /// # Examples + /// + /// ``` + /// let mut v = [-5i32, 4, 2, -3, 1]; + /// + /// // Find the items less than or equal to the median, the median, and greater than or equal to + /// // the median. + /// let (lesser, median, greater) = v.select_nth_unstable(2); + /// + /// assert!(lesser == [-3, -5] || lesser == [-5, -3]); + /// assert_eq!(median, &mut 1); + /// assert!(greater == [4, 2] || greater == [2, 4]); + /// + /// // We are only guaranteed the slice will be one of the following, based on the way we sort + /// // about the specified index. + /// assert!(v == [-3, -5, 1, 2, 4] || + /// v == [-5, -3, 1, 2, 4] || + /// v == [-3, -5, 1, 4, 2] || + /// v == [-5, -3, 1, 4, 2]); + /// ``` + /// + /// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort + /// [total order]: https://en.wikipedia.org/wiki/Total_order + #[stable(feature = "slice_select_nth_unstable", since = "1.49.0")] + #[inline] + pub fn select_nth_unstable(&mut self, index: usize) -> (&mut [T], &mut T, &mut [T]) + where + T: Ord, + { + sort::select::partition_at_index(self, index, T::lt) + } + + /// Reorders the slice with a comparator function such that the element at `index` after the + /// reordering is at its final sorted position. + /// + /// This reordering has the additional property that any value at position `i < index` will be + /// less than or equal to any value at a position `j > index` using the comparator function. + /// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at + /// position `index`), in-place (i.e. does not allocate), and runs in *O*(*n*) time. This + /// function is also known as "kth element" in other libraries. + /// + /// It returns a triplet of the following from the slice reordered according to the provided + /// comparator function: the subslice prior to `index`, the element at `index`, and the subslice + /// after `index`; accordingly, the values in those two subslices will respectively all be + /// less-than-or-equal-to and greater-than-or-equal-to the value of the element at `index`. + /// + /// # Current implementation + /// + /// The current algorithm is an introselect implementation based on [ipnsort] by Lukas Bergdoll + /// and Orson Peters, which is also the basis for [`sort_unstable`]. The fallback algorithm is + /// Median of Medians using Tukey's Ninther for pivot selection, which guarantees linear runtime + /// for all inputs. + /// + /// [`sort_unstable`]: slice::sort_unstable + /// + /// # Panics + /// + /// Panics when `index >= len()`, meaning it always panics on empty slices. + /// + /// May panic if `compare` does not implement a [total order]. + /// + /// # Examples + /// + /// ``` + /// let mut v = [-5i32, 4, 2, -3, 1]; + /// + /// // Find the items less than or equal to the median, the median, and greater than or equal to + /// // the median as if the slice were sorted in descending order. + /// let (lesser, median, greater) = v.select_nth_unstable_by(2, |a, b| b.cmp(a)); + /// + /// assert!(lesser == [4, 2] || lesser == [2, 4]); + /// assert_eq!(median, &mut 1); + /// assert!(greater == [-3, -5] || greater == [-5, -3]); + /// + /// // We are only guaranteed the slice will be one of the following, based on the way we sort + /// // about the specified index. + /// assert!(v == [2, 4, 1, -5, -3] || + /// v == [2, 4, 1, -3, -5] || + /// v == [4, 2, 1, -5, -3] || + /// v == [4, 2, 1, -3, -5]); + /// ``` + /// + /// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort + /// [total order]: https://en.wikipedia.org/wiki/Total_order + #[stable(feature = "slice_select_nth_unstable", since = "1.49.0")] + #[inline] + pub fn select_nth_unstable_by( + &mut self, + index: usize, + mut compare: F, + ) -> (&mut [T], &mut T, &mut [T]) + where + F: FnMut(&T, &T) -> Ordering, + { + sort::select::partition_at_index(self, index, |a: &T, b: &T| compare(a, b) == Less) + } + + /// Reorders the slice with a key extraction function such that the element at `index` after the + /// reordering is at its final sorted position. + /// + /// This reordering has the additional property that any value at position `i < index` will be + /// less than or equal to any value at a position `j > index` using the key extraction function. + /// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at + /// position `index`), in-place (i.e. does not allocate), and runs in *O*(*n*) time. This + /// function is also known as "kth element" in other libraries. + /// + /// It returns a triplet of the following from the slice reordered according to the provided key + /// extraction function: the subslice prior to `index`, the element at `index`, and the subslice + /// after `index`; accordingly, the values in those two subslices will respectively all be + /// less-than-or-equal-to and greater-than-or-equal-to the value of the element at `index`. + /// + /// # Current implementation + /// + /// The current algorithm is an introselect implementation based on [ipnsort] by Lukas Bergdoll + /// and Orson Peters, which is also the basis for [`sort_unstable`]. The fallback algorithm is + /// Median of Medians using Tukey's Ninther for pivot selection, which guarantees linear runtime + /// for all inputs. + /// + /// [`sort_unstable`]: slice::sort_unstable + /// + /// # Panics + /// + /// Panics when `index >= len()`, meaning it always panics on empty slices. + /// + /// May panic if `K: Ord` does not implement a total order. + /// + /// # Examples + /// + /// ``` + /// let mut v = [-5i32, 4, 1, -3, 2]; + /// + /// // Find the items less than or equal to the median, the median, and greater than or equal to + /// // the median as if the slice were sorted according to absolute value. + /// let (lesser, median, greater) = v.select_nth_unstable_by_key(2, |a| a.abs()); + /// + /// assert!(lesser == [1, 2] || lesser == [2, 1]); + /// assert_eq!(median, &mut -3); + /// assert!(greater == [4, -5] || greater == [-5, 4]); + /// + /// // We are only guaranteed the slice will be one of the following, based on the way we sort + /// // about the specified index. + /// assert!(v == [1, 2, -3, 4, -5] || + /// v == [1, 2, -3, -5, 4] || + /// v == [2, 1, -3, 4, -5] || + /// v == [2, 1, -3, -5, 4]); + /// ``` + /// + /// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort + /// [total order]: https://en.wikipedia.org/wiki/Total_order + #[stable(feature = "slice_select_nth_unstable", since = "1.49.0")] + #[inline] + pub fn select_nth_unstable_by_key( + &mut self, + index: usize, + mut f: F, + ) -> (&mut [T], &mut T, &mut [T]) + where + F: FnMut(&T) -> K, + K: Ord, + { + sort::select::partition_at_index(self, index, |a: &T, b: &T| f(a).lt(&f(b))) + } + + /// Moves all consecutive repeated elements to the end of the slice according to the + /// [`PartialEq`] trait implementation. + /// + /// Returns two slices. The first contains no consecutive repeated elements. + /// The second contains all the duplicates in no specified order. + /// + /// If the slice is sorted, the first returned slice contains no duplicates. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_partition_dedup)] + /// + /// let mut slice = [1, 2, 2, 3, 3, 2, 1, 1]; + /// + /// let (dedup, duplicates) = slice.partition_dedup(); + /// + /// assert_eq!(dedup, [1, 2, 3, 2, 1]); + /// assert_eq!(duplicates, [2, 3, 1]); + /// ``` + #[unstable(feature = "slice_partition_dedup", issue = "54279")] + #[inline] + pub fn partition_dedup(&mut self) -> (&mut [T], &mut [T]) + where + T: PartialEq, + { + self.partition_dedup_by(|a, b| a == b) + } + + /// Moves all but the first of consecutive elements to the end of the slice satisfying + /// a given equality relation. + /// + /// Returns two slices. The first contains no consecutive repeated elements. + /// The second contains all the duplicates in no specified order. + /// + /// The `same_bucket` function is passed references to two elements from the slice and + /// must determine if the elements compare equal. The elements are passed in opposite order + /// from their order in the slice, so if `same_bucket(a, b)` returns `true`, `a` is moved + /// at the end of the slice. + /// + /// If the slice is sorted, the first returned slice contains no duplicates. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_partition_dedup)] + /// + /// let mut slice = ["foo", "Foo", "BAZ", "Bar", "bar", "baz", "BAZ"]; + /// + /// let (dedup, duplicates) = slice.partition_dedup_by(|a, b| a.eq_ignore_ascii_case(b)); + /// + /// assert_eq!(dedup, ["foo", "BAZ", "Bar", "baz"]); + /// assert_eq!(duplicates, ["bar", "Foo", "BAZ"]); + /// ``` + #[unstable(feature = "slice_partition_dedup", issue = "54279")] + #[inline] + pub fn partition_dedup_by(&mut self, mut same_bucket: F) -> (&mut [T], &mut [T]) + where + F: FnMut(&mut T, &mut T) -> bool, + { + // Although we have a mutable reference to `self`, we cannot make + // *arbitrary* changes. The `same_bucket` calls could panic, so we + // must ensure that the slice is in a valid state at all times. + // + // The way that we handle this is by using swaps; we iterate + // over all the elements, swapping as we go so that at the end + // the elements we wish to keep are in the front, and those we + // wish to reject are at the back. We can then split the slice. + // This operation is still `O(n)`. + // + // Example: We start in this state, where `r` represents "next + // read" and `w` represents "next_write". + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 1 | 2 | 3 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Comparing self[r] against self[w-1], this is not a duplicate, so + // we swap self[r] and self[w] (no effect as r==w) and then increment both + // r and w, leaving us with: + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 1 | 2 | 3 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Comparing self[r] against self[w-1], this value is a duplicate, + // so we increment `r` but leave everything else unchanged: + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 1 | 2 | 3 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Comparing self[r] against self[w-1], this is not a duplicate, + // so swap self[r] and self[w] and advance r and w: + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 2 | 1 | 3 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Not a duplicate, repeat: + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 2 | 3 | 1 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Duplicate, advance r. End of slice. Split at w. + + let len = self.len(); + if len <= 1 { + return (self, &mut []); + } + + let ptr = self.as_mut_ptr(); + let mut next_read: usize = 1; + let mut next_write: usize = 1; + + // SAFETY: the `while` condition guarantees `next_read` and `next_write` + // are less than `len`, thus are inside `self`. `prev_ptr_write` points to + // one element before `ptr_write`, but `next_write` starts at 1, so + // `prev_ptr_write` is never less than 0 and is inside the slice. + // This fulfils the requirements for dereferencing `ptr_read`, `prev_ptr_write` + // and `ptr_write`, and for using `ptr.add(next_read)`, `ptr.add(next_write - 1)` + // and `prev_ptr_write.offset(1)`. + // + // `next_write` is also incremented at most once per loop at most meaning + // no element is skipped when it may need to be swapped. + // + // `ptr_read` and `prev_ptr_write` never point to the same element. This + // is required for `&mut *ptr_read`, `&mut *prev_ptr_write` to be safe. + // The explanation is simply that `next_read >= next_write` is always true, + // thus `next_read > next_write - 1` is too. + unsafe { + // Avoid bounds checks by using raw pointers. + while next_read < len { + let ptr_read = ptr.add(next_read); + let prev_ptr_write = ptr.add(next_write - 1); + if !same_bucket(&mut *ptr_read, &mut *prev_ptr_write) { + if next_read != next_write { + let ptr_write = prev_ptr_write.add(1); + mem::swap(&mut *ptr_read, &mut *ptr_write); + } + next_write += 1; + } + next_read += 1; + } + } + + self.split_at_mut(next_write) + } + + /// Moves all but the first of consecutive elements to the end of the slice that resolve + /// to the same key. + /// + /// Returns two slices. The first contains no consecutive repeated elements. + /// The second contains all the duplicates in no specified order. + /// + /// If the slice is sorted, the first returned slice contains no duplicates. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_partition_dedup)] + /// + /// let mut slice = [10, 20, 21, 30, 30, 20, 11, 13]; + /// + /// let (dedup, duplicates) = slice.partition_dedup_by_key(|i| *i / 10); + /// + /// assert_eq!(dedup, [10, 20, 30, 20, 11]); + /// assert_eq!(duplicates, [21, 30, 13]); + /// ``` + #[unstable(feature = "slice_partition_dedup", issue = "54279")] + #[inline] + pub fn partition_dedup_by_key(&mut self, mut key: F) -> (&mut [T], &mut [T]) + where + F: FnMut(&mut T) -> K, + K: PartialEq, + { + self.partition_dedup_by(|a, b| key(a) == key(b)) + } + + /// Rotates the slice in-place such that the first `mid` elements of the + /// slice move to the end while the last `self.len() - mid` elements move to + /// the front. + /// + /// After calling `rotate_left`, the element previously at index `mid` will + /// become the first element in the slice. + /// + /// # Panics + /// + /// This function will panic if `mid` is greater than the length of the + /// slice. Note that `mid == self.len()` does _not_ panic and is a no-op + /// rotation. + /// + /// # Complexity + /// + /// Takes linear (in `self.len()`) time. + /// + /// # Examples + /// + /// ``` + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// a.rotate_left(2); + /// assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']); + /// ``` + /// + /// Rotating a subslice: + /// + /// ``` + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// a[1..5].rotate_left(1); + /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']); + /// ``` + #[stable(feature = "slice_rotate", since = "1.26.0")] + pub fn rotate_left(&mut self, mid: usize) { + assert!(mid <= self.len()); + let k = self.len() - mid; + let p = self.as_mut_ptr(); + + // SAFETY: The range `[p.add(mid) - mid, p.add(mid) + k)` is trivially + // valid for reading and writing, as required by `ptr_rotate`. + unsafe { + rotate::ptr_rotate(mid, p.add(mid), k); + } + } + + /// Rotates the slice in-place such that the first `self.len() - k` + /// elements of the slice move to the end while the last `k` elements move + /// to the front. + /// + /// After calling `rotate_right`, the element previously at index + /// `self.len() - k` will become the first element in the slice. + /// + /// # Panics + /// + /// This function will panic if `k` is greater than the length of the + /// slice. Note that `k == self.len()` does _not_ panic and is a no-op + /// rotation. + /// + /// # Complexity + /// + /// Takes linear (in `self.len()`) time. + /// + /// # Examples + /// + /// ``` + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// a.rotate_right(2); + /// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']); + /// ``` + /// + /// Rotating a subslice: + /// + /// ``` + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// a[1..5].rotate_right(1); + /// assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']); + /// ``` + #[stable(feature = "slice_rotate", since = "1.26.0")] + pub fn rotate_right(&mut self, k: usize) { + assert!(k <= self.len()); + let mid = self.len() - k; + let p = self.as_mut_ptr(); + + // SAFETY: The range `[p.add(mid) - mid, p.add(mid) + k)` is trivially + // valid for reading and writing, as required by `ptr_rotate`. + unsafe { + rotate::ptr_rotate(mid, p.add(mid), k); + } + } + + /// Fills `self` with elements by cloning `value`. + /// + /// # Examples + /// + /// ``` + /// let mut buf = vec![0; 10]; + /// buf.fill(1); + /// assert_eq!(buf, vec![1; 10]); + /// ``` + #[doc(alias = "memset")] + #[stable(feature = "slice_fill", since = "1.50.0")] + pub fn fill(&mut self, value: T) + where + T: Clone, + { + specialize::SpecFill::spec_fill(self, value); + } + + /// Fills `self` with elements returned by calling a closure repeatedly. + /// + /// This method uses a closure to create new values. If you'd rather + /// [`Clone`] a given value, use [`fill`]. If you want to use the [`Default`] + /// trait to generate values, you can pass [`Default::default`] as the + /// argument. + /// + /// [`fill`]: slice::fill + /// + /// # Examples + /// + /// ``` + /// let mut buf = vec![1; 10]; + /// buf.fill_with(Default::default); + /// assert_eq!(buf, vec![0; 10]); + /// ``` + #[stable(feature = "slice_fill_with", since = "1.51.0")] + pub fn fill_with(&mut self, mut f: F) + where + F: FnMut() -> T, + { + for el in self { + *el = f(); + } + } + + /// Copies the elements from `src` into `self`. + /// + /// The length of `src` must be the same as `self`. + /// + /// # Panics + /// + /// This function will panic if the two slices have different lengths. + /// + /// # Examples + /// + /// Cloning two elements from a slice into another: + /// + /// ``` + /// let src = [1, 2, 3, 4]; + /// let mut dst = [0, 0]; + /// + /// // Because the slices have to be the same length, + /// // we slice the source slice from four elements + /// // to two. It will panic if we don't do this. + /// dst.clone_from_slice(&src[2..]); + /// + /// assert_eq!(src, [1, 2, 3, 4]); + /// assert_eq!(dst, [3, 4]); + /// ``` + /// + /// Rust enforces that there can only be one mutable reference with no + /// immutable references to a particular piece of data in a particular + /// scope. Because of this, attempting to use `clone_from_slice` on a + /// single slice will result in a compile failure: + /// + /// ```compile_fail + /// let mut slice = [1, 2, 3, 4, 5]; + /// + /// slice[..2].clone_from_slice(&slice[3..]); // compile fail! + /// ``` + /// + /// To work around this, we can use [`split_at_mut`] to create two distinct + /// sub-slices from a slice: + /// + /// ``` + /// let mut slice = [1, 2, 3, 4, 5]; + /// + /// { + /// let (left, right) = slice.split_at_mut(2); + /// left.clone_from_slice(&right[1..]); + /// } + /// + /// assert_eq!(slice, [4, 5, 3, 4, 5]); + /// ``` + /// + /// [`copy_from_slice`]: slice::copy_from_slice + /// [`split_at_mut`]: slice::split_at_mut + #[stable(feature = "clone_from_slice", since = "1.7.0")] + #[track_caller] + pub fn clone_from_slice(&mut self, src: &[T]) + where + T: Clone, + { + self.spec_clone_from(src); + } + + /// Copies all elements from `src` into `self`, using a memcpy. + /// + /// The length of `src` must be the same as `self`. + /// + /// If `T` does not implement `Copy`, use [`clone_from_slice`]. + /// + /// # Panics + /// + /// This function will panic if the two slices have different lengths. + /// + /// # Examples + /// + /// Copying two elements from a slice into another: + /// + /// ``` + /// let src = [1, 2, 3, 4]; + /// let mut dst = [0, 0]; + /// + /// // Because the slices have to be the same length, + /// // we slice the source slice from four elements + /// // to two. It will panic if we don't do this. + /// dst.copy_from_slice(&src[2..]); + /// + /// assert_eq!(src, [1, 2, 3, 4]); + /// assert_eq!(dst, [3, 4]); + /// ``` + /// + /// Rust enforces that there can only be one mutable reference with no + /// immutable references to a particular piece of data in a particular + /// scope. Because of this, attempting to use `copy_from_slice` on a + /// single slice will result in a compile failure: + /// + /// ```compile_fail + /// let mut slice = [1, 2, 3, 4, 5]; + /// + /// slice[..2].copy_from_slice(&slice[3..]); // compile fail! + /// ``` + /// + /// To work around this, we can use [`split_at_mut`] to create two distinct + /// sub-slices from a slice: + /// + /// ``` + /// let mut slice = [1, 2, 3, 4, 5]; + /// + /// { + /// let (left, right) = slice.split_at_mut(2); + /// left.copy_from_slice(&right[1..]); + /// } + /// + /// assert_eq!(slice, [4, 5, 3, 4, 5]); + /// ``` + /// + /// [`clone_from_slice`]: slice::clone_from_slice + /// [`split_at_mut`]: slice::split_at_mut + #[doc(alias = "memcpy")] + #[stable(feature = "copy_from_slice", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_copy_from_slice", issue = "131415")] + #[track_caller] + pub const fn copy_from_slice(&mut self, src: &[T]) + where + T: Copy, + { + // The panic code path was put into a cold function to not bloat the + // call site. + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] + #[cfg_attr(feature = "panic_immediate_abort", inline)] + #[track_caller] + const fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! { + const_panic!( + "copy_from_slice: source slice length does not match destination slice length", + "copy_from_slice: source slice length ({src_len}) does not match destination slice length ({dst_len})", + src_len: usize, + dst_len: usize, + ) + } + + if self.len() != src.len() { + len_mismatch_fail(self.len(), src.len()); + } + + // SAFETY: `self` is valid for `self.len()` elements by definition, and `src` was + // checked to have the same length. The slices cannot overlap because + // mutable references are exclusive. + unsafe { + ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len()); + } + } + + /// Copies elements from one part of the slice to another part of itself, + /// using a memmove. + /// + /// `src` is the range within `self` to copy from. `dest` is the starting + /// index of the range within `self` to copy to, which will have the same + /// length as `src`. The two ranges may overlap. The ends of the two ranges + /// must be less than or equal to `self.len()`. + /// + /// # Panics + /// + /// This function will panic if either range exceeds the end of the slice, + /// or if the end of `src` is before the start. + /// + /// # Examples + /// + /// Copying four bytes within a slice: + /// + /// ``` + /// let mut bytes = *b"Hello, World!"; + /// + /// bytes.copy_within(1..5, 8); + /// + /// assert_eq!(&bytes, b"Hello, Wello!"); + /// ``` + #[stable(feature = "copy_within", since = "1.37.0")] + #[track_caller] + pub fn copy_within>(&mut self, src: R, dest: usize) + where + T: Copy, + { + let Range { start: src_start, end: src_end } = slice::range(src, ..self.len()); + let count = src_end - src_start; + assert!(dest <= self.len() - count, "dest is out of bounds"); + // SAFETY: the conditions for `ptr::copy` have all been checked above, + // as have those for `ptr::add`. + unsafe { + // Derive both `src_ptr` and `dest_ptr` from the same loan + let ptr = self.as_mut_ptr(); + let src_ptr = ptr.add(src_start); + let dest_ptr = ptr.add(dest); + ptr::copy(src_ptr, dest_ptr, count); + } + } + + /// Swaps all elements in `self` with those in `other`. + /// + /// The length of `other` must be the same as `self`. + /// + /// # Panics + /// + /// This function will panic if the two slices have different lengths. + /// + /// # Example + /// + /// Swapping two elements across slices: + /// + /// ``` + /// let mut slice1 = [0, 0]; + /// let mut slice2 = [1, 2, 3, 4]; + /// + /// slice1.swap_with_slice(&mut slice2[2..]); + /// + /// assert_eq!(slice1, [3, 4]); + /// assert_eq!(slice2, [1, 2, 0, 0]); + /// ``` + /// + /// Rust enforces that there can only be one mutable reference to a + /// particular piece of data in a particular scope. Because of this, + /// attempting to use `swap_with_slice` on a single slice will result in + /// a compile failure: + /// + /// ```compile_fail + /// let mut slice = [1, 2, 3, 4, 5]; + /// slice[..2].swap_with_slice(&mut slice[3..]); // compile fail! + /// ``` + /// + /// To work around this, we can use [`split_at_mut`] to create two distinct + /// mutable sub-slices from a slice: + /// + /// ``` + /// let mut slice = [1, 2, 3, 4, 5]; + /// + /// { + /// let (left, right) = slice.split_at_mut(2); + /// left.swap_with_slice(&mut right[1..]); + /// } + /// + /// assert_eq!(slice, [4, 5, 3, 1, 2]); + /// ``` + /// + /// [`split_at_mut`]: slice::split_at_mut + #[stable(feature = "swap_with_slice", since = "1.27.0")] + #[track_caller] + pub fn swap_with_slice(&mut self, other: &mut [T]) { + assert!(self.len() == other.len(), "destination and source slices have different lengths"); + // SAFETY: `self` is valid for `self.len()` elements by definition, and `src` was + // checked to have the same length. The slices cannot overlap because + // mutable references are exclusive. + unsafe { + ptr::swap_nonoverlapping(self.as_mut_ptr(), other.as_mut_ptr(), self.len()); + } + } + + /// Function to calculate lengths of the middle and trailing slice for `align_to{,_mut}`. + fn align_to_offsets(&self) -> (usize, usize) { + // What we gonna do about `rest` is figure out what multiple of `U`s we can put in a + // lowest number of `T`s. And how many `T`s we need for each such "multiple". + // + // Consider for example T=u8 U=u16. Then we can put 1 U in 2 Ts. Simple. Now, consider + // for example a case where size_of:: = 16, size_of:: = 24. We can put 2 Us in + // place of every 3 Ts in the `rest` slice. A bit more complicated. + // + // Formula to calculate this is: + // + // Us = lcm(size_of::, size_of::) / size_of:: + // Ts = lcm(size_of::, size_of::) / size_of:: + // + // Expanded and simplified: + // + // Us = size_of:: / gcd(size_of::, size_of::) + // Ts = size_of:: / gcd(size_of::, size_of::) + // + // Luckily since all this is constant-evaluated... performance here matters not! + const fn gcd(a: usize, b: usize) -> usize { + if b == 0 { a } else { gcd(b, a % b) } + } + + // Explicitly wrap the function call in a const block so it gets + // constant-evaluated even in debug mode. + let gcd: usize = const { gcd(mem::size_of::(), mem::size_of::()) }; + let ts: usize = mem::size_of::() / gcd; + let us: usize = mem::size_of::() / gcd; + + // Armed with this knowledge, we can find how many `U`s we can fit! + let us_len = self.len() / ts * us; + // And how many `T`s will be in the trailing slice! + let ts_len = self.len() % ts; + (us_len, ts_len) + } + + /// Transmutes the slice to a slice of another type, ensuring alignment of the types is + /// maintained. + /// + /// This method splits the slice into three distinct slices: prefix, correctly aligned middle + /// slice of a new type, and the suffix slice. The middle part will be as big as possible under + /// the given alignment constraint and element size. + /// + /// This method has no purpose when either input element `T` or output element `U` are + /// zero-sized and will return the original slice without splitting anything. + /// + /// # Safety + /// + /// This method is essentially a `transmute` with respect to the elements in the returned + /// middle slice, so all the usual caveats pertaining to `transmute::` also apply here. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// unsafe { + /// let bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7]; + /// let (prefix, shorts, suffix) = bytes.align_to::(); + /// // less_efficient_algorithm_for_bytes(prefix); + /// // more_efficient_algorithm_for_aligned_shorts(shorts); + /// // less_efficient_algorithm_for_bytes(suffix); + /// } + /// ``` + #[stable(feature = "slice_align_to", since = "1.30.0")] + #[must_use] + pub unsafe fn align_to(&self) -> (&[T], &[U], &[T]) { + // Note that most of this function will be constant-evaluated, + if U::IS_ZST || T::IS_ZST { + // handle ZSTs specially, which is – don't handle them at all. + return (self, &[], &[]); + } + + // First, find at what point do we split between the first and 2nd slice. Easy with + // ptr.align_offset. + let ptr = self.as_ptr(); + // SAFETY: See the `align_to_mut` method for the detailed safety comment. + let offset = unsafe { crate::ptr::align_offset(ptr, mem::align_of::()) }; + if offset > self.len() { + (self, &[], &[]) + } else { + let (left, rest) = self.split_at(offset); + let (us_len, ts_len) = rest.align_to_offsets::(); + // Inform Miri that we want to consider the "middle" pointer to be suitably aligned. + #[cfg(miri)] + crate::intrinsics::miri_promise_symbolic_alignment( + rest.as_ptr().cast(), + mem::align_of::(), + ); + // SAFETY: now `rest` is definitely aligned, so `from_raw_parts` below is okay, + // since the caller guarantees that we can transmute `T` to `U` safely. + unsafe { + ( + left, + from_raw_parts(rest.as_ptr() as *const U, us_len), + from_raw_parts(rest.as_ptr().add(rest.len() - ts_len), ts_len), + ) + } + } + } + + /// Transmutes the mutable slice to a mutable slice of another type, ensuring alignment of the + /// types is maintained. + /// + /// This method splits the slice into three distinct slices: prefix, correctly aligned middle + /// slice of a new type, and the suffix slice. The middle part will be as big as possible under + /// the given alignment constraint and element size. + /// + /// This method has no purpose when either input element `T` or output element `U` are + /// zero-sized and will return the original slice without splitting anything. + /// + /// # Safety + /// + /// This method is essentially a `transmute` with respect to the elements in the returned + /// middle slice, so all the usual caveats pertaining to `transmute::` also apply here. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// unsafe { + /// let mut bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7]; + /// let (prefix, shorts, suffix) = bytes.align_to_mut::(); + /// // less_efficient_algorithm_for_bytes(prefix); + /// // more_efficient_algorithm_for_aligned_shorts(shorts); + /// // less_efficient_algorithm_for_bytes(suffix); + /// } + /// ``` + #[stable(feature = "slice_align_to", since = "1.30.0")] + #[must_use] + pub unsafe fn align_to_mut(&mut self) -> (&mut [T], &mut [U], &mut [T]) { + // Note that most of this function will be constant-evaluated, + if U::IS_ZST || T::IS_ZST { + // handle ZSTs specially, which is – don't handle them at all. + return (self, &mut [], &mut []); + } + + // First, find at what point do we split between the first and 2nd slice. Easy with + // ptr.align_offset. + let ptr = self.as_ptr(); + // SAFETY: Here we are ensuring we will use aligned pointers for U for the + // rest of the method. This is done by passing a pointer to &[T] with an + // alignment targeted for U. + // `crate::ptr::align_offset` is called with a correctly aligned and + // valid pointer `ptr` (it comes from a reference to `self`) and with + // a size that is a power of two (since it comes from the alignment for U), + // satisfying its safety constraints. + let offset = unsafe { crate::ptr::align_offset(ptr, mem::align_of::()) }; + if offset > self.len() { + (self, &mut [], &mut []) + } else { + let (left, rest) = self.split_at_mut(offset); + let (us_len, ts_len) = rest.align_to_offsets::(); + let rest_len = rest.len(); + let mut_ptr = rest.as_mut_ptr(); + // Inform Miri that we want to consider the "middle" pointer to be suitably aligned. + #[cfg(miri)] + crate::intrinsics::miri_promise_symbolic_alignment( + mut_ptr.cast() as *const (), + mem::align_of::(), + ); + // We can't use `rest` again after this, that would invalidate its alias `mut_ptr`! + // SAFETY: see comments for `align_to`. + unsafe { + ( + left, + from_raw_parts_mut(mut_ptr as *mut U, us_len), + from_raw_parts_mut(mut_ptr.add(rest_len - ts_len), ts_len), + ) + } + } + } + + /// Splits a slice into a prefix, a middle of aligned SIMD types, and a suffix. + /// + /// This is a safe wrapper around [`slice::align_to`], so inherits the same + /// guarantees as that method. + /// + /// # Panics + /// + /// This will panic if the size of the SIMD type is different from + /// `LANES` times that of the scalar. + /// + /// At the time of writing, the trait restrictions on `Simd` keeps + /// that from ever happening, as only power-of-two numbers of lanes are + /// supported. It's possible that, in the future, those restrictions might + /// be lifted in a way that would make it possible to see panics from this + /// method for something like `LANES == 3`. + /// + /// # Examples + /// + /// ``` + /// #![feature(portable_simd)] + /// use core::simd::prelude::*; + /// + /// let short = &[1, 2, 3]; + /// let (prefix, middle, suffix) = short.as_simd::<4>(); + /// assert_eq!(middle, []); // Not enough elements for anything in the middle + /// + /// // They might be split in any possible way between prefix and suffix + /// let it = prefix.iter().chain(suffix).copied(); + /// assert_eq!(it.collect::>(), vec![1, 2, 3]); + /// + /// fn basic_simd_sum(x: &[f32]) -> f32 { + /// use std::ops::Add; + /// let (prefix, middle, suffix) = x.as_simd(); + /// let sums = f32x4::from_array([ + /// prefix.iter().copied().sum(), + /// 0.0, + /// 0.0, + /// suffix.iter().copied().sum(), + /// ]); + /// let sums = middle.iter().copied().fold(sums, f32x4::add); + /// sums.reduce_sum() + /// } + /// + /// let numbers: Vec = (1..101).map(|x| x as _).collect(); + /// assert_eq!(basic_simd_sum(&numbers[1..99]), 4949.0); + /// ``` + #[unstable(feature = "portable_simd", issue = "86656")] + #[must_use] + pub fn as_simd(&self) -> (&[T], &[Simd], &[T]) + where + Simd: AsRef<[T; LANES]>, + T: simd::SimdElement, + simd::LaneCount: simd::SupportedLaneCount, + { + // These are expected to always match, as vector types are laid out like + // arrays per , but we + // might as well double-check since it'll optimize away anyhow. + assert_eq!(mem::size_of::>(), mem::size_of::<[T; LANES]>()); + + // SAFETY: The simd types have the same layout as arrays, just with + // potentially-higher alignment, so the de-facto transmutes are sound. + unsafe { self.align_to() } + } + + /// Splits a mutable slice into a mutable prefix, a middle of aligned SIMD types, + /// and a mutable suffix. + /// + /// This is a safe wrapper around [`slice::align_to_mut`], so inherits the same + /// guarantees as that method. + /// + /// This is the mutable version of [`slice::as_simd`]; see that for examples. + /// + /// # Panics + /// + /// This will panic if the size of the SIMD type is different from + /// `LANES` times that of the scalar. + /// + /// At the time of writing, the trait restrictions on `Simd` keeps + /// that from ever happening, as only power-of-two numbers of lanes are + /// supported. It's possible that, in the future, those restrictions might + /// be lifted in a way that would make it possible to see panics from this + /// method for something like `LANES == 3`. + #[unstable(feature = "portable_simd", issue = "86656")] + #[must_use] + pub fn as_simd_mut(&mut self) -> (&mut [T], &mut [Simd], &mut [T]) + where + Simd: AsMut<[T; LANES]>, + T: simd::SimdElement, + simd::LaneCount: simd::SupportedLaneCount, + { + // These are expected to always match, as vector types are laid out like + // arrays per , but we + // might as well double-check since it'll optimize away anyhow. + assert_eq!(mem::size_of::>(), mem::size_of::<[T; LANES]>()); + + // SAFETY: The simd types have the same layout as arrays, just with + // potentially-higher alignment, so the de-facto transmutes are sound. + unsafe { self.align_to_mut() } + } + + /// Checks if the elements of this slice are sorted. + /// + /// That is, for each element `a` and its following element `b`, `a <= b` must hold. If the + /// slice yields exactly zero or one element, `true` is returned. + /// + /// Note that if `Self::Item` is only `PartialOrd`, but not `Ord`, the above definition + /// implies that this function returns `false` if any two consecutive items are not + /// comparable. + /// + /// # Examples + /// + /// ``` + /// let empty: [i32; 0] = []; + /// + /// assert!([1, 2, 2, 9].is_sorted()); + /// assert!(![1, 3, 2, 4].is_sorted()); + /// assert!([0].is_sorted()); + /// assert!(empty.is_sorted()); + /// assert!(![0.0, 1.0, f32::NAN].is_sorted()); + /// ``` + #[inline] + #[stable(feature = "is_sorted", since = "1.82.0")] + #[must_use] + pub fn is_sorted(&self) -> bool + where + T: PartialOrd, + { + // This odd number works the best. 32 + 1 extra due to overlapping chunk boundaries. + const CHUNK_SIZE: usize = 33; + if self.len() < CHUNK_SIZE { + return self.windows(2).all(|w| w[0] <= w[1]); + } + let mut i = 0; + // Check in chunks for autovectorization. + while i < self.len() - CHUNK_SIZE { + let chunk = &self[i..i + CHUNK_SIZE]; + if !chunk.windows(2).fold(true, |acc, w| acc & (w[0] <= w[1])) { + return false; + } + // We need to ensure that chunk boundaries are also sorted. + // Overlap the next chunk with the last element of our last chunk. + i += CHUNK_SIZE - 1; + } + self[i..].windows(2).all(|w| w[0] <= w[1]) + } + + /// Checks if the elements of this slice are sorted using the given comparator function. + /// + /// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare` + /// function to determine whether two elements are to be considered in sorted order. + /// + /// # Examples + /// + /// ``` + /// assert!([1, 2, 2, 9].is_sorted_by(|a, b| a <= b)); + /// assert!(![1, 2, 2, 9].is_sorted_by(|a, b| a < b)); + /// + /// assert!([0].is_sorted_by(|a, b| true)); + /// assert!([0].is_sorted_by(|a, b| false)); + /// + /// let empty: [i32; 0] = []; + /// assert!(empty.is_sorted_by(|a, b| false)); + /// assert!(empty.is_sorted_by(|a, b| true)); + /// ``` + #[stable(feature = "is_sorted", since = "1.82.0")] + #[must_use] + pub fn is_sorted_by<'a, F>(&'a self, mut compare: F) -> bool + where + F: FnMut(&'a T, &'a T) -> bool, + { + self.array_windows().all(|[a, b]| compare(a, b)) + } + + /// Checks if the elements of this slice are sorted using the given key extraction function. + /// + /// Instead of comparing the slice's elements directly, this function compares the keys of the + /// elements, as determined by `f`. Apart from that, it's equivalent to [`is_sorted`]; see its + /// documentation for more information. + /// + /// [`is_sorted`]: slice::is_sorted + /// + /// # Examples + /// + /// ``` + /// assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len())); + /// assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs())); + /// ``` + #[inline] + #[stable(feature = "is_sorted", since = "1.82.0")] + #[must_use] + pub fn is_sorted_by_key<'a, F, K>(&'a self, f: F) -> bool + where + F: FnMut(&'a T) -> K, + K: PartialOrd, + { + self.iter().is_sorted_by_key(f) + } + + /// Returns the index of the partition point according to the given predicate + /// (the index of the first element of the second partition). + /// + /// The slice is assumed to be partitioned according to the given predicate. + /// This means that all elements for which the predicate returns true are at the start of the slice + /// and all elements for which the predicate returns false are at the end. + /// For example, `[7, 15, 3, 5, 4, 12, 6]` is partitioned under the predicate `x % 2 != 0` + /// (all odd numbers are at the start, all even at the end). + /// + /// If this slice is not partitioned, the returned result is unspecified and meaningless, + /// as this method performs a kind of binary search. + /// + /// See also [`binary_search`], [`binary_search_by`], and [`binary_search_by_key`]. + /// + /// [`binary_search`]: slice::binary_search + /// [`binary_search_by`]: slice::binary_search_by + /// [`binary_search_by_key`]: slice::binary_search_by_key + /// + /// # Examples + /// + /// ``` + /// let v = [1, 2, 3, 3, 5, 6, 7]; + /// let i = v.partition_point(|&x| x < 5); + /// + /// assert_eq!(i, 4); + /// assert!(v[..i].iter().all(|&x| x < 5)); + /// assert!(v[i..].iter().all(|&x| !(x < 5))); + /// ``` + /// + /// If all elements of the slice match the predicate, including if the slice + /// is empty, then the length of the slice will be returned: + /// + /// ``` + /// let a = [2, 4, 8]; + /// assert_eq!(a.partition_point(|x| x < &100), a.len()); + /// let a: [i32; 0] = []; + /// assert_eq!(a.partition_point(|x| x < &100), 0); + /// ``` + /// + /// If you want to insert an item to a sorted vector, while maintaining + /// sort order: + /// + /// ``` + /// let mut s = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let num = 42; + /// let idx = s.partition_point(|&x| x <= num); + /// s.insert(idx, num); + /// assert_eq!(s, [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]); + /// ``` + #[stable(feature = "partition_point", since = "1.52.0")] + #[must_use] + pub fn partition_point

(&self, mut pred: P) -> usize + where + P: FnMut(&T) -> bool, + { + self.binary_search_by(|x| if pred(x) { Less } else { Greater }).unwrap_or_else(|i| i) + } + + /// Removes the subslice corresponding to the given range + /// and returns a reference to it. + /// + /// Returns `None` and does not modify the slice if the given + /// range is out of bounds. + /// + /// Note that this method only accepts one-sided ranges such as + /// `2..` or `..6`, but not `2..6`. + /// + /// # Examples + /// + /// Taking the first three elements of a slice: + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &[_] = &['a', 'b', 'c', 'd']; + /// let mut first_three = slice.take(..3).unwrap(); + /// + /// assert_eq!(slice, &['d']); + /// assert_eq!(first_three, &['a', 'b', 'c']); + /// ``` + /// + /// Taking the last two elements of a slice: + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &[_] = &['a', 'b', 'c', 'd']; + /// let mut tail = slice.take(2..).unwrap(); + /// + /// assert_eq!(slice, &['a', 'b']); + /// assert_eq!(tail, &['c', 'd']); + /// ``` + /// + /// Getting `None` when `range` is out of bounds: + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &[_] = &['a', 'b', 'c', 'd']; + /// + /// assert_eq!(None, slice.take(5..)); + /// assert_eq!(None, slice.take(..5)); + /// assert_eq!(None, slice.take(..=4)); + /// let expected: &[char] = &['a', 'b', 'c', 'd']; + /// assert_eq!(Some(expected), slice.take(..4)); + /// ``` + #[inline] + #[must_use = "method does not modify the slice if the range is out of bounds"] + #[unstable(feature = "slice_take", issue = "62280")] + pub fn take<'a, R: OneSidedRange>(self: &mut &'a Self, range: R) -> Option<&'a Self> { + let (direction, split_index) = split_point_of(range)?; + if split_index > self.len() { + return None; + } + let (front, back) = self.split_at(split_index); + match direction { + Direction::Front => { + *self = back; + Some(front) + } + Direction::Back => { + *self = front; + Some(back) + } + } + } + + /// Removes the subslice corresponding to the given range + /// and returns a mutable reference to it. + /// + /// Returns `None` and does not modify the slice if the given + /// range is out of bounds. + /// + /// Note that this method only accepts one-sided ranges such as + /// `2..` or `..6`, but not `2..6`. + /// + /// # Examples + /// + /// Taking the first three elements of a slice: + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd']; + /// let mut first_three = slice.take_mut(..3).unwrap(); + /// + /// assert_eq!(slice, &mut ['d']); + /// assert_eq!(first_three, &mut ['a', 'b', 'c']); + /// ``` + /// + /// Taking the last two elements of a slice: + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd']; + /// let mut tail = slice.take_mut(2..).unwrap(); + /// + /// assert_eq!(slice, &mut ['a', 'b']); + /// assert_eq!(tail, &mut ['c', 'd']); + /// ``` + /// + /// Getting `None` when `range` is out of bounds: + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd']; + /// + /// assert_eq!(None, slice.take_mut(5..)); + /// assert_eq!(None, slice.take_mut(..5)); + /// assert_eq!(None, slice.take_mut(..=4)); + /// let expected: &mut [_] = &mut ['a', 'b', 'c', 'd']; + /// assert_eq!(Some(expected), slice.take_mut(..4)); + /// ``` + #[inline] + #[must_use = "method does not modify the slice if the range is out of bounds"] + #[unstable(feature = "slice_take", issue = "62280")] + pub fn take_mut<'a, R: OneSidedRange>( + self: &mut &'a mut Self, + range: R, + ) -> Option<&'a mut Self> { + let (direction, split_index) = split_point_of(range)?; + if split_index > self.len() { + return None; + } + let (front, back) = mem::take(self).split_at_mut(split_index); + match direction { + Direction::Front => { + *self = back; + Some(front) + } + Direction::Back => { + *self = front; + Some(back) + } + } + } + + /// Removes the first element of the slice and returns a reference + /// to it. + /// + /// Returns `None` if the slice is empty. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &[_] = &['a', 'b', 'c']; + /// let first = slice.take_first().unwrap(); + /// + /// assert_eq!(slice, &['b', 'c']); + /// assert_eq!(first, &'a'); + /// ``` + #[inline] + #[unstable(feature = "slice_take", issue = "62280")] + pub fn take_first<'a>(self: &mut &'a Self) -> Option<&'a T> { + let (first, rem) = self.split_first()?; + *self = rem; + Some(first) + } + + /// Removes the first element of the slice and returns a mutable + /// reference to it. + /// + /// Returns `None` if the slice is empty. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c']; + /// let first = slice.take_first_mut().unwrap(); + /// *first = 'd'; + /// + /// assert_eq!(slice, &['b', 'c']); + /// assert_eq!(first, &'d'); + /// ``` + #[inline] + #[unstable(feature = "slice_take", issue = "62280")] + pub fn take_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { + let (first, rem) = mem::take(self).split_first_mut()?; + *self = rem; + Some(first) + } + + /// Removes the last element of the slice and returns a reference + /// to it. + /// + /// Returns `None` if the slice is empty. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &[_] = &['a', 'b', 'c']; + /// let last = slice.take_last().unwrap(); + /// + /// assert_eq!(slice, &['a', 'b']); + /// assert_eq!(last, &'c'); + /// ``` + #[inline] + #[unstable(feature = "slice_take", issue = "62280")] + pub fn take_last<'a>(self: &mut &'a Self) -> Option<&'a T> { + let (last, rem) = self.split_last()?; + *self = rem; + Some(last) + } + + /// Removes the last element of the slice and returns a mutable + /// reference to it. + /// + /// Returns `None` if the slice is empty. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c']; + /// let last = slice.take_last_mut().unwrap(); + /// *last = 'd'; + /// + /// assert_eq!(slice, &['a', 'b']); + /// assert_eq!(last, &'d'); + /// ``` + #[inline] + #[unstable(feature = "slice_take", issue = "62280")] + pub fn take_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { + let (last, rem) = mem::take(self).split_last_mut()?; + *self = rem; + Some(last) + } + + /// Returns mutable references to many indices at once, without doing any checks. + /// + /// An index can be either a `usize`, a [`Range`] or a [`RangeInclusive`]. Note + /// that this method takes an array, so all indices must be of the same type. + /// If passed an array of `usize`s this method gives back an array of mutable references + /// to single elements, while if passed an array of ranges it gives back an array of + /// mutable references to slices. + /// + /// For a safe alternative see [`get_many_mut`]. + /// + /// # Safety + /// + /// Calling this method with overlapping or out-of-bounds indices is *[undefined behavior]* + /// even if the resulting references are not used. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_many_mut)] + /// + /// let x = &mut [1, 2, 4]; + /// + /// unsafe { + /// let [a, b] = x.get_many_unchecked_mut([0, 2]); + /// *a *= 10; + /// *b *= 100; + /// } + /// assert_eq!(x, &[10, 2, 400]); + /// + /// unsafe { + /// let [a, b] = x.get_many_unchecked_mut([0..1, 1..3]); + /// a[0] = 8; + /// b[0] = 88; + /// b[1] = 888; + /// } + /// assert_eq!(x, &[8, 88, 888]); + /// + /// unsafe { + /// let [a, b] = x.get_many_unchecked_mut([1..=2, 0..=0]); + /// a[0] = 11; + /// a[1] = 111; + /// b[0] = 1; + /// } + /// assert_eq!(x, &[1, 11, 111]); + /// ``` + /// + /// [`get_many_mut`]: slice::get_many_mut + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + #[unstable(feature = "get_many_mut", issue = "104642")] + #[inline] + pub unsafe fn get_many_unchecked_mut( + &mut self, + indices: [I; N], + ) -> [&mut I::Output; N] + where + I: GetManyMutIndex + SliceIndex, + { + // NB: This implementation is written as it is because any variation of + // `indices.map(|i| self.get_unchecked_mut(i))` would make miri unhappy, + // or generate worse code otherwise. This is also why we need to go + // through a raw pointer here. + let slice: *mut [T] = self; + let mut arr: mem::MaybeUninit<[&mut I::Output; N]> = mem::MaybeUninit::uninit(); + let arr_ptr = arr.as_mut_ptr(); + + // SAFETY: We expect `indices` to contain disjunct values that are + // in bounds of `self`. + unsafe { + for i in 0..N { + let idx = indices.get_unchecked(i).clone(); + arr_ptr.cast::<&mut I::Output>().add(i).write(&mut *slice.get_unchecked_mut(idx)); + } + arr.assume_init() + } + } + + /// Returns mutable references to many indices at once. + /// + /// An index can be either a `usize`, a [`Range`] or a [`RangeInclusive`]. Note + /// that this method takes an array, so all indices must be of the same type. + /// If passed an array of `usize`s this method gives back an array of mutable references + /// to single elements, while if passed an array of ranges it gives back an array of + /// mutable references to slices. + /// + /// Returns an error if any index is out-of-bounds, or if there are overlapping indices. + /// An empty range is not considered to overlap if it is located at the beginning or at + /// the end of another range, but is considered to overlap if it is located in the middle. + /// + /// This method does a O(n^2) check to check that there are no overlapping indices, so be careful + /// when passing many indices. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_many_mut)] + /// + /// let v = &mut [1, 2, 3]; + /// if let Ok([a, b]) = v.get_many_mut([0, 2]) { + /// *a = 413; + /// *b = 612; + /// } + /// assert_eq!(v, &[413, 2, 612]); + /// + /// if let Ok([a, b]) = v.get_many_mut([0..1, 1..3]) { + /// a[0] = 8; + /// b[0] = 88; + /// b[1] = 888; + /// } + /// assert_eq!(v, &[8, 88, 888]); + /// + /// if let Ok([a, b]) = v.get_many_mut([1..=2, 0..=0]) { + /// a[0] = 11; + /// a[1] = 111; + /// b[0] = 1; + /// } + /// assert_eq!(v, &[1, 11, 111]); + /// ``` + #[unstable(feature = "get_many_mut", issue = "104642")] + #[inline] + pub fn get_many_mut( + &mut self, + indices: [I; N], + ) -> Result<[&mut I::Output; N], GetManyMutError> + where + I: GetManyMutIndex + SliceIndex, + { + if !get_many_check_valid(&indices, self.len()) { + return Err(GetManyMutError { _private: () }); + } + // SAFETY: The `get_many_check_valid()` call checked that all indices + // are disjunct and in bounds. + unsafe { Ok(self.get_many_unchecked_mut(indices)) } + } + + /// Returns the index that an element reference points to. + /// + /// Returns `None` if `element` does not point within the slice or if it points between elements. + /// + /// This method is useful for extending slice iterators like [`slice::split`]. + /// + /// Note that this uses pointer arithmetic and **does not compare elements**. + /// To find the index of an element via comparison, use + /// [`.iter().position()`](crate::iter::Iterator::position) instead. + /// + /// # Panics + /// Panics if `T` is zero-sized. + /// + /// # Examples + /// Basic usage: + /// ``` + /// #![feature(substr_range)] + /// + /// let nums: &[u32] = &[1, 7, 1, 1]; + /// let num = &nums[2]; + /// + /// assert_eq!(num, &1); + /// assert_eq!(nums.elem_offset(num), Some(2)); + /// ``` + /// Returning `None` with an in-between element: + /// ``` + /// #![feature(substr_range)] + /// + /// let arr: &[[u32; 2]] = &[[0, 1], [2, 3]]; + /// let flat_arr: &[u32] = arr.as_flattened(); + /// + /// let ok_elm: &[u32; 2] = flat_arr[0..2].try_into().unwrap(); + /// let weird_elm: &[u32; 2] = flat_arr[1..3].try_into().unwrap(); + /// + /// assert_eq!(ok_elm, &[0, 1]); + /// assert_eq!(weird_elm, &[1, 2]); + /// + /// assert_eq!(arr.elem_offset(ok_elm), Some(0)); // Points to element 0 + /// assert_eq!(arr.elem_offset(weird_elm), None); // Points between element 0 and 1 + /// ``` + #[must_use] + #[unstable(feature = "substr_range", issue = "126769")] + pub fn elem_offset(&self, element: &T) -> Option { + if T::IS_ZST { + panic!("elements are zero-sized"); + } + + let self_start = self.as_ptr().addr(); + let elem_start = ptr::from_ref(element).addr(); + + let byte_offset = elem_start.wrapping_sub(self_start); + + if byte_offset % mem::size_of::() != 0 { + return None; + } + + let offset = byte_offset / mem::size_of::(); + + if offset < self.len() { Some(offset) } else { None } + } + + /// Returns the range of indices that a subslice points to. + /// + /// Returns `None` if `subslice` does not point within the slice or if it points between elements. + /// + /// This method **does not compare elements**. Instead, this method finds the location in the slice that + /// `subslice` was obtained from. To find the index of a subslice via comparison, instead use + /// [`.windows()`](slice::windows)[`.position()`](crate::iter::Iterator::position). + /// + /// This method is useful for extending slice iterators like [`slice::split`]. + /// + /// Note that this may return a false positive (either `Some(0..0)` or `Some(self.len()..self.len())`) + /// if `subslice` has a length of zero and points to the beginning or end of another, separate, slice. + /// + /// # Panics + /// Panics if `T` is zero-sized. + /// + /// # Examples + /// Basic usage: + /// ``` + /// #![feature(substr_range)] + /// + /// let nums = &[0, 5, 10, 0, 0, 5]; + /// + /// let mut iter = nums + /// .split(|t| *t == 0) + /// .map(|n| nums.subslice_range(n).unwrap()); + /// + /// assert_eq!(iter.next(), Some(0..0)); + /// assert_eq!(iter.next(), Some(1..3)); + /// assert_eq!(iter.next(), Some(4..4)); + /// assert_eq!(iter.next(), Some(5..6)); + /// ``` + #[must_use] + #[unstable(feature = "substr_range", issue = "126769")] + pub fn subslice_range(&self, subslice: &[T]) -> Option> { + if T::IS_ZST { + panic!("elements are zero-sized"); + } + + let self_start = self.as_ptr().addr(); + let subslice_start = subslice.as_ptr().addr(); + + let byte_start = subslice_start.wrapping_sub(self_start); + + if byte_start % core::mem::size_of::() != 0 { + return None; + } + + let start = byte_start / core::mem::size_of::(); + let end = start.wrapping_add(subslice.len()); + + if start <= self.len() && end <= self.len() { Some(start..end) } else { None } + } +} + +impl [[T; N]] { + /// Takes a `&[[T; N]]`, and flattens it to a `&[T]`. + /// + /// # Panics + /// + /// This panics if the length of the resulting slice would overflow a `usize`. + /// + /// This is only possible when flattening a slice of arrays of zero-sized + /// types, and thus tends to be irrelevant in practice. If + /// `size_of::() > 0`, this will never panic. + /// + /// # Examples + /// + /// ``` + /// assert_eq!([[1, 2, 3], [4, 5, 6]].as_flattened(), &[1, 2, 3, 4, 5, 6]); + /// + /// assert_eq!( + /// [[1, 2, 3], [4, 5, 6]].as_flattened(), + /// [[1, 2], [3, 4], [5, 6]].as_flattened(), + /// ); + /// + /// let slice_of_empty_arrays: &[[i32; 0]] = &[[], [], [], [], []]; + /// assert!(slice_of_empty_arrays.as_flattened().is_empty()); + /// + /// let empty_slice_of_arrays: &[[u32; 10]] = &[]; + /// assert!(empty_slice_of_arrays.as_flattened().is_empty()); + /// ``` + #[stable(feature = "slice_flatten", since = "1.80.0")] + #[rustc_const_unstable(feature = "const_slice_flatten", issue = "95629")] + pub const fn as_flattened(&self) -> &[T] { + let len = if T::IS_ZST { + self.len().checked_mul(N).expect("slice len overflow") + } else { + // SAFETY: `self.len() * N` cannot overflow because `self` is + // already in the address space. + unsafe { self.len().unchecked_mul(N) } + }; + // SAFETY: `[T]` is layout-identical to `[T; N]` + unsafe { from_raw_parts(self.as_ptr().cast(), len) } + } + + /// Takes a `&mut [[T; N]]`, and flattens it to a `&mut [T]`. + /// + /// # Panics + /// + /// This panics if the length of the resulting slice would overflow a `usize`. + /// + /// This is only possible when flattening a slice of arrays of zero-sized + /// types, and thus tends to be irrelevant in practice. If + /// `size_of::() > 0`, this will never panic. + /// + /// # Examples + /// + /// ``` + /// fn add_5_to_all(slice: &mut [i32]) { + /// for i in slice { + /// *i += 5; + /// } + /// } + /// + /// let mut array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; + /// add_5_to_all(array.as_flattened_mut()); + /// assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]); + /// ``` + #[stable(feature = "slice_flatten", since = "1.80.0")] + pub fn as_flattened_mut(&mut self) -> &mut [T] { + let len = if T::IS_ZST { + self.len().checked_mul(N).expect("slice len overflow") + } else { + // SAFETY: `self.len() * N` cannot overflow because `self` is + // already in the address space. + unsafe { self.len().unchecked_mul(N) } + }; + // SAFETY: `[T]` is layout-identical to `[T; N]` + unsafe { from_raw_parts_mut(self.as_mut_ptr().cast(), len) } + } +} + +#[cfg(not(test))] +impl [f32] { + /// Sorts the slice of floats. + /// + /// This sort is in-place (i.e. does not allocate), *O*(*n* \* log(*n*)) worst-case, and uses + /// the ordering defined by [`f32::total_cmp`]. + /// + /// # Current implementation + /// + /// This uses the same sorting algorithm as [`sort_unstable_by`](slice::sort_unstable_by). + /// + /// # Examples + /// + /// ``` + /// #![feature(sort_floats)] + /// let mut v = [2.6, -5e-8, f32::NAN, 8.29, f32::INFINITY, -1.0, 0.0, -f32::INFINITY, -0.0]; + /// + /// v.sort_floats(); + /// let sorted = [-f32::INFINITY, -1.0, -5e-8, -0.0, 0.0, 2.6, 8.29, f32::INFINITY, f32::NAN]; + /// assert_eq!(&v[..8], &sorted[..8]); + /// assert!(v[8].is_nan()); + /// ``` + #[unstable(feature = "sort_floats", issue = "93396")] + #[inline] + pub fn sort_floats(&mut self) { + self.sort_unstable_by(f32::total_cmp); + } +} + +#[cfg(not(test))] +impl [f64] { + /// Sorts the slice of floats. + /// + /// This sort is in-place (i.e. does not allocate), *O*(*n* \* log(*n*)) worst-case, and uses + /// the ordering defined by [`f64::total_cmp`]. + /// + /// # Current implementation + /// + /// This uses the same sorting algorithm as [`sort_unstable_by`](slice::sort_unstable_by). + /// + /// # Examples + /// + /// ``` + /// #![feature(sort_floats)] + /// let mut v = [2.6, -5e-8, f64::NAN, 8.29, f64::INFINITY, -1.0, 0.0, -f64::INFINITY, -0.0]; + /// + /// v.sort_floats(); + /// let sorted = [-f64::INFINITY, -1.0, -5e-8, -0.0, 0.0, 2.6, 8.29, f64::INFINITY, f64::NAN]; + /// assert_eq!(&v[..8], &sorted[..8]); + /// assert!(v[8].is_nan()); + /// ``` + #[unstable(feature = "sort_floats", issue = "93396")] + #[inline] + pub fn sort_floats(&mut self) { + self.sort_unstable_by(f64::total_cmp); + } +} + +trait CloneFromSpec { + fn spec_clone_from(&mut self, src: &[T]); +} + +impl CloneFromSpec for [T] +where + T: Clone, +{ + #[track_caller] + default fn spec_clone_from(&mut self, src: &[T]) { + assert!(self.len() == src.len(), "destination and source slices have different lengths"); + // NOTE: We need to explicitly slice them to the same length + // to make it easier for the optimizer to elide bounds checking. + // But since it can't be relied on we also have an explicit specialization for T: Copy. + let len = self.len(); + let src = &src[..len]; + for i in 0..len { + self[i].clone_from(&src[i]); + } + } +} + +impl CloneFromSpec for [T] +where + T: Copy, +{ + #[track_caller] + fn spec_clone_from(&mut self, src: &[T]) { + self.copy_from_slice(src); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for &[T] { + /// Creates an empty slice. + fn default() -> Self { + &[] + } +} + +#[stable(feature = "mut_slice_default", since = "1.5.0")] +impl Default for &mut [T] { + /// Creates a mutable empty slice. + fn default() -> Self { + &mut [] + } +} + +#[unstable(feature = "slice_pattern", reason = "stopgap trait for slice patterns", issue = "56345")] +/// Patterns in slices - currently, only used by `strip_prefix` and `strip_suffix`. At a future +/// point, we hope to generalise `core::str::Pattern` (which at the time of writing is limited to +/// `str`) to slices, and then this trait will be replaced or abolished. +pub trait SlicePattern { + /// The element type of the slice being matched on. + type Item; + + /// Currently, the consumers of `SlicePattern` need a slice. + fn as_slice(&self) -> &[Self::Item]; +} + +#[stable(feature = "slice_strip", since = "1.51.0")] +impl SlicePattern for [T] { + type Item = T; + + #[inline] + fn as_slice(&self) -> &[Self::Item] { + self + } +} + +#[stable(feature = "slice_strip", since = "1.51.0")] +impl SlicePattern for [T; N] { + type Item = T; + + #[inline] + fn as_slice(&self) -> &[Self::Item] { + self + } +} + +/// This checks every index against each other, and against `len`. +/// +/// This will do `binomial(N + 1, 2) = N * (N + 1) / 2 = 0, 1, 3, 6, 10, ..` +/// comparison operations. +#[inline] +fn get_many_check_valid(indices: &[I; N], len: usize) -> bool { + // NB: The optimizer should inline the loops into a sequence + // of instructions without additional branching. + let mut valid = true; + for (i, idx) in indices.iter().enumerate() { + valid &= idx.is_in_bounds(len); + for idx2 in &indices[..i] { + valid &= !idx.is_overlapping(idx2); + } + } + valid +} + +/// The error type returned by [`get_many_mut`][`slice::get_many_mut`]. +/// +/// It indicates one of two possible errors: +/// - An index is out-of-bounds. +/// - The same index appeared multiple times in the array. +/// +/// # Examples +/// +/// ``` +/// #![feature(get_many_mut)] +/// +/// let v = &mut [1, 2, 3]; +/// assert!(v.get_many_mut([0, 999]).is_err()); +/// assert!(v.get_many_mut([1, 1]).is_err()); +/// ``` +#[unstable(feature = "get_many_mut", issue = "104642")] +// NB: The N here is there to be forward-compatible with adding more details +// to the error type at a later point +#[derive(Clone, PartialEq, Eq)] +pub struct GetManyMutError { + _private: (), +} + +#[unstable(feature = "get_many_mut", issue = "104642")] +impl fmt::Debug for GetManyMutError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("GetManyMutError").finish_non_exhaustive() + } +} + +#[unstable(feature = "get_many_mut", issue = "104642")] +impl fmt::Display for GetManyMutError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt("an index is out of bounds or appeared multiple times in the array", f) + } +} + +mod private_get_many_mut_index { + use super::{Range, RangeInclusive, range}; + + #[unstable(feature = "get_many_mut_helpers", issue = "none")] + pub trait Sealed {} + + #[unstable(feature = "get_many_mut_helpers", issue = "none")] + impl Sealed for usize {} + #[unstable(feature = "get_many_mut_helpers", issue = "none")] + impl Sealed for Range {} + #[unstable(feature = "get_many_mut_helpers", issue = "none")] + impl Sealed for RangeInclusive {} + #[unstable(feature = "get_many_mut_helpers", issue = "none")] + impl Sealed for range::Range {} + #[unstable(feature = "get_many_mut_helpers", issue = "none")] + impl Sealed for range::RangeInclusive {} +} + +/// A helper trait for `<[T]>::get_many_mut()`. +/// +/// # Safety +/// +/// If `is_in_bounds()` returns `true` and `is_overlapping()` returns `false`, +/// it must be safe to index the slice with the indices. +#[unstable(feature = "get_many_mut_helpers", issue = "none")] +pub unsafe trait GetManyMutIndex: Clone + private_get_many_mut_index::Sealed { + /// Returns `true` if `self` is in bounds for `len` slice elements. + #[unstable(feature = "get_many_mut_helpers", issue = "none")] + fn is_in_bounds(&self, len: usize) -> bool; + + /// Returns `true` if `self` overlaps with `other`. + /// + /// Note that we don't consider zero-length ranges to overlap at the beginning or the end, + /// but do consider them to overlap in the middle. + #[unstable(feature = "get_many_mut_helpers", issue = "none")] + fn is_overlapping(&self, other: &Self) -> bool; +} + +#[unstable(feature = "get_many_mut_helpers", issue = "none")] +// SAFETY: We implement `is_in_bounds()` and `is_overlapping()` correctly. +unsafe impl GetManyMutIndex for usize { + #[inline] + fn is_in_bounds(&self, len: usize) -> bool { + *self < len + } + + #[inline] + fn is_overlapping(&self, other: &Self) -> bool { + *self == *other + } +} + +#[unstable(feature = "get_many_mut_helpers", issue = "none")] +// SAFETY: We implement `is_in_bounds()` and `is_overlapping()` correctly. +unsafe impl GetManyMutIndex for Range { + #[inline] + fn is_in_bounds(&self, len: usize) -> bool { + (self.start <= self.end) & (self.end <= len) + } + + #[inline] + fn is_overlapping(&self, other: &Self) -> bool { + (self.start < other.end) & (other.start < self.end) + } +} + +#[unstable(feature = "get_many_mut_helpers", issue = "none")] +// SAFETY: We implement `is_in_bounds()` and `is_overlapping()` correctly. +unsafe impl GetManyMutIndex for RangeInclusive { + #[inline] + fn is_in_bounds(&self, len: usize) -> bool { + (self.start <= self.end) & (self.end < len) + } + + #[inline] + fn is_overlapping(&self, other: &Self) -> bool { + (self.start <= other.end) & (other.start <= self.end) + } +} + +#[unstable(feature = "get_many_mut_helpers", issue = "none")] +// SAFETY: We implement `is_in_bounds()` and `is_overlapping()` correctly. +unsafe impl GetManyMutIndex for range::Range { + #[inline] + fn is_in_bounds(&self, len: usize) -> bool { + Range::from(*self).is_in_bounds(len) + } + + #[inline] + fn is_overlapping(&self, other: &Self) -> bool { + Range::from(*self).is_overlapping(&Range::from(*other)) + } +} + +#[unstable(feature = "get_many_mut_helpers", issue = "none")] +// SAFETY: We implement `is_in_bounds()` and `is_overlapping()` correctly. +unsafe impl GetManyMutIndex for range::RangeInclusive { + #[inline] + fn is_in_bounds(&self, len: usize) -> bool { + RangeInclusive::from(*self).is_in_bounds(len) + } + + #[inline] + fn is_overlapping(&self, other: &Self) -> bool { + RangeInclusive::from(*self).is_overlapping(&RangeInclusive::from(*other)) + } +} diff --git a/CoqOfRust/core/slice/raw.rs b/CoqOfRust/core/slice/raw.rs new file mode 100644 index 000000000..319b76899 --- /dev/null +++ b/CoqOfRust/core/slice/raw.rs @@ -0,0 +1,346 @@ +//! Free functions to create `&[T]` and `&mut [T]`. + +use crate::ops::Range; +use crate::{array, ptr, ub_checks}; + +/// Forms a slice from a pointer and a length. +/// +/// The `len` argument is the number of **elements**, not the number of bytes. +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `data` must be non-null, [valid] for reads for `len * mem::size_of::()` many bytes, +/// and it must be properly aligned. This means in particular: +/// +/// * The entire memory range of this slice must be contained within a single allocated object! +/// Slices can never span across multiple allocated objects. See [below](#incorrect-usage) +/// for an example incorrectly not taking this into account. +/// * `data` must be non-null and aligned even for zero-length slices or slices of ZSTs. One +/// reason for this is that enum layout optimizations may rely on references +/// (including slices of any length) being aligned and non-null to distinguish +/// them from other data. You can obtain a pointer that is usable as `data` +/// for zero-length slices using [`NonNull::dangling()`]. +/// +/// * `data` must point to `len` consecutive properly initialized values of type `T`. +/// +/// * The memory referenced by the returned slice must not be mutated for the duration +/// of lifetime `'a`, except inside an `UnsafeCell`. +/// +/// * The total size `len * mem::size_of::()` of the slice must be no larger than `isize::MAX`, +/// and adding that size to `data` must not "wrap around" the address space. +/// See the safety documentation of [`pointer::offset`]. +/// +/// # Caveat +/// +/// The lifetime for the returned slice is inferred from its usage. To +/// prevent accidental misuse, it's suggested to tie the lifetime to whichever +/// source lifetime is safe in the context, such as by providing a helper +/// function taking the lifetime of a host value for the slice, or by explicit +/// annotation. +/// +/// # Examples +/// +/// ``` +/// use std::slice; +/// +/// // manifest a slice for a single element +/// let x = 42; +/// let ptr = &x as *const _; +/// let slice = unsafe { slice::from_raw_parts(ptr, 1) }; +/// assert_eq!(slice[0], 42); +/// ``` +/// +/// ### Incorrect usage +/// +/// The following `join_slices` function is **unsound** ⚠️ +/// +/// ```rust,no_run +/// use std::slice; +/// +/// fn join_slices<'a, T>(fst: &'a [T], snd: &'a [T]) -> &'a [T] { +/// let fst_end = fst.as_ptr().wrapping_add(fst.len()); +/// let snd_start = snd.as_ptr(); +/// assert_eq!(fst_end, snd_start, "Slices must be contiguous!"); +/// unsafe { +/// // The assertion above ensures `fst` and `snd` are contiguous, but they might +/// // still be contained within _different allocated objects_, in which case +/// // creating this slice is undefined behavior. +/// slice::from_raw_parts(fst.as_ptr(), fst.len() + snd.len()) +/// } +/// } +/// +/// fn main() { +/// // `a` and `b` are different allocated objects... +/// let a = 42; +/// let b = 27; +/// // ... which may nevertheless be laid out contiguously in memory: | a | b | +/// let _ = join_slices(slice::from_ref(&a), slice::from_ref(&b)); // UB +/// } +/// ``` +/// +/// ### FFI: Handling null pointers +/// +/// In languages such as C++, pointers to empty collections are not guaranteed to be non-null. +/// When accepting such pointers, they have to be checked for null-ness to avoid undefined +/// behavior. +/// +/// ``` +/// use std::slice; +/// +/// /// Sum the elements of an FFI slice. +/// /// +/// /// # Safety +/// /// +/// /// If ptr is not NULL, it must be correctly aligned and +/// /// point to `len` initialized items of type `f32`. +/// unsafe extern "C" fn sum_slice(ptr: *const f32, len: usize) -> f32 { +/// let data = if ptr.is_null() { +/// // `len` is assumed to be 0. +/// &[] +/// } else { +/// // SAFETY: see function docstring. +/// unsafe { slice::from_raw_parts(ptr, len) } +/// }; +/// data.into_iter().sum() +/// } +/// +/// // This could be the result of C++'s std::vector::data(): +/// let ptr = std::ptr::null(); +/// // And this could be std::vector::size(): +/// let len = 0; +/// assert_eq!(unsafe { sum_slice(ptr, len) }, 0.0); +/// ``` +/// +/// [valid]: ptr#safety +/// [`NonNull::dangling()`]: ptr::NonNull::dangling +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_slice_from_raw_parts", since = "1.64.0")] +#[must_use] +#[rustc_diagnostic_item = "slice_from_raw_parts"] +pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { + // SAFETY: the caller must uphold the safety contract for `from_raw_parts`. + unsafe { + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`", + ( + data: *mut () = data as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + len: usize = len, + ) => + ub_checks::maybe_is_aligned_and_not_null(data, align, false) + && ub_checks::is_valid_allocation_size(size, len) + ); + &*ptr::slice_from_raw_parts(data, len) + } +} + +/// Performs the same functionality as [`from_raw_parts`], except that a +/// mutable slice is returned. +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `data` must be non-null, [valid] for both reads and writes for `len * mem::size_of::()` many bytes, +/// and it must be properly aligned. This means in particular: +/// +/// * The entire memory range of this slice must be contained within a single allocated object! +/// Slices can never span across multiple allocated objects. +/// * `data` must be non-null and aligned even for zero-length slices or slices of ZSTs. One +/// reason for this is that enum layout optimizations may rely on references +/// (including slices of any length) being aligned and non-null to distinguish +/// them from other data. You can obtain a pointer that is usable as `data` +/// for zero-length slices using [`NonNull::dangling()`]. +/// +/// * `data` must point to `len` consecutive properly initialized values of type `T`. +/// +/// * The memory referenced by the returned slice must not be accessed through any other pointer +/// (not derived from the return value) for the duration of lifetime `'a`. +/// Both read and write accesses are forbidden. +/// +/// * The total size `len * mem::size_of::()` of the slice must be no larger than `isize::MAX`, +/// and adding that size to `data` must not "wrap around" the address space. +/// See the safety documentation of [`pointer::offset`]. +/// +/// [valid]: ptr#safety +/// [`NonNull::dangling()`]: ptr::NonNull::dangling +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")] +#[must_use] +#[rustc_diagnostic_item = "slice_from_raw_parts_mut"] +pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { + // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`. + unsafe { + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "slice::from_raw_parts_mut requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`", + ( + data: *mut () = data as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + len: usize = len, + ) => + ub_checks::maybe_is_aligned_and_not_null(data, align, false) + && ub_checks::is_valid_allocation_size(size, len) + ); + &mut *ptr::slice_from_raw_parts_mut(data, len) + } +} + +/// Converts a reference to T into a slice of length 1 (without copying). +#[stable(feature = "from_ref", since = "1.28.0")] +#[rustc_const_stable(feature = "const_slice_from_ref_shared", since = "1.63.0")] +#[must_use] +pub const fn from_ref(s: &T) -> &[T] { + array::from_ref(s) +} + +/// Converts a reference to T into a slice of length 1 (without copying). +#[stable(feature = "from_ref", since = "1.28.0")] +#[rustc_const_stable(feature = "const_slice_from_ref", since = "1.83.0")] +#[must_use] +pub const fn from_mut(s: &mut T) -> &mut [T] { + array::from_mut(s) +} + +/// Forms a slice from a pointer range. +/// +/// This function is useful for interacting with foreign interfaces which +/// use two pointers to refer to a range of elements in memory, as is +/// common in C++. +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * The `start` pointer of the range must be a non-null, [valid] and properly aligned pointer +/// to the first element of a slice. +/// +/// * The `end` pointer must be a [valid] and properly aligned pointer to *one past* +/// the last element, such that the offset from the end to the start pointer is +/// the length of the slice. +/// +/// * The entire memory range of this slice must be contained within a single allocated object! +/// Slices can never span across multiple allocated objects. +/// +/// * The range must contain `N` consecutive properly initialized values of type `T`. +/// +/// * The memory referenced by the returned slice must not be mutated for the duration +/// of lifetime `'a`, except inside an `UnsafeCell`. +/// +/// * The total length of the range must be no larger than `isize::MAX`, +/// and adding that size to `start` must not "wrap around" the address space. +/// See the safety documentation of [`pointer::offset`]. +/// +/// Note that a range created from [`slice::as_ptr_range`] fulfills these requirements. +/// +/// # Panics +/// +/// This function panics if `T` is a Zero-Sized Type (“ZST”). +/// +/// # Caveat +/// +/// The lifetime for the returned slice is inferred from its usage. To +/// prevent accidental misuse, it's suggested to tie the lifetime to whichever +/// source lifetime is safe in the context, such as by providing a helper +/// function taking the lifetime of a host value for the slice, or by explicit +/// annotation. +/// +/// # Examples +/// +/// ``` +/// #![feature(slice_from_ptr_range)] +/// +/// use core::slice; +/// +/// let x = [1, 2, 3]; +/// let range = x.as_ptr_range(); +/// +/// unsafe { +/// assert_eq!(slice::from_ptr_range(range), &x); +/// } +/// ``` +/// +/// [valid]: ptr#safety +#[unstable(feature = "slice_from_ptr_range", issue = "89792")] +#[rustc_const_unstable(feature = "const_slice_from_ptr_range", issue = "89792")] +pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] { + // SAFETY: the caller must uphold the safety contract for `from_ptr_range`. + unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) } +} + +/// Forms a mutable slice from a pointer range. +/// +/// This is the same functionality as [`from_ptr_range`], except that a +/// mutable slice is returned. +/// +/// This function is useful for interacting with foreign interfaces which +/// use two pointers to refer to a range of elements in memory, as is +/// common in C++. +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * The `start` pointer of the range must be a non-null, [valid] and properly aligned pointer +/// to the first element of a slice. +/// +/// * The `end` pointer must be a [valid] and properly aligned pointer to *one past* +/// the last element, such that the offset from the end to the start pointer is +/// the length of the slice. +/// +/// * The entire memory range of this slice must be contained within a single allocated object! +/// Slices can never span across multiple allocated objects. +/// +/// * The range must contain `N` consecutive properly initialized values of type `T`. +/// +/// * The memory referenced by the returned slice must not be accessed through any other pointer +/// (not derived from the return value) for the duration of lifetime `'a`. +/// Both read and write accesses are forbidden. +/// +/// * The total length of the range must be no larger than `isize::MAX`, +/// and adding that size to `start` must not "wrap around" the address space. +/// See the safety documentation of [`pointer::offset`]. +/// +/// Note that a range created from [`slice::as_mut_ptr_range`] fulfills these requirements. +/// +/// # Panics +/// +/// This function panics if `T` is a Zero-Sized Type (“ZST”). +/// +/// # Caveat +/// +/// The lifetime for the returned slice is inferred from its usage. To +/// prevent accidental misuse, it's suggested to tie the lifetime to whichever +/// source lifetime is safe in the context, such as by providing a helper +/// function taking the lifetime of a host value for the slice, or by explicit +/// annotation. +/// +/// # Examples +/// +/// ``` +/// #![feature(slice_from_ptr_range)] +/// +/// use core::slice; +/// +/// let mut x = [1, 2, 3]; +/// let range = x.as_mut_ptr_range(); +/// +/// unsafe { +/// assert_eq!(slice::from_mut_ptr_range(range), &mut [1, 2, 3]); +/// } +/// ``` +/// +/// [valid]: ptr#safety +#[unstable(feature = "slice_from_ptr_range", issue = "89792")] +#[rustc_const_unstable(feature = "const_slice_from_mut_ptr_range", issue = "89792")] +pub const unsafe fn from_mut_ptr_range<'a, T>(range: Range<*mut T>) -> &'a mut [T] { + // SAFETY: the caller must uphold the safety contract for `from_mut_ptr_range`. + unsafe { from_raw_parts_mut(range.start, range.end.sub_ptr(range.start)) } +} diff --git a/CoqOfRust/core/slice/rotate.rs b/CoqOfRust/core/slice/rotate.rs new file mode 100644 index 000000000..1e4865a7c --- /dev/null +++ b/CoqOfRust/core/slice/rotate.rs @@ -0,0 +1,237 @@ +use crate::mem::{self, MaybeUninit, SizedTypeProperties}; +use crate::{cmp, ptr}; + +/// Rotates the range `[mid-left, mid+right)` such that the element at `mid` becomes the first +/// element. Equivalently, rotates the range `left` elements to the left or `right` elements to the +/// right. +/// +/// # Safety +/// +/// The specified range must be valid for reading and writing. +/// +/// # Algorithm +/// +/// Algorithm 1 is used for small values of `left + right` or for large `T`. The elements are moved +/// into their final positions one at a time starting at `mid - left` and advancing by `right` steps +/// modulo `left + right`, such that only one temporary is needed. Eventually, we arrive back at +/// `mid - left`. However, if `gcd(left + right, right)` is not 1, the above steps skipped over +/// elements. For example: +/// ```text +/// left = 10, right = 6 +/// the `^` indicates an element in its final place +/// 6 7 8 9 10 11 12 13 14 15 . 0 1 2 3 4 5 +/// after using one step of the above algorithm (The X will be overwritten at the end of the round, +/// and 12 is stored in a temporary): +/// X 7 8 9 10 11 6 13 14 15 . 0 1 2 3 4 5 +/// ^ +/// after using another step (now 2 is in the temporary): +/// X 7 8 9 10 11 6 13 14 15 . 0 1 12 3 4 5 +/// ^ ^ +/// after the third step (the steps wrap around, and 8 is in the temporary): +/// X 7 2 9 10 11 6 13 14 15 . 0 1 12 3 4 5 +/// ^ ^ ^ +/// after 7 more steps, the round ends with the temporary 0 getting put in the X: +/// 0 7 2 9 4 11 6 13 8 15 . 10 1 12 3 14 5 +/// ^ ^ ^ ^ ^ ^ ^ ^ +/// ``` +/// Fortunately, the number of skipped over elements between finalized elements is always equal, so +/// we can just offset our starting position and do more rounds (the total number of rounds is the +/// `gcd(left + right, right)` value). The end result is that all elements are finalized once and +/// only once. +/// +/// Algorithm 2 is used if `left + right` is large but `min(left, right)` is small enough to +/// fit onto a stack buffer. The `min(left, right)` elements are copied onto the buffer, `memmove` +/// is applied to the others, and the ones on the buffer are moved back into the hole on the +/// opposite side of where they originated. +/// +/// Algorithms that can be vectorized outperform the above once `left + right` becomes large enough. +/// Algorithm 1 can be vectorized by chunking and performing many rounds at once, but there are too +/// few rounds on average until `left + right` is enormous, and the worst case of a single +/// round is always there. Instead, algorithm 3 utilizes repeated swapping of +/// `min(left, right)` elements until a smaller rotate problem is left. +/// +/// ```text +/// left = 11, right = 4 +/// [4 5 6 7 8 9 10 11 12 13 14 . 0 1 2 3] +/// ^ ^ ^ ^ ^ ^ ^ ^ swapping the right most elements with elements to the left +/// [4 5 6 7 8 9 10 . 0 1 2 3] 11 12 13 14 +/// ^ ^ ^ ^ ^ ^ ^ ^ swapping these +/// [4 5 6 . 0 1 2 3] 7 8 9 10 11 12 13 14 +/// we cannot swap any more, but a smaller rotation problem is left to solve +/// ``` +/// when `left < right` the swapping happens from the left instead. +pub unsafe fn ptr_rotate(mut left: usize, mut mid: *mut T, mut right: usize) { + type BufType = [usize; 32]; + if T::IS_ZST { + return; + } + loop { + // N.B. the below algorithms can fail if these cases are not checked + if (right == 0) || (left == 0) { + return; + } + if !cfg!(feature = "optimize_for_size") + && ((left + right < 24) || (mem::size_of::() > mem::size_of::<[usize; 4]>())) + { + // Algorithm 1 + // Microbenchmarks indicate that the average performance for random shifts is better all + // the way until about `left + right == 32`, but the worst case performance breaks even + // around 16. 24 was chosen as middle ground. If the size of `T` is larger than 4 + // `usize`s, this algorithm also outperforms other algorithms. + // SAFETY: callers must ensure `mid - left` is valid for reading and writing. + let x = unsafe { mid.sub(left) }; + // beginning of first round + // SAFETY: see previous comment. + let mut tmp: T = unsafe { x.read() }; + let mut i = right; + // `gcd` can be found before hand by calculating `gcd(left + right, right)`, + // but it is faster to do one loop which calculates the gcd as a side effect, then + // doing the rest of the chunk + let mut gcd = right; + // benchmarks reveal that it is faster to swap temporaries all the way through instead + // of reading one temporary once, copying backwards, and then writing that temporary at + // the very end. This is possibly due to the fact that swapping or replacing temporaries + // uses only one memory address in the loop instead of needing to manage two. + loop { + // [long-safety-expl] + // SAFETY: callers must ensure `[left, left+mid+right)` are all valid for reading and + // writing. + // + // - `i` start with `right` so `mid-left <= x+i = x+right = mid-left+right < mid+right` + // - `i <= left+right-1` is always true + // - if `i < left`, `right` is added so `i < left+right` and on the next + // iteration `left` is removed from `i` so it doesn't go further + // - if `i >= left`, `left` is removed immediately and so it doesn't go further. + // - overflows cannot happen for `i` since the function's safety contract ask for + // `mid+right-1 = x+left+right` to be valid for writing + // - underflows cannot happen because `i` must be bigger or equal to `left` for + // a subtraction of `left` to happen. + // + // So `x+i` is valid for reading and writing if the caller respected the contract + tmp = unsafe { x.add(i).replace(tmp) }; + // instead of incrementing `i` and then checking if it is outside the bounds, we + // check if `i` will go outside the bounds on the next increment. This prevents + // any wrapping of pointers or `usize`. + if i >= left { + i -= left; + if i == 0 { + // end of first round + // SAFETY: tmp has been read from a valid source and x is valid for writing + // according to the caller. + unsafe { x.write(tmp) }; + break; + } + // this conditional must be here if `left + right >= 15` + if i < gcd { + gcd = i; + } + } else { + i += right; + } + } + // finish the chunk with more rounds + for start in 1..gcd { + // SAFETY: `gcd` is at most equal to `right` so all values in `1..gcd` are valid for + // reading and writing as per the function's safety contract, see [long-safety-expl] + // above + tmp = unsafe { x.add(start).read() }; + // [safety-expl-addition] + // + // Here `start < gcd` so `start < right` so `i < right+right`: `right` being the + // greatest common divisor of `(left+right, right)` means that `left = right` so + // `i < left+right` so `x+i = mid-left+i` is always valid for reading and writing + // according to the function's safety contract. + i = start + right; + loop { + // SAFETY: see [long-safety-expl] and [safety-expl-addition] + tmp = unsafe { x.add(i).replace(tmp) }; + if i >= left { + i -= left; + if i == start { + // SAFETY: see [long-safety-expl] and [safety-expl-addition] + unsafe { x.add(start).write(tmp) }; + break; + } + } else { + i += right; + } + } + } + return; + // `T` is not a zero-sized type, so it's okay to divide by its size. + } else if !cfg!(feature = "optimize_for_size") + && cmp::min(left, right) <= mem::size_of::() / mem::size_of::() + { + // Algorithm 2 + // The `[T; 0]` here is to ensure this is appropriately aligned for T + let mut rawarray = MaybeUninit::<(BufType, [T; 0])>::uninit(); + let buf = rawarray.as_mut_ptr() as *mut T; + // SAFETY: `mid-left <= mid-left+right < mid+right` + let dim = unsafe { mid.sub(left).add(right) }; + if left <= right { + // SAFETY: + // + // 1) The `else if` condition about the sizes ensures `[mid-left; left]` will fit in + // `buf` without overflow and `buf` was created just above and so cannot be + // overlapped with any value of `[mid-left; left]` + // 2) [mid-left, mid+right) are all valid for reading and writing and we don't care + // about overlaps here. + // 3) The `if` condition about `left <= right` ensures writing `left` elements to + // `dim = mid-left+right` is valid because: + // - `buf` is valid and `left` elements were written in it in 1) + // - `dim+left = mid-left+right+left = mid+right` and we write `[dim, dim+left)` + unsafe { + // 1) + ptr::copy_nonoverlapping(mid.sub(left), buf, left); + // 2) + ptr::copy(mid, mid.sub(left), right); + // 3) + ptr::copy_nonoverlapping(buf, dim, left); + } + } else { + // SAFETY: same reasoning as above but with `left` and `right` reversed + unsafe { + ptr::copy_nonoverlapping(mid, buf, right); + ptr::copy(mid.sub(left), dim, left); + ptr::copy_nonoverlapping(buf, mid.sub(left), right); + } + } + return; + } else if left >= right { + // Algorithm 3 + // There is an alternate way of swapping that involves finding where the last swap + // of this algorithm would be, and swapping using that last chunk instead of swapping + // adjacent chunks like this algorithm is doing, but this way is still faster. + loop { + // SAFETY: + // `left >= right` so `[mid-right, mid+right)` is valid for reading and writing + // Subtracting `right` from `mid` each turn is counterbalanced by the addition and + // check after it. + unsafe { + ptr::swap_nonoverlapping(mid.sub(right), mid, right); + mid = mid.sub(right); + } + left -= right; + if left < right { + break; + } + } + } else { + // Algorithm 3, `left < right` + loop { + // SAFETY: `[mid-left, mid+left)` is valid for reading and writing because + // `left < right` so `mid+left < mid+right`. + // Adding `left` to `mid` each turn is counterbalanced by the subtraction and check + // after it. + unsafe { + ptr::swap_nonoverlapping(mid.sub(left), mid, left); + mid = mid.add(left); + } + right -= left; + if right < left { + break; + } + } + } + } +} diff --git a/CoqOfRust/core/slice/sort/mod.rs b/CoqOfRust/core/slice/sort/mod.rs new file mode 100644 index 000000000..79852708b --- /dev/null +++ b/CoqOfRust/core/slice/sort/mod.rs @@ -0,0 +1,8 @@ +//! This module and the contained sub-modules contains the code for efficient and robust sort +//! implementations, as well as the domain adjacent implementation of `select_nth_unstable`. + +pub mod stable; +pub mod unstable; + +pub(crate) mod select; +pub(crate) mod shared; diff --git a/CoqOfRust/core/slice/sort/select.rs b/CoqOfRust/core/slice/sort/select.rs new file mode 100644 index 000000000..3358c03d3 --- /dev/null +++ b/CoqOfRust/core/slice/sort/select.rs @@ -0,0 +1,309 @@ +//! This module contains the implementation for `slice::select_nth_unstable`. +//! It uses an introselect algorithm based on ipnsort by Lukas Bergdoll and Orson Peters, +//! published at: +//! +//! The fallback algorithm used for introselect is Median of Medians using Tukey's Ninther +//! for pivot selection. Using this as a fallback ensures O(n) worst case running time with +//! better performance than one would get using heapsort as fallback. + +use crate::mem::{self, SizedTypeProperties}; +#[cfg(not(feature = "optimize_for_size"))] +use crate::slice::sort::shared::pivot::choose_pivot; +use crate::slice::sort::shared::smallsort::insertion_sort_shift_left; +use crate::slice::sort::unstable::quicksort::partition; + +/// Reorders the slice such that the element at `index` is at its final sorted position. +pub(crate) fn partition_at_index( + v: &mut [T], + index: usize, + mut is_less: F, +) -> (&mut [T], &mut T, &mut [T]) +where + F: FnMut(&T, &T) -> bool, +{ + let len = v.len(); + + // Puts a lower limit of 1 on `len`. + if index >= len { + panic!("partition_at_index index {} greater than length of slice {}", index, len); + } + + if T::IS_ZST { + // Sorting has no meaningful behavior on zero-sized types. Do nothing. + } else if index == len - 1 { + // Find max element and place it in the last position of the array. We're free to use + // `unwrap()` here because we checked that `v` is not empty. + let max_idx = max_index(v, &mut is_less).unwrap(); + v.swap(max_idx, index); + } else if index == 0 { + // Find min element and place it in the first position of the array. We're free to use + // `unwrap()` here because we checked that `v` is not empty. + let min_idx = min_index(v, &mut is_less).unwrap(); + v.swap(min_idx, index); + } else { + cfg_if! { + if #[cfg(feature = "optimize_for_size")] { + median_of_medians(v, &mut is_less, index); + } else { + partition_at_index_loop(v, index, None, &mut is_less); + } + } + } + + let (left, right) = v.split_at_mut(index); + let (pivot, right) = right.split_at_mut(1); + let pivot = &mut pivot[0]; + (left, pivot, right) +} + +// For small sub-slices it's faster to use a dedicated small-sort, but because it is only called at +// most once, it doesn't make sense to use something more sophisticated than insertion-sort. +const INSERTION_SORT_THRESHOLD: usize = 16; + +#[cfg(not(feature = "optimize_for_size"))] +fn partition_at_index_loop<'a, T, F>( + mut v: &'a mut [T], + mut index: usize, + mut ancestor_pivot: Option<&'a T>, + is_less: &mut F, +) where + F: FnMut(&T, &T) -> bool, +{ + // Limit the amount of iterations and fall back to fast deterministic selection to ensure O(n) + // worst case running time. This limit needs to be constant, because using `ilog2(len)` like in + // `sort` would result in O(n log n) time complexity. The exact value of the limit is chosen + // somewhat arbitrarily, but for most inputs bad pivot selections should be relatively rare, so + // the limit is reached for sub-slices len / (2^limit or less). Which makes the remaining work + // with the fallback minimal in relative terms. + let mut limit = 16; + + loop { + if v.len() <= INSERTION_SORT_THRESHOLD { + if v.len() >= 2 { + insertion_sort_shift_left(v, 1, is_less); + } + return; + } + + if limit == 0 { + median_of_medians(v, is_less, index); + return; + } + + limit -= 1; + + // Choose a pivot + let pivot_pos = choose_pivot(v, is_less); + + // If the chosen pivot is equal to the predecessor, then it's the smallest element in the + // slice. Partition the slice into elements equal to and elements greater than the pivot. + // This case is usually hit when the slice contains many duplicate elements. + if let Some(p) = ancestor_pivot { + // SAFETY: choose_pivot promises to return a valid pivot position. + let pivot = unsafe { v.get_unchecked(pivot_pos) }; + + if !is_less(p, pivot) { + let num_lt = partition(v, pivot_pos, &mut |a, b| !is_less(b, a)); + + // Continue sorting elements greater than the pivot. We know that `mid` contains + // the pivot. So we can continue after `mid`. + let mid = num_lt + 1; + + // If we've passed our index, then we're good. + if mid > index { + return; + } + + v = &mut v[mid..]; + index = index - mid; + ancestor_pivot = None; + continue; + } + } + + let mid = partition(v, pivot_pos, is_less); + + // Split the slice into `left`, `pivot`, and `right`. + let (left, right) = v.split_at_mut(mid); + let (pivot, right) = right.split_at_mut(1); + let pivot = &pivot[0]; + + if mid < index { + v = right; + index = index - mid - 1; + ancestor_pivot = Some(pivot); + } else if mid > index { + v = left; + } else { + // If mid == index, then we're done, since partition() guaranteed that all elements + // after mid are greater than or equal to mid. + return; + } + } +} + +/// Helper function that returns the index of the minimum element in the slice using the given +/// comparator function +fn min_index bool>(slice: &[T], is_less: &mut F) -> Option { + slice + .iter() + .enumerate() + .reduce(|acc, t| if is_less(t.1, acc.1) { t } else { acc }) + .map(|(i, _)| i) +} + +/// Helper function that returns the index of the maximum element in the slice using the given +/// comparator function +fn max_index bool>(slice: &[T], is_less: &mut F) -> Option { + slice + .iter() + .enumerate() + .reduce(|acc, t| if is_less(acc.1, t.1) { t } else { acc }) + .map(|(i, _)| i) +} + +/// Selection algorithm to select the k-th element from the slice in guaranteed O(n) time. +/// This is essentially a quickselect that uses Tukey's Ninther for pivot selection +fn median_of_medians bool>(mut v: &mut [T], is_less: &mut F, mut k: usize) { + // Since this function isn't public, it should never be called with an out-of-bounds index. + debug_assert!(k < v.len()); + + // If T is as ZST, `partition_at_index` will already return early. + debug_assert!(!T::IS_ZST); + + // We now know that `k < v.len() <= isize::MAX` + loop { + if v.len() <= INSERTION_SORT_THRESHOLD { + if v.len() >= 2 { + insertion_sort_shift_left(v, 1, is_less); + } + + return; + } + + // `median_of_{minima,maxima}` can't handle the extreme cases of the first/last element, + // so we catch them here and just do a linear search. + if k == v.len() - 1 { + // Find max element and place it in the last position of the array. We're free to use + // `unwrap()` here because we know v must not be empty. + let max_idx = max_index(v, is_less).unwrap(); + v.swap(max_idx, k); + return; + } else if k == 0 { + // Find min element and place it in the first position of the array. We're free to use + // `unwrap()` here because we know v must not be empty. + let min_idx = min_index(v, is_less).unwrap(); + v.swap(min_idx, k); + return; + } + + let p = median_of_ninthers(v, is_less); + + if p == k { + return; + } else if p > k { + v = &mut v[..p]; + } else { + // Since `p < k < v.len()`, `p + 1` doesn't overflow and is + // a valid index into the slice. + v = &mut v[p + 1..]; + k -= p + 1; + } + } +} + +// Optimized for when `k` lies somewhere in the middle of the slice. Selects a pivot +// as close as possible to the median of the slice. For more details on how the algorithm +// operates, refer to the paper . +fn median_of_ninthers bool>(v: &mut [T], is_less: &mut F) -> usize { + // use `saturating_mul` so the multiplication doesn't overflow on 16-bit platforms. + let frac = if v.len() <= 1024 { + v.len() / 12 + } else if v.len() <= 128_usize.saturating_mul(1024) { + v.len() / 64 + } else { + v.len() / 1024 + }; + + let pivot = frac / 2; + let lo = v.len() / 2 - pivot; + let hi = frac + lo; + let gap = (v.len() - 9 * frac) / 4; + let mut a = lo - 4 * frac - gap; + let mut b = hi + gap; + for i in lo..hi { + ninther(v, is_less, a, i - frac, b, a + 1, i, b + 1, a + 2, i + frac, b + 2); + a += 3; + b += 3; + } + + median_of_medians(&mut v[lo..lo + frac], is_less, pivot); + + partition(v, lo + pivot, is_less) +} + +/// Moves around the 9 elements at the indices a..i, such that +/// `v[d]` contains the median of the 9 elements and the other +/// elements are partitioned around it. +fn ninther bool>( + v: &mut [T], + is_less: &mut F, + a: usize, + mut b: usize, + c: usize, + mut d: usize, + e: usize, + mut f: usize, + g: usize, + mut h: usize, + i: usize, +) { + b = median_idx(v, is_less, a, b, c); + h = median_idx(v, is_less, g, h, i); + if is_less(&v[h], &v[b]) { + mem::swap(&mut b, &mut h); + } + if is_less(&v[f], &v[d]) { + mem::swap(&mut d, &mut f); + } + if is_less(&v[e], &v[d]) { + // do nothing + } else if is_less(&v[f], &v[e]) { + d = f; + } else { + if is_less(&v[e], &v[b]) { + v.swap(e, b); + } else if is_less(&v[h], &v[e]) { + v.swap(e, h); + } + return; + } + if is_less(&v[d], &v[b]) { + d = b; + } else if is_less(&v[h], &v[d]) { + d = h; + } + + v.swap(d, e); +} + +/// returns the index pointing to the median of the 3 +/// elements `v[a]`, `v[b]` and `v[c]` +fn median_idx bool>( + v: &[T], + is_less: &mut F, + mut a: usize, + b: usize, + mut c: usize, +) -> usize { + if is_less(&v[c], &v[a]) { + mem::swap(&mut a, &mut c); + } + if is_less(&v[c], &v[b]) { + return c; + } + if is_less(&v[b], &v[a]) { + return a; + } + b +} diff --git a/CoqOfRust/core/slice/sort/shared/mod.rs b/CoqOfRust/core/slice/sort/shared/mod.rs new file mode 100644 index 000000000..e2cdcb3dd --- /dev/null +++ b/CoqOfRust/core/slice/sort/shared/mod.rs @@ -0,0 +1,47 @@ +#![cfg_attr(any(feature = "optimize_for_size", target_pointer_width = "16"), allow(dead_code))] + +use crate::marker::Freeze; + +pub(crate) mod pivot; +pub(crate) mod smallsort; + +/// SAFETY: this is safety relevant, how does this interact with the soundness holes in +/// specialization? +#[rustc_unsafe_specialization_marker] +pub(crate) trait FreezeMarker {} + +impl FreezeMarker for T {} + +/// Finds a run of sorted elements starting at the beginning of the slice. +/// +/// Returns the length of the run, and a bool that is false when the run +/// is ascending, and true if the run strictly descending. +#[inline(always)] +pub(crate) fn find_existing_run bool>( + v: &[T], + is_less: &mut F, +) -> (usize, bool) { + let len = v.len(); + if len < 2 { + return (len, false); + } + + // SAFETY: We checked that len >= 2, so 0 and 1 are valid indices. + // This also means that run_len < len implies run_len and run_len - 1 + // are valid indices as well. + unsafe { + let mut run_len = 2; + let strictly_descending = is_less(v.get_unchecked(1), v.get_unchecked(0)); + if strictly_descending { + while run_len < len && is_less(v.get_unchecked(run_len), v.get_unchecked(run_len - 1)) { + run_len += 1; + } + } else { + while run_len < len && !is_less(v.get_unchecked(run_len), v.get_unchecked(run_len - 1)) + { + run_len += 1; + } + } + (run_len, strictly_descending) + } +} diff --git a/CoqOfRust/core/slice/sort/shared/pivot.rs b/CoqOfRust/core/slice/sort/shared/pivot.rs new file mode 100644 index 000000000..255a1eb6c --- /dev/null +++ b/CoqOfRust/core/slice/sort/shared/pivot.rs @@ -0,0 +1,88 @@ +//! This module contains the logic for pivot selection. + +use crate::intrinsics; + +// Recursively select a pseudomedian if above this threshold. +const PSEUDO_MEDIAN_REC_THRESHOLD: usize = 64; + +/// Selects a pivot from `v`. Algorithm taken from glidesort by Orson Peters. +/// +/// This chooses a pivot by sampling an adaptive amount of points, approximating +/// the quality of a median of sqrt(n) elements. +pub fn choose_pivot bool>(v: &[T], is_less: &mut F) -> usize { + // We use unsafe code and raw pointers here because we're dealing with + // heavy recursion. Passing safe slices around would involve a lot of + // branches and function call overhead. + + let len = v.len(); + if len < 8 { + intrinsics::abort(); + } + + // SAFETY: a, b, c point to initialized regions of len_div_8 elements, + // satisfying median3 and median3_rec's preconditions as v_base points + // to an initialized region of n = len elements. + unsafe { + let v_base = v.as_ptr(); + let len_div_8 = len / 8; + + let a = v_base; // [0, floor(n/8)) + let b = v_base.add(len_div_8 * 4); // [4*floor(n/8), 5*floor(n/8)) + let c = v_base.add(len_div_8 * 7); // [7*floor(n/8), 8*floor(n/8)) + + if len < PSEUDO_MEDIAN_REC_THRESHOLD { + median3(&*a, &*b, &*c, is_less).sub_ptr(v_base) + } else { + median3_rec(a, b, c, len_div_8, is_less).sub_ptr(v_base) + } + } +} + +/// Calculates an approximate median of 3 elements from sections a, b, c, or +/// recursively from an approximation of each, if they're large enough. By +/// dividing the size of each section by 8 when recursing we have logarithmic +/// recursion depth and overall sample from f(n) = 3*f(n/8) -> f(n) = +/// O(n^(log(3)/log(8))) ~= O(n^0.528) elements. +/// +/// SAFETY: a, b, c must point to the start of initialized regions of memory of +/// at least n elements. +unsafe fn median3_rec bool>( + mut a: *const T, + mut b: *const T, + mut c: *const T, + n: usize, + is_less: &mut F, +) -> *const T { + // SAFETY: a, b, c still point to initialized regions of n / 8 elements, + // by the exact same logic as in choose_pivot. + unsafe { + if n * 8 >= PSEUDO_MEDIAN_REC_THRESHOLD { + let n8 = n / 8; + a = median3_rec(a, a.add(n8 * 4), a.add(n8 * 7), n8, is_less); + b = median3_rec(b, b.add(n8 * 4), b.add(n8 * 7), n8, is_less); + c = median3_rec(c, c.add(n8 * 4), c.add(n8 * 7), n8, is_less); + } + median3(&*a, &*b, &*c, is_less) + } +} + +/// Calculates the median of 3 elements. +/// +/// SAFETY: a, b, c must be valid initialized elements. +#[inline(always)] +fn median3 bool>(a: &T, b: &T, c: &T, is_less: &mut F) -> *const T { + // Compiler tends to make this branchless when sensible, and avoids the + // third comparison when not. + let x = is_less(a, b); + let y = is_less(a, c); + if x == y { + // If x=y=0 then b, c <= a. In this case we want to return max(b, c). + // If x=y=1 then a < b, c. In this case we want to return min(b, c). + // By toggling the outcome of b < c using XOR x we get this behavior. + let z = is_less(b, c); + if z ^ x { c } else { b } + } else { + // Either c <= a < b or b <= a < c, thus a is our median. + a + } +} diff --git a/CoqOfRust/core/slice/sort/shared/smallsort.rs b/CoqOfRust/core/slice/sort/shared/smallsort.rs new file mode 100644 index 000000000..09f898309 --- /dev/null +++ b/CoqOfRust/core/slice/sort/shared/smallsort.rs @@ -0,0 +1,872 @@ +//! This module contains a variety of sort implementations that are optimized for small lengths. + +use crate::mem::{self, ManuallyDrop, MaybeUninit}; +use crate::slice::sort::shared::FreezeMarker; +use crate::{intrinsics, ptr, slice}; + +// It's important to differentiate between SMALL_SORT_THRESHOLD performance for +// small slices and small-sort performance sorting small sub-slices as part of +// the main quicksort loop. For the former, testing showed that the +// representative benchmarks for real-world performance are cold CPU state and +// not single-size hot benchmarks. For the latter the CPU will call them many +// times, so hot benchmarks are fine and more realistic. And it's worth it to +// optimize sorting small sub-slices with more sophisticated solutions than +// insertion sort. + +/// Using a trait allows us to specialize on `Freeze` which in turn allows us to make safe +/// abstractions. +pub(crate) trait StableSmallSortTypeImpl: Sized { + /// For which input length <= return value of this function, is it valid to call `small_sort`. + fn small_sort_threshold() -> usize; + + /// Sorts `v` using strategies optimized for small sizes. + fn small_sort bool>( + v: &mut [Self], + scratch: &mut [MaybeUninit], + is_less: &mut F, + ); +} + +impl StableSmallSortTypeImpl for T { + #[inline(always)] + default fn small_sort_threshold() -> usize { + // Optimal number of comparisons, and good perf. + SMALL_SORT_FALLBACK_THRESHOLD + } + + #[inline(always)] + default fn small_sort bool>( + v: &mut [T], + _scratch: &mut [MaybeUninit], + is_less: &mut F, + ) { + if v.len() >= 2 { + insertion_sort_shift_left(v, 1, is_less); + } + } +} + +impl StableSmallSortTypeImpl for T { + #[inline(always)] + fn small_sort_threshold() -> usize { + SMALL_SORT_GENERAL_THRESHOLD + } + + #[inline(always)] + fn small_sort bool>( + v: &mut [T], + scratch: &mut [MaybeUninit], + is_less: &mut F, + ) { + small_sort_general_with_scratch(v, scratch, is_less); + } +} + +/// Using a trait allows us to specialize on `Freeze` which in turn allows us to make safe +/// abstractions. +pub(crate) trait UnstableSmallSortTypeImpl: Sized { + /// For which input length <= return value of this function, is it valid to call `small_sort`. + fn small_sort_threshold() -> usize; + + /// Sorts `v` using strategies optimized for small sizes. + fn small_sort bool>(v: &mut [Self], is_less: &mut F); +} + +impl UnstableSmallSortTypeImpl for T { + #[inline(always)] + default fn small_sort_threshold() -> usize { + SMALL_SORT_FALLBACK_THRESHOLD + } + + #[inline(always)] + default fn small_sort(v: &mut [T], is_less: &mut F) + where + F: FnMut(&T, &T) -> bool, + { + small_sort_fallback(v, is_less); + } +} + +impl UnstableSmallSortTypeImpl for T { + #[inline(always)] + fn small_sort_threshold() -> usize { + ::small_sort_threshold() + } + + #[inline(always)] + fn small_sort(v: &mut [T], is_less: &mut F) + where + F: FnMut(&T, &T) -> bool, + { + ::small_sort(v, is_less); + } +} + +/// FIXME(const_trait_impl) use original ipnsort approach with choose_unstable_small_sort, +/// as found here . +pub(crate) trait UnstableSmallSortFreezeTypeImpl: Sized + FreezeMarker { + fn small_sort_threshold() -> usize; + + fn small_sort bool>(v: &mut [Self], is_less: &mut F); +} + +impl UnstableSmallSortFreezeTypeImpl for T { + #[inline(always)] + default fn small_sort_threshold() -> usize { + if (mem::size_of::() * SMALL_SORT_GENERAL_SCRATCH_LEN) <= MAX_STACK_ARRAY_SIZE { + SMALL_SORT_GENERAL_THRESHOLD + } else { + SMALL_SORT_FALLBACK_THRESHOLD + } + } + + #[inline(always)] + default fn small_sort(v: &mut [T], is_less: &mut F) + where + F: FnMut(&T, &T) -> bool, + { + if (mem::size_of::() * SMALL_SORT_GENERAL_SCRATCH_LEN) <= MAX_STACK_ARRAY_SIZE { + small_sort_general(v, is_less); + } else { + small_sort_fallback(v, is_less); + } + } +} + +/// SAFETY: Only used for run-time optimization heuristic. +#[rustc_unsafe_specialization_marker] +trait CopyMarker {} + +impl CopyMarker for T {} + +impl UnstableSmallSortFreezeTypeImpl for T { + #[inline(always)] + fn small_sort_threshold() -> usize { + if has_efficient_in_place_swap::() + && (mem::size_of::() * SMALL_SORT_NETWORK_SCRATCH_LEN) <= MAX_STACK_ARRAY_SIZE + { + SMALL_SORT_NETWORK_THRESHOLD + } else if (mem::size_of::() * SMALL_SORT_GENERAL_SCRATCH_LEN) <= MAX_STACK_ARRAY_SIZE { + SMALL_SORT_GENERAL_THRESHOLD + } else { + SMALL_SORT_FALLBACK_THRESHOLD + } + } + + #[inline(always)] + fn small_sort(v: &mut [T], is_less: &mut F) + where + F: FnMut(&T, &T) -> bool, + { + if has_efficient_in_place_swap::() + && (mem::size_of::() * SMALL_SORT_NETWORK_SCRATCH_LEN) <= MAX_STACK_ARRAY_SIZE + { + small_sort_network(v, is_less); + } else if (mem::size_of::() * SMALL_SORT_GENERAL_SCRATCH_LEN) <= MAX_STACK_ARRAY_SIZE { + small_sort_general(v, is_less); + } else { + small_sort_fallback(v, is_less); + } + } +} + +/// Optimal number of comparisons, and good perf. +const SMALL_SORT_FALLBACK_THRESHOLD: usize = 16; + +/// From a comparison perspective 20 was ~2% more efficient for fully random input, but for +/// wall-clock performance choosing 32 yielded better performance overall. +/// +/// SAFETY: If you change this value, you have to adjust [`small_sort_general`] ! +const SMALL_SORT_GENERAL_THRESHOLD: usize = 32; + +/// [`small_sort_general`] uses [`sort8_stable`] as primitive and does a kind of ping-pong merge, +/// where the output of the first two [`sort8_stable`] calls is stored at the end of the scratch +/// buffer. This simplifies panic handling and avoids additional copies. This affects the required +/// scratch buffer size. +/// +/// SAFETY: If you change this value, you have to adjust [`small_sort_general`] ! +pub(crate) const SMALL_SORT_GENERAL_SCRATCH_LEN: usize = SMALL_SORT_GENERAL_THRESHOLD + 16; + +/// SAFETY: If you change this value, you have to adjust [`small_sort_network`] ! +const SMALL_SORT_NETWORK_THRESHOLD: usize = 32; +const SMALL_SORT_NETWORK_SCRATCH_LEN: usize = SMALL_SORT_NETWORK_THRESHOLD; + +/// Using a stack array, could cause a stack overflow if the type `T` is very large. To be +/// conservative we limit the usage of small-sorts that require a stack array to types that fit +/// within this limit. +const MAX_STACK_ARRAY_SIZE: usize = 4096; + +fn small_sort_fallback bool>(v: &mut [T], is_less: &mut F) { + if v.len() >= 2 { + insertion_sort_shift_left(v, 1, is_less); + } +} + +fn small_sort_general bool>(v: &mut [T], is_less: &mut F) { + let mut stack_array = MaybeUninit::<[T; SMALL_SORT_GENERAL_SCRATCH_LEN]>::uninit(); + + // SAFETY: The memory is backed by `stack_array`, and the operation is safe as long as the len + // is the same. + let scratch = unsafe { + slice::from_raw_parts_mut( + stack_array.as_mut_ptr() as *mut MaybeUninit, + SMALL_SORT_GENERAL_SCRATCH_LEN, + ) + }; + + small_sort_general_with_scratch(v, scratch, is_less); +} + +fn small_sort_general_with_scratch bool>( + v: &mut [T], + scratch: &mut [MaybeUninit], + is_less: &mut F, +) { + let len = v.len(); + if len < 2 { + return; + } + + if scratch.len() < len + 16 { + intrinsics::abort(); + } + + let v_base = v.as_mut_ptr(); + let len_div_2 = len / 2; + + // SAFETY: See individual comments. + unsafe { + let scratch_base = scratch.as_mut_ptr() as *mut T; + + let presorted_len = if const { mem::size_of::() <= 16 } && len >= 16 { + // SAFETY: scratch_base is valid and has enough space. + sort8_stable(v_base, scratch_base, scratch_base.add(len), is_less); + sort8_stable( + v_base.add(len_div_2), + scratch_base.add(len_div_2), + scratch_base.add(len + 8), + is_less, + ); + + 8 + } else if len >= 8 { + // SAFETY: scratch_base is valid and has enough space. + sort4_stable(v_base, scratch_base, is_less); + sort4_stable(v_base.add(len_div_2), scratch_base.add(len_div_2), is_less); + + 4 + } else { + ptr::copy_nonoverlapping(v_base, scratch_base, 1); + ptr::copy_nonoverlapping(v_base.add(len_div_2), scratch_base.add(len_div_2), 1); + + 1 + }; + + for offset in [0, len_div_2] { + // SAFETY: at this point dst is initialized with presorted_len elements. + // We extend this to desired_len, src is valid for desired_len elements. + let src = v_base.add(offset); + let dst = scratch_base.add(offset); + let desired_len = if offset == 0 { len_div_2 } else { len - len_div_2 }; + + for i in presorted_len..desired_len { + ptr::copy_nonoverlapping(src.add(i), dst.add(i), 1); + insert_tail(dst, dst.add(i), is_less); + } + } + + // SAFETY: see comment in `CopyOnDrop::drop`. + let drop_guard = CopyOnDrop { src: scratch_base, dst: v_base, len }; + + // SAFETY: at this point scratch_base is fully initialized, allowing us + // to use it as the source of our merge back into the original array. + // If a panic occurs we ensure the original array is restored to a valid + // permutation of the input through drop_guard. This technique is similar + // to ping-pong merging. + bidirectional_merge( + &*ptr::slice_from_raw_parts(drop_guard.src, drop_guard.len), + drop_guard.dst, + is_less, + ); + mem::forget(drop_guard); + } +} + +struct CopyOnDrop { + src: *const T, + dst: *mut T, + len: usize, +} + +impl Drop for CopyOnDrop { + fn drop(&mut self) { + // SAFETY: `src` must contain `len` initialized elements, and dst must + // be valid to write `len` elements. + unsafe { + ptr::copy_nonoverlapping(self.src, self.dst, self.len); + } + } +} + +fn small_sort_network(v: &mut [T], is_less: &mut F) +where + T: FreezeMarker, + F: FnMut(&T, &T) -> bool, +{ + // This implementation is tuned to be efficient for integer types. + + let len = v.len(); + if len < 2 { + return; + } + + if len > SMALL_SORT_NETWORK_SCRATCH_LEN { + intrinsics::abort(); + } + + let mut stack_array = MaybeUninit::<[T; SMALL_SORT_NETWORK_SCRATCH_LEN]>::uninit(); + + let len_div_2 = len / 2; + let no_merge = len < 18; + + let v_base = v.as_mut_ptr(); + let initial_region_len = if no_merge { len } else { len_div_2 }; + // SAFETY: Both possible values of `initial_region_len` are in-bounds. + let mut region = unsafe { &mut *ptr::slice_from_raw_parts_mut(v_base, initial_region_len) }; + + // Avoid compiler unrolling, we *really* don't want that to happen here for binary-size reasons. + loop { + let presorted_len = if region.len() >= 13 { + sort13_optimal(region, is_less); + 13 + } else if region.len() >= 9 { + sort9_optimal(region, is_less); + 9 + } else { + 1 + }; + + insertion_sort_shift_left(region, presorted_len, is_less); + + if no_merge { + return; + } + + if region.as_ptr() != v_base { + break; + } + + // SAFETY: The right side of `v` based on `len_div_2` is guaranteed in-bounds. + unsafe { + region = &mut *ptr::slice_from_raw_parts_mut(v_base.add(len_div_2), len - len_div_2) + }; + } + + // SAFETY: We checked that T is Freeze and thus observation safe. + // Should is_less panic v was not modified in parity_merge and retains it's original input. + // scratch and v must not alias and scratch has v.len() space. + unsafe { + let scratch_base = stack_array.as_mut_ptr() as *mut T; + bidirectional_merge( + &mut *ptr::slice_from_raw_parts_mut(v_base, len), + scratch_base, + is_less, + ); + ptr::copy_nonoverlapping(scratch_base, v_base, len); + } +} + +/// Swap two values in the slice pointed to by `v_base` at the position `a_pos` and `b_pos` if the +/// value at position `b_pos` is less than the one at position `a_pos`. +/// +/// Purposefully not marked `#[inline]`, despite us wanting it to be inlined for integers like +/// types. `is_less` could be a huge function and we want to give the compiler an option to +/// not inline this function. For the same reasons that this function is very perf critical +/// it should be in the same module as the functions that use it. +unsafe fn swap_if_less(v_base: *mut T, a_pos: usize, b_pos: usize, is_less: &mut F) +where + F: FnMut(&T, &T) -> bool, +{ + // SAFETY: the caller must guarantee that `a` and `b` each added to `v_base` yield valid + // pointers into `v_base`, and are properly aligned, and part of the same allocation. + unsafe { + let v_a = v_base.add(a_pos); + let v_b = v_base.add(b_pos); + + // PANIC SAFETY: if is_less panics, no scratch memory was created and the slice should still be + // in a well defined state, without duplicates. + + // Important to only swap if it is more and not if it is equal. is_less should return false for + // equal, so we don't swap. + let should_swap = is_less(&*v_b, &*v_a); + + // This is a branchless version of swap if. + // The equivalent code with a branch would be: + // + // if should_swap { + // ptr::swap(left, right, 1); + // } + + // The goal is to generate cmov instructions here. + let left_swap = if should_swap { v_b } else { v_a }; + let right_swap = if should_swap { v_a } else { v_b }; + + let right_swap_tmp = ManuallyDrop::new(ptr::read(right_swap)); + ptr::copy(left_swap, v_a, 1); + ptr::copy_nonoverlapping(&*right_swap_tmp, v_b, 1); + } +} + +/// Sorts the first 9 elements of `v` with a fast fixed function. +/// +/// Should `is_less` generate substantial amounts of code the compiler can choose to not inline +/// `swap_if_less`. If the code of a sort impl changes so as to call this function in multiple +/// places, `#[inline(never)]` is recommended to keep binary-size in check. The current design of +/// `small_sort_network` makes sure to only call this once. +fn sort9_optimal(v: &mut [T], is_less: &mut F) +where + F: FnMut(&T, &T) -> bool, +{ + if v.len() < 9 { + intrinsics::abort(); + } + + let v_base = v.as_mut_ptr(); + + // Optimal sorting network see: + // https://bertdobbelaere.github.io/sorting_networks.html. + + // SAFETY: We checked the len. + unsafe { + swap_if_less(v_base, 0, 3, is_less); + swap_if_less(v_base, 1, 7, is_less); + swap_if_less(v_base, 2, 5, is_less); + swap_if_less(v_base, 4, 8, is_less); + swap_if_less(v_base, 0, 7, is_less); + swap_if_less(v_base, 2, 4, is_less); + swap_if_less(v_base, 3, 8, is_less); + swap_if_less(v_base, 5, 6, is_less); + swap_if_less(v_base, 0, 2, is_less); + swap_if_less(v_base, 1, 3, is_less); + swap_if_less(v_base, 4, 5, is_less); + swap_if_less(v_base, 7, 8, is_less); + swap_if_less(v_base, 1, 4, is_less); + swap_if_less(v_base, 3, 6, is_less); + swap_if_less(v_base, 5, 7, is_less); + swap_if_less(v_base, 0, 1, is_less); + swap_if_less(v_base, 2, 4, is_less); + swap_if_less(v_base, 3, 5, is_less); + swap_if_less(v_base, 6, 8, is_less); + swap_if_less(v_base, 2, 3, is_less); + swap_if_less(v_base, 4, 5, is_less); + swap_if_less(v_base, 6, 7, is_less); + swap_if_less(v_base, 1, 2, is_less); + swap_if_less(v_base, 3, 4, is_less); + swap_if_less(v_base, 5, 6, is_less); + } +} + +/// Sorts the first 13 elements of `v` with a fast fixed function. +/// +/// Should `is_less` generate substantial amounts of code the compiler can choose to not inline +/// `swap_if_less`. If the code of a sort impl changes so as to call this function in multiple +/// places, `#[inline(never)]` is recommended to keep binary-size in check. The current design of +/// `small_sort_network` makes sure to only call this once. +fn sort13_optimal(v: &mut [T], is_less: &mut F) +where + F: FnMut(&T, &T) -> bool, +{ + if v.len() < 13 { + intrinsics::abort(); + } + + let v_base = v.as_mut_ptr(); + + // Optimal sorting network see: + // https://bertdobbelaere.github.io/sorting_networks.html. + + // SAFETY: We checked the len. + unsafe { + swap_if_less(v_base, 0, 12, is_less); + swap_if_less(v_base, 1, 10, is_less); + swap_if_less(v_base, 2, 9, is_less); + swap_if_less(v_base, 3, 7, is_less); + swap_if_less(v_base, 5, 11, is_less); + swap_if_less(v_base, 6, 8, is_less); + swap_if_less(v_base, 1, 6, is_less); + swap_if_less(v_base, 2, 3, is_less); + swap_if_less(v_base, 4, 11, is_less); + swap_if_less(v_base, 7, 9, is_less); + swap_if_less(v_base, 8, 10, is_less); + swap_if_less(v_base, 0, 4, is_less); + swap_if_less(v_base, 1, 2, is_less); + swap_if_less(v_base, 3, 6, is_less); + swap_if_less(v_base, 7, 8, is_less); + swap_if_less(v_base, 9, 10, is_less); + swap_if_less(v_base, 11, 12, is_less); + swap_if_less(v_base, 4, 6, is_less); + swap_if_less(v_base, 5, 9, is_less); + swap_if_less(v_base, 8, 11, is_less); + swap_if_less(v_base, 10, 12, is_less); + swap_if_less(v_base, 0, 5, is_less); + swap_if_less(v_base, 3, 8, is_less); + swap_if_less(v_base, 4, 7, is_less); + swap_if_less(v_base, 6, 11, is_less); + swap_if_less(v_base, 9, 10, is_less); + swap_if_less(v_base, 0, 1, is_less); + swap_if_less(v_base, 2, 5, is_less); + swap_if_less(v_base, 6, 9, is_less); + swap_if_less(v_base, 7, 8, is_less); + swap_if_less(v_base, 10, 11, is_less); + swap_if_less(v_base, 1, 3, is_less); + swap_if_less(v_base, 2, 4, is_less); + swap_if_less(v_base, 5, 6, is_less); + swap_if_less(v_base, 9, 10, is_less); + swap_if_less(v_base, 1, 2, is_less); + swap_if_less(v_base, 3, 4, is_less); + swap_if_less(v_base, 5, 7, is_less); + swap_if_less(v_base, 6, 8, is_less); + swap_if_less(v_base, 2, 3, is_less); + swap_if_less(v_base, 4, 5, is_less); + swap_if_less(v_base, 6, 7, is_less); + swap_if_less(v_base, 8, 9, is_less); + swap_if_less(v_base, 3, 4, is_less); + swap_if_less(v_base, 5, 6, is_less); + } +} + +/// Sorts range [begin, tail] assuming [begin, tail) is already sorted. +/// +/// # Safety +/// begin < tail and p must be valid and initialized for all begin <= p <= tail. +unsafe fn insert_tail bool>(begin: *mut T, tail: *mut T, is_less: &mut F) { + // SAFETY: see individual comments. + unsafe { + // SAFETY: in-bounds as tail > begin. + let mut sift = tail.sub(1); + if !is_less(&*tail, &*sift) { + return; + } + + // SAFETY: after this read tail is never read from again, as we only ever + // read from sift, sift < tail and we only ever decrease sift. Thus this is + // effectively a move, not a copy. Should a panic occur, or we have found + // the correct insertion position, gap_guard ensures the element is moved + // back into the array. + let tmp = ManuallyDrop::new(tail.read()); + let mut gap_guard = CopyOnDrop { src: &*tmp, dst: tail, len: 1 }; + + loop { + // SAFETY: we move sift into the gap (which is valid), and point the + // gap guard destination at sift, ensuring that if a panic occurs the + // gap is once again filled. + ptr::copy_nonoverlapping(sift, gap_guard.dst, 1); + gap_guard.dst = sift; + + if sift == begin { + break; + } + + // SAFETY: we checked that sift != begin, thus this is in-bounds. + sift = sift.sub(1); + if !is_less(&tmp, &*sift) { + break; + } + } + } +} + +/// Sort `v` assuming `v[..offset]` is already sorted. +pub fn insertion_sort_shift_left bool>( + v: &mut [T], + offset: usize, + is_less: &mut F, +) { + let len = v.len(); + if offset == 0 || offset > len { + intrinsics::abort(); + } + + // SAFETY: see individual comments. + unsafe { + // We write this basic loop directly using pointers, as when we use a + // for loop LLVM likes to unroll this loop which we do not want. + // SAFETY: v_end is the one-past-end pointer, and we checked that + // offset <= len, thus tail is also in-bounds. + let v_base = v.as_mut_ptr(); + let v_end = v_base.add(len); + let mut tail = v_base.add(offset); + while tail != v_end { + // SAFETY: v_base and tail are both valid pointers to elements, and + // v_base < tail since we checked offset != 0. + insert_tail(v_base, tail, is_less); + + // SAFETY: we checked that tail is not yet the one-past-end pointer. + tail = tail.add(1); + } + } +} + +/// SAFETY: The caller MUST guarantee that `v_base` is valid for 4 reads and +/// `dst` is valid for 4 writes. The result will be stored in `dst[0..4]`. +pub unsafe fn sort4_stable bool>( + v_base: *const T, + dst: *mut T, + is_less: &mut F, +) { + // By limiting select to picking pointers, we are guaranteed good cmov code-gen + // regardless of type T's size. Further this only does 5 instead of 6 + // comparisons compared to a stable transposition 4 element sorting-network, + // and always copies each element exactly once. + + // SAFETY: all pointers have offset at most 3 from v_base and dst, and are + // thus in-bounds by the precondition. + unsafe { + // Stably create two pairs a <= b and c <= d. + let c1 = is_less(&*v_base.add(1), &*v_base); + let c2 = is_less(&*v_base.add(3), &*v_base.add(2)); + let a = v_base.add(c1 as usize); + let b = v_base.add(!c1 as usize); + let c = v_base.add(2 + c2 as usize); + let d = v_base.add(2 + (!c2 as usize)); + + // Compare (a, c) and (b, d) to identify max/min. We're left with two + // unknown elements, but because we are a stable sort we must know which + // one is leftmost and which one is rightmost. + // c3, c4 | min max unknown_left unknown_right + // 0, 0 | a d b c + // 0, 1 | a b c d + // 1, 0 | c d a b + // 1, 1 | c b a d + let c3 = is_less(&*c, &*a); + let c4 = is_less(&*d, &*b); + let min = select(c3, c, a); + let max = select(c4, b, d); + let unknown_left = select(c3, a, select(c4, c, b)); + let unknown_right = select(c4, d, select(c3, b, c)); + + // Sort the last two unknown elements. + let c5 = is_less(&*unknown_right, &*unknown_left); + let lo = select(c5, unknown_right, unknown_left); + let hi = select(c5, unknown_left, unknown_right); + + ptr::copy_nonoverlapping(min, dst, 1); + ptr::copy_nonoverlapping(lo, dst.add(1), 1); + ptr::copy_nonoverlapping(hi, dst.add(2), 1); + ptr::copy_nonoverlapping(max, dst.add(3), 1); + } + + #[inline(always)] + fn select(cond: bool, if_true: *const T, if_false: *const T) -> *const T { + if cond { if_true } else { if_false } + } +} + +/// SAFETY: The caller MUST guarantee that `v_base` is valid for 8 reads and +/// writes, `scratch_base` and `dst` MUST be valid for 8 writes. The result will +/// be stored in `dst[0..8]`. +unsafe fn sort8_stable bool>( + v_base: *mut T, + dst: *mut T, + scratch_base: *mut T, + is_less: &mut F, +) { + // SAFETY: these pointers are all in-bounds by the precondition of our function. + unsafe { + sort4_stable(v_base, scratch_base, is_less); + sort4_stable(v_base.add(4), scratch_base.add(4), is_less); + } + + // SAFETY: scratch_base[0..8] is now initialized, allowing us to merge back + // into dst. + unsafe { + bidirectional_merge(&*ptr::slice_from_raw_parts(scratch_base, 8), dst, is_less); + } +} + +#[inline(always)] +unsafe fn merge_up bool>( + mut left_src: *const T, + mut right_src: *const T, + mut dst: *mut T, + is_less: &mut F, +) -> (*const T, *const T, *mut T) { + // This is a branchless merge utility function. + // The equivalent code with a branch would be: + // + // if !is_less(&*right_src, &*left_src) { + // ptr::copy_nonoverlapping(left_src, dst, 1); + // left_src = left_src.add(1); + // } else { + // ptr::copy_nonoverlapping(right_src, dst, 1); + // right_src = right_src.add(1); + // } + // dst = dst.add(1); + + // SAFETY: The caller must guarantee that `left_src`, `right_src` are valid + // to read and `dst` is valid to write, while not aliasing. + unsafe { + let is_l = !is_less(&*right_src, &*left_src); + let src = if is_l { left_src } else { right_src }; + ptr::copy_nonoverlapping(src, dst, 1); + right_src = right_src.add(!is_l as usize); + left_src = left_src.add(is_l as usize); + dst = dst.add(1); + } + + (left_src, right_src, dst) +} + +#[inline(always)] +unsafe fn merge_down bool>( + mut left_src: *const T, + mut right_src: *const T, + mut dst: *mut T, + is_less: &mut F, +) -> (*const T, *const T, *mut T) { + // This is a branchless merge utility function. + // The equivalent code with a branch would be: + // + // if !is_less(&*right_src, &*left_src) { + // ptr::copy_nonoverlapping(right_src, dst, 1); + // right_src = right_src.wrapping_sub(1); + // } else { + // ptr::copy_nonoverlapping(left_src, dst, 1); + // left_src = left_src.wrapping_sub(1); + // } + // dst = dst.sub(1); + + // SAFETY: The caller must guarantee that `left_src`, `right_src` are valid + // to read and `dst` is valid to write, while not aliasing. + unsafe { + let is_l = !is_less(&*right_src, &*left_src); + let src = if is_l { right_src } else { left_src }; + ptr::copy_nonoverlapping(src, dst, 1); + right_src = right_src.wrapping_sub(is_l as usize); + left_src = left_src.wrapping_sub(!is_l as usize); + dst = dst.sub(1); + } + + (left_src, right_src, dst) +} + +/// Merge v assuming v[..len / 2] and v[len / 2..] are sorted. +/// +/// Original idea for bi-directional merging by Igor van den Hoven (quadsort), +/// adapted to only use merge up and down. In contrast to the original +/// parity_merge function, it performs 2 writes instead of 4 per iteration. +/// +/// # Safety +/// The caller must guarantee that `dst` is valid for v.len() writes. +/// Also `v.as_ptr()` and `dst` must not alias and v.len() must be >= 2. +/// +/// Note that T must be Freeze, the comparison function is evaluated on outdated +/// temporary 'copies' that may not end up in the final array. +unsafe fn bidirectional_merge bool>( + v: &[T], + dst: *mut T, + is_less: &mut F, +) { + // It helps to visualize the merge: + // + // Initial: + // + // |dst (in dst) + // |left |right + // v v + // [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx] + // ^ ^ + // |left_rev |right_rev + // |dst_rev (in dst) + // + // After: + // + // |dst (in dst) + // |left | |right + // v v v + // [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx] + // ^ ^ ^ + // |left_rev | |right_rev + // |dst_rev (in dst) + // + // In each iteration one of left or right moves up one position, and one of + // left_rev or right_rev moves down one position, whereas dst always moves + // up one position and dst_rev always moves down one position. Assuming + // the input was sorted and the comparison function is correctly implemented + // at the end we will have left == left_rev + 1, and right == right_rev + 1, + // fully consuming the input having written it to dst. + + let len = v.len(); + let src = v.as_ptr(); + + let len_div_2 = len / 2; + + // SAFETY: The caller has to ensure that len >= 2. + unsafe { + intrinsics::assume(len_div_2 != 0); // This can avoid useless code-gen. + } + + // SAFETY: no matter what the result of the user-provided comparison function + // is, all 4 read pointers will always be in-bounds. Writing `dst` and `dst_rev` + // will always be in bounds if the caller guarantees that `dst` is valid for + // `v.len()` writes. + unsafe { + let mut left = src; + let mut right = src.add(len_div_2); + let mut dst = dst; + + let mut left_rev = src.add(len_div_2 - 1); + let mut right_rev = src.add(len - 1); + let mut dst_rev = dst.add(len - 1); + + for _ in 0..len_div_2 { + (left, right, dst) = merge_up(left, right, dst, is_less); + (left_rev, right_rev, dst_rev) = merge_down(left_rev, right_rev, dst_rev, is_less); + } + + let left_end = left_rev.wrapping_add(1); + let right_end = right_rev.wrapping_add(1); + + // Odd length, so one element is left unconsumed in the input. + if len % 2 != 0 { + let left_nonempty = left < left_end; + let last_src = if left_nonempty { left } else { right }; + ptr::copy_nonoverlapping(last_src, dst, 1); + left = left.add(left_nonempty as usize); + right = right.add((!left_nonempty) as usize); + } + + // We now should have consumed the full input exactly once. This can only fail if the + // user-provided comparison function fails to implement a strict weak ordering. In that case + // we panic and never access the inconsistent state in dst. + if left != left_end || right != right_end { + panic_on_ord_violation(); + } + } +} + +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +fn panic_on_ord_violation() -> ! { + // This is indicative of a logic bug in the user-provided comparison function or Ord + // implementation. They are expected to implement a total order as explained in the Ord + // documentation. + // + // By panicking we inform the user, that they have a logic bug in their program. If a strict + // weak ordering is not given, the concept of comparison based sorting cannot yield a sorted + // result. E.g.: a < b < c < a + // + // The Ord documentation requires users to implement a total order. Arguably that's + // unnecessarily strict in the context of sorting. Issues only arise if the weaker requirement + // of a strict weak ordering is violated. + // + // The panic message talks about a total order because that's what the Ord documentation talks + // about and requires, so as to not confuse users. + panic!("user-provided comparison function does not correctly implement a total order"); +} + +#[must_use] +pub(crate) const fn has_efficient_in_place_swap() -> bool { + // Heuristic that holds true on all tested 64-bit capable architectures. + mem::size_of::() <= 8 // mem::size_of::() +} diff --git a/CoqOfRust/core/slice/sort/stable/drift.rs b/CoqOfRust/core/slice/sort/stable/drift.rs new file mode 100644 index 000000000..644e75a45 --- /dev/null +++ b/CoqOfRust/core/slice/sort/stable/drift.rs @@ -0,0 +1,298 @@ +//! This module contains the hybrid top-level loop combining bottom-up Mergesort with top-down +//! Quicksort. + +use crate::mem::MaybeUninit; +use crate::slice::sort::shared::find_existing_run; +use crate::slice::sort::shared::smallsort::StableSmallSortTypeImpl; +use crate::slice::sort::stable::merge::merge; +use crate::slice::sort::stable::quicksort::quicksort; +use crate::{cmp, intrinsics}; + +/// Sorts `v` based on comparison function `is_less`. If `eager_sort` is true, +/// it will only do small-sorts and physical merges, ensuring O(N * log(N)) +/// worst-case complexity. `scratch.len()` must be at least `max(v.len() / 2, +/// MIN_SMALL_SORT_SCRATCH_LEN)` otherwise the implementation may abort. +/// Fully ascending and descending inputs will be sorted with exactly N - 1 +/// comparisons. +/// +/// This is the main loop for driftsort, which uses powersort's heuristic to +/// determine in which order to merge runs, see below for details. +pub fn sort bool>( + v: &mut [T], + scratch: &mut [MaybeUninit], + eager_sort: bool, + is_less: &mut F, +) { + let len = v.len(); + if len < 2 { + return; // Removing this length check *increases* code size. + } + let scale_factor = merge_tree_scale_factor(len); + + // It's important to have a relatively high entry barrier for pre-sorted + // runs, as the presence of a single such run will force on average several + // merge operations and shrink the maximum quicksort size a lot. For that + // reason we use sqrt(len) as our pre-sorted run threshold. + const MIN_SQRT_RUN_LEN: usize = 64; + let min_good_run_len = if len <= (MIN_SQRT_RUN_LEN * MIN_SQRT_RUN_LEN) { + // For small input length `MIN_SQRT_RUN_LEN` would break pattern + // detection of full or nearly sorted inputs. + cmp::min(len - len / 2, MIN_SQRT_RUN_LEN) + } else { + sqrt_approx(len) + }; + + // (stack_len, runs, desired_depths) together form a stack maintaining run + // information for the powersort heuristic. desired_depths[i] is the desired + // depth of the merge node that merges runs[i] with the run that comes after + // it. + let mut stack_len = 0; + let mut run_storage = MaybeUninit::<[DriftsortRun; 66]>::uninit(); + let runs: *mut DriftsortRun = run_storage.as_mut_ptr().cast(); + let mut desired_depth_storage = MaybeUninit::<[u8; 66]>::uninit(); + let desired_depths: *mut u8 = desired_depth_storage.as_mut_ptr().cast(); + + let mut scan_idx = 0; + let mut prev_run = DriftsortRun::new_sorted(0); // Initial dummy run. + loop { + // Compute the next run and the desired depth of the merge node between + // prev_run and next_run. On the last iteration we create a dummy run + // with root-level desired depth to fully collapse the merge tree. + let (next_run, desired_depth); + if scan_idx < len { + next_run = + create_run(&mut v[scan_idx..], scratch, min_good_run_len, eager_sort, is_less); + desired_depth = merge_tree_depth( + scan_idx - prev_run.len(), + scan_idx, + scan_idx + next_run.len(), + scale_factor, + ); + } else { + next_run = DriftsortRun::new_sorted(0); + desired_depth = 0; + }; + + // Process the merge nodes between earlier runs[i] that have a desire to + // be deeper in the merge tree than the merge node for the splitpoint + // between prev_run and next_run. + // + // SAFETY: first note that this is the only place we modify stack_len, + // runs or desired depths. We maintain the following invariants: + // 1. The first stack_len elements of runs/desired_depths are initialized. + // 2. For all valid i > 0, desired_depths[i] < desired_depths[i+1]. + // 3. The sum of all valid runs[i].len() plus prev_run.len() equals + // scan_idx. + unsafe { + while stack_len > 1 && *desired_depths.add(stack_len - 1) >= desired_depth { + // Desired depth greater than the upcoming desired depth, pop + // left neighbor run from stack and merge into prev_run. + let left = *runs.add(stack_len - 1); + let merged_len = left.len() + prev_run.len(); + let merge_start_idx = scan_idx - merged_len; + let merge_slice = v.get_unchecked_mut(merge_start_idx..scan_idx); + prev_run = logical_merge(merge_slice, scratch, left, prev_run, is_less); + stack_len -= 1; + } + + // We now know that desired_depths[stack_len - 1] < desired_depth, + // maintaining our invariant. This also guarantees we don't overflow + // the stack as merge_tree_depth(..) <= 64 and thus we can only have + // 64 distinct values on the stack before pushing, plus our initial + // dummy run, while our capacity is 66. + *runs.add(stack_len) = prev_run; + *desired_depths.add(stack_len) = desired_depth; + stack_len += 1; + } + + // Break before overriding the last run with our dummy run. + if scan_idx >= len { + break; + } + + scan_idx += next_run.len(); + prev_run = next_run; + } + + if !prev_run.sorted() { + stable_quicksort(v, scratch, is_less); + } +} + +// Nearly-Optimal Mergesorts: Fast, Practical Sorting Methods That Optimally +// Adapt to Existing Runs by J. Ian Munro and Sebastian Wild. +// +// This method forms a binary merge tree, where each internal node corresponds +// to a splitting point between the adjacent runs that have to be merged. If we +// visualize our array as the number line from 0 to 1, we want to find the +// dyadic fraction with smallest denominator that lies between the midpoints of +// our to-be-merged slices. The exponent in the dyadic fraction indicates the +// desired depth in the binary merge tree this internal node wishes to have. +// This does not always correspond to the actual depth due to the inherent +// imbalance in runs, but we follow it as closely as possible. +// +// As an optimization we rescale the number line from [0, 1) to [0, 2^62). Then +// finding the simplest dyadic fraction between midpoints corresponds to finding +// the most significant bit difference of the midpoints. We save scale_factor = +// ceil(2^62 / n) to perform this rescaling using a multiplication, avoiding +// having to repeatedly do integer divides. This rescaling isn't exact when n is +// not a power of two since we use integers and not reals, but the result is +// very close, and in fact when n < 2^30 the resulting tree is equivalent as the +// approximation errors stay entirely in the lower order bits. +// +// Thus for the splitting point between two adjacent slices [a, b) and [b, c) +// the desired depth of the corresponding merge node is CLZ((a+b)*f ^ (b+c)*f), +// where CLZ counts the number of leading zeros in an integer and f is our scale +// factor. Note that we omitted the division by two in the midpoint +// calculations, as this simply shifts the bits by one position (and thus always +// adds one to the result), and we only care about the relative depths. +// +// Finally, if we try to upper bound x = (a+b)*f giving x = (n-1 + n) * ceil(2^62 / n) then +// x < (2^62 / n + 1) * 2n +// x < 2^63 + 2n +// So as long as n < 2^62 we find that x < 2^64, meaning our operations do not +// overflow. +#[inline(always)] +fn merge_tree_scale_factor(n: usize) -> u64 { + if usize::BITS > u64::BITS { + panic!("Platform not supported"); + } + + ((1 << 62) + n as u64 - 1) / n as u64 +} + +// Note: merge_tree_depth output is < 64 when left < right as f*x and f*y must +// differ in some bit, and is <= 64 always. +#[inline(always)] +fn merge_tree_depth(left: usize, mid: usize, right: usize, scale_factor: u64) -> u8 { + let x = left as u64 + mid as u64; + let y = mid as u64 + right as u64; + ((scale_factor * x) ^ (scale_factor * y)).leading_zeros() as u8 +} + +fn sqrt_approx(n: usize) -> usize { + // Note that sqrt(n) = n^(1/2), and that 2^log2(n) = n. We combine these + // two facts to approximate sqrt(n) as 2^(log2(n) / 2). Because our integer + // log floors we want to add 0.5 to compensate for this on average, so our + // initial approximation is 2^((1 + floor(log2(n))) / 2). + // + // We then apply an iteration of Newton's method to improve our + // approximation, which for sqrt(n) is a1 = (a0 + n / a0) / 2. + // + // Finally we note that the exponentiation / division can be done directly + // with shifts. We OR with 1 to avoid zero-checks in the integer log. + let ilog = (n | 1).ilog2(); + let shift = (1 + ilog) / 2; + ((1 << shift) + (n >> shift)) / 2 +} + +// Lazy logical runs as in Glidesort. +#[inline(always)] +fn logical_merge bool>( + v: &mut [T], + scratch: &mut [MaybeUninit], + left: DriftsortRun, + right: DriftsortRun, + is_less: &mut F, +) -> DriftsortRun { + // If one or both of the runs are sorted do a physical merge, using + // quicksort to sort the unsorted run if present. We also *need* to + // physically merge if the combined runs would not fit in the scratch space + // anymore (as this would mean we are no longer able to quicksort them). + let len = v.len(); + let can_fit_in_scratch = len <= scratch.len(); + if !can_fit_in_scratch || left.sorted() || right.sorted() { + if !left.sorted() { + stable_quicksort(&mut v[..left.len()], scratch, is_less); + } + if !right.sorted() { + stable_quicksort(&mut v[left.len()..], scratch, is_less); + } + merge(v, scratch, left.len(), is_less); + + DriftsortRun::new_sorted(len) + } else { + DriftsortRun::new_unsorted(len) + } +} + +/// Creates a new logical run. +/// +/// A logical run can either be sorted or unsorted. If there is a pre-existing +/// run that clears the `min_good_run_len` threshold it is returned as a sorted +/// run. If not, the result depends on the value of `eager_sort`. If it is true, +/// then a sorted run of length `T::SMALL_SORT_THRESHOLD` is returned, and if it +/// is false an unsorted run of length `min_good_run_len` is returned. +fn create_run bool>( + v: &mut [T], + scratch: &mut [MaybeUninit], + min_good_run_len: usize, + eager_sort: bool, + is_less: &mut F, +) -> DriftsortRun { + let len = v.len(); + if len >= min_good_run_len { + let (run_len, was_reversed) = find_existing_run(v, is_less); + + // SAFETY: find_existing_run promises to return a valid run_len. + unsafe { intrinsics::assume(run_len <= len) }; + + if run_len >= min_good_run_len { + if was_reversed { + v[..run_len].reverse(); + } + + return DriftsortRun::new_sorted(run_len); + } + } + + if eager_sort { + // We call quicksort with a len that will immediately call small-sort. + // By not calling the small-sort directly here it can always be inlined into + // the quicksort itself, making the recursive base case faster and is generally + // more binary-size efficient. + let eager_run_len = cmp::min(T::small_sort_threshold(), len); + quicksort(&mut v[..eager_run_len], scratch, 0, None, is_less); + DriftsortRun::new_sorted(eager_run_len) + } else { + DriftsortRun::new_unsorted(cmp::min(min_good_run_len, len)) + } +} + +fn stable_quicksort bool>( + v: &mut [T], + scratch: &mut [MaybeUninit], + is_less: &mut F, +) { + // Limit the number of imbalanced partitions to `2 * floor(log2(len))`. + // The binary OR by one is used to eliminate the zero-check in the logarithm. + let limit = 2 * (v.len() | 1).ilog2(); + quicksort(v, scratch, limit, None, is_less); +} + +/// Compactly stores the length of a run, and whether or not it is sorted. This +/// can always fit in a `usize` because the maximum slice length is [`isize::MAX`]. +#[derive(Copy, Clone)] +struct DriftsortRun(usize); + +impl DriftsortRun { + #[inline(always)] + fn new_sorted(length: usize) -> Self { + Self((length << 1) | 1) + } + + #[inline(always)] + fn new_unsorted(length: usize) -> Self { + Self(length << 1) + } + + #[inline(always)] + fn sorted(self) -> bool { + self.0 & 1 == 1 + } + + #[inline(always)] + fn len(self) -> usize { + self.0 >> 1 + } +} diff --git a/CoqOfRust/core/slice/sort/stable/merge.rs b/CoqOfRust/core/slice/sort/stable/merge.rs new file mode 100644 index 000000000..0cb217407 --- /dev/null +++ b/CoqOfRust/core/slice/sort/stable/merge.rs @@ -0,0 +1,150 @@ +//! This module contains logic for performing a merge of two sorted sub-slices. + +use crate::mem::MaybeUninit; +use crate::{cmp, ptr}; + +/// Merges non-decreasing runs `v[..mid]` and `v[mid..]` using `scratch` as +/// temporary storage, and stores the result into `v[..]`. +pub fn merge bool>( + v: &mut [T], + scratch: &mut [MaybeUninit], + mid: usize, + is_less: &mut F, +) { + let len = v.len(); + + if mid == 0 || mid >= len || scratch.len() < cmp::min(mid, len - mid) { + return; + } + + // SAFETY: We checked that the two slices are non-empty and `mid` is in-bounds. + // We checked that the buffer `scratch` has enough capacity to hold a copy of + // the shorter slice. `merge_up` and `merge_down` are written in such a way that + // they uphold the contract described in `MergeState::drop`. + unsafe { + // The merge process first copies the shorter run into `buf`. Then it traces + // the newly copied run and the longer run forwards (or backwards), comparing + // their next unconsumed elements and copying the lesser (or greater) one into `v`. + // + // As soon as the shorter run is fully consumed, the process is done. If the + // longer run gets consumed first, then we must copy whatever is left of the + // shorter run into the remaining gap in `v`. + // + // Intermediate state of the process is always tracked by `gap`, which serves + // two purposes: + // 1. Protects integrity of `v` from panics in `is_less`. + // 2. Fills the remaining gap in `v` if the longer run gets consumed first. + + let buf = MaybeUninit::slice_as_mut_ptr(scratch); + + let v_base = v.as_mut_ptr(); + let v_mid = v_base.add(mid); + let v_end = v_base.add(len); + + let left_len = mid; + let right_len = len - mid; + + let left_is_shorter = left_len <= right_len; + let save_base = if left_is_shorter { v_base } else { v_mid }; + let save_len = if left_is_shorter { left_len } else { right_len }; + + ptr::copy_nonoverlapping(save_base, buf, save_len); + + let mut merge_state = MergeState { start: buf, end: buf.add(save_len), dst: save_base }; + + if left_is_shorter { + merge_state.merge_up(v_mid, v_end, is_less); + } else { + merge_state.merge_down(v_base, buf, v_end, is_less); + } + // Finally, `merge_state` gets dropped. If the shorter run was not fully + // consumed, whatever remains of it will now be copied into the hole in `v`. + } +} + +// When dropped, copies the range `start..end` into `dst..`. +struct MergeState { + start: *mut T, + end: *mut T, + dst: *mut T, +} + +impl MergeState { + /// # Safety + /// The caller MUST guarantee that `self` is initialized in a way where `start -> end` is + /// the longer sub-slice and so that `dst` can be written to at least the shorter sub-slice + /// length times. In addition `start -> end` and `right -> right_end` MUST be valid to be + /// read. This function MUST only be called once. + unsafe fn merge_up bool>( + &mut self, + mut right: *const T, + right_end: *const T, + is_less: &mut F, + ) { + // SAFETY: See function safety comment. + unsafe { + let left = &mut self.start; + let out = &mut self.dst; + + while *left != self.end && right as *const T != right_end { + let consume_left = !is_less(&*right, &**left); + + let src = if consume_left { *left } else { right }; + ptr::copy_nonoverlapping(src, *out, 1); + + *left = left.add(consume_left as usize); + right = right.add(!consume_left as usize); + + *out = out.add(1); + } + } + } + + /// # Safety + /// The caller MUST guarantee that `self` is initialized in a way where `left_end <- dst` is + /// the shorter sub-slice and so that `out` can be written to at least the shorter sub-slice + /// length times. In addition `left_end <- dst` and `right_end <- end` MUST be valid to be + /// read. This function MUST only be called once. + unsafe fn merge_down bool>( + &mut self, + left_end: *const T, + right_end: *const T, + mut out: *mut T, + is_less: &mut F, + ) { + // SAFETY: See function safety comment. + unsafe { + loop { + let left = self.dst.sub(1); + let right = self.end.sub(1); + out = out.sub(1); + + let consume_left = is_less(&*right, &*left); + + let src = if consume_left { left } else { right }; + ptr::copy_nonoverlapping(src, out, 1); + + self.dst = left.add(!consume_left as usize); + self.end = right.add(consume_left as usize); + + if self.dst as *const T == left_end || self.end as *const T == right_end { + break; + } + } + } + } +} + +impl Drop for MergeState { + fn drop(&mut self) { + // SAFETY: The user of MergeState MUST ensure, that at any point this drop + // impl MAY run, for example when the user provided `is_less` panics, that + // copying the contiguous region between `start` and `end` to `dst` will + // leave the input slice `v` with each original element and all possible + // modifications observed. + unsafe { + let len = self.end.sub_ptr(self.start); + ptr::copy_nonoverlapping(self.start, self.dst, len); + } + } +} diff --git a/CoqOfRust/core/slice/sort/stable/mod.rs b/CoqOfRust/core/slice/sort/stable/mod.rs new file mode 100644 index 000000000..7adcc83b8 --- /dev/null +++ b/CoqOfRust/core/slice/sort/stable/mod.rs @@ -0,0 +1,151 @@ +//! This module contains the entry points for `slice::sort`. + +#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))] +use crate::cmp; +use crate::intrinsics; +use crate::mem::{self, MaybeUninit, SizedTypeProperties}; +#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))] +use crate::slice::sort::shared::smallsort::{ + SMALL_SORT_GENERAL_SCRATCH_LEN, StableSmallSortTypeImpl, insertion_sort_shift_left, +}; + +pub(crate) mod merge; + +#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))] +pub(crate) mod drift; +#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))] +pub(crate) mod quicksort; + +#[cfg(any(feature = "optimize_for_size", target_pointer_width = "16"))] +pub(crate) mod tiny; + +/// Stable sort called driftsort by Orson Peters and Lukas Bergdoll. +/// Design document: +/// +/// +/// Upholds all safety properties outlined here: +/// +#[inline(always)] +pub fn sort bool, BufT: BufGuard>(v: &mut [T], is_less: &mut F) { + // Arrays of zero-sized types are always all-equal, and thus sorted. + if T::IS_ZST { + return; + } + + // Instrumenting the standard library showed that 90+% of the calls to sort + // by rustc are either of size 0 or 1. + let len = v.len(); + if intrinsics::likely(len < 2) { + return; + } + + cfg_if! { + if #[cfg(any(feature = "optimize_for_size", target_pointer_width = "16"))] { + let alloc_len = len / 2; + + cfg_if! { + if #[cfg(target_pointer_width = "16")] { + let mut heap_buf = BufT::with_capacity(alloc_len); + let scratch = heap_buf.as_uninit_slice_mut(); + } else { + // For small inputs 4KiB of stack storage suffices, which allows us to avoid + // calling the (de-)allocator. Benchmarks showed this was quite beneficial. + let mut stack_buf = AlignedStorage::::new(); + let stack_scratch = stack_buf.as_uninit_slice_mut(); + let mut heap_buf; + let scratch = if stack_scratch.len() >= alloc_len { + stack_scratch + } else { + heap_buf = BufT::with_capacity(alloc_len); + heap_buf.as_uninit_slice_mut() + }; + } + } + + tiny::mergesort(v, scratch, is_less); + } else { + // More advanced sorting methods than insertion sort are faster if called in + // a hot loop for small inputs, but for general-purpose code the small + // binary size of insertion sort is more important. The instruction cache in + // modern processors is very valuable, and for a single sort call in general + // purpose code any gains from an advanced method are cancelled by i-cache + // misses during the sort, and thrashing the i-cache for surrounding code. + const MAX_LEN_ALWAYS_INSERTION_SORT: usize = 20; + if intrinsics::likely(len <= MAX_LEN_ALWAYS_INSERTION_SORT) { + insertion_sort_shift_left(v, 1, is_less); + return; + } + + driftsort_main::(v, is_less); + } + } +} + +/// See [`sort`] +/// +/// Deliberately don't inline the main sorting routine entrypoint to ensure the +/// inlined insertion sort i-cache footprint remains minimal. +#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))] +#[inline(never)] +fn driftsort_main bool, BufT: BufGuard>(v: &mut [T], is_less: &mut F) { + // By allocating n elements of memory we can ensure the entire input can + // be sorted using stable quicksort, which allows better performance on + // random and low-cardinality distributions. However, we still want to + // reduce our memory usage to n / 2 for large inputs. We do this by scaling + // our allocation as max(n / 2, min(n, 8MB)), ensuring we scale like n for + // small inputs and n / 2 for large inputs, without a sudden drop off. We + // also need to ensure our alloc >= MIN_SMALL_SORT_SCRATCH_LEN, as the + // small-sort always needs this much memory. + const MAX_FULL_ALLOC_BYTES: usize = 8_000_000; // 8MB + let max_full_alloc = MAX_FULL_ALLOC_BYTES / mem::size_of::(); + let len = v.len(); + let alloc_len = + cmp::max(cmp::max(len / 2, cmp::min(len, max_full_alloc)), SMALL_SORT_GENERAL_SCRATCH_LEN); + + // For small inputs 4KiB of stack storage suffices, which allows us to avoid + // calling the (de-)allocator. Benchmarks showed this was quite beneficial. + let mut stack_buf = AlignedStorage::::new(); + let stack_scratch = stack_buf.as_uninit_slice_mut(); + let mut heap_buf; + let scratch = if stack_scratch.len() >= alloc_len { + stack_scratch + } else { + heap_buf = BufT::with_capacity(alloc_len); + heap_buf.as_uninit_slice_mut() + }; + + // For small inputs using quicksort is not yet beneficial, and a single + // small-sort or two small-sorts plus a single merge outperforms it, so use + // eager mode. + let eager_sort = len <= T::small_sort_threshold() * 2; + crate::slice::sort::stable::drift::sort(v, scratch, eager_sort, is_less); +} + +#[doc(hidden)] +/// Abstracts owned memory buffer, so that sort code can live in core where no allocation is +/// possible. This trait can then be implemented in a place that has access to allocation. +pub trait BufGuard { + /// Creates new buffer that holds at least `capacity` memory. + fn with_capacity(capacity: usize) -> Self; + /// Returns mutable access to uninitialized memory owned by the buffer. + fn as_uninit_slice_mut(&mut self) -> &mut [MaybeUninit]; +} + +#[repr(C)] +struct AlignedStorage { + _align: [T; 0], + storage: [MaybeUninit; N], +} + +impl AlignedStorage { + fn new() -> Self { + Self { _align: [], storage: [const { MaybeUninit::uninit() }; N] } + } + + fn as_uninit_slice_mut(&mut self) -> &mut [MaybeUninit] { + let len = N / mem::size_of::(); + + // SAFETY: `_align` ensures we are correctly aligned. + unsafe { core::slice::from_raw_parts_mut(self.storage.as_mut_ptr().cast(), len) } + } +} diff --git a/CoqOfRust/core/slice/sort/stable/quicksort.rs b/CoqOfRust/core/slice/sort/stable/quicksort.rs new file mode 100644 index 000000000..0c8308bfc --- /dev/null +++ b/CoqOfRust/core/slice/sort/stable/quicksort.rs @@ -0,0 +1,257 @@ +//! This module contains a stable quicksort and partition implementation. + +use crate::mem::{self, ManuallyDrop, MaybeUninit}; +use crate::slice::sort::shared::FreezeMarker; +use crate::slice::sort::shared::pivot::choose_pivot; +use crate::slice::sort::shared::smallsort::StableSmallSortTypeImpl; +use crate::{intrinsics, ptr}; + +/// Sorts `v` recursively using quicksort. +/// +/// `limit` when initialized with `c*log(v.len())` for some c ensures we do not +/// overflow the stack or go quadratic. +#[inline(never)] +pub fn quicksort bool>( + mut v: &mut [T], + scratch: &mut [MaybeUninit], + mut limit: u32, + mut left_ancestor_pivot: Option<&T>, + is_less: &mut F, +) { + loop { + let len = v.len(); + + if len <= T::small_sort_threshold() { + T::small_sort(v, scratch, is_less); + return; + } + + if limit == 0 { + // We have had too many bad pivots, switch to O(n log n) fallback + // algorithm. In our case that is driftsort in eager mode. + crate::slice::sort::stable::drift::sort(v, scratch, true, is_less); + return; + } + limit -= 1; + + let pivot_pos = choose_pivot(v, is_less); + // SAFETY: choose_pivot promises to return a valid pivot index. + unsafe { + intrinsics::assume(pivot_pos < v.len()); + } + + // SAFETY: We only access the temporary copy for Freeze types, otherwise + // self-modifications via `is_less` would not be observed and this would + // be unsound. Our temporary copy does not escape this scope. + let pivot_copy = unsafe { ManuallyDrop::new(ptr::read(&v[pivot_pos])) }; + let pivot_ref = (!has_direct_interior_mutability::()).then_some(&*pivot_copy); + + // We choose a pivot, and check if this pivot is equal to our left + // ancestor. If true, we do a partition putting equal elements on the + // left and do not recurse on it. This gives O(n log k) sorting for k + // distinct values, a strategy borrowed from pdqsort. For types with + // interior mutability we can't soundly create a temporary copy of the + // ancestor pivot, and use left_partition_len == 0 as our method for + // detecting when we re-use a pivot, which means we do at most three + // partition operations with pivot p instead of the optimal two. + let mut perform_equal_partition = false; + if let Some(la_pivot) = left_ancestor_pivot { + perform_equal_partition = !is_less(la_pivot, &v[pivot_pos]); + } + + let mut left_partition_len = 0; + if !perform_equal_partition { + left_partition_len = stable_partition(v, scratch, pivot_pos, false, is_less); + perform_equal_partition = left_partition_len == 0; + } + + if perform_equal_partition { + let mid_eq = stable_partition(v, scratch, pivot_pos, true, &mut |a, b| !is_less(b, a)); + v = &mut v[mid_eq..]; + left_ancestor_pivot = None; + continue; + } + + // Process left side with the next loop iter, right side with recursion. + let (left, right) = v.split_at_mut(left_partition_len); + quicksort(right, scratch, limit, pivot_ref, is_less); + v = left; + } +} + +/// Partitions `v` using pivot `p = v[pivot_pos]` and returns the number of +/// elements less than `p`. The relative order of elements that compare < p and +/// those that compare >= p is preserved - it is a stable partition. +/// +/// If `is_less` is not a strict total order or panics, `scratch.len() < v.len()`, +/// or `pivot_pos >= v.len()`, the result and `v`'s state is sound but unspecified. +fn stable_partition bool>( + v: &mut [T], + scratch: &mut [MaybeUninit], + pivot_pos: usize, + pivot_goes_left: bool, + is_less: &mut F, +) -> usize { + let len = v.len(); + + if intrinsics::unlikely(scratch.len() < len || pivot_pos >= len) { + core::intrinsics::abort() + } + + let v_base = v.as_ptr(); + let scratch_base = MaybeUninit::slice_as_mut_ptr(scratch); + + // The core idea is to write the values that compare as less-than to the left + // side of `scratch`, while the values that compared as greater or equal than + // `v[pivot_pos]` go to the right side of `scratch` in reverse. See + // PartitionState for details. + + // SAFETY: see individual comments. + unsafe { + // SAFETY: we made sure the scratch has length >= len and that pivot_pos + // is in-bounds. v and scratch are disjoint slices. + let pivot = v_base.add(pivot_pos); + let mut state = PartitionState::new(v_base, scratch_base, len); + + let mut pivot_in_scratch = ptr::null_mut(); + let mut loop_end_pos = pivot_pos; + + // SAFETY: this loop is equivalent to calling state.partition_one + // exactly len times. + loop { + // Ideally the outer loop won't be unrolled, to save binary size, + // but we do want the inner loop to be unrolled for small types, as + // this gave significant performance boosts in benchmarks. Unrolling + // through for _ in 0..UNROLL_LEN { .. } instead of manually improves + // compile times but has a ~10-20% performance penalty on opt-level=s. + if const { mem::size_of::() <= 16 } { + const UNROLL_LEN: usize = 4; + let unroll_end = v_base.add(loop_end_pos.saturating_sub(UNROLL_LEN - 1)); + while state.scan < unroll_end { + state.partition_one(is_less(&*state.scan, &*pivot)); + state.partition_one(is_less(&*state.scan, &*pivot)); + state.partition_one(is_less(&*state.scan, &*pivot)); + state.partition_one(is_less(&*state.scan, &*pivot)); + } + } + + let loop_end = v_base.add(loop_end_pos); + while state.scan < loop_end { + state.partition_one(is_less(&*state.scan, &*pivot)); + } + + if loop_end_pos == len { + break; + } + + // We avoid comparing pivot with itself, as this could create deadlocks for + // certain comparison operators. We also store its location later for later. + pivot_in_scratch = state.partition_one(pivot_goes_left); + + loop_end_pos = len; + } + + // `pivot` must be copied into its correct position again, because a + // comparison operator might have modified it. + if has_direct_interior_mutability::() { + ptr::copy_nonoverlapping(pivot, pivot_in_scratch, 1); + } + + // SAFETY: partition_one being called exactly len times guarantees that scratch + // is initialized with a permuted copy of `v`, and that num_left <= v.len(). + // Copying scratch[0..num_left] and scratch[num_left..v.len()] back is thus + // sound, as the values in scratch will never be read again, meaning our copies + // semantically act as moves, permuting `v`. + + // Copy all the elements < p directly from swap to v. + let v_base = v.as_mut_ptr(); + ptr::copy_nonoverlapping(scratch_base, v_base, state.num_left); + + // Copy the elements >= p in reverse order. + for i in 0..len - state.num_left { + ptr::copy_nonoverlapping( + scratch_base.add(len - 1 - i), + v_base.add(state.num_left + i), + 1, + ); + } + + state.num_left + } +} + +struct PartitionState { + // The start of the scratch auxiliary memory. + scratch_base: *mut T, + // The current element that is being looked at, scans left to right through slice. + scan: *const T, + // Counts the number of elements that went to the left side, also works around: + // https://github.com/rust-lang/rust/issues/117128 + num_left: usize, + // Reverse scratch output pointer. + scratch_rev: *mut T, +} + +impl PartitionState { + /// # Safety + /// + /// `scan` and `scratch` must point to valid disjoint buffers of length `len`. The + /// scan buffer must be initialized. + unsafe fn new(scan: *const T, scratch: *mut T, len: usize) -> Self { + // SAFETY: See function safety comment. + unsafe { Self { scratch_base: scratch, scan, num_left: 0, scratch_rev: scratch.add(len) } } + } + + /// Depending on the value of `towards_left` this function will write a value + /// to the growing left or right side of the scratch memory. This forms the + /// branchless core of the partition. + /// + /// # Safety + /// + /// This function may be called at most `len` times. If it is called exactly + /// `len` times the scratch buffer then contains a copy of each element from + /// the scan buffer exactly once - a permutation, and num_left <= len. + unsafe fn partition_one(&mut self, towards_left: bool) -> *mut T { + // SAFETY: see individual comments. + unsafe { + // SAFETY: in-bounds because this function is called at most len times, and thus + // right now is incremented at most len - 1 times. Similarly, num_left < len and + // num_right < len, where num_right == i - num_left at the start of the ith + // iteration (zero-indexed). + self.scratch_rev = self.scratch_rev.sub(1); + + // SAFETY: now we have scratch_rev == base + len - (i + 1). This means + // scratch_rev + num_left == base + len - 1 - num_right < base + len. + let dst_base = if towards_left { self.scratch_base } else { self.scratch_rev }; + let dst = dst_base.add(self.num_left); + ptr::copy_nonoverlapping(self.scan, dst, 1); + + self.num_left += towards_left as usize; + self.scan = self.scan.add(1); + dst + } + } +} + +trait IsFreeze { + fn is_freeze() -> bool; +} + +impl IsFreeze for T { + default fn is_freeze() -> bool { + false + } +} +impl IsFreeze for T { + fn is_freeze() -> bool { + true + } +} + +#[must_use] +fn has_direct_interior_mutability() -> bool { + // If a type has interior mutability it may alter itself during comparison + // in a way that must be preserved after the sort operation concludes. + // Otherwise a type like Mutex>> could lead to double free. + !T::is_freeze() +} diff --git a/CoqOfRust/core/slice/sort/stable/tiny.rs b/CoqOfRust/core/slice/sort/stable/tiny.rs new file mode 100644 index 000000000..071ab8e10 --- /dev/null +++ b/CoqOfRust/core/slice/sort/stable/tiny.rs @@ -0,0 +1,41 @@ +//! Binary-size optimized mergesort inspired by https://github.com/voultapher/tiny-sort-rs. + +use crate::mem::MaybeUninit; +use crate::ptr; +use crate::slice::sort::stable::merge; + +/// Tiny recursive top-down merge sort optimized for binary size. It has no adaptiveness whatsoever, +/// no run detection, etc. +#[inline(always)] +pub fn mergesort bool>( + v: &mut [T], + scratch: &mut [MaybeUninit], + is_less: &mut F, +) { + let len = v.len(); + + if len > 2 { + let mid = len / 2; + + // SAFETY: mid is in-bounds. + unsafe { + // Sort the left half recursively. + mergesort(v.get_unchecked_mut(..mid), scratch, is_less); + // Sort the right half recursively. + mergesort(v.get_unchecked_mut(mid..), scratch, is_less); + } + + merge::merge(v, scratch, mid, is_less); + } else if len == 2 { + // SAFETY: We checked the len, the pointers we create are valid and don't overlap. + unsafe { + let v_base = v.as_mut_ptr(); + let v_a = v_base; + let v_b = v_base.add(1); + + if is_less(&*v_b, &*v_a) { + ptr::swap_nonoverlapping(v_a, v_b, 1); + } + } + } +} diff --git a/CoqOfRust/core/slice/sort/unstable/heapsort.rs b/CoqOfRust/core/slice/sort/unstable/heapsort.rs new file mode 100644 index 000000000..85231779d --- /dev/null +++ b/CoqOfRust/core/slice/sort/unstable/heapsort.rs @@ -0,0 +1,77 @@ +//! This module contains a branchless heapsort as fallback for unstable quicksort. + +use crate::{cmp, intrinsics, ptr}; + +/// Sorts `v` using heapsort, which guarantees *O*(*n* \* log(*n*)) worst-case. +/// +/// Never inline this, it sits the main hot-loop in `recurse` and is meant as unlikely algorithmic +/// fallback. +#[inline(never)] +pub(crate) fn heapsort(v: &mut [T], is_less: &mut F) +where + F: FnMut(&T, &T) -> bool, +{ + let len = v.len(); + + for i in (0..len + len / 2).rev() { + let sift_idx = if i >= len { + i - len + } else { + v.swap(0, i); + 0 + }; + + // SAFETY: The above calculation ensures that `sift_idx` is either 0 or + // `(len..(len + (len / 2))) - len`, which simplifies to `0..(len / 2)`. + // This guarantees the required `sift_idx <= len`. + unsafe { + sift_down(&mut v[..cmp::min(i, len)], sift_idx, is_less); + } + } +} + +// This binary heap respects the invariant `parent >= child`. +// +// SAFETY: The caller has to guarantee that `node <= v.len()`. +#[inline(always)] +unsafe fn sift_down(v: &mut [T], mut node: usize, is_less: &mut F) +where + F: FnMut(&T, &T) -> bool, +{ + // SAFETY: See function safety. + unsafe { + intrinsics::assume(node <= v.len()); + } + + let len = v.len(); + + let v_base = v.as_mut_ptr(); + + loop { + // Children of `node`. + let mut child = 2 * node + 1; + if child >= len { + break; + } + + // SAFETY: The invariants and checks guarantee that both node and child are in-bounds. + unsafe { + // Choose the greater child. + if child + 1 < len { + // We need a branch to be sure not to out-of-bounds index, + // but it's highly predictable. The comparison, however, + // is better done branchless, especially for primitives. + child += is_less(&*v_base.add(child), &*v_base.add(child + 1)) as usize; + } + + // Stop if the invariant holds at `node`. + if !is_less(&*v_base.add(node), &*v_base.add(child)) { + break; + } + + ptr::swap_nonoverlapping(v_base.add(node), v_base.add(child), 1); + } + + node = child; + } +} diff --git a/CoqOfRust/core/slice/sort/unstable/mod.rs b/CoqOfRust/core/slice/sort/unstable/mod.rs new file mode 100644 index 000000000..2eb653c46 --- /dev/null +++ b/CoqOfRust/core/slice/sort/unstable/mod.rs @@ -0,0 +1,84 @@ +//! This module contains the entry points for `slice::sort_unstable`. + +use crate::intrinsics; +use crate::mem::SizedTypeProperties; +#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))] +use crate::slice::sort::shared::find_existing_run; +#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))] +use crate::slice::sort::shared::smallsort::insertion_sort_shift_left; + +pub(crate) mod heapsort; +pub(crate) mod quicksort; + +/// Unstable sort called ipnsort by Lukas Bergdoll and Orson Peters. +/// Design document: +/// +/// +/// Upholds all safety properties outlined here: +/// +#[inline(always)] +pub fn sort bool>(v: &mut [T], is_less: &mut F) { + // Arrays of zero-sized types are always all-equal, and thus sorted. + if T::IS_ZST { + return; + } + + // Instrumenting the standard library showed that 90+% of the calls to sort + // by rustc are either of size 0 or 1. + let len = v.len(); + if intrinsics::likely(len < 2) { + return; + } + + cfg_if! { + if #[cfg(any(feature = "optimize_for_size", target_pointer_width = "16"))] { + heapsort::heapsort(v, is_less); + } else { + // More advanced sorting methods than insertion sort are faster if called in + // a hot loop for small inputs, but for general-purpose code the small + // binary size of insertion sort is more important. The instruction cache in + // modern processors is very valuable, and for a single sort call in general + // purpose code any gains from an advanced method are cancelled by i-cache + // misses during the sort, and thrashing the i-cache for surrounding code. + const MAX_LEN_ALWAYS_INSERTION_SORT: usize = 20; + if intrinsics::likely(len <= MAX_LEN_ALWAYS_INSERTION_SORT) { + insertion_sort_shift_left(v, 1, is_less); + return; + } + + ipnsort(v, is_less); + } + } +} + +/// See [`sort`] +/// +/// Deliberately don't inline the main sorting routine entrypoint to ensure the +/// inlined insertion sort i-cache footprint remains minimal. +#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))] +#[inline(never)] +fn ipnsort(v: &mut [T], is_less: &mut F) +where + F: FnMut(&T, &T) -> bool, +{ + let len = v.len(); + let (run_len, was_reversed) = find_existing_run(v, is_less); + + // SAFETY: find_existing_run promises to return a valid run_len. + unsafe { intrinsics::assume(run_len <= len) }; + + if run_len == len { + if was_reversed { + v.reverse(); + } + + // It would be possible to a do in-place merging here for a long existing streak. But that + // makes the implementation a lot bigger, users can use `slice::sort` for that use-case. + return; + } + + // Limit the number of imbalanced partitions to `2 * floor(log2(len))`. + // The binary OR by one is used to eliminate the zero-check in the logarithm. + let limit = 2 * (len | 1).ilog2(); + crate::slice::sort::unstable::quicksort::quicksort(v, None, limit, is_less); +} diff --git a/CoqOfRust/core/slice/sort/unstable/quicksort.rs b/CoqOfRust/core/slice/sort/unstable/quicksort.rs new file mode 100644 index 000000000..4feef5dee --- /dev/null +++ b/CoqOfRust/core/slice/sort/unstable/quicksort.rs @@ -0,0 +1,391 @@ +//! This module contains an unstable quicksort and two partition implementations. + +use crate::mem::{self, ManuallyDrop}; +#[cfg(not(feature = "optimize_for_size"))] +use crate::slice::sort::shared::pivot::choose_pivot; +#[cfg(not(feature = "optimize_for_size"))] +use crate::slice::sort::shared::smallsort::UnstableSmallSortTypeImpl; +#[cfg(not(feature = "optimize_for_size"))] +use crate::slice::sort::unstable::heapsort; +use crate::{intrinsics, ptr}; + +/// Sorts `v` recursively. +/// +/// If the slice had a predecessor in the original array, it is specified as `ancestor_pivot`. +/// +/// `limit` is the number of allowed imbalanced partitions before switching to `heapsort`. If zero, +/// this function will immediately switch to heapsort. +#[cfg(not(feature = "optimize_for_size"))] +pub(crate) fn quicksort<'a, T, F>( + mut v: &'a mut [T], + mut ancestor_pivot: Option<&'a T>, + mut limit: u32, + is_less: &mut F, +) where + F: FnMut(&T, &T) -> bool, +{ + loop { + if v.len() <= T::small_sort_threshold() { + T::small_sort(v, is_less); + return; + } + + // If too many bad pivot choices were made, simply fall back to heapsort in order to + // guarantee `O(N x log(N))` worst-case. + if limit == 0 { + heapsort::heapsort(v, is_less); + return; + } + + limit -= 1; + + // Choose a pivot and try guessing whether the slice is already sorted. + let pivot_pos = choose_pivot(v, is_less); + + // If the chosen pivot is equal to the predecessor, then it's the smallest element in the + // slice. Partition the slice into elements equal to and elements greater than the pivot. + // This case is usually hit when the slice contains many duplicate elements. + if let Some(p) = ancestor_pivot { + // SAFETY: We assume choose_pivot yields an in-bounds position. + if !is_less(p, unsafe { v.get_unchecked(pivot_pos) }) { + let num_lt = partition(v, pivot_pos, &mut |a, b| !is_less(b, a)); + + // Continue sorting elements greater than the pivot. We know that `num_lt` contains + // the pivot. So we can continue after `num_lt`. + v = &mut v[(num_lt + 1)..]; + ancestor_pivot = None; + continue; + } + } + + // Partition the slice. + let num_lt = partition(v, pivot_pos, is_less); + // SAFETY: partition ensures that `num_lt` will be in-bounds. + unsafe { intrinsics::assume(num_lt < v.len()) }; + + // Split the slice into `left`, `pivot`, and `right`. + let (left, right) = v.split_at_mut(num_lt); + let (pivot, right) = right.split_at_mut(1); + let pivot = &pivot[0]; + + // Recurse into the left side. We have a fixed recursion limit, testing shows no real + // benefit for recursing into the shorter side. + quicksort(left, ancestor_pivot, limit, is_less); + + // Continue with the right side. + v = right; + ancestor_pivot = Some(pivot); + } +} + +/// Takes the input slice `v` and re-arranges elements such that when the call returns normally +/// all elements that compare true for `is_less(elem, pivot)` where `pivot == v[pivot_pos]` are +/// on the left side of `v` followed by the other elements, notionally considered greater or +/// equal to `pivot`. +/// +/// Returns the number of elements that are compared true for `is_less(elem, pivot)`. +/// +/// If `is_less` does not implement a total order the resulting order and return value are +/// unspecified. All original elements will remain in `v` and any possible modifications via +/// interior mutability will be observable. Same is true if `is_less` panics or `v.len()` +/// exceeds `scratch.len()`. +pub(crate) fn partition(v: &mut [T], pivot: usize, is_less: &mut F) -> usize +where + F: FnMut(&T, &T) -> bool, +{ + let len = v.len(); + + // Allows for panic-free code-gen by proving this property to the compiler. + if len == 0 { + return 0; + } + + if pivot >= len { + intrinsics::abort(); + } + + // SAFETY: We checked that `pivot` is in-bounds. + unsafe { + // Place the pivot at the beginning of slice. + v.swap_unchecked(0, pivot); + } + let (pivot, v_without_pivot) = v.split_at_mut(1); + + // Assuming that Rust generates noalias LLVM IR we can be sure that a partition function + // signature of the form `(v: &mut [T], pivot: &T)` guarantees that pivot and v can't alias. + // Having this guarantee is crucial for optimizations. It's possible to copy the pivot value + // into a stack value, but this creates issues for types with interior mutability mandating + // a drop guard. + let pivot = &mut pivot[0]; + + // This construct is used to limit the LLVM IR generated, which saves large amounts of + // compile-time by only instantiating the code that is needed. Idea by Frank Steffahn. + let num_lt = (const { inst_partition::() })(v_without_pivot, pivot, is_less); + + if num_lt >= len { + intrinsics::abort(); + } + + // SAFETY: We checked that `num_lt` is in-bounds. + unsafe { + // Place the pivot between the two partitions. + v.swap_unchecked(0, num_lt); + } + + num_lt +} + +const fn inst_partition bool>() -> fn(&mut [T], &T, &mut F) -> usize { + const MAX_BRANCHLESS_PARTITION_SIZE: usize = 96; + if mem::size_of::() <= MAX_BRANCHLESS_PARTITION_SIZE { + // Specialize for types that are relatively cheap to copy, where branchless optimizations + // have large leverage e.g. `u64` and `String`. + cfg_if! { + if #[cfg(feature = "optimize_for_size")] { + partition_lomuto_branchless_simple:: + } else { + partition_lomuto_branchless_cyclic:: + } + } + } else { + partition_hoare_branchy_cyclic:: + } +} + +/// See [`partition`]. +fn partition_hoare_branchy_cyclic(v: &mut [T], pivot: &T, is_less: &mut F) -> usize +where + F: FnMut(&T, &T) -> bool, +{ + let len = v.len(); + + if len == 0 { + return 0; + } + + // Optimized for large types that are expensive to move. Not optimized for integers. Optimized + // for small code-gen, assuming that is_less is an expensive operation that generates + // substantial amounts of code or a call. And that copying elements will likely be a call to + // memcpy. Using 2 `ptr::copy_nonoverlapping` has the chance to be faster than + // `ptr::swap_nonoverlapping` because `memcpy` can use wide SIMD based on runtime feature + // detection. Benchmarks support this analysis. + + let mut gap_opt: Option> = None; + + // SAFETY: The left-to-right scanning loop performs a bounds check, where we know that `left >= + // v_base && left < right && right <= v_base.add(len)`. The right-to-left scanning loop performs + // a bounds check ensuring that `right` is in-bounds. We checked that `len` is more than zero, + // which means that unconditional `right = right.sub(1)` is safe to do. The exit check makes + // sure that `left` and `right` never alias, making `ptr::copy_nonoverlapping` safe. The + // drop-guard `gap` ensures that should `is_less` panic we always overwrite the duplicate in the + // input. `gap.pos` stores the previous value of `right` and starts at `right` and so it too is + // in-bounds. We never pass the saved `gap.value` to `is_less` while it is inside the `GapGuard` + // thus any changes via interior mutability will be observed. + unsafe { + let v_base = v.as_mut_ptr(); + + let mut left = v_base; + let mut right = v_base.add(len); + + loop { + // Find the first element greater than the pivot. + while left < right && is_less(&*left, pivot) { + left = left.add(1); + } + + // Find the last element equal to the pivot. + loop { + right = right.sub(1); + if left >= right || is_less(&*right, pivot) { + break; + } + } + + if left >= right { + break; + } + + // Swap the found pair of out-of-order elements via cyclic permutation. + let is_first_swap_pair = gap_opt.is_none(); + + if is_first_swap_pair { + gap_opt = Some(GapGuard { pos: right, value: ManuallyDrop::new(ptr::read(left)) }); + } + + let gap = gap_opt.as_mut().unwrap_unchecked(); + + // Single place where we instantiate ptr::copy_nonoverlapping in the partition. + if !is_first_swap_pair { + ptr::copy_nonoverlapping(left, gap.pos, 1); + } + gap.pos = right; + ptr::copy_nonoverlapping(right, left, 1); + + left = left.add(1); + } + + left.sub_ptr(v_base) + + // `gap_opt` goes out of scope and overwrites the last wrong-side element on the right side + // with the first wrong-side element of the left side that was initially overwritten by the + // first wrong-side element on the right side element. + } +} + +#[cfg(not(feature = "optimize_for_size"))] +struct PartitionState { + // The current element that is being looked at, scans left to right through slice. + right: *mut T, + // Counts the number of elements that compared less-than, also works around: + // https://github.com/rust-lang/rust/issues/117128 + num_lt: usize, + // Gap guard that tracks the temporary duplicate in the input. + gap: GapGuardRaw, +} + +#[cfg(not(feature = "optimize_for_size"))] +fn partition_lomuto_branchless_cyclic(v: &mut [T], pivot: &T, is_less: &mut F) -> usize +where + F: FnMut(&T, &T) -> bool, +{ + // Novel partition implementation by Lukas Bergdoll and Orson Peters. Branchless Lomuto + // partition paired with a cyclic permutation. + // https://github.com/Voultapher/sort-research-rs/blob/main/writeup/lomcyc_partition/text.md + + let len = v.len(); + let v_base = v.as_mut_ptr(); + + if len == 0 { + return 0; + } + + // SAFETY: We checked that `len` is more than zero, which means that reading `v_base` is safe to + // do. From there we have a bounded loop where `v_base.add(i)` is guaranteed in-bounds. `v` and + // `pivot` can't alias because of type system rules. The drop-guard `gap` ensures that should + // `is_less` panic we always overwrite the duplicate in the input. `gap.pos` stores the previous + // value of `right` and starts at `v_base` and so it too is in-bounds. Given `UNROLL_LEN == 2` + // after the main loop we either have A) the last element in `v` that has not yet been processed + // because `len % 2 != 0`, or B) all elements have been processed except the gap value that was + // saved at the beginning with `ptr::read(v_base)`. In the case A) the loop will iterate twice, + // first performing loop_body to take care of the last element that didn't fit into the unroll. + // After that the behavior is the same as for B) where we use the saved value as `right` to + // overwrite the duplicate. If this very last call to `is_less` panics the saved value will be + // copied back including all possible changes via interior mutability. If `is_less` does not + // panic and the code continues we overwrite the duplicate and do `right = right.add(1)`, this + // is safe to do with `&mut *gap.value` because `T` is the same as `[T; 1]` and generating a + // pointer one past the allocation is safe. + unsafe { + let mut loop_body = |state: &mut PartitionState| { + let right_is_lt = is_less(&*state.right, pivot); + let left = v_base.add(state.num_lt); + + ptr::copy(left, state.gap.pos, 1); + ptr::copy_nonoverlapping(state.right, left, 1); + + state.gap.pos = state.right; + state.num_lt += right_is_lt as usize; + + state.right = state.right.add(1); + }; + + // Ideally we could just use GapGuard in PartitionState, but the reference that is + // materialized with `&mut state` when calling `loop_body` would create a mutable reference + // to the parent struct that contains the gap value, invalidating the reference pointer + // created from a reference to the gap value in the cleanup loop. This is only an issue + // under Stacked Borrows, Tree Borrows accepts the intuitive code using GapGuard as valid. + let mut gap_value = ManuallyDrop::new(ptr::read(v_base)); + + let mut state = PartitionState { + num_lt: 0, + right: v_base.add(1), + + gap: GapGuardRaw { pos: v_base, value: &mut *gap_value }, + }; + + // Manual unrolling that works well on x86, Arm and with opt-level=s without murdering + // compile-times. Leaving this to the compiler yields ok to bad results. + let unroll_len = const { if mem::size_of::() <= 16 { 2 } else { 1 } }; + + let unroll_end = v_base.add(len - (unroll_len - 1)); + while state.right < unroll_end { + if unroll_len == 2 { + loop_body(&mut state); + loop_body(&mut state); + } else { + loop_body(&mut state); + } + } + + // Single instantiate `loop_body` for both the unroll cleanup and cyclic permutation + // cleanup. Optimizes binary-size and compile-time. + let end = v_base.add(len); + loop { + let is_done = state.right == end; + state.right = if is_done { state.gap.value } else { state.right }; + + loop_body(&mut state); + + if is_done { + mem::forget(state.gap); + break; + } + } + + state.num_lt + } +} + +#[cfg(feature = "optimize_for_size")] +fn partition_lomuto_branchless_simple bool>( + v: &mut [T], + pivot: &T, + is_less: &mut F, +) -> usize { + let mut left = 0; + + for right in 0..v.len() { + // SAFETY: `left` can at max be incremented by 1 each loop iteration, which implies that + // left <= right and that both are in-bounds. + unsafe { + let right_is_lt = is_less(v.get_unchecked(right), pivot); + v.swap_unchecked(left, right); + left += right_is_lt as usize; + } + } + + left +} + +struct GapGuard { + pos: *mut T, + value: ManuallyDrop, +} + +impl Drop for GapGuard { + fn drop(&mut self) { + // SAFETY: `self` MUST be constructed in a way that makes copying the gap value into + // `self.pos` sound. + unsafe { + ptr::copy_nonoverlapping(&*self.value, self.pos, 1); + } + } +} + +/// Ideally this wouldn't be needed and we could just use the regular GapGuard. +/// See comment in [`partition_lomuto_branchless_cyclic`]. +#[cfg(not(feature = "optimize_for_size"))] +struct GapGuardRaw { + pos: *mut T, + value: *mut T, +} + +#[cfg(not(feature = "optimize_for_size"))] +impl Drop for GapGuardRaw { + fn drop(&mut self) { + // SAFETY: `self` MUST be constructed in a way that makes copying the gap value into + // `self.pos` sound. + unsafe { + ptr::copy_nonoverlapping(self.value, self.pos, 1); + } + } +} diff --git a/CoqOfRust/core/slice/specialize.rs b/CoqOfRust/core/slice/specialize.rs new file mode 100644 index 000000000..80eb59058 --- /dev/null +++ b/CoqOfRust/core/slice/specialize.rs @@ -0,0 +1,23 @@ +pub(super) trait SpecFill { + fn spec_fill(&mut self, value: T); +} + +impl SpecFill for [T] { + default fn spec_fill(&mut self, value: T) { + if let Some((last, elems)) = self.split_last_mut() { + for el in elems { + el.clone_from(&value); + } + + *last = value + } + } +} + +impl SpecFill for [T] { + fn spec_fill(&mut self, value: T) { + for item in self.iter_mut() { + *item = value; + } + } +} diff --git a/CoqOfRust/core/str/converts.rs b/CoqOfRust/core/str/converts.rs new file mode 100644 index 000000000..c7bae4276 --- /dev/null +++ b/CoqOfRust/core/str/converts.rs @@ -0,0 +1,241 @@ +//! Ways to create a `str` from bytes slice. + +use super::Utf8Error; +use super::validations::run_utf8_validation; +use crate::{mem, ptr}; + +/// Converts a slice of bytes to a string slice. +/// +/// A string slice ([`&str`]) is made of bytes ([`u8`]), and a byte slice +/// ([`&[u8]`][byteslice]) is made of bytes, so this function converts between +/// the two. Not all byte slices are valid string slices, however: [`&str`] requires +/// that it is valid UTF-8. `from_utf8()` checks to ensure that the bytes are valid +/// UTF-8, and then does the conversion. +/// +/// [`&str`]: str +/// [byteslice]: slice +/// +/// If you are sure that the byte slice is valid UTF-8, and you don't want to +/// incur the overhead of the validity check, there is an unsafe version of +/// this function, [`from_utf8_unchecked`], which has the same +/// behavior but skips the check. +/// +/// If you need a `String` instead of a `&str`, consider +/// [`String::from_utf8`][string]. +/// +/// [string]: ../../std/string/struct.String.html#method.from_utf8 +/// +/// Because you can stack-allocate a `[u8; N]`, and you can take a +/// [`&[u8]`][byteslice] of it, this function is one way to have a +/// stack-allocated string. There is an example of this in the +/// examples section below. +/// +/// [byteslice]: slice +/// +/// # Errors +/// +/// Returns `Err` if the slice is not UTF-8 with a description as to why the +/// provided slice is not UTF-8. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::str; +/// +/// // some bytes, in a vector +/// let sparkle_heart = vec![240, 159, 146, 150]; +/// +/// // We know these bytes are valid, so just use `unwrap()`. +/// let sparkle_heart = str::from_utf8(&sparkle_heart).unwrap(); +/// +/// assert_eq!("💖", sparkle_heart); +/// ``` +/// +/// Incorrect bytes: +/// +/// ``` +/// use std::str; +/// +/// // some invalid bytes, in a vector +/// let sparkle_heart = vec![0, 159, 146, 150]; +/// +/// assert!(str::from_utf8(&sparkle_heart).is_err()); +/// ``` +/// +/// See the docs for [`Utf8Error`] for more details on the kinds of +/// errors that can be returned. +/// +/// A "stack allocated string": +/// +/// ``` +/// use std::str; +/// +/// // some bytes, in a stack-allocated array +/// let sparkle_heart = [240, 159, 146, 150]; +/// +/// // We know these bytes are valid, so just use `unwrap()`. +/// let sparkle_heart: &str = str::from_utf8(&sparkle_heart).unwrap(); +/// +/// assert_eq!("💖", sparkle_heart); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")] +#[rustc_diagnostic_item = "str_from_utf8"] +pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { + // FIXME(const-hack): This should use `?` again, once it's `const` + match run_utf8_validation(v) { + Ok(_) => { + // SAFETY: validation succeeded. + Ok(unsafe { from_utf8_unchecked(v) }) + } + Err(err) => Err(err), + } +} + +/// Converts a mutable slice of bytes to a mutable string slice. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::str; +/// +/// // "Hello, Rust!" as a mutable vector +/// let mut hellorust = vec![72, 101, 108, 108, 111, 44, 32, 82, 117, 115, 116, 33]; +/// +/// // As we know these bytes are valid, we can use `unwrap()` +/// let outstr = str::from_utf8_mut(&mut hellorust).unwrap(); +/// +/// assert_eq!("Hello, Rust!", outstr); +/// ``` +/// +/// Incorrect bytes: +/// +/// ``` +/// use std::str; +/// +/// // Some invalid bytes in a mutable vector +/// let mut invalid = vec![128, 223]; +/// +/// assert!(str::from_utf8_mut(&mut invalid).is_err()); +/// ``` +/// See the docs for [`Utf8Error`] for more details on the kinds of +/// errors that can be returned. +#[stable(feature = "str_mut_extras", since = "1.20.0")] +#[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")] +#[rustc_diagnostic_item = "str_from_utf8_mut"] +pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { + // FIXME(const-hack): This should use `?` again, once it's `const` + match run_utf8_validation(v) { + Ok(_) => { + // SAFETY: validation succeeded. + Ok(unsafe { from_utf8_unchecked_mut(v) }) + } + Err(err) => Err(err), + } +} + +/// Converts a slice of bytes to a string slice without checking +/// that the string contains valid UTF-8. +/// +/// See the safe version, [`from_utf8`], for more information. +/// +/// # Safety +/// +/// The bytes passed in must be valid UTF-8. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::str; +/// +/// // some bytes, in a vector +/// let sparkle_heart = vec![240, 159, 146, 150]; +/// +/// let sparkle_heart = unsafe { +/// str::from_utf8_unchecked(&sparkle_heart) +/// }; +/// +/// assert_eq!("💖", sparkle_heart); +/// ``` +#[inline] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_str_from_utf8_unchecked", since = "1.55.0")] +#[rustc_diagnostic_item = "str_from_utf8_unchecked"] +pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { + // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8. + // Also relies on `&str` and `&[u8]` having the same layout. + unsafe { mem::transmute(v) } +} + +/// Converts a slice of bytes to a string slice without checking +/// that the string contains valid UTF-8; mutable version. +/// +/// See the immutable version, [`from_utf8_unchecked()`] for more information. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::str; +/// +/// let mut heart = vec![240, 159, 146, 150]; +/// let heart = unsafe { str::from_utf8_unchecked_mut(&mut heart) }; +/// +/// assert_eq!("💖", heart); +/// ``` +#[inline] +#[must_use] +#[stable(feature = "str_mut_extras", since = "1.20.0")] +#[rustc_const_stable(feature = "const_str_from_utf8_unchecked_mut", since = "1.83.0")] +#[rustc_diagnostic_item = "str_from_utf8_unchecked_mut"] +pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { + // SAFETY: the caller must guarantee that the bytes `v` + // are valid UTF-8, thus the cast to `*mut str` is safe. + // Also, the pointer dereference is safe because that pointer + // comes from a reference which is guaranteed to be valid for writes. + unsafe { &mut *(v as *mut [u8] as *mut str) } +} + +/// Creates a `&str` from a pointer and a length. +/// +/// The pointed-to bytes must be valid UTF-8. +/// If this might not be the case, use `str::from_utf8(slice::from_raw_parts(ptr, len))`, +/// which will return an `Err` if the data isn't valid UTF-8. +/// +/// This function is the `str` equivalent of [`slice::from_raw_parts`](crate::slice::from_raw_parts). +/// See that function's documentation for safety concerns and examples. +/// +/// The mutable version of this function is [`from_raw_parts_mut`]. +#[inline] +#[must_use] +#[unstable(feature = "str_from_raw_parts", issue = "119206")] +pub const unsafe fn from_raw_parts<'a>(ptr: *const u8, len: usize) -> &'a str { + // SAFETY: the caller must uphold the safety contract for `from_raw_parts`. + unsafe { &*ptr::from_raw_parts(ptr, len) } +} + +/// Creates a `&mut str` from a pointer and a length. +/// +/// The pointed-to bytes must be valid UTF-8. +/// If this might not be the case, use `str::from_utf8_mut(slice::from_raw_parts_mut(ptr, len))`, +/// which will return an `Err` if the data isn't valid UTF-8. +/// +/// This function is the `str` equivalent of [`slice::from_raw_parts_mut`](crate::slice::from_raw_parts_mut). +/// See that function's documentation for safety concerns and examples. +/// +/// The immutable version of this function is [`from_raw_parts`]. +#[inline] +#[must_use] +#[unstable(feature = "str_from_raw_parts", issue = "119206")] +pub const unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut str { + // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`. + unsafe { &mut *ptr::from_raw_parts_mut(ptr, len) } +} diff --git a/CoqOfRust/core/str/count.rs b/CoqOfRust/core/str/count.rs new file mode 100644 index 000000000..b5d7aaf05 --- /dev/null +++ b/CoqOfRust/core/str/count.rs @@ -0,0 +1,137 @@ +//! Code for efficiently counting the number of `char`s in a UTF-8 encoded +//! string. +//! +//! Broadly, UTF-8 encodes `char`s as a "leading" byte which begins the `char`, +//! followed by some number (possibly 0) of continuation bytes. +//! +//! The leading byte can have a number of bit-patterns (with the specific +//! pattern indicating how many continuation bytes follow), but the continuation +//! bytes are always in the format `0b10XX_XXXX` (where the `X`s can take any +//! value). That is, the most significant bit is set, and the second most +//! significant bit is unset. +//! +//! To count the number of characters, we can just count the number of bytes in +//! the string which are not continuation bytes, which can be done many bytes at +//! a time fairly easily. +//! +//! Note: Because the term "leading byte" can sometimes be ambiguous (for +//! example, it could also refer to the first byte of a slice), we'll often use +//! the term "non-continuation byte" to refer to these bytes in the code. + +use core::intrinsics::unlikely; + +const USIZE_SIZE: usize = core::mem::size_of::(); +const UNROLL_INNER: usize = 4; + +#[inline] +pub(super) fn count_chars(s: &str) -> usize { + if cfg!(feature = "optimize_for_size") || s.len() < USIZE_SIZE * UNROLL_INNER { + // Avoid entering the optimized implementation for strings where the + // difference is not likely to matter, or where it might even be slower. + // That said, a ton of thought was not spent on the particular threshold + // here, beyond "this value seems to make sense". + char_count_general_case(s.as_bytes()) + } else { + do_count_chars(s) + } +} + +fn do_count_chars(s: &str) -> usize { + // For correctness, `CHUNK_SIZE` must be: + // + // - Less than or equal to 255, otherwise we'll overflow bytes in `counts`. + // - A multiple of `UNROLL_INNER`, otherwise our `break` inside the + // `body.chunks(CHUNK_SIZE)` loop is incorrect. + // + // For performance, `CHUNK_SIZE` should be: + // - Relatively cheap to `/` against (so some simple sum of powers of two). + // - Large enough to avoid paying for the cost of the `sum_bytes_in_usize` + // too often. + const CHUNK_SIZE: usize = 192; + + // Check the properties of `CHUNK_SIZE` and `UNROLL_INNER` that are required + // for correctness. + const _: () = assert!(CHUNK_SIZE < 256); + const _: () = assert!(CHUNK_SIZE % UNROLL_INNER == 0); + + // SAFETY: transmuting `[u8]` to `[usize]` is safe except for size + // differences which are handled by `align_to`. + let (head, body, tail) = unsafe { s.as_bytes().align_to::() }; + + // This should be quite rare, and basically exists to handle the degenerate + // cases where align_to fails (as well as miri under symbolic alignment + // mode). + // + // The `unlikely` helps discourage LLVM from inlining the body, which is + // nice, as we would rather not mark the `char_count_general_case` function + // as cold. + if unlikely(body.is_empty() || head.len() > USIZE_SIZE || tail.len() > USIZE_SIZE) { + return char_count_general_case(s.as_bytes()); + } + + let mut total = char_count_general_case(head) + char_count_general_case(tail); + // Split `body` into `CHUNK_SIZE` chunks to reduce the frequency with which + // we call `sum_bytes_in_usize`. + for chunk in body.chunks(CHUNK_SIZE) { + // We accumulate intermediate sums in `counts`, where each byte contains + // a subset of the sum of this chunk, like a `[u8; size_of::()]`. + let mut counts = 0; + + let (unrolled_chunks, remainder) = chunk.as_chunks::(); + for unrolled in unrolled_chunks { + for &word in unrolled { + // Because `CHUNK_SIZE` is < 256, this addition can't cause the + // count in any of the bytes to overflow into a subsequent byte. + counts += contains_non_continuation_byte(word); + } + } + + // Sum the values in `counts` (which, again, is conceptually a `[u8; + // size_of::()]`), and accumulate the result into `total`. + total += sum_bytes_in_usize(counts); + + // If there's any data in `remainder`, then handle it. This will only + // happen for the last `chunk` in `body.chunks()` (because `CHUNK_SIZE` + // is divisible by `UNROLL_INNER`), so we explicitly break at the end + // (which seems to help LLVM out). + if !remainder.is_empty() { + // Accumulate all the data in the remainder. + let mut counts = 0; + for &word in remainder { + counts += contains_non_continuation_byte(word); + } + total += sum_bytes_in_usize(counts); + break; + } + } + total +} + +// Checks each byte of `w` to see if it contains the first byte in a UTF-8 +// sequence. Bytes in `w` which are continuation bytes are left as `0x00` (e.g. +// false), and bytes which are non-continuation bytes are left as `0x01` (e.g. +// true) +#[inline] +fn contains_non_continuation_byte(w: usize) -> usize { + const LSB: usize = usize::repeat_u8(0x01); + ((!w >> 7) | (w >> 6)) & LSB +} + +// Morally equivalent to `values.to_ne_bytes().into_iter().sum::()`, but +// more efficient. +#[inline] +fn sum_bytes_in_usize(values: usize) -> usize { + const LSB_SHORTS: usize = usize::repeat_u16(0x0001); + const SKIP_BYTES: usize = usize::repeat_u16(0x00ff); + + let pair_sum: usize = (values & SKIP_BYTES) + ((values >> 8) & SKIP_BYTES); + pair_sum.wrapping_mul(LSB_SHORTS) >> ((USIZE_SIZE - 2) * 8) +} + +// This is the most direct implementation of the concept of "count the number of +// bytes in the string which are not continuation bytes", and is used for the +// head and tail of the input string (the first and last item in the tuple +// returned by `slice::align_to`). +fn char_count_general_case(s: &[u8]) -> usize { + s.iter().filter(|&&byte| !super::validations::utf8_is_cont_byte(byte)).count() +} diff --git a/CoqOfRust/core/str/error.rs b/CoqOfRust/core/str/error.rs new file mode 100644 index 000000000..4c8231a22 --- /dev/null +++ b/CoqOfRust/core/str/error.rs @@ -0,0 +1,155 @@ +//! Defines utf8 error type. + +use crate::error::Error; +use crate::fmt; + +/// Errors which can occur when attempting to interpret a sequence of [`u8`] +/// as a string. +/// +/// As such, the `from_utf8` family of functions and methods for both [`String`]s +/// and [`&str`]s make use of this error, for example. +/// +/// [`String`]: ../../std/string/struct.String.html#method.from_utf8 +/// [`&str`]: super::from_utf8 +/// +/// # Examples +/// +/// This error type’s methods can be used to create functionality +/// similar to `String::from_utf8_lossy` without allocating heap memory: +/// +/// ``` +/// fn from_utf8_lossy(mut input: &[u8], mut push: F) where F: FnMut(&str) { +/// loop { +/// match std::str::from_utf8(input) { +/// Ok(valid) => { +/// push(valid); +/// break +/// } +/// Err(error) => { +/// let (valid, after_valid) = input.split_at(error.valid_up_to()); +/// unsafe { +/// push(std::str::from_utf8_unchecked(valid)) +/// } +/// push("\u{FFFD}"); +/// +/// if let Some(invalid_sequence_length) = error.error_len() { +/// input = &after_valid[invalid_sequence_length..] +/// } else { +/// break +/// } +/// } +/// } +/// } +/// } +/// ``` +#[derive(Copy, Eq, PartialEq, Clone, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Utf8Error { + pub(super) valid_up_to: usize, + pub(super) error_len: Option, +} + +impl Utf8Error { + /// Returns the index in the given string up to which valid UTF-8 was + /// verified. + /// + /// It is the maximum index such that `from_utf8(&input[..index])` + /// would return `Ok(_)`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::str; + /// + /// // some invalid bytes, in a vector + /// let sparkle_heart = vec![0, 159, 146, 150]; + /// + /// // std::str::from_utf8 returns a Utf8Error + /// let error = str::from_utf8(&sparkle_heart).unwrap_err(); + /// + /// // the second byte is invalid here + /// assert_eq!(1, error.valid_up_to()); + /// ``` + #[stable(feature = "utf8_error", since = "1.5.0")] + #[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")] + #[must_use] + #[inline] + pub const fn valid_up_to(&self) -> usize { + self.valid_up_to + } + + /// Provides more information about the failure: + /// + /// * `None`: the end of the input was reached unexpectedly. + /// `self.valid_up_to()` is 1 to 3 bytes from the end of the input. + /// If a byte stream (such as a file or a network socket) is being decoded incrementally, + /// this could be a valid `char` whose UTF-8 byte sequence is spanning multiple chunks. + /// + /// * `Some(len)`: an unexpected byte was encountered. + /// The length provided is that of the invalid byte sequence + /// that starts at the index given by `valid_up_to()`. + /// Decoding should resume after that sequence + /// (after inserting a [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD]) in case of + /// lossy decoding. + /// + /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html + #[stable(feature = "utf8_error_error_len", since = "1.20.0")] + #[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")] + #[must_use] + #[inline] + pub const fn error_len(&self) -> Option { + // FIXME(const-hack): This should become `map` again, once it's `const` + match self.error_len { + Some(len) => Some(len as usize), + None => None, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Utf8Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(error_len) = self.error_len { + write!( + f, + "invalid utf-8 sequence of {} bytes from index {}", + error_len, self.valid_up_to + ) + } else { + write!(f, "incomplete utf-8 byte sequence from index {}", self.valid_up_to) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for Utf8Error { + #[allow(deprecated)] + fn description(&self) -> &str { + "invalid utf-8: corrupt contents" + } +} + +/// An error returned when parsing a `bool` using [`from_str`] fails +/// +/// [`from_str`]: super::FromStr::from_str +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct ParseBoolError; + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for ParseBoolError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + "provided string was not `true` or `false`".fmt(f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for ParseBoolError { + #[allow(deprecated)] + fn description(&self) -> &str { + "failed to parse bool" + } +} diff --git a/CoqOfRust/core/str/iter.rs b/CoqOfRust/core/str/iter.rs new file mode 100644 index 000000000..425c4eaee --- /dev/null +++ b/CoqOfRust/core/str/iter.rs @@ -0,0 +1,1610 @@ +//! Iterators for `str` methods. + +use super::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher}; +use super::validations::{next_code_point, next_code_point_reverse}; +use super::{ + BytesIsNotEmpty, CharEscapeDebugContinue, CharEscapeDefault, CharEscapeUnicode, + IsAsciiWhitespace, IsNotEmpty, IsWhitespace, LinesMap, UnsafeBytesToStr, from_utf8_unchecked, +}; +use crate::fmt::{self, Write}; +use crate::iter::{ + Chain, Copied, Filter, FlatMap, Flatten, FusedIterator, Map, TrustedLen, TrustedRandomAccess, + TrustedRandomAccessNoCoerce, +}; +use crate::num::NonZero; +use crate::ops::Try; +use crate::slice::{self, Split as SliceSplit}; +use crate::{char as char_mod, option}; + +/// An iterator over the [`char`]s of a string slice. +/// +/// +/// This struct is created by the [`chars`] method on [`str`]. +/// See its documentation for more. +/// +/// [`char`]: prim@char +/// [`chars`]: str::chars +#[derive(Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Chars<'a> { + pub(super) iter: slice::Iter<'a, u8>, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> Iterator for Chars<'a> { + type Item = char; + + #[inline] + fn next(&mut self) -> Option { + // SAFETY: `str` invariant says `self.iter` is a valid UTF-8 string and + // the resulting `ch` is a valid Unicode Scalar Value. + unsafe { next_code_point(&mut self.iter).map(|ch| char::from_u32_unchecked(ch)) } + } + + #[inline] + fn count(self) -> usize { + super::count::count_chars(self.as_str()) + } + + #[inline] + fn advance_by(&mut self, mut remainder: usize) -> Result<(), NonZero> { + const CHUNK_SIZE: usize = 32; + + if remainder >= CHUNK_SIZE { + let mut chunks = self.iter.as_slice().array_chunks::(); + let mut bytes_skipped: usize = 0; + + while remainder > CHUNK_SIZE + && let Some(chunk) = chunks.next() + { + bytes_skipped += CHUNK_SIZE; + + let mut start_bytes = [false; CHUNK_SIZE]; + + for i in 0..CHUNK_SIZE { + start_bytes[i] = !super::validations::utf8_is_cont_byte(chunk[i]); + } + + remainder -= start_bytes.into_iter().map(|i| i as u8).sum::() as usize; + } + + // SAFETY: The amount of bytes exists since we just iterated over them, + // so advance_by will succeed. + unsafe { self.iter.advance_by(bytes_skipped).unwrap_unchecked() }; + + // skip trailing continuation bytes + while self.iter.len() > 0 { + let b = self.iter.as_slice()[0]; + if !super::validations::utf8_is_cont_byte(b) { + break; + } + // SAFETY: We just peeked at the byte, therefore it exists + unsafe { self.iter.advance_by(1).unwrap_unchecked() }; + } + } + + while (remainder > 0) && (self.iter.len() > 0) { + remainder -= 1; + let b = self.iter.as_slice()[0]; + let slurp = super::validations::utf8_char_width(b); + // SAFETY: utf8 validity requires that the string must contain + // the continuation bytes (if any) + unsafe { self.iter.advance_by(slurp).unwrap_unchecked() }; + } + + NonZero::new(remainder).map_or(Ok(()), Err) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.iter.len(); + // `(len + 3)` can't overflow, because we know that the `slice::Iter` + // belongs to a slice in memory which has a maximum length of + // `isize::MAX` (that's well below `usize::MAX`). + ((len + 3) / 4, Some(len)) + } + + #[inline] + fn last(mut self) -> Option { + // No need to go through the entire string. + self.next_back() + } +} + +#[stable(feature = "chars_debug_impl", since = "1.38.0")] +impl fmt::Debug for Chars<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Chars(")?; + f.debug_list().entries(self.clone()).finish()?; + write!(f, ")")?; + Ok(()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> DoubleEndedIterator for Chars<'a> { + #[inline] + fn next_back(&mut self) -> Option { + // SAFETY: `str` invariant says `self.iter` is a valid UTF-8 string and + // the resulting `ch` is a valid Unicode Scalar Value. + unsafe { next_code_point_reverse(&mut self.iter).map(|ch| char::from_u32_unchecked(ch)) } + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Chars<'_> {} + +impl<'a> Chars<'a> { + /// Views the underlying data as a subslice of the original data. + /// + /// This has the same lifetime as the original slice, and so the + /// iterator can continue to be used while this exists. + /// + /// # Examples + /// + /// ``` + /// let mut chars = "abc".chars(); + /// + /// assert_eq!(chars.as_str(), "abc"); + /// chars.next(); + /// assert_eq!(chars.as_str(), "bc"); + /// chars.next(); + /// chars.next(); + /// assert_eq!(chars.as_str(), ""); + /// ``` + #[stable(feature = "iter_to_slice", since = "1.4.0")] + #[must_use] + #[inline] + pub fn as_str(&self) -> &'a str { + // SAFETY: `Chars` is only made from a str, which guarantees the iter is valid UTF-8. + unsafe { from_utf8_unchecked(self.iter.as_slice()) } + } +} + +/// An iterator over the [`char`]s of a string slice, and their positions. +/// +/// This struct is created by the [`char_indices`] method on [`str`]. +/// See its documentation for more. +/// +/// [`char`]: prim@char +/// [`char_indices`]: str::char_indices +#[derive(Clone, Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct CharIndices<'a> { + pub(super) front_offset: usize, + pub(super) iter: Chars<'a>, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> Iterator for CharIndices<'a> { + type Item = (usize, char); + + #[inline] + fn next(&mut self) -> Option<(usize, char)> { + let pre_len = self.iter.iter.len(); + match self.iter.next() { + None => None, + Some(ch) => { + let index = self.front_offset; + let len = self.iter.iter.len(); + self.front_offset += pre_len - len; + Some((index, ch)) + } + } + } + + #[inline] + fn count(self) -> usize { + self.iter.count() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + #[inline] + fn last(mut self) -> Option<(usize, char)> { + // No need to go through the entire string. + self.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> DoubleEndedIterator for CharIndices<'a> { + #[inline] + fn next_back(&mut self) -> Option<(usize, char)> { + self.iter.next_back().map(|ch| { + let index = self.front_offset + self.iter.iter.len(); + (index, ch) + }) + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for CharIndices<'_> {} + +impl<'a> CharIndices<'a> { + /// Views the underlying data as a subslice of the original data. + /// + /// This has the same lifetime as the original slice, and so the + /// iterator can continue to be used while this exists. + #[stable(feature = "iter_to_slice", since = "1.4.0")] + #[must_use] + #[inline] + pub fn as_str(&self) -> &'a str { + self.iter.as_str() + } + + /// Returns the byte position of the next character, or the length + /// of the underlying string if there are no more characters. + /// + /// This means that, when the iterator has not been fully consumed, + /// the returned value will match the index that will be returned + /// by the next call to [`next()`](Self::next). + /// + /// # Examples + /// + /// ``` + /// let mut chars = "a楽".char_indices(); + /// + /// // `next()` has not been called yet, so `offset()` returns the byte + /// // index of the first character of the string, which is always 0. + /// assert_eq!(chars.offset(), 0); + /// // As expected, the first call to `next()` also returns 0 as index. + /// assert_eq!(chars.next(), Some((0, 'a'))); + /// + /// // `next()` has been called once, so `offset()` returns the byte index + /// // of the second character ... + /// assert_eq!(chars.offset(), 1); + /// // ... which matches the index returned by the next call to `next()`. + /// assert_eq!(chars.next(), Some((1, '楽'))); + /// + /// // Once the iterator has been consumed, `offset()` returns the length + /// // in bytes of the string. + /// assert_eq!(chars.offset(), 4); + /// assert_eq!(chars.next(), None); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "char_indices_offset", since = "1.82.0")] + pub fn offset(&self) -> usize { + self.front_offset + } +} + +/// An iterator over the bytes of a string slice. +/// +/// This struct is created by the [`bytes`] method on [`str`]. +/// See its documentation for more. +/// +/// [`bytes`]: str::bytes +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone, Debug)] +pub struct Bytes<'a>(pub(super) Copied>); + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Bytes<'_> { + type Item = u8; + + #[inline] + fn next(&mut self) -> Option { + self.0.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + + #[inline] + fn count(self) -> usize { + self.0.count() + } + + #[inline] + fn last(self) -> Option { + self.0.last() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.0.nth(n) + } + + #[inline] + fn all(&mut self, f: F) -> bool + where + F: FnMut(Self::Item) -> bool, + { + self.0.all(f) + } + + #[inline] + fn any(&mut self, f: F) -> bool + where + F: FnMut(Self::Item) -> bool, + { + self.0.any(f) + } + + #[inline] + fn find

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + self.0.find(predicate) + } + + #[inline] + fn position

(&mut self, predicate: P) -> Option + where + P: FnMut(Self::Item) -> bool, + { + self.0.position(predicate) + } + + #[inline] + fn rposition

(&mut self, predicate: P) -> Option + where + P: FnMut(Self::Item) -> bool, + { + self.0.rposition(predicate) + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> u8 { + // SAFETY: the caller must uphold the safety contract + // for `Iterator::__iterator_get_unchecked`. + unsafe { self.0.__iterator_get_unchecked(idx) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Bytes<'_> { + #[inline] + fn next_back(&mut self) -> Option { + self.0.next_back() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.0.nth_back(n) + } + + #[inline] + fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + self.0.rfind(predicate) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Bytes<'_> { + #[inline] + fn len(&self) -> usize { + self.0.len() + } + + #[inline] + fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Bytes<'_> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Bytes<'_> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for Bytes<'_> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccessNoCoerce for Bytes<'_> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +/// This macro generates a Clone impl for string pattern API +/// wrapper types of the form X<'a, P> +macro_rules! derive_pattern_clone { + (clone $t:ident with |$s:ident| $e:expr) => { + impl<'a, P> Clone for $t<'a, P> + where + P: Pattern: Clone>, + { + fn clone(&self) -> Self { + let $s = self; + $e + } + } + }; +} + +/// This macro generates two public iterator structs +/// wrapping a private internal one that makes use of the `Pattern` API. +/// +/// For all patterns `P: Pattern` the following items will be +/// generated (generics omitted): +/// +/// struct $forward_iterator($internal_iterator); +/// struct $reverse_iterator($internal_iterator); +/// +/// impl Iterator for $forward_iterator +/// { /* internal ends up calling Searcher::next_match() */ } +/// +/// impl DoubleEndedIterator for $forward_iterator +/// where P::Searcher: DoubleEndedSearcher +/// { /* internal ends up calling Searcher::next_match_back() */ } +/// +/// impl Iterator for $reverse_iterator +/// where P::Searcher: ReverseSearcher +/// { /* internal ends up calling Searcher::next_match_back() */ } +/// +/// impl DoubleEndedIterator for $reverse_iterator +/// where P::Searcher: DoubleEndedSearcher +/// { /* internal ends up calling Searcher::next_match() */ } +/// +/// The internal one is defined outside the macro, and has almost the same +/// semantic as a DoubleEndedIterator by delegating to `pattern::Searcher` and +/// `pattern::ReverseSearcher` for both forward and reverse iteration. +/// +/// "Almost", because a `Searcher` and a `ReverseSearcher` for a given +/// `Pattern` might not return the same elements, so actually implementing +/// `DoubleEndedIterator` for it would be incorrect. +/// (See the docs in `str::pattern` for more details) +/// +/// However, the internal struct still represents a single ended iterator from +/// either end, and depending on pattern is also a valid double ended iterator, +/// so the two wrapper structs implement `Iterator` +/// and `DoubleEndedIterator` depending on the concrete pattern type, leading +/// to the complex impls seen above. +macro_rules! generate_pattern_iterators { + { + // Forward iterator + forward: + $(#[$forward_iterator_attribute:meta])* + struct $forward_iterator:ident; + + // Reverse iterator + reverse: + $(#[$reverse_iterator_attribute:meta])* + struct $reverse_iterator:ident; + + // Stability of all generated items + stability: + $(#[$common_stability_attribute:meta])* + + // Internal almost-iterator that is being delegated to + internal: + $internal_iterator:ident yielding ($iterty:ty); + + // Kind of delegation - either single ended or double ended + delegate $($t:tt)* + } => { + $(#[$forward_iterator_attribute])* + $(#[$common_stability_attribute])* + pub struct $forward_iterator<'a, P: Pattern>(pub(super) $internal_iterator<'a, P>); + + $(#[$common_stability_attribute])* + impl<'a, P> fmt::Debug for $forward_iterator<'a, P> + where + P: Pattern: fmt::Debug>, + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple(stringify!($forward_iterator)) + .field(&self.0) + .finish() + } + } + + $(#[$common_stability_attribute])* + impl<'a, P: Pattern> Iterator for $forward_iterator<'a, P> { + type Item = $iterty; + + #[inline] + fn next(&mut self) -> Option<$iterty> { + self.0.next() + } + } + + $(#[$common_stability_attribute])* + impl<'a, P> Clone for $forward_iterator<'a, P> + where + P: Pattern: Clone>, + { + fn clone(&self) -> Self { + $forward_iterator(self.0.clone()) + } + } + + $(#[$reverse_iterator_attribute])* + $(#[$common_stability_attribute])* + pub struct $reverse_iterator<'a, P: Pattern>(pub(super) $internal_iterator<'a, P>); + + $(#[$common_stability_attribute])* + impl<'a, P> fmt::Debug for $reverse_iterator<'a, P> + where + P: Pattern: fmt::Debug>, + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple(stringify!($reverse_iterator)) + .field(&self.0) + .finish() + } + } + + $(#[$common_stability_attribute])* + impl<'a, P> Iterator for $reverse_iterator<'a, P> + where + P: Pattern: ReverseSearcher<'a>>, + { + type Item = $iterty; + + #[inline] + fn next(&mut self) -> Option<$iterty> { + self.0.next_back() + } + } + + $(#[$common_stability_attribute])* + impl<'a, P> Clone for $reverse_iterator<'a, P> + where + P: Pattern: Clone>, + { + fn clone(&self) -> Self { + $reverse_iterator(self.0.clone()) + } + } + + #[stable(feature = "fused", since = "1.26.0")] + impl<'a, P: Pattern> FusedIterator for $forward_iterator<'a, P> {} + + #[stable(feature = "fused", since = "1.26.0")] + impl<'a, P> FusedIterator for $reverse_iterator<'a, P> + where + P: Pattern: ReverseSearcher<'a>>, + {} + + generate_pattern_iterators!($($t)* with $(#[$common_stability_attribute])*, + $forward_iterator, + $reverse_iterator, $iterty); + }; + { + double ended; with $(#[$common_stability_attribute:meta])*, + $forward_iterator:ident, + $reverse_iterator:ident, $iterty:ty + } => { + $(#[$common_stability_attribute])* + impl<'a, P> DoubleEndedIterator for $forward_iterator<'a, P> + where + P: Pattern: DoubleEndedSearcher<'a>>, + { + #[inline] + fn next_back(&mut self) -> Option<$iterty> { + self.0.next_back() + } + } + + $(#[$common_stability_attribute])* + impl<'a, P> DoubleEndedIterator for $reverse_iterator<'a, P> + where + P: Pattern: DoubleEndedSearcher<'a>>, + { + #[inline] + fn next_back(&mut self) -> Option<$iterty> { + self.0.next() + } + } + }; + { + single ended; with $(#[$common_stability_attribute:meta])*, + $forward_iterator:ident, + $reverse_iterator:ident, $iterty:ty + } => {} +} + +derive_pattern_clone! { + clone SplitInternal + with |s| SplitInternal { matcher: s.matcher.clone(), ..*s } +} + +pub(super) struct SplitInternal<'a, P: Pattern> { + pub(super) start: usize, + pub(super) end: usize, + pub(super) matcher: P::Searcher<'a>, + pub(super) allow_trailing_empty: bool, + pub(super) finished: bool, +} + +impl<'a, P> fmt::Debug for SplitInternal<'a, P> +where + P: Pattern: fmt::Debug>, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SplitInternal") + .field("start", &self.start) + .field("end", &self.end) + .field("matcher", &self.matcher) + .field("allow_trailing_empty", &self.allow_trailing_empty) + .field("finished", &self.finished) + .finish() + } +} + +impl<'a, P: Pattern> SplitInternal<'a, P> { + #[inline] + fn get_end(&mut self) -> Option<&'a str> { + if !self.finished { + self.finished = true; + + if self.allow_trailing_empty || self.end - self.start > 0 { + // SAFETY: `self.start` and `self.end` always lie on unicode boundaries. + let string = unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) }; + return Some(string); + } + } + + None + } + + #[inline] + fn next(&mut self) -> Option<&'a str> { + if self.finished { + return None; + } + + let haystack = self.matcher.haystack(); + match self.matcher.next_match() { + // SAFETY: `Searcher` guarantees that `a` and `b` lie on unicode boundaries. + Some((a, b)) => unsafe { + let elt = haystack.get_unchecked(self.start..a); + self.start = b; + Some(elt) + }, + None => self.get_end(), + } + } + + #[inline] + fn next_inclusive(&mut self) -> Option<&'a str> { + if self.finished { + return None; + } + + let haystack = self.matcher.haystack(); + match self.matcher.next_match() { + // SAFETY: `Searcher` guarantees that `b` lies on unicode boundary, + // and self.start is either the start of the original string, + // or `b` was assigned to it, so it also lies on unicode boundary. + Some((_, b)) => unsafe { + let elt = haystack.get_unchecked(self.start..b); + self.start = b; + Some(elt) + }, + None => self.get_end(), + } + } + + #[inline] + fn next_back(&mut self) -> Option<&'a str> + where + P::Searcher<'a>: ReverseSearcher<'a>, + { + if self.finished { + return None; + } + + if !self.allow_trailing_empty { + self.allow_trailing_empty = true; + match self.next_back() { + Some(elt) if !elt.is_empty() => return Some(elt), + _ => { + if self.finished { + return None; + } + } + } + } + + let haystack = self.matcher.haystack(); + match self.matcher.next_match_back() { + // SAFETY: `Searcher` guarantees that `a` and `b` lie on unicode boundaries. + Some((a, b)) => unsafe { + let elt = haystack.get_unchecked(b..self.end); + self.end = a; + Some(elt) + }, + // SAFETY: `self.start` and `self.end` always lie on unicode boundaries. + None => unsafe { + self.finished = true; + Some(haystack.get_unchecked(self.start..self.end)) + }, + } + } + + #[inline] + fn next_back_inclusive(&mut self) -> Option<&'a str> + where + P::Searcher<'a>: ReverseSearcher<'a>, + { + if self.finished { + return None; + } + + if !self.allow_trailing_empty { + self.allow_trailing_empty = true; + match self.next_back_inclusive() { + Some(elt) if !elt.is_empty() => return Some(elt), + _ => { + if self.finished { + return None; + } + } + } + } + + let haystack = self.matcher.haystack(); + match self.matcher.next_match_back() { + // SAFETY: `Searcher` guarantees that `b` lies on unicode boundary, + // and self.end is either the end of the original string, + // or `b` was assigned to it, so it also lies on unicode boundary. + Some((_, b)) => unsafe { + let elt = haystack.get_unchecked(b..self.end); + self.end = b; + Some(elt) + }, + // SAFETY: self.start is either the start of the original string, + // or start of a substring that represents the part of the string that hasn't + // iterated yet. Either way, it is guaranteed to lie on unicode boundary. + // self.end is either the end of the original string, + // or `b` was assigned to it, so it also lies on unicode boundary. + None => unsafe { + self.finished = true; + Some(haystack.get_unchecked(self.start..self.end)) + }, + } + } + + #[inline] + fn remainder(&self) -> Option<&'a str> { + // `Self::get_end` doesn't change `self.start` + if self.finished { + return None; + } + + // SAFETY: `self.start` and `self.end` always lie on unicode boundaries. + Some(unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) }) + } +} + +generate_pattern_iterators! { + forward: + /// Created with the method [`split`]. + /// + /// [`split`]: str::split + struct Split; + reverse: + /// Created with the method [`rsplit`]. + /// + /// [`rsplit`]: str::rsplit + struct RSplit; + stability: + #[stable(feature = "rust1", since = "1.0.0")] + internal: + SplitInternal yielding (&'a str); + delegate double ended; +} + +impl<'a, P: Pattern> Split<'a, P> { + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_split_remainder)] + /// let mut split = "Mary had a little lamb".split(' '); + /// assert_eq!(split.remainder(), Some("Mary had a little lamb")); + /// split.next(); + /// assert_eq!(split.remainder(), Some("had a little lamb")); + /// split.by_ref().for_each(drop); + /// assert_eq!(split.remainder(), None); + /// ``` + #[inline] + #[unstable(feature = "str_split_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.remainder() + } +} + +impl<'a, P: Pattern> RSplit<'a, P> { + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_split_remainder)] + /// let mut split = "Mary had a little lamb".rsplit(' '); + /// assert_eq!(split.remainder(), Some("Mary had a little lamb")); + /// split.next(); + /// assert_eq!(split.remainder(), Some("Mary had a little")); + /// split.by_ref().for_each(drop); + /// assert_eq!(split.remainder(), None); + /// ``` + #[inline] + #[unstable(feature = "str_split_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.remainder() + } +} + +generate_pattern_iterators! { + forward: + /// Created with the method [`split_terminator`]. + /// + /// [`split_terminator`]: str::split_terminator + struct SplitTerminator; + reverse: + /// Created with the method [`rsplit_terminator`]. + /// + /// [`rsplit_terminator`]: str::rsplit_terminator + struct RSplitTerminator; + stability: + #[stable(feature = "rust1", since = "1.0.0")] + internal: + SplitInternal yielding (&'a str); + delegate double ended; +} + +impl<'a, P: Pattern> SplitTerminator<'a, P> { + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_split_remainder)] + /// let mut split = "A..B..".split_terminator('.'); + /// assert_eq!(split.remainder(), Some("A..B..")); + /// split.next(); + /// assert_eq!(split.remainder(), Some(".B..")); + /// split.by_ref().for_each(drop); + /// assert_eq!(split.remainder(), None); + /// ``` + #[inline] + #[unstable(feature = "str_split_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.remainder() + } +} + +impl<'a, P: Pattern> RSplitTerminator<'a, P> { + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_split_remainder)] + /// let mut split = "A..B..".rsplit_terminator('.'); + /// assert_eq!(split.remainder(), Some("A..B..")); + /// split.next(); + /// assert_eq!(split.remainder(), Some("A..B")); + /// split.by_ref().for_each(drop); + /// assert_eq!(split.remainder(), None); + /// ``` + #[inline] + #[unstable(feature = "str_split_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.remainder() + } +} + +derive_pattern_clone! { + clone SplitNInternal + with |s| SplitNInternal { iter: s.iter.clone(), ..*s } +} + +pub(super) struct SplitNInternal<'a, P: Pattern> { + pub(super) iter: SplitInternal<'a, P>, + /// The number of splits remaining + pub(super) count: usize, +} + +impl<'a, P> fmt::Debug for SplitNInternal<'a, P> +where + P: Pattern: fmt::Debug>, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SplitNInternal") + .field("iter", &self.iter) + .field("count", &self.count) + .finish() + } +} + +impl<'a, P: Pattern> SplitNInternal<'a, P> { + #[inline] + fn next(&mut self) -> Option<&'a str> { + match self.count { + 0 => None, + 1 => { + self.count = 0; + self.iter.get_end() + } + _ => { + self.count -= 1; + self.iter.next() + } + } + } + + #[inline] + fn next_back(&mut self) -> Option<&'a str> + where + P::Searcher<'a>: ReverseSearcher<'a>, + { + match self.count { + 0 => None, + 1 => { + self.count = 0; + self.iter.get_end() + } + _ => { + self.count -= 1; + self.iter.next_back() + } + } + } + + #[inline] + fn remainder(&self) -> Option<&'a str> { + self.iter.remainder() + } +} + +generate_pattern_iterators! { + forward: + /// Created with the method [`splitn`]. + /// + /// [`splitn`]: str::splitn + struct SplitN; + reverse: + /// Created with the method [`rsplitn`]. + /// + /// [`rsplitn`]: str::rsplitn + struct RSplitN; + stability: + #[stable(feature = "rust1", since = "1.0.0")] + internal: + SplitNInternal yielding (&'a str); + delegate single ended; +} + +impl<'a, P: Pattern> SplitN<'a, P> { + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_split_remainder)] + /// let mut split = "Mary had a little lamb".splitn(3, ' '); + /// assert_eq!(split.remainder(), Some("Mary had a little lamb")); + /// split.next(); + /// assert_eq!(split.remainder(), Some("had a little lamb")); + /// split.by_ref().for_each(drop); + /// assert_eq!(split.remainder(), None); + /// ``` + #[inline] + #[unstable(feature = "str_split_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.remainder() + } +} + +impl<'a, P: Pattern> RSplitN<'a, P> { + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_split_remainder)] + /// let mut split = "Mary had a little lamb".rsplitn(3, ' '); + /// assert_eq!(split.remainder(), Some("Mary had a little lamb")); + /// split.next(); + /// assert_eq!(split.remainder(), Some("Mary had a little")); + /// split.by_ref().for_each(drop); + /// assert_eq!(split.remainder(), None); + /// ``` + #[inline] + #[unstable(feature = "str_split_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.remainder() + } +} + +derive_pattern_clone! { + clone MatchIndicesInternal + with |s| MatchIndicesInternal(s.0.clone()) +} + +pub(super) struct MatchIndicesInternal<'a, P: Pattern>(pub(super) P::Searcher<'a>); + +impl<'a, P> fmt::Debug for MatchIndicesInternal<'a, P> +where + P: Pattern: fmt::Debug>, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("MatchIndicesInternal").field(&self.0).finish() + } +} + +impl<'a, P: Pattern> MatchIndicesInternal<'a, P> { + #[inline] + fn next(&mut self) -> Option<(usize, &'a str)> { + self.0 + .next_match() + // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries. + .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) }) + } + + #[inline] + fn next_back(&mut self) -> Option<(usize, &'a str)> + where + P::Searcher<'a>: ReverseSearcher<'a>, + { + self.0 + .next_match_back() + // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries. + .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) }) + } +} + +generate_pattern_iterators! { + forward: + /// Created with the method [`match_indices`]. + /// + /// [`match_indices`]: str::match_indices + struct MatchIndices; + reverse: + /// Created with the method [`rmatch_indices`]. + /// + /// [`rmatch_indices`]: str::rmatch_indices + struct RMatchIndices; + stability: + #[stable(feature = "str_match_indices", since = "1.5.0")] + internal: + MatchIndicesInternal yielding ((usize, &'a str)); + delegate double ended; +} + +derive_pattern_clone! { + clone MatchesInternal + with |s| MatchesInternal(s.0.clone()) +} + +pub(super) struct MatchesInternal<'a, P: Pattern>(pub(super) P::Searcher<'a>); + +impl<'a, P> fmt::Debug for MatchesInternal<'a, P> +where + P: Pattern: fmt::Debug>, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("MatchesInternal").field(&self.0).finish() + } +} + +impl<'a, P: Pattern> MatchesInternal<'a, P> { + #[inline] + fn next(&mut self) -> Option<&'a str> { + // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries. + self.0.next_match().map(|(a, b)| unsafe { + // Indices are known to be on utf8 boundaries + self.0.haystack().get_unchecked(a..b) + }) + } + + #[inline] + fn next_back(&mut self) -> Option<&'a str> + where + P::Searcher<'a>: ReverseSearcher<'a>, + { + // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries. + self.0.next_match_back().map(|(a, b)| unsafe { + // Indices are known to be on utf8 boundaries + self.0.haystack().get_unchecked(a..b) + }) + } +} + +generate_pattern_iterators! { + forward: + /// Created with the method [`matches`]. + /// + /// [`matches`]: str::matches + struct Matches; + reverse: + /// Created with the method [`rmatches`]. + /// + /// [`rmatches`]: str::rmatches + struct RMatches; + stability: + #[stable(feature = "str_matches", since = "1.2.0")] + internal: + MatchesInternal yielding (&'a str); + delegate double ended; +} + +/// An iterator over the lines of a string, as string slices. +/// +/// This struct is created with the [`lines`] method on [`str`]. +/// See its documentation for more. +/// +/// [`lines`]: str::lines +#[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[derive(Clone, Debug)] +pub struct Lines<'a>(pub(super) Map, LinesMap>); + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> Iterator for Lines<'a> { + type Item = &'a str; + + #[inline] + fn next(&mut self) -> Option<&'a str> { + self.0.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + + #[inline] + fn last(mut self) -> Option<&'a str> { + self.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> DoubleEndedIterator for Lines<'a> { + #[inline] + fn next_back(&mut self) -> Option<&'a str> { + self.0.next_back() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Lines<'_> {} + +impl<'a> Lines<'a> { + /// Returns the remaining lines of the split string. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_lines_remainder)] + /// + /// let mut lines = "a\nb\nc\nd".lines(); + /// assert_eq!(lines.remainder(), Some("a\nb\nc\nd")); + /// + /// lines.next(); + /// assert_eq!(lines.remainder(), Some("b\nc\nd")); + /// + /// lines.by_ref().for_each(drop); + /// assert_eq!(lines.remainder(), None); + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "str_lines_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.iter.remainder() + } +} + +/// Created with the method [`lines_any`]. +/// +/// [`lines_any`]: str::lines_any +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.4.0", note = "use lines()/Lines instead now")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[derive(Clone, Debug)] +#[allow(deprecated)] +pub struct LinesAny<'a>(pub(super) Lines<'a>); + +#[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] +impl<'a> Iterator for LinesAny<'a> { + type Item = &'a str; + + #[inline] + fn next(&mut self) -> Option<&'a str> { + self.0.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] +impl<'a> DoubleEndedIterator for LinesAny<'a> { + #[inline] + fn next_back(&mut self) -> Option<&'a str> { + self.0.next_back() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +#[allow(deprecated)] +impl FusedIterator for LinesAny<'_> {} + +/// An iterator over the non-whitespace substrings of a string, +/// separated by any amount of whitespace. +/// +/// This struct is created by the [`split_whitespace`] method on [`str`]. +/// See its documentation for more. +/// +/// [`split_whitespace`]: str::split_whitespace +#[stable(feature = "split_whitespace", since = "1.1.0")] +#[derive(Clone, Debug)] +pub struct SplitWhitespace<'a> { + pub(super) inner: Filter, IsNotEmpty>, +} + +/// An iterator over the non-ASCII-whitespace substrings of a string, +/// separated by any amount of ASCII whitespace. +/// +/// This struct is created by the [`split_ascii_whitespace`] method on [`str`]. +/// See its documentation for more. +/// +/// [`split_ascii_whitespace`]: str::split_ascii_whitespace +#[stable(feature = "split_ascii_whitespace", since = "1.34.0")] +#[derive(Clone, Debug)] +pub struct SplitAsciiWhitespace<'a> { + pub(super) inner: + Map, BytesIsNotEmpty>, UnsafeBytesToStr>, +} + +/// An iterator over the substrings of a string, +/// terminated by a substring matching to a predicate function +/// Unlike `Split`, it contains the matched part as a terminator +/// of the subslice. +/// +/// This struct is created by the [`split_inclusive`] method on [`str`]. +/// See its documentation for more. +/// +/// [`split_inclusive`]: str::split_inclusive +#[stable(feature = "split_inclusive", since = "1.51.0")] +pub struct SplitInclusive<'a, P: Pattern>(pub(super) SplitInternal<'a, P>); + +#[stable(feature = "split_whitespace", since = "1.1.0")] +impl<'a> Iterator for SplitWhitespace<'a> { + type Item = &'a str; + + #[inline] + fn next(&mut self) -> Option<&'a str> { + self.inner.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + #[inline] + fn last(mut self) -> Option<&'a str> { + self.next_back() + } +} + +#[stable(feature = "split_whitespace", since = "1.1.0")] +impl<'a> DoubleEndedIterator for SplitWhitespace<'a> { + #[inline] + fn next_back(&mut self) -> Option<&'a str> { + self.inner.next_back() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for SplitWhitespace<'_> {} + +impl<'a> SplitWhitespace<'a> { + /// Returns remainder of the split string + /// + /// # Examples + /// + /// ``` + /// #![feature(str_split_whitespace_remainder)] + /// + /// let mut split = "Mary had a little lamb".split_whitespace(); + /// assert_eq!(split.remainder(), Some("Mary had a little lamb")); + /// + /// split.next(); + /// assert_eq!(split.remainder(), Some("had a little lamb")); + /// + /// split.by_ref().for_each(drop); + /// assert_eq!(split.remainder(), None); + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "str_split_whitespace_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.inner.iter.remainder() + } +} + +#[stable(feature = "split_ascii_whitespace", since = "1.34.0")] +impl<'a> Iterator for SplitAsciiWhitespace<'a> { + type Item = &'a str; + + #[inline] + fn next(&mut self) -> Option<&'a str> { + self.inner.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + #[inline] + fn last(mut self) -> Option<&'a str> { + self.next_back() + } +} + +#[stable(feature = "split_ascii_whitespace", since = "1.34.0")] +impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a> { + #[inline] + fn next_back(&mut self) -> Option<&'a str> { + self.inner.next_back() + } +} + +#[stable(feature = "split_ascii_whitespace", since = "1.34.0")] +impl FusedIterator for SplitAsciiWhitespace<'_> {} + +impl<'a> SplitAsciiWhitespace<'a> { + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_split_whitespace_remainder)] + /// + /// let mut split = "Mary had a little lamb".split_ascii_whitespace(); + /// assert_eq!(split.remainder(), Some("Mary had a little lamb")); + /// + /// split.next(); + /// assert_eq!(split.remainder(), Some("had a little lamb")); + /// + /// split.by_ref().for_each(drop); + /// assert_eq!(split.remainder(), None); + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "str_split_whitespace_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + if self.inner.iter.iter.finished { + return None; + } + + // SAFETY: Slice is created from str. + Some(unsafe { crate::str::from_utf8_unchecked(&self.inner.iter.iter.v) }) + } +} + +#[stable(feature = "split_inclusive", since = "1.51.0")] +impl<'a, P: Pattern> Iterator for SplitInclusive<'a, P> { + type Item = &'a str; + + #[inline] + fn next(&mut self) -> Option<&'a str> { + self.0.next_inclusive() + } +} + +#[stable(feature = "split_inclusive", since = "1.51.0")] +impl<'a, P: Pattern: fmt::Debug>> fmt::Debug for SplitInclusive<'a, P> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SplitInclusive").field("0", &self.0).finish() + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "split_inclusive", since = "1.51.0")] +impl<'a, P: Pattern: Clone>> Clone for SplitInclusive<'a, P> { + fn clone(&self) -> Self { + SplitInclusive(self.0.clone()) + } +} + +#[stable(feature = "split_inclusive", since = "1.51.0")] +impl<'a, P: Pattern: DoubleEndedSearcher<'a>>> DoubleEndedIterator + for SplitInclusive<'a, P> +{ + #[inline] + fn next_back(&mut self) -> Option<&'a str> { + self.0.next_back_inclusive() + } +} + +#[stable(feature = "split_inclusive", since = "1.51.0")] +impl<'a, P: Pattern> FusedIterator for SplitInclusive<'a, P> {} + +impl<'a, P: Pattern> SplitInclusive<'a, P> { + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_split_inclusive_remainder)] + /// let mut split = "Mary had a little lamb".split_inclusive(' '); + /// assert_eq!(split.remainder(), Some("Mary had a little lamb")); + /// split.next(); + /// assert_eq!(split.remainder(), Some("had a little lamb")); + /// split.by_ref().for_each(drop); + /// assert_eq!(split.remainder(), None); + /// ``` + #[inline] + #[unstable(feature = "str_split_inclusive_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.remainder() + } +} + +/// An iterator of [`u16`] over the string encoded as UTF-16. +/// +/// This struct is created by the [`encode_utf16`] method on [`str`]. +/// See its documentation for more. +/// +/// [`encode_utf16`]: str::encode_utf16 +#[derive(Clone)] +#[stable(feature = "encode_utf16", since = "1.8.0")] +pub struct EncodeUtf16<'a> { + pub(super) chars: Chars<'a>, + pub(super) extra: u16, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for EncodeUtf16<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("EncodeUtf16").finish_non_exhaustive() + } +} + +#[stable(feature = "encode_utf16", since = "1.8.0")] +impl<'a> Iterator for EncodeUtf16<'a> { + type Item = u16; + + #[inline] + fn next(&mut self) -> Option { + if self.extra != 0 { + let tmp = self.extra; + self.extra = 0; + return Some(tmp); + } + + let mut buf = [0; 2]; + self.chars.next().map(|ch| { + let n = ch.encode_utf16(&mut buf).len(); + if n == 2 { + self.extra = buf[1]; + } + buf[0] + }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.chars.iter.len(); + // The highest bytes:code units ratio occurs for 3-byte sequences, + // since a 4-byte sequence results in 2 code units. The lower bound + // is therefore determined by assuming the remaining bytes contain as + // many 3-byte sequences as possible. The highest bytes:code units + // ratio is for 1-byte sequences, so use this for the upper bound. + // `(len + 2)` can't overflow, because we know that the `slice::Iter` + // belongs to a slice in memory which has a maximum length of + // `isize::MAX` (that's well below `usize::MAX`) + if self.extra == 0 { + ((len + 2) / 3, Some(len)) + } else { + // We're in the middle of a surrogate pair, so add the remaining + // surrogate to the bounds. + ((len + 2) / 3 + 1, Some(len + 1)) + } + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for EncodeUtf16<'_> {} + +/// The return type of [`str::escape_debug`]. +#[stable(feature = "str_escape", since = "1.34.0")] +#[derive(Clone, Debug)] +pub struct EscapeDebug<'a> { + pub(super) inner: Chain< + Flatten>, + FlatMap, char_mod::EscapeDebug, CharEscapeDebugContinue>, + >, +} + +/// The return type of [`str::escape_default`]. +#[stable(feature = "str_escape", since = "1.34.0")] +#[derive(Clone, Debug)] +pub struct EscapeDefault<'a> { + pub(super) inner: FlatMap, char_mod::EscapeDefault, CharEscapeDefault>, +} + +/// The return type of [`str::escape_unicode`]. +#[stable(feature = "str_escape", since = "1.34.0")] +#[derive(Clone, Debug)] +pub struct EscapeUnicode<'a> { + pub(super) inner: FlatMap, char_mod::EscapeUnicode, CharEscapeUnicode>, +} + +macro_rules! escape_types_impls { + ($( $Name: ident ),+) => {$( + #[stable(feature = "str_escape", since = "1.34.0")] + impl<'a> fmt::Display for $Name<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.clone().try_for_each(|c| f.write_char(c)) + } + } + + #[stable(feature = "str_escape", since = "1.34.0")] + impl<'a> Iterator for $Name<'a> { + type Item = char; + + #[inline] + fn next(&mut self) -> Option { self.inner.next() } + + #[inline] + fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try + { + self.inner.try_fold(init, fold) + } + + #[inline] + fn fold(self, init: Acc, fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.inner.fold(init, fold) + } + } + + #[stable(feature = "str_escape", since = "1.34.0")] + impl<'a> FusedIterator for $Name<'a> {} + )+} +} + +escape_types_impls!(EscapeDebug, EscapeDefault, EscapeUnicode); diff --git a/CoqOfRust/core/str/lossy.rs b/CoqOfRust/core/str/lossy.rs new file mode 100644 index 000000000..e7677c831 --- /dev/null +++ b/CoqOfRust/core/str/lossy.rs @@ -0,0 +1,298 @@ +use super::from_utf8_unchecked; +use super::validations::utf8_char_width; +use crate::fmt; +use crate::fmt::{Formatter, Write}; +use crate::iter::FusedIterator; + +impl [u8] { + /// Creates an iterator over the contiguous valid UTF-8 ranges of this + /// slice, and the non-UTF-8 fragments in between. + /// + /// See the [`Utf8Chunk`] type for documenation of the items yielded by this iterator. + /// + /// # Examples + /// + /// This function formats arbitrary but mostly-UTF-8 bytes into Rust source + /// code in the form of a C-string literal (`c"..."`). + /// + /// ``` + /// use std::fmt::Write as _; + /// + /// pub fn cstr_literal(bytes: &[u8]) -> String { + /// let mut repr = String::new(); + /// repr.push_str("c\""); + /// for chunk in bytes.utf8_chunks() { + /// for ch in chunk.valid().chars() { + /// // Escapes \0, \t, \r, \n, \\, \', \", and uses \u{...} for non-printable characters. + /// write!(repr, "{}", ch.escape_debug()).unwrap(); + /// } + /// for byte in chunk.invalid() { + /// write!(repr, "\\x{:02X}", byte).unwrap(); + /// } + /// } + /// repr.push('"'); + /// repr + /// } + /// + /// fn main() { + /// let lit = cstr_literal(b"\xferris the \xf0\x9f\xa6\x80\x07"); + /// let expected = stringify!(c"\xFErris the 🦀\u{7}"); + /// assert_eq!(lit, expected); + /// } + /// ``` + #[stable(feature = "utf8_chunks", since = "1.79.0")] + pub fn utf8_chunks(&self) -> Utf8Chunks<'_> { + Utf8Chunks { source: self } + } +} + +/// An item returned by the [`Utf8Chunks`] iterator. +/// +/// A `Utf8Chunk` stores a sequence of [`u8`] up to the first broken character +/// when decoding a UTF-8 string. +/// +/// # Examples +/// +/// ``` +/// // An invalid UTF-8 string +/// let bytes = b"foo\xF1\x80bar"; +/// +/// // Decode the first `Utf8Chunk` +/// let chunk = bytes.utf8_chunks().next().unwrap(); +/// +/// // The first three characters are valid UTF-8 +/// assert_eq!("foo", chunk.valid()); +/// +/// // The fourth character is broken +/// assert_eq!(b"\xF1\x80", chunk.invalid()); +/// ``` +#[stable(feature = "utf8_chunks", since = "1.79.0")] +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Utf8Chunk<'a> { + valid: &'a str, + invalid: &'a [u8], +} + +impl<'a> Utf8Chunk<'a> { + /// Returns the next validated UTF-8 substring. + /// + /// This substring can be empty at the start of the string or between + /// broken UTF-8 characters. + #[must_use] + #[stable(feature = "utf8_chunks", since = "1.79.0")] + pub fn valid(&self) -> &'a str { + self.valid + } + + /// Returns the invalid sequence that caused a failure. + /// + /// The returned slice will have a maximum length of 3 and starts after the + /// substring given by [`valid`]. Decoding will resume after this sequence. + /// + /// If empty, this is the last chunk in the string. If non-empty, an + /// unexpected byte was encountered or the end of the input was reached + /// unexpectedly. + /// + /// Lossy decoding would replace this sequence with [`U+FFFD REPLACEMENT + /// CHARACTER`]. + /// + /// [`valid`]: Self::valid + /// [`U+FFFD REPLACEMENT CHARACTER`]: crate::char::REPLACEMENT_CHARACTER + #[must_use] + #[stable(feature = "utf8_chunks", since = "1.79.0")] + pub fn invalid(&self) -> &'a [u8] { + self.invalid + } +} + +#[must_use] +#[unstable(feature = "str_internals", issue = "none")] +pub struct Debug<'a>(&'a [u8]); + +#[unstable(feature = "str_internals", issue = "none")] +impl fmt::Debug for Debug<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_char('"')?; + + for chunk in self.0.utf8_chunks() { + // Valid part. + // Here we partially parse UTF-8 again which is suboptimal. + { + let valid = chunk.valid(); + let mut from = 0; + for (i, c) in valid.char_indices() { + let esc = c.escape_debug(); + // If char needs escaping, flush backlog so far and write, else skip + if esc.len() != 1 { + f.write_str(&valid[from..i])?; + for c in esc { + f.write_char(c)?; + } + from = i + c.len_utf8(); + } + } + f.write_str(&valid[from..])?; + } + + // Broken parts of string as hex escape. + for &b in chunk.invalid() { + write!(f, "\\x{:02X}", b)?; + } + } + + f.write_char('"') + } +} + +/// An iterator used to decode a slice of mostly UTF-8 bytes to string slices +/// ([`&str`]) and byte slices ([`&[u8]`][byteslice]). +/// +/// If you want a simple conversion from UTF-8 byte slices to string slices, +/// [`from_utf8`] is easier to use. +/// +/// See the [`Utf8Chunk`] type for documenation of the items yielded by this iterator. +/// +/// [byteslice]: slice +/// [`from_utf8`]: super::from_utf8 +/// +/// # Examples +/// +/// This can be used to create functionality similar to +/// [`String::from_utf8_lossy`] without allocating heap memory: +/// +/// ``` +/// fn from_utf8_lossy(input: &[u8], mut push: F) where F: FnMut(&str) { +/// for chunk in input.utf8_chunks() { +/// push(chunk.valid()); +/// +/// if !chunk.invalid().is_empty() { +/// push("\u{FFFD}"); +/// } +/// } +/// } +/// ``` +/// +/// [`String::from_utf8_lossy`]: ../../std/string/struct.String.html#method.from_utf8_lossy +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "utf8_chunks", since = "1.79.0")] +#[derive(Clone)] +pub struct Utf8Chunks<'a> { + source: &'a [u8], +} + +impl<'a> Utf8Chunks<'a> { + #[doc(hidden)] + #[unstable(feature = "str_internals", issue = "none")] + pub fn debug(&self) -> Debug<'_> { + Debug(self.source) + } +} + +#[stable(feature = "utf8_chunks", since = "1.79.0")] +impl<'a> Iterator for Utf8Chunks<'a> { + type Item = Utf8Chunk<'a>; + + fn next(&mut self) -> Option> { + if self.source.is_empty() { + return None; + } + + const TAG_CONT_U8: u8 = 128; + fn safe_get(xs: &[u8], i: usize) -> u8 { + *xs.get(i).unwrap_or(&0) + } + + let mut i = 0; + let mut valid_up_to = 0; + while i < self.source.len() { + // SAFETY: `i < self.source.len()` per previous line. + // For some reason the following are both significantly slower: + // while let Some(&byte) = self.source.get(i) { + // while let Some(byte) = self.source.get(i).copied() { + let byte = unsafe { *self.source.get_unchecked(i) }; + i += 1; + + if byte < 128 { + // This could be a `1 => ...` case in the match below, but for + // the common case of all-ASCII inputs, we bypass loading the + // sizeable UTF8_CHAR_WIDTH table into cache. + } else { + let w = utf8_char_width(byte); + + match w { + 2 => { + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + break; + } + i += 1; + } + 3 => { + match (byte, safe_get(self.source, i)) { + (0xE0, 0xA0..=0xBF) => (), + (0xE1..=0xEC, 0x80..=0xBF) => (), + (0xED, 0x80..=0x9F) => (), + (0xEE..=0xEF, 0x80..=0xBF) => (), + _ => break, + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + break; + } + i += 1; + } + 4 => { + match (byte, safe_get(self.source, i)) { + (0xF0, 0x90..=0xBF) => (), + (0xF1..=0xF3, 0x80..=0xBF) => (), + (0xF4, 0x80..=0x8F) => (), + _ => break, + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + break; + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + break; + } + i += 1; + } + _ => break, + } + } + + valid_up_to = i; + } + + // SAFETY: `i <= self.source.len()` because it is only ever incremented + // via `i += 1` and in between every single one of those increments, `i` + // is compared against `self.source.len()`. That happens either + // literally by `i < self.source.len()` in the while-loop's condition, + // or indirectly by `safe_get(self.source, i) & 192 != TAG_CONT_U8`. The + // loop is terminated as soon as the latest `i += 1` has made `i` no + // longer less than `self.source.len()`, which means it'll be at most + // equal to `self.source.len()`. + let (inspected, remaining) = unsafe { self.source.split_at_unchecked(i) }; + self.source = remaining; + + // SAFETY: `valid_up_to <= i` because it is only ever assigned via + // `valid_up_to = i` and `i` only increases. + let (valid, invalid) = unsafe { inspected.split_at_unchecked(valid_up_to) }; + + Some(Utf8Chunk { + // SAFETY: All bytes up to `valid_up_to` are valid UTF-8. + valid: unsafe { from_utf8_unchecked(valid) }, + invalid, + }) + } +} + +#[stable(feature = "utf8_chunks", since = "1.79.0")] +impl FusedIterator for Utf8Chunks<'_> {} + +#[stable(feature = "utf8_chunks", since = "1.79.0")] +impl fmt::Debug for Utf8Chunks<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_struct("Utf8Chunks").field("source", &self.debug()).finish() + } +} diff --git a/CoqOfRust/core/str/mod.rs b/CoqOfRust/core/str/mod.rs new file mode 100644 index 000000000..8a473b398 --- /dev/null +++ b/CoqOfRust/core/str/mod.rs @@ -0,0 +1,2871 @@ +//! String manipulation. +//! +//! For more details, see the [`std::str`] module. +//! +//! [`std::str`]: ../../std/str/index.html + +#![stable(feature = "rust1", since = "1.0.0")] + +mod converts; +mod count; +mod error; +mod iter; +mod traits; +mod validations; + +use self::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher}; +use crate::char::{self, EscapeDebugExtArgs}; +use crate::ops::Range; +use crate::slice::{self, SliceIndex}; +use crate::{ascii, mem}; + +pub mod pattern; + +mod lossy; +#[unstable(feature = "str_from_raw_parts", issue = "119206")] +pub use converts::{from_raw_parts, from_raw_parts_mut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use converts::{from_utf8, from_utf8_unchecked}; +#[stable(feature = "str_mut_extras", since = "1.20.0")] +pub use converts::{from_utf8_mut, from_utf8_unchecked_mut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use error::{ParseBoolError, Utf8Error}; +#[stable(feature = "encode_utf16", since = "1.8.0")] +pub use iter::EncodeUtf16; +#[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] +pub use iter::LinesAny; +#[stable(feature = "split_ascii_whitespace", since = "1.34.0")] +pub use iter::SplitAsciiWhitespace; +#[stable(feature = "split_inclusive", since = "1.51.0")] +pub use iter::SplitInclusive; +#[stable(feature = "rust1", since = "1.0.0")] +pub use iter::{Bytes, CharIndices, Chars, Lines, SplitWhitespace}; +#[stable(feature = "str_escape", since = "1.34.0")] +pub use iter::{EscapeDebug, EscapeDefault, EscapeUnicode}; +#[stable(feature = "str_match_indices", since = "1.5.0")] +pub use iter::{MatchIndices, RMatchIndices}; +use iter::{MatchIndicesInternal, MatchesInternal, SplitInternal, SplitNInternal}; +#[stable(feature = "str_matches", since = "1.2.0")] +pub use iter::{Matches, RMatches}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use iter::{RSplit, RSplitTerminator, Split, SplitTerminator}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use iter::{RSplitN, SplitN}; +#[stable(feature = "utf8_chunks", since = "1.79.0")] +pub use lossy::{Utf8Chunk, Utf8Chunks}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use traits::FromStr; +#[unstable(feature = "str_internals", issue = "none")] +pub use validations::{next_code_point, utf8_char_width}; + +#[inline(never)] +#[cold] +#[track_caller] +#[rustc_allow_const_fn_unstable(const_eval_select)] +#[cfg(not(feature = "panic_immediate_abort"))] +const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! { + crate::intrinsics::const_eval_select((s, begin, end), slice_error_fail_ct, slice_error_fail_rt) +} + +#[cfg(feature = "panic_immediate_abort")] +const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! { + slice_error_fail_ct(s, begin, end) +} + +#[track_caller] +const fn slice_error_fail_ct(_: &str, _: usize, _: usize) -> ! { + panic!("failed to slice string"); +} + +#[track_caller] +fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! { + const MAX_DISPLAY_LENGTH: usize = 256; + let trunc_len = s.floor_char_boundary(MAX_DISPLAY_LENGTH); + let s_trunc = &s[..trunc_len]; + let ellipsis = if trunc_len < s.len() { "[...]" } else { "" }; + + // 1. out of bounds + if begin > s.len() || end > s.len() { + let oob_index = if begin > s.len() { begin } else { end }; + panic!("byte index {oob_index} is out of bounds of `{s_trunc}`{ellipsis}"); + } + + // 2. begin <= end + assert!( + begin <= end, + "begin <= end ({} <= {}) when slicing `{}`{}", + begin, + end, + s_trunc, + ellipsis + ); + + // 3. character boundary + let index = if !s.is_char_boundary(begin) { begin } else { end }; + // find the character + let char_start = s.floor_char_boundary(index); + // `char_start` must be less than len and a char boundary + let ch = s[char_start..].chars().next().unwrap(); + let char_range = char_start..char_start + ch.len_utf8(); + panic!( + "byte index {} is not a char boundary; it is inside {:?} (bytes {:?}) of `{}`{}", + index, ch, char_range, s_trunc, ellipsis + ); +} + +#[cfg(not(test))] +impl str { + /// Returns the length of `self`. + /// + /// This length is in bytes, not [`char`]s or graphemes. In other words, + /// it might not be what a human considers the length of the string. + /// + /// [`char`]: prim@char + /// + /// # Examples + /// + /// ``` + /// let len = "foo".len(); + /// assert_eq!(3, len); + /// + /// assert_eq!("ƒoo".len(), 4); // fancy f! + /// assert_eq!("ƒoo".chars().count(), 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_str_len", since = "1.39.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "str_len")] + #[must_use] + #[inline] + pub const fn len(&self) -> usize { + self.as_bytes().len() + } + + /// Returns `true` if `self` has a length of zero bytes. + /// + /// # Examples + /// + /// ``` + /// let s = ""; + /// assert!(s.is_empty()); + /// + /// let s = "not empty"; + /// assert!(!s.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_str_is_empty", since = "1.39.0")] + #[must_use] + #[inline] + pub const fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Checks that `index`-th byte is the first byte in a UTF-8 code point + /// sequence or the end of the string. + /// + /// The start and end of the string (when `index == self.len()`) are + /// considered to be boundaries. + /// + /// Returns `false` if `index` is greater than `self.len()`. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// assert!(s.is_char_boundary(0)); + /// // start of `老` + /// assert!(s.is_char_boundary(6)); + /// assert!(s.is_char_boundary(s.len())); + /// + /// // second byte of `ö` + /// assert!(!s.is_char_boundary(2)); + /// + /// // third byte of `老` + /// assert!(!s.is_char_boundary(8)); + /// ``` + #[must_use] + #[stable(feature = "is_char_boundary", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_is_char_boundary", issue = "131516")] + #[inline] + pub const fn is_char_boundary(&self, index: usize) -> bool { + // 0 is always ok. + // Test for 0 explicitly so that it can optimize out the check + // easily and skip reading string data for that case. + // Note that optimizing `self.get(..index)` relies on this. + if index == 0 { + return true; + } + + if index >= self.len() { + // For `true` we have two options: + // + // - index == self.len() + // Empty strings are valid, so return true + // - index > self.len() + // In this case return false + // + // The check is placed exactly here, because it improves generated + // code on higher opt-levels. See PR #84751 for more details. + index == self.len() + } else { + self.as_bytes()[index].is_utf8_char_boundary() + } + } + + /// Finds the closest `x` not exceeding `index` where [`is_char_boundary(x)`] is `true`. + /// + /// This method can help you truncate a string so that it's still valid UTF-8, but doesn't + /// exceed a given number of bytes. Note that this is done purely at the character level + /// and can still visually split graphemes, even though the underlying characters aren't + /// split. For example, the emoji 🧑‍🔬 (scientist) could be split so that the string only + /// includes 🧑 (person) instead. + /// + /// [`is_char_boundary(x)`]: Self::is_char_boundary + /// + /// # Examples + /// + /// ``` + /// #![feature(round_char_boundary)] + /// let s = "❤️🧡💛💚💙💜"; + /// assert_eq!(s.len(), 26); + /// assert!(!s.is_char_boundary(13)); + /// + /// let closest = s.floor_char_boundary(13); + /// assert_eq!(closest, 10); + /// assert_eq!(&s[..closest], "❤️🧡"); + /// ``` + #[unstable(feature = "round_char_boundary", issue = "93743")] + #[inline] + pub fn floor_char_boundary(&self, index: usize) -> usize { + if index >= self.len() { + self.len() + } else { + let lower_bound = index.saturating_sub(3); + let new_index = self.as_bytes()[lower_bound..=index] + .iter() + .rposition(|b| b.is_utf8_char_boundary()); + + // SAFETY: we know that the character boundary will be within four bytes + unsafe { lower_bound + new_index.unwrap_unchecked() } + } + } + + /// Finds the closest `x` not below `index` where [`is_char_boundary(x)`] is `true`. + /// + /// If `index` is greater than the length of the string, this returns the length of the string. + /// + /// This method is the natural complement to [`floor_char_boundary`]. See that method + /// for more details. + /// + /// [`floor_char_boundary`]: str::floor_char_boundary + /// [`is_char_boundary(x)`]: Self::is_char_boundary + /// + /// # Examples + /// + /// ``` + /// #![feature(round_char_boundary)] + /// let s = "❤️🧡💛💚💙💜"; + /// assert_eq!(s.len(), 26); + /// assert!(!s.is_char_boundary(13)); + /// + /// let closest = s.ceil_char_boundary(13); + /// assert_eq!(closest, 14); + /// assert_eq!(&s[..closest], "❤️🧡💛"); + /// ``` + #[unstable(feature = "round_char_boundary", issue = "93743")] + #[inline] + pub fn ceil_char_boundary(&self, index: usize) -> usize { + if index > self.len() { + self.len() + } else { + let upper_bound = Ord::min(index + 4, self.len()); + self.as_bytes()[index..upper_bound] + .iter() + .position(|b| b.is_utf8_char_boundary()) + .map_or(upper_bound, |pos| pos + index) + } + } + + /// Converts a string slice to a byte slice. To convert the byte slice back + /// into a string slice, use the [`from_utf8`] function. + /// + /// # Examples + /// + /// ``` + /// let bytes = "bors".as_bytes(); + /// assert_eq!(b"bors", bytes); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "str_as_bytes", since = "1.39.0")] + #[must_use] + #[inline(always)] + #[allow(unused_attributes)] + pub const fn as_bytes(&self) -> &[u8] { + // SAFETY: const sound because we transmute two types with the same layout + unsafe { mem::transmute(self) } + } + + /// Converts a mutable string slice to a mutable byte slice. + /// + /// # Safety + /// + /// The caller must ensure that the content of the slice is valid UTF-8 + /// before the borrow ends and the underlying `str` is used. + /// + /// Use of a `str` whose contents are not valid UTF-8 is undefined behavior. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::from("Hello"); + /// let bytes = unsafe { s.as_bytes_mut() }; + /// + /// assert_eq!(b"Hello", bytes); + /// ``` + /// + /// Mutability: + /// + /// ``` + /// let mut s = String::from("🗻∈🌏"); + /// + /// unsafe { + /// let bytes = s.as_bytes_mut(); + /// + /// bytes[0] = 0xF0; + /// bytes[1] = 0x9F; + /// bytes[2] = 0x8D; + /// bytes[3] = 0x94; + /// } + /// + /// assert_eq!("🍔∈🌏", s); + /// ``` + #[stable(feature = "str_mut_extras", since = "1.20.0")] + #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] + #[must_use] + #[inline(always)] + pub const unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { + // SAFETY: the cast from `&str` to `&[u8]` is safe since `str` + // has the same layout as `&[u8]` (only std can make this guarantee). + // The pointer dereference is safe since it comes from a mutable reference which + // is guaranteed to be valid for writes. + unsafe { &mut *(self as *mut str as *mut [u8]) } + } + + /// Converts a string slice to a raw pointer. + /// + /// As string slices are a slice of bytes, the raw pointer points to a + /// [`u8`]. This pointer will be pointing to the first byte of the string + /// slice. + /// + /// The caller must ensure that the returned pointer is never written to. + /// If you need to mutate the contents of the string slice, use [`as_mut_ptr`]. + /// + /// [`as_mut_ptr`]: str::as_mut_ptr + /// + /// # Examples + /// + /// ``` + /// let s = "Hello"; + /// let ptr = s.as_ptr(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0")] + #[rustc_never_returns_null_ptr] + #[rustc_as_ptr] + #[must_use] + #[inline(always)] + pub const fn as_ptr(&self) -> *const u8 { + self as *const str as *const u8 + } + + /// Converts a mutable string slice to a raw pointer. + /// + /// As string slices are a slice of bytes, the raw pointer points to a + /// [`u8`]. This pointer will be pointing to the first byte of the string + /// slice. + /// + /// It is your responsibility to make sure that the string slice only gets + /// modified in a way that it remains valid UTF-8. + #[stable(feature = "str_as_mut_ptr", since = "1.36.0")] + #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] + #[rustc_never_returns_null_ptr] + #[rustc_as_ptr] + #[must_use] + #[inline(always)] + pub const fn as_mut_ptr(&mut self) -> *mut u8 { + self as *mut str as *mut u8 + } + + /// Returns a subslice of `str`. + /// + /// This is the non-panicking alternative to indexing the `str`. Returns + /// [`None`] whenever equivalent indexing operation would panic. + /// + /// # Examples + /// + /// ``` + /// let v = String::from("🗻∈🌏"); + /// + /// assert_eq!(Some("🗻"), v.get(0..4)); + /// + /// // indices not on UTF-8 sequence boundaries + /// assert!(v.get(1..).is_none()); + /// assert!(v.get(..8).is_none()); + /// + /// // out of bounds + /// assert!(v.get(..42).is_none()); + /// ``` + #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[inline] + pub fn get>(&self, i: I) -> Option<&I::Output> { + i.get(self) + } + + /// Returns a mutable subslice of `str`. + /// + /// This is the non-panicking alternative to indexing the `str`. Returns + /// [`None`] whenever equivalent indexing operation would panic. + /// + /// # Examples + /// + /// ``` + /// let mut v = String::from("hello"); + /// // correct length + /// assert!(v.get_mut(0..5).is_some()); + /// // out of bounds + /// assert!(v.get_mut(..42).is_none()); + /// assert_eq!(Some("he"), v.get_mut(0..2).map(|v| &*v)); + /// + /// assert_eq!("hello", v); + /// { + /// let s = v.get_mut(0..2); + /// let s = s.map(|s| { + /// s.make_ascii_uppercase(); + /// &*s + /// }); + /// assert_eq!(Some("HE"), s); + /// } + /// assert_eq!("HEllo", v); + /// ``` + #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[inline] + pub fn get_mut>(&mut self, i: I) -> Option<&mut I::Output> { + i.get_mut(self) + } + + /// Returns an unchecked subslice of `str`. + /// + /// This is the unchecked alternative to indexing the `str`. + /// + /// # Safety + /// + /// Callers of this function are responsible that these preconditions are + /// satisfied: + /// + /// * The starting index must not exceed the ending index; + /// * Indexes must be within bounds of the original slice; + /// * Indexes must lie on UTF-8 sequence boundaries. + /// + /// Failing that, the returned string slice may reference invalid memory or + /// violate the invariants communicated by the `str` type. + /// + /// # Examples + /// + /// ``` + /// let v = "🗻∈🌏"; + /// unsafe { + /// assert_eq!("🗻", v.get_unchecked(0..4)); + /// assert_eq!("∈", v.get_unchecked(4..7)); + /// assert_eq!("🌏", v.get_unchecked(7..11)); + /// } + /// ``` + #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[inline] + pub unsafe fn get_unchecked>(&self, i: I) -> &I::Output { + // SAFETY: the caller must uphold the safety contract for `get_unchecked`; + // the slice is dereferenceable because `self` is a safe reference. + // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. + unsafe { &*i.get_unchecked(self) } + } + + /// Returns a mutable, unchecked subslice of `str`. + /// + /// This is the unchecked alternative to indexing the `str`. + /// + /// # Safety + /// + /// Callers of this function are responsible that these preconditions are + /// satisfied: + /// + /// * The starting index must not exceed the ending index; + /// * Indexes must be within bounds of the original slice; + /// * Indexes must lie on UTF-8 sequence boundaries. + /// + /// Failing that, the returned string slice may reference invalid memory or + /// violate the invariants communicated by the `str` type. + /// + /// # Examples + /// + /// ``` + /// let mut v = String::from("🗻∈🌏"); + /// unsafe { + /// assert_eq!("🗻", v.get_unchecked_mut(0..4)); + /// assert_eq!("∈", v.get_unchecked_mut(4..7)); + /// assert_eq!("🌏", v.get_unchecked_mut(7..11)); + /// } + /// ``` + #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[inline] + pub unsafe fn get_unchecked_mut>(&mut self, i: I) -> &mut I::Output { + // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`; + // the slice is dereferenceable because `self` is a safe reference. + // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. + unsafe { &mut *i.get_unchecked_mut(self) } + } + + /// Creates a string slice from another string slice, bypassing safety + /// checks. + /// + /// This is generally not recommended, use with caution! For a safe + /// alternative see [`str`] and [`Index`]. + /// + /// [`Index`]: crate::ops::Index + /// + /// This new slice goes from `begin` to `end`, including `begin` but + /// excluding `end`. + /// + /// To get a mutable string slice instead, see the + /// [`slice_mut_unchecked`] method. + /// + /// [`slice_mut_unchecked`]: str::slice_mut_unchecked + /// + /// # Safety + /// + /// Callers of this function are responsible that three preconditions are + /// satisfied: + /// + /// * `begin` must not exceed `end`. + /// * `begin` and `end` must be byte positions within the string slice. + /// * `begin` and `end` must lie on UTF-8 sequence boundaries. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// unsafe { + /// assert_eq!("Löwe 老虎 Léopard", s.slice_unchecked(0, 21)); + /// } + /// + /// let s = "Hello, world!"; + /// + /// unsafe { + /// assert_eq!("world", s.slice_unchecked(7, 12)); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.29.0", note = "use `get_unchecked(begin..end)` instead")] + #[must_use] + #[inline] + pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { + // SAFETY: the caller must uphold the safety contract for `get_unchecked`; + // the slice is dereferenceable because `self` is a safe reference. + // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. + unsafe { &*(begin..end).get_unchecked(self) } + } + + /// Creates a string slice from another string slice, bypassing safety + /// checks. + /// + /// This is generally not recommended, use with caution! For a safe + /// alternative see [`str`] and [`IndexMut`]. + /// + /// [`IndexMut`]: crate::ops::IndexMut + /// + /// This new slice goes from `begin` to `end`, including `begin` but + /// excluding `end`. + /// + /// To get an immutable string slice instead, see the + /// [`slice_unchecked`] method. + /// + /// [`slice_unchecked`]: str::slice_unchecked + /// + /// # Safety + /// + /// Callers of this function are responsible that three preconditions are + /// satisfied: + /// + /// * `begin` must not exceed `end`. + /// * `begin` and `end` must be byte positions within the string slice. + /// * `begin` and `end` must lie on UTF-8 sequence boundaries. + #[stable(feature = "str_slice_mut", since = "1.5.0")] + #[deprecated(since = "1.29.0", note = "use `get_unchecked_mut(begin..end)` instead")] + #[inline] + pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str { + // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`; + // the slice is dereferenceable because `self` is a safe reference. + // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. + unsafe { &mut *(begin..end).get_unchecked_mut(self) } + } + + /// Divides one string slice into two at an index. + /// + /// The argument, `mid`, should be a byte offset from the start of the + /// string. It must also be on the boundary of a UTF-8 code point. + /// + /// The two slices returned go from the start of the string slice to `mid`, + /// and from `mid` to the end of the string slice. + /// + /// To get mutable string slices instead, see the [`split_at_mut`] + /// method. + /// + /// [`split_at_mut`]: str::split_at_mut + /// + /// # Panics + /// + /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is past + /// the end of the last code point of the string slice. For a non-panicking + /// alternative see [`split_at_checked`](str::split_at_checked). + /// + /// # Examples + /// + /// ``` + /// let s = "Per Martin-Löf"; + /// + /// let (first, last) = s.split_at(3); + /// + /// assert_eq!("Per", first); + /// assert_eq!(" Martin-Löf", last); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "str_split_at", since = "1.4.0")] + #[rustc_const_unstable(feature = "const_str_split_at", issue = "131518")] + pub const fn split_at(&self, mid: usize) -> (&str, &str) { + match self.split_at_checked(mid) { + None => slice_error_fail(self, 0, mid), + Some(pair) => pair, + } + } + + /// Divides one mutable string slice into two at an index. + /// + /// The argument, `mid`, should be a byte offset from the start of the + /// string. It must also be on the boundary of a UTF-8 code point. + /// + /// The two slices returned go from the start of the string slice to `mid`, + /// and from `mid` to the end of the string slice. + /// + /// To get immutable string slices instead, see the [`split_at`] method. + /// + /// [`split_at`]: str::split_at + /// + /// # Panics + /// + /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is past + /// the end of the last code point of the string slice. For a non-panicking + /// alternative see [`split_at_mut_checked`](str::split_at_mut_checked). + /// + /// # Examples + /// + /// ``` + /// let mut s = "Per Martin-Löf".to_string(); + /// { + /// let (first, last) = s.split_at_mut(3); + /// first.make_ascii_uppercase(); + /// assert_eq!("PER", first); + /// assert_eq!(" Martin-Löf", last); + /// } + /// assert_eq!("PER Martin-Löf", s); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "str_split_at", since = "1.4.0")] + #[rustc_const_unstable(feature = "const_str_split_at", issue = "131518")] + pub const fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) { + // is_char_boundary checks that the index is in [0, .len()] + if self.is_char_boundary(mid) { + // SAFETY: just checked that `mid` is on a char boundary. + unsafe { self.split_at_mut_unchecked(mid) } + } else { + slice_error_fail(self, 0, mid) + } + } + + /// Divides one string slice into two at an index. + /// + /// The argument, `mid`, should be a valid byte offset from the start of the + /// string. It must also be on the boundary of a UTF-8 code point. The + /// method returns `None` if that’s not the case. + /// + /// The two slices returned go from the start of the string slice to `mid`, + /// and from `mid` to the end of the string slice. + /// + /// To get mutable string slices instead, see the [`split_at_mut_checked`] + /// method. + /// + /// [`split_at_mut_checked`]: str::split_at_mut_checked + /// + /// # Examples + /// + /// ``` + /// let s = "Per Martin-Löf"; + /// + /// let (first, last) = s.split_at_checked(3).unwrap(); + /// assert_eq!("Per", first); + /// assert_eq!(" Martin-Löf", last); + /// + /// assert_eq!(None, s.split_at_checked(13)); // Inside “ö” + /// assert_eq!(None, s.split_at_checked(16)); // Beyond the string length + /// ``` + #[inline] + #[must_use] + #[stable(feature = "split_at_checked", since = "1.80.0")] + #[rustc_const_unstable(feature = "const_str_split_at", issue = "131518")] + pub const fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)> { + // is_char_boundary checks that the index is in [0, .len()] + if self.is_char_boundary(mid) { + // SAFETY: just checked that `mid` is on a char boundary. + Some(unsafe { self.split_at_unchecked(mid) }) + } else { + None + } + } + + /// Divides one mutable string slice into two at an index. + /// + /// The argument, `mid`, should be a valid byte offset from the start of the + /// string. It must also be on the boundary of a UTF-8 code point. The + /// method returns `None` if that’s not the case. + /// + /// The two slices returned go from the start of the string slice to `mid`, + /// and from `mid` to the end of the string slice. + /// + /// To get immutable string slices instead, see the [`split_at_checked`] method. + /// + /// [`split_at_checked`]: str::split_at_checked + /// + /// # Examples + /// + /// ``` + /// let mut s = "Per Martin-Löf".to_string(); + /// if let Some((first, last)) = s.split_at_mut_checked(3) { + /// first.make_ascii_uppercase(); + /// assert_eq!("PER", first); + /// assert_eq!(" Martin-Löf", last); + /// } + /// assert_eq!("PER Martin-Löf", s); + /// + /// assert_eq!(None, s.split_at_mut_checked(13)); // Inside “ö” + /// assert_eq!(None, s.split_at_mut_checked(16)); // Beyond the string length + /// ``` + #[inline] + #[must_use] + #[stable(feature = "split_at_checked", since = "1.80.0")] + #[rustc_const_unstable(feature = "const_str_split_at", issue = "131518")] + pub const fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut str, &mut str)> { + // is_char_boundary checks that the index is in [0, .len()] + if self.is_char_boundary(mid) { + // SAFETY: just checked that `mid` is on a char boundary. + Some(unsafe { self.split_at_mut_unchecked(mid) }) + } else { + None + } + } + + /// Divides one string slice into two at an index. + /// + /// # Safety + /// + /// The caller must ensure that `mid` is a valid byte offset from the start + /// of the string and falls on the boundary of a UTF-8 code point. + const unsafe fn split_at_unchecked(&self, mid: usize) -> (&str, &str) { + let len = self.len(); + let ptr = self.as_ptr(); + // SAFETY: caller guarantees `mid` is on a char boundary. + unsafe { + ( + from_utf8_unchecked(slice::from_raw_parts(ptr, mid)), + from_utf8_unchecked(slice::from_raw_parts(ptr.add(mid), len - mid)), + ) + } + } + + /// Divides one string slice into two at an index. + /// + /// # Safety + /// + /// The caller must ensure that `mid` is a valid byte offset from the start + /// of the string and falls on the boundary of a UTF-8 code point. + const unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut str, &mut str) { + let len = self.len(); + let ptr = self.as_mut_ptr(); + // SAFETY: caller guarantees `mid` is on a char boundary. + unsafe { + ( + from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)), + from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr.add(mid), len - mid)), + ) + } + } + + /// Returns an iterator over the [`char`]s of a string slice. + /// + /// As a string slice consists of valid UTF-8, we can iterate through a + /// string slice by [`char`]. This method returns such an iterator. + /// + /// It's important to remember that [`char`] represents a Unicode Scalar + /// Value, and might not match your idea of what a 'character' is. Iteration + /// over grapheme clusters may be what you actually want. This functionality + /// is not provided by Rust's standard library, check crates.io instead. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let word = "goodbye"; + /// + /// let count = word.chars().count(); + /// assert_eq!(7, count); + /// + /// let mut chars = word.chars(); + /// + /// assert_eq!(Some('g'), chars.next()); + /// assert_eq!(Some('o'), chars.next()); + /// assert_eq!(Some('o'), chars.next()); + /// assert_eq!(Some('d'), chars.next()); + /// assert_eq!(Some('b'), chars.next()); + /// assert_eq!(Some('y'), chars.next()); + /// assert_eq!(Some('e'), chars.next()); + /// + /// assert_eq!(None, chars.next()); + /// ``` + /// + /// Remember, [`char`]s might not match your intuition about characters: + /// + /// [`char`]: prim@char + /// + /// ``` + /// let y = "y̆"; + /// + /// let mut chars = y.chars(); + /// + /// assert_eq!(Some('y'), chars.next()); // not 'y̆' + /// assert_eq!(Some('\u{0306}'), chars.next()); + /// + /// assert_eq!(None, chars.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg_attr(not(test), rustc_diagnostic_item = "str_chars")] + pub fn chars(&self) -> Chars<'_> { + Chars { iter: self.as_bytes().iter() } + } + + /// Returns an iterator over the [`char`]s of a string slice, and their + /// positions. + /// + /// As a string slice consists of valid UTF-8, we can iterate through a + /// string slice by [`char`]. This method returns an iterator of both + /// these [`char`]s, as well as their byte positions. + /// + /// The iterator yields tuples. The position is first, the [`char`] is + /// second. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let word = "goodbye"; + /// + /// let count = word.char_indices().count(); + /// assert_eq!(7, count); + /// + /// let mut char_indices = word.char_indices(); + /// + /// assert_eq!(Some((0, 'g')), char_indices.next()); + /// assert_eq!(Some((1, 'o')), char_indices.next()); + /// assert_eq!(Some((2, 'o')), char_indices.next()); + /// assert_eq!(Some((3, 'd')), char_indices.next()); + /// assert_eq!(Some((4, 'b')), char_indices.next()); + /// assert_eq!(Some((5, 'y')), char_indices.next()); + /// assert_eq!(Some((6, 'e')), char_indices.next()); + /// + /// assert_eq!(None, char_indices.next()); + /// ``` + /// + /// Remember, [`char`]s might not match your intuition about characters: + /// + /// [`char`]: prim@char + /// + /// ``` + /// let yes = "y̆es"; + /// + /// let mut char_indices = yes.char_indices(); + /// + /// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆') + /// assert_eq!(Some((1, '\u{0306}')), char_indices.next()); + /// + /// // note the 3 here - the previous character took up two bytes + /// assert_eq!(Some((3, 'e')), char_indices.next()); + /// assert_eq!(Some((4, 's')), char_indices.next()); + /// + /// assert_eq!(None, char_indices.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn char_indices(&self) -> CharIndices<'_> { + CharIndices { front_offset: 0, iter: self.chars() } + } + + /// Returns an iterator over the bytes of a string slice. + /// + /// As a string slice consists of a sequence of bytes, we can iterate + /// through a string slice by byte. This method returns such an iterator. + /// + /// # Examples + /// + /// ``` + /// let mut bytes = "bors".bytes(); + /// + /// assert_eq!(Some(b'b'), bytes.next()); + /// assert_eq!(Some(b'o'), bytes.next()); + /// assert_eq!(Some(b'r'), bytes.next()); + /// assert_eq!(Some(b's'), bytes.next()); + /// + /// assert_eq!(None, bytes.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn bytes(&self) -> Bytes<'_> { + Bytes(self.as_bytes().iter().copied()) + } + + /// Splits a string slice by whitespace. + /// + /// The iterator returned will return string slices that are sub-slices of + /// the original string slice, separated by any amount of whitespace. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. If you only want to split on ASCII whitespace + /// instead, use [`split_ascii_whitespace`]. + /// + /// [`split_ascii_whitespace`]: str::split_ascii_whitespace + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut iter = "A few words".split_whitespace(); + /// + /// assert_eq!(Some("A"), iter.next()); + /// assert_eq!(Some("few"), iter.next()); + /// assert_eq!(Some("words"), iter.next()); + /// + /// assert_eq!(None, iter.next()); + /// ``` + /// + /// All kinds of whitespace are considered: + /// + /// ``` + /// let mut iter = " Mary had\ta\u{2009}little \n\t lamb".split_whitespace(); + /// assert_eq!(Some("Mary"), iter.next()); + /// assert_eq!(Some("had"), iter.next()); + /// assert_eq!(Some("a"), iter.next()); + /// assert_eq!(Some("little"), iter.next()); + /// assert_eq!(Some("lamb"), iter.next()); + /// + /// assert_eq!(None, iter.next()); + /// ``` + /// + /// If the string is empty or all whitespace, the iterator yields no string slices: + /// ``` + /// assert_eq!("".split_whitespace().next(), None); + /// assert_eq!(" ".split_whitespace().next(), None); + /// ``` + #[must_use = "this returns the split string as an iterator, \ + without modifying the original"] + #[stable(feature = "split_whitespace", since = "1.1.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "str_split_whitespace")] + #[inline] + pub fn split_whitespace(&self) -> SplitWhitespace<'_> { + SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) } + } + + /// Splits a string slice by ASCII whitespace. + /// + /// The iterator returned will return string slices that are sub-slices of + /// the original string slice, separated by any amount of ASCII whitespace. + /// + /// To split by Unicode `Whitespace` instead, use [`split_whitespace`]. + /// + /// [`split_whitespace`]: str::split_whitespace + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut iter = "A few words".split_ascii_whitespace(); + /// + /// assert_eq!(Some("A"), iter.next()); + /// assert_eq!(Some("few"), iter.next()); + /// assert_eq!(Some("words"), iter.next()); + /// + /// assert_eq!(None, iter.next()); + /// ``` + /// + /// All kinds of ASCII whitespace are considered: + /// + /// ``` + /// let mut iter = " Mary had\ta little \n\t lamb".split_ascii_whitespace(); + /// assert_eq!(Some("Mary"), iter.next()); + /// assert_eq!(Some("had"), iter.next()); + /// assert_eq!(Some("a"), iter.next()); + /// assert_eq!(Some("little"), iter.next()); + /// assert_eq!(Some("lamb"), iter.next()); + /// + /// assert_eq!(None, iter.next()); + /// ``` + /// + /// If the string is empty or all ASCII whitespace, the iterator yields no string slices: + /// ``` + /// assert_eq!("".split_ascii_whitespace().next(), None); + /// assert_eq!(" ".split_ascii_whitespace().next(), None); + /// ``` + #[must_use = "this returns the split string as an iterator, \ + without modifying the original"] + #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] + #[inline] + pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_> { + let inner = + self.as_bytes().split(IsAsciiWhitespace).filter(BytesIsNotEmpty).map(UnsafeBytesToStr); + SplitAsciiWhitespace { inner } + } + + /// Returns an iterator over the lines of a string, as string slices. + /// + /// Lines are split at line endings that are either newlines (`\n`) or + /// sequences of a carriage return followed by a line feed (`\r\n`). + /// + /// Line terminators are not included in the lines returned by the iterator. + /// + /// Note that any carriage return (`\r`) not immediately followed by a + /// line feed (`\n`) does not split a line. These carriage returns are + /// thereby included in the produced lines. + /// + /// The final line ending is optional. A string that ends with a final line + /// ending will return the same lines as an otherwise identical string + /// without a final line ending. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let text = "foo\r\nbar\n\nbaz\r"; + /// let mut lines = text.lines(); + /// + /// assert_eq!(Some("foo"), lines.next()); + /// assert_eq!(Some("bar"), lines.next()); + /// assert_eq!(Some(""), lines.next()); + /// // Trailing carriage return is included in the last line + /// assert_eq!(Some("baz\r"), lines.next()); + /// + /// assert_eq!(None, lines.next()); + /// ``` + /// + /// The final line does not require any ending: + /// + /// ``` + /// let text = "foo\nbar\n\r\nbaz"; + /// let mut lines = text.lines(); + /// + /// assert_eq!(Some("foo"), lines.next()); + /// assert_eq!(Some("bar"), lines.next()); + /// assert_eq!(Some(""), lines.next()); + /// assert_eq!(Some("baz"), lines.next()); + /// + /// assert_eq!(None, lines.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn lines(&self) -> Lines<'_> { + Lines(self.split_inclusive('\n').map(LinesMap)) + } + + /// Returns an iterator over the lines of a string. + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.4.0", note = "use lines() instead now", suggestion = "lines")] + #[inline] + #[allow(deprecated)] + pub fn lines_any(&self) -> LinesAny<'_> { + LinesAny(self.lines()) + } + + /// Returns an iterator of `u16` over the string encoded as UTF-16. + /// + /// # Examples + /// + /// ``` + /// let text = "Zażółć gęślą jaźń"; + /// + /// let utf8_len = text.len(); + /// let utf16_len = text.encode_utf16().count(); + /// + /// assert!(utf16_len <= utf8_len); + /// ``` + #[must_use = "this returns the encoded string as an iterator, \ + without modifying the original"] + #[stable(feature = "encode_utf16", since = "1.8.0")] + pub fn encode_utf16(&self) -> EncodeUtf16<'_> { + EncodeUtf16 { chars: self.chars(), extra: 0 } + } + + /// Returns `true` if the given pattern matches a sub-slice of + /// this string slice. + /// + /// Returns `false` if it does not. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Examples + /// + /// ``` + /// let bananas = "bananas"; + /// + /// assert!(bananas.contains("nana")); + /// assert!(!bananas.contains("apples")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn contains(&self, pat: P) -> bool { + pat.is_contained_in(self) + } + + /// Returns `true` if the given pattern matches a prefix of this + /// string slice. + /// + /// Returns `false` if it does not. + /// + /// The [pattern] can be a `&str`, in which case this function will return true if + /// the `&str` is a prefix of this string slice. + /// + /// The [pattern] can also be a [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// These will only be checked against the first character of this string slice. + /// Look at the second example below regarding behavior for slices of [`char`]s. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Examples + /// + /// ``` + /// let bananas = "bananas"; + /// + /// assert!(bananas.starts_with("bana")); + /// assert!(!bananas.starts_with("nana")); + /// ``` + /// + /// ``` + /// let bananas = "bananas"; + /// + /// // Note that both of these assert successfully. + /// assert!(bananas.starts_with(&['b', 'a', 'n', 'a'])); + /// assert!(bananas.starts_with(&['a', 'b', 'c', 'd'])); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "str_starts_with")] + pub fn starts_with(&self, pat: P) -> bool { + pat.is_prefix_of(self) + } + + /// Returns `true` if the given pattern matches a suffix of this + /// string slice. + /// + /// Returns `false` if it does not. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Examples + /// + /// ``` + /// let bananas = "bananas"; + /// + /// assert!(bananas.ends_with("anas")); + /// assert!(!bananas.ends_with("nana")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "str_ends_with")] + pub fn ends_with(&self, pat: P) -> bool + where + for<'a> P::Searcher<'a>: ReverseSearcher<'a>, + { + pat.is_suffix_of(self) + } + + /// Returns the byte index of the first character of this string slice that + /// matches the pattern. + /// + /// Returns [`None`] if the pattern doesn't match. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard Gepardi"; + /// + /// assert_eq!(s.find('L'), Some(0)); + /// assert_eq!(s.find('é'), Some(14)); + /// assert_eq!(s.find("pard"), Some(17)); + /// ``` + /// + /// More complex patterns using point-free style and closures: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.find(char::is_whitespace), Some(5)); + /// assert_eq!(s.find(char::is_lowercase), Some(1)); + /// assert_eq!(s.find(|c: char| c.is_whitespace() || c.is_lowercase()), Some(1)); + /// assert_eq!(s.find(|c: char| (c < 'o') && (c > 'a')), Some(4)); + /// ``` + /// + /// Not finding the pattern: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// let x: &[_] = &['1', '2']; + /// + /// assert_eq!(s.find(x), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn find(&self, pat: P) -> Option { + pat.into_searcher(self).next_match().map(|(i, _)| i) + } + + /// Returns the byte index for the first character of the last match of the pattern in + /// this string slice. + /// + /// Returns [`None`] if the pattern doesn't match. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard Gepardi"; + /// + /// assert_eq!(s.rfind('L'), Some(13)); + /// assert_eq!(s.rfind('é'), Some(14)); + /// assert_eq!(s.rfind("pard"), Some(24)); + /// ``` + /// + /// More complex patterns with closures: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.rfind(char::is_whitespace), Some(12)); + /// assert_eq!(s.rfind(char::is_lowercase), Some(20)); + /// ``` + /// + /// Not finding the pattern: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// let x: &[_] = &['1', '2']; + /// + /// assert_eq!(s.rfind(x), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rfind(&self, pat: P) -> Option + where + for<'a> P::Searcher<'a>: ReverseSearcher<'a>, + { + pat.into_searcher(self).next_match_back().map(|(i, _)| i) + } + + /// Returns an iterator over substrings of this string slice, separated by + /// characters matched by a pattern. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, e.g., [`char`], but not for `&str`. + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rsplit`] method can be used. + /// + /// [`rsplit`]: str::rsplit + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); + /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); + /// + /// let v: Vec<&str> = "".split('X').collect(); + /// assert_eq!(v, [""]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); + /// assert_eq!(v, ["lion", "", "tiger", "leopard"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect(); + /// assert_eq!(v, ["lion", "tiger", "leopard"]); + /// + /// let v: Vec<&str> = "abc1def2ghi".split(char::is_numeric).collect(); + /// assert_eq!(v, ["abc", "def", "ghi"]); + /// + /// let v: Vec<&str> = "lionXtigerXleopard".split(char::is_uppercase).collect(); + /// assert_eq!(v, ["lion", "tiger", "leopard"]); + /// ``` + /// + /// If the pattern is a slice of chars, split on each occurrence of any of the characters: + /// + /// ``` + /// let v: Vec<&str> = "2020-11-03 23:59".split(&['-', ' ', ':', '@'][..]).collect(); + /// assert_eq!(v, ["2020", "11", "03", "23", "59"]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".split(|c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["abc", "def", "ghi"]); + /// ``` + /// + /// If a string contains multiple contiguous separators, you will end up + /// with empty strings in the output: + /// + /// ``` + /// let x = "||||a||b|c".to_string(); + /// let d: Vec<_> = x.split('|').collect(); + /// + /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]); + /// ``` + /// + /// Contiguous separators are separated by the empty string. + /// + /// ``` + /// let x = "(///)".to_string(); + /// let d: Vec<_> = x.split('/').collect(); + /// + /// assert_eq!(d, &["(", "", "", ")"]); + /// ``` + /// + /// Separators at the start or end of a string are neighbored + /// by empty strings. + /// + /// ``` + /// let d: Vec<_> = "010".split("0").collect(); + /// assert_eq!(d, &["", "1", ""]); + /// ``` + /// + /// When the empty string is used as a separator, it separates + /// every character in the string, along with the beginning + /// and end of the string. + /// + /// ``` + /// let f: Vec<_> = "rust".split("").collect(); + /// assert_eq!(f, &["", "r", "u", "s", "t", ""]); + /// ``` + /// + /// Contiguous separators can lead to possibly surprising behavior + /// when whitespace is used as the separator. This code is correct: + /// + /// ``` + /// let x = " a b c".to_string(); + /// let d: Vec<_> = x.split(' ').collect(); + /// + /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]); + /// ``` + /// + /// It does _not_ give you: + /// + /// ```,ignore + /// assert_eq!(d, &["a", "b", "c"]); + /// ``` + /// + /// Use [`split_whitespace`] for this behavior. + /// + /// [`split_whitespace`]: str::split_whitespace + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split(&self, pat: P) -> Split<'_, P> { + Split(SplitInternal { + start: 0, + end: self.len(), + matcher: pat.into_searcher(self), + allow_trailing_empty: true, + finished: false, + }) + } + + /// Returns an iterator over substrings of this string slice, separated by + /// characters matched by a pattern. + /// + /// Differs from the iterator produced by `split` in that `split_inclusive` + /// leaves the matched part as the terminator of the substring. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Examples + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb\nlittle lamb\nlittle lamb." + /// .split_inclusive('\n').collect(); + /// assert_eq!(v, ["Mary had a little lamb\n", "little lamb\n", "little lamb."]); + /// ``` + /// + /// If the last element of the string is matched, + /// that element will be considered the terminator of the preceding substring. + /// That substring will be the last item returned by the iterator. + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb\nlittle lamb\nlittle lamb.\n" + /// .split_inclusive('\n').collect(); + /// assert_eq!(v, ["Mary had a little lamb\n", "little lamb\n", "little lamb.\n"]); + /// ``` + #[stable(feature = "split_inclusive", since = "1.51.0")] + #[inline] + pub fn split_inclusive(&self, pat: P) -> SplitInclusive<'_, P> { + SplitInclusive(SplitInternal { + start: 0, + end: self.len(), + matcher: pat.into_searcher(self), + allow_trailing_empty: false, + finished: false, + }) + } + + /// Returns an iterator over substrings of the given string slice, separated + /// by characters matched by a pattern and yielded in reverse order. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse + /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse + /// search yields the same elements. + /// + /// For iterating from the front, the [`split`] method can be used. + /// + /// [`split`]: str::split + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect(); + /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]); + /// + /// let v: Vec<&str> = "".rsplit('X').collect(); + /// assert_eq!(v, [""]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect(); + /// assert_eq!(v, ["leopard", "tiger", "", "lion"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect(); + /// assert_eq!(v, ["leopard", "tiger", "lion"]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".rsplit(|c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["ghi", "def", "abc"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplit(&self, pat: P) -> RSplit<'_, P> + where + for<'a> P::Searcher<'a>: ReverseSearcher<'a>, + { + RSplit(self.split(pat).0) + } + + /// Returns an iterator over substrings of the given string slice, separated + /// by characters matched by a pattern. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// Equivalent to [`split`], except that the trailing substring + /// is skipped if empty. + /// + /// [`split`]: str::split + /// + /// This method can be used for string data that is _terminated_, + /// rather than _separated_ by a pattern. + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, e.g., [`char`], but not for `&str`. + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rsplit_terminator`] method can be used. + /// + /// [`rsplit_terminator`]: str::rsplit_terminator + /// + /// # Examples + /// + /// ``` + /// let v: Vec<&str> = "A.B.".split_terminator('.').collect(); + /// assert_eq!(v, ["A", "B"]); + /// + /// let v: Vec<&str> = "A..B..".split_terminator(".").collect(); + /// assert_eq!(v, ["A", "", "B", ""]); + /// + /// let v: Vec<&str> = "A.B:C.D".split_terminator(&['.', ':'][..]).collect(); + /// assert_eq!(v, ["A", "B", "C", "D"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split_terminator(&self, pat: P) -> SplitTerminator<'_, P> { + SplitTerminator(SplitInternal { allow_trailing_empty: false, ..self.split(pat).0 }) + } + + /// Returns an iterator over substrings of `self`, separated by characters + /// matched by a pattern and yielded in reverse order. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// Equivalent to [`split`], except that the trailing substring is + /// skipped if empty. + /// + /// [`split`]: str::split + /// + /// This method can be used for string data that is _terminated_, + /// rather than _separated_ by a pattern. + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a + /// reverse search, and it will be double ended if a forward/reverse + /// search yields the same elements. + /// + /// For iterating from the front, the [`split_terminator`] method can be + /// used. + /// + /// [`split_terminator`]: str::split_terminator + /// + /// # Examples + /// + /// ``` + /// let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect(); + /// assert_eq!(v, ["B", "A"]); + /// + /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect(); + /// assert_eq!(v, ["", "B", "", "A"]); + /// + /// let v: Vec<&str> = "A.B:C.D".rsplit_terminator(&['.', ':'][..]).collect(); + /// assert_eq!(v, ["D", "C", "B", "A"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplit_terminator(&self, pat: P) -> RSplitTerminator<'_, P> + where + for<'a> P::Searcher<'a>: ReverseSearcher<'a>, + { + RSplitTerminator(self.split_terminator(pat).0) + } + + /// Returns an iterator over substrings of the given string slice, separated + /// by a pattern, restricted to returning at most `n` items. + /// + /// If `n` substrings are returned, the last substring (the `n`th substring) + /// will contain the remainder of the string. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Iterator behavior + /// + /// The returned iterator will not be double ended, because it is + /// not efficient to support. + /// + /// If the pattern allows a reverse search, the [`rsplitn`] method can be + /// used. + /// + /// [`rsplitn`]: str::rsplitn + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect(); + /// assert_eq!(v, ["Mary", "had", "a little lambda"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect(); + /// assert_eq!(v, ["lion", "", "tigerXleopard"]); + /// + /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect(); + /// assert_eq!(v, ["abcXdef"]); + /// + /// let v: Vec<&str> = "".splitn(1, 'X').collect(); + /// assert_eq!(v, [""]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".splitn(2, |c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["abc", "defXghi"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn splitn(&self, n: usize, pat: P) -> SplitN<'_, P> { + SplitN(SplitNInternal { iter: self.split(pat).0, count: n }) + } + + /// Returns an iterator over substrings of this string slice, separated by a + /// pattern, starting from the end of the string, restricted to returning at + /// most `n` items. + /// + /// If `n` substrings are returned, the last substring (the `n`th substring) + /// will contain the remainder of the string. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Iterator behavior + /// + /// The returned iterator will not be double ended, because it is not + /// efficient to support. + /// + /// For splitting from the front, the [`splitn`] method can be used. + /// + /// [`splitn`]: str::splitn + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect(); + /// assert_eq!(v, ["lamb", "little", "Mary had a"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect(); + /// assert_eq!(v, ["leopard", "tiger", "lionX"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect(); + /// assert_eq!(v, ["leopard", "lion::tiger"]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".rsplitn(2, |c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["ghi", "abc1def"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplitn(&self, n: usize, pat: P) -> RSplitN<'_, P> + where + for<'a> P::Searcher<'a>: ReverseSearcher<'a>, + { + RSplitN(self.splitn(n, pat).0) + } + + /// Splits the string on the first occurrence of the specified delimiter and + /// returns prefix before delimiter and suffix after delimiter. + /// + /// # Examples + /// + /// ``` + /// assert_eq!("cfg".split_once('='), None); + /// assert_eq!("cfg=".split_once('='), Some(("cfg", ""))); + /// assert_eq!("cfg=foo".split_once('='), Some(("cfg", "foo"))); + /// assert_eq!("cfg=foo=bar".split_once('='), Some(("cfg", "foo=bar"))); + /// ``` + #[stable(feature = "str_split_once", since = "1.52.0")] + #[inline] + pub fn split_once(&self, delimiter: P) -> Option<(&'_ str, &'_ str)> { + let (start, end) = delimiter.into_searcher(self).next_match()?; + // SAFETY: `Searcher` is known to return valid indices. + unsafe { Some((self.get_unchecked(..start), self.get_unchecked(end..))) } + } + + /// Splits the string on the last occurrence of the specified delimiter and + /// returns prefix before delimiter and suffix after delimiter. + /// + /// # Examples + /// + /// ``` + /// assert_eq!("cfg".rsplit_once('='), None); + /// assert_eq!("cfg=foo".rsplit_once('='), Some(("cfg", "foo"))); + /// assert_eq!("cfg=foo=bar".rsplit_once('='), Some(("cfg=foo", "bar"))); + /// ``` + #[stable(feature = "str_split_once", since = "1.52.0")] + #[inline] + pub fn rsplit_once(&self, delimiter: P) -> Option<(&'_ str, &'_ str)> + where + for<'a> P::Searcher<'a>: ReverseSearcher<'a>, + { + let (start, end) = delimiter.into_searcher(self).next_match_back()?; + // SAFETY: `Searcher` is known to return valid indices. + unsafe { Some((self.get_unchecked(..start), self.get_unchecked(end..))) } + } + + /// Returns an iterator over the disjoint matches of a pattern within the + /// given string slice. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, e.g., [`char`], but not for `&str`. + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rmatches`] method can be used. + /// + /// [`rmatches`]: str::rmatches + /// + /// # Examples + /// + /// ``` + /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect(); + /// assert_eq!(v, ["abc", "abc", "abc"]); + /// + /// let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect(); + /// assert_eq!(v, ["1", "2", "3"]); + /// ``` + #[stable(feature = "str_matches", since = "1.2.0")] + #[inline] + pub fn matches(&self, pat: P) -> Matches<'_, P> { + Matches(MatchesInternal(pat.into_searcher(self))) + } + + /// Returns an iterator over the disjoint matches of a pattern within this + /// string slice, yielded in reverse order. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse + /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse + /// search yields the same elements. + /// + /// For iterating from the front, the [`matches`] method can be used. + /// + /// [`matches`]: str::matches + /// + /// # Examples + /// + /// ``` + /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect(); + /// assert_eq!(v, ["abc", "abc", "abc"]); + /// + /// let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect(); + /// assert_eq!(v, ["3", "2", "1"]); + /// ``` + #[stable(feature = "str_matches", since = "1.2.0")] + #[inline] + pub fn rmatches(&self, pat: P) -> RMatches<'_, P> + where + for<'a> P::Searcher<'a>: ReverseSearcher<'a>, + { + RMatches(self.matches(pat).0) + } + + /// Returns an iterator over the disjoint matches of a pattern within this string + /// slice as well as the index that the match starts at. + /// + /// For matches of `pat` within `self` that overlap, only the indices + /// corresponding to the first match are returned. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, e.g., [`char`], but not for `&str`. + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rmatch_indices`] method can be used. + /// + /// [`rmatch_indices`]: str::rmatch_indices + /// + /// # Examples + /// + /// ``` + /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect(); + /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]); + /// + /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect(); + /// assert_eq!(v, [(1, "abc"), (4, "abc")]); + /// + /// let v: Vec<_> = "ababa".match_indices("aba").collect(); + /// assert_eq!(v, [(0, "aba")]); // only the first `aba` + /// ``` + #[stable(feature = "str_match_indices", since = "1.5.0")] + #[inline] + pub fn match_indices(&self, pat: P) -> MatchIndices<'_, P> { + MatchIndices(MatchIndicesInternal(pat.into_searcher(self))) + } + + /// Returns an iterator over the disjoint matches of a pattern within `self`, + /// yielded in reverse order along with the index of the match. + /// + /// For matches of `pat` within `self` that overlap, only the indices + /// corresponding to the last match are returned. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse + /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse + /// search yields the same elements. + /// + /// For iterating from the front, the [`match_indices`] method can be used. + /// + /// [`match_indices`]: str::match_indices + /// + /// # Examples + /// + /// ``` + /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect(); + /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]); + /// + /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect(); + /// assert_eq!(v, [(4, "abc"), (1, "abc")]); + /// + /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect(); + /// assert_eq!(v, [(2, "aba")]); // only the last `aba` + /// ``` + #[stable(feature = "str_match_indices", since = "1.5.0")] + #[inline] + pub fn rmatch_indices(&self, pat: P) -> RMatchIndices<'_, P> + where + for<'a> P::Searcher<'a>: ReverseSearcher<'a>, + { + RMatchIndices(self.match_indices(pat).0) + } + + /// Returns a string slice with leading and trailing whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`, which includes newlines. + /// + /// # Examples + /// + /// ``` + /// let s = "\n Hello\tworld\t\n"; + /// + /// assert_eq!("Hello\tworld", s.trim()); + /// ``` + #[inline] + #[must_use = "this returns the trimmed string as a slice, \ + without modifying the original"] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "str_trim")] + pub fn trim(&self) -> &str { + self.trim_matches(|c: char| c.is_whitespace()) + } + + /// Returns a string slice with leading whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`, which includes newlines. + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. `start` in this context means the first + /// position of that byte string; for a left-to-right language like English or + /// Russian, this will be left side, and for right-to-left languages like + /// Arabic or Hebrew, this will be the right side. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "\n Hello\tworld\t\n"; + /// assert_eq!("Hello\tworld\t\n", s.trim_start()); + /// ``` + /// + /// Directionality: + /// + /// ``` + /// let s = " English "; + /// assert!(Some('E') == s.trim_start().chars().next()); + /// + /// let s = " עברית "; + /// assert!(Some('ע') == s.trim_start().chars().next()); + /// ``` + #[inline] + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] + #[stable(feature = "trim_direction", since = "1.30.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "str_trim_start")] + pub fn trim_start(&self) -> &str { + self.trim_start_matches(|c: char| c.is_whitespace()) + } + + /// Returns a string slice with trailing whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`, which includes newlines. + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. `end` in this context means the last + /// position of that byte string; for a left-to-right language like English or + /// Russian, this will be right side, and for right-to-left languages like + /// Arabic or Hebrew, this will be the left side. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "\n Hello\tworld\t\n"; + /// assert_eq!("\n Hello\tworld", s.trim_end()); + /// ``` + /// + /// Directionality: + /// + /// ``` + /// let s = " English "; + /// assert!(Some('h') == s.trim_end().chars().rev().next()); + /// + /// let s = " עברית "; + /// assert!(Some('ת') == s.trim_end().chars().rev().next()); + /// ``` + #[inline] + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] + #[stable(feature = "trim_direction", since = "1.30.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "str_trim_end")] + pub fn trim_end(&self) -> &str { + self.trim_end_matches(|c: char| c.is_whitespace()) + } + + /// Returns a string slice with leading whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Left' in this context means the first + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _right_ side, not the left. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// + /// assert_eq!("Hello\tworld\t", s.trim_left()); + /// ``` + /// + /// Directionality: + /// + /// ``` + /// let s = " English"; + /// assert!(Some('E') == s.trim_left().chars().next()); + /// + /// let s = " עברית"; + /// assert!(Some('ע') == s.trim_left().chars().next()); + /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.33.0", note = "superseded by `trim_start`", suggestion = "trim_start")] + pub fn trim_left(&self) -> &str { + self.trim_start() + } + + /// Returns a string slice with trailing whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Right' in this context means the last + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _left_ side, not the right. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// + /// assert_eq!(" Hello\tworld", s.trim_right()); + /// ``` + /// + /// Directionality: + /// + /// ``` + /// let s = "English "; + /// assert!(Some('h') == s.trim_right().chars().rev().next()); + /// + /// let s = "עברית "; + /// assert!(Some('ת') == s.trim_right().chars().rev().next()); + /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.33.0", note = "superseded by `trim_end`", suggestion = "trim_end")] + pub fn trim_right(&self) -> &str { + self.trim_end() + } + + /// Returns a string slice with all prefixes and suffixes that match a + /// pattern repeatedly removed. + /// + /// The [pattern] can be a [`char`], a slice of [`char`]s, or a function + /// or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); + /// assert_eq!("123foo1bar123".trim_matches(char::is_numeric), "foo1bar"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar"); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar"); + /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_matches(&self, pat: P) -> &str + where + for<'a> P::Searcher<'a>: DoubleEndedSearcher<'a>, + { + let mut i = 0; + let mut j = 0; + let mut matcher = pat.into_searcher(self); + if let Some((a, b)) = matcher.next_reject() { + i = a; + j = b; // Remember earliest known match, correct it below if + // last match is different + } + if let Some((_, b)) = matcher.next_reject_back() { + j = b; + } + // SAFETY: `Searcher` is known to return valid indices. + unsafe { self.get_unchecked(i..j) } + } + + /// Returns a string slice with all prefixes that match a pattern + /// repeatedly removed. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. `start` in this context means the first + /// position of that byte string; for a left-to-right language like English or + /// Russian, this will be left side, and for right-to-left languages like + /// Arabic or Hebrew, this will be the right side. + /// + /// # Examples + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11"); + /// assert_eq!("123foo1bar123".trim_start_matches(char::is_numeric), "foo1bar123"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_start_matches(x), "foo1bar12"); + /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] + #[stable(feature = "trim_direction", since = "1.30.0")] + pub fn trim_start_matches(&self, pat: P) -> &str { + let mut i = self.len(); + let mut matcher = pat.into_searcher(self); + if let Some((a, _)) = matcher.next_reject() { + i = a; + } + // SAFETY: `Searcher` is known to return valid indices. + unsafe { self.get_unchecked(i..self.len()) } + } + + /// Returns a string slice with the prefix removed. + /// + /// If the string starts with the pattern `prefix`, returns the substring after the prefix, + /// wrapped in `Some`. Unlike [`trim_start_matches`], this method removes the prefix exactly once. + /// + /// If the string does not start with `prefix`, returns `None`. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// [`trim_start_matches`]: Self::trim_start_matches + /// + /// # Examples + /// + /// ``` + /// assert_eq!("foo:bar".strip_prefix("foo:"), Some("bar")); + /// assert_eq!("foo:bar".strip_prefix("bar"), None); + /// assert_eq!("foofoo".strip_prefix("foo"), Some("foo")); + /// ``` + #[must_use = "this returns the remaining substring as a new slice, \ + without modifying the original"] + #[stable(feature = "str_strip", since = "1.45.0")] + pub fn strip_prefix(&self, prefix: P) -> Option<&str> { + prefix.strip_prefix_of(self) + } + + /// Returns a string slice with the suffix removed. + /// + /// If the string ends with the pattern `suffix`, returns the substring before the suffix, + /// wrapped in `Some`. Unlike [`trim_end_matches`], this method removes the suffix exactly once. + /// + /// If the string does not end with `suffix`, returns `None`. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// [`trim_end_matches`]: Self::trim_end_matches + /// + /// # Examples + /// + /// ``` + /// assert_eq!("bar:foo".strip_suffix(":foo"), Some("bar")); + /// assert_eq!("bar:foo".strip_suffix("bar"), None); + /// assert_eq!("foofoo".strip_suffix("foo"), Some("foo")); + /// ``` + #[must_use = "this returns the remaining substring as a new slice, \ + without modifying the original"] + #[stable(feature = "str_strip", since = "1.45.0")] + pub fn strip_suffix(&self, suffix: P) -> Option<&str> + where + for<'a> P::Searcher<'a>: ReverseSearcher<'a>, + { + suffix.strip_suffix_of(self) + } + + /// Returns a string slice with all suffixes that match a pattern + /// repeatedly removed. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. `end` in this context means the last + /// position of that byte string; for a left-to-right language like English or + /// Russian, this will be right side, and for right-to-left languages like + /// Arabic or Hebrew, this will be the left side. + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar"); + /// assert_eq!("123foo1bar123".trim_end_matches(char::is_numeric), "123foo1bar"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_end_matches(x), "12foo1bar"); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// assert_eq!("1fooX".trim_end_matches(|c| c == '1' || c == 'X'), "1foo"); + /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] + #[stable(feature = "trim_direction", since = "1.30.0")] + pub fn trim_end_matches(&self, pat: P) -> &str + where + for<'a> P::Searcher<'a>: ReverseSearcher<'a>, + { + let mut j = 0; + let mut matcher = pat.into_searcher(self); + if let Some((_, b)) = matcher.next_reject_back() { + j = b; + } + // SAFETY: `Searcher` is known to return valid indices. + unsafe { self.get_unchecked(0..j) } + } + + /// Returns a string slice with all prefixes that match a pattern + /// repeatedly removed. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Left' in this context means the first + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _right_ side, not the left. + /// + /// # Examples + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); + /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated( + since = "1.33.0", + note = "superseded by `trim_start_matches`", + suggestion = "trim_start_matches" + )] + pub fn trim_left_matches(&self, pat: P) -> &str { + self.trim_start_matches(pat) + } + + /// Returns a string slice with all suffixes that match a pattern + /// repeatedly removed. + /// + /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Right' in this context means the last + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _left_ side, not the right. + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); + /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar"); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated( + since = "1.33.0", + note = "superseded by `trim_end_matches`", + suggestion = "trim_end_matches" + )] + pub fn trim_right_matches(&self, pat: P) -> &str + where + for<'a> P::Searcher<'a>: ReverseSearcher<'a>, + { + self.trim_end_matches(pat) + } + + /// Parses this string slice into another type. + /// + /// Because `parse` is so general, it can cause problems with type + /// inference. As such, `parse` is one of the few times you'll see + /// the syntax affectionately known as the 'turbofish': `::<>`. This + /// helps the inference algorithm understand specifically which type + /// you're trying to parse into. + /// + /// `parse` can parse into any type that implements the [`FromStr`] trait. + + /// + /// # Errors + /// + /// Will return [`Err`] if it's not possible to parse this string slice into + /// the desired type. + /// + /// [`Err`]: FromStr::Err + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let four: u32 = "4".parse().unwrap(); + /// + /// assert_eq!(4, four); + /// ``` + /// + /// Using the 'turbofish' instead of annotating `four`: + /// + /// ``` + /// let four = "4".parse::(); + /// + /// assert_eq!(Ok(4), four); + /// ``` + /// + /// Failing to parse: + /// + /// ``` + /// let nope = "j".parse::(); + /// + /// assert!(nope.is_err()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn parse(&self) -> Result { + FromStr::from_str(self) + } + + /// Checks if all characters in this string are within the ASCII range. + /// + /// # Examples + /// + /// ``` + /// let ascii = "hello!\n"; + /// let non_ascii = "Grüße, Jürgen ❤"; + /// + /// assert!(ascii.is_ascii()); + /// assert!(!non_ascii.is_ascii()); + /// ``` + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_slice_is_ascii", since = "1.74.0")] + #[must_use] + #[inline] + pub const fn is_ascii(&self) -> bool { + // We can treat each byte as character here: all multibyte characters + // start with a byte that is not in the ASCII range, so we will stop + // there already. + self.as_bytes().is_ascii() + } + + /// If this string slice [`is_ascii`](Self::is_ascii), returns it as a slice + /// of [ASCII characters](`ascii::Char`), otherwise returns `None`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub const fn as_ascii(&self) -> Option<&[ascii::Char]> { + // Like in `is_ascii`, we can work on the bytes directly. + self.as_bytes().as_ascii() + } + + /// Checks that two strings are an ASCII case-insensitive match. + /// + /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, + /// but without allocating and copying temporaries. + /// + /// # Examples + /// + /// ``` + /// assert!("Ferris".eq_ignore_ascii_case("FERRIS")); + /// assert!("Ferrös".eq_ignore_ascii_case("FERRöS")); + /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS")); + /// ``` + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_unstable(feature = "const_eq_ignore_ascii_case", issue = "131719")] + #[must_use] + #[inline] + pub const fn eq_ignore_ascii_case(&self, other: &str) -> bool { + self.as_bytes().eq_ignore_ascii_case(other.as_bytes()) + } + + /// Converts this string to its ASCII upper case equivalent in-place. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new uppercased value without modifying the existing one, use + /// [`to_ascii_uppercase()`]. + /// + /// [`to_ascii_uppercase()`]: #method.to_ascii_uppercase + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("Grüße, Jürgen ❤"); + /// + /// s.make_ascii_uppercase(); + /// + /// assert_eq!("GRüßE, JüRGEN ❤", s); + /// ``` + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] + #[inline] + pub const fn make_ascii_uppercase(&mut self) { + // SAFETY: changing ASCII letters only does not invalidate UTF-8. + let me = unsafe { self.as_bytes_mut() }; + me.make_ascii_uppercase() + } + + /// Converts this string to its ASCII lower case equivalent in-place. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new lowercased value without modifying the existing one, use + /// [`to_ascii_lowercase()`]. + /// + /// [`to_ascii_lowercase()`]: #method.to_ascii_lowercase + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("GRÜßE, JÜRGEN ❤"); + /// + /// s.make_ascii_lowercase(); + /// + /// assert_eq!("grÜße, jÜrgen ❤", s); + /// ``` + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] + #[inline] + pub const fn make_ascii_lowercase(&mut self) { + // SAFETY: changing ASCII letters only does not invalidate UTF-8. + let me = unsafe { self.as_bytes_mut() }; + me.make_ascii_lowercase() + } + + /// Returns a string slice with leading ASCII whitespace removed. + /// + /// 'Whitespace' refers to the definition used by + /// [`u8::is_ascii_whitespace`]. + /// + /// [`u8::is_ascii_whitespace`]: u8::is_ascii_whitespace + /// + /// # Examples + /// + /// ``` + /// assert_eq!(" \t \u{3000}hello world\n".trim_ascii_start(), "\u{3000}hello world\n"); + /// assert_eq!(" ".trim_ascii_start(), ""); + /// assert_eq!("".trim_ascii_start(), ""); + /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] + #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")] + #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")] + #[inline] + pub const fn trim_ascii_start(&self) -> &str { + // SAFETY: Removing ASCII characters from a `&str` does not invalidate + // UTF-8. + unsafe { core::str::from_utf8_unchecked(self.as_bytes().trim_ascii_start()) } + } + + /// Returns a string slice with trailing ASCII whitespace removed. + /// + /// 'Whitespace' refers to the definition used by + /// [`u8::is_ascii_whitespace`]. + /// + /// [`u8::is_ascii_whitespace`]: u8::is_ascii_whitespace + /// + /// # Examples + /// + /// ``` + /// assert_eq!("\r hello world\u{3000}\n ".trim_ascii_end(), "\r hello world\u{3000}"); + /// assert_eq!(" ".trim_ascii_end(), ""); + /// assert_eq!("".trim_ascii_end(), ""); + /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] + #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")] + #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")] + #[inline] + pub const fn trim_ascii_end(&self) -> &str { + // SAFETY: Removing ASCII characters from a `&str` does not invalidate + // UTF-8. + unsafe { core::str::from_utf8_unchecked(self.as_bytes().trim_ascii_end()) } + } + + /// Returns a string slice with leading and trailing ASCII whitespace + /// removed. + /// + /// 'Whitespace' refers to the definition used by + /// [`u8::is_ascii_whitespace`]. + /// + /// [`u8::is_ascii_whitespace`]: u8::is_ascii_whitespace + /// + /// # Examples + /// + /// ``` + /// assert_eq!("\r hello world\n ".trim_ascii(), "hello world"); + /// assert_eq!(" ".trim_ascii(), ""); + /// assert_eq!("".trim_ascii(), ""); + /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] + #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")] + #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")] + #[inline] + pub const fn trim_ascii(&self) -> &str { + // SAFETY: Removing ASCII characters from a `&str` does not invalidate + // UTF-8. + unsafe { core::str::from_utf8_unchecked(self.as_bytes().trim_ascii()) } + } + + /// Returns an iterator that escapes each char in `self` with [`char::escape_debug`]. + /// + /// Note: only extended grapheme codepoints that begin the string will be + /// escaped. + /// + /// # Examples + /// + /// As an iterator: + /// + /// ``` + /// for c in "❤\n!".escape_debug() { + /// print!("{c}"); + /// } + /// println!(); + /// ``` + /// + /// Using `println!` directly: + /// + /// ``` + /// println!("{}", "❤\n!".escape_debug()); + /// ``` + /// + /// + /// Both are equivalent to: + /// + /// ``` + /// println!("❤\\n!"); + /// ``` + /// + /// Using `to_string`: + /// + /// ``` + /// assert_eq!("❤\n!".escape_debug().to_string(), "❤\\n!"); + /// ``` + #[must_use = "this returns the escaped string as an iterator, \ + without modifying the original"] + #[stable(feature = "str_escape", since = "1.34.0")] + pub fn escape_debug(&self) -> EscapeDebug<'_> { + let mut chars = self.chars(); + EscapeDebug { + inner: chars + .next() + .map(|first| first.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL)) + .into_iter() + .flatten() + .chain(chars.flat_map(CharEscapeDebugContinue)), + } + } + + /// Returns an iterator that escapes each char in `self` with [`char::escape_default`]. + /// + /// # Examples + /// + /// As an iterator: + /// + /// ``` + /// for c in "❤\n!".escape_default() { + /// print!("{c}"); + /// } + /// println!(); + /// ``` + /// + /// Using `println!` directly: + /// + /// ``` + /// println!("{}", "❤\n!".escape_default()); + /// ``` + /// + /// + /// Both are equivalent to: + /// + /// ``` + /// println!("\\u{{2764}}\\n!"); + /// ``` + /// + /// Using `to_string`: + /// + /// ``` + /// assert_eq!("❤\n!".escape_default().to_string(), "\\u{2764}\\n!"); + /// ``` + #[must_use = "this returns the escaped string as an iterator, \ + without modifying the original"] + #[stable(feature = "str_escape", since = "1.34.0")] + pub fn escape_default(&self) -> EscapeDefault<'_> { + EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) } + } + + /// Returns an iterator that escapes each char in `self` with [`char::escape_unicode`]. + /// + /// # Examples + /// + /// As an iterator: + /// + /// ``` + /// for c in "❤\n!".escape_unicode() { + /// print!("{c}"); + /// } + /// println!(); + /// ``` + /// + /// Using `println!` directly: + /// + /// ``` + /// println!("{}", "❤\n!".escape_unicode()); + /// ``` + /// + /// + /// Both are equivalent to: + /// + /// ``` + /// println!("\\u{{2764}}\\u{{a}}\\u{{21}}"); + /// ``` + /// + /// Using `to_string`: + /// + /// ``` + /// assert_eq!("❤\n!".escape_unicode().to_string(), "\\u{2764}\\u{a}\\u{21}"); + /// ``` + #[must_use = "this returns the escaped string as an iterator, \ + without modifying the original"] + #[stable(feature = "str_escape", since = "1.34.0")] + pub fn escape_unicode(&self) -> EscapeUnicode<'_> { + EscapeUnicode { inner: self.chars().flat_map(CharEscapeUnicode) } + } + + /// Returns the range that a substring points to. + /// + /// Returns `None` if `substr` does not point within `self`. + /// + /// Unlike [`str::find`], **this does not search through the string**. + /// Instead, it uses pointer arithmetic to find where in the string + /// `substr` is derived from. + /// + /// This is useful for extending [`str::split`] and similar methods. + /// + /// Note that this method may return false positives (typically either + /// `Some(0..0)` or `Some(self.len()..self.len())`) if `substr` is a + /// zero-length `str` that points at the beginning or end of another, + /// independent, `str`. + /// + /// # Examples + /// ``` + /// #![feature(substr_range)] + /// + /// let data = "a, b, b, a"; + /// let mut iter = data.split(", ").map(|s| data.substr_range(s).unwrap()); + /// + /// assert_eq!(iter.next(), Some(0..1)); + /// assert_eq!(iter.next(), Some(3..4)); + /// assert_eq!(iter.next(), Some(6..7)); + /// assert_eq!(iter.next(), Some(9..10)); + /// ``` + #[must_use] + #[unstable(feature = "substr_range", issue = "126769")] + pub fn substr_range(&self, substr: &str) -> Option> { + self.as_bytes().subslice_range(substr.as_bytes()) + } + + /// Returns the same string as a string slice `&str`. + /// + /// This method is redundant when used directly on `&str`, but + /// it helps dereferencing other string-like types to string slices, + /// for example references to `Box` or `Arc`. + #[inline] + #[unstable(feature = "str_as_str", issue = "130366")] + pub fn as_str(&self) -> &str { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef<[u8]> for str { + #[inline] + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for &str { + /// Creates an empty str + #[inline] + fn default() -> Self { + "" + } +} + +#[stable(feature = "default_mut_str", since = "1.28.0")] +impl Default for &mut str { + /// Creates an empty mutable str + #[inline] + fn default() -> Self { + // SAFETY: The empty string is valid UTF-8. + unsafe { from_utf8_unchecked_mut(&mut []) } + } +} + +impl_fn_for_zst! { + /// A nameable, cloneable fn type + #[derive(Clone)] + struct LinesMap impl<'a> Fn = |line: &'a str| -> &'a str { + let Some(line) = line.strip_suffix('\n') else { return line }; + let Some(line) = line.strip_suffix('\r') else { return line }; + line + }; + + #[derive(Clone)] + struct CharEscapeDebugContinue impl Fn = |c: char| -> char::EscapeDebug { + c.escape_debug_ext(EscapeDebugExtArgs { + escape_grapheme_extended: false, + escape_single_quote: true, + escape_double_quote: true + }) + }; + + #[derive(Clone)] + struct CharEscapeUnicode impl Fn = |c: char| -> char::EscapeUnicode { + c.escape_unicode() + }; + #[derive(Clone)] + struct CharEscapeDefault impl Fn = |c: char| -> char::EscapeDefault { + c.escape_default() + }; + + #[derive(Clone)] + struct IsWhitespace impl Fn = |c: char| -> bool { + c.is_whitespace() + }; + + #[derive(Clone)] + struct IsAsciiWhitespace impl Fn = |byte: &u8| -> bool { + byte.is_ascii_whitespace() + }; + + #[derive(Clone)] + struct IsNotEmpty impl<'a, 'b> Fn = |s: &'a &'b str| -> bool { + !s.is_empty() + }; + + #[derive(Clone)] + struct BytesIsNotEmpty impl<'a, 'b> Fn = |s: &'a &'b [u8]| -> bool { + !s.is_empty() + }; + + #[derive(Clone)] + struct UnsafeBytesToStr impl<'a> Fn = |bytes: &'a [u8]| -> &'a str { + // SAFETY: not safe + unsafe { from_utf8_unchecked(bytes) } + }; +} + +// This is required to make `impl From<&str> for Box` and `impl From for Box` not overlap. +#[stable(feature = "error_in_core_neg_impl", since = "1.65.0")] +impl !crate::error::Error for &str {} diff --git a/CoqOfRust/core/str/pattern.rs b/CoqOfRust/core/str/pattern.rs new file mode 100644 index 000000000..52e236489 --- /dev/null +++ b/CoqOfRust/core/str/pattern.rs @@ -0,0 +1,1967 @@ +//! The string Pattern API. +//! +//! The Pattern API provides a generic mechanism for using different pattern +//! types when searching through a string. +//! +//! For more details, see the traits [`Pattern`], [`Searcher`], +//! [`ReverseSearcher`], and [`DoubleEndedSearcher`]. +//! +//! Although this API is unstable, it is exposed via stable APIs on the +//! [`str`] type. +//! +//! # Examples +//! +//! [`Pattern`] is [implemented][pattern-impls] in the stable API for +//! [`&str`][`str`], [`char`], slices of [`char`], and functions and closures +//! implementing `FnMut(char) -> bool`. +//! +//! ``` +//! let s = "Can you find a needle in a haystack?"; +//! +//! // &str pattern +//! assert_eq!(s.find("you"), Some(4)); +//! // char pattern +//! assert_eq!(s.find('n'), Some(2)); +//! // array of chars pattern +//! assert_eq!(s.find(&['a', 'e', 'i', 'o', 'u']), Some(1)); +//! // slice of chars pattern +//! assert_eq!(s.find(&['a', 'e', 'i', 'o', 'u'][..]), Some(1)); +//! // closure pattern +//! assert_eq!(s.find(|c: char| c.is_ascii_punctuation()), Some(35)); +//! ``` +//! +//! [pattern-impls]: Pattern#implementors + +#![unstable( + feature = "pattern", + reason = "API not fully fleshed out and ready to be stabilized", + issue = "27721" +)] + +use crate::cmp::Ordering; +use crate::convert::TryInto as _; +use crate::slice::memchr; +use crate::{cmp, fmt}; + +// Pattern + +/// A string pattern. +/// +/// A `Pattern` expresses that the implementing type +/// can be used as a string pattern for searching in a [`&str`][str]. +/// +/// For example, both `'a'` and `"aa"` are patterns that +/// would match at index `1` in the string `"baaaab"`. +/// +/// The trait itself acts as a builder for an associated +/// [`Searcher`] type, which does the actual work of finding +/// occurrences of the pattern in a string. +/// +/// Depending on the type of the pattern, the behavior of methods like +/// [`str::find`] and [`str::contains`] can change. The table below describes +/// some of those behaviors. +/// +/// | Pattern type | Match condition | +/// |--------------------------|-------------------------------------------| +/// | `&str` | is substring | +/// | `char` | is contained in string | +/// | `&[char]` | any char in slice is contained in string | +/// | `F: FnMut(char) -> bool` | `F` returns `true` for a char in string | +/// | `&&str` | is substring | +/// | `&String` | is substring | +/// +/// # Examples +/// +/// ``` +/// // &str +/// assert_eq!("abaaa".find("ba"), Some(1)); +/// assert_eq!("abaaa".find("bac"), None); +/// +/// // char +/// assert_eq!("abaaa".find('a'), Some(0)); +/// assert_eq!("abaaa".find('b'), Some(1)); +/// assert_eq!("abaaa".find('c'), None); +/// +/// // &[char; N] +/// assert_eq!("ab".find(&['b', 'a']), Some(0)); +/// assert_eq!("abaaa".find(&['a', 'z']), Some(0)); +/// assert_eq!("abaaa".find(&['c', 'd']), None); +/// +/// // &[char] +/// assert_eq!("ab".find(&['b', 'a'][..]), Some(0)); +/// assert_eq!("abaaa".find(&['a', 'z'][..]), Some(0)); +/// assert_eq!("abaaa".find(&['c', 'd'][..]), None); +/// +/// // FnMut(char) -> bool +/// assert_eq!("abcdef_z".find(|ch| ch > 'd' && ch < 'y'), Some(4)); +/// assert_eq!("abcddd_z".find(|ch| ch > 'd' && ch < 'y'), None); +/// ``` +pub trait Pattern: Sized { + /// Associated searcher for this pattern + type Searcher<'a>: Searcher<'a>; + + /// Constructs the associated searcher from + /// `self` and the `haystack` to search in. + fn into_searcher(self, haystack: &str) -> Self::Searcher<'_>; + + /// Checks whether the pattern matches anywhere in the haystack + #[inline] + fn is_contained_in(self, haystack: &str) -> bool { + self.into_searcher(haystack).next_match().is_some() + } + + /// Checks whether the pattern matches at the front of the haystack + #[inline] + fn is_prefix_of(self, haystack: &str) -> bool { + matches!(self.into_searcher(haystack).next(), SearchStep::Match(0, _)) + } + + /// Checks whether the pattern matches at the back of the haystack + #[inline] + fn is_suffix_of<'a>(self, haystack: &'a str) -> bool + where + Self::Searcher<'a>: ReverseSearcher<'a>, + { + matches!(self.into_searcher(haystack).next_back(), SearchStep::Match(_, j) if haystack.len() == j) + } + + /// Removes the pattern from the front of haystack, if it matches. + #[inline] + fn strip_prefix_of(self, haystack: &str) -> Option<&str> { + if let SearchStep::Match(start, len) = self.into_searcher(haystack).next() { + debug_assert_eq!( + start, 0, + "The first search step from Searcher \ + must include the first character" + ); + // SAFETY: `Searcher` is known to return valid indices. + unsafe { Some(haystack.get_unchecked(len..)) } + } else { + None + } + } + + /// Removes the pattern from the back of haystack, if it matches. + #[inline] + fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str> + where + Self::Searcher<'a>: ReverseSearcher<'a>, + { + if let SearchStep::Match(start, end) = self.into_searcher(haystack).next_back() { + debug_assert_eq!( + end, + haystack.len(), + "The first search step from ReverseSearcher \ + must include the last character" + ); + // SAFETY: `Searcher` is known to return valid indices. + unsafe { Some(haystack.get_unchecked(..start)) } + } else { + None + } + } + + /// Returns the pattern as utf-8 bytes if possible. + fn as_utf8_pattern(&self) -> Option> { + None + } +} +/// Result of calling [`Pattern::as_utf8_pattern()`]. +/// Can be used for inspecting the contents of a [`Pattern`] in cases +/// where the underlying representation can be represented as UTF-8. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum Utf8Pattern<'a> { + /// Type returned by String and str types. + StringPattern(&'a [u8]), + /// Type returned by char types. + CharPattern(char), +} + +// Searcher + +/// Result of calling [`Searcher::next()`] or [`ReverseSearcher::next_back()`]. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum SearchStep { + /// Expresses that a match of the pattern has been found at + /// `haystack[a..b]`. + Match(usize, usize), + /// Expresses that `haystack[a..b]` has been rejected as a possible match + /// of the pattern. + /// + /// Note that there might be more than one `Reject` between two `Match`es, + /// there is no requirement for them to be combined into one. + Reject(usize, usize), + /// Expresses that every byte of the haystack has been visited, ending + /// the iteration. + Done, +} + +/// A searcher for a string pattern. +/// +/// This trait provides methods for searching for non-overlapping +/// matches of a pattern starting from the front (left) of a string. +/// +/// It will be implemented by associated `Searcher` +/// types of the [`Pattern`] trait. +/// +/// The trait is marked unsafe because the indices returned by the +/// [`next()`][Searcher::next] methods are required to lie on valid utf8 +/// boundaries in the haystack. This enables consumers of this trait to +/// slice the haystack without additional runtime checks. +pub unsafe trait Searcher<'a> { + /// Getter for the underlying string to be searched in + /// + /// Will always return the same [`&str`][str]. + fn haystack(&self) -> &'a str; + + /// Performs the next search step starting from the front. + /// + /// - Returns [`Match(a, b)`][SearchStep::Match] if `haystack[a..b]` matches + /// the pattern. + /// - Returns [`Reject(a, b)`][SearchStep::Reject] if `haystack[a..b]` can + /// not match the pattern, even partially. + /// - Returns [`Done`][SearchStep::Done] if every byte of the haystack has + /// been visited. + /// + /// The stream of [`Match`][SearchStep::Match] and + /// [`Reject`][SearchStep::Reject] values up to a [`Done`][SearchStep::Done] + /// will contain index ranges that are adjacent, non-overlapping, + /// covering the whole haystack, and laying on utf8 boundaries. + /// + /// A [`Match`][SearchStep::Match] result needs to contain the whole matched + /// pattern, however [`Reject`][SearchStep::Reject] results may be split up + /// into arbitrary many adjacent fragments. Both ranges may have zero length. + /// + /// As an example, the pattern `"aaa"` and the haystack `"cbaaaaab"` + /// might produce the stream + /// `[Reject(0, 1), Reject(1, 2), Match(2, 5), Reject(5, 8)]` + fn next(&mut self) -> SearchStep; + + /// Finds the next [`Match`][SearchStep::Match] result. See [`next()`][Searcher::next]. + /// + /// Unlike [`next()`][Searcher::next], there is no guarantee that the returned ranges + /// of this and [`next_reject`][Searcher::next_reject] will overlap. This will return + /// `(start_match, end_match)`, where start_match is the index of where + /// the match begins, and end_match is the index after the end of the match. + #[inline] + fn next_match(&mut self) -> Option<(usize, usize)> { + loop { + match self.next() { + SearchStep::Match(a, b) => return Some((a, b)), + SearchStep::Done => return None, + _ => continue, + } + } + } + + /// Finds the next [`Reject`][SearchStep::Reject] result. See [`next()`][Searcher::next] + /// and [`next_match()`][Searcher::next_match]. + /// + /// Unlike [`next()`][Searcher::next], there is no guarantee that the returned ranges + /// of this and [`next_match`][Searcher::next_match] will overlap. + #[inline] + fn next_reject(&mut self) -> Option<(usize, usize)> { + loop { + match self.next() { + SearchStep::Reject(a, b) => return Some((a, b)), + SearchStep::Done => return None, + _ => continue, + } + } + } +} + +/// A reverse searcher for a string pattern. +/// +/// This trait provides methods for searching for non-overlapping +/// matches of a pattern starting from the back (right) of a string. +/// +/// It will be implemented by associated [`Searcher`] +/// types of the [`Pattern`] trait if the pattern supports searching +/// for it from the back. +/// +/// The index ranges returned by this trait are not required +/// to exactly match those of the forward search in reverse. +/// +/// For the reason why this trait is marked unsafe, see the +/// parent trait [`Searcher`]. +pub unsafe trait ReverseSearcher<'a>: Searcher<'a> { + /// Performs the next search step starting from the back. + /// + /// - Returns [`Match(a, b)`][SearchStep::Match] if `haystack[a..b]` + /// matches the pattern. + /// - Returns [`Reject(a, b)`][SearchStep::Reject] if `haystack[a..b]` + /// can not match the pattern, even partially. + /// - Returns [`Done`][SearchStep::Done] if every byte of the haystack + /// has been visited + /// + /// The stream of [`Match`][SearchStep::Match] and + /// [`Reject`][SearchStep::Reject] values up to a [`Done`][SearchStep::Done] + /// will contain index ranges that are adjacent, non-overlapping, + /// covering the whole haystack, and laying on utf8 boundaries. + /// + /// A [`Match`][SearchStep::Match] result needs to contain the whole matched + /// pattern, however [`Reject`][SearchStep::Reject] results may be split up + /// into arbitrary many adjacent fragments. Both ranges may have zero length. + /// + /// As an example, the pattern `"aaa"` and the haystack `"cbaaaaab"` + /// might produce the stream + /// `[Reject(7, 8), Match(4, 7), Reject(1, 4), Reject(0, 1)]`. + fn next_back(&mut self) -> SearchStep; + + /// Finds the next [`Match`][SearchStep::Match] result. + /// See [`next_back()`][ReverseSearcher::next_back]. + #[inline] + fn next_match_back(&mut self) -> Option<(usize, usize)> { + loop { + match self.next_back() { + SearchStep::Match(a, b) => return Some((a, b)), + SearchStep::Done => return None, + _ => continue, + } + } + } + + /// Finds the next [`Reject`][SearchStep::Reject] result. + /// See [`next_back()`][ReverseSearcher::next_back]. + #[inline] + fn next_reject_back(&mut self) -> Option<(usize, usize)> { + loop { + match self.next_back() { + SearchStep::Reject(a, b) => return Some((a, b)), + SearchStep::Done => return None, + _ => continue, + } + } + } +} + +/// A marker trait to express that a [`ReverseSearcher`] +/// can be used for a [`DoubleEndedIterator`] implementation. +/// +/// For this, the impl of [`Searcher`] and [`ReverseSearcher`] need +/// to follow these conditions: +/// +/// - All results of `next()` need to be identical +/// to the results of `next_back()` in reverse order. +/// - `next()` and `next_back()` need to behave as +/// the two ends of a range of values, that is they +/// can not "walk past each other". +/// +/// # Examples +/// +/// `char::Searcher` is a `DoubleEndedSearcher` because searching for a +/// [`char`] only requires looking at one at a time, which behaves the same +/// from both ends. +/// +/// `(&str)::Searcher` is not a `DoubleEndedSearcher` because +/// the pattern `"aa"` in the haystack `"aaa"` matches as either +/// `"[aa]a"` or `"a[aa]"`, depending on which side it is searched. +pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {} + +///////////////////////////////////////////////////////////////////////////// +// Impl for char +///////////////////////////////////////////////////////////////////////////// + +/// Associated type for `::Searcher<'a>`. +#[derive(Clone, Debug)] +pub struct CharSearcher<'a> { + haystack: &'a str, + // safety invariant: `finger`/`finger_back` must be a valid utf8 byte index of `haystack` + // This invariant can be broken *within* next_match and next_match_back, however + // they must exit with fingers on valid code point boundaries. + /// `finger` is the current byte index of the forward search. + /// Imagine that it exists before the byte at its index, i.e. + /// `haystack[finger]` is the first byte of the slice we must inspect during + /// forward searching + finger: usize, + /// `finger_back` is the current byte index of the reverse search. + /// Imagine that it exists after the byte at its index, i.e. + /// haystack[finger_back - 1] is the last byte of the slice we must inspect during + /// forward searching (and thus the first byte to be inspected when calling next_back()). + finger_back: usize, + /// The character being searched for + needle: char, + + // safety invariant: `utf8_size` must be less than 5 + /// The number of bytes `needle` takes up when encoded in utf8. + utf8_size: u8, + /// A utf8 encoded copy of the `needle` + utf8_encoded: [u8; 4], +} + +impl CharSearcher<'_> { + fn utf8_size(&self) -> usize { + self.utf8_size.into() + } +} + +unsafe impl<'a> Searcher<'a> for CharSearcher<'a> { + #[inline] + fn haystack(&self) -> &'a str { + self.haystack + } + #[inline] + fn next(&mut self) -> SearchStep { + let old_finger = self.finger; + // SAFETY: 1-4 guarantee safety of `get_unchecked` + // 1. `self.finger` and `self.finger_back` are kept on unicode boundaries + // (this is invariant) + // 2. `self.finger >= 0` since it starts at 0 and only increases + // 3. `self.finger < self.finger_back` because otherwise the char `iter` + // would return `SearchStep::Done` + // 4. `self.finger` comes before the end of the haystack because `self.finger_back` + // starts at the end and only decreases + let slice = unsafe { self.haystack.get_unchecked(old_finger..self.finger_back) }; + let mut iter = slice.chars(); + let old_len = iter.iter.len(); + if let Some(ch) = iter.next() { + // add byte offset of current character + // without re-encoding as utf-8 + self.finger += old_len - iter.iter.len(); + if ch == self.needle { + SearchStep::Match(old_finger, self.finger) + } else { + SearchStep::Reject(old_finger, self.finger) + } + } else { + SearchStep::Done + } + } + #[inline] + fn next_match(&mut self) -> Option<(usize, usize)> { + loop { + // get the haystack after the last character found + let bytes = self.haystack.as_bytes().get(self.finger..self.finger_back)?; + // the last byte of the utf8 encoded needle + // SAFETY: we have an invariant that `utf8_size < 5` + let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size() - 1) }; + if let Some(index) = memchr::memchr(last_byte, bytes) { + // The new finger is the index of the byte we found, + // plus one, since we memchr'd for the last byte of the character. + // + // Note that this doesn't always give us a finger on a UTF8 boundary. + // If we *didn't* find our character + // we may have indexed to the non-last byte of a 3-byte or 4-byte character. + // We can't just skip to the next valid starting byte because a character like + // ꁁ (U+A041 YI SYLLABLE PA), utf-8 `EA 81 81` will have us always find + // the second byte when searching for the third. + // + // However, this is totally okay. While we have the invariant that + // self.finger is on a UTF8 boundary, this invariant is not relied upon + // within this method (it is relied upon in CharSearcher::next()). + // + // We only exit this method when we reach the end of the string, or if we + // find something. When we find something the `finger` will be set + // to a UTF8 boundary. + self.finger += index + 1; + if self.finger >= self.utf8_size() { + let found_char = self.finger - self.utf8_size(); + if let Some(slice) = self.haystack.as_bytes().get(found_char..self.finger) { + if slice == &self.utf8_encoded[0..self.utf8_size()] { + return Some((found_char, self.finger)); + } + } + } + } else { + // found nothing, exit + self.finger = self.finger_back; + return None; + } + } + } + + // let next_reject use the default implementation from the Searcher trait +} + +unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> { + #[inline] + fn next_back(&mut self) -> SearchStep { + let old_finger = self.finger_back; + // SAFETY: see the comment for next() above + let slice = unsafe { self.haystack.get_unchecked(self.finger..old_finger) }; + let mut iter = slice.chars(); + let old_len = iter.iter.len(); + if let Some(ch) = iter.next_back() { + // subtract byte offset of current character + // without re-encoding as utf-8 + self.finger_back -= old_len - iter.iter.len(); + if ch == self.needle { + SearchStep::Match(self.finger_back, old_finger) + } else { + SearchStep::Reject(self.finger_back, old_finger) + } + } else { + SearchStep::Done + } + } + #[inline] + fn next_match_back(&mut self) -> Option<(usize, usize)> { + let haystack = self.haystack.as_bytes(); + loop { + // get the haystack up to but not including the last character searched + let bytes = haystack.get(self.finger..self.finger_back)?; + // the last byte of the utf8 encoded needle + // SAFETY: we have an invariant that `utf8_size < 5` + let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size() - 1) }; + if let Some(index) = memchr::memrchr(last_byte, bytes) { + // we searched a slice that was offset by self.finger, + // add self.finger to recoup the original index + let index = self.finger + index; + // memrchr will return the index of the byte we wish to + // find. In case of an ASCII character, this is indeed + // were we wish our new finger to be ("after" the found + // char in the paradigm of reverse iteration). For + // multibyte chars we need to skip down by the number of more + // bytes they have than ASCII + let shift = self.utf8_size() - 1; + if index >= shift { + let found_char = index - shift; + if let Some(slice) = haystack.get(found_char..(found_char + self.utf8_size())) { + if slice == &self.utf8_encoded[0..self.utf8_size()] { + // move finger to before the character found (i.e., at its start index) + self.finger_back = found_char; + return Some((self.finger_back, self.finger_back + self.utf8_size())); + } + } + } + // We can't use finger_back = index - size + 1 here. If we found the last char + // of a different-sized character (or the middle byte of a different character) + // we need to bump the finger_back down to `index`. This similarly makes + // `finger_back` have the potential to no longer be on a boundary, + // but this is OK since we only exit this function on a boundary + // or when the haystack has been searched completely. + // + // Unlike next_match this does not + // have the problem of repeated bytes in utf-8 because + // we're searching for the last byte, and we can only have + // found the last byte when searching in reverse. + self.finger_back = index; + } else { + self.finger_back = self.finger; + // found nothing, exit + return None; + } + } + } + + // let next_reject_back use the default implementation from the Searcher trait +} + +impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {} + +/// Searches for chars that are equal to a given [`char`]. +/// +/// # Examples +/// +/// ``` +/// assert_eq!("Hello world".find('o'), Some(4)); +/// ``` +impl Pattern for char { + type Searcher<'a> = CharSearcher<'a>; + + #[inline] + fn into_searcher(self, haystack: &str) -> Self::Searcher<'_> { + let mut utf8_encoded = [0; 4]; + let utf8_size = self + .encode_utf8(&mut utf8_encoded) + .len() + .try_into() + .expect("char len should be less than 255"); + + CharSearcher { + haystack, + finger: 0, + finger_back: haystack.len(), + needle: self, + utf8_size, + utf8_encoded, + } + } + + #[inline] + fn is_contained_in(self, haystack: &str) -> bool { + if (self as u32) < 128 { + haystack.as_bytes().contains(&(self as u8)) + } else { + let mut buffer = [0u8; 4]; + self.encode_utf8(&mut buffer).is_contained_in(haystack) + } + } + + #[inline] + fn is_prefix_of(self, haystack: &str) -> bool { + self.encode_utf8(&mut [0u8; 4]).is_prefix_of(haystack) + } + + #[inline] + fn strip_prefix_of(self, haystack: &str) -> Option<&str> { + self.encode_utf8(&mut [0u8; 4]).strip_prefix_of(haystack) + } + + #[inline] + fn is_suffix_of<'a>(self, haystack: &'a str) -> bool + where + Self::Searcher<'a>: ReverseSearcher<'a>, + { + self.encode_utf8(&mut [0u8; 4]).is_suffix_of(haystack) + } + + #[inline] + fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str> + where + Self::Searcher<'a>: ReverseSearcher<'a>, + { + self.encode_utf8(&mut [0u8; 4]).strip_suffix_of(haystack) + } + + #[inline] + fn as_utf8_pattern(&self) -> Option> { + Some(Utf8Pattern::CharPattern(*self)) + } +} + +///////////////////////////////////////////////////////////////////////////// +// Impl for a MultiCharEq wrapper +///////////////////////////////////////////////////////////////////////////// + +#[doc(hidden)] +trait MultiCharEq { + fn matches(&mut self, c: char) -> bool; +} + +impl MultiCharEq for F +where + F: FnMut(char) -> bool, +{ + #[inline] + fn matches(&mut self, c: char) -> bool { + (*self)(c) + } +} + +impl MultiCharEq for [char; N] { + #[inline] + fn matches(&mut self, c: char) -> bool { + self.iter().any(|&m| m == c) + } +} + +impl MultiCharEq for &[char; N] { + #[inline] + fn matches(&mut self, c: char) -> bool { + self.iter().any(|&m| m == c) + } +} + +impl MultiCharEq for &[char] { + #[inline] + fn matches(&mut self, c: char) -> bool { + self.iter().any(|&m| m == c) + } +} + +struct MultiCharEqPattern(C); + +#[derive(Clone, Debug)] +struct MultiCharEqSearcher<'a, C: MultiCharEq> { + char_eq: C, + haystack: &'a str, + char_indices: super::CharIndices<'a>, +} + +impl Pattern for MultiCharEqPattern { + type Searcher<'a> = MultiCharEqSearcher<'a, C>; + + #[inline] + fn into_searcher(self, haystack: &str) -> MultiCharEqSearcher<'_, C> { + MultiCharEqSearcher { haystack, char_eq: self.0, char_indices: haystack.char_indices() } + } +} + +unsafe impl<'a, C: MultiCharEq> Searcher<'a> for MultiCharEqSearcher<'a, C> { + #[inline] + fn haystack(&self) -> &'a str { + self.haystack + } + + #[inline] + fn next(&mut self) -> SearchStep { + let s = &mut self.char_indices; + // Compare lengths of the internal byte slice iterator + // to find length of current char + let pre_len = s.iter.iter.len(); + if let Some((i, c)) = s.next() { + let len = s.iter.iter.len(); + let char_len = pre_len - len; + if self.char_eq.matches(c) { + return SearchStep::Match(i, i + char_len); + } else { + return SearchStep::Reject(i, i + char_len); + } + } + SearchStep::Done + } +} + +unsafe impl<'a, C: MultiCharEq> ReverseSearcher<'a> for MultiCharEqSearcher<'a, C> { + #[inline] + fn next_back(&mut self) -> SearchStep { + let s = &mut self.char_indices; + // Compare lengths of the internal byte slice iterator + // to find length of current char + let pre_len = s.iter.iter.len(); + if let Some((i, c)) = s.next_back() { + let len = s.iter.iter.len(); + let char_len = pre_len - len; + if self.char_eq.matches(c) { + return SearchStep::Match(i, i + char_len); + } else { + return SearchStep::Reject(i, i + char_len); + } + } + SearchStep::Done + } +} + +impl<'a, C: MultiCharEq> DoubleEndedSearcher<'a> for MultiCharEqSearcher<'a, C> {} + +///////////////////////////////////////////////////////////////////////////// + +macro_rules! pattern_methods { + ($a:lifetime, $t:ty, $pmap:expr, $smap:expr) => { + type Searcher<$a> = $t; + + #[inline] + fn into_searcher<$a>(self, haystack: &$a str) -> $t { + ($smap)(($pmap)(self).into_searcher(haystack)) + } + + #[inline] + fn is_contained_in<$a>(self, haystack: &$a str) -> bool { + ($pmap)(self).is_contained_in(haystack) + } + + #[inline] + fn is_prefix_of<$a>(self, haystack: &$a str) -> bool { + ($pmap)(self).is_prefix_of(haystack) + } + + #[inline] + fn strip_prefix_of<$a>(self, haystack: &$a str) -> Option<&$a str> { + ($pmap)(self).strip_prefix_of(haystack) + } + + #[inline] + fn is_suffix_of<$a>(self, haystack: &$a str) -> bool + where + $t: ReverseSearcher<$a>, + { + ($pmap)(self).is_suffix_of(haystack) + } + + #[inline] + fn strip_suffix_of<$a>(self, haystack: &$a str) -> Option<&$a str> + where + $t: ReverseSearcher<$a>, + { + ($pmap)(self).strip_suffix_of(haystack) + } + }; +} + +macro_rules! searcher_methods { + (forward) => { + #[inline] + fn haystack(&self) -> &'a str { + self.0.haystack() + } + #[inline] + fn next(&mut self) -> SearchStep { + self.0.next() + } + #[inline] + fn next_match(&mut self) -> Option<(usize, usize)> { + self.0.next_match() + } + #[inline] + fn next_reject(&mut self) -> Option<(usize, usize)> { + self.0.next_reject() + } + }; + (reverse) => { + #[inline] + fn next_back(&mut self) -> SearchStep { + self.0.next_back() + } + #[inline] + fn next_match_back(&mut self) -> Option<(usize, usize)> { + self.0.next_match_back() + } + #[inline] + fn next_reject_back(&mut self) -> Option<(usize, usize)> { + self.0.next_reject_back() + } + }; +} + +/// Associated type for `<[char; N] as Pattern>::Searcher<'a>`. +#[derive(Clone, Debug)] +pub struct CharArraySearcher<'a, const N: usize>( + as Pattern>::Searcher<'a>, +); + +/// Associated type for `<&[char; N] as Pattern>::Searcher<'a>`. +#[derive(Clone, Debug)] +pub struct CharArrayRefSearcher<'a, 'b, const N: usize>( + as Pattern>::Searcher<'a>, +); + +/// Searches for chars that are equal to any of the [`char`]s in the array. +/// +/// # Examples +/// +/// ``` +/// assert_eq!("Hello world".find(['o', 'l']), Some(2)); +/// assert_eq!("Hello world".find(['h', 'w']), Some(6)); +/// ``` +impl Pattern for [char; N] { + pattern_methods!('a, CharArraySearcher<'a, N>, MultiCharEqPattern, CharArraySearcher); +} + +unsafe impl<'a, const N: usize> Searcher<'a> for CharArraySearcher<'a, N> { + searcher_methods!(forward); +} + +unsafe impl<'a, const N: usize> ReverseSearcher<'a> for CharArraySearcher<'a, N> { + searcher_methods!(reverse); +} + +impl<'a, const N: usize> DoubleEndedSearcher<'a> for CharArraySearcher<'a, N> {} + +/// Searches for chars that are equal to any of the [`char`]s in the array. +/// +/// # Examples +/// +/// ``` +/// assert_eq!("Hello world".find(&['o', 'l']), Some(2)); +/// assert_eq!("Hello world".find(&['h', 'w']), Some(6)); +/// ``` +impl<'b, const N: usize> Pattern for &'b [char; N] { + pattern_methods!('a, CharArrayRefSearcher<'a, 'b, N>, MultiCharEqPattern, CharArrayRefSearcher); +} + +unsafe impl<'a, 'b, const N: usize> Searcher<'a> for CharArrayRefSearcher<'a, 'b, N> { + searcher_methods!(forward); +} + +unsafe impl<'a, 'b, const N: usize> ReverseSearcher<'a> for CharArrayRefSearcher<'a, 'b, N> { + searcher_methods!(reverse); +} + +impl<'a, 'b, const N: usize> DoubleEndedSearcher<'a> for CharArrayRefSearcher<'a, 'b, N> {} + +///////////////////////////////////////////////////////////////////////////// +// Impl for &[char] +///////////////////////////////////////////////////////////////////////////// + +// Todo: Change / Remove due to ambiguity in meaning. + +/// Associated type for `<&[char] as Pattern>::Searcher<'a>`. +#[derive(Clone, Debug)] +pub struct CharSliceSearcher<'a, 'b>( as Pattern>::Searcher<'a>); + +unsafe impl<'a, 'b> Searcher<'a> for CharSliceSearcher<'a, 'b> { + searcher_methods!(forward); +} + +unsafe impl<'a, 'b> ReverseSearcher<'a> for CharSliceSearcher<'a, 'b> { + searcher_methods!(reverse); +} + +impl<'a, 'b> DoubleEndedSearcher<'a> for CharSliceSearcher<'a, 'b> {} + +/// Searches for chars that are equal to any of the [`char`]s in the slice. +/// +/// # Examples +/// +/// ``` +/// assert_eq!("Hello world".find(&['o', 'l'][..]), Some(2)); +/// assert_eq!("Hello world".find(&['h', 'w'][..]), Some(6)); +/// ``` +impl<'b> Pattern for &'b [char] { + pattern_methods!('a, CharSliceSearcher<'a, 'b>, MultiCharEqPattern, CharSliceSearcher); +} + +///////////////////////////////////////////////////////////////////////////// +// Impl for F: FnMut(char) -> bool +///////////////////////////////////////////////////////////////////////////// + +/// Associated type for `::Searcher<'a>`. +#[derive(Clone)] +pub struct CharPredicateSearcher<'a, F>( as Pattern>::Searcher<'a>) +where + F: FnMut(char) -> bool; + +impl fmt::Debug for CharPredicateSearcher<'_, F> +where + F: FnMut(char) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("CharPredicateSearcher") + .field("haystack", &self.0.haystack) + .field("char_indices", &self.0.char_indices) + .finish() + } +} +unsafe impl<'a, F> Searcher<'a> for CharPredicateSearcher<'a, F> +where + F: FnMut(char) -> bool, +{ + searcher_methods!(forward); +} + +unsafe impl<'a, F> ReverseSearcher<'a> for CharPredicateSearcher<'a, F> +where + F: FnMut(char) -> bool, +{ + searcher_methods!(reverse); +} + +impl<'a, F> DoubleEndedSearcher<'a> for CharPredicateSearcher<'a, F> where F: FnMut(char) -> bool {} + +/// Searches for [`char`]s that match the given predicate. +/// +/// # Examples +/// +/// ``` +/// assert_eq!("Hello world".find(char::is_uppercase), Some(0)); +/// assert_eq!("Hello world".find(|c| "aeiou".contains(c)), Some(1)); +/// ``` +impl Pattern for F +where + F: FnMut(char) -> bool, +{ + pattern_methods!('a, CharPredicateSearcher<'a, F>, MultiCharEqPattern, CharPredicateSearcher); +} + +///////////////////////////////////////////////////////////////////////////// +// Impl for &&str +///////////////////////////////////////////////////////////////////////////// + +/// Delegates to the `&str` impl. +impl<'b, 'c> Pattern for &'c &'b str { + pattern_methods!('a, StrSearcher<'a, 'b>, |&s| s, |s| s); +} + +///////////////////////////////////////////////////////////////////////////// +// Impl for &str +///////////////////////////////////////////////////////////////////////////// + +/// Non-allocating substring search. +/// +/// Will handle the pattern `""` as returning empty matches at each character +/// boundary. +/// +/// # Examples +/// +/// ``` +/// assert_eq!("Hello world".find("world"), Some(6)); +/// ``` +impl<'b> Pattern for &'b str { + type Searcher<'a> = StrSearcher<'a, 'b>; + + #[inline] + fn into_searcher(self, haystack: &str) -> StrSearcher<'_, 'b> { + StrSearcher::new(haystack, self) + } + + /// Checks whether the pattern matches at the front of the haystack. + #[inline] + fn is_prefix_of(self, haystack: &str) -> bool { + haystack.as_bytes().starts_with(self.as_bytes()) + } + + /// Checks whether the pattern matches anywhere in the haystack + #[inline] + fn is_contained_in(self, haystack: &str) -> bool { + if self.len() == 0 { + return true; + } + + match self.len().cmp(&haystack.len()) { + Ordering::Less => { + if self.len() == 1 { + return haystack.as_bytes().contains(&self.as_bytes()[0]); + } + + #[cfg(all(target_arch = "x86_64", target_feature = "sse2"))] + if self.len() <= 32 { + if let Some(result) = simd_contains(self, haystack) { + return result; + } + } + + self.into_searcher(haystack).next_match().is_some() + } + _ => self == haystack, + } + } + + /// Removes the pattern from the front of haystack, if it matches. + #[inline] + fn strip_prefix_of(self, haystack: &str) -> Option<&str> { + if self.is_prefix_of(haystack) { + // SAFETY: prefix was just verified to exist. + unsafe { Some(haystack.get_unchecked(self.as_bytes().len()..)) } + } else { + None + } + } + + /// Checks whether the pattern matches at the back of the haystack. + #[inline] + fn is_suffix_of<'a>(self, haystack: &'a str) -> bool + where + Self::Searcher<'a>: ReverseSearcher<'a>, + { + haystack.as_bytes().ends_with(self.as_bytes()) + } + + /// Removes the pattern from the back of haystack, if it matches. + #[inline] + fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str> + where + Self::Searcher<'a>: ReverseSearcher<'a>, + { + if self.is_suffix_of(haystack) { + let i = haystack.len() - self.as_bytes().len(); + // SAFETY: suffix was just verified to exist. + unsafe { Some(haystack.get_unchecked(..i)) } + } else { + None + } + } + + #[inline] + fn as_utf8_pattern(&self) -> Option> { + Some(Utf8Pattern::StringPattern(self.as_bytes())) + } +} + +///////////////////////////////////////////////////////////////////////////// +// Two Way substring searcher +///////////////////////////////////////////////////////////////////////////// + +#[derive(Clone, Debug)] +/// Associated type for `<&str as Pattern>::Searcher<'a>`. +pub struct StrSearcher<'a, 'b> { + haystack: &'a str, + needle: &'b str, + + searcher: StrSearcherImpl, +} + +#[derive(Clone, Debug)] +enum StrSearcherImpl { + Empty(EmptyNeedle), + TwoWay(TwoWaySearcher), +} + +#[derive(Clone, Debug)] +struct EmptyNeedle { + position: usize, + end: usize, + is_match_fw: bool, + is_match_bw: bool, + // Needed in case of an empty haystack, see #85462 + is_finished: bool, +} + +impl<'a, 'b> StrSearcher<'a, 'b> { + fn new(haystack: &'a str, needle: &'b str) -> StrSearcher<'a, 'b> { + if needle.is_empty() { + StrSearcher { + haystack, + needle, + searcher: StrSearcherImpl::Empty(EmptyNeedle { + position: 0, + end: haystack.len(), + is_match_fw: true, + is_match_bw: true, + is_finished: false, + }), + } + } else { + StrSearcher { + haystack, + needle, + searcher: StrSearcherImpl::TwoWay(TwoWaySearcher::new( + needle.as_bytes(), + haystack.len(), + )), + } + } + } +} + +unsafe impl<'a, 'b> Searcher<'a> for StrSearcher<'a, 'b> { + #[inline] + fn haystack(&self) -> &'a str { + self.haystack + } + + #[inline] + fn next(&mut self) -> SearchStep { + match self.searcher { + StrSearcherImpl::Empty(ref mut searcher) => { + if searcher.is_finished { + return SearchStep::Done; + } + // empty needle rejects every char and matches every empty string between them + let is_match = searcher.is_match_fw; + searcher.is_match_fw = !searcher.is_match_fw; + let pos = searcher.position; + match self.haystack[pos..].chars().next() { + _ if is_match => SearchStep::Match(pos, pos), + None => { + searcher.is_finished = true; + SearchStep::Done + } + Some(ch) => { + searcher.position += ch.len_utf8(); + SearchStep::Reject(pos, searcher.position) + } + } + } + StrSearcherImpl::TwoWay(ref mut searcher) => { + // TwoWaySearcher produces valid *Match* indices that split at char boundaries + // as long as it does correct matching and that haystack and needle are + // valid UTF-8 + // *Rejects* from the algorithm can fall on any indices, but we will walk them + // manually to the next character boundary, so that they are utf-8 safe. + if searcher.position == self.haystack.len() { + return SearchStep::Done; + } + let is_long = searcher.memory == usize::MAX; + match searcher.next::( + self.haystack.as_bytes(), + self.needle.as_bytes(), + is_long, + ) { + SearchStep::Reject(a, mut b) => { + // skip to next char boundary + while !self.haystack.is_char_boundary(b) { + b += 1; + } + searcher.position = cmp::max(b, searcher.position); + SearchStep::Reject(a, b) + } + otherwise => otherwise, + } + } + } + } + + #[inline] + fn next_match(&mut self) -> Option<(usize, usize)> { + match self.searcher { + StrSearcherImpl::Empty(..) => loop { + match self.next() { + SearchStep::Match(a, b) => return Some((a, b)), + SearchStep::Done => return None, + SearchStep::Reject(..) => {} + } + }, + StrSearcherImpl::TwoWay(ref mut searcher) => { + let is_long = searcher.memory == usize::MAX; + // write out `true` and `false` cases to encourage the compiler + // to specialize the two cases separately. + if is_long { + searcher.next::( + self.haystack.as_bytes(), + self.needle.as_bytes(), + true, + ) + } else { + searcher.next::( + self.haystack.as_bytes(), + self.needle.as_bytes(), + false, + ) + } + } + } + } +} + +unsafe impl<'a, 'b> ReverseSearcher<'a> for StrSearcher<'a, 'b> { + #[inline] + fn next_back(&mut self) -> SearchStep { + match self.searcher { + StrSearcherImpl::Empty(ref mut searcher) => { + if searcher.is_finished { + return SearchStep::Done; + } + let is_match = searcher.is_match_bw; + searcher.is_match_bw = !searcher.is_match_bw; + let end = searcher.end; + match self.haystack[..end].chars().next_back() { + _ if is_match => SearchStep::Match(end, end), + None => { + searcher.is_finished = true; + SearchStep::Done + } + Some(ch) => { + searcher.end -= ch.len_utf8(); + SearchStep::Reject(searcher.end, end) + } + } + } + StrSearcherImpl::TwoWay(ref mut searcher) => { + if searcher.end == 0 { + return SearchStep::Done; + } + let is_long = searcher.memory == usize::MAX; + match searcher.next_back::( + self.haystack.as_bytes(), + self.needle.as_bytes(), + is_long, + ) { + SearchStep::Reject(mut a, b) => { + // skip to next char boundary + while !self.haystack.is_char_boundary(a) { + a -= 1; + } + searcher.end = cmp::min(a, searcher.end); + SearchStep::Reject(a, b) + } + otherwise => otherwise, + } + } + } + } + + #[inline] + fn next_match_back(&mut self) -> Option<(usize, usize)> { + match self.searcher { + StrSearcherImpl::Empty(..) => loop { + match self.next_back() { + SearchStep::Match(a, b) => return Some((a, b)), + SearchStep::Done => return None, + SearchStep::Reject(..) => {} + } + }, + StrSearcherImpl::TwoWay(ref mut searcher) => { + let is_long = searcher.memory == usize::MAX; + // write out `true` and `false`, like `next_match` + if is_long { + searcher.next_back::( + self.haystack.as_bytes(), + self.needle.as_bytes(), + true, + ) + } else { + searcher.next_back::( + self.haystack.as_bytes(), + self.needle.as_bytes(), + false, + ) + } + } + } + } +} + +/// The internal state of the two-way substring search algorithm. +#[derive(Clone, Debug)] +struct TwoWaySearcher { + // constants + /// critical factorization index + crit_pos: usize, + /// critical factorization index for reversed needle + crit_pos_back: usize, + period: usize, + /// `byteset` is an extension (not part of the two way algorithm); + /// it's a 64-bit "fingerprint" where each set bit `j` corresponds + /// to a (byte & 63) == j present in the needle. + byteset: u64, + + // variables + position: usize, + end: usize, + /// index into needle before which we have already matched + memory: usize, + /// index into needle after which we have already matched + memory_back: usize, +} + +/* + This is the Two-Way search algorithm, which was introduced in the paper: + Crochemore, M., Perrin, D., 1991, Two-way string-matching, Journal of the ACM 38(3):651-675. + + Here's some background information. + + A *word* is a string of symbols. The *length* of a word should be a familiar + notion, and here we denote it for any word x by |x|. + (We also allow for the possibility of the *empty word*, a word of length zero). + + If x is any non-empty word, then an integer p with 0 < p <= |x| is said to be a + *period* for x iff for all i with 0 <= i <= |x| - p - 1, we have x[i] == x[i+p]. + For example, both 1 and 2 are periods for the string "aa". As another example, + the only period of the string "abcd" is 4. + + We denote by period(x) the *smallest* period of x (provided that x is non-empty). + This is always well-defined since every non-empty word x has at least one period, + |x|. We sometimes call this *the period* of x. + + If u, v and x are words such that x = uv, where uv is the concatenation of u and + v, then we say that (u, v) is a *factorization* of x. + + Let (u, v) be a factorization for a word x. Then if w is a non-empty word such + that both of the following hold + + - either w is a suffix of u or u is a suffix of w + - either w is a prefix of v or v is a prefix of w + + then w is said to be a *repetition* for the factorization (u, v). + + Just to unpack this, there are four possibilities here. Let w = "abc". Then we + might have: + + - w is a suffix of u and w is a prefix of v. ex: ("lolabc", "abcde") + - w is a suffix of u and v is a prefix of w. ex: ("lolabc", "ab") + - u is a suffix of w and w is a prefix of v. ex: ("bc", "abchi") + - u is a suffix of w and v is a prefix of w. ex: ("bc", "a") + + Note that the word vu is a repetition for any factorization (u,v) of x = uv, + so every factorization has at least one repetition. + + If x is a string and (u, v) is a factorization for x, then a *local period* for + (u, v) is an integer r such that there is some word w such that |w| = r and w is + a repetition for (u, v). + + We denote by local_period(u, v) the smallest local period of (u, v). We sometimes + call this *the local period* of (u, v). Provided that x = uv is non-empty, this + is well-defined (because each non-empty word has at least one factorization, as + noted above). + + It can be proven that the following is an equivalent definition of a local period + for a factorization (u, v): any positive integer r such that x[i] == x[i+r] for + all i such that |u| - r <= i <= |u| - 1 and such that both x[i] and x[i+r] are + defined. (i.e., i > 0 and i + r < |x|). + + Using the above reformulation, it is easy to prove that + + 1 <= local_period(u, v) <= period(uv) + + A factorization (u, v) of x such that local_period(u,v) = period(x) is called a + *critical factorization*. + + The algorithm hinges on the following theorem, which is stated without proof: + + **Critical Factorization Theorem** Any word x has at least one critical + factorization (u, v) such that |u| < period(x). + + The purpose of maximal_suffix is to find such a critical factorization. + + If the period is short, compute another factorization x = u' v' to use + for reverse search, chosen instead so that |v'| < period(x). + +*/ +impl TwoWaySearcher { + fn new(needle: &[u8], end: usize) -> TwoWaySearcher { + let (crit_pos_false, period_false) = TwoWaySearcher::maximal_suffix(needle, false); + let (crit_pos_true, period_true) = TwoWaySearcher::maximal_suffix(needle, true); + + let (crit_pos, period) = if crit_pos_false > crit_pos_true { + (crit_pos_false, period_false) + } else { + (crit_pos_true, period_true) + }; + + // A particularly readable explanation of what's going on here can be found + // in Crochemore and Rytter's book "Text Algorithms", ch 13. Specifically + // see the code for "Algorithm CP" on p. 323. + // + // What's going on is we have some critical factorization (u, v) of the + // needle, and we want to determine whether u is a suffix of + // &v[..period]. If it is, we use "Algorithm CP1". Otherwise we use + // "Algorithm CP2", which is optimized for when the period of the needle + // is large. + if needle[..crit_pos] == needle[period..period + crit_pos] { + // short period case -- the period is exact + // compute a separate critical factorization for the reversed needle + // x = u' v' where |v'| < period(x). + // + // This is sped up by the period being known already. + // Note that a case like x = "acba" may be factored exactly forwards + // (crit_pos = 1, period = 3) while being factored with approximate + // period in reverse (crit_pos = 2, period = 2). We use the given + // reverse factorization but keep the exact period. + let crit_pos_back = needle.len() + - cmp::max( + TwoWaySearcher::reverse_maximal_suffix(needle, period, false), + TwoWaySearcher::reverse_maximal_suffix(needle, period, true), + ); + + TwoWaySearcher { + crit_pos, + crit_pos_back, + period, + byteset: Self::byteset_create(&needle[..period]), + + position: 0, + end, + memory: 0, + memory_back: needle.len(), + } + } else { + // long period case -- we have an approximation to the actual period, + // and don't use memorization. + // + // Approximate the period by lower bound max(|u|, |v|) + 1. + // The critical factorization is efficient to use for both forward and + // reverse search. + + TwoWaySearcher { + crit_pos, + crit_pos_back: crit_pos, + period: cmp::max(crit_pos, needle.len() - crit_pos) + 1, + byteset: Self::byteset_create(needle), + + position: 0, + end, + memory: usize::MAX, // Dummy value to signify that the period is long + memory_back: usize::MAX, + } + } + } + + #[inline] + fn byteset_create(bytes: &[u8]) -> u64 { + bytes.iter().fold(0, |a, &b| (1 << (b & 0x3f)) | a) + } + + #[inline] + fn byteset_contains(&self, byte: u8) -> bool { + (self.byteset >> ((byte & 0x3f) as usize)) & 1 != 0 + } + + // One of the main ideas of Two-Way is that we factorize the needle into + // two halves, (u, v), and begin trying to find v in the haystack by scanning + // left to right. If v matches, we try to match u by scanning right to left. + // How far we can jump when we encounter a mismatch is all based on the fact + // that (u, v) is a critical factorization for the needle. + #[inline] + fn next(&mut self, haystack: &[u8], needle: &[u8], long_period: bool) -> S::Output + where + S: TwoWayStrategy, + { + // `next()` uses `self.position` as its cursor + let old_pos = self.position; + let needle_last = needle.len() - 1; + 'search: loop { + // Check that we have room to search in + // position + needle_last can not overflow if we assume slices + // are bounded by isize's range. + let tail_byte = match haystack.get(self.position + needle_last) { + Some(&b) => b, + None => { + self.position = haystack.len(); + return S::rejecting(old_pos, self.position); + } + }; + + if S::use_early_reject() && old_pos != self.position { + return S::rejecting(old_pos, self.position); + } + + // Quickly skip by large portions unrelated to our substring + if !self.byteset_contains(tail_byte) { + self.position += needle.len(); + if !long_period { + self.memory = 0; + } + continue 'search; + } + + // See if the right part of the needle matches + let start = + if long_period { self.crit_pos } else { cmp::max(self.crit_pos, self.memory) }; + for i in start..needle.len() { + if needle[i] != haystack[self.position + i] { + self.position += i - self.crit_pos + 1; + if !long_period { + self.memory = 0; + } + continue 'search; + } + } + + // See if the left part of the needle matches + let start = if long_period { 0 } else { self.memory }; + for i in (start..self.crit_pos).rev() { + if needle[i] != haystack[self.position + i] { + self.position += self.period; + if !long_period { + self.memory = needle.len() - self.period; + } + continue 'search; + } + } + + // We have found a match! + let match_pos = self.position; + + // Note: add self.period instead of needle.len() to have overlapping matches + self.position += needle.len(); + if !long_period { + self.memory = 0; // set to needle.len() - self.period for overlapping matches + } + + return S::matching(match_pos, match_pos + needle.len()); + } + } + + // Follows the ideas in `next()`. + // + // The definitions are symmetrical, with period(x) = period(reverse(x)) + // and local_period(u, v) = local_period(reverse(v), reverse(u)), so if (u, v) + // is a critical factorization, so is (reverse(v), reverse(u)). + // + // For the reverse case we have computed a critical factorization x = u' v' + // (field `crit_pos_back`). We need |u| < period(x) for the forward case and + // thus |v'| < period(x) for the reverse. + // + // To search in reverse through the haystack, we search forward through + // a reversed haystack with a reversed needle, matching first u' and then v'. + #[inline] + fn next_back(&mut self, haystack: &[u8], needle: &[u8], long_period: bool) -> S::Output + where + S: TwoWayStrategy, + { + // `next_back()` uses `self.end` as its cursor -- so that `next()` and `next_back()` + // are independent. + let old_end = self.end; + 'search: loop { + // Check that we have room to search in + // end - needle.len() will wrap around when there is no more room, + // but due to slice length limits it can never wrap all the way back + // into the length of haystack. + let front_byte = match haystack.get(self.end.wrapping_sub(needle.len())) { + Some(&b) => b, + None => { + self.end = 0; + return S::rejecting(0, old_end); + } + }; + + if S::use_early_reject() && old_end != self.end { + return S::rejecting(self.end, old_end); + } + + // Quickly skip by large portions unrelated to our substring + if !self.byteset_contains(front_byte) { + self.end -= needle.len(); + if !long_period { + self.memory_back = needle.len(); + } + continue 'search; + } + + // See if the left part of the needle matches + let crit = if long_period { + self.crit_pos_back + } else { + cmp::min(self.crit_pos_back, self.memory_back) + }; + for i in (0..crit).rev() { + if needle[i] != haystack[self.end - needle.len() + i] { + self.end -= self.crit_pos_back - i; + if !long_period { + self.memory_back = needle.len(); + } + continue 'search; + } + } + + // See if the right part of the needle matches + let needle_end = if long_period { needle.len() } else { self.memory_back }; + for i in self.crit_pos_back..needle_end { + if needle[i] != haystack[self.end - needle.len() + i] { + self.end -= self.period; + if !long_period { + self.memory_back = self.period; + } + continue 'search; + } + } + + // We have found a match! + let match_pos = self.end - needle.len(); + // Note: sub self.period instead of needle.len() to have overlapping matches + self.end -= needle.len(); + if !long_period { + self.memory_back = needle.len(); + } + + return S::matching(match_pos, match_pos + needle.len()); + } + } + + // Compute the maximal suffix of `arr`. + // + // The maximal suffix is a possible critical factorization (u, v) of `arr`. + // + // Returns (`i`, `p`) where `i` is the starting index of v and `p` is the + // period of v. + // + // `order_greater` determines if lexical order is `<` or `>`. Both + // orders must be computed -- the ordering with the largest `i` gives + // a critical factorization. + // + // For long period cases, the resulting period is not exact (it is too short). + #[inline] + fn maximal_suffix(arr: &[u8], order_greater: bool) -> (usize, usize) { + let mut left = 0; // Corresponds to i in the paper + let mut right = 1; // Corresponds to j in the paper + let mut offset = 0; // Corresponds to k in the paper, but starting at 0 + // to match 0-based indexing. + let mut period = 1; // Corresponds to p in the paper + + while let Some(&a) = arr.get(right + offset) { + // `left` will be inbounds when `right` is. + let b = arr[left + offset]; + if (a < b && !order_greater) || (a > b && order_greater) { + // Suffix is smaller, period is entire prefix so far. + right += offset + 1; + offset = 0; + period = right - left; + } else if a == b { + // Advance through repetition of the current period. + if offset + 1 == period { + right += offset + 1; + offset = 0; + } else { + offset += 1; + } + } else { + // Suffix is larger, start over from current location. + left = right; + right += 1; + offset = 0; + period = 1; + } + } + (left, period) + } + + // Compute the maximal suffix of the reverse of `arr`. + // + // The maximal suffix is a possible critical factorization (u', v') of `arr`. + // + // Returns `i` where `i` is the starting index of v', from the back; + // returns immediately when a period of `known_period` is reached. + // + // `order_greater` determines if lexical order is `<` or `>`. Both + // orders must be computed -- the ordering with the largest `i` gives + // a critical factorization. + // + // For long period cases, the resulting period is not exact (it is too short). + fn reverse_maximal_suffix(arr: &[u8], known_period: usize, order_greater: bool) -> usize { + let mut left = 0; // Corresponds to i in the paper + let mut right = 1; // Corresponds to j in the paper + let mut offset = 0; // Corresponds to k in the paper, but starting at 0 + // to match 0-based indexing. + let mut period = 1; // Corresponds to p in the paper + let n = arr.len(); + + while right + offset < n { + let a = arr[n - (1 + right + offset)]; + let b = arr[n - (1 + left + offset)]; + if (a < b && !order_greater) || (a > b && order_greater) { + // Suffix is smaller, period is entire prefix so far. + right += offset + 1; + offset = 0; + period = right - left; + } else if a == b { + // Advance through repetition of the current period. + if offset + 1 == period { + right += offset + 1; + offset = 0; + } else { + offset += 1; + } + } else { + // Suffix is larger, start over from current location. + left = right; + right += 1; + offset = 0; + period = 1; + } + if period == known_period { + break; + } + } + debug_assert!(period <= known_period); + left + } +} + +// TwoWayStrategy allows the algorithm to either skip non-matches as quickly +// as possible, or to work in a mode where it emits Rejects relatively quickly. +trait TwoWayStrategy { + type Output; + fn use_early_reject() -> bool; + fn rejecting(a: usize, b: usize) -> Self::Output; + fn matching(a: usize, b: usize) -> Self::Output; +} + +/// Skip to match intervals as quickly as possible +enum MatchOnly {} + +impl TwoWayStrategy for MatchOnly { + type Output = Option<(usize, usize)>; + + #[inline] + fn use_early_reject() -> bool { + false + } + #[inline] + fn rejecting(_a: usize, _b: usize) -> Self::Output { + None + } + #[inline] + fn matching(a: usize, b: usize) -> Self::Output { + Some((a, b)) + } +} + +/// Emit Rejects regularly +enum RejectAndMatch {} + +impl TwoWayStrategy for RejectAndMatch { + type Output = SearchStep; + + #[inline] + fn use_early_reject() -> bool { + true + } + #[inline] + fn rejecting(a: usize, b: usize) -> Self::Output { + SearchStep::Reject(a, b) + } + #[inline] + fn matching(a: usize, b: usize) -> Self::Output { + SearchStep::Match(a, b) + } +} + +/// SIMD search for short needles based on +/// Wojciech Muła's "SIMD-friendly algorithms for substring searching"[0] +/// +/// It skips ahead by the vector width on each iteration (rather than the needle length as two-way +/// does) by probing the first and last byte of the needle for the whole vector width +/// and only doing full needle comparisons when the vectorized probe indicated potential matches. +/// +/// Since the x86_64 baseline only offers SSE2 we only use u8x16 here. +/// If we ever ship std with for x86-64-v3 or adapt this for other platforms then wider vectors +/// should be evaluated. +/// +/// For haystacks smaller than vector-size + needle length it falls back to +/// a naive O(n*m) search so this implementation should not be called on larger needles. +/// +/// [0]: http://0x80.pl/articles/simd-strfind.html#sse-avx2 +#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))] +#[inline] +fn simd_contains(needle: &str, haystack: &str) -> Option { + let needle = needle.as_bytes(); + let haystack = haystack.as_bytes(); + + debug_assert!(needle.len() > 1); + + use crate::ops::BitAnd; + use crate::simd::cmp::SimdPartialEq; + use crate::simd::{mask8x16 as Mask, u8x16 as Block}; + + let first_probe = needle[0]; + let last_byte_offset = needle.len() - 1; + + // the offset used for the 2nd vector + let second_probe_offset = if needle.len() == 2 { + // never bail out on len=2 needles because the probes will fully cover them and have + // no degenerate cases. + 1 + } else { + // try a few bytes in case first and last byte of the needle are the same + let Some(second_probe_offset) = + (needle.len().saturating_sub(4)..needle.len()).rfind(|&idx| needle[idx] != first_probe) + else { + // fall back to other search methods if we can't find any different bytes + // since we could otherwise hit some degenerate cases + return None; + }; + second_probe_offset + }; + + // do a naive search if the haystack is too small to fit + if haystack.len() < Block::LEN + last_byte_offset { + return Some(haystack.windows(needle.len()).any(|c| c == needle)); + } + + let first_probe: Block = Block::splat(first_probe); + let second_probe: Block = Block::splat(needle[second_probe_offset]); + // first byte are already checked by the outer loop. to verify a match only the + // remainder has to be compared. + let trimmed_needle = &needle[1..]; + + // this #[cold] is load-bearing, benchmark before removing it... + let check_mask = #[cold] + |idx, mask: u16, skip: bool| -> bool { + if skip { + return false; + } + + // and so is this. optimizations are weird. + let mut mask = mask; + + while mask != 0 { + let trailing = mask.trailing_zeros(); + let offset = idx + trailing as usize + 1; + // SAFETY: mask is between 0 and 15 trailing zeroes, we skip one additional byte that was already compared + // and then take trimmed_needle.len() bytes. This is within the bounds defined by the outer loop + unsafe { + let sub = haystack.get_unchecked(offset..).get_unchecked(..trimmed_needle.len()); + if small_slice_eq(sub, trimmed_needle) { + return true; + } + } + mask &= !(1 << trailing); + } + false + }; + + let test_chunk = |idx| -> u16 { + // SAFETY: this requires at least LANES bytes being readable at idx + // that is ensured by the loop ranges (see comments below) + let a: Block = unsafe { haystack.as_ptr().add(idx).cast::().read_unaligned() }; + // SAFETY: this requires LANES + block_offset bytes being readable at idx + let b: Block = unsafe { + haystack.as_ptr().add(idx).add(second_probe_offset).cast::().read_unaligned() + }; + let eq_first: Mask = a.simd_eq(first_probe); + let eq_last: Mask = b.simd_eq(second_probe); + let both = eq_first.bitand(eq_last); + let mask = both.to_bitmask() as u16; + + mask + }; + + let mut i = 0; + let mut result = false; + // The loop condition must ensure that there's enough headroom to read LANE bytes, + // and not only at the current index but also at the index shifted by block_offset + const UNROLL: usize = 4; + while i + last_byte_offset + UNROLL * Block::LEN < haystack.len() && !result { + let mut masks = [0u16; UNROLL]; + for j in 0..UNROLL { + masks[j] = test_chunk(i + j * Block::LEN); + } + for j in 0..UNROLL { + let mask = masks[j]; + if mask != 0 { + result |= check_mask(i + j * Block::LEN, mask, result); + } + } + i += UNROLL * Block::LEN; + } + while i + last_byte_offset + Block::LEN < haystack.len() && !result { + let mask = test_chunk(i); + if mask != 0 { + result |= check_mask(i, mask, result); + } + i += Block::LEN; + } + + // Process the tail that didn't fit into LANES-sized steps. + // This simply repeats the same procedure but as right-aligned chunk instead + // of a left-aligned one. The last byte must be exactly flush with the string end so + // we don't miss a single byte or read out of bounds. + let i = haystack.len() - last_byte_offset - Block::LEN; + let mask = test_chunk(i); + if mask != 0 { + result |= check_mask(i, mask, result); + } + + Some(result) +} + +/// Compares short slices for equality. +/// +/// It avoids a call to libc's memcmp which is faster on long slices +/// due to SIMD optimizations but it incurs a function call overhead. +/// +/// # Safety +/// +/// Both slices must have the same length. +#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))] // only called on x86 +#[inline] +unsafe fn small_slice_eq(x: &[u8], y: &[u8]) -> bool { + debug_assert_eq!(x.len(), y.len()); + // This function is adapted from + // https://github.com/BurntSushi/memchr/blob/8037d11b4357b0f07be2bb66dc2659d9cf28ad32/src/memmem/util.rs#L32 + + // If we don't have enough bytes to do 4-byte at a time loads, then + // fall back to the naive slow version. + // + // Potential alternative: We could do a copy_nonoverlapping combined with a mask instead + // of a loop. Benchmark it. + if x.len() < 4 { + for (&b1, &b2) in x.iter().zip(y) { + if b1 != b2 { + return false; + } + } + return true; + } + // When we have 4 or more bytes to compare, then proceed in chunks of 4 at + // a time using unaligned loads. + // + // Also, why do 4 byte loads instead of, say, 8 byte loads? The reason is + // that this particular version of memcmp is likely to be called with tiny + // needles. That means that if we do 8 byte loads, then a higher proportion + // of memcmp calls will use the slower variant above. With that said, this + // is a hypothesis and is only loosely supported by benchmarks. There's + // likely some improvement that could be made here. The main thing here + // though is to optimize for latency, not throughput. + + // SAFETY: Via the conditional above, we know that both `px` and `py` + // have the same length, so `px < pxend` implies that `py < pyend`. + // Thus, dereferencing both `px` and `py` in the loop below is safe. + // + // Moreover, we set `pxend` and `pyend` to be 4 bytes before the actual + // end of `px` and `py`. Thus, the final dereference outside of the + // loop is guaranteed to be valid. (The final comparison will overlap with + // the last comparison done in the loop for lengths that aren't multiples + // of four.) + // + // Finally, we needn't worry about alignment here, since we do unaligned + // loads. + unsafe { + let (mut px, mut py) = (x.as_ptr(), y.as_ptr()); + let (pxend, pyend) = (px.add(x.len() - 4), py.add(y.len() - 4)); + while px < pxend { + let vx = (px as *const u32).read_unaligned(); + let vy = (py as *const u32).read_unaligned(); + if vx != vy { + return false; + } + px = px.add(4); + py = py.add(4); + } + let vx = (pxend as *const u32).read_unaligned(); + let vy = (pyend as *const u32).read_unaligned(); + vx == vy + } +} diff --git a/CoqOfRust/core/str/traits.rs b/CoqOfRust/core/str/traits.rs new file mode 100644 index 000000000..77c70b978 --- /dev/null +++ b/CoqOfRust/core/str/traits.rs @@ -0,0 +1,860 @@ +//! Trait implementations for `str`. + +use super::ParseBoolError; +use crate::cmp::Ordering; +use crate::intrinsics::unchecked_sub; +use crate::slice::SliceIndex; +use crate::ub_checks::assert_unsafe_precondition; +use crate::{ops, ptr, range}; + +/// Implements ordering of strings. +/// +/// Strings are ordered [lexicographically](Ord#lexicographical-comparison) by their byte values. This orders Unicode code +/// points based on their positions in the code charts. This is not necessarily the same as +/// "alphabetical" order, which varies by language and locale. Sorting strings according to +/// culturally-accepted standards requires locale-specific data that is outside the scope of +/// the `str` type. +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for str { + #[inline] + fn cmp(&self, other: &str) -> Ordering { + self.as_bytes().cmp(other.as_bytes()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for str { + #[inline] + fn eq(&self, other: &str) -> bool { + self.as_bytes() == other.as_bytes() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for str {} + +/// Implements comparison operations on strings. +/// +/// Strings are compared [lexicographically](Ord#lexicographical-comparison) by their byte values. This compares Unicode code +/// points based on their positions in the code charts. This is not necessarily the same as +/// "alphabetical" order, which varies by language and locale. Comparing strings according to +/// culturally-accepted standards requires locale-specific data that is outside the scope of +/// the `str` type. +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for str { + #[inline] + fn partial_cmp(&self, other: &str) -> Option { + Some(self.cmp(other)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Index for str +where + I: SliceIndex, +{ + type Output = I::Output; + + #[inline] + fn index(&self, index: I) -> &I::Output { + index.index(self) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::IndexMut for str +where + I: SliceIndex, +{ + #[inline] + fn index_mut(&mut self, index: I) -> &mut I::Output { + index.index_mut(self) + } +} + +#[inline(never)] +#[cold] +#[track_caller] +const fn str_index_overflow_fail() -> ! { + panic!("attempted to index str up to maximum usize"); +} + +/// Implements substring slicing with syntax `&self[..]` or `&mut self[..]`. +/// +/// Returns a slice of the whole string, i.e., returns `&self` or `&mut +/// self`. Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. Unlike +/// other indexing operations, this can never panic. +/// +/// This operation is *O*(1). +/// +/// Prior to 1.20.0, these indexing operations were still supported by +/// direct implementation of `Index` and `IndexMut`. +/// +/// Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. +#[stable(feature = "str_checked_slicing", since = "1.20.0")] +unsafe impl SliceIndex for ops::RangeFull { + type Output = str; + #[inline] + fn get(self, slice: &str) -> Option<&Self::Output> { + Some(slice) + } + #[inline] + fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { + Some(slice) + } + #[inline] + unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { + slice + } + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { + slice + } + #[inline] + fn index(self, slice: &str) -> &Self::Output { + slice + } + #[inline] + fn index_mut(self, slice: &mut str) -> &mut Self::Output { + slice + } +} + +/// Implements substring slicing with syntax `&self[begin .. end]` or `&mut +/// self[begin .. end]`. +/// +/// Returns a slice of the given string from the byte range +/// [`begin`, `end`). +/// +/// This operation is *O*(1). +/// +/// Prior to 1.20.0, these indexing operations were still supported by +/// direct implementation of `Index` and `IndexMut`. +/// +/// # Panics +/// +/// Panics if `begin` or `end` does not point to the starting byte offset of +/// a character (as defined by `is_char_boundary`), if `begin > end`, or if +/// `end > len`. +/// +/// # Examples +/// +/// ``` +/// let s = "Löwe 老虎 Léopard"; +/// assert_eq!(&s[0 .. 1], "L"); +/// +/// assert_eq!(&s[1 .. 9], "öwe 老"); +/// +/// // these will panic: +/// // byte 2 lies within `ö`: +/// // &s[2 ..3]; +/// +/// // byte 8 lies within `老` +/// // &s[1 .. 8]; +/// +/// // byte 100 is outside the string +/// // &s[3 .. 100]; +/// ``` +#[stable(feature = "str_checked_slicing", since = "1.20.0")] +unsafe impl SliceIndex for ops::Range { + type Output = str; + #[inline] + fn get(self, slice: &str) -> Option<&Self::Output> { + if self.start <= self.end + && slice.is_char_boundary(self.start) + && slice.is_char_boundary(self.end) + { + // SAFETY: just checked that `start` and `end` are on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + // We also checked char boundaries, so this is valid UTF-8. + Some(unsafe { &*self.get_unchecked(slice) }) + } else { + None + } + } + #[inline] + fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { + if self.start <= self.end + && slice.is_char_boundary(self.start) + && slice.is_char_boundary(self.end) + { + // SAFETY: just checked that `start` and `end` are on a char boundary. + // We know the pointer is unique because we got it from `slice`. + Some(unsafe { &mut *self.get_unchecked_mut(slice) }) + } else { + None + } + } + #[inline] + unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { + let slice = slice as *const [u8]; + + assert_unsafe_precondition!( + // We'd like to check that the bounds are on char boundaries, + // but there's not really a way to do so without reading + // behind the pointer, which has aliasing implications. + // It's also not possible to move this check up to + // `str::get_unchecked` without adding a special function + // to `SliceIndex` just for this. + check_library_ub, + "str::get_unchecked requires that the range is within the string slice", + ( + start: usize = self.start, + end: usize = self.end, + len: usize = slice.len() + ) => end >= start && end <= len, + ); + + // SAFETY: the caller guarantees that `self` is in bounds of `slice` + // which satisfies all the conditions for `add`. + unsafe { + let new_len = unchecked_sub(self.end, self.start); + ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) as *const str + } + } + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { + let slice = slice as *mut [u8]; + + assert_unsafe_precondition!( + check_library_ub, + "str::get_unchecked_mut requires that the range is within the string slice", + ( + start: usize = self.start, + end: usize = self.end, + len: usize = slice.len() + ) => end >= start && end <= len, + ); + + // SAFETY: see comments for `get_unchecked`. + unsafe { + let new_len = unchecked_sub(self.end, self.start); + ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) as *mut str + } + } + #[inline] + fn index(self, slice: &str) -> &Self::Output { + let (start, end) = (self.start, self.end); + match self.get(slice) { + Some(s) => s, + None => super::slice_error_fail(slice, start, end), + } + } + #[inline] + fn index_mut(self, slice: &mut str) -> &mut Self::Output { + // is_char_boundary checks that the index is in [0, .len()] + // cannot reuse `get` as above, because of NLL trouble + if self.start <= self.end + && slice.is_char_boundary(self.start) + && slice.is_char_boundary(self.end) + { + // SAFETY: just checked that `start` and `end` are on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + unsafe { &mut *self.get_unchecked_mut(slice) } + } else { + super::slice_error_fail(slice, self.start, self.end) + } + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +unsafe impl SliceIndex for range::Range { + type Output = str; + #[inline] + fn get(self, slice: &str) -> Option<&Self::Output> { + if self.start <= self.end + && slice.is_char_boundary(self.start) + && slice.is_char_boundary(self.end) + { + // SAFETY: just checked that `start` and `end` are on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + // We also checked char boundaries, so this is valid UTF-8. + Some(unsafe { &*self.get_unchecked(slice) }) + } else { + None + } + } + #[inline] + fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { + if self.start <= self.end + && slice.is_char_boundary(self.start) + && slice.is_char_boundary(self.end) + { + // SAFETY: just checked that `start` and `end` are on a char boundary. + // We know the pointer is unique because we got it from `slice`. + Some(unsafe { &mut *self.get_unchecked_mut(slice) }) + } else { + None + } + } + #[inline] + unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { + let slice = slice as *const [u8]; + + assert_unsafe_precondition!( + // We'd like to check that the bounds are on char boundaries, + // but there's not really a way to do so without reading + // behind the pointer, which has aliasing implications. + // It's also not possible to move this check up to + // `str::get_unchecked` without adding a special function + // to `SliceIndex` just for this. + check_library_ub, + "str::get_unchecked requires that the range is within the string slice", + ( + start: usize = self.start, + end: usize = self.end, + len: usize = slice.len() + ) => end >= start && end <= len, + ); + + // SAFETY: the caller guarantees that `self` is in bounds of `slice` + // which satisfies all the conditions for `add`. + unsafe { + let new_len = unchecked_sub(self.end, self.start); + ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) as *const str + } + } + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { + let slice = slice as *mut [u8]; + + assert_unsafe_precondition!( + check_library_ub, + "str::get_unchecked_mut requires that the range is within the string slice", + ( + start: usize = self.start, + end: usize = self.end, + len: usize = slice.len() + ) => end >= start && end <= len, + ); + + // SAFETY: see comments for `get_unchecked`. + unsafe { + let new_len = unchecked_sub(self.end, self.start); + ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) as *mut str + } + } + #[inline] + fn index(self, slice: &str) -> &Self::Output { + let (start, end) = (self.start, self.end); + match self.get(slice) { + Some(s) => s, + None => super::slice_error_fail(slice, start, end), + } + } + #[inline] + fn index_mut(self, slice: &mut str) -> &mut Self::Output { + // is_char_boundary checks that the index is in [0, .len()] + // cannot reuse `get` as above, because of NLL trouble + if self.start <= self.end + && slice.is_char_boundary(self.start) + && slice.is_char_boundary(self.end) + { + // SAFETY: just checked that `start` and `end` are on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + unsafe { &mut *self.get_unchecked_mut(slice) } + } else { + super::slice_error_fail(slice, self.start, self.end) + } + } +} + +/// Implements substring slicing for arbitrary bounds. +/// +/// Returns a slice of the given string bounded by the byte indices +/// provided by each bound. +/// +/// This operation is *O*(1). +/// +/// # Panics +/// +/// Panics if `begin` or `end` (if it exists and once adjusted for +/// inclusion/exclusion) does not point to the starting byte offset of +/// a character (as defined by `is_char_boundary`), if `begin > end`, or if +/// `end > len`. +#[stable(feature = "slice_index_str_with_ops_bound_pair", since = "1.73.0")] +unsafe impl SliceIndex for (ops::Bound, ops::Bound) { + type Output = str; + + #[inline] + fn get(self, slice: &str) -> Option<&str> { + crate::slice::index::into_range(slice.len(), self)?.get(slice) + } + + #[inline] + fn get_mut(self, slice: &mut str) -> Option<&mut str> { + crate::slice::index::into_range(slice.len(), self)?.get_mut(slice) + } + + #[inline] + unsafe fn get_unchecked(self, slice: *const str) -> *const str { + let len = (slice as *const [u8]).len(); + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { crate::slice::index::into_range_unchecked(len, self).get_unchecked(slice) } + } + + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut str { + let len = (slice as *mut [u8]).len(); + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { crate::slice::index::into_range_unchecked(len, self).get_unchecked_mut(slice) } + } + + #[inline] + fn index(self, slice: &str) -> &str { + crate::slice::index::into_slice_range(slice.len(), self).index(slice) + } + + #[inline] + fn index_mut(self, slice: &mut str) -> &mut str { + crate::slice::index::into_slice_range(slice.len(), self).index_mut(slice) + } +} + +/// Implements substring slicing with syntax `&self[.. end]` or `&mut +/// self[.. end]`. +/// +/// Returns a slice of the given string from the byte range \[0, `end`). +/// Equivalent to `&self[0 .. end]` or `&mut self[0 .. end]`. +/// +/// This operation is *O*(1). +/// +/// Prior to 1.20.0, these indexing operations were still supported by +/// direct implementation of `Index` and `IndexMut`. +/// +/// # Panics +/// +/// Panics if `end` does not point to the starting byte offset of a +/// character (as defined by `is_char_boundary`), or if `end > len`. +#[stable(feature = "str_checked_slicing", since = "1.20.0")] +unsafe impl SliceIndex for ops::RangeTo { + type Output = str; + #[inline] + fn get(self, slice: &str) -> Option<&Self::Output> { + if slice.is_char_boundary(self.end) { + // SAFETY: just checked that `end` is on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + Some(unsafe { &*self.get_unchecked(slice) }) + } else { + None + } + } + #[inline] + fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { + if slice.is_char_boundary(self.end) { + // SAFETY: just checked that `end` is on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + Some(unsafe { &mut *self.get_unchecked_mut(slice) }) + } else { + None + } + } + #[inline] + unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (0..self.end).get_unchecked(slice) } + } + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (0..self.end).get_unchecked_mut(slice) } + } + #[inline] + fn index(self, slice: &str) -> &Self::Output { + let end = self.end; + match self.get(slice) { + Some(s) => s, + None => super::slice_error_fail(slice, 0, end), + } + } + #[inline] + fn index_mut(self, slice: &mut str) -> &mut Self::Output { + if slice.is_char_boundary(self.end) { + // SAFETY: just checked that `end` is on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + unsafe { &mut *self.get_unchecked_mut(slice) } + } else { + super::slice_error_fail(slice, 0, self.end) + } + } +} + +/// Implements substring slicing with syntax `&self[begin ..]` or `&mut +/// self[begin ..]`. +/// +/// Returns a slice of the given string from the byte range \[`begin`, `len`). +/// Equivalent to `&self[begin .. len]` or `&mut self[begin .. len]`. +/// +/// This operation is *O*(1). +/// +/// Prior to 1.20.0, these indexing operations were still supported by +/// direct implementation of `Index` and `IndexMut`. +/// +/// # Panics +/// +/// Panics if `begin` does not point to the starting byte offset of +/// a character (as defined by `is_char_boundary`), or if `begin > len`. +#[stable(feature = "str_checked_slicing", since = "1.20.0")] +unsafe impl SliceIndex for ops::RangeFrom { + type Output = str; + #[inline] + fn get(self, slice: &str) -> Option<&Self::Output> { + if slice.is_char_boundary(self.start) { + // SAFETY: just checked that `start` is on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + Some(unsafe { &*self.get_unchecked(slice) }) + } else { + None + } + } + #[inline] + fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { + if slice.is_char_boundary(self.start) { + // SAFETY: just checked that `start` is on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + Some(unsafe { &mut *self.get_unchecked_mut(slice) }) + } else { + None + } + } + #[inline] + unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { + let len = (slice as *const [u8]).len(); + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (self.start..len).get_unchecked(slice) } + } + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { + let len = (slice as *mut [u8]).len(); + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (self.start..len).get_unchecked_mut(slice) } + } + #[inline] + fn index(self, slice: &str) -> &Self::Output { + let (start, end) = (self.start, slice.len()); + match self.get(slice) { + Some(s) => s, + None => super::slice_error_fail(slice, start, end), + } + } + #[inline] + fn index_mut(self, slice: &mut str) -> &mut Self::Output { + if slice.is_char_boundary(self.start) { + // SAFETY: just checked that `start` is on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + unsafe { &mut *self.get_unchecked_mut(slice) } + } else { + super::slice_error_fail(slice, self.start, slice.len()) + } + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +unsafe impl SliceIndex for range::RangeFrom { + type Output = str; + #[inline] + fn get(self, slice: &str) -> Option<&Self::Output> { + if slice.is_char_boundary(self.start) { + // SAFETY: just checked that `start` is on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + Some(unsafe { &*self.get_unchecked(slice) }) + } else { + None + } + } + #[inline] + fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { + if slice.is_char_boundary(self.start) { + // SAFETY: just checked that `start` is on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + Some(unsafe { &mut *self.get_unchecked_mut(slice) }) + } else { + None + } + } + #[inline] + unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { + let len = (slice as *const [u8]).len(); + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (self.start..len).get_unchecked(slice) } + } + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { + let len = (slice as *mut [u8]).len(); + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (self.start..len).get_unchecked_mut(slice) } + } + #[inline] + fn index(self, slice: &str) -> &Self::Output { + let (start, end) = (self.start, slice.len()); + match self.get(slice) { + Some(s) => s, + None => super::slice_error_fail(slice, start, end), + } + } + #[inline] + fn index_mut(self, slice: &mut str) -> &mut Self::Output { + if slice.is_char_boundary(self.start) { + // SAFETY: just checked that `start` is on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + unsafe { &mut *self.get_unchecked_mut(slice) } + } else { + super::slice_error_fail(slice, self.start, slice.len()) + } + } +} + +/// Implements substring slicing with syntax `&self[begin ..= end]` or `&mut +/// self[begin ..= end]`. +/// +/// Returns a slice of the given string from the byte range +/// [`begin`, `end`]. Equivalent to `&self [begin .. end + 1]` or `&mut +/// self[begin .. end + 1]`, except if `end` has the maximum value for +/// `usize`. +/// +/// This operation is *O*(1). +/// +/// # Panics +/// +/// Panics if `begin` does not point to the starting byte offset of +/// a character (as defined by `is_char_boundary`), if `end` does not point +/// to the ending byte offset of a character (`end + 1` is either a starting +/// byte offset or equal to `len`), if `begin > end`, or if `end >= len`. +#[stable(feature = "inclusive_range", since = "1.26.0")] +unsafe impl SliceIndex for ops::RangeInclusive { + type Output = str; + #[inline] + fn get(self, slice: &str) -> Option<&Self::Output> { + if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) } + } + #[inline] + fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { + if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) } + } + #[inline] + unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { + // SAFETY: the caller must uphold the safety contract for `get_unchecked`. + unsafe { self.into_slice_range().get_unchecked(slice) } + } + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { + // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`. + unsafe { self.into_slice_range().get_unchecked_mut(slice) } + } + #[inline] + fn index(self, slice: &str) -> &Self::Output { + if *self.end() == usize::MAX { + str_index_overflow_fail(); + } + self.into_slice_range().index(slice) + } + #[inline] + fn index_mut(self, slice: &mut str) -> &mut Self::Output { + if *self.end() == usize::MAX { + str_index_overflow_fail(); + } + self.into_slice_range().index_mut(slice) + } +} + +#[unstable(feature = "new_range_api", issue = "125687")] +unsafe impl SliceIndex for range::RangeInclusive { + type Output = str; + #[inline] + fn get(self, slice: &str) -> Option<&Self::Output> { + if self.end == usize::MAX { None } else { self.into_slice_range().get(slice) } + } + #[inline] + fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { + if self.end == usize::MAX { None } else { self.into_slice_range().get_mut(slice) } + } + #[inline] + unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { + // SAFETY: the caller must uphold the safety contract for `get_unchecked`. + unsafe { self.into_slice_range().get_unchecked(slice) } + } + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { + // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`. + unsafe { self.into_slice_range().get_unchecked_mut(slice) } + } + #[inline] + fn index(self, slice: &str) -> &Self::Output { + if self.end == usize::MAX { + str_index_overflow_fail(); + } + self.into_slice_range().index(slice) + } + #[inline] + fn index_mut(self, slice: &mut str) -> &mut Self::Output { + if self.end == usize::MAX { + str_index_overflow_fail(); + } + self.into_slice_range().index_mut(slice) + } +} + +/// Implements substring slicing with syntax `&self[..= end]` or `&mut +/// self[..= end]`. +/// +/// Returns a slice of the given string from the byte range \[0, `end`\]. +/// Equivalent to `&self [0 .. end + 1]`, except if `end` has the maximum +/// value for `usize`. +/// +/// This operation is *O*(1). +/// +/// # Panics +/// +/// Panics if `end` does not point to the ending byte offset of a character +/// (`end + 1` is either a starting byte offset as defined by +/// `is_char_boundary`, or equal to `len`), or if `end >= len`. +#[stable(feature = "inclusive_range", since = "1.26.0")] +unsafe impl SliceIndex for ops::RangeToInclusive { + type Output = str; + #[inline] + fn get(self, slice: &str) -> Option<&Self::Output> { + (0..=self.end).get(slice) + } + #[inline] + fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { + (0..=self.end).get_mut(slice) + } + #[inline] + unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { + // SAFETY: the caller must uphold the safety contract for `get_unchecked`. + unsafe { (0..=self.end).get_unchecked(slice) } + } + #[inline] + unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { + // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`. + unsafe { (0..=self.end).get_unchecked_mut(slice) } + } + #[inline] + fn index(self, slice: &str) -> &Self::Output { + (0..=self.end).index(slice) + } + #[inline] + fn index_mut(self, slice: &mut str) -> &mut Self::Output { + (0..=self.end).index_mut(slice) + } +} + +/// Parse a value from a string +/// +/// `FromStr`'s [`from_str`] method is often used implicitly, through +/// [`str`]'s [`parse`] method. See [`parse`]'s documentation for examples. +/// +/// [`from_str`]: FromStr::from_str +/// [`parse`]: str::parse +/// +/// `FromStr` does not have a lifetime parameter, and so you can only parse types +/// that do not contain a lifetime parameter themselves. In other words, you can +/// parse an `i32` with `FromStr`, but not a `&i32`. You can parse a struct that +/// contains an `i32`, but not one that contains an `&i32`. +/// +/// # Examples +/// +/// Basic implementation of `FromStr` on an example `Point` type: +/// +/// ``` +/// use std::str::FromStr; +/// +/// #[derive(Debug, PartialEq)] +/// struct Point { +/// x: i32, +/// y: i32 +/// } +/// +/// #[derive(Debug, PartialEq, Eq)] +/// struct ParsePointError; +/// +/// impl FromStr for Point { +/// type Err = ParsePointError; +/// +/// fn from_str(s: &str) -> Result { +/// let (x, y) = s +/// .strip_prefix('(') +/// .and_then(|s| s.strip_suffix(')')) +/// .and_then(|s| s.split_once(',')) +/// .ok_or(ParsePointError)?; +/// +/// let x_fromstr = x.parse::().map_err(|_| ParsePointError)?; +/// let y_fromstr = y.parse::().map_err(|_| ParsePointError)?; +/// +/// Ok(Point { x: x_fromstr, y: y_fromstr }) +/// } +/// } +/// +/// let expected = Ok(Point { x: 1, y: 2 }); +/// // Explicit call +/// assert_eq!(Point::from_str("(1,2)"), expected); +/// // Implicit calls, through parse +/// assert_eq!("(1,2)".parse(), expected); +/// assert_eq!("(1,2)".parse::(), expected); +/// // Invalid input string +/// assert!(Point::from_str("(1 2)").is_err()); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub trait FromStr: Sized { + /// The associated error which can be returned from parsing. + #[stable(feature = "rust1", since = "1.0.0")] + type Err; + + /// Parses a string `s` to return a value of this type. + /// + /// If parsing succeeds, return the value inside [`Ok`], otherwise + /// when the string is ill-formatted return an error specific to the + /// inside [`Err`]. The error type is specific to the implementation of the trait. + /// + /// # Examples + /// + /// Basic usage with [`i32`], a type that implements `FromStr`: + /// + /// ``` + /// use std::str::FromStr; + /// + /// let s = "5"; + /// let x = i32::from_str(s).unwrap(); + /// + /// assert_eq!(5, x); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "from_str_method"] + fn from_str(s: &str) -> Result; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromStr for bool { + type Err = ParseBoolError; + + /// Parse a `bool` from a string. + /// + /// The only accepted values are `"true"` and `"false"`. Any other input + /// will return an error. + /// + /// # Examples + /// + /// ``` + /// use std::str::FromStr; + /// + /// assert_eq!(FromStr::from_str("true"), Ok(true)); + /// assert_eq!(FromStr::from_str("false"), Ok(false)); + /// assert!(::from_str("not even a boolean").is_err()); + /// ``` + /// + /// Note, in many cases, the `.parse()` method on `str` is more proper. + /// + /// ``` + /// assert_eq!("true".parse(), Ok(true)); + /// assert_eq!("false".parse(), Ok(false)); + /// assert!("not even a boolean".parse::().is_err()); + /// ``` + #[inline] + fn from_str(s: &str) -> Result { + match s { + "true" => Ok(true), + "false" => Ok(false), + _ => Err(ParseBoolError), + } + } +} diff --git a/CoqOfRust/core/str/validations.rs b/CoqOfRust/core/str/validations.rs new file mode 100644 index 000000000..0f724dd96 --- /dev/null +++ b/CoqOfRust/core/str/validations.rs @@ -0,0 +1,284 @@ +//! Operations related to UTF-8 validation. + +use super::Utf8Error; +use crate::intrinsics::const_eval_select; +use crate::mem; + +/// Returns the initial codepoint accumulator for the first byte. +/// The first byte is special, only want bottom 5 bits for width 2, 4 bits +/// for width 3, and 3 bits for width 4. +#[inline] +const fn utf8_first_byte(byte: u8, width: u32) -> u32 { + (byte & (0x7F >> width)) as u32 +} + +/// Returns the value of `ch` updated with continuation byte `byte`. +#[inline] +const fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 { + (ch << 6) | (byte & CONT_MASK) as u32 +} + +/// Checks whether the byte is a UTF-8 continuation byte (i.e., starts with the +/// bits `10`). +#[inline] +pub(super) const fn utf8_is_cont_byte(byte: u8) -> bool { + (byte as i8) < -64 +} + +/// Reads the next code point out of a byte iterator (assuming a +/// UTF-8-like encoding). +/// +/// # Safety +/// +/// `bytes` must produce a valid UTF-8-like (UTF-8 or WTF-8) string +#[unstable(feature = "str_internals", issue = "none")] +#[inline] +pub unsafe fn next_code_point<'a, I: Iterator>(bytes: &mut I) -> Option { + // Decode UTF-8 + let x = *bytes.next()?; + if x < 128 { + return Some(x as u32); + } + + // Multibyte case follows + // Decode from a byte combination out of: [[[x y] z] w] + // NOTE: Performance is sensitive to the exact formulation here + let init = utf8_first_byte(x, 2); + // SAFETY: `bytes` produces an UTF-8-like string, + // so the iterator must produce a value here. + let y = unsafe { *bytes.next().unwrap_unchecked() }; + let mut ch = utf8_acc_cont_byte(init, y); + if x >= 0xE0 { + // [[x y z] w] case + // 5th bit in 0xE0 .. 0xEF is always clear, so `init` is still valid + // SAFETY: `bytes` produces an UTF-8-like string, + // so the iterator must produce a value here. + let z = unsafe { *bytes.next().unwrap_unchecked() }; + let y_z = utf8_acc_cont_byte((y & CONT_MASK) as u32, z); + ch = init << 12 | y_z; + if x >= 0xF0 { + // [x y z w] case + // use only the lower 3 bits of `init` + // SAFETY: `bytes` produces an UTF-8-like string, + // so the iterator must produce a value here. + let w = unsafe { *bytes.next().unwrap_unchecked() }; + ch = (init & 7) << 18 | utf8_acc_cont_byte(y_z, w); + } + } + + Some(ch) +} + +/// Reads the last code point out of a byte iterator (assuming a +/// UTF-8-like encoding). +/// +/// # Safety +/// +/// `bytes` must produce a valid UTF-8-like (UTF-8 or WTF-8) string +#[inline] +pub(super) unsafe fn next_code_point_reverse<'a, I>(bytes: &mut I) -> Option +where + I: DoubleEndedIterator, +{ + // Decode UTF-8 + let w = match *bytes.next_back()? { + next_byte if next_byte < 128 => return Some(next_byte as u32), + back_byte => back_byte, + }; + + // Multibyte case follows + // Decode from a byte combination out of: [x [y [z w]]] + let mut ch; + // SAFETY: `bytes` produces an UTF-8-like string, + // so the iterator must produce a value here. + let z = unsafe { *bytes.next_back().unwrap_unchecked() }; + ch = utf8_first_byte(z, 2); + if utf8_is_cont_byte(z) { + // SAFETY: `bytes` produces an UTF-8-like string, + // so the iterator must produce a value here. + let y = unsafe { *bytes.next_back().unwrap_unchecked() }; + ch = utf8_first_byte(y, 3); + if utf8_is_cont_byte(y) { + // SAFETY: `bytes` produces an UTF-8-like string, + // so the iterator must produce a value here. + let x = unsafe { *bytes.next_back().unwrap_unchecked() }; + ch = utf8_first_byte(x, 4); + ch = utf8_acc_cont_byte(ch, y); + } + ch = utf8_acc_cont_byte(ch, z); + } + ch = utf8_acc_cont_byte(ch, w); + + Some(ch) +} + +const NONASCII_MASK: usize = usize::repeat_u8(0x80); + +/// Returns `true` if any byte in the word `x` is nonascii (>= 128). +#[inline] +const fn contains_nonascii(x: usize) -> bool { + (x & NONASCII_MASK) != 0 +} + +/// Walks through `v` checking that it's a valid UTF-8 sequence, +/// returning `Ok(())` in that case, or, if it is invalid, `Err(err)`. +#[inline(always)] +#[rustc_allow_const_fn_unstable(const_eval_select)] // fallback impl has same behavior +pub(super) const fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { + let mut index = 0; + let len = v.len(); + + const USIZE_BYTES: usize = mem::size_of::(); + + let ascii_block_size = 2 * USIZE_BYTES; + let blocks_end = if len >= ascii_block_size { len - ascii_block_size + 1 } else { 0 }; + // Below, we safely fall back to a slower codepath if the offset is `usize::MAX`, + // so the end-to-end behavior is the same at compiletime and runtime. + let align = const_eval_select!( + @capture { v: &[u8] } -> usize: + if const { + usize::MAX + } else { + v.as_ptr().align_offset(USIZE_BYTES) + } + ); + + while index < len { + let old_offset = index; + macro_rules! err { + ($error_len: expr) => { + return Err(Utf8Error { valid_up_to: old_offset, error_len: $error_len }) + }; + } + + macro_rules! next { + () => {{ + index += 1; + // we needed data, but there was none: error! + if index >= len { + err!(None) + } + v[index] + }}; + } + + let first = v[index]; + if first >= 128 { + let w = utf8_char_width(first); + // 2-byte encoding is for codepoints \u{0080} to \u{07ff} + // first C2 80 last DF BF + // 3-byte encoding is for codepoints \u{0800} to \u{ffff} + // first E0 A0 80 last EF BF BF + // excluding surrogates codepoints \u{d800} to \u{dfff} + // ED A0 80 to ED BF BF + // 4-byte encoding is for codepoints \u{10000} to \u{10ffff} + // first F0 90 80 80 last F4 8F BF BF + // + // Use the UTF-8 syntax from the RFC + // + // https://tools.ietf.org/html/rfc3629 + // UTF8-1 = %x00-7F + // UTF8-2 = %xC2-DF UTF8-tail + // UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) / + // %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail ) + // UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) / + // %xF4 %x80-8F 2( UTF8-tail ) + match w { + 2 => { + if next!() as i8 >= -64 { + err!(Some(1)) + } + } + 3 => { + match (first, next!()) { + (0xE0, 0xA0..=0xBF) + | (0xE1..=0xEC, 0x80..=0xBF) + | (0xED, 0x80..=0x9F) + | (0xEE..=0xEF, 0x80..=0xBF) => {} + _ => err!(Some(1)), + } + if next!() as i8 >= -64 { + err!(Some(2)) + } + } + 4 => { + match (first, next!()) { + (0xF0, 0x90..=0xBF) | (0xF1..=0xF3, 0x80..=0xBF) | (0xF4, 0x80..=0x8F) => {} + _ => err!(Some(1)), + } + if next!() as i8 >= -64 { + err!(Some(2)) + } + if next!() as i8 >= -64 { + err!(Some(3)) + } + } + _ => err!(Some(1)), + } + index += 1; + } else { + // Ascii case, try to skip forward quickly. + // When the pointer is aligned, read 2 words of data per iteration + // until we find a word containing a non-ascii byte. + if align != usize::MAX && align.wrapping_sub(index) % USIZE_BYTES == 0 { + let ptr = v.as_ptr(); + while index < blocks_end { + // SAFETY: since `align - index` and `ascii_block_size` are + // multiples of `USIZE_BYTES`, `block = ptr.add(index)` is + // always aligned with a `usize` so it's safe to dereference + // both `block` and `block.add(1)`. + unsafe { + let block = ptr.add(index) as *const usize; + // break if there is a nonascii byte + let zu = contains_nonascii(*block); + let zv = contains_nonascii(*block.add(1)); + if zu || zv { + break; + } + } + index += ascii_block_size; + } + // step from the point where the wordwise loop stopped + while index < len && v[index] < 128 { + index += 1; + } + } else { + index += 1; + } + } + } + + Ok(()) +} + +// https://tools.ietf.org/html/rfc3629 +const UTF8_CHAR_WIDTH: &[u8; 256] = &[ + // 1 2 3 4 5 6 7 8 9 A B C D E F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // D + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // E + 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F +]; + +/// Given a first byte, determines how many bytes are in this UTF-8 character. +#[unstable(feature = "str_internals", issue = "none")] +#[must_use] +#[inline] +pub const fn utf8_char_width(b: u8) -> usize { + UTF8_CHAR_WIDTH[b as usize] as usize +} + +/// Mask of the value bits of a continuation byte. +const CONT_MASK: u8 = 0b0011_1111; diff --git a/CoqOfRust/core/sync/atomic.rs b/CoqOfRust/core/sync/atomic.rs new file mode 100644 index 000000000..487fffba8 --- /dev/null +++ b/CoqOfRust/core/sync/atomic.rs @@ -0,0 +1,3811 @@ +//! Atomic types +//! +//! Atomic types provide primitive shared-memory communication between +//! threads, and are the building blocks of other concurrent +//! types. +//! +//! This module defines atomic versions of a select number of primitive +//! types, including [`AtomicBool`], [`AtomicIsize`], [`AtomicUsize`], +//! [`AtomicI8`], [`AtomicU16`], etc. +//! Atomic types present operations that, when used correctly, synchronize +//! updates between threads. +//! +//! Atomic variables are safe to share between threads (they implement [`Sync`]) +//! but they do not themselves provide the mechanism for sharing and follow the +//! [threading model](../../../std/thread/index.html#the-threading-model) of Rust. +//! The most common way to share an atomic variable is to put it into an [`Arc`][arc] (an +//! atomically-reference-counted shared pointer). +//! +//! [arc]: ../../../std/sync/struct.Arc.html +//! +//! Atomic types may be stored in static variables, initialized using +//! the constant initializers like [`AtomicBool::new`]. Atomic statics +//! are often used for lazy global initialization. +//! +//! ## Memory model for atomic accesses +//! +//! Rust atomics currently follow the same rules as [C++20 atomics][cpp], specifically the rules +//! from the [`intro.races`][cpp-intro.races] section, without the "consume" memory ordering. Since +//! C++ uses an object-based memory model whereas Rust is access-based, a bit of translation work +//! has to be done to apply the C++ rules to Rust: whenever C++ talks about "the value of an +//! object", we understand that to mean the resulting bytes obtained when doing a read. When the C++ +//! standard talks about "the value of an atomic object", this refers to the result of doing an +//! atomic load (via the operations provided in this module). A "modification of an atomic object" +//! refers to an atomic store. +//! +//! The end result is *almost* equivalent to saying that creating a *shared reference* to one of the +//! Rust atomic types corresponds to creating an `atomic_ref` in C++, with the `atomic_ref` being +//! destroyed when the lifetime of the shared reference ends. The main difference is that Rust +//! permits concurrent atomic and non-atomic reads to the same memory as those cause no issue in the +//! C++ memory model, they are just forbidden in C++ because memory is partitioned into "atomic +//! objects" and "non-atomic objects" (with `atomic_ref` temporarily converting a non-atomic object +//! into an atomic object). +//! +//! The most important aspect of this model is that *data races* are undefined behavior. A data race +//! is defined as conflicting non-synchronized accesses where at least one of the accesses is +//! non-atomic. Here, accesses are *conflicting* if they affect overlapping regions of memory and at +//! least one of them is a write. They are *non-synchronized* if neither of them *happens-before* +//! the other, according to the happens-before order of the memory model. +//! +//! The other possible cause of undefined behavior in the memory model are mixed-size accesses: Rust +//! inherits the C++ limitation that non-synchronized conflicting atomic accesses may not partially +//! overlap. In other words, every pair of non-synchronized atomic accesses must be either disjoint, +//! access the exact same memory (including using the same access size), or both be reads. +//! +//! Each atomic access takes an [`Ordering`] which defines how the operation interacts with the +//! happens-before order. These orderings behave the same as the corresponding [C++20 atomic +//! orderings][cpp_memory_order]. For more information, see the [nomicon]. +//! +//! [cpp]: https://en.cppreference.com/w/cpp/atomic +//! [cpp-intro.races]: https://timsong-cpp.github.io/cppwp/n4868/intro.multithread#intro.races +//! [cpp_memory_order]: https://en.cppreference.com/w/cpp/atomic/memory_order +//! [nomicon]: ../../../nomicon/atomics.html +//! +//! ```rust,no_run undefined_behavior +//! use std::sync::atomic::{AtomicU16, AtomicU8, Ordering}; +//! use std::mem::transmute; +//! use std::thread; +//! +//! let atomic = AtomicU16::new(0); +//! +//! thread::scope(|s| { +//! // This is UB: conflicting non-synchronized accesses, at least one of which is non-atomic. +//! s.spawn(|| atomic.store(1, Ordering::Relaxed)); // atomic store +//! s.spawn(|| unsafe { atomic.as_ptr().write(2) }); // non-atomic write +//! }); +//! +//! thread::scope(|s| { +//! // This is fine: the accesses do not conflict (as none of them performs any modification). +//! // In C++ this would be disallowed since creating an `atomic_ref` precludes +//! // further non-atomic accesses, but Rust does not have that limitation. +//! s.spawn(|| atomic.load(Ordering::Relaxed)); // atomic load +//! s.spawn(|| unsafe { atomic.as_ptr().read() }); // non-atomic read +//! }); +//! +//! thread::scope(|s| { +//! // This is fine: `join` synchronizes the code in a way such that the atomic +//! // store happens-before the non-atomic write. +//! let handle = s.spawn(|| atomic.store(1, Ordering::Relaxed)); // atomic store +//! handle.join().unwrap(); // synchronize +//! s.spawn(|| unsafe { atomic.as_ptr().write(2) }); // non-atomic write +//! }); +//! +//! thread::scope(|s| { +//! // This is UB: non-synchronized conflicting differently-sized atomic accesses. +//! s.spawn(|| atomic.store(1, Ordering::Relaxed)); +//! s.spawn(|| unsafe { +//! let differently_sized = transmute::<&AtomicU16, &AtomicU8>(&atomic); +//! differently_sized.store(2, Ordering::Relaxed); +//! }); +//! }); +//! +//! thread::scope(|s| { +//! // This is fine: `join` synchronizes the code in a way such that +//! // the 1-byte store happens-before the 2-byte store. +//! let handle = s.spawn(|| atomic.store(1, Ordering::Relaxed)); +//! handle.join().unwrap(); +//! s.spawn(|| unsafe { +//! let differently_sized = transmute::<&AtomicU16, &AtomicU8>(&atomic); +//! differently_sized.store(2, Ordering::Relaxed); +//! }); +//! }); +//! ``` +//! +//! # Portability +//! +//! All atomic types in this module are guaranteed to be [lock-free] if they're +//! available. This means they don't internally acquire a global mutex. Atomic +//! types and operations are not guaranteed to be wait-free. This means that +//! operations like `fetch_or` may be implemented with a compare-and-swap loop. +//! +//! Atomic operations may be implemented at the instruction layer with +//! larger-size atomics. For example some platforms use 4-byte atomic +//! instructions to implement `AtomicI8`. Note that this emulation should not +//! have an impact on correctness of code, it's just something to be aware of. +//! +//! The atomic types in this module might not be available on all platforms. The +//! atomic types here are all widely available, however, and can generally be +//! relied upon existing. Some notable exceptions are: +//! +//! * PowerPC and MIPS platforms with 32-bit pointers do not have `AtomicU64` or +//! `AtomicI64` types. +//! * ARM platforms like `armv5te` that aren't for Linux only provide `load` +//! and `store` operations, and do not support Compare and Swap (CAS) +//! operations, such as `swap`, `fetch_add`, etc. Additionally on Linux, +//! these CAS operations are implemented via [operating system support], which +//! may come with a performance penalty. +//! * ARM targets with `thumbv6m` only provide `load` and `store` operations, +//! and do not support Compare and Swap (CAS) operations, such as `swap`, +//! `fetch_add`, etc. +//! +//! [operating system support]: https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt +//! +//! Note that future platforms may be added that also do not have support for +//! some atomic operations. Maximally portable code will want to be careful +//! about which atomic types are used. `AtomicUsize` and `AtomicIsize` are +//! generally the most portable, but even then they're not available everywhere. +//! For reference, the `std` library requires `AtomicBool`s and pointer-sized atomics, although +//! `core` does not. +//! +//! The `#[cfg(target_has_atomic)]` attribute can be used to conditionally +//! compile based on the target's supported bit widths. It is a key-value +//! option set for each supported size, with values "8", "16", "32", "64", +//! "128", and "ptr" for pointer-sized atomics. +//! +//! [lock-free]: https://en.wikipedia.org/wiki/Non-blocking_algorithm +//! +//! # Atomic accesses to read-only memory +//! +//! In general, *all* atomic accesses on read-only memory are undefined behavior. For instance, attempting +//! to do a `compare_exchange` that will definitely fail (making it conceptually a read-only +//! operation) can still cause a segmentation fault if the underlying memory page is mapped read-only. Since +//! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault +//! on read-only memory. +//! +//! For the purpose of this section, "read-only memory" is defined as memory that is read-only in +//! the underlying target, i.e., the pages are mapped with a read-only flag and any attempt to write +//! will cause a page fault. In particular, an `&u128` reference that points to memory that is +//! read-write mapped is *not* considered to point to "read-only memory". In Rust, almost all memory +//! is read-write; the only exceptions are memory created by `const` items or `static` items without +//! interior mutability, and memory that was specifically marked as read-only by the operating +//! system via platform-specific APIs. +//! +//! As an exception from the general rule stated above, "sufficiently small" atomic loads with +//! `Ordering::Relaxed` are implemented in a way that works on read-only memory, and are hence not +//! undefined behavior. The exact size limit for what makes a load "sufficiently small" varies +//! depending on the target: +//! +//! | `target_arch` | Size limit | +//! |---------------|---------| +//! | `x86`, `arm`, `mips`, `mips32r6`, `powerpc`, `riscv32`, `sparc`, `hexagon` | 4 bytes | +//! | `x86_64`, `aarch64`, `loongarch64`, `mips64`, `mips64r6`, `powerpc64`, `riscv64`, `sparc64`, `s390x` | 8 bytes | +//! +//! Atomics loads that are larger than this limit as well as atomic loads with ordering other +//! than `Relaxed`, as well as *all* atomic loads on targets not listed in the table, might still be +//! read-only under certain conditions, but that is not a stable guarantee and should not be relied +//! upon. +//! +//! If you need to do an acquire load on read-only memory, you can do a relaxed load followed by an +//! acquire fence instead. +//! +//! # Examples +//! +//! A simple spinlock: +//! +//! ``` +//! use std::sync::Arc; +//! use std::sync::atomic::{AtomicUsize, Ordering}; +//! use std::{hint, thread}; +//! +//! fn main() { +//! let spinlock = Arc::new(AtomicUsize::new(1)); +//! +//! let spinlock_clone = Arc::clone(&spinlock); +//! +//! let thread = thread::spawn(move || { +//! spinlock_clone.store(0, Ordering::Release); +//! }); +//! +//! // Wait for the other thread to release the lock +//! while spinlock.load(Ordering::Acquire) != 0 { +//! hint::spin_loop(); +//! } +//! +//! if let Err(panic) = thread.join() { +//! println!("Thread had an error: {panic:?}"); +//! } +//! } +//! ``` +//! +//! Keep a global count of live threads: +//! +//! ``` +//! use std::sync::atomic::{AtomicUsize, Ordering}; +//! +//! static GLOBAL_THREAD_COUNT: AtomicUsize = AtomicUsize::new(0); +//! +//! // Note that Relaxed ordering doesn't synchronize anything +//! // except the global thread counter itself. +//! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::Relaxed); +//! // Note that this number may not be true at the moment of printing +//! // because some other thread may have changed static value already. +//! println!("live threads: {}", old_thread_count + 1); +//! ``` + +#![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))] +#![rustc_diagnostic_item = "atomic_mod"] +// Clippy complains about the pattern of "safe function calling unsafe function taking pointers". +// This happens with AtomicPtr intrinsics but is fine, as the pointers clippy is concerned about +// are just normal values that get loaded/stored, but not dereferenced. +#![allow(clippy::not_unsafe_ptr_arg_deref)] + +use self::Ordering::*; +use crate::cell::UnsafeCell; +use crate::hint::spin_loop; +use crate::{fmt, intrinsics}; + +// Some architectures don't have byte-sized atomics, which results in LLVM +// emulating them using a LL/SC loop. However for AtomicBool we can take +// advantage of the fact that it only ever contains 0 or 1 and use atomic OR/AND +// instead, which LLVM can emulate using a larger atomic OR/AND operation. +// +// This list should only contain architectures which have word-sized atomic-or/ +// atomic-and instructions but don't natively support byte-sized atomics. +#[cfg(target_has_atomic = "8")] +const EMULATE_ATOMIC_BOOL: bool = + cfg!(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "loongarch64")); + +/// A boolean type which can be safely shared between threads. +/// +/// This type has the same size, alignment, and bit validity as a [`bool`]. +/// +/// **Note**: This type is only available on platforms that support atomic +/// loads and stores of `u8`. +#[cfg(target_has_atomic_load_store = "8")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "AtomicBool"] +#[repr(C, align(1))] +pub struct AtomicBool { + v: UnsafeCell, +} + +#[cfg(target_has_atomic_load_store = "8")] +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for AtomicBool { + /// Creates an `AtomicBool` initialized to `false`. + #[inline] + fn default() -> Self { + Self::new(false) + } +} + +// Send is implicitly implemented for AtomicBool. +#[cfg(target_has_atomic_load_store = "8")] +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for AtomicBool {} + +/// A raw pointer type which can be safely shared between threads. +/// +/// This type has the same size and bit validity as a `*mut T`. +/// +/// **Note**: This type is only available on platforms that support atomic +/// loads and stores of pointers. Its size depends on the target pointer's size. +#[cfg(target_has_atomic_load_store = "ptr")] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "AtomicPtr")] +#[cfg_attr(target_pointer_width = "16", repr(C, align(2)))] +#[cfg_attr(target_pointer_width = "32", repr(C, align(4)))] +#[cfg_attr(target_pointer_width = "64", repr(C, align(8)))] +pub struct AtomicPtr { + p: UnsafeCell<*mut T>, +} + +#[cfg(target_has_atomic_load_store = "ptr")] +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for AtomicPtr { + /// Creates a null `AtomicPtr`. + fn default() -> AtomicPtr { + AtomicPtr::new(crate::ptr::null_mut()) + } +} + +#[cfg(target_has_atomic_load_store = "ptr")] +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for AtomicPtr {} +#[cfg(target_has_atomic_load_store = "ptr")] +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for AtomicPtr {} + +/// Atomic memory orderings +/// +/// Memory orderings specify the way atomic operations synchronize memory. +/// In its weakest [`Ordering::Relaxed`], only the memory directly touched by the +/// operation is synchronized. On the other hand, a store-load pair of [`Ordering::SeqCst`] +/// operations synchronize other memory while additionally preserving a total order of such +/// operations across all threads. +/// +/// Rust's memory orderings are [the same as those of +/// C++20](https://en.cppreference.com/w/cpp/atomic/memory_order). +/// +/// For more information see the [nomicon]. +/// +/// [nomicon]: ../../../nomicon/atomics.html +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[non_exhaustive] +#[rustc_diagnostic_item = "Ordering"] +pub enum Ordering { + /// No ordering constraints, only atomic operations. + /// + /// Corresponds to [`memory_order_relaxed`] in C++20. + /// + /// [`memory_order_relaxed`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Relaxed_ordering + #[stable(feature = "rust1", since = "1.0.0")] + Relaxed, + /// When coupled with a store, all previous operations become ordered + /// before any load of this value with [`Acquire`] (or stronger) ordering. + /// In particular, all previous writes become visible to all threads + /// that perform an [`Acquire`] (or stronger) load of this value. + /// + /// Notice that using this ordering for an operation that combines loads + /// and stores leads to a [`Relaxed`] load operation! + /// + /// This ordering is only applicable for operations that can perform a store. + /// + /// Corresponds to [`memory_order_release`] in C++20. + /// + /// [`memory_order_release`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering + #[stable(feature = "rust1", since = "1.0.0")] + Release, + /// When coupled with a load, if the loaded value was written by a store operation with + /// [`Release`] (or stronger) ordering, then all subsequent operations + /// become ordered after that store. In particular, all subsequent loads will see data + /// written before the store. + /// + /// Notice that using this ordering for an operation that combines loads + /// and stores leads to a [`Relaxed`] store operation! + /// + /// This ordering is only applicable for operations that can perform a load. + /// + /// Corresponds to [`memory_order_acquire`] in C++20. + /// + /// [`memory_order_acquire`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering + #[stable(feature = "rust1", since = "1.0.0")] + Acquire, + /// Has the effects of both [`Acquire`] and [`Release`] together: + /// For loads it uses [`Acquire`] ordering. For stores it uses the [`Release`] ordering. + /// + /// Notice that in the case of `compare_and_swap`, it is possible that the operation ends up + /// not performing any store and hence it has just [`Acquire`] ordering. However, + /// `AcqRel` will never perform [`Relaxed`] accesses. + /// + /// This ordering is only applicable for operations that combine both loads and stores. + /// + /// Corresponds to [`memory_order_acq_rel`] in C++20. + /// + /// [`memory_order_acq_rel`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering + #[stable(feature = "rust1", since = "1.0.0")] + AcqRel, + /// Like [`Acquire`]/[`Release`]/[`AcqRel`] (for load, store, and load-with-store + /// operations, respectively) with the additional guarantee that all threads see all + /// sequentially consistent operations in the same order. + /// + /// Corresponds to [`memory_order_seq_cst`] in C++20. + /// + /// [`memory_order_seq_cst`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Sequentially-consistent_ordering + #[stable(feature = "rust1", since = "1.0.0")] + SeqCst, +} + +/// An [`AtomicBool`] initialized to `false`. +#[cfg(target_has_atomic_load_store = "8")] +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated( + since = "1.34.0", + note = "the `new` function is now preferred", + suggestion = "AtomicBool::new(false)" +)] +pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false); + +#[cfg(target_has_atomic_load_store = "8")] +impl AtomicBool { + /// Creates a new `AtomicBool`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::AtomicBool; + /// + /// let atomic_true = AtomicBool::new(true); + /// let atomic_false = AtomicBool::new(false); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")] + #[must_use] + pub const fn new(v: bool) -> AtomicBool { + AtomicBool { v: UnsafeCell::new(v as u8) } + } + + /// Creates a new `AtomicBool` from a pointer. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{self, AtomicBool}; + /// + /// // Get a pointer to an allocated value + /// let ptr: *mut bool = Box::into_raw(Box::new(false)); + /// + /// assert!(ptr.cast::().is_aligned()); + /// + /// { + /// // Create an atomic view of the allocated value + /// let atomic = unsafe { AtomicBool::from_ptr(ptr) }; + /// + /// // Use `atomic` for atomic operations, possibly share it with other threads + /// atomic.store(true, atomic::Ordering::Relaxed); + /// } + /// + /// // It's ok to non-atomically access the value behind `ptr`, + /// // since the reference to the atomic ended its lifetime in the block above + /// assert_eq!(unsafe { *ptr }, true); + /// + /// // Deallocate the value + /// unsafe { drop(Box::from_raw(ptr)) } + /// ``` + /// + /// # Safety + /// + /// * `ptr` must be aligned to `align_of::()` (note that this is always true, since + /// `align_of::() == 1`). + /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. + /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not + /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes, + /// without synchronization. + /// + /// [valid]: crate::ptr#safety + /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses + #[stable(feature = "atomic_from_ptr", since = "1.75.0")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] + pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool { + // SAFETY: guaranteed by the caller + unsafe { &*ptr.cast() } + } + + /// Returns a mutable reference to the underlying [`bool`]. + /// + /// This is safe because the mutable reference guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let mut some_bool = AtomicBool::new(true); + /// assert_eq!(*some_bool.get_mut(), true); + /// *some_bool.get_mut() = false; + /// assert_eq!(some_bool.load(Ordering::SeqCst), false); + /// ``` + #[inline] + #[stable(feature = "atomic_access", since = "1.15.0")] + pub fn get_mut(&mut self) -> &mut bool { + // SAFETY: the mutable reference guarantees unique ownership. + unsafe { &mut *(self.v.get() as *mut bool) } + } + + /// Gets atomic access to a `&mut bool`. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut)] + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let mut some_bool = true; + /// let a = AtomicBool::from_mut(&mut some_bool); + /// a.store(false, Ordering::Relaxed); + /// assert_eq!(some_bool, false); + /// ``` + #[inline] + #[cfg(target_has_atomic_equal_alignment = "8")] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn from_mut(v: &mut bool) -> &mut Self { + // SAFETY: the mutable reference guarantees unique ownership, and + // alignment of both `bool` and `Self` is 1. + unsafe { &mut *(v as *mut bool as *mut Self) } + } + + /// Gets non-atomic access to a `&mut [AtomicBool]` slice. + /// + /// This is safe because the mutable reference guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut)] + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let mut some_bools = [const { AtomicBool::new(false) }; 10]; + /// + /// let view: &mut [bool] = AtomicBool::get_mut_slice(&mut some_bools); + /// assert_eq!(view, [false; 10]); + /// view[..5].copy_from_slice(&[true; 5]); + /// + /// std::thread::scope(|s| { + /// for t in &some_bools[..5] { + /// s.spawn(move || assert_eq!(t.load(Ordering::Relaxed), true)); + /// } + /// + /// for f in &some_bools[5..] { + /// s.spawn(move || assert_eq!(f.load(Ordering::Relaxed), false)); + /// } + /// }); + /// ``` + #[inline] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn get_mut_slice(this: &mut [Self]) -> &mut [bool] { + // SAFETY: the mutable reference guarantees unique ownership. + unsafe { &mut *(this as *mut [Self] as *mut [bool]) } + } + + /// Gets atomic access to a `&mut [bool]` slice. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut)] + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let mut some_bools = [false; 10]; + /// let a = &*AtomicBool::from_mut_slice(&mut some_bools); + /// std::thread::scope(|s| { + /// for i in 0..a.len() { + /// s.spawn(move || a[i].store(true, Ordering::Relaxed)); + /// } + /// }); + /// assert_eq!(some_bools, [true; 10]); + /// ``` + #[inline] + #[cfg(target_has_atomic_equal_alignment = "8")] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn from_mut_slice(v: &mut [bool]) -> &mut [Self] { + // SAFETY: the mutable reference guarantees unique ownership, and + // alignment of both `bool` and `Self` is 1. + unsafe { &mut *(v as *mut [bool] as *mut [Self]) } + } + + /// Consumes the atomic and returns the contained value. + /// + /// This is safe because passing `self` by value guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::AtomicBool; + /// + /// let some_bool = AtomicBool::new(true); + /// assert_eq!(some_bool.into_inner(), true); + /// ``` + #[inline] + #[stable(feature = "atomic_access", since = "1.15.0")] + #[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")] + pub const fn into_inner(self) -> bool { + self.v.into_inner() != 0 + } + + /// Loads a value from the bool. + /// + /// `load` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. + /// + /// # Panics + /// + /// Panics if `order` is [`Release`] or [`AcqRel`]. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let some_bool = AtomicBool::new(true); + /// + /// assert_eq!(some_bool.load(Ordering::Relaxed), true); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn load(&self, order: Ordering) -> bool { + // SAFETY: any data races are prevented by atomic intrinsics and the raw + // pointer passed in is valid because we got it from a reference. + unsafe { atomic_load(self.v.get(), order) != 0 } + } + + /// Stores a value into the bool. + /// + /// `store` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. + /// + /// # Panics + /// + /// Panics if `order` is [`Acquire`] or [`AcqRel`]. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let some_bool = AtomicBool::new(true); + /// + /// some_bool.store(false, Ordering::Relaxed); + /// assert_eq!(some_bool.load(Ordering::Relaxed), false); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn store(&self, val: bool, order: Ordering) { + // SAFETY: any data races are prevented by atomic intrinsics and the raw + // pointer passed in is valid because we got it from a reference. + unsafe { + atomic_store(self.v.get(), val as u8, order); + } + } + + /// Stores a value into the bool, returning the previous value. + /// + /// `swap` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on `u8`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let some_bool = AtomicBool::new(true); + /// + /// assert_eq!(some_bool.swap(false, Ordering::Relaxed), true); + /// assert_eq!(some_bool.load(Ordering::Relaxed), false); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(target_has_atomic = "8")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn swap(&self, val: bool, order: Ordering) -> bool { + if EMULATE_ATOMIC_BOOL { + if val { self.fetch_or(true, order) } else { self.fetch_and(false, order) } + } else { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 } + } + } + + /// Stores a value into the [`bool`] if the current value is the same as the `current` value. + /// + /// The return value is always the previous value. If it is equal to `current`, then the value + /// was updated. + /// + /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. Notice that even when using [`AcqRel`], the operation + /// might fail and hence just perform an `Acquire` load, but not have `Release` semantics. + /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it + /// happens, and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on `u8`. + /// + /// # Migrating to `compare_exchange` and `compare_exchange_weak` + /// + /// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for + /// memory orderings: + /// + /// Original | Success | Failure + /// -------- | ------- | ------- + /// Relaxed | Relaxed | Relaxed + /// Acquire | Acquire | Acquire + /// Release | Release | Relaxed + /// AcqRel | AcqRel | Acquire + /// SeqCst | SeqCst | SeqCst + /// + /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds, + /// which allows the compiler to generate better assembly code when the compare and swap + /// is used in a loop. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let some_bool = AtomicBool::new(true); + /// + /// assert_eq!(some_bool.compare_and_swap(true, false, Ordering::Relaxed), true); + /// assert_eq!(some_bool.load(Ordering::Relaxed), false); + /// + /// assert_eq!(some_bool.compare_and_swap(true, true, Ordering::Relaxed), false); + /// assert_eq!(some_bool.load(Ordering::Relaxed), false); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated( + since = "1.50.0", + note = "Use `compare_exchange` or `compare_exchange_weak` instead" + )] + #[cfg(target_has_atomic = "8")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool { + match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { + Ok(x) => x, + Err(x) => x, + } + } + + /// Stores a value into the [`bool`] if the current value is the same as the `current` value. + /// + /// The return value is a result indicating whether the new value was written and containing + /// the previous value. On success this value is guaranteed to be equal to `current`. + /// + /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using [`Acquire`] as success ordering makes the store part + /// of this operation [`Relaxed`], and using [`Release`] makes the successful load + /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on `u8`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let some_bool = AtomicBool::new(true); + /// + /// assert_eq!(some_bool.compare_exchange(true, + /// false, + /// Ordering::Acquire, + /// Ordering::Relaxed), + /// Ok(true)); + /// assert_eq!(some_bool.load(Ordering::Relaxed), false); + /// + /// assert_eq!(some_bool.compare_exchange(true, true, + /// Ordering::SeqCst, + /// Ordering::Acquire), + /// Err(false)); + /// assert_eq!(some_bool.load(Ordering::Relaxed), false); + /// ``` + #[inline] + #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] + #[doc(alias = "compare_and_swap")] + #[cfg(target_has_atomic = "8")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn compare_exchange( + &self, + current: bool, + new: bool, + success: Ordering, + failure: Ordering, + ) -> Result { + if EMULATE_ATOMIC_BOOL { + // Pick the strongest ordering from success and failure. + let order = match (success, failure) { + (SeqCst, _) => SeqCst, + (_, SeqCst) => SeqCst, + (AcqRel, _) => AcqRel, + (_, AcqRel) => { + panic!("there is no such thing as an acquire-release failure ordering") + } + (Release, Acquire) => AcqRel, + (Acquire, _) => Acquire, + (_, Acquire) => Acquire, + (Release, Relaxed) => Release, + (_, Release) => panic!("there is no such thing as a release failure ordering"), + (Relaxed, Relaxed) => Relaxed, + }; + let old = if current == new { + // This is a no-op, but we still need to perform the operation + // for memory ordering reasons. + self.fetch_or(false, order) + } else { + // This sets the value to the new one and returns the old one. + self.swap(new, order) + }; + if old == current { Ok(old) } else { Err(old) } + } else { + // SAFETY: data races are prevented by atomic intrinsics. + match unsafe { + atomic_compare_exchange(self.v.get(), current as u8, new as u8, success, failure) + } { + Ok(x) => Ok(x != 0), + Err(x) => Err(x != 0), + } + } + } + + /// Stores a value into the [`bool`] if the current value is the same as the `current` value. + /// + /// Unlike [`AtomicBool::compare_exchange`], this function is allowed to spuriously fail even when the + /// comparison succeeds, which can result in more efficient code on some platforms. The + /// return value is a result indicating whether the new value was written and containing the + /// previous value. + /// + /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using [`Acquire`] as success ordering makes the store part + /// of this operation [`Relaxed`], and using [`Release`] makes the successful load + /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on `u8`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let val = AtomicBool::new(false); + /// + /// let new = true; + /// let mut old = val.load(Ordering::Relaxed); + /// loop { + /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { + /// Ok(_) => break, + /// Err(x) => old = x, + /// } + /// } + /// ``` + #[inline] + #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] + #[doc(alias = "compare_and_swap")] + #[cfg(target_has_atomic = "8")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn compare_exchange_weak( + &self, + current: bool, + new: bool, + success: Ordering, + failure: Ordering, + ) -> Result { + if EMULATE_ATOMIC_BOOL { + return self.compare_exchange(current, new, success, failure); + } + + // SAFETY: data races are prevented by atomic intrinsics. + match unsafe { + atomic_compare_exchange_weak(self.v.get(), current as u8, new as u8, success, failure) + } { + Ok(x) => Ok(x != 0), + Err(x) => Err(x != 0), + } + } + + /// Logical "and" with a boolean value. + /// + /// Performs a logical "and" operation on the current value and the argument `val`, and sets + /// the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on `u8`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let foo = AtomicBool::new(true); + /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), true); + /// assert_eq!(foo.load(Ordering::SeqCst), false); + /// + /// let foo = AtomicBool::new(true); + /// assert_eq!(foo.fetch_and(true, Ordering::SeqCst), true); + /// assert_eq!(foo.load(Ordering::SeqCst), true); + /// + /// let foo = AtomicBool::new(false); + /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), false); + /// assert_eq!(foo.load(Ordering::SeqCst), false); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(target_has_atomic = "8")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_and(&self, val: bool, order: Ordering) -> bool { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_and(self.v.get(), val as u8, order) != 0 } + } + + /// Logical "nand" with a boolean value. + /// + /// Performs a logical "nand" operation on the current value and the argument `val`, and sets + /// the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on `u8`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let foo = AtomicBool::new(true); + /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), true); + /// assert_eq!(foo.load(Ordering::SeqCst), true); + /// + /// let foo = AtomicBool::new(true); + /// assert_eq!(foo.fetch_nand(true, Ordering::SeqCst), true); + /// assert_eq!(foo.load(Ordering::SeqCst) as usize, 0); + /// assert_eq!(foo.load(Ordering::SeqCst), false); + /// + /// let foo = AtomicBool::new(false); + /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), false); + /// assert_eq!(foo.load(Ordering::SeqCst), true); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(target_has_atomic = "8")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool { + // We can't use atomic_nand here because it can result in a bool with + // an invalid value. This happens because the atomic operation is done + // with an 8-bit integer internally, which would set the upper 7 bits. + // So we just use fetch_xor or swap instead. + if val { + // !(x & true) == !x + // We must invert the bool. + self.fetch_xor(true, order) + } else { + // !(x & false) == true + // We must set the bool to true. + self.swap(true, order) + } + } + + /// Logical "or" with a boolean value. + /// + /// Performs a logical "or" operation on the current value and the argument `val`, and sets the + /// new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on `u8`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let foo = AtomicBool::new(true); + /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), true); + /// assert_eq!(foo.load(Ordering::SeqCst), true); + /// + /// let foo = AtomicBool::new(true); + /// assert_eq!(foo.fetch_or(true, Ordering::SeqCst), true); + /// assert_eq!(foo.load(Ordering::SeqCst), true); + /// + /// let foo = AtomicBool::new(false); + /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), false); + /// assert_eq!(foo.load(Ordering::SeqCst), false); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(target_has_atomic = "8")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_or(&self, val: bool, order: Ordering) -> bool { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_or(self.v.get(), val as u8, order) != 0 } + } + + /// Logical "xor" with a boolean value. + /// + /// Performs a logical "xor" operation on the current value and the argument `val`, and sets + /// the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on `u8`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let foo = AtomicBool::new(true); + /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), true); + /// assert_eq!(foo.load(Ordering::SeqCst), true); + /// + /// let foo = AtomicBool::new(true); + /// assert_eq!(foo.fetch_xor(true, Ordering::SeqCst), true); + /// assert_eq!(foo.load(Ordering::SeqCst), false); + /// + /// let foo = AtomicBool::new(false); + /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), false); + /// assert_eq!(foo.load(Ordering::SeqCst), false); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(target_has_atomic = "8")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 } + } + + /// Logical "not" with a boolean value. + /// + /// Performs a logical "not" operation on the current value, and sets + /// the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_not` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on `u8`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let foo = AtomicBool::new(true); + /// assert_eq!(foo.fetch_not(Ordering::SeqCst), true); + /// assert_eq!(foo.load(Ordering::SeqCst), false); + /// + /// let foo = AtomicBool::new(false); + /// assert_eq!(foo.fetch_not(Ordering::SeqCst), false); + /// assert_eq!(foo.load(Ordering::SeqCst), true); + /// ``` + #[inline] + #[stable(feature = "atomic_bool_fetch_not", since = "1.81.0")] + #[cfg(target_has_atomic = "8")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_not(&self, order: Ordering) -> bool { + self.fetch_xor(true, order) + } + + /// Returns a mutable pointer to the underlying [`bool`]. + /// + /// Doing non-atomic reads and writes on the resulting boolean can be a data race. + /// This method is mostly useful for FFI, where the function signature may use + /// `*mut bool` instead of `&AtomicBool`. + /// + /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the + /// atomic types work with interior mutability. All modifications of an atomic change the value + /// through a shared reference, and can do so safely as long as they use atomic operations. Any + /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same + /// restriction: operations on it must be atomic. + /// + /// # Examples + /// + /// ```ignore (extern-declaration) + /// # fn main() { + /// use std::sync::atomic::AtomicBool; + /// + /// extern "C" { + /// fn my_atomic_op(arg: *mut bool); + /// } + /// + /// let mut atomic = AtomicBool::new(true); + /// unsafe { + /// my_atomic_op(atomic.as_ptr()); + /// } + /// # } + /// ``` + #[inline] + #[stable(feature = "atomic_as_ptr", since = "1.70.0")] + #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] + #[rustc_never_returns_null_ptr] + pub const fn as_ptr(&self) -> *mut bool { + self.v.get().cast() + } + + /// Fetches the value, and applies a function to it that returns an optional + /// new value. Returns a `Result` of `Ok(previous_value)` if the function + /// returned `Some(_)`, else `Err(previous_value)`. + /// + /// Note: This may call the function multiple times if the value has been + /// changed from other threads in the meantime, as long as the function + /// returns `Some(_)`, but the function will have been applied only once to + /// the stored value. + /// + /// `fetch_update` takes two [`Ordering`] arguments to describe the memory + /// ordering of this operation. The first describes the required ordering for + /// when the operation finally succeeds while the second describes the + /// required ordering for loads. These correspond to the success and failure + /// orderings of [`AtomicBool::compare_exchange`] respectively. + /// + /// Using [`Acquire`] as success ordering makes the store part of this + /// operation [`Relaxed`], and using [`Release`] makes the final successful + /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], + /// [`Acquire`] or [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on `u8`. + /// + /// # Considerations + /// + /// This method is not magic; it is not provided by the hardware. + /// It is implemented in terms of [`AtomicBool::compare_exchange_weak`], and suffers from the same drawbacks. + /// In particular, this method will not circumvent the [ABA Problem]. + /// + /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem + /// + /// # Examples + /// + /// ```rust + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let x = AtomicBool::new(false); + /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(false)); + /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(false)); + /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(true)); + /// assert_eq!(x.load(Ordering::SeqCst), false); + /// ``` + #[inline] + #[stable(feature = "atomic_fetch_update", since = "1.53.0")] + #[cfg(target_has_atomic = "8")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_update( + &self, + set_order: Ordering, + fetch_order: Ordering, + mut f: F, + ) -> Result + where + F: FnMut(bool) -> Option, + { + let mut prev = self.load(fetch_order); + while let Some(next) = f(prev) { + match self.compare_exchange_weak(prev, next, set_order, fetch_order) { + x @ Ok(_) => return x, + Err(next_prev) => prev = next_prev, + } + } + Err(prev) + } +} + +#[cfg(target_has_atomic_load_store = "ptr")] +impl AtomicPtr { + /// Creates a new `AtomicPtr`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::AtomicPtr; + /// + /// let ptr = &mut 5; + /// let atomic_ptr = AtomicPtr::new(ptr); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")] + pub const fn new(p: *mut T) -> AtomicPtr { + AtomicPtr { p: UnsafeCell::new(p) } + } + + /// Creates a new `AtomicPtr` from a pointer. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{self, AtomicPtr}; + /// + /// // Get a pointer to an allocated value + /// let ptr: *mut *mut u8 = Box::into_raw(Box::new(std::ptr::null_mut())); + /// + /// assert!(ptr.cast::>().is_aligned()); + /// + /// { + /// // Create an atomic view of the allocated value + /// let atomic = unsafe { AtomicPtr::from_ptr(ptr) }; + /// + /// // Use `atomic` for atomic operations, possibly share it with other threads + /// atomic.store(std::ptr::NonNull::dangling().as_ptr(), atomic::Ordering::Relaxed); + /// } + /// + /// // It's ok to non-atomically access the value behind `ptr`, + /// // since the reference to the atomic ended its lifetime in the block above + /// assert!(!unsafe { *ptr }.is_null()); + /// + /// // Deallocate the value + /// unsafe { drop(Box::from_raw(ptr)) } + /// ``` + /// + /// # Safety + /// + /// * `ptr` must be aligned to `align_of::>()` (note that on some platforms this + /// can be bigger than `align_of::<*mut T>()`). + /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. + /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not + /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes, + /// without synchronization. + /// + /// [valid]: crate::ptr#safety + /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses + #[stable(feature = "atomic_from_ptr", since = "1.75.0")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] + pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr { + // SAFETY: guaranteed by the caller + unsafe { &*ptr.cast() } + } + + /// Returns a mutable reference to the underlying pointer. + /// + /// This is safe because the mutable reference guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let mut data = 10; + /// let mut atomic_ptr = AtomicPtr::new(&mut data); + /// let mut other_data = 5; + /// *atomic_ptr.get_mut() = &mut other_data; + /// assert_eq!(unsafe { *atomic_ptr.load(Ordering::SeqCst) }, 5); + /// ``` + #[inline] + #[stable(feature = "atomic_access", since = "1.15.0")] + pub fn get_mut(&mut self) -> &mut *mut T { + self.p.get_mut() + } + + /// Gets atomic access to a pointer. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut)] + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let mut data = 123; + /// let mut some_ptr = &mut data as *mut i32; + /// let a = AtomicPtr::from_mut(&mut some_ptr); + /// let mut other_data = 456; + /// a.store(&mut other_data, Ordering::Relaxed); + /// assert_eq!(unsafe { *some_ptr }, 456); + /// ``` + #[inline] + #[cfg(target_has_atomic_equal_alignment = "ptr")] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn from_mut(v: &mut *mut T) -> &mut Self { + let [] = [(); align_of::>() - align_of::<*mut ()>()]; + // SAFETY: + // - the mutable reference guarantees unique ownership. + // - the alignment of `*mut T` and `Self` is the same on all platforms + // supported by rust, as verified above. + unsafe { &mut *(v as *mut *mut T as *mut Self) } + } + + /// Gets non-atomic access to a `&mut [AtomicPtr]` slice. + /// + /// This is safe because the mutable reference guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut)] + /// use std::ptr::null_mut; + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let mut some_ptrs = [const { AtomicPtr::new(null_mut::()) }; 10]; + /// + /// let view: &mut [*mut String] = AtomicPtr::get_mut_slice(&mut some_ptrs); + /// assert_eq!(view, [null_mut::(); 10]); + /// view + /// .iter_mut() + /// .enumerate() + /// .for_each(|(i, ptr)| *ptr = Box::into_raw(Box::new(format!("iteration#{i}")))); + /// + /// std::thread::scope(|s| { + /// for ptr in &some_ptrs { + /// s.spawn(move || { + /// let ptr = ptr.load(Ordering::Relaxed); + /// assert!(!ptr.is_null()); + /// + /// let name = unsafe { Box::from_raw(ptr) }; + /// println!("Hello, {name}!"); + /// }); + /// } + /// }); + /// ``` + #[inline] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn get_mut_slice(this: &mut [Self]) -> &mut [*mut T] { + // SAFETY: the mutable reference guarantees unique ownership. + unsafe { &mut *(this as *mut [Self] as *mut [*mut T]) } + } + + /// Gets atomic access to a slice of pointers. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut)] + /// use std::ptr::null_mut; + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let mut some_ptrs = [null_mut::(); 10]; + /// let a = &*AtomicPtr::from_mut_slice(&mut some_ptrs); + /// std::thread::scope(|s| { + /// for i in 0..a.len() { + /// s.spawn(move || { + /// let name = Box::new(format!("thread{i}")); + /// a[i].store(Box::into_raw(name), Ordering::Relaxed); + /// }); + /// } + /// }); + /// for p in some_ptrs { + /// assert!(!p.is_null()); + /// let name = unsafe { Box::from_raw(p) }; + /// println!("Hello, {name}!"); + /// } + /// ``` + #[inline] + #[cfg(target_has_atomic_equal_alignment = "ptr")] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn from_mut_slice(v: &mut [*mut T]) -> &mut [Self] { + // SAFETY: + // - the mutable reference guarantees unique ownership. + // - the alignment of `*mut T` and `Self` is the same on all platforms + // supported by rust, as verified above. + unsafe { &mut *(v as *mut [*mut T] as *mut [Self]) } + } + + /// Consumes the atomic and returns the contained value. + /// + /// This is safe because passing `self` by value guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::AtomicPtr; + /// + /// let mut data = 5; + /// let atomic_ptr = AtomicPtr::new(&mut data); + /// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5); + /// ``` + #[inline] + #[stable(feature = "atomic_access", since = "1.15.0")] + #[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")] + pub const fn into_inner(self) -> *mut T { + self.p.into_inner() + } + + /// Loads a value from the pointer. + /// + /// `load` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. + /// + /// # Panics + /// + /// Panics if `order` is [`Release`] or [`AcqRel`]. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let ptr = &mut 5; + /// let some_ptr = AtomicPtr::new(ptr); + /// + /// let value = some_ptr.load(Ordering::Relaxed); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn load(&self, order: Ordering) -> *mut T { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_load(self.p.get(), order) } + } + + /// Stores a value into the pointer. + /// + /// `store` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. + /// + /// # Panics + /// + /// Panics if `order` is [`Acquire`] or [`AcqRel`]. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let ptr = &mut 5; + /// let some_ptr = AtomicPtr::new(ptr); + /// + /// let other_ptr = &mut 10; + /// + /// some_ptr.store(other_ptr, Ordering::Relaxed); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn store(&self, ptr: *mut T, order: Ordering) { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { + atomic_store(self.p.get(), ptr, order); + } + } + + /// Stores a value into the pointer, returning the previous value. + /// + /// `swap` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on pointers. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let ptr = &mut 5; + /// let some_ptr = AtomicPtr::new(ptr); + /// + /// let other_ptr = &mut 10; + /// + /// let value = some_ptr.swap(other_ptr, Ordering::Relaxed); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(target_has_atomic = "ptr")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_swap(self.p.get(), ptr, order) } + } + + /// Stores a value into the pointer if the current value is the same as the `current` value. + /// + /// The return value is always the previous value. If it is equal to `current`, then the value + /// was updated. + /// + /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. Notice that even when using [`AcqRel`], the operation + /// might fail and hence just perform an `Acquire` load, but not have `Release` semantics. + /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it + /// happens, and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on pointers. + /// + /// # Migrating to `compare_exchange` and `compare_exchange_weak` + /// + /// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for + /// memory orderings: + /// + /// Original | Success | Failure + /// -------- | ------- | ------- + /// Relaxed | Relaxed | Relaxed + /// Acquire | Acquire | Acquire + /// Release | Release | Relaxed + /// AcqRel | AcqRel | Acquire + /// SeqCst | SeqCst | SeqCst + /// + /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds, + /// which allows the compiler to generate better assembly code when the compare and swap + /// is used in a loop. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let ptr = &mut 5; + /// let some_ptr = AtomicPtr::new(ptr); + /// + /// let other_ptr = &mut 10; + /// + /// let value = some_ptr.compare_and_swap(ptr, other_ptr, Ordering::Relaxed); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated( + since = "1.50.0", + note = "Use `compare_exchange` or `compare_exchange_weak` instead" + )] + #[cfg(target_has_atomic = "ptr")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T { + match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { + Ok(x) => x, + Err(x) => x, + } + } + + /// Stores a value into the pointer if the current value is the same as the `current` value. + /// + /// The return value is a result indicating whether the new value was written and containing + /// the previous value. On success this value is guaranteed to be equal to `current`. + /// + /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using [`Acquire`] as success ordering makes the store part + /// of this operation [`Relaxed`], and using [`Release`] makes the successful load + /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on pointers. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let ptr = &mut 5; + /// let some_ptr = AtomicPtr::new(ptr); + /// + /// let other_ptr = &mut 10; + /// + /// let value = some_ptr.compare_exchange(ptr, other_ptr, + /// Ordering::SeqCst, Ordering::Relaxed); + /// ``` + #[inline] + #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] + #[cfg(target_has_atomic = "ptr")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn compare_exchange( + &self, + current: *mut T, + new: *mut T, + success: Ordering, + failure: Ordering, + ) -> Result<*mut T, *mut T> { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_compare_exchange(self.p.get(), current, new, success, failure) } + } + + /// Stores a value into the pointer if the current value is the same as the `current` value. + /// + /// Unlike [`AtomicPtr::compare_exchange`], this function is allowed to spuriously fail even when the + /// comparison succeeds, which can result in more efficient code on some platforms. The + /// return value is a result indicating whether the new value was written and containing the + /// previous value. + /// + /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using [`Acquire`] as success ordering makes the store part + /// of this operation [`Relaxed`], and using [`Release`] makes the successful load + /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on pointers. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let some_ptr = AtomicPtr::new(&mut 5); + /// + /// let new = &mut 10; + /// let mut old = some_ptr.load(Ordering::Relaxed); + /// loop { + /// match some_ptr.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { + /// Ok(_) => break, + /// Err(x) => old = x, + /// } + /// } + /// ``` + #[inline] + #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] + #[cfg(target_has_atomic = "ptr")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn compare_exchange_weak( + &self, + current: *mut T, + new: *mut T, + success: Ordering, + failure: Ordering, + ) -> Result<*mut T, *mut T> { + // SAFETY: This intrinsic is unsafe because it operates on a raw pointer + // but we know for sure that the pointer is valid (we just got it from + // an `UnsafeCell` that we have by reference) and the atomic operation + // itself allows us to safely mutate the `UnsafeCell` contents. + unsafe { atomic_compare_exchange_weak(self.p.get(), current, new, success, failure) } + } + + /// Fetches the value, and applies a function to it that returns an optional + /// new value. Returns a `Result` of `Ok(previous_value)` if the function + /// returned `Some(_)`, else `Err(previous_value)`. + /// + /// Note: This may call the function multiple times if the value has been + /// changed from other threads in the meantime, as long as the function + /// returns `Some(_)`, but the function will have been applied only once to + /// the stored value. + /// + /// `fetch_update` takes two [`Ordering`] arguments to describe the memory + /// ordering of this operation. The first describes the required ordering for + /// when the operation finally succeeds while the second describes the + /// required ordering for loads. These correspond to the success and failure + /// orderings of [`AtomicPtr::compare_exchange`] respectively. + /// + /// Using [`Acquire`] as success ordering makes the store part of this + /// operation [`Relaxed`], and using [`Release`] makes the final successful + /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], + /// [`Acquire`] or [`Relaxed`]. + /// + /// **Note:** This method is only available on platforms that support atomic + /// operations on pointers. + /// + /// # Considerations + /// + /// This method is not magic; it is not provided by the hardware. + /// It is implemented in terms of [`AtomicPtr::compare_exchange_weak`], and suffers from the same drawbacks. + /// In particular, this method will not circumvent the [ABA Problem]. + /// + /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem + /// + /// # Examples + /// + /// ```rust + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let ptr: *mut _ = &mut 5; + /// let some_ptr = AtomicPtr::new(ptr); + /// + /// let new: *mut _ = &mut 10; + /// assert_eq!(some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(ptr)); + /// let result = some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { + /// if x == ptr { + /// Some(new) + /// } else { + /// None + /// } + /// }); + /// assert_eq!(result, Ok(ptr)); + /// assert_eq!(some_ptr.load(Ordering::SeqCst), new); + /// ``` + #[inline] + #[stable(feature = "atomic_fetch_update", since = "1.53.0")] + #[cfg(target_has_atomic = "ptr")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_update( + &self, + set_order: Ordering, + fetch_order: Ordering, + mut f: F, + ) -> Result<*mut T, *mut T> + where + F: FnMut(*mut T) -> Option<*mut T>, + { + let mut prev = self.load(fetch_order); + while let Some(next) = f(prev) { + match self.compare_exchange_weak(prev, next, set_order, fetch_order) { + x @ Ok(_) => return x, + Err(next_prev) => prev = next_prev, + } + } + Err(prev) + } + + /// Offsets the pointer's address by adding `val` (in units of `T`), + /// returning the previous pointer. + /// + /// This is equivalent to using [`wrapping_add`] to atomically perform the + /// equivalent of `ptr = ptr.wrapping_add(val);`. + /// + /// This method operates in units of `T`, which means that it cannot be used + /// to offset the pointer by an amount which is not a multiple of + /// `size_of::()`. This can sometimes be inconvenient, as you may want to + /// work with a deliberately misaligned pointer. In such cases, you may use + /// the [`fetch_byte_add`](Self::fetch_byte_add) method instead. + /// + /// `fetch_ptr_add` takes an [`Ordering`] argument which describes the + /// memory ordering of this operation. All ordering modes are possible. Note + /// that using [`Acquire`] makes the store part of this operation + /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic + /// operations on [`AtomicPtr`]. + /// + /// [`wrapping_add`]: pointer::wrapping_add + /// + /// # Examples + /// + /// ``` + /// #![feature(strict_provenance_atomic_ptr)] + /// use core::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let atom = AtomicPtr::::new(core::ptr::null_mut()); + /// assert_eq!(atom.fetch_ptr_add(1, Ordering::Relaxed).addr(), 0); + /// // Note: units of `size_of::()`. + /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 8); + /// ``` + #[inline] + #[cfg(target_has_atomic = "ptr")] + #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T { + self.fetch_byte_add(val.wrapping_mul(core::mem::size_of::()), order) + } + + /// Offsets the pointer's address by subtracting `val` (in units of `T`), + /// returning the previous pointer. + /// + /// This is equivalent to using [`wrapping_sub`] to atomically perform the + /// equivalent of `ptr = ptr.wrapping_sub(val);`. + /// + /// This method operates in units of `T`, which means that it cannot be used + /// to offset the pointer by an amount which is not a multiple of + /// `size_of::()`. This can sometimes be inconvenient, as you may want to + /// work with a deliberately misaligned pointer. In such cases, you may use + /// the [`fetch_byte_sub`](Self::fetch_byte_sub) method instead. + /// + /// `fetch_ptr_sub` takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. All ordering modes are possible. Note that + /// using [`Acquire`] makes the store part of this operation [`Relaxed`], + /// and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic + /// operations on [`AtomicPtr`]. + /// + /// [`wrapping_sub`]: pointer::wrapping_sub + /// + /// # Examples + /// + /// ``` + /// #![feature(strict_provenance_atomic_ptr)] + /// use core::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let array = [1i32, 2i32]; + /// let atom = AtomicPtr::new(array.as_ptr().wrapping_add(1) as *mut _); + /// + /// assert!(core::ptr::eq( + /// atom.fetch_ptr_sub(1, Ordering::Relaxed), + /// &array[1], + /// )); + /// assert!(core::ptr::eq(atom.load(Ordering::Relaxed), &array[0])); + /// ``` + #[inline] + #[cfg(target_has_atomic = "ptr")] + #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T { + self.fetch_byte_sub(val.wrapping_mul(core::mem::size_of::()), order) + } + + /// Offsets the pointer's address by adding `val` *bytes*, returning the + /// previous pointer. + /// + /// This is equivalent to using [`wrapping_byte_add`] to atomically + /// perform `ptr = ptr.wrapping_byte_add(val)`. + /// + /// `fetch_byte_add` takes an [`Ordering`] argument which describes the + /// memory ordering of this operation. All ordering modes are possible. Note + /// that using [`Acquire`] makes the store part of this operation + /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic + /// operations on [`AtomicPtr`]. + /// + /// [`wrapping_byte_add`]: pointer::wrapping_byte_add + /// + /// # Examples + /// + /// ``` + /// #![feature(strict_provenance_atomic_ptr)] + /// use core::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let atom = AtomicPtr::::new(core::ptr::null_mut()); + /// assert_eq!(atom.fetch_byte_add(1, Ordering::Relaxed).addr(), 0); + /// // Note: in units of bytes, not `size_of::()`. + /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 1); + /// ``` + #[inline] + #[cfg(target_has_atomic = "ptr")] + #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_add(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() } + } + + /// Offsets the pointer's address by subtracting `val` *bytes*, returning the + /// previous pointer. + /// + /// This is equivalent to using [`wrapping_byte_sub`] to atomically + /// perform `ptr = ptr.wrapping_byte_sub(val)`. + /// + /// `fetch_byte_sub` takes an [`Ordering`] argument which describes the + /// memory ordering of this operation. All ordering modes are possible. Note + /// that using [`Acquire`] makes the store part of this operation + /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic + /// operations on [`AtomicPtr`]. + /// + /// [`wrapping_byte_sub`]: pointer::wrapping_byte_sub + /// + /// # Examples + /// + /// ``` + /// #![feature(strict_provenance_atomic_ptr)] + /// use core::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let atom = AtomicPtr::::new(core::ptr::without_provenance_mut(1)); + /// assert_eq!(atom.fetch_byte_sub(1, Ordering::Relaxed).addr(), 1); + /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 0); + /// ``` + #[inline] + #[cfg(target_has_atomic = "ptr")] + #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_sub(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() } + } + + /// Performs a bitwise "or" operation on the address of the current pointer, + /// and the argument `val`, and stores a pointer with provenance of the + /// current pointer and the resulting address. + /// + /// This is equivalent to using [`map_addr`] to atomically perform + /// `ptr = ptr.map_addr(|a| a | val)`. This can be used in tagged + /// pointer schemes to atomically set tag bits. + /// + /// **Caveat**: This operation returns the previous value. To compute the + /// stored value without losing provenance, you may use [`map_addr`]. For + /// example: `a.fetch_or(val).map_addr(|a| a | val)`. + /// + /// `fetch_or` takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. All ordering modes are possible. Note that + /// using [`Acquire`] makes the store part of this operation [`Relaxed`], + /// and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic + /// operations on [`AtomicPtr`]. + /// + /// This API and its claimed semantics are part of the Strict Provenance + /// experiment, see the [module documentation for `ptr`][crate::ptr] for + /// details. + /// + /// [`map_addr`]: pointer::map_addr + /// + /// # Examples + /// + /// ``` + /// #![feature(strict_provenance_atomic_ptr)] + /// use core::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let pointer = &mut 3i64 as *mut i64; + /// + /// let atom = AtomicPtr::::new(pointer); + /// // Tag the bottom bit of the pointer. + /// assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 0); + /// // Extract and untag. + /// let tagged = atom.load(Ordering::Relaxed); + /// assert_eq!(tagged.addr() & 1, 1); + /// assert_eq!(tagged.map_addr(|p| p & !1), pointer); + /// ``` + #[inline] + #[cfg(target_has_atomic = "ptr")] + #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_or(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() } + } + + /// Performs a bitwise "and" operation on the address of the current + /// pointer, and the argument `val`, and stores a pointer with provenance of + /// the current pointer and the resulting address. + /// + /// This is equivalent to using [`map_addr`] to atomically perform + /// `ptr = ptr.map_addr(|a| a & val)`. This can be used in tagged + /// pointer schemes to atomically unset tag bits. + /// + /// **Caveat**: This operation returns the previous value. To compute the + /// stored value without losing provenance, you may use [`map_addr`]. For + /// example: `a.fetch_and(val).map_addr(|a| a & val)`. + /// + /// `fetch_and` takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. All ordering modes are possible. Note that + /// using [`Acquire`] makes the store part of this operation [`Relaxed`], + /// and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic + /// operations on [`AtomicPtr`]. + /// + /// This API and its claimed semantics are part of the Strict Provenance + /// experiment, see the [module documentation for `ptr`][crate::ptr] for + /// details. + /// + /// [`map_addr`]: pointer::map_addr + /// + /// # Examples + /// + /// ``` + /// #![feature(strict_provenance_atomic_ptr)] + /// use core::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let pointer = &mut 3i64 as *mut i64; + /// // A tagged pointer + /// let atom = AtomicPtr::::new(pointer.map_addr(|a| a | 1)); + /// assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 1); + /// // Untag, and extract the previously tagged pointer. + /// let untagged = atom.fetch_and(!1, Ordering::Relaxed) + /// .map_addr(|a| a & !1); + /// assert_eq!(untagged, pointer); + /// ``` + #[inline] + #[cfg(target_has_atomic = "ptr")] + #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_and(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() } + } + + /// Performs a bitwise "xor" operation on the address of the current + /// pointer, and the argument `val`, and stores a pointer with provenance of + /// the current pointer and the resulting address. + /// + /// This is equivalent to using [`map_addr`] to atomically perform + /// `ptr = ptr.map_addr(|a| a ^ val)`. This can be used in tagged + /// pointer schemes to atomically toggle tag bits. + /// + /// **Caveat**: This operation returns the previous value. To compute the + /// stored value without losing provenance, you may use [`map_addr`]. For + /// example: `a.fetch_xor(val).map_addr(|a| a ^ val)`. + /// + /// `fetch_xor` takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. All ordering modes are possible. Note that + /// using [`Acquire`] makes the store part of this operation [`Relaxed`], + /// and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic + /// operations on [`AtomicPtr`]. + /// + /// This API and its claimed semantics are part of the Strict Provenance + /// experiment, see the [module documentation for `ptr`][crate::ptr] for + /// details. + /// + /// [`map_addr`]: pointer::map_addr + /// + /// # Examples + /// + /// ``` + /// #![feature(strict_provenance_atomic_ptr)] + /// use core::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let pointer = &mut 3i64 as *mut i64; + /// let atom = AtomicPtr::::new(pointer); + /// + /// // Toggle a tag bit on the pointer. + /// atom.fetch_xor(1, Ordering::Relaxed); + /// assert_eq!(atom.load(Ordering::Relaxed).addr() & 1, 1); + /// ``` + #[inline] + #[cfg(target_has_atomic = "ptr")] + #[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_xor(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() } + } + + /// Returns a mutable pointer to the underlying pointer. + /// + /// Doing non-atomic reads and writes on the resulting pointer can be a data race. + /// This method is mostly useful for FFI, where the function signature may use + /// `*mut *mut T` instead of `&AtomicPtr`. + /// + /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the + /// atomic types work with interior mutability. All modifications of an atomic change the value + /// through a shared reference, and can do so safely as long as they use atomic operations. Any + /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same + /// restriction: operations on it must be atomic. + /// + /// # Examples + /// + /// ```ignore (extern-declaration) + /// use std::sync::atomic::AtomicPtr; + /// + /// extern "C" { + /// fn my_atomic_op(arg: *mut *mut u32); + /// } + /// + /// let mut value = 17; + /// let atomic = AtomicPtr::new(&mut value); + /// + /// // SAFETY: Safe as long as `my_atomic_op` is atomic. + /// unsafe { + /// my_atomic_op(atomic.as_ptr()); + /// } + /// ``` + #[inline] + #[stable(feature = "atomic_as_ptr", since = "1.70.0")] + #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] + #[rustc_never_returns_null_ptr] + pub const fn as_ptr(&self) -> *mut *mut T { + self.p.get() + } +} + +#[cfg(target_has_atomic_load_store = "8")] +#[stable(feature = "atomic_bool_from", since = "1.24.0")] +impl From for AtomicBool { + /// Converts a `bool` into an `AtomicBool`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::AtomicBool; + /// let atomic_bool = AtomicBool::from(true); + /// assert_eq!(format!("{atomic_bool:?}"), "true") + /// ``` + #[inline] + fn from(b: bool) -> Self { + Self::new(b) + } +} + +#[cfg(target_has_atomic_load_store = "ptr")] +#[stable(feature = "atomic_from", since = "1.23.0")] +impl From<*mut T> for AtomicPtr { + /// Converts a `*mut T` into an `AtomicPtr`. + #[inline] + fn from(p: *mut T) -> Self { + Self::new(p) + } +} + +#[allow(unused_macros)] // This macro ends up being unused on some architectures. +macro_rules! if_8_bit { + (u8, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($yes)*)?) }; + (i8, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($yes)*)?) }; + ($_:ident, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($no)*)?) }; +} + +#[cfg(target_has_atomic_load_store)] +macro_rules! atomic_int { + ($cfg_cas:meta, + $cfg_align:meta, + $stable:meta, + $stable_cxchg:meta, + $stable_debug:meta, + $stable_access:meta, + $stable_from:meta, + $stable_nand:meta, + $const_stable_new:meta, + $const_stable_into_inner:meta, + $diagnostic_item:meta, + $s_int_type:literal, + $extra_feature:expr, + $min_fn:ident, $max_fn:ident, + $align:expr, + $int_type:ident $atomic_type:ident) => { + /// An integer type which can be safely shared between threads. + /// + /// This type has the same + #[doc = if_8_bit!( + $int_type, + yes = ["size, alignment, and bit validity"], + no = ["size and bit validity"], + )] + /// as the underlying integer type, [` + #[doc = $s_int_type] + /// `]. + #[doc = if_8_bit! { + $int_type, + no = [ + "However, the alignment of this type is always equal to its ", + "size, even on targets where [`", $s_int_type, "`] has a ", + "lesser alignment." + ], + }] + /// + /// For more about the differences between atomic types and + /// non-atomic types as well as information about the portability of + /// this type, please see the [module-level documentation]. + /// + /// **Note:** This type is only available on platforms that support + /// atomic loads and stores of [` + #[doc = $s_int_type] + /// `]. + /// + /// [module-level documentation]: crate::sync::atomic + #[$stable] + #[$diagnostic_item] + #[repr(C, align($align))] + pub struct $atomic_type { + v: UnsafeCell<$int_type>, + } + + #[$stable] + impl Default for $atomic_type { + #[inline] + fn default() -> Self { + Self::new(Default::default()) + } + } + + #[$stable_from] + impl From<$int_type> for $atomic_type { + #[doc = concat!("Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`.")] + #[inline] + fn from(v: $int_type) -> Self { Self::new(v) } + } + + #[$stable_debug] + impl fmt::Debug for $atomic_type { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.load(Ordering::Relaxed), f) + } + } + + // Send is implicitly implemented. + #[$stable] + unsafe impl Sync for $atomic_type {} + + impl $atomic_type { + /// Creates a new atomic integer. + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")] + /// + #[doc = concat!("let atomic_forty_two = ", stringify!($atomic_type), "::new(42);")] + /// ``` + #[inline] + #[$stable] + #[$const_stable_new] + #[must_use] + pub const fn new(v: $int_type) -> Self { + Self {v: UnsafeCell::new(v)} + } + + /// Creates a new reference to an atomic integer from a pointer. + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{self, ", stringify!($atomic_type), "};")] + /// + /// // Get a pointer to an allocated value + #[doc = concat!("let ptr: *mut ", stringify!($int_type), " = Box::into_raw(Box::new(0));")] + /// + #[doc = concat!("assert!(ptr.cast::<", stringify!($atomic_type), ">().is_aligned());")] + /// + /// { + /// // Create an atomic view of the allocated value + // SAFETY: this is a doc comment, tidy, it can't hurt you (also guaranteed by the construction of `ptr` and the assert above) + #[doc = concat!(" let atomic = unsafe {", stringify!($atomic_type), "::from_ptr(ptr) };")] + /// + /// // Use `atomic` for atomic operations, possibly share it with other threads + /// atomic.store(1, atomic::Ordering::Relaxed); + /// } + /// + /// // It's ok to non-atomically access the value behind `ptr`, + /// // since the reference to the atomic ended its lifetime in the block above + /// assert_eq!(unsafe { *ptr }, 1); + /// + /// // Deallocate the value + /// unsafe { drop(Box::from_raw(ptr)) } + /// ``` + /// + /// # Safety + /// + /// * `ptr` must be aligned to + #[doc = concat!(" `align_of::<", stringify!($atomic_type), ">()`")] + #[doc = if_8_bit!{ + $int_type, + yes = [ + " (note that this is always true, since `align_of::<", + stringify!($atomic_type), ">() == 1`)." + ], + no = [ + " (note that on some platforms this can be bigger than `align_of::<", + stringify!($int_type), ">()`)." + ], + }] + /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. + /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not + /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes, + /// without synchronization. + /// + /// [valid]: crate::ptr#safety + /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses + #[stable(feature = "atomic_from_ptr", since = "1.75.0")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] + pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type { + // SAFETY: guaranteed by the caller + unsafe { &*ptr.cast() } + } + + + /// Returns a mutable reference to the underlying integer. + /// + /// This is safe because the mutable reference guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let mut some_var = ", stringify!($atomic_type), "::new(10);")] + /// assert_eq!(*some_var.get_mut(), 10); + /// *some_var.get_mut() = 5; + /// assert_eq!(some_var.load(Ordering::SeqCst), 5); + /// ``` + #[inline] + #[$stable_access] + pub fn get_mut(&mut self) -> &mut $int_type { + self.v.get_mut() + } + + #[doc = concat!("Get atomic access to a `&mut ", stringify!($int_type), "`.")] + /// + #[doc = if_8_bit! { + $int_type, + no = [ + "**Note:** This function is only available on targets where `", + stringify!($int_type), "` has an alignment of ", $align, " bytes." + ], + }] + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut)] + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + /// let mut some_int = 123; + #[doc = concat!("let a = ", stringify!($atomic_type), "::from_mut(&mut some_int);")] + /// a.store(100, Ordering::Relaxed); + /// assert_eq!(some_int, 100); + /// ``` + /// + #[inline] + #[$cfg_align] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn from_mut(v: &mut $int_type) -> &mut Self { + let [] = [(); align_of::() - align_of::<$int_type>()]; + // SAFETY: + // - the mutable reference guarantees unique ownership. + // - the alignment of `$int_type` and `Self` is the + // same, as promised by $cfg_align and verified above. + unsafe { &mut *(v as *mut $int_type as *mut Self) } + } + + #[doc = concat!("Get non-atomic access to a `&mut [", stringify!($atomic_type), "]` slice")] + /// + /// This is safe because the mutable reference guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut)] + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let mut some_ints = [const { ", stringify!($atomic_type), "::new(0) }; 10];")] + /// + #[doc = concat!("let view: &mut [", stringify!($int_type), "] = ", stringify!($atomic_type), "::get_mut_slice(&mut some_ints);")] + /// assert_eq!(view, [0; 10]); + /// view + /// .iter_mut() + /// .enumerate() + /// .for_each(|(idx, int)| *int = idx as _); + /// + /// std::thread::scope(|s| { + /// some_ints + /// .iter() + /// .enumerate() + /// .for_each(|(idx, int)| { + /// s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _)); + /// }) + /// }); + /// ``` + #[inline] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn get_mut_slice(this: &mut [Self]) -> &mut [$int_type] { + // SAFETY: the mutable reference guarantees unique ownership. + unsafe { &mut *(this as *mut [Self] as *mut [$int_type]) } + } + + #[doc = concat!("Get atomic access to a `&mut [", stringify!($int_type), "]` slice.")] + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut)] + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + /// let mut some_ints = [0; 10]; + #[doc = concat!("let a = &*", stringify!($atomic_type), "::from_mut_slice(&mut some_ints);")] + /// std::thread::scope(|s| { + /// for i in 0..a.len() { + /// s.spawn(move || a[i].store(i as _, Ordering::Relaxed)); + /// } + /// }); + /// for (i, n) in some_ints.into_iter().enumerate() { + /// assert_eq!(i, n as usize); + /// } + /// ``` + #[inline] + #[$cfg_align] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn from_mut_slice(v: &mut [$int_type]) -> &mut [Self] { + let [] = [(); align_of::() - align_of::<$int_type>()]; + // SAFETY: + // - the mutable reference guarantees unique ownership. + // - the alignment of `$int_type` and `Self` is the + // same, as promised by $cfg_align and verified above. + unsafe { &mut *(v as *mut [$int_type] as *mut [Self]) } + } + + /// Consumes the atomic and returns the contained value. + /// + /// This is safe because passing `self` by value guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")] + /// + #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")] + /// assert_eq!(some_var.into_inner(), 5); + /// ``` + #[inline] + #[$stable_access] + #[$const_stable_into_inner] + pub const fn into_inner(self) -> $int_type { + self.v.into_inner() + } + + /// Loads a value from the atomic integer. + /// + /// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation. + /// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. + /// + /// # Panics + /// + /// Panics if `order` is [`Release`] or [`AcqRel`]. + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")] + /// + /// assert_eq!(some_var.load(Ordering::Relaxed), 5); + /// ``` + #[inline] + #[$stable] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn load(&self, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_load(self.v.get(), order) } + } + + /// Stores a value into the atomic integer. + /// + /// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation. + /// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. + /// + /// # Panics + /// + /// Panics if `order` is [`Acquire`] or [`AcqRel`]. + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")] + /// + /// some_var.store(10, Ordering::Relaxed); + /// assert_eq!(some_var.load(Ordering::Relaxed), 10); + /// ``` + #[inline] + #[$stable] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn store(&self, val: $int_type, order: Ordering) { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_store(self.v.get(), val, order); } + } + + /// Stores a value into the atomic integer, returning the previous value. + /// + /// `swap` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")] + /// + /// assert_eq!(some_var.swap(10, Ordering::Relaxed), 5); + /// ``` + #[inline] + #[$stable] + #[$cfg_cas] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_swap(self.v.get(), val, order) } + } + + /// Stores a value into the atomic integer if the current value is the same as + /// the `current` value. + /// + /// The return value is always the previous value. If it is equal to `current`, then the + /// value was updated. + /// + /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. Notice that even when using [`AcqRel`], the operation + /// might fail and hence just perform an `Acquire` load, but not have `Release` semantics. + /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it + /// happens, and using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`].")] + /// + /// # Migrating to `compare_exchange` and `compare_exchange_weak` + /// + /// `compare_and_swap` is equivalent to `compare_exchange` with the following mapping for + /// memory orderings: + /// + /// Original | Success | Failure + /// -------- | ------- | ------- + /// Relaxed | Relaxed | Relaxed + /// Acquire | Acquire | Acquire + /// Release | Release | Relaxed + /// AcqRel | AcqRel | Acquire + /// SeqCst | SeqCst | SeqCst + /// + /// `compare_exchange_weak` is allowed to fail spuriously even when the comparison succeeds, + /// which allows the compiler to generate better assembly code when the compare and swap + /// is used in a loop. + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")] + /// + /// assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5); + /// assert_eq!(some_var.load(Ordering::Relaxed), 10); + /// + /// assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10); + /// assert_eq!(some_var.load(Ordering::Relaxed), 10); + /// ``` + #[inline] + #[$stable] + #[deprecated( + since = "1.50.0", + note = "Use `compare_exchange` or `compare_exchange_weak` instead") + ] + #[$cfg_cas] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn compare_and_swap(&self, + current: $int_type, + new: $int_type, + order: Ordering) -> $int_type { + match self.compare_exchange(current, + new, + order, + strongest_failure_ordering(order)) { + Ok(x) => x, + Err(x) => x, + } + } + + /// Stores a value into the atomic integer if the current value is the same as + /// the `current` value. + /// + /// The return value is a result indicating whether the new value was written and + /// containing the previous value. On success this value is guaranteed to be equal to + /// `current`. + /// + /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using [`Acquire`] as success ordering makes the store part + /// of this operation [`Relaxed`], and using [`Release`] makes the successful load + /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")] + /// + /// assert_eq!(some_var.compare_exchange(5, 10, + /// Ordering::Acquire, + /// Ordering::Relaxed), + /// Ok(5)); + /// assert_eq!(some_var.load(Ordering::Relaxed), 10); + /// + /// assert_eq!(some_var.compare_exchange(6, 12, + /// Ordering::SeqCst, + /// Ordering::Acquire), + /// Err(10)); + /// assert_eq!(some_var.load(Ordering::Relaxed), 10); + /// ``` + #[inline] + #[$stable_cxchg] + #[$cfg_cas] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn compare_exchange(&self, + current: $int_type, + new: $int_type, + success: Ordering, + failure: Ordering) -> Result<$int_type, $int_type> { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) } + } + + /// Stores a value into the atomic integer if the current value is the same as + /// the `current` value. + /// + #[doc = concat!("Unlike [`", stringify!($atomic_type), "::compare_exchange`],")] + /// this function is allowed to spuriously fail even + /// when the comparison succeeds, which can result in more efficient code on some + /// platforms. The return value is a result indicating whether the new value was + /// written and containing the previous value. + /// + /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using [`Acquire`] as success ordering makes the store part + /// of this operation [`Relaxed`], and using [`Release`] makes the successful load + /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let val = ", stringify!($atomic_type), "::new(4);")] + /// + /// let mut old = val.load(Ordering::Relaxed); + /// loop { + /// let new = old * 2; + /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { + /// Ok(_) => break, + /// Err(x) => old = x, + /// } + /// } + /// ``` + #[inline] + #[$stable_cxchg] + #[$cfg_cas] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn compare_exchange_weak(&self, + current: $int_type, + new: $int_type, + success: Ordering, + failure: Ordering) -> Result<$int_type, $int_type> { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { + atomic_compare_exchange_weak(self.v.get(), current, new, success, failure) + } + } + + /// Adds to the current value, returning the previous value. + /// + /// This operation wraps around on overflow. + /// + /// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0);")] + /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0); + /// assert_eq!(foo.load(Ordering::SeqCst), 10); + /// ``` + #[inline] + #[$stable] + #[$cfg_cas] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_add(self.v.get(), val, order) } + } + + /// Subtracts from the current value, returning the previous value. + /// + /// This operation wraps around on overflow. + /// + /// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(20);")] + /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20); + /// assert_eq!(foo.load(Ordering::SeqCst), 10); + /// ``` + #[inline] + #[$stable] + #[$cfg_cas] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_sub(self.v.get(), val, order) } + } + + /// Bitwise "and" with the current value. + /// + /// Performs a bitwise "and" operation on the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")] + /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101); + /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001); + /// ``` + #[inline] + #[$stable] + #[$cfg_cas] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_and(self.v.get(), val, order) } + } + + /// Bitwise "nand" with the current value. + /// + /// Performs a bitwise "nand" operation on the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0x13);")] + /// assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13); + /// assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31)); + /// ``` + #[inline] + #[$stable_nand] + #[$cfg_cas] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_nand(self.v.get(), val, order) } + } + + /// Bitwise "or" with the current value. + /// + /// Performs a bitwise "or" operation on the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")] + /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101); + /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111); + /// ``` + #[inline] + #[$stable] + #[$cfg_cas] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_or(self.v.get(), val, order) } + } + + /// Bitwise "xor" with the current value. + /// + /// Performs a bitwise "xor" operation on the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")] + /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101); + /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110); + /// ``` + #[inline] + #[$stable] + #[$cfg_cas] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { atomic_xor(self.v.get(), val, order) } + } + + /// Fetches the value, and applies a function to it that returns an optional + /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else + /// `Err(previous_value)`. + /// + /// Note: This may call the function multiple times if the value has been changed from other threads in + /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied + /// only once to the stored value. + /// + /// `fetch_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation. + /// The first describes the required ordering for when the operation finally succeeds while the second + /// describes the required ordering for loads. These correspond to the success and failure orderings of + #[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange`]")] + /// respectively. + /// + /// Using [`Acquire`] as success ordering makes the store part + /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load + /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`].")] + /// + /// # Considerations + /// + /// This method is not magic; it is not provided by the hardware. + /// It is implemented in terms of + #[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange_weak`],")] + /// and suffers from the same drawbacks. + /// In particular, this method will not circumvent the [ABA Problem]. + /// + /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem + /// + /// # Examples + /// + /// ```rust + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")] + /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7)); + /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7)); + /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8)); + /// assert_eq!(x.load(Ordering::SeqCst), 9); + /// ``` + #[inline] + #[stable(feature = "no_more_cas", since = "1.45.0")] + #[$cfg_cas] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_update(&self, + set_order: Ordering, + fetch_order: Ordering, + mut f: F) -> Result<$int_type, $int_type> + where F: FnMut($int_type) -> Option<$int_type> { + let mut prev = self.load(fetch_order); + while let Some(next) = f(prev) { + match self.compare_exchange_weak(prev, next, set_order, fetch_order) { + x @ Ok(_) => return x, + Err(next_prev) => prev = next_prev + } + } + Err(prev) + } + + /// Maximum with the current value. + /// + /// Finds the maximum of the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")] + /// assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23); + /// assert_eq!(foo.load(Ordering::SeqCst), 42); + /// ``` + /// + /// If you want to obtain the maximum value in one step, you can use the following: + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")] + /// let bar = 42; + /// let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar); + /// assert!(max_foo == 42); + /// ``` + #[inline] + #[stable(feature = "atomic_min_max", since = "1.45.0")] + #[$cfg_cas] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { $max_fn(self.v.get(), val, order) } + } + + /// Minimum with the current value. + /// + /// Finds the minimum of the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. + /// + /// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// **Note**: This method is only available on platforms that support atomic operations on + #[doc = concat!("[`", $s_int_type, "`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")] + /// assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23); + /// assert_eq!(foo.load(Ordering::Relaxed), 23); + /// assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23); + /// assert_eq!(foo.load(Ordering::Relaxed), 22); + /// ``` + /// + /// If you want to obtain the minimum value in one step, you can use the following: + /// + /// ``` + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")] + /// let bar = 12; + /// let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar); + /// assert_eq!(min_foo, 12); + /// ``` + #[inline] + #[stable(feature = "atomic_min_max", since = "1.45.0")] + #[$cfg_cas] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. + unsafe { $min_fn(self.v.get(), val, order) } + } + + /// Returns a mutable pointer to the underlying integer. + /// + /// Doing non-atomic reads and writes on the resulting integer can be a data race. + /// This method is mostly useful for FFI, where the function signature may use + #[doc = concat!("`*mut ", stringify!($int_type), "` instead of `&", stringify!($atomic_type), "`.")] + /// + /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the + /// atomic types work with interior mutability. All modifications of an atomic change the value + /// through a shared reference, and can do so safely as long as they use atomic operations. Any + /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same + /// restriction: operations on it must be atomic. + /// + /// # Examples + /// + /// ```ignore (extern-declaration) + /// # fn main() { + #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")] + /// + /// extern "C" { + #[doc = concat!(" fn my_atomic_op(arg: *mut ", stringify!($int_type), ");")] + /// } + /// + #[doc = concat!("let atomic = ", stringify!($atomic_type), "::new(1);")] + /// + /// // SAFETY: Safe as long as `my_atomic_op` is atomic. + /// unsafe { + /// my_atomic_op(atomic.as_ptr()); + /// } + /// # } + /// ``` + #[inline] + #[stable(feature = "atomic_as_ptr", since = "1.70.0")] + #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] + #[rustc_never_returns_null_ptr] + pub const fn as_ptr(&self) -> *mut $int_type { + self.v.get() + } + } + } +} + +#[cfg(target_has_atomic_load_store = "8")] +atomic_int! { + cfg(target_has_atomic = "8"), + cfg(target_has_atomic_equal_alignment = "8"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), + rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), + cfg_attr(not(test), rustc_diagnostic_item = "AtomicI8"), + "i8", + "", + atomic_min, atomic_max, + 1, + i8 AtomicI8 +} +#[cfg(target_has_atomic_load_store = "8")] +atomic_int! { + cfg(target_has_atomic = "8"), + cfg(target_has_atomic_equal_alignment = "8"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), + rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), + cfg_attr(not(test), rustc_diagnostic_item = "AtomicU8"), + "u8", + "", + atomic_umin, atomic_umax, + 1, + u8 AtomicU8 +} +#[cfg(target_has_atomic_load_store = "16")] +atomic_int! { + cfg(target_has_atomic = "16"), + cfg(target_has_atomic_equal_alignment = "16"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), + rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), + cfg_attr(not(test), rustc_diagnostic_item = "AtomicI16"), + "i16", + "", + atomic_min, atomic_max, + 2, + i16 AtomicI16 +} +#[cfg(target_has_atomic_load_store = "16")] +atomic_int! { + cfg(target_has_atomic = "16"), + cfg(target_has_atomic_equal_alignment = "16"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), + rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), + cfg_attr(not(test), rustc_diagnostic_item = "AtomicU16"), + "u16", + "", + atomic_umin, atomic_umax, + 2, + u16 AtomicU16 +} +#[cfg(target_has_atomic_load_store = "32")] +atomic_int! { + cfg(target_has_atomic = "32"), + cfg(target_has_atomic_equal_alignment = "32"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), + rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), + cfg_attr(not(test), rustc_diagnostic_item = "AtomicI32"), + "i32", + "", + atomic_min, atomic_max, + 4, + i32 AtomicI32 +} +#[cfg(target_has_atomic_load_store = "32")] +atomic_int! { + cfg(target_has_atomic = "32"), + cfg(target_has_atomic_equal_alignment = "32"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), + rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), + cfg_attr(not(test), rustc_diagnostic_item = "AtomicU32"), + "u32", + "", + atomic_umin, atomic_umax, + 4, + u32 AtomicU32 +} +#[cfg(target_has_atomic_load_store = "64")] +atomic_int! { + cfg(target_has_atomic = "64"), + cfg(target_has_atomic_equal_alignment = "64"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), + rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), + cfg_attr(not(test), rustc_diagnostic_item = "AtomicI64"), + "i64", + "", + atomic_min, atomic_max, + 8, + i64 AtomicI64 +} +#[cfg(target_has_atomic_load_store = "64")] +atomic_int! { + cfg(target_has_atomic = "64"), + cfg(target_has_atomic_equal_alignment = "64"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), + rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), + cfg_attr(not(test), rustc_diagnostic_item = "AtomicU64"), + "u64", + "", + atomic_umin, atomic_umax, + 8, + u64 AtomicU64 +} +#[cfg(target_has_atomic_load_store = "128")] +atomic_int! { + cfg(target_has_atomic = "128"), + cfg(target_has_atomic_equal_alignment = "128"), + unstable(feature = "integer_atomics", issue = "99069"), + unstable(feature = "integer_atomics", issue = "99069"), + unstable(feature = "integer_atomics", issue = "99069"), + unstable(feature = "integer_atomics", issue = "99069"), + unstable(feature = "integer_atomics", issue = "99069"), + unstable(feature = "integer_atomics", issue = "99069"), + rustc_const_unstable(feature = "integer_atomics", issue = "99069"), + rustc_const_unstable(feature = "integer_atomics", issue = "99069"), + cfg_attr(not(test), rustc_diagnostic_item = "AtomicI128"), + "i128", + "#![feature(integer_atomics)]\n\n", + atomic_min, atomic_max, + 16, + i128 AtomicI128 +} +#[cfg(target_has_atomic_load_store = "128")] +atomic_int! { + cfg(target_has_atomic = "128"), + cfg(target_has_atomic_equal_alignment = "128"), + unstable(feature = "integer_atomics", issue = "99069"), + unstable(feature = "integer_atomics", issue = "99069"), + unstable(feature = "integer_atomics", issue = "99069"), + unstable(feature = "integer_atomics", issue = "99069"), + unstable(feature = "integer_atomics", issue = "99069"), + unstable(feature = "integer_atomics", issue = "99069"), + rustc_const_unstable(feature = "integer_atomics", issue = "99069"), + rustc_const_unstable(feature = "integer_atomics", issue = "99069"), + cfg_attr(not(test), rustc_diagnostic_item = "AtomicU128"), + "u128", + "#![feature(integer_atomics)]\n\n", + atomic_umin, atomic_umax, + 16, + u128 AtomicU128 +} + +#[cfg(target_has_atomic_load_store = "ptr")] +macro_rules! atomic_int_ptr_sized { + ( $($target_pointer_width:literal $align:literal)* ) => { $( + #[cfg(target_pointer_width = $target_pointer_width)] + atomic_int! { + cfg(target_has_atomic = "ptr"), + cfg(target_has_atomic_equal_alignment = "ptr"), + stable(feature = "rust1", since = "1.0.0"), + stable(feature = "extended_compare_and_swap", since = "1.10.0"), + stable(feature = "atomic_debug", since = "1.3.0"), + stable(feature = "atomic_access", since = "1.15.0"), + stable(feature = "atomic_from", since = "1.23.0"), + stable(feature = "atomic_nand", since = "1.27.0"), + rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"), + rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), + cfg_attr(not(test), rustc_diagnostic_item = "AtomicIsize"), + "isize", + "", + atomic_min, atomic_max, + $align, + isize AtomicIsize + } + #[cfg(target_pointer_width = $target_pointer_width)] + atomic_int! { + cfg(target_has_atomic = "ptr"), + cfg(target_has_atomic_equal_alignment = "ptr"), + stable(feature = "rust1", since = "1.0.0"), + stable(feature = "extended_compare_and_swap", since = "1.10.0"), + stable(feature = "atomic_debug", since = "1.3.0"), + stable(feature = "atomic_access", since = "1.15.0"), + stable(feature = "atomic_from", since = "1.23.0"), + stable(feature = "atomic_nand", since = "1.27.0"), + rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"), + rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), + cfg_attr(not(test), rustc_diagnostic_item = "AtomicUsize"), + "usize", + "", + atomic_umin, atomic_umax, + $align, + usize AtomicUsize + } + + /// An [`AtomicIsize`] initialized to `0`. + #[cfg(target_pointer_width = $target_pointer_width)] + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated( + since = "1.34.0", + note = "the `new` function is now preferred", + suggestion = "AtomicIsize::new(0)", + )] + pub const ATOMIC_ISIZE_INIT: AtomicIsize = AtomicIsize::new(0); + + /// An [`AtomicUsize`] initialized to `0`. + #[cfg(target_pointer_width = $target_pointer_width)] + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated( + since = "1.34.0", + note = "the `new` function is now preferred", + suggestion = "AtomicUsize::new(0)", + )] + pub const ATOMIC_USIZE_INIT: AtomicUsize = AtomicUsize::new(0); + )* }; +} + +#[cfg(target_has_atomic_load_store = "ptr")] +atomic_int_ptr_sized! { + "16" 2 + "32" 4 + "64" 8 +} + +#[inline] +#[cfg(target_has_atomic)] +fn strongest_failure_ordering(order: Ordering) -> Ordering { + match order { + Release => Relaxed, + Relaxed => Relaxed, + SeqCst => SeqCst, + Acquire => Acquire, + AcqRel => Acquire, + } +} + +#[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_store(dst: *mut T, val: T, order: Ordering) { + // SAFETY: the caller must uphold the safety contract for `atomic_store`. + unsafe { + match order { + Relaxed => intrinsics::atomic_store_relaxed(dst, val), + Release => intrinsics::atomic_store_release(dst, val), + SeqCst => intrinsics::atomic_store_seqcst(dst, val), + Acquire => panic!("there is no such thing as an acquire store"), + AcqRel => panic!("there is no such thing as an acquire-release store"), + } + } +} + +#[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { + // SAFETY: the caller must uphold the safety contract for `atomic_load`. + unsafe { + match order { + Relaxed => intrinsics::atomic_load_relaxed(dst), + Acquire => intrinsics::atomic_load_acquire(dst), + SeqCst => intrinsics::atomic_load_seqcst(dst), + Release => panic!("there is no such thing as a release load"), + AcqRel => panic!("there is no such thing as an acquire-release load"), + } + } +} + +#[inline] +#[cfg(target_has_atomic)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { + // SAFETY: the caller must uphold the safety contract for `atomic_swap`. + unsafe { + match order { + Relaxed => intrinsics::atomic_xchg_relaxed(dst, val), + Acquire => intrinsics::atomic_xchg_acquire(dst, val), + Release => intrinsics::atomic_xchg_release(dst, val), + AcqRel => intrinsics::atomic_xchg_acqrel(dst, val), + SeqCst => intrinsics::atomic_xchg_seqcst(dst, val), + } + } +} + +/// Returns the previous value (like __sync_fetch_and_add). +#[inline] +#[cfg(target_has_atomic)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { + // SAFETY: the caller must uphold the safety contract for `atomic_add`. + unsafe { + match order { + Relaxed => intrinsics::atomic_xadd_relaxed(dst, val), + Acquire => intrinsics::atomic_xadd_acquire(dst, val), + Release => intrinsics::atomic_xadd_release(dst, val), + AcqRel => intrinsics::atomic_xadd_acqrel(dst, val), + SeqCst => intrinsics::atomic_xadd_seqcst(dst, val), + } + } +} + +/// Returns the previous value (like __sync_fetch_and_sub). +#[inline] +#[cfg(target_has_atomic)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { + // SAFETY: the caller must uphold the safety contract for `atomic_sub`. + unsafe { + match order { + Relaxed => intrinsics::atomic_xsub_relaxed(dst, val), + Acquire => intrinsics::atomic_xsub_acquire(dst, val), + Release => intrinsics::atomic_xsub_release(dst, val), + AcqRel => intrinsics::atomic_xsub_acqrel(dst, val), + SeqCst => intrinsics::atomic_xsub_seqcst(dst, val), + } + } +} + +#[inline] +#[cfg(target_has_atomic)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_compare_exchange( + dst: *mut T, + old: T, + new: T, + success: Ordering, + failure: Ordering, +) -> Result { + // SAFETY: the caller must uphold the safety contract for `atomic_compare_exchange`. + let (val, ok) = unsafe { + match (success, failure) { + (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed_relaxed(dst, old, new), + (Relaxed, Acquire) => intrinsics::atomic_cxchg_relaxed_acquire(dst, old, new), + (Relaxed, SeqCst) => intrinsics::atomic_cxchg_relaxed_seqcst(dst, old, new), + (Acquire, Relaxed) => intrinsics::atomic_cxchg_acquire_relaxed(dst, old, new), + (Acquire, Acquire) => intrinsics::atomic_cxchg_acquire_acquire(dst, old, new), + (Acquire, SeqCst) => intrinsics::atomic_cxchg_acquire_seqcst(dst, old, new), + (Release, Relaxed) => intrinsics::atomic_cxchg_release_relaxed(dst, old, new), + (Release, Acquire) => intrinsics::atomic_cxchg_release_acquire(dst, old, new), + (Release, SeqCst) => intrinsics::atomic_cxchg_release_seqcst(dst, old, new), + (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_relaxed(dst, old, new), + (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel_acquire(dst, old, new), + (AcqRel, SeqCst) => intrinsics::atomic_cxchg_acqrel_seqcst(dst, old, new), + (SeqCst, Relaxed) => intrinsics::atomic_cxchg_seqcst_relaxed(dst, old, new), + (SeqCst, Acquire) => intrinsics::atomic_cxchg_seqcst_acquire(dst, old, new), + (SeqCst, SeqCst) => intrinsics::atomic_cxchg_seqcst_seqcst(dst, old, new), + (_, AcqRel) => panic!("there is no such thing as an acquire-release failure ordering"), + (_, Release) => panic!("there is no such thing as a release failure ordering"), + } + }; + if ok { Ok(val) } else { Err(val) } +} + +#[inline] +#[cfg(target_has_atomic)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_compare_exchange_weak( + dst: *mut T, + old: T, + new: T, + success: Ordering, + failure: Ordering, +) -> Result { + // SAFETY: the caller must uphold the safety contract for `atomic_compare_exchange_weak`. + let (val, ok) = unsafe { + match (success, failure) { + (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed_relaxed(dst, old, new), + (Relaxed, Acquire) => intrinsics::atomic_cxchgweak_relaxed_acquire(dst, old, new), + (Relaxed, SeqCst) => intrinsics::atomic_cxchgweak_relaxed_seqcst(dst, old, new), + (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acquire_relaxed(dst, old, new), + (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acquire_acquire(dst, old, new), + (Acquire, SeqCst) => intrinsics::atomic_cxchgweak_acquire_seqcst(dst, old, new), + (Release, Relaxed) => intrinsics::atomic_cxchgweak_release_relaxed(dst, old, new), + (Release, Acquire) => intrinsics::atomic_cxchgweak_release_acquire(dst, old, new), + (Release, SeqCst) => intrinsics::atomic_cxchgweak_release_seqcst(dst, old, new), + (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_relaxed(dst, old, new), + (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel_acquire(dst, old, new), + (AcqRel, SeqCst) => intrinsics::atomic_cxchgweak_acqrel_seqcst(dst, old, new), + (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_seqcst_relaxed(dst, old, new), + (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_seqcst_acquire(dst, old, new), + (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak_seqcst_seqcst(dst, old, new), + (_, AcqRel) => panic!("there is no such thing as an acquire-release failure ordering"), + (_, Release) => panic!("there is no such thing as a release failure ordering"), + } + }; + if ok { Ok(val) } else { Err(val) } +} + +#[inline] +#[cfg(target_has_atomic)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { + // SAFETY: the caller must uphold the safety contract for `atomic_and` + unsafe { + match order { + Relaxed => intrinsics::atomic_and_relaxed(dst, val), + Acquire => intrinsics::atomic_and_acquire(dst, val), + Release => intrinsics::atomic_and_release(dst, val), + AcqRel => intrinsics::atomic_and_acqrel(dst, val), + SeqCst => intrinsics::atomic_and_seqcst(dst, val), + } + } +} + +#[inline] +#[cfg(target_has_atomic)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { + // SAFETY: the caller must uphold the safety contract for `atomic_nand` + unsafe { + match order { + Relaxed => intrinsics::atomic_nand_relaxed(dst, val), + Acquire => intrinsics::atomic_nand_acquire(dst, val), + Release => intrinsics::atomic_nand_release(dst, val), + AcqRel => intrinsics::atomic_nand_acqrel(dst, val), + SeqCst => intrinsics::atomic_nand_seqcst(dst, val), + } + } +} + +#[inline] +#[cfg(target_has_atomic)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { + // SAFETY: the caller must uphold the safety contract for `atomic_or` + unsafe { + match order { + SeqCst => intrinsics::atomic_or_seqcst(dst, val), + Acquire => intrinsics::atomic_or_acquire(dst, val), + Release => intrinsics::atomic_or_release(dst, val), + AcqRel => intrinsics::atomic_or_acqrel(dst, val), + Relaxed => intrinsics::atomic_or_relaxed(dst, val), + } + } +} + +#[inline] +#[cfg(target_has_atomic)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { + // SAFETY: the caller must uphold the safety contract for `atomic_xor` + unsafe { + match order { + SeqCst => intrinsics::atomic_xor_seqcst(dst, val), + Acquire => intrinsics::atomic_xor_acquire(dst, val), + Release => intrinsics::atomic_xor_release(dst, val), + AcqRel => intrinsics::atomic_xor_acqrel(dst, val), + Relaxed => intrinsics::atomic_xor_relaxed(dst, val), + } + } +} + +/// returns the max value (signed comparison) +#[inline] +#[cfg(target_has_atomic)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { + // SAFETY: the caller must uphold the safety contract for `atomic_max` + unsafe { + match order { + Relaxed => intrinsics::atomic_max_relaxed(dst, val), + Acquire => intrinsics::atomic_max_acquire(dst, val), + Release => intrinsics::atomic_max_release(dst, val), + AcqRel => intrinsics::atomic_max_acqrel(dst, val), + SeqCst => intrinsics::atomic_max_seqcst(dst, val), + } + } +} + +/// returns the min value (signed comparison) +#[inline] +#[cfg(target_has_atomic)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { + // SAFETY: the caller must uphold the safety contract for `atomic_min` + unsafe { + match order { + Relaxed => intrinsics::atomic_min_relaxed(dst, val), + Acquire => intrinsics::atomic_min_acquire(dst, val), + Release => intrinsics::atomic_min_release(dst, val), + AcqRel => intrinsics::atomic_min_acqrel(dst, val), + SeqCst => intrinsics::atomic_min_seqcst(dst, val), + } + } +} + +/// returns the max value (unsigned comparison) +#[inline] +#[cfg(target_has_atomic)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { + // SAFETY: the caller must uphold the safety contract for `atomic_umax` + unsafe { + match order { + Relaxed => intrinsics::atomic_umax_relaxed(dst, val), + Acquire => intrinsics::atomic_umax_acquire(dst, val), + Release => intrinsics::atomic_umax_release(dst, val), + AcqRel => intrinsics::atomic_umax_acqrel(dst, val), + SeqCst => intrinsics::atomic_umax_seqcst(dst, val), + } + } +} + +/// returns the min value (unsigned comparison) +#[inline] +#[cfg(target_has_atomic)] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { + // SAFETY: the caller must uphold the safety contract for `atomic_umin` + unsafe { + match order { + Relaxed => intrinsics::atomic_umin_relaxed(dst, val), + Acquire => intrinsics::atomic_umin_acquire(dst, val), + Release => intrinsics::atomic_umin_release(dst, val), + AcqRel => intrinsics::atomic_umin_acqrel(dst, val), + SeqCst => intrinsics::atomic_umin_seqcst(dst, val), + } + } +} + +/// An atomic fence. +/// +/// Fences create synchronization between themselves and atomic operations or fences in other +/// threads. To achieve this, a fence prevents the compiler and CPU from reordering certain types of +/// memory operations around it. +/// +/// A fence 'A' which has (at least) [`Release`] ordering semantics, synchronizes +/// with a fence 'B' with (at least) [`Acquire`] semantics, if and only if there +/// exist operations X and Y, both operating on some atomic object 'M' such +/// that A is sequenced before X, Y is sequenced before B and Y observes +/// the change to M. This provides a happens-before dependence between A and B. +/// +/// ```text +/// Thread 1 Thread 2 +/// +/// fence(Release); A -------------- +/// x.store(3, Relaxed); X --------- | +/// | | +/// | | +/// -------------> Y if x.load(Relaxed) == 3 { +/// |-------> B fence(Acquire); +/// ... +/// } +/// ``` +/// +/// Note that in the example above, it is crucial that the accesses to `x` are atomic. Fences cannot +/// be used to establish synchronization among non-atomic accesses in different threads. However, +/// thanks to the happens-before relationship between A and B, any non-atomic accesses that +/// happen-before A are now also properly synchronized with any non-atomic accesses that +/// happen-after B. +/// +/// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize +/// with a fence. +/// +/// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`] +/// and [`Release`] semantics, participates in the global program order of the +/// other [`SeqCst`] operations and/or fences. +/// +/// Accepts [`Acquire`], [`Release`], [`AcqRel`] and [`SeqCst`] orderings. +/// +/// # Panics +/// +/// Panics if `order` is [`Relaxed`]. +/// +/// # Examples +/// +/// ``` +/// use std::sync::atomic::AtomicBool; +/// use std::sync::atomic::fence; +/// use std::sync::atomic::Ordering; +/// +/// // A mutual exclusion primitive based on spinlock. +/// pub struct Mutex { +/// flag: AtomicBool, +/// } +/// +/// impl Mutex { +/// pub fn new() -> Mutex { +/// Mutex { +/// flag: AtomicBool::new(false), +/// } +/// } +/// +/// pub fn lock(&self) { +/// // Wait until the old value is `false`. +/// while self +/// .flag +/// .compare_exchange_weak(false, true, Ordering::Relaxed, Ordering::Relaxed) +/// .is_err() +/// {} +/// // This fence synchronizes-with store in `unlock`. +/// fence(Ordering::Acquire); +/// } +/// +/// pub fn unlock(&self) { +/// self.flag.store(false, Ordering::Release); +/// } +/// } +/// ``` +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "fence"] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub fn fence(order: Ordering) { + // SAFETY: using an atomic fence is safe. + unsafe { + match order { + Acquire => intrinsics::atomic_fence_acquire(), + Release => intrinsics::atomic_fence_release(), + AcqRel => intrinsics::atomic_fence_acqrel(), + SeqCst => intrinsics::atomic_fence_seqcst(), + Relaxed => panic!("there is no such thing as a relaxed fence"), + } + } +} + +/// A "compiler-only" atomic fence. +/// +/// Like [`fence`], this function establishes synchronization with other atomic operations and +/// fences. However, unlike [`fence`], `compiler_fence` only establishes synchronization with +/// operations *in the same thread*. This may at first sound rather useless, since code within a +/// thread is typically already totally ordered and does not need any further synchronization. +/// However, there are cases where code can run on the same thread without being ordered: +/// - The most common case is that of a *signal handler*: a signal handler runs in the same thread +/// as the code it interrupted, but it is not ordered with respect to that code. `compiler_fence` +/// can be used to establish synchronization between a thread and its signal handler, the same way +/// that `fence` can be used to establish synchronization across threads. +/// - Similar situations can arise in embedded programming with interrupt handlers, or in custom +/// implementations of preemptive green threads. In general, `compiler_fence` can establish +/// synchronization with code that is guaranteed to run on the same hardware CPU. +/// +/// See [`fence`] for how a fence can be used to achieve synchronization. Note that just like +/// [`fence`], synchronization still requires atomic operations to be used in both threads -- it is +/// not possible to perform synchronization entirely with fences and non-atomic operations. +/// +/// `compiler_fence` does not emit any machine code, but restricts the kinds of memory re-ordering +/// the compiler is allowed to do. `compiler_fence` corresponds to [`atomic_signal_fence`] in C and +/// C++. +/// +/// [`atomic_signal_fence`]: https://en.cppreference.com/w/cpp/atomic/atomic_signal_fence +/// +/// # Panics +/// +/// Panics if `order` is [`Relaxed`]. +/// +/// # Examples +/// +/// Without `compiler_fence`, the `assert_eq!` in following code +/// is *not* guaranteed to succeed, despite everything happening in a single thread. +/// To see why, remember that the compiler is free to swap the stores to +/// `IMPORTANT_VARIABLE` and `IS_READY` since they are both +/// `Ordering::Relaxed`. If it does, and the signal handler is invoked right +/// after `IS_READY` is updated, then the signal handler will see +/// `IS_READY=1`, but `IMPORTANT_VARIABLE=0`. +/// Using a `compiler_fence` remedies this situation. +/// +/// ``` +/// use std::sync::atomic::{AtomicBool, AtomicUsize}; +/// use std::sync::atomic::Ordering; +/// use std::sync::atomic::compiler_fence; +/// +/// static IMPORTANT_VARIABLE: AtomicUsize = AtomicUsize::new(0); +/// static IS_READY: AtomicBool = AtomicBool::new(false); +/// +/// fn main() { +/// IMPORTANT_VARIABLE.store(42, Ordering::Relaxed); +/// // prevent earlier writes from being moved beyond this point +/// compiler_fence(Ordering::Release); +/// IS_READY.store(true, Ordering::Relaxed); +/// } +/// +/// fn signal_handler() { +/// if IS_READY.load(Ordering::Relaxed) { +/// assert_eq!(IMPORTANT_VARIABLE.load(Ordering::Relaxed), 42); +/// } +/// } +/// ``` +#[inline] +#[stable(feature = "compiler_fences", since = "1.21.0")] +#[rustc_diagnostic_item = "compiler_fence"] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +pub fn compiler_fence(order: Ordering) { + // SAFETY: using an atomic fence is safe. + unsafe { + match order { + Acquire => intrinsics::atomic_singlethreadfence_acquire(), + Release => intrinsics::atomic_singlethreadfence_release(), + AcqRel => intrinsics::atomic_singlethreadfence_acqrel(), + SeqCst => intrinsics::atomic_singlethreadfence_seqcst(), + Relaxed => panic!("there is no such thing as a relaxed compiler fence"), + } + } +} + +#[cfg(target_has_atomic_load_store = "8")] +#[stable(feature = "atomic_debug", since = "1.3.0")] +impl fmt::Debug for AtomicBool { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.load(Ordering::Relaxed), f) + } +} + +#[cfg(target_has_atomic_load_store = "ptr")] +#[stable(feature = "atomic_debug", since = "1.3.0")] +impl fmt::Debug for AtomicPtr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.load(Ordering::Relaxed), f) + } +} + +#[cfg(target_has_atomic_load_store = "ptr")] +#[stable(feature = "atomic_pointer", since = "1.24.0")] +impl fmt::Pointer for AtomicPtr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&self.load(Ordering::Relaxed), f) + } +} + +/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock"). +/// +/// This function is deprecated in favor of [`hint::spin_loop`]. +/// +/// [`hint::spin_loop`]: crate::hint::spin_loop +#[inline] +#[stable(feature = "spin_loop_hint", since = "1.24.0")] +#[deprecated(since = "1.51.0", note = "use hint::spin_loop instead")] +pub fn spin_loop_hint() { + spin_loop() +} diff --git a/CoqOfRust/core/sync/exclusive.rs b/CoqOfRust/core/sync/exclusive.rs new file mode 100644 index 000000000..340b0b79e --- /dev/null +++ b/CoqOfRust/core/sync/exclusive.rs @@ -0,0 +1,222 @@ +//! Defines [`Exclusive`]. + +use core::fmt; +use core::future::Future; +use core::marker::Tuple; +use core::ops::{Coroutine, CoroutineState}; +use core::pin::Pin; +use core::task::{Context, Poll}; + +/// `Exclusive` provides only _mutable_ access, also referred to as _exclusive_ +/// access to the underlying value. It provides no _immutable_, or _shared_ +/// access to the underlying value. +/// +/// While this may seem not very useful, it allows `Exclusive` to _unconditionally_ +/// implement [`Sync`]. Indeed, the safety requirements of `Sync` state that for `Exclusive` +/// to be `Sync`, it must be sound to _share_ across threads, that is, it must be sound +/// for `&Exclusive` to cross thread boundaries. By design, a `&Exclusive` has no API +/// whatsoever, making it useless, thus harmless, thus memory safe. +/// +/// Certain constructs like [`Future`]s can only be used with _exclusive_ access, +/// and are often `Send` but not `Sync`, so `Exclusive` can be used as hint to the +/// Rust compiler that something is `Sync` in practice. +/// +/// ## Examples +/// Using a non-`Sync` future prevents the wrapping struct from being `Sync` +/// ```compile_fail +/// use core::cell::Cell; +/// +/// async fn other() {} +/// fn assert_sync(t: T) {} +/// struct State { +/// future: F +/// } +/// +/// assert_sync(State { +/// future: async { +/// let cell = Cell::new(1); +/// let cell_ref = &cell; +/// other().await; +/// let value = cell_ref.get(); +/// } +/// }); +/// ``` +/// +/// `Exclusive` ensures the struct is `Sync` without stripping the future of its +/// functionality. +/// ``` +/// #![feature(exclusive_wrapper)] +/// use core::cell::Cell; +/// use core::sync::Exclusive; +/// +/// async fn other() {} +/// fn assert_sync(t: T) {} +/// struct State { +/// future: Exclusive +/// } +/// +/// assert_sync(State { +/// future: Exclusive::new(async { +/// let cell = Cell::new(1); +/// let cell_ref = &cell; +/// other().await; +/// let value = cell_ref.get(); +/// }) +/// }); +/// ``` +/// +/// ## Parallels with a mutex +/// In some sense, `Exclusive` can be thought of as a _compile-time_ version of +/// a mutex, as the borrow-checker guarantees that only one `&mut` can exist +/// for any value. This is a parallel with the fact that +/// `&` and `&mut` references together can be thought of as a _compile-time_ +/// version of a read-write lock. +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[doc(alias = "SyncWrapper")] +#[doc(alias = "SyncCell")] +#[doc(alias = "Unique")] +// `Exclusive` can't have `PartialOrd`, `Clone`, etc. impls as they would +// use `&` access to the inner value, violating the `Sync` impl's safety +// requirements. +#[derive(Default)] +#[repr(transparent)] +pub struct Exclusive { + inner: T, +} + +// See `Exclusive`'s docs for justification. +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +unsafe impl Sync for Exclusive {} + +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +impl fmt::Debug for Exclusive { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.debug_struct("Exclusive").finish_non_exhaustive() + } +} + +impl Exclusive { + /// Wrap a value in an `Exclusive` + #[unstable(feature = "exclusive_wrapper", issue = "98407")] + #[must_use] + #[inline] + pub const fn new(t: T) -> Self { + Self { inner: t } + } + + /// Unwrap the value contained in the `Exclusive` + #[unstable(feature = "exclusive_wrapper", issue = "98407")] + #[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")] + #[must_use] + #[inline] + pub const fn into_inner(self) -> T { + self.inner + } +} + +impl Exclusive { + /// Gets exclusive access to the underlying value. + #[unstable(feature = "exclusive_wrapper", issue = "98407")] + #[must_use] + #[inline] + pub const fn get_mut(&mut self) -> &mut T { + &mut self.inner + } + + /// Gets pinned exclusive access to the underlying value. + /// + /// `Exclusive` is considered to _structurally pin_ the underlying + /// value, which means _unpinned_ `Exclusive`s can produce _unpinned_ + /// access to the underlying value, but _pinned_ `Exclusive`s only + /// produce _pinned_ access to the underlying value. + #[unstable(feature = "exclusive_wrapper", issue = "98407")] + #[must_use] + #[inline] + pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { + // SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned + // `Pin::map_unchecked_mut` is not const, so we do this conversion manually + unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } + } + + /// Build a _mutable_ reference to an `Exclusive` from + /// a _mutable_ reference to a `T`. This allows you to skip + /// building an `Exclusive` with [`Exclusive::new`]. + #[unstable(feature = "exclusive_wrapper", issue = "98407")] + #[must_use] + #[inline] + pub const fn from_mut(r: &'_ mut T) -> &'_ mut Exclusive { + // SAFETY: repr is ≥ C, so refs have the same layout; and `Exclusive` properties are `&mut`-agnostic + unsafe { &mut *(r as *mut T as *mut Exclusive) } + } + + /// Build a _pinned mutable_ reference to an `Exclusive` from + /// a _pinned mutable_ reference to a `T`. This allows you to skip + /// building an `Exclusive` with [`Exclusive::new`]. + #[unstable(feature = "exclusive_wrapper", issue = "98407")] + #[must_use] + #[inline] + pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut Exclusive> { + // SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned + // `Pin::map_unchecked_mut` is not const, so we do this conversion manually + unsafe { Pin::new_unchecked(Self::from_mut(r.get_unchecked_mut())) } + } +} + +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +impl From for Exclusive { + #[inline] + fn from(t: T) -> Self { + Self::new(t) + } +} + +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +impl FnOnce for Exclusive +where + F: FnOnce, + Args: Tuple, +{ + type Output = F::Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output { + self.into_inner().call_once(args) + } +} + +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +impl FnMut for Exclusive +where + F: FnMut, + Args: Tuple, +{ + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { + self.get_mut().call_mut(args) + } +} + +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +impl Future for Exclusive +where + T: Future + ?Sized, +{ + type Output = T::Output; + + #[inline] + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.get_pin_mut().poll(cx) + } +} + +#[unstable(feature = "coroutine_trait", issue = "43122")] // also #98407 +impl Coroutine for Exclusive +where + G: Coroutine + ?Sized, +{ + type Yield = G::Yield; + type Return = G::Return; + + #[inline] + fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState { + G::resume(self.get_pin_mut(), arg) + } +} diff --git a/CoqOfRust/core/sync/mod.rs b/CoqOfRust/core/sync/mod.rs new file mode 100644 index 000000000..4365e4cb2 --- /dev/null +++ b/CoqOfRust/core/sync/mod.rs @@ -0,0 +1,8 @@ +//! Synchronization primitives + +#![stable(feature = "rust1", since = "1.0.0")] + +pub mod atomic; +mod exclusive; +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +pub use exclusive::Exclusive; diff --git a/CoqOfRust/core/task/mod.rs b/CoqOfRust/core/task/mod.rs new file mode 100644 index 000000000..f1a789e32 --- /dev/null +++ b/CoqOfRust/core/task/mod.rs @@ -0,0 +1,15 @@ +#![stable(feature = "futures_api", since = "1.36.0")] + +//! Types and Traits for working with asynchronous tasks. + +mod poll; +#[stable(feature = "futures_api", since = "1.36.0")] +pub use self::poll::Poll; + +mod wake; +#[stable(feature = "futures_api", since = "1.36.0")] +pub use self::wake::{Context, ContextBuilder, LocalWaker, RawWaker, RawWakerVTable, Waker}; + +mod ready; +#[stable(feature = "ready_macro", since = "1.64.0")] +pub use ready::ready; diff --git a/CoqOfRust/core/task/poll.rs b/CoqOfRust/core/task/poll.rs new file mode 100644 index 000000000..6aab22177 --- /dev/null +++ b/CoqOfRust/core/task/poll.rs @@ -0,0 +1,293 @@ +#![stable(feature = "futures_api", since = "1.36.0")] + +use crate::convert; +use crate::ops::{self, ControlFlow}; + +/// Indicates whether a value is available or if the current task has been +/// scheduled to receive a wakeup instead. +/// +/// This is returned by [`Future::poll`](core::future::Future::poll). +#[must_use = "this `Poll` may be a `Pending` variant, which should be handled"] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[lang = "Poll"] +#[stable(feature = "futures_api", since = "1.36.0")] +pub enum Poll { + /// Represents that a value is immediately ready. + #[lang = "Ready"] + #[stable(feature = "futures_api", since = "1.36.0")] + Ready(#[stable(feature = "futures_api", since = "1.36.0")] T), + + /// Represents that a value is not ready yet. + /// + /// When a function returns `Pending`, the function *must* also + /// ensure that the current task is scheduled to be awoken when + /// progress can be made. + #[lang = "Pending"] + #[stable(feature = "futures_api", since = "1.36.0")] + Pending, +} + +impl Poll { + /// Maps a `Poll` to `Poll` by applying a function to a contained value. + /// + /// # Examples + /// + /// Converts a Poll<[String]> into a Poll<[usize]>, consuming + /// the original: + /// + /// [String]: ../../std/string/struct.String.html "String" + /// ``` + /// # use core::task::Poll; + /// let poll_some_string = Poll::Ready(String::from("Hello, World!")); + /// // `Poll::map` takes self *by value*, consuming `poll_some_string` + /// let poll_some_len = poll_some_string.map(|s| s.len()); + /// + /// assert_eq!(poll_some_len, Poll::Ready(13)); + /// ``` + #[stable(feature = "futures_api", since = "1.36.0")] + #[inline] + pub fn map(self, f: F) -> Poll + where + F: FnOnce(T) -> U, + { + match self { + Poll::Ready(t) => Poll::Ready(f(t)), + Poll::Pending => Poll::Pending, + } + } + + /// Returns `true` if the poll is a [`Poll::Ready`] value. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let x: Poll = Poll::Ready(2); + /// assert_eq!(x.is_ready(), true); + /// + /// let x: Poll = Poll::Pending; + /// assert_eq!(x.is_ready(), false); + /// ``` + #[inline] + #[rustc_const_stable(feature = "const_poll", since = "1.49.0")] + #[stable(feature = "futures_api", since = "1.36.0")] + pub const fn is_ready(&self) -> bool { + matches!(*self, Poll::Ready(_)) + } + + /// Returns `true` if the poll is a [`Pending`] value. + /// + /// [`Pending`]: Poll::Pending + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let x: Poll = Poll::Ready(2); + /// assert_eq!(x.is_pending(), false); + /// + /// let x: Poll = Poll::Pending; + /// assert_eq!(x.is_pending(), true); + /// ``` + #[inline] + #[rustc_const_stable(feature = "const_poll", since = "1.49.0")] + #[stable(feature = "futures_api", since = "1.36.0")] + pub const fn is_pending(&self) -> bool { + !self.is_ready() + } +} + +impl Poll> { + /// Maps a `Poll>` to `Poll>` by applying a + /// function to a contained `Poll::Ready(Ok)` value, leaving all other + /// variants untouched. + /// + /// This function can be used to compose the results of two functions. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let res: Poll> = Poll::Ready("12".parse()); + /// let squared = res.map_ok(|n| n * n); + /// assert_eq!(squared, Poll::Ready(Ok(144))); + /// ``` + #[stable(feature = "futures_api", since = "1.36.0")] + #[inline] + pub fn map_ok(self, f: F) -> Poll> + where + F: FnOnce(T) -> U, + { + match self { + Poll::Ready(Ok(t)) => Poll::Ready(Ok(f(t))), + Poll::Ready(Err(e)) => Poll::Ready(Err(e)), + Poll::Pending => Poll::Pending, + } + } + + /// Maps a `Poll::Ready>` to `Poll::Ready>` by + /// applying a function to a contained `Poll::Ready(Err)` value, leaving all other + /// variants untouched. + /// + /// This function can be used to pass through a successful result while handling + /// an error. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let res: Poll> = Poll::Ready("oops".parse()); + /// let res = res.map_err(|_| 0_u8); + /// assert_eq!(res, Poll::Ready(Err(0))); + /// ``` + #[stable(feature = "futures_api", since = "1.36.0")] + #[inline] + pub fn map_err(self, f: F) -> Poll> + where + F: FnOnce(E) -> U, + { + match self { + Poll::Ready(Ok(t)) => Poll::Ready(Ok(t)), + Poll::Ready(Err(e)) => Poll::Ready(Err(f(e))), + Poll::Pending => Poll::Pending, + } + } +} + +impl Poll>> { + /// Maps a `Poll>>` to `Poll>>` by + /// applying a function to a contained `Poll::Ready(Some(Ok))` value, + /// leaving all other variants untouched. + /// + /// This function can be used to compose the results of two functions. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let res: Poll>> = Poll::Ready(Some("12".parse())); + /// let squared = res.map_ok(|n| n * n); + /// assert_eq!(squared, Poll::Ready(Some(Ok(144)))); + /// ``` + #[stable(feature = "poll_map", since = "1.51.0")] + #[inline] + pub fn map_ok(self, f: F) -> Poll>> + where + F: FnOnce(T) -> U, + { + match self { + Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))), + Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))), + Poll::Ready(None) => Poll::Ready(None), + Poll::Pending => Poll::Pending, + } + } + + /// Maps a `Poll::Ready>>` to + /// `Poll::Ready>>` by applying a function to a + /// contained `Poll::Ready(Some(Err))` value, leaving all other variants + /// untouched. + /// + /// This function can be used to pass through a successful result while handling + /// an error. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let res: Poll>> = Poll::Ready(Some("oops".parse())); + /// let res = res.map_err(|_| 0_u8); + /// assert_eq!(res, Poll::Ready(Some(Err(0)))); + /// ``` + #[stable(feature = "poll_map", since = "1.51.0")] + #[inline] + pub fn map_err(self, f: F) -> Poll>> + where + F: FnOnce(E) -> U, + { + match self { + Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))), + Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))), + Poll::Ready(None) => Poll::Ready(None), + Poll::Pending => Poll::Pending, + } + } +} + +#[stable(feature = "futures_api", since = "1.36.0")] +impl From for Poll { + /// Moves the value into a [`Poll::Ready`] to make a `Poll`. + /// + /// # Example + /// + /// ``` + /// # use core::task::Poll; + /// assert_eq!(Poll::from(true), Poll::Ready(true)); + /// ``` + fn from(t: T) -> Poll { + Poll::Ready(t) + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl ops::Try for Poll> { + type Output = Poll; + type Residual = Result; + + #[inline] + fn from_output(c: Self::Output) -> Self { + c.map(Ok) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + Poll::Ready(Ok(x)) => ControlFlow::Continue(Poll::Ready(x)), + Poll::Ready(Err(e)) => ControlFlow::Break(Err(e)), + Poll::Pending => ControlFlow::Continue(Poll::Pending), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl> ops::FromResidual> for Poll> { + #[inline] + fn from_residual(x: Result) -> Self { + match x { + Err(e) => Poll::Ready(Err(From::from(e))), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl ops::Try for Poll>> { + type Output = Poll>; + type Residual = Result; + + #[inline] + fn from_output(c: Self::Output) -> Self { + c.map(|x| x.map(Ok)) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + Poll::Ready(Some(Ok(x))) => ControlFlow::Continue(Poll::Ready(Some(x))), + Poll::Ready(Some(Err(e))) => ControlFlow::Break(Err(e)), + Poll::Ready(None) => ControlFlow::Continue(Poll::Ready(None)), + Poll::Pending => ControlFlow::Continue(Poll::Pending), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl> ops::FromResidual> + for Poll>> +{ + #[inline] + fn from_residual(x: Result) -> Self { + match x { + Err(e) => Poll::Ready(Some(Err(From::from(e)))), + } + } +} diff --git a/CoqOfRust/core/task/ready.rs b/CoqOfRust/core/task/ready.rs new file mode 100644 index 000000000..495d72fd1 --- /dev/null +++ b/CoqOfRust/core/task/ready.rs @@ -0,0 +1,57 @@ +/// Extracts the successful type of a [`Poll`]. +/// +/// This macro bakes in propagation of [`Pending`] signals by returning early. +/// +/// [`Poll`]: crate::task::Poll +/// [`Pending`]: crate::task::Poll::Pending +/// +/// # Examples +/// +/// ``` +/// use std::task::{ready, Context, Poll}; +/// use std::future::{self, Future}; +/// use std::pin::Pin; +/// +/// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> { +/// let mut fut = future::ready(42); +/// let fut = Pin::new(&mut fut); +/// +/// let num = ready!(fut.poll(cx)); +/// # let _ = num; +/// // ... use num +/// +/// Poll::Ready(()) +/// } +/// ``` +/// +/// The `ready!` call expands to: +/// +/// ``` +/// # use std::task::{Context, Poll}; +/// # use std::future::{self, Future}; +/// # use std::pin::Pin; +/// # +/// # pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> { +/// # let mut fut = future::ready(42); +/// # let fut = Pin::new(&mut fut); +/// # +/// let num = match fut.poll(cx) { +/// Poll::Ready(t) => t, +/// Poll::Pending => return Poll::Pending, +/// }; +/// # let _ = num; // to silence unused warning +/// # // ... use num +/// # +/// # Poll::Ready(()) +/// # } +/// ``` +#[stable(feature = "ready_macro", since = "1.64.0")] +#[rustc_macro_transparency = "semitransparent"] +pub macro ready($e:expr) { + match $e { + $crate::task::Poll::Ready(t) => t, + $crate::task::Poll::Pending => { + return $crate::task::Poll::Pending; + } + } +} diff --git a/CoqOfRust/core/task/wake.rs b/CoqOfRust/core/task/wake.rs new file mode 100644 index 000000000..6762ed54e --- /dev/null +++ b/CoqOfRust/core/task/wake.rs @@ -0,0 +1,939 @@ +#![stable(feature = "futures_api", since = "1.36.0")] + +use crate::any::Any; +use crate::marker::PhantomData; +use crate::mem::{ManuallyDrop, transmute}; +use crate::panic::AssertUnwindSafe; +use crate::{fmt, ptr}; + +/// A `RawWaker` allows the implementor of a task executor to create a [`Waker`] +/// or a [`LocalWaker`] which provides customized wakeup behavior. +/// +/// It consists of a data pointer and a [virtual function pointer table (vtable)][vtable] +/// that customizes the behavior of the `RawWaker`. +/// +/// `RawWaker`s are unsafe to use. +/// Implementing the [`Wake`] trait is a safe alternative that requires memory allocation. +/// +/// [vtable]: https://en.wikipedia.org/wiki/Virtual_method_table +/// [`Wake`]: ../../alloc/task/trait.Wake.html +#[derive(PartialEq, Debug)] +#[stable(feature = "futures_api", since = "1.36.0")] +pub struct RawWaker { + /// A data pointer, which can be used to store arbitrary data as required + /// by the executor. This could be e.g. a type-erased pointer to an `Arc` + /// that is associated with the task. + /// The value of this field gets passed to all functions that are part of + /// the vtable as the first parameter. + data: *const (), + /// Virtual function pointer table that customizes the behavior of this waker. + vtable: &'static RawWakerVTable, +} + +impl RawWaker { + /// Creates a new `RawWaker` from the provided `data` pointer and `vtable`. + /// + /// The `data` pointer can be used to store arbitrary data as required + /// by the executor. This could be e.g. a type-erased pointer to an `Arc` + /// that is associated with the task. + /// The value of this pointer will get passed to all functions that are part + /// of the `vtable` as the first parameter. + /// + /// It is important to consider that the `data` pointer must point to a + /// thread safe type such as an `[Arc]` + /// when used to construct a [`Waker`]. This restriction is lifted when + /// constructing a [`LocalWaker`], which allows using types that do not implement + /// [Send] + [Sync] like `[Rc]`. + /// + /// The `vtable` customizes the behavior of a `Waker` which gets created + /// from a `RawWaker`. For each operation on the `Waker`, the associated + /// function in the `vtable` of the underlying `RawWaker` will be called. + /// + /// [`Arc`]: std::sync::Arc + /// [`Rc`]: std::rc::Rc + #[inline] + #[rustc_promotable] + #[stable(feature = "futures_api", since = "1.36.0")] + #[rustc_const_stable(feature = "futures_api", since = "1.36.0")] + #[must_use] + pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker { + RawWaker { data, vtable } + } + + #[stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")] + const NOOP: RawWaker = { + const VTABLE: RawWakerVTable = RawWakerVTable::new( + // Cloning just returns a new no-op raw waker + |_| RawWaker::NOOP, + // `wake` does nothing + |_| {}, + // `wake_by_ref` does nothing + |_| {}, + // Dropping does nothing as we don't allocate anything + |_| {}, + ); + RawWaker::new(ptr::null(), &VTABLE) + }; +} + +/// A virtual function pointer table (vtable) that specifies the behavior +/// of a [`RawWaker`]. +/// +/// The pointer passed to all functions inside the vtable is the `data` pointer +/// from the enclosing [`RawWaker`] object. +/// +/// The functions inside this struct are only intended to be called on the `data` +/// pointer of a properly constructed [`RawWaker`] object from inside the +/// [`RawWaker`] implementation. Calling one of the contained functions using +/// any other `data` pointer will cause undefined behavior. +/// +/// Note that while this type implements `PartialEq`, comparing function pointers, and hence +/// comparing structs like this that contain function pointers, is unreliable: pointers to the same +/// function can compare inequal (because functions are duplicated in multiple codegen units), and +/// pointers to *different* functions can compare equal (since identical functions can be +/// deduplicated within a codegen unit). +/// +/// # Thread safety +/// If the [`RawWaker`] will be used to construct a [`Waker`] then +/// these functions must all be thread-safe (even though [`RawWaker`] is +/// \![Send] + \![Sync]). This is because [`Waker`] is [Send] + [Sync], +/// and it may be moved to arbitrary threads or invoked by `&` reference. For example, +/// this means that if the `clone` and `drop` functions manage a reference count, +/// they must do so atomically. +/// +/// However, if the [`RawWaker`] will be used to construct a [`LocalWaker`] instead, then +/// these functions don't need to be thread safe. This means that \![Send] + \![Sync] +/// data can be stored in the data pointer, and reference counting does not need any atomic +/// synchronization. This is because [`LocalWaker`] is not thread safe itself, so it cannot +/// be sent across threads. +#[stable(feature = "futures_api", since = "1.36.0")] +#[derive(PartialEq, Copy, Clone, Debug)] +pub struct RawWakerVTable { + /// This function will be called when the [`RawWaker`] gets cloned, e.g. when + /// the [`Waker`] in which the [`RawWaker`] is stored gets cloned. + /// + /// The implementation of this function must retain all resources that are + /// required for this additional instance of a [`RawWaker`] and associated + /// task. Calling `wake` on the resulting [`RawWaker`] should result in a wakeup + /// of the same task that would have been awoken by the original [`RawWaker`]. + clone: unsafe fn(*const ()) -> RawWaker, + + /// This function will be called when `wake` is called on the [`Waker`]. + /// It must wake up the task associated with this [`RawWaker`]. + /// + /// The implementation of this function must make sure to release any + /// resources that are associated with this instance of a [`RawWaker`] and + /// associated task. + wake: unsafe fn(*const ()), + + /// This function will be called when `wake_by_ref` is called on the [`Waker`]. + /// It must wake up the task associated with this [`RawWaker`]. + /// + /// This function is similar to `wake`, but must not consume the provided data + /// pointer. + wake_by_ref: unsafe fn(*const ()), + + /// This function will be called when a [`Waker`] gets dropped. + /// + /// The implementation of this function must make sure to release any + /// resources that are associated with this instance of a [`RawWaker`] and + /// associated task. + drop: unsafe fn(*const ()), +} + +impl RawWakerVTable { + /// Creates a new `RawWakerVTable` from the provided `clone`, `wake`, + /// `wake_by_ref`, and `drop` functions. + /// + /// If the [`RawWaker`] will be used to construct a [`Waker`] then + /// these functions must all be thread-safe (even though [`RawWaker`] is + /// \![Send] + \![Sync]). This is because [`Waker`] is [Send] + [Sync], + /// and it may be moved to arbitrary threads or invoked by `&` reference. For example, + /// this means that if the `clone` and `drop` functions manage a reference count, + /// they must do so atomically. + /// + /// However, if the [`RawWaker`] will be used to construct a [`LocalWaker`] instead, then + /// these functions don't need to be thread safe. This means that \![Send] + \![Sync] + /// data can be stored in the data pointer, and reference counting does not need any atomic + /// synchronization. This is because [`LocalWaker`] is not thread safe itself, so it cannot + /// be sent across threads. + /// # `clone` + /// + /// This function will be called when the [`RawWaker`] gets cloned, e.g. when + /// the [`Waker`]/[`LocalWaker`] in which the [`RawWaker`] is stored gets cloned. + /// + /// The implementation of this function must retain all resources that are + /// required for this additional instance of a [`RawWaker`] and associated + /// task. Calling `wake` on the resulting [`RawWaker`] should result in a wakeup + /// of the same task that would have been awoken by the original [`RawWaker`]. + /// + /// # `wake` + /// + /// This function will be called when `wake` is called on the [`Waker`]. + /// It must wake up the task associated with this [`RawWaker`]. + /// + /// The implementation of this function must make sure to release any + /// resources that are associated with this instance of a [`RawWaker`] and + /// associated task. + /// + /// # `wake_by_ref` + /// + /// This function will be called when `wake_by_ref` is called on the [`Waker`]. + /// It must wake up the task associated with this [`RawWaker`]. + /// + /// This function is similar to `wake`, but must not consume the provided data + /// pointer. + /// + /// # `drop` + /// + /// This function will be called when a [`Waker`]/[`LocalWaker`] gets + /// dropped. + /// + /// The implementation of this function must make sure to release any + /// resources that are associated with this instance of a [`RawWaker`] and + /// associated task. + #[rustc_promotable] + #[stable(feature = "futures_api", since = "1.36.0")] + #[rustc_const_stable(feature = "futures_api", since = "1.36.0")] + pub const fn new( + clone: unsafe fn(*const ()) -> RawWaker, + wake: unsafe fn(*const ()), + wake_by_ref: unsafe fn(*const ()), + drop: unsafe fn(*const ()), + ) -> Self { + Self { clone, wake, wake_by_ref, drop } + } +} + +#[derive(Debug)] +enum ExtData<'a> { + Some(&'a mut dyn Any), + None(()), +} + +/// The context of an asynchronous task. +/// +/// Currently, `Context` only serves to provide access to a [`&Waker`](Waker) +/// which can be used to wake the current task. +#[stable(feature = "futures_api", since = "1.36.0")] +#[lang = "Context"] +pub struct Context<'a> { + waker: &'a Waker, + local_waker: &'a LocalWaker, + ext: AssertUnwindSafe>, + // Ensure we future-proof against variance changes by forcing + // the lifetime to be invariant (argument-position lifetimes + // are contravariant while return-position lifetimes are + // covariant). + _marker: PhantomData &'a ()>, + // Ensure `Context` is `!Send` and `!Sync` in order to allow + // for future `!Send` and / or `!Sync` fields. + _marker2: PhantomData<*mut ()>, +} + +impl<'a> Context<'a> { + /// Creates a new `Context` from a [`&Waker`](Waker). + #[stable(feature = "futures_api", since = "1.36.0")] + #[rustc_const_stable(feature = "const_waker", since = "1.82.0")] + #[must_use] + #[inline] + pub const fn from_waker(waker: &'a Waker) -> Self { + ContextBuilder::from_waker(waker).build() + } + + /// Returns a reference to the [`Waker`] for the current task. + #[inline] + #[must_use] + #[stable(feature = "futures_api", since = "1.36.0")] + #[rustc_const_stable(feature = "const_waker", since = "1.82.0")] + pub const fn waker(&self) -> &'a Waker { + &self.waker + } + + /// Returns a reference to the [`LocalWaker`] for the current task. + #[inline] + #[unstable(feature = "local_waker", issue = "118959")] + pub const fn local_waker(&self) -> &'a LocalWaker { + &self.local_waker + } + + /// Returns a reference to the extension data for the current task. + #[inline] + #[unstable(feature = "context_ext", issue = "123392")] + pub const fn ext(&mut self) -> &mut dyn Any { + // FIXME: this field makes Context extra-weird about unwind safety + // can we justify AssertUnwindSafe if we stabilize this? do we care? + match &mut self.ext.0 { + ExtData::Some(data) => *data, + ExtData::None(unit) => unit, + } + } +} + +#[stable(feature = "futures_api", since = "1.36.0")] +impl fmt::Debug for Context<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Context").field("waker", &self.waker).finish() + } +} + +/// A Builder used to construct a `Context` instance +/// with support for `LocalWaker`. +/// +/// # Examples +/// ``` +/// #![feature(local_waker)] +/// use std::task::{ContextBuilder, LocalWaker, Waker, Poll}; +/// use std::future::Future; +/// +/// let local_waker = LocalWaker::noop(); +/// let waker = Waker::noop(); +/// +/// let mut cx = ContextBuilder::from_waker(&waker) +/// .local_waker(&local_waker) +/// .build(); +/// +/// let mut future = std::pin::pin!(async { 20 }); +/// let poll = future.as_mut().poll(&mut cx); +/// assert_eq!(poll, Poll::Ready(20)); +/// +/// ``` +#[unstable(feature = "local_waker", issue = "118959")] +#[derive(Debug)] +pub struct ContextBuilder<'a> { + waker: &'a Waker, + local_waker: &'a LocalWaker, + ext: ExtData<'a>, + // Ensure we future-proof against variance changes by forcing + // the lifetime to be invariant (argument-position lifetimes + // are contravariant while return-position lifetimes are + // covariant). + _marker: PhantomData &'a ()>, + // Ensure `Context` is `!Send` and `!Sync` in order to allow + // for future `!Send` and / or `!Sync` fields. + _marker2: PhantomData<*mut ()>, +} + +impl<'a> ContextBuilder<'a> { + /// Creates a ContextBuilder from a Waker. + #[inline] + #[unstable(feature = "local_waker", issue = "118959")] + pub const fn from_waker(waker: &'a Waker) -> Self { + // SAFETY: LocalWaker is just Waker without thread safety + let local_waker = unsafe { transmute(waker) }; + Self { + waker: waker, + local_waker, + ext: ExtData::None(()), + _marker: PhantomData, + _marker2: PhantomData, + } + } + + /// Creates a ContextBuilder from an existing Context. + #[inline] + #[unstable(feature = "context_ext", issue = "123392")] + pub const fn from(cx: &'a mut Context<'_>) -> Self { + let ext = match &mut cx.ext.0 { + ExtData::Some(ext) => ExtData::Some(*ext), + ExtData::None(()) => ExtData::None(()), + }; + Self { + waker: cx.waker, + local_waker: cx.local_waker, + ext, + _marker: PhantomData, + _marker2: PhantomData, + } + } + + /// Sets the value for the waker on `Context`. + #[inline] + #[unstable(feature = "context_ext", issue = "123392")] + pub const fn waker(self, waker: &'a Waker) -> Self { + Self { waker, ..self } + } + + /// Sets the value for the local waker on `Context`. + #[inline] + #[unstable(feature = "local_waker", issue = "118959")] + pub const fn local_waker(self, local_waker: &'a LocalWaker) -> Self { + Self { local_waker, ..self } + } + + /// Sets the value for the extension data on `Context`. + #[inline] + #[unstable(feature = "context_ext", issue = "123392")] + pub const fn ext(self, data: &'a mut dyn Any) -> Self { + Self { ext: ExtData::Some(data), ..self } + } + + /// Builds the `Context`. + #[inline] + #[unstable(feature = "local_waker", issue = "118959")] + pub const fn build(self) -> Context<'a> { + let ContextBuilder { waker, local_waker, ext, _marker, _marker2 } = self; + Context { waker, local_waker, ext: AssertUnwindSafe(ext), _marker, _marker2 } + } +} + +/// A `Waker` is a handle for waking up a task by notifying its executor that it +/// is ready to be run. +/// +/// This handle encapsulates a [`RawWaker`] instance, which defines the +/// executor-specific wakeup behavior. +/// +/// The typical life of a `Waker` is that it is constructed by an executor, wrapped in a +/// [`Context`], then passed to [`Future::poll()`]. Then, if the future chooses to return +/// [`Poll::Pending`], it must also store the waker somehow and call [`Waker::wake()`] when +/// the future should be polled again. +/// +/// Implements [`Clone`], [`Send`], and [`Sync`]; therefore, a waker may be invoked +/// from any thread, including ones not in any way managed by the executor. For example, +/// this might be done to wake a future when a blocking function call completes on another +/// thread. +/// +/// Note that it is preferable to use `waker.clone_from(&new_waker)` instead +/// of `*waker = new_waker.clone()`, as the former will avoid cloning the waker +/// unnecessarily if the two wakers [wake the same task](Self::will_wake). +/// +/// Constructing a `Waker` from a [`RawWaker`] is unsafe. +/// Implementing the [`Wake`] trait is a safe alternative that requires memory allocation. +/// +/// [`Future::poll()`]: core::future::Future::poll +/// [`Poll::Pending`]: core::task::Poll::Pending +/// [`Wake`]: ../../alloc/task/trait.Wake.html +#[repr(transparent)] +#[stable(feature = "futures_api", since = "1.36.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Waker")] +pub struct Waker { + waker: RawWaker, +} + +#[stable(feature = "futures_api", since = "1.36.0")] +impl Unpin for Waker {} +#[stable(feature = "futures_api", since = "1.36.0")] +unsafe impl Send for Waker {} +#[stable(feature = "futures_api", since = "1.36.0")] +unsafe impl Sync for Waker {} + +impl Waker { + /// Wakes up the task associated with this `Waker`. + /// + /// As long as the executor keeps running and the task is not finished, it is + /// guaranteed that each invocation of [`wake()`](Self::wake) (or + /// [`wake_by_ref()`](Self::wake_by_ref)) will be followed by at least one + /// [`poll()`] of the task to which this `Waker` belongs. This makes + /// it possible to temporarily yield to other tasks while running potentially + /// unbounded processing loops. + /// + /// Note that the above implies that multiple wake-ups may be coalesced into a + /// single [`poll()`] invocation by the runtime. + /// + /// Also note that yielding to competing tasks is not guaranteed: it is the + /// executor’s choice which task to run and the executor may choose to run the + /// current task again. + /// + /// [`poll()`]: crate::future::Future::poll + #[inline] + #[stable(feature = "futures_api", since = "1.36.0")] + pub fn wake(self) { + // The actual wakeup call is delegated through a virtual function call + // to the implementation which is defined by the executor. + + // Don't call `drop` -- the waker will be consumed by `wake`. + let this = ManuallyDrop::new(self); + + // SAFETY: This is safe because `Waker::from_raw` is the only way + // to initialize `wake` and `data` requiring the user to acknowledge + // that the contract of `RawWaker` is upheld. + unsafe { (this.waker.vtable.wake)(this.waker.data) }; + } + + /// Wakes up the task associated with this `Waker` without consuming the `Waker`. + /// + /// This is similar to [`wake()`](Self::wake), but may be slightly less efficient in + /// the case where an owned `Waker` is available. This method should be preferred to + /// calling `waker.clone().wake()`. + #[inline] + #[stable(feature = "futures_api", since = "1.36.0")] + pub fn wake_by_ref(&self) { + // The actual wakeup call is delegated through a virtual function call + // to the implementation which is defined by the executor. + + // SAFETY: see `wake` + unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) } + } + + /// Returns `true` if this `Waker` and another `Waker` would awake the same task. + /// + /// This function works on a best-effort basis, and may return false even + /// when the `Waker`s would awaken the same task. However, if this function + /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task. + /// + /// This function is primarily used for optimization purposes — for example, + /// this type's [`clone_from`](Self::clone_from) implementation uses it to + /// avoid cloning the waker when they would wake the same task anyway. + #[inline] + #[must_use] + #[stable(feature = "futures_api", since = "1.36.0")] + pub fn will_wake(&self, other: &Waker) -> bool { + // We optimize this by comparing vtable addresses instead of vtable contents. + // This is permitted since the function is documented as best-effort. + let RawWaker { data: a_data, vtable: a_vtable } = self.waker; + let RawWaker { data: b_data, vtable: b_vtable } = other.waker; + a_data == b_data && ptr::eq(a_vtable, b_vtable) + } + + /// Creates a new `Waker` from the provided `data` pointer and `vtable`. + /// + /// The `data` pointer can be used to store arbitrary data as required + /// by the executor. This could be e.g. a type-erased pointer to an `Arc` + /// that is associated with the task. + /// The value of this pointer will get passed to all functions that are part + /// of the `vtable` as the first parameter. + /// + /// It is important to consider that the `data` pointer must point to a + /// thread safe type such as an `Arc`. + /// + /// The `vtable` customizes the behavior of a `Waker`. For each operation + /// on the `Waker`, the associated function in the `vtable` will be called. + /// + /// # Safety + /// + /// The behavior of the returned `Waker` is undefined if the contract defined + /// in [`RawWakerVTable`]'s documentation is not upheld. + /// + /// (Authors wishing to avoid unsafe code may implement the [`Wake`] trait instead, at the + /// cost of a required heap allocation.) + /// + /// [`Wake`]: ../../alloc/task/trait.Wake.html + #[inline] + #[must_use] + #[stable(feature = "waker_getters", since = "1.83.0")] + #[rustc_const_stable(feature = "waker_getters", since = "1.83.0")] + pub const unsafe fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self { + Waker { waker: RawWaker { data, vtable } } + } + + /// Creates a new `Waker` from [`RawWaker`]. + /// + /// # Safety + /// + /// The behavior of the returned `Waker` is undefined if the contract defined + /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. + /// + /// (Authors wishing to avoid unsafe code may implement the [`Wake`] trait instead, at the + /// cost of a required heap allocation.) + /// + /// [`Wake`]: ../../alloc/task/trait.Wake.html + #[inline] + #[must_use] + #[stable(feature = "futures_api", since = "1.36.0")] + #[rustc_const_stable(feature = "const_waker", since = "1.82.0")] + pub const unsafe fn from_raw(waker: RawWaker) -> Waker { + Waker { waker } + } + + /// Returns a reference to a `Waker` that does nothing when used. + /// + // Note! Much of the documentation for this method is duplicated + // in the docs for `LocalWaker::noop`. + // If you edit it, consider editing the other copy too. + // + /// This is mostly useful for writing tests that need a [`Context`] to poll + /// some futures, but are not expecting those futures to wake the waker or + /// do not need to do anything specific if it happens. + /// + /// More generally, using `Waker::noop()` to poll a future + /// means discarding the notification of when the future should be polled again. + /// So it should only be used when such a notification will not be needed to make progress. + /// + /// If an owned `Waker` is needed, `clone()` this one. + /// + /// # Examples + /// + /// ``` + /// use std::future::Future; + /// use std::task; + /// + /// let mut cx = task::Context::from_waker(task::Waker::noop()); + /// + /// let mut future = Box::pin(async { 10 }); + /// assert_eq!(future.as_mut().poll(&mut cx), task::Poll::Ready(10)); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")] + pub const fn noop() -> &'static Waker { + const WAKER: &Waker = &Waker { waker: RawWaker::NOOP }; + WAKER + } + + /// Gets the `data` pointer used to create this `Waker`. + #[inline] + #[must_use] + #[stable(feature = "waker_getters", since = "1.83.0")] + pub fn data(&self) -> *const () { + self.waker.data + } + + /// Gets the `vtable` pointer used to create this `Waker`. + #[inline] + #[must_use] + #[stable(feature = "waker_getters", since = "1.83.0")] + pub fn vtable(&self) -> &'static RawWakerVTable { + self.waker.vtable + } +} + +#[stable(feature = "futures_api", since = "1.36.0")] +impl Clone for Waker { + #[inline] + fn clone(&self) -> Self { + Waker { + // SAFETY: This is safe because `Waker::from_raw` is the only way + // to initialize `clone` and `data` requiring the user to acknowledge + // that the contract of [`RawWaker`] is upheld. + waker: unsafe { (self.waker.vtable.clone)(self.waker.data) }, + } + } + + /// Assigns a clone of `source` to `self`, unless [`self.will_wake(source)`][Waker::will_wake] anyway. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids cloning the waker if `self` is already the same waker. + /// + /// # Examples + /// + /// ``` + /// use std::future::Future; + /// use std::pin::Pin; + /// use std::sync::{Arc, Mutex}; + /// use std::task::{Context, Poll, Waker}; + /// + /// struct Waiter { + /// shared: Arc>, + /// } + /// + /// struct Shared { + /// waker: Waker, + /// // ... + /// } + /// + /// impl Future for Waiter { + /// type Output = (); + /// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + /// let mut shared = self.shared.lock().unwrap(); + /// + /// // update the waker + /// shared.waker.clone_from(cx.waker()); + /// + /// // readiness logic ... + /// # Poll::Ready(()) + /// } + /// } + /// + /// ``` + #[inline] + fn clone_from(&mut self, source: &Self) { + if !self.will_wake(source) { + *self = source.clone(); + } + } +} + +#[stable(feature = "futures_api", since = "1.36.0")] +impl Drop for Waker { + #[inline] + fn drop(&mut self) { + // SAFETY: This is safe because `Waker::from_raw` is the only way + // to initialize `drop` and `data` requiring the user to acknowledge + // that the contract of `RawWaker` is upheld. + unsafe { (self.waker.vtable.drop)(self.waker.data) } + } +} + +#[stable(feature = "futures_api", since = "1.36.0")] +impl fmt::Debug for Waker { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let vtable_ptr = self.waker.vtable as *const RawWakerVTable; + f.debug_struct("Waker") + .field("data", &self.waker.data) + .field("vtable", &vtable_ptr) + .finish() + } +} + +/// A `LocalWaker` is analogous to a [`Waker`], but it does not implement [`Send`] or [`Sync`]. +/// +/// This handle encapsulates a [`RawWaker`] instance, which defines the +/// executor-specific wakeup behavior. +/// +/// Local wakers can be requested from a `Context` with the [`local_waker`] method. +/// +/// The typical life of a `LocalWaker` is that it is constructed by an executor, wrapped in a +/// [`Context`] using [`ContextBuilder`], then passed to [`Future::poll()`]. Then, if the future chooses to return +/// [`Poll::Pending`], it must also store the waker somehow and call [`LocalWaker::wake()`] when +/// the future should be polled again. +/// +/// Implements [`Clone`], but neither [`Send`] nor [`Sync`]; therefore, a local waker may +/// not be moved to other threads. In general, when deciding to use wakers or local wakers, +/// local wakers are preferable unless the waker needs to be sent across threads. This is because +/// wakers can incur in additional cost related to memory synchronization. +/// +/// Note that it is preferable to use `local_waker.clone_from(&new_waker)` instead +/// of `*local_waker = new_waker.clone()`, as the former will avoid cloning the waker +/// unnecessarily if the two wakers [wake the same task](Self::will_wake). +/// +/// # Examples +/// Usage of a local waker to implement a future analogous to `std::thread::yield_now()`. +/// ``` +/// #![feature(local_waker)] +/// use std::future::{Future, poll_fn}; +/// use std::task::Poll; +/// +/// // a future that returns pending once. +/// fn yield_now() -> impl Future + Unpin { +/// let mut yielded = false; +/// poll_fn(move |cx| { +/// if !yielded { +/// yielded = true; +/// cx.local_waker().wake_by_ref(); +/// return Poll::Pending; +/// } +/// return Poll::Ready(()) +/// }) +/// } +/// +/// # async fn __() { +/// yield_now().await; +/// # } +/// ``` +/// +/// [`Future::poll()`]: core::future::Future::poll +/// [`Poll::Pending`]: core::task::Poll::Pending +/// [`local_waker`]: core::task::Context::local_waker +#[unstable(feature = "local_waker", issue = "118959")] +#[repr(transparent)] +pub struct LocalWaker { + waker: RawWaker, +} + +#[unstable(feature = "local_waker", issue = "118959")] +impl Unpin for LocalWaker {} + +impl LocalWaker { + /// Wakes up the task associated with this `LocalWaker`. + /// + /// As long as the executor keeps running and the task is not finished, it is + /// guaranteed that each invocation of [`wake()`](Self::wake) (or + /// [`wake_by_ref()`](Self::wake_by_ref)) will be followed by at least one + /// [`poll()`] of the task to which this `LocalWaker` belongs. This makes + /// it possible to temporarily yield to other tasks while running potentially + /// unbounded processing loops. + /// + /// Note that the above implies that multiple wake-ups may be coalesced into a + /// single [`poll()`] invocation by the runtime. + /// + /// Also note that yielding to competing tasks is not guaranteed: it is the + /// executor’s choice which task to run and the executor may choose to run the + /// current task again. + /// + /// [`poll()`]: crate::future::Future::poll + #[inline] + #[unstable(feature = "local_waker", issue = "118959")] + pub fn wake(self) { + // The actual wakeup call is delegated through a virtual function call + // to the implementation which is defined by the executor. + + // Don't call `drop` -- the waker will be consumed by `wake`. + let this = ManuallyDrop::new(self); + + // SAFETY: This is safe because `Waker::from_raw` is the only way + // to initialize `wake` and `data` requiring the user to acknowledge + // that the contract of `RawWaker` is upheld. + unsafe { (this.waker.vtable.wake)(this.waker.data) }; + } + + /// Wakes up the task associated with this `LocalWaker` without consuming the `LocalWaker`. + /// + /// This is similar to [`wake()`](Self::wake), but may be slightly less efficient in + /// the case where an owned `Waker` is available. This method should be preferred to + /// calling `waker.clone().wake()`. + #[inline] + #[unstable(feature = "local_waker", issue = "118959")] + pub fn wake_by_ref(&self) { + // The actual wakeup call is delegated through a virtual function call + // to the implementation which is defined by the executor. + + // SAFETY: see `wake` + unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) } + } + + /// Returns `true` if this `LocalWaker` and another `LocalWaker` would awake the same task. + /// + /// This function works on a best-effort basis, and may return false even + /// when the `Waker`s would awaken the same task. However, if this function + /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task. + /// + /// This function is primarily used for optimization purposes — for example, + /// this type's [`clone_from`](Self::clone_from) implementation uses it to + /// avoid cloning the waker when they would wake the same task anyway. + #[inline] + #[must_use] + #[unstable(feature = "local_waker", issue = "118959")] + pub fn will_wake(&self, other: &LocalWaker) -> bool { + // We optimize this by comparing vtable addresses instead of vtable contents. + // This is permitted since the function is documented as best-effort. + let RawWaker { data: a_data, vtable: a_vtable } = self.waker; + let RawWaker { data: b_data, vtable: b_vtable } = other.waker; + a_data == b_data && ptr::eq(a_vtable, b_vtable) + } + + /// Creates a new `LocalWaker` from the provided `data` pointer and `vtable`. + /// + /// The `data` pointer can be used to store arbitrary data as required + /// by the executor. This could be e.g. a type-erased pointer to an `Arc` + /// that is associated with the task. + /// The value of this pointer will get passed to all functions that are part + /// of the `vtable` as the first parameter. + /// + /// The `vtable` customizes the behavior of a `LocalWaker`. For each + /// operation on the `LocalWaker`, the associated function in the `vtable` + /// will be called. + /// + /// # Safety + /// + /// The behavior of the returned `Waker` is undefined if the contract defined + /// in [`RawWakerVTable`]'s documentation is not upheld. + /// + #[inline] + #[must_use] + #[unstable(feature = "local_waker", issue = "118959")] + pub const unsafe fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self { + LocalWaker { waker: RawWaker { data, vtable } } + } + + /// Creates a new `LocalWaker` from [`RawWaker`]. + /// + /// The behavior of the returned `LocalWaker` is undefined if the contract defined + /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. + /// Therefore this method is unsafe. + #[inline] + #[must_use] + #[unstable(feature = "local_waker", issue = "118959")] + pub const unsafe fn from_raw(waker: RawWaker) -> LocalWaker { + Self { waker } + } + + /// Returns a reference to a `LocalWaker` that does nothing when used. + /// + // Note! Much of the documentation for this method is duplicated + // in the docs for `Waker::noop`. + // If you edit it, consider editing the other copy too. + // + /// This is mostly useful for writing tests that need a [`Context`] to poll + /// some futures, but are not expecting those futures to wake the waker or + /// do not need to do anything specific if it happens. + /// + /// More generally, using `LocalWaker::noop()` to poll a future + /// means discarding the notification of when the future should be polled again, + /// So it should only be used when such a notification will not be needed to make progress. + /// + /// If an owned `LocalWaker` is needed, `clone()` this one. + /// + /// # Examples + /// + /// ``` + /// #![feature(local_waker)] + /// use std::future::Future; + /// use std::task::{ContextBuilder, LocalWaker, Waker, Poll}; + /// + /// let mut cx = ContextBuilder::from_waker(Waker::noop()) + /// .local_waker(LocalWaker::noop()) + /// .build(); + /// + /// let mut future = Box::pin(async { 10 }); + /// assert_eq!(future.as_mut().poll(&mut cx), Poll::Ready(10)); + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "local_waker", issue = "118959")] + pub const fn noop() -> &'static LocalWaker { + const WAKER: &LocalWaker = &LocalWaker { waker: RawWaker::NOOP }; + WAKER + } + + /// Gets the `data` pointer used to create this `LocalWaker`. + #[inline] + #[must_use] + #[unstable(feature = "local_waker", issue = "118959")] + pub fn data(&self) -> *const () { + self.waker.data + } + + /// Gets the `vtable` pointer used to create this `LocalWaker`. + #[inline] + #[must_use] + #[unstable(feature = "local_waker", issue = "118959")] + pub fn vtable(&self) -> &'static RawWakerVTable { + self.waker.vtable + } +} +#[unstable(feature = "local_waker", issue = "118959")] +impl Clone for LocalWaker { + #[inline] + fn clone(&self) -> Self { + LocalWaker { + // SAFETY: This is safe because `Waker::from_raw` is the only way + // to initialize `clone` and `data` requiring the user to acknowledge + // that the contract of [`RawWaker`] is upheld. + waker: unsafe { (self.waker.vtable.clone)(self.waker.data) }, + } + } + + #[inline] + fn clone_from(&mut self, source: &Self) { + if !self.will_wake(source) { + *self = source.clone(); + } + } +} + +#[unstable(feature = "local_waker", issue = "118959")] +impl AsRef for Waker { + fn as_ref(&self) -> &LocalWaker { + // SAFETY: LocalWaker is just Waker without thread safety + unsafe { transmute(self) } + } +} + +#[unstable(feature = "local_waker", issue = "118959")] +impl Drop for LocalWaker { + #[inline] + fn drop(&mut self) { + // SAFETY: This is safe because `LocalWaker::from_raw` is the only way + // to initialize `drop` and `data` requiring the user to acknowledge + // that the contract of `RawWaker` is upheld. + unsafe { (self.waker.vtable.drop)(self.waker.data) } + } +} + +#[unstable(feature = "local_waker", issue = "118959")] +impl fmt::Debug for LocalWaker { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let vtable_ptr = self.waker.vtable as *const RawWakerVTable; + f.debug_struct("LocalWaker") + .field("data", &self.waker.data) + .field("vtable", &vtable_ptr) + .finish() + } +} + +#[unstable(feature = "local_waker", issue = "118959")] +impl !Send for LocalWaker {} +#[unstable(feature = "local_waker", issue = "118959")] +impl !Sync for LocalWaker {} diff --git a/CoqOfRust/core/time.rs b/CoqOfRust/core/time.rs new file mode 100644 index 000000000..2d93148ba --- /dev/null +++ b/CoqOfRust/core/time.rs @@ -0,0 +1,1700 @@ +#![stable(feature = "duration_core", since = "1.25.0")] + +//! Temporal quantification. +//! +//! # Examples: +//! +//! There are multiple ways to create a new [`Duration`]: +//! +//! ``` +//! # use std::time::Duration; +//! let five_seconds = Duration::from_secs(5); +//! assert_eq!(five_seconds, Duration::from_millis(5_000)); +//! assert_eq!(five_seconds, Duration::from_micros(5_000_000)); +//! assert_eq!(five_seconds, Duration::from_nanos(5_000_000_000)); +//! +//! let ten_seconds = Duration::from_secs(10); +//! let seven_nanos = Duration::from_nanos(7); +//! let total = ten_seconds + seven_nanos; +//! assert_eq!(total, Duration::new(10, 7)); +//! ``` + +use crate::fmt; +use crate::iter::Sum; +use crate::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; + +const NANOS_PER_SEC: u32 = 1_000_000_000; +const NANOS_PER_MILLI: u32 = 1_000_000; +const NANOS_PER_MICRO: u32 = 1_000; +const MILLIS_PER_SEC: u64 = 1_000; +const MICROS_PER_SEC: u64 = 1_000_000; +#[unstable(feature = "duration_units", issue = "120301")] +const SECS_PER_MINUTE: u64 = 60; +#[unstable(feature = "duration_units", issue = "120301")] +const MINS_PER_HOUR: u64 = 60; +#[unstable(feature = "duration_units", issue = "120301")] +const HOURS_PER_DAY: u64 = 24; +#[unstable(feature = "duration_units", issue = "120301")] +const DAYS_PER_WEEK: u64 = 7; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] +#[rustc_layout_scalar_valid_range_start(0)] +#[rustc_layout_scalar_valid_range_end(999_999_999)] +struct Nanoseconds(u32); + +impl Nanoseconds { + // SAFETY: 0 is within the valid range + const ZERO: Self = unsafe { Nanoseconds(0) }; +} + +impl Default for Nanoseconds { + #[inline] + fn default() -> Self { + Self::ZERO + } +} + +/// A `Duration` type to represent a span of time, typically used for system +/// timeouts. +/// +/// Each `Duration` is composed of a whole number of seconds and a fractional part +/// represented in nanoseconds. If the underlying system does not support +/// nanosecond-level precision, APIs binding a system timeout will typically round up +/// the number of nanoseconds. +/// +/// [`Duration`]s implement many common traits, including [`Add`], [`Sub`], and other +/// [`ops`] traits. It implements [`Default`] by returning a zero-length `Duration`. +/// +/// [`ops`]: crate::ops +/// +/// # Examples +/// +/// ``` +/// use std::time::Duration; +/// +/// let five_seconds = Duration::new(5, 0); +/// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5); +/// +/// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5); +/// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5); +/// +/// let ten_millis = Duration::from_millis(10); +/// ``` +/// +/// # Formatting `Duration` values +/// +/// `Duration` intentionally does not have a `Display` impl, as there are a +/// variety of ways to format spans of time for human readability. `Duration` +/// provides a `Debug` impl that shows the full precision of the value. +/// +/// The `Debug` output uses the non-ASCII "µs" suffix for microseconds. If your +/// program output may appear in contexts that cannot rely on full Unicode +/// compatibility, you may wish to format `Duration` objects yourself or use a +/// crate to do so. +#[stable(feature = "duration", since = "1.3.0")] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[cfg_attr(not(test), rustc_diagnostic_item = "Duration")] +pub struct Duration { + secs: u64, + nanos: Nanoseconds, // Always 0 <= nanos < NANOS_PER_SEC +} + +impl Duration { + /// The duration of one second. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constants)] + /// use std::time::Duration; + /// + /// assert_eq!(Duration::SECOND, Duration::from_secs(1)); + /// ``` + #[unstable(feature = "duration_constants", issue = "57391")] + pub const SECOND: Duration = Duration::from_secs(1); + + /// The duration of one millisecond. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constants)] + /// use std::time::Duration; + /// + /// assert_eq!(Duration::MILLISECOND, Duration::from_millis(1)); + /// ``` + #[unstable(feature = "duration_constants", issue = "57391")] + pub const MILLISECOND: Duration = Duration::from_millis(1); + + /// The duration of one microsecond. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constants)] + /// use std::time::Duration; + /// + /// assert_eq!(Duration::MICROSECOND, Duration::from_micros(1)); + /// ``` + #[unstable(feature = "duration_constants", issue = "57391")] + pub const MICROSECOND: Duration = Duration::from_micros(1); + + /// The duration of one nanosecond. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constants)] + /// use std::time::Duration; + /// + /// assert_eq!(Duration::NANOSECOND, Duration::from_nanos(1)); + /// ``` + #[unstable(feature = "duration_constants", issue = "57391")] + pub const NANOSECOND: Duration = Duration::from_nanos(1); + + /// A duration of zero time. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::ZERO; + /// assert!(duration.is_zero()); + /// assert_eq!(duration.as_nanos(), 0); + /// ``` + #[stable(feature = "duration_zero", since = "1.53.0")] + pub const ZERO: Duration = Duration::from_nanos(0); + + /// The maximum duration. + /// + /// May vary by platform as necessary. Must be able to contain the difference between + /// two instances of [`Instant`] or two instances of [`SystemTime`]. + /// This constraint gives it a value of about 584,942,417,355 years in practice, + /// which is currently used on all platforms. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// assert_eq!(Duration::MAX, Duration::new(u64::MAX, 1_000_000_000 - 1)); + /// ``` + /// [`Instant`]: ../../std/time/struct.Instant.html + /// [`SystemTime`]: ../../std/time/struct.SystemTime.html + #[stable(feature = "duration_saturating_ops", since = "1.53.0")] + pub const MAX: Duration = Duration::new(u64::MAX, NANOS_PER_SEC - 1); + + /// Creates a new `Duration` from the specified number of whole seconds and + /// additional nanoseconds. + /// + /// If the number of nanoseconds is greater than 1 billion (the number of + /// nanoseconds in a second), then it will carry over into the seconds provided. + /// + /// # Panics + /// + /// This constructor will panic if the carry from the nanoseconds overflows + /// the seconds counter. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let five_seconds = Duration::new(5, 0); + /// ``` + #[stable(feature = "duration", since = "1.3.0")] + #[inline] + #[must_use] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] + pub const fn new(secs: u64, nanos: u32) -> Duration { + if nanos < NANOS_PER_SEC { + // SAFETY: nanos < NANOS_PER_SEC, therefore nanos is within the valid range + Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } + } else { + let secs = secs + .checked_add((nanos / NANOS_PER_SEC) as u64) + .expect("overflow in Duration::new"); + let nanos = nanos % NANOS_PER_SEC; + // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range + Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } + } + } + + /// Creates a new `Duration` from the specified number of whole seconds. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::from_secs(5); + /// + /// assert_eq!(5, duration.as_secs()); + /// assert_eq!(0, duration.subsec_nanos()); + /// ``` + #[stable(feature = "duration", since = "1.3.0")] + #[must_use] + #[inline] + #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] + pub const fn from_secs(secs: u64) -> Duration { + Duration { secs, nanos: Nanoseconds::ZERO } + } + + /// Creates a new `Duration` from the specified number of milliseconds. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::from_millis(2_569); + /// + /// assert_eq!(2, duration.as_secs()); + /// assert_eq!(569_000_000, duration.subsec_nanos()); + /// ``` + #[stable(feature = "duration", since = "1.3.0")] + #[must_use] + #[inline] + #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] + pub const fn from_millis(millis: u64) -> Duration { + let secs = millis / MILLIS_PER_SEC; + let subsec_millis = (millis % MILLIS_PER_SEC) as u32; + // SAFETY: (x % 1_000) * 1_000_000 < 1_000_000_000 + // => x % 1_000 < 1_000 + let subsec_nanos = unsafe { Nanoseconds(subsec_millis * NANOS_PER_MILLI) }; + + Duration { secs, nanos: subsec_nanos } + } + + /// Creates a new `Duration` from the specified number of microseconds. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::from_micros(1_000_002); + /// + /// assert_eq!(1, duration.as_secs()); + /// assert_eq!(2_000, duration.subsec_nanos()); + /// ``` + #[stable(feature = "duration_from_micros", since = "1.27.0")] + #[must_use] + #[inline] + #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] + pub const fn from_micros(micros: u64) -> Duration { + let secs = micros / MICROS_PER_SEC; + let subsec_micros = (micros % MICROS_PER_SEC) as u32; + // SAFETY: (x % 1_000_000) * 1_000 < 1_000_000_000 + // => x % 1_000_000 < 1_000_000 + let subsec_nanos = unsafe { Nanoseconds(subsec_micros * NANOS_PER_MICRO) }; + + Duration { secs, nanos: subsec_nanos } + } + + /// Creates a new `Duration` from the specified number of nanoseconds. + /// + /// Note: Using this on the return value of `as_nanos()` might cause unexpected behavior: + /// `as_nanos()` returns a u128, and can return values that do not fit in u64, e.g. 585 years. + /// Instead, consider using the pattern `Duration::new(d.as_secs(), d.subsec_nanos())` + /// if you cannot copy/clone the Duration directly. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::from_nanos(1_000_000_123); + /// + /// assert_eq!(1, duration.as_secs()); + /// assert_eq!(123, duration.subsec_nanos()); + /// ``` + #[stable(feature = "duration_extras", since = "1.27.0")] + #[must_use] + #[inline] + #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] + pub const fn from_nanos(nanos: u64) -> Duration { + const NANOS_PER_SEC: u64 = self::NANOS_PER_SEC as u64; + let secs = nanos / NANOS_PER_SEC; + let subsec_nanos = (nanos % NANOS_PER_SEC) as u32; + // SAFETY: x % 1_000_000_000 < 1_000_000_000 + let subsec_nanos = unsafe { Nanoseconds(subsec_nanos) }; + + Duration { secs, nanos: subsec_nanos } + } + + /// Creates a new `Duration` from the specified number of weeks. + /// + /// # Panics + /// + /// Panics if the given number of weeks overflows the `Duration` size. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constructors)] + /// use std::time::Duration; + /// + /// let duration = Duration::from_weeks(4); + /// + /// assert_eq!(4 * 7 * 24 * 60 * 60, duration.as_secs()); + /// assert_eq!(0, duration.subsec_nanos()); + /// ``` + #[unstable(feature = "duration_constructors", issue = "120301")] + #[must_use] + #[inline] + pub const fn from_weeks(weeks: u64) -> Duration { + if weeks > u64::MAX / (SECS_PER_MINUTE * MINS_PER_HOUR * HOURS_PER_DAY * DAYS_PER_WEEK) { + panic!("overflow in Duration::from_weeks"); + } + + Duration::from_secs(weeks * MINS_PER_HOUR * SECS_PER_MINUTE * HOURS_PER_DAY * DAYS_PER_WEEK) + } + + /// Creates a new `Duration` from the specified number of days. + /// + /// # Panics + /// + /// Panics if the given number of days overflows the `Duration` size. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constructors)] + /// use std::time::Duration; + /// + /// let duration = Duration::from_days(7); + /// + /// assert_eq!(7 * 24 * 60 * 60, duration.as_secs()); + /// assert_eq!(0, duration.subsec_nanos()); + /// ``` + #[unstable(feature = "duration_constructors", issue = "120301")] + #[must_use] + #[inline] + pub const fn from_days(days: u64) -> Duration { + if days > u64::MAX / (SECS_PER_MINUTE * MINS_PER_HOUR * HOURS_PER_DAY) { + panic!("overflow in Duration::from_days"); + } + + Duration::from_secs(days * MINS_PER_HOUR * SECS_PER_MINUTE * HOURS_PER_DAY) + } + + /// Creates a new `Duration` from the specified number of hours. + /// + /// # Panics + /// + /// Panics if the given number of hours overflows the `Duration` size. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constructors)] + /// use std::time::Duration; + /// + /// let duration = Duration::from_hours(6); + /// + /// assert_eq!(6 * 60 * 60, duration.as_secs()); + /// assert_eq!(0, duration.subsec_nanos()); + /// ``` + #[unstable(feature = "duration_constructors", issue = "120301")] + #[must_use] + #[inline] + pub const fn from_hours(hours: u64) -> Duration { + if hours > u64::MAX / (SECS_PER_MINUTE * MINS_PER_HOUR) { + panic!("overflow in Duration::from_hours"); + } + + Duration::from_secs(hours * MINS_PER_HOUR * SECS_PER_MINUTE) + } + + /// Creates a new `Duration` from the specified number of minutes. + /// + /// # Panics + /// + /// Panics if the given number of minutes overflows the `Duration` size. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constructors)] + /// use std::time::Duration; + /// + /// let duration = Duration::from_mins(10); + /// + /// assert_eq!(10 * 60, duration.as_secs()); + /// assert_eq!(0, duration.subsec_nanos()); + /// ``` + #[unstable(feature = "duration_constructors", issue = "120301")] + #[must_use] + #[inline] + pub const fn from_mins(mins: u64) -> Duration { + if mins > u64::MAX / SECS_PER_MINUTE { + panic!("overflow in Duration::from_mins"); + } + + Duration::from_secs(mins * SECS_PER_MINUTE) + } + + /// Returns true if this `Duration` spans no time. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// assert!(Duration::ZERO.is_zero()); + /// assert!(Duration::new(0, 0).is_zero()); + /// assert!(Duration::from_nanos(0).is_zero()); + /// assert!(Duration::from_secs(0).is_zero()); + /// + /// assert!(!Duration::new(1, 1).is_zero()); + /// assert!(!Duration::from_nanos(1).is_zero()); + /// assert!(!Duration::from_secs(1).is_zero()); + /// ``` + #[must_use] + #[stable(feature = "duration_zero", since = "1.53.0")] + #[rustc_const_stable(feature = "duration_zero", since = "1.53.0")] + #[inline] + pub const fn is_zero(&self) -> bool { + self.secs == 0 && self.nanos.0 == 0 + } + + /// Returns the number of _whole_ seconds contained by this `Duration`. + /// + /// The returned value does not include the fractional (nanosecond) part of the + /// duration, which can be obtained using [`subsec_nanos`]. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::new(5, 730_023_852); + /// assert_eq!(duration.as_secs(), 5); + /// ``` + /// + /// To determine the total number of seconds represented by the `Duration` + /// including the fractional part, use [`as_secs_f64`] or [`as_secs_f32`] + /// + /// [`as_secs_f64`]: Duration::as_secs_f64 + /// [`as_secs_f32`]: Duration::as_secs_f32 + /// [`subsec_nanos`]: Duration::subsec_nanos + #[stable(feature = "duration", since = "1.3.0")] + #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] + #[must_use] + #[inline] + pub const fn as_secs(&self) -> u64 { + self.secs + } + + /// Returns the fractional part of this `Duration`, in whole milliseconds. + /// + /// This method does **not** return the length of the duration when + /// represented by milliseconds. The returned number always represents a + /// fractional portion of a second (i.e., it is less than one thousand). + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::from_millis(5_432); + /// assert_eq!(duration.as_secs(), 5); + /// assert_eq!(duration.subsec_millis(), 432); + /// ``` + #[stable(feature = "duration_extras", since = "1.27.0")] + #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] + #[must_use] + #[inline] + pub const fn subsec_millis(&self) -> u32 { + self.nanos.0 / NANOS_PER_MILLI + } + + /// Returns the fractional part of this `Duration`, in whole microseconds. + /// + /// This method does **not** return the length of the duration when + /// represented by microseconds. The returned number always represents a + /// fractional portion of a second (i.e., it is less than one million). + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::from_micros(1_234_567); + /// assert_eq!(duration.as_secs(), 1); + /// assert_eq!(duration.subsec_micros(), 234_567); + /// ``` + #[stable(feature = "duration_extras", since = "1.27.0")] + #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] + #[must_use] + #[inline] + pub const fn subsec_micros(&self) -> u32 { + self.nanos.0 / NANOS_PER_MICRO + } + + /// Returns the fractional part of this `Duration`, in nanoseconds. + /// + /// This method does **not** return the length of the duration when + /// represented by nanoseconds. The returned number always represents a + /// fractional portion of a second (i.e., it is less than one billion). + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::from_millis(5_010); + /// assert_eq!(duration.as_secs(), 5); + /// assert_eq!(duration.subsec_nanos(), 10_000_000); + /// ``` + #[stable(feature = "duration", since = "1.3.0")] + #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] + #[must_use] + #[inline] + pub const fn subsec_nanos(&self) -> u32 { + self.nanos.0 + } + + /// Returns the total number of whole milliseconds contained by this `Duration`. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::new(5, 730_023_852); + /// assert_eq!(duration.as_millis(), 5_730); + /// ``` + #[stable(feature = "duration_as_u128", since = "1.33.0")] + #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] + #[must_use] + #[inline] + pub const fn as_millis(&self) -> u128 { + self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MILLI) as u128 + } + + /// Returns the total number of whole microseconds contained by this `Duration`. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::new(5, 730_023_852); + /// assert_eq!(duration.as_micros(), 5_730_023); + /// ``` + #[stable(feature = "duration_as_u128", since = "1.33.0")] + #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] + #[must_use] + #[inline] + pub const fn as_micros(&self) -> u128 { + self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MICRO) as u128 + } + + /// Returns the total number of nanoseconds contained by this `Duration`. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::new(5, 730_023_852); + /// assert_eq!(duration.as_nanos(), 5_730_023_852); + /// ``` + #[stable(feature = "duration_as_u128", since = "1.33.0")] + #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] + #[must_use] + #[inline] + pub const fn as_nanos(&self) -> u128 { + self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos.0 as u128 + } + + /// Computes the absolute difference between `self` and `other`. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// assert_eq!(Duration::new(100, 0).abs_diff(Duration::new(80, 0)), Duration::new(20, 0)); + /// assert_eq!(Duration::new(100, 400_000_000).abs_diff(Duration::new(110, 0)), Duration::new(9, 600_000_000)); + /// ``` + #[stable(feature = "duration_abs_diff", since = "1.81.0")] + #[rustc_const_stable(feature = "duration_abs_diff", since = "1.81.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn abs_diff(self, other: Duration) -> Duration { + if let Some(res) = self.checked_sub(other) { res } else { other.checked_sub(self).unwrap() } + } + + /// Checked `Duration` addition. Computes `self + other`, returning [`None`] + /// if overflow occurred. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1))); + /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(u64::MAX, 0)), None); + /// ``` + #[stable(feature = "duration_checked_ops", since = "1.16.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] + pub const fn checked_add(self, rhs: Duration) -> Option { + if let Some(mut secs) = self.secs.checked_add(rhs.secs) { + let mut nanos = self.nanos.0 + rhs.nanos.0; + if nanos >= NANOS_PER_SEC { + nanos -= NANOS_PER_SEC; + if let Some(new_secs) = secs.checked_add(1) { + secs = new_secs; + } else { + return None; + } + } + debug_assert!(nanos < NANOS_PER_SEC); + Some(Duration::new(secs, nanos)) + } else { + None + } + } + + /// Saturating `Duration` addition. Computes `self + other`, returning [`Duration::MAX`] + /// if overflow occurred. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constants)] + /// use std::time::Duration; + /// + /// assert_eq!(Duration::new(0, 0).saturating_add(Duration::new(0, 1)), Duration::new(0, 1)); + /// assert_eq!(Duration::new(1, 0).saturating_add(Duration::new(u64::MAX, 0)), Duration::MAX); + /// ``` + #[stable(feature = "duration_saturating_ops", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] + pub const fn saturating_add(self, rhs: Duration) -> Duration { + match self.checked_add(rhs) { + Some(res) => res, + None => Duration::MAX, + } + } + + /// Checked `Duration` subtraction. Computes `self - other`, returning [`None`] + /// if the result would be negative or if overflow occurred. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// assert_eq!(Duration::new(0, 1).checked_sub(Duration::new(0, 0)), Some(Duration::new(0, 1))); + /// assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None); + /// ``` + #[stable(feature = "duration_checked_ops", since = "1.16.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] + pub const fn checked_sub(self, rhs: Duration) -> Option { + if let Some(mut secs) = self.secs.checked_sub(rhs.secs) { + let nanos = if self.nanos.0 >= rhs.nanos.0 { + self.nanos.0 - rhs.nanos.0 + } else if let Some(sub_secs) = secs.checked_sub(1) { + secs = sub_secs; + self.nanos.0 + NANOS_PER_SEC - rhs.nanos.0 + } else { + return None; + }; + debug_assert!(nanos < NANOS_PER_SEC); + Some(Duration::new(secs, nanos)) + } else { + None + } + } + + /// Saturating `Duration` subtraction. Computes `self - other`, returning [`Duration::ZERO`] + /// if the result would be negative or if overflow occurred. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// assert_eq!(Duration::new(0, 1).saturating_sub(Duration::new(0, 0)), Duration::new(0, 1)); + /// assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::ZERO); + /// ``` + #[stable(feature = "duration_saturating_ops", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] + pub const fn saturating_sub(self, rhs: Duration) -> Duration { + match self.checked_sub(rhs) { + Some(res) => res, + None => Duration::ZERO, + } + } + + /// Checked `Duration` multiplication. Computes `self * other`, returning + /// [`None`] if overflow occurred. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2))); + /// assert_eq!(Duration::new(u64::MAX - 1, 0).checked_mul(2), None); + /// ``` + #[stable(feature = "duration_checked_ops", since = "1.16.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] + pub const fn checked_mul(self, rhs: u32) -> Option { + // Multiply nanoseconds as u64, because it cannot overflow that way. + let total_nanos = self.nanos.0 as u64 * rhs as u64; + let extra_secs = total_nanos / (NANOS_PER_SEC as u64); + let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; + // FIXME(const-hack): use `and_then` once that is possible. + if let Some(s) = self.secs.checked_mul(rhs as u64) { + if let Some(secs) = s.checked_add(extra_secs) { + debug_assert!(nanos < NANOS_PER_SEC); + return Some(Duration::new(secs, nanos)); + } + } + None + } + + /// Saturating `Duration` multiplication. Computes `self * other`, returning + /// [`Duration::MAX`] if overflow occurred. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constants)] + /// use std::time::Duration; + /// + /// assert_eq!(Duration::new(0, 500_000_001).saturating_mul(2), Duration::new(1, 2)); + /// assert_eq!(Duration::new(u64::MAX - 1, 0).saturating_mul(2), Duration::MAX); + /// ``` + #[stable(feature = "duration_saturating_ops", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] + pub const fn saturating_mul(self, rhs: u32) -> Duration { + match self.checked_mul(rhs) { + Some(res) => res, + None => Duration::MAX, + } + } + + /// Checked `Duration` division. Computes `self / other`, returning [`None`] + /// if `other == 0`. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); + /// assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); + /// assert_eq!(Duration::new(2, 0).checked_div(0), None); + /// ``` + #[stable(feature = "duration_checked_ops", since = "1.16.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] + pub const fn checked_div(self, rhs: u32) -> Option { + if rhs != 0 { + let (secs, extra_secs) = (self.secs / (rhs as u64), self.secs % (rhs as u64)); + let (mut nanos, extra_nanos) = (self.nanos.0 / rhs, self.nanos.0 % rhs); + nanos += + ((extra_secs * (NANOS_PER_SEC as u64) + extra_nanos as u64) / (rhs as u64)) as u32; + debug_assert!(nanos < NANOS_PER_SEC); + Some(Duration::new(secs, nanos)) + } else { + None + } + } + + /// Returns the number of seconds contained by this `Duration` as `f64`. + /// + /// The returned value includes the fractional (nanosecond) part of the duration. + /// + /// # Examples + /// ``` + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 700_000_000); + /// assert_eq!(dur.as_secs_f64(), 2.7); + /// ``` + #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use] + #[inline] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] + pub const fn as_secs_f64(&self) -> f64 { + (self.secs as f64) + (self.nanos.0 as f64) / (NANOS_PER_SEC as f64) + } + + /// Returns the number of seconds contained by this `Duration` as `f32`. + /// + /// The returned value includes the fractional (nanosecond) part of the duration. + /// + /// # Examples + /// ``` + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 700_000_000); + /// assert_eq!(dur.as_secs_f32(), 2.7); + /// ``` + #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use] + #[inline] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] + pub const fn as_secs_f32(&self) -> f32 { + (self.secs as f32) + (self.nanos.0 as f32) / (NANOS_PER_SEC as f32) + } + + /// Returns the number of milliseconds contained by this `Duration` as `f64`. + /// + /// The returned value includes the fractional (nanosecond) part of the duration. + /// + /// # Examples + /// ``` + /// #![feature(duration_millis_float)] + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 345_678_000); + /// assert_eq!(dur.as_millis_f64(), 2_345.678); + /// ``` + #[unstable(feature = "duration_millis_float", issue = "122451")] + #[must_use] + #[inline] + pub const fn as_millis_f64(&self) -> f64 { + (self.secs as f64) * (MILLIS_PER_SEC as f64) + + (self.nanos.0 as f64) / (NANOS_PER_MILLI as f64) + } + + /// Returns the number of milliseconds contained by this `Duration` as `f32`. + /// + /// The returned value includes the fractional (nanosecond) part of the duration. + /// + /// # Examples + /// ``` + /// #![feature(duration_millis_float)] + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 345_678_000); + /// assert_eq!(dur.as_millis_f32(), 2_345.678); + /// ``` + #[unstable(feature = "duration_millis_float", issue = "122451")] + #[must_use] + #[inline] + pub const fn as_millis_f32(&self) -> f32 { + (self.secs as f32) * (MILLIS_PER_SEC as f32) + + (self.nanos.0 as f32) / (NANOS_PER_MILLI as f32) + } + + /// Creates a new `Duration` from the specified number of seconds represented + /// as `f64`. + /// + /// # Panics + /// This constructor will panic if `secs` is negative, overflows `Duration` or not finite. + /// + /// # Examples + /// ``` + /// use std::time::Duration; + /// + /// let res = Duration::from_secs_f64(0.0); + /// assert_eq!(res, Duration::new(0, 0)); + /// let res = Duration::from_secs_f64(1e-20); + /// assert_eq!(res, Duration::new(0, 0)); + /// let res = Duration::from_secs_f64(4.2e-7); + /// assert_eq!(res, Duration::new(0, 420)); + /// let res = Duration::from_secs_f64(2.7); + /// assert_eq!(res, Duration::new(2, 700_000_000)); + /// let res = Duration::from_secs_f64(3e10); + /// assert_eq!(res, Duration::new(30_000_000_000, 0)); + /// // subnormal float + /// let res = Duration::from_secs_f64(f64::from_bits(1)); + /// assert_eq!(res, Duration::new(0, 0)); + /// // conversion uses rounding + /// let res = Duration::from_secs_f64(0.999e-9); + /// assert_eq!(res, Duration::new(0, 1)); + /// ``` + #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use] + #[inline] + pub fn from_secs_f64(secs: f64) -> Duration { + match Duration::try_from_secs_f64(secs) { + Ok(v) => v, + Err(e) => panic!("{}", e.description()), + } + } + + /// Creates a new `Duration` from the specified number of seconds represented + /// as `f32`. + /// + /// # Panics + /// This constructor will panic if `secs` is negative, overflows `Duration` or not finite. + /// + /// # Examples + /// ``` + /// use std::time::Duration; + /// + /// let res = Duration::from_secs_f32(0.0); + /// assert_eq!(res, Duration::new(0, 0)); + /// let res = Duration::from_secs_f32(1e-20); + /// assert_eq!(res, Duration::new(0, 0)); + /// let res = Duration::from_secs_f32(4.2e-7); + /// assert_eq!(res, Duration::new(0, 420)); + /// let res = Duration::from_secs_f32(2.7); + /// assert_eq!(res, Duration::new(2, 700_000_048)); + /// let res = Duration::from_secs_f32(3e10); + /// assert_eq!(res, Duration::new(30_000_001_024, 0)); + /// // subnormal float + /// let res = Duration::from_secs_f32(f32::from_bits(1)); + /// assert_eq!(res, Duration::new(0, 0)); + /// // conversion uses rounding + /// let res = Duration::from_secs_f32(0.999e-9); + /// assert_eq!(res, Duration::new(0, 1)); + /// ``` + #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use] + #[inline] + pub fn from_secs_f32(secs: f32) -> Duration { + match Duration::try_from_secs_f32(secs) { + Ok(v) => v, + Err(e) => panic!("{}", e.description()), + } + } + + /// Multiplies `Duration` by `f64`. + /// + /// # Panics + /// This method will panic if result is negative, overflows `Duration` or not finite. + /// + /// # Examples + /// ``` + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 700_000_000); + /// assert_eq!(dur.mul_f64(3.14), Duration::new(8, 478_000_000)); + /// assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0)); + /// ``` + #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub fn mul_f64(self, rhs: f64) -> Duration { + Duration::from_secs_f64(rhs * self.as_secs_f64()) + } + + /// Multiplies `Duration` by `f32`. + /// + /// # Panics + /// This method will panic if result is negative, overflows `Duration` or not finite. + /// + /// # Examples + /// ``` + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 700_000_000); + /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_641)); + /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847_800, 0)); + /// ``` + #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub fn mul_f32(self, rhs: f32) -> Duration { + Duration::from_secs_f32(rhs * self.as_secs_f32()) + } + + /// Divides `Duration` by `f64`. + /// + /// # Panics + /// This method will panic if result is negative, overflows `Duration` or not finite. + /// + /// # Examples + /// ``` + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 700_000_000); + /// assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611)); + /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_599)); + /// ``` + #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub fn div_f64(self, rhs: f64) -> Duration { + Duration::from_secs_f64(self.as_secs_f64() / rhs) + } + + /// Divides `Duration` by `f32`. + /// + /// # Panics + /// This method will panic if result is negative, overflows `Duration` or not finite. + /// + /// # Examples + /// ``` + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 700_000_000); + /// // note that due to rounding errors result is slightly + /// // different from 0.859_872_611 + /// assert_eq!(dur.div_f32(3.14), Duration::new(0, 859_872_580)); + /// assert_eq!(dur.div_f32(3.14e5), Duration::new(0, 8_599)); + /// ``` + #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub fn div_f32(self, rhs: f32) -> Duration { + Duration::from_secs_f32(self.as_secs_f32() / rhs) + } + + /// Divides `Duration` by `Duration` and returns `f64`. + /// + /// # Examples + /// ``` + /// use std::time::Duration; + /// + /// let dur1 = Duration::new(2, 700_000_000); + /// let dur2 = Duration::new(5, 400_000_000); + /// assert_eq!(dur1.div_duration_f64(dur2), 0.5); + /// ``` + #[stable(feature = "div_duration", since = "1.80.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] + pub const fn div_duration_f64(self, rhs: Duration) -> f64 { + let self_nanos = (self.secs as f64) * (NANOS_PER_SEC as f64) + (self.nanos.0 as f64); + let rhs_nanos = (rhs.secs as f64) * (NANOS_PER_SEC as f64) + (rhs.nanos.0 as f64); + self_nanos / rhs_nanos + } + + /// Divides `Duration` by `Duration` and returns `f32`. + /// + /// # Examples + /// ``` + /// use std::time::Duration; + /// + /// let dur1 = Duration::new(2, 700_000_000); + /// let dur2 = Duration::new(5, 400_000_000); + /// assert_eq!(dur1.div_duration_f32(dur2), 0.5); + /// ``` + #[stable(feature = "div_duration", since = "1.80.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] + pub const fn div_duration_f32(self, rhs: Duration) -> f32 { + let self_nanos = (self.secs as f32) * (NANOS_PER_SEC as f32) + (self.nanos.0 as f32); + let rhs_nanos = (rhs.secs as f32) * (NANOS_PER_SEC as f32) + (rhs.nanos.0 as f32); + self_nanos / rhs_nanos + } +} + +#[stable(feature = "duration", since = "1.3.0")] +impl Add for Duration { + type Output = Duration; + + #[inline] + fn add(self, rhs: Duration) -> Duration { + self.checked_add(rhs).expect("overflow when adding durations") + } +} + +#[stable(feature = "time_augmented_assignment", since = "1.9.0")] +impl AddAssign for Duration { + #[inline] + fn add_assign(&mut self, rhs: Duration) { + *self = *self + rhs; + } +} + +#[stable(feature = "duration", since = "1.3.0")] +impl Sub for Duration { + type Output = Duration; + + #[inline] + fn sub(self, rhs: Duration) -> Duration { + self.checked_sub(rhs).expect("overflow when subtracting durations") + } +} + +#[stable(feature = "time_augmented_assignment", since = "1.9.0")] +impl SubAssign for Duration { + #[inline] + fn sub_assign(&mut self, rhs: Duration) { + *self = *self - rhs; + } +} + +#[stable(feature = "duration", since = "1.3.0")] +impl Mul for Duration { + type Output = Duration; + + #[inline] + fn mul(self, rhs: u32) -> Duration { + self.checked_mul(rhs).expect("overflow when multiplying duration by scalar") + } +} + +#[stable(feature = "symmetric_u32_duration_mul", since = "1.31.0")] +impl Mul for u32 { + type Output = Duration; + + #[inline] + fn mul(self, rhs: Duration) -> Duration { + rhs * self + } +} + +#[stable(feature = "time_augmented_assignment", since = "1.9.0")] +impl MulAssign for Duration { + #[inline] + fn mul_assign(&mut self, rhs: u32) { + *self = *self * rhs; + } +} + +#[stable(feature = "duration", since = "1.3.0")] +impl Div for Duration { + type Output = Duration; + + #[inline] + fn div(self, rhs: u32) -> Duration { + self.checked_div(rhs).expect("divide by zero error when dividing duration by scalar") + } +} + +#[stable(feature = "time_augmented_assignment", since = "1.9.0")] +impl DivAssign for Duration { + #[inline] + fn div_assign(&mut self, rhs: u32) { + *self = *self / rhs; + } +} + +macro_rules! sum_durations { + ($iter:expr) => {{ + let mut total_secs: u64 = 0; + let mut total_nanos: u64 = 0; + + for entry in $iter { + total_secs = + total_secs.checked_add(entry.secs).expect("overflow in iter::sum over durations"); + total_nanos = match total_nanos.checked_add(entry.nanos.0 as u64) { + Some(n) => n, + None => { + total_secs = total_secs + .checked_add(total_nanos / NANOS_PER_SEC as u64) + .expect("overflow in iter::sum over durations"); + (total_nanos % NANOS_PER_SEC as u64) + entry.nanos.0 as u64 + } + }; + } + total_secs = total_secs + .checked_add(total_nanos / NANOS_PER_SEC as u64) + .expect("overflow in iter::sum over durations"); + total_nanos = total_nanos % NANOS_PER_SEC as u64; + Duration::new(total_secs, total_nanos as u32) + }}; +} + +#[stable(feature = "duration_sum", since = "1.16.0")] +impl Sum for Duration { + fn sum>(iter: I) -> Duration { + sum_durations!(iter) + } +} + +#[stable(feature = "duration_sum", since = "1.16.0")] +impl<'a> Sum<&'a Duration> for Duration { + fn sum>(iter: I) -> Duration { + sum_durations!(iter) + } +} + +#[stable(feature = "duration_debug_impl", since = "1.27.0")] +impl fmt::Debug for Duration { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// Formats a floating point number in decimal notation. + /// + /// The number is given as the `integer_part` and a fractional part. + /// The value of the fractional part is `fractional_part / divisor`. So + /// `integer_part` = 3, `fractional_part` = 12 and `divisor` = 100 + /// represents the number `3.012`. Trailing zeros are omitted. + /// + /// `divisor` must not be above 100_000_000. It also should be a power + /// of 10, everything else doesn't make sense. `fractional_part` has + /// to be less than `10 * divisor`! + /// + /// A prefix and postfix may be added. The whole thing is padded + /// to the formatter's `width`, if specified. + fn fmt_decimal( + f: &mut fmt::Formatter<'_>, + integer_part: u64, + mut fractional_part: u32, + mut divisor: u32, + prefix: &str, + postfix: &str, + ) -> fmt::Result { + // Encode the fractional part into a temporary buffer. The buffer + // only need to hold 9 elements, because `fractional_part` has to + // be smaller than 10^9. The buffer is prefilled with '0' digits + // to simplify the code below. + let mut buf = [b'0'; 9]; + + // The next digit is written at this position + let mut pos = 0; + + // We keep writing digits into the buffer while there are non-zero + // digits left and we haven't written enough digits yet. + while fractional_part > 0 && pos < f.precision().unwrap_or(9) { + // Write new digit into the buffer + buf[pos] = b'0' + (fractional_part / divisor) as u8; + + fractional_part %= divisor; + divisor /= 10; + pos += 1; + } + + // If a precision < 9 was specified, there may be some non-zero + // digits left that weren't written into the buffer. In that case we + // need to perform rounding to match the semantics of printing + // normal floating point numbers. However, we only need to do work + // when rounding up. This happens if the first digit of the + // remaining ones is >= 5. + let integer_part = if fractional_part > 0 && fractional_part >= divisor * 5 { + // Round up the number contained in the buffer. We go through + // the buffer backwards and keep track of the carry. + let mut rev_pos = pos; + let mut carry = true; + while carry && rev_pos > 0 { + rev_pos -= 1; + + // If the digit in the buffer is not '9', we just need to + // increment it and can stop then (since we don't have a + // carry anymore). Otherwise, we set it to '0' (overflow) + // and continue. + if buf[rev_pos] < b'9' { + buf[rev_pos] += 1; + carry = false; + } else { + buf[rev_pos] = b'0'; + } + } + + // If we still have the carry bit set, that means that we set + // the whole buffer to '0's and need to increment the integer + // part. + if carry { + // If `integer_part == u64::MAX` and precision < 9, any + // carry of the overflow during rounding of the + // `fractional_part` into the `integer_part` will cause the + // `integer_part` itself to overflow. Avoid this by using an + // `Option`, with `None` representing `u64::MAX + 1`. + integer_part.checked_add(1) + } else { + Some(integer_part) + } + } else { + Some(integer_part) + }; + + // Determine the end of the buffer: if precision is set, we just + // use as many digits from the buffer (capped to 9). If it isn't + // set, we only use all digits up to the last non-zero one. + let end = f.precision().map(|p| crate::cmp::min(p, 9)).unwrap_or(pos); + + // This closure emits the formatted duration without emitting any + // padding (padding is calculated below). + let emit_without_padding = |f: &mut fmt::Formatter<'_>| { + if let Some(integer_part) = integer_part { + write!(f, "{}{}", prefix, integer_part)?; + } else { + // u64::MAX + 1 == 18446744073709551616 + write!(f, "{}18446744073709551616", prefix)?; + } + + // Write the decimal point and the fractional part (if any). + if end > 0 { + // 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]) }; + + // If the user request a precision > 9, we pad '0's at the end. + let w = f.precision().unwrap_or(pos); + write!(f, ".{:0 { + // No `width` specified. There's no need to calculate the + // length of the output in this case, just emit it. + emit_without_padding(f) + } + Some(requested_w) => { + // A `width` was specified. Calculate the actual width of + // the output in order to calculate the required padding. + // It consists of 4 parts: + // 1. The prefix: is either "+" or "", so we can just use len(). + // 2. The postfix: can be "µs" so we have to count UTF8 characters. + let mut actual_w = prefix.len() + postfix.chars().count(); + // 3. The integer part: + if let Some(integer_part) = integer_part { + if let Some(log) = integer_part.checked_ilog10() { + // integer_part is > 0, so has length log10(x)+1 + actual_w += 1 + log as usize; + } else { + // integer_part is 0, so has length 1. + actual_w += 1; + } + } else { + // integer_part is u64::MAX + 1, so has length 20 + actual_w += 20; + } + // 4. The fractional part (if any): + if end > 0 { + let frac_part_w = f.precision().unwrap_or(pos); + actual_w += 1 + frac_part_w; + } + + if requested_w <= actual_w { + // Output is already longer than `width`, so don't pad. + emit_without_padding(f) + } else { + // We need to add padding. Use the `Formatter::padding` helper function. + let default_align = fmt::Alignment::Left; + let post_padding = f.padding(requested_w - actual_w, default_align)?; + emit_without_padding(f)?; + post_padding.write(f) + } + } + } + } + + // Print leading '+' sign if requested + let prefix = if f.sign_plus() { "+" } else { "" }; + + if self.secs > 0 { + fmt_decimal(f, self.secs, self.nanos.0, NANOS_PER_SEC / 10, prefix, "s") + } else if self.nanos.0 >= NANOS_PER_MILLI { + fmt_decimal( + f, + (self.nanos.0 / NANOS_PER_MILLI) as u64, + self.nanos.0 % NANOS_PER_MILLI, + NANOS_PER_MILLI / 10, + prefix, + "ms", + ) + } else if self.nanos.0 >= NANOS_PER_MICRO { + fmt_decimal( + f, + (self.nanos.0 / NANOS_PER_MICRO) as u64, + self.nanos.0 % NANOS_PER_MICRO, + NANOS_PER_MICRO / 10, + prefix, + "µs", + ) + } else { + fmt_decimal(f, self.nanos.0 as u64, 0, 1, prefix, "ns") + } + } +} + +/// An error which can be returned when converting a floating-point value of seconds +/// into a [`Duration`]. +/// +/// This error is used as the error type for [`Duration::try_from_secs_f32`] and +/// [`Duration::try_from_secs_f64`]. +/// +/// # Example +/// +/// ``` +/// use std::time::Duration; +/// +/// if let Err(e) = Duration::try_from_secs_f32(-1.0) { +/// println!("Failed conversion to Duration: {e}"); +/// } +/// ``` +#[derive(Debug, Clone, PartialEq, Eq)] +#[stable(feature = "duration_checked_float", since = "1.66.0")] +pub struct TryFromFloatSecsError { + kind: TryFromFloatSecsErrorKind, +} + +impl TryFromFloatSecsError { + const fn description(&self) -> &'static str { + match self.kind { + TryFromFloatSecsErrorKind::Negative => { + "cannot convert float seconds to Duration: value is negative" + } + TryFromFloatSecsErrorKind::OverflowOrNan => { + "cannot convert float seconds to Duration: value is either too big or NaN" + } + } + } +} + +#[stable(feature = "duration_checked_float", since = "1.66.0")] +impl fmt::Display for TryFromFloatSecsError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.description().fmt(f) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum TryFromFloatSecsErrorKind { + // Value is negative. + Negative, + // Value is either too big to be represented as `Duration` or `NaN`. + OverflowOrNan, +} + +macro_rules! try_from_secs { + ( + secs = $secs: expr, + mantissa_bits = $mant_bits: literal, + exponent_bits = $exp_bits: literal, + offset = $offset: literal, + bits_ty = $bits_ty:ty, + double_ty = $double_ty:ty, + ) => {{ + const MIN_EXP: i16 = 1 - (1i16 << $exp_bits) / 2; + const MANT_MASK: $bits_ty = (1 << $mant_bits) - 1; + const EXP_MASK: $bits_ty = (1 << $exp_bits) - 1; + + if $secs < 0.0 { + return Err(TryFromFloatSecsError { kind: TryFromFloatSecsErrorKind::Negative }); + } + + let bits = $secs.to_bits(); + let mant = (bits & MANT_MASK) | (MANT_MASK + 1); + let exp = ((bits >> $mant_bits) & EXP_MASK) as i16 + MIN_EXP; + + let (secs, nanos) = if exp < -31 { + // the input represents less than 1ns and can not be rounded to it + (0u64, 0u32) + } else if exp < 0 { + // the input is less than 1 second + let t = <$double_ty>::from(mant) << ($offset + exp); + let nanos_offset = $mant_bits + $offset; + let nanos_tmp = u128::from(NANOS_PER_SEC) * u128::from(t); + let nanos = (nanos_tmp >> nanos_offset) as u32; + + let rem_mask = (1 << nanos_offset) - 1; + let rem_msb_mask = 1 << (nanos_offset - 1); + let rem = nanos_tmp & rem_mask; + let is_tie = rem == rem_msb_mask; + let is_even = (nanos & 1) == 0; + let rem_msb = nanos_tmp & rem_msb_mask == 0; + let add_ns = !(rem_msb || (is_even && is_tie)); + + // f32 does not have enough precision to trigger the second branch + // since it can not represent numbers between 0.999_999_940_395 and 1.0. + let nanos = nanos + add_ns as u32; + if ($mant_bits == 23) || (nanos != NANOS_PER_SEC) { (0, nanos) } else { (1, 0) } + } else if exp < $mant_bits { + let secs = u64::from(mant >> ($mant_bits - exp)); + let t = <$double_ty>::from((mant << exp) & MANT_MASK); + let nanos_offset = $mant_bits; + let nanos_tmp = <$double_ty>::from(NANOS_PER_SEC) * t; + let nanos = (nanos_tmp >> nanos_offset) as u32; + + let rem_mask = (1 << nanos_offset) - 1; + let rem_msb_mask = 1 << (nanos_offset - 1); + let rem = nanos_tmp & rem_mask; + let is_tie = rem == rem_msb_mask; + let is_even = (nanos & 1) == 0; + let rem_msb = nanos_tmp & rem_msb_mask == 0; + let add_ns = !(rem_msb || (is_even && is_tie)); + + // f32 does not have enough precision to trigger the second branch. + // For example, it can not represent numbers between 1.999_999_880... + // and 2.0. Bigger values result in even smaller precision of the + // fractional part. + let nanos = nanos + add_ns as u32; + if ($mant_bits == 23) || (nanos != NANOS_PER_SEC) { + (secs, nanos) + } else { + (secs + 1, 0) + } + } else if exp < 64 { + // the input has no fractional part + let secs = u64::from(mant) << (exp - $mant_bits); + (secs, 0) + } else { + return Err(TryFromFloatSecsError { kind: TryFromFloatSecsErrorKind::OverflowOrNan }); + }; + + Ok(Duration::new(secs, nanos)) + }}; +} + +impl Duration { + /// The checked version of [`from_secs_f32`]. + /// + /// [`from_secs_f32`]: Duration::from_secs_f32 + /// + /// This constructor will return an `Err` if `secs` is negative, overflows `Duration` or not finite. + /// + /// # Examples + /// ``` + /// use std::time::Duration; + /// + /// let res = Duration::try_from_secs_f32(0.0); + /// assert_eq!(res, Ok(Duration::new(0, 0))); + /// let res = Duration::try_from_secs_f32(1e-20); + /// assert_eq!(res, Ok(Duration::new(0, 0))); + /// let res = Duration::try_from_secs_f32(4.2e-7); + /// assert_eq!(res, Ok(Duration::new(0, 420))); + /// let res = Duration::try_from_secs_f32(2.7); + /// assert_eq!(res, Ok(Duration::new(2, 700_000_048))); + /// let res = Duration::try_from_secs_f32(3e10); + /// assert_eq!(res, Ok(Duration::new(30_000_001_024, 0))); + /// // subnormal float: + /// let res = Duration::try_from_secs_f32(f32::from_bits(1)); + /// assert_eq!(res, Ok(Duration::new(0, 0))); + /// + /// let res = Duration::try_from_secs_f32(-5.0); + /// assert!(res.is_err()); + /// let res = Duration::try_from_secs_f32(f32::NAN); + /// assert!(res.is_err()); + /// let res = Duration::try_from_secs_f32(2e19); + /// assert!(res.is_err()); + /// + /// // the conversion uses rounding with tie resolution to even + /// let res = Duration::try_from_secs_f32(0.999e-9); + /// assert_eq!(res, Ok(Duration::new(0, 1))); + /// + /// // this float represents exactly 976562.5e-9 + /// let val = f32::from_bits(0x3A80_0000); + /// let res = Duration::try_from_secs_f32(val); + /// assert_eq!(res, Ok(Duration::new(0, 976_562))); + /// + /// // this float represents exactly 2929687.5e-9 + /// let val = f32::from_bits(0x3B40_0000); + /// let res = Duration::try_from_secs_f32(val); + /// assert_eq!(res, Ok(Duration::new(0, 2_929_688))); + /// + /// // this float represents exactly 1.000_976_562_5 + /// let val = f32::from_bits(0x3F802000); + /// let res = Duration::try_from_secs_f32(val); + /// assert_eq!(res, Ok(Duration::new(1, 976_562))); + /// + /// // this float represents exactly 1.002_929_687_5 + /// let val = f32::from_bits(0x3F806000); + /// let res = Duration::try_from_secs_f32(val); + /// assert_eq!(res, Ok(Duration::new(1, 2_929_688))); + /// ``` + #[stable(feature = "duration_checked_float", since = "1.66.0")] + #[inline] + pub fn try_from_secs_f32(secs: f32) -> Result { + try_from_secs!( + secs = secs, + mantissa_bits = 23, + exponent_bits = 8, + offset = 41, + bits_ty = u32, + double_ty = u64, + ) + } + + /// The checked version of [`from_secs_f64`]. + /// + /// [`from_secs_f64`]: Duration::from_secs_f64 + /// + /// This constructor will return an `Err` if `secs` is negative, overflows `Duration` or not finite. + /// + /// # Examples + /// ``` + /// use std::time::Duration; + /// + /// let res = Duration::try_from_secs_f64(0.0); + /// assert_eq!(res, Ok(Duration::new(0, 0))); + /// let res = Duration::try_from_secs_f64(1e-20); + /// assert_eq!(res, Ok(Duration::new(0, 0))); + /// let res = Duration::try_from_secs_f64(4.2e-7); + /// assert_eq!(res, Ok(Duration::new(0, 420))); + /// let res = Duration::try_from_secs_f64(2.7); + /// assert_eq!(res, Ok(Duration::new(2, 700_000_000))); + /// let res = Duration::try_from_secs_f64(3e10); + /// assert_eq!(res, Ok(Duration::new(30_000_000_000, 0))); + /// // subnormal float + /// let res = Duration::try_from_secs_f64(f64::from_bits(1)); + /// assert_eq!(res, Ok(Duration::new(0, 0))); + /// + /// let res = Duration::try_from_secs_f64(-5.0); + /// assert!(res.is_err()); + /// let res = Duration::try_from_secs_f64(f64::NAN); + /// assert!(res.is_err()); + /// let res = Duration::try_from_secs_f64(2e19); + /// assert!(res.is_err()); + /// + /// // the conversion uses rounding with tie resolution to even + /// let res = Duration::try_from_secs_f64(0.999e-9); + /// assert_eq!(res, Ok(Duration::new(0, 1))); + /// let res = Duration::try_from_secs_f64(0.999_999_999_499); + /// assert_eq!(res, Ok(Duration::new(0, 999_999_999))); + /// let res = Duration::try_from_secs_f64(0.999_999_999_501); + /// assert_eq!(res, Ok(Duration::new(1, 0))); + /// let res = Duration::try_from_secs_f64(42.999_999_999_499); + /// assert_eq!(res, Ok(Duration::new(42, 999_999_999))); + /// let res = Duration::try_from_secs_f64(42.999_999_999_501); + /// assert_eq!(res, Ok(Duration::new(43, 0))); + /// + /// // this float represents exactly 976562.5e-9 + /// let val = f64::from_bits(0x3F50_0000_0000_0000); + /// let res = Duration::try_from_secs_f64(val); + /// assert_eq!(res, Ok(Duration::new(0, 976_562))); + /// + /// // this float represents exactly 2929687.5e-9 + /// let val = f64::from_bits(0x3F68_0000_0000_0000); + /// let res = Duration::try_from_secs_f64(val); + /// assert_eq!(res, Ok(Duration::new(0, 2_929_688))); + /// + /// // this float represents exactly 1.000_976_562_5 + /// let val = f64::from_bits(0x3FF0_0400_0000_0000); + /// let res = Duration::try_from_secs_f64(val); + /// assert_eq!(res, Ok(Duration::new(1, 976_562))); + /// + /// // this float represents exactly 1.002_929_687_5 + /// let val = f64::from_bits(0x3_FF00_C000_0000_000); + /// let res = Duration::try_from_secs_f64(val); + /// assert_eq!(res, Ok(Duration::new(1, 2_929_688))); + /// ``` + #[stable(feature = "duration_checked_float", since = "1.66.0")] + #[inline] + pub fn try_from_secs_f64(secs: f64) -> Result { + try_from_secs!( + secs = secs, + mantissa_bits = 52, + exponent_bits = 11, + offset = 44, + bits_ty = u64, + double_ty = u128, + ) + } +} diff --git a/CoqOfRust/core/tuple.rs b/CoqOfRust/core/tuple.rs new file mode 100644 index 000000000..206b5b9e2 --- /dev/null +++ b/CoqOfRust/core/tuple.rs @@ -0,0 +1,213 @@ +// See core/src/primitive_docs.rs for documentation. + +use crate::cmp::Ordering::{self, *}; +use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy}; + +// Recursive macro for implementing n-ary tuple functions and operations +// +// Also provides implementations for tuples with lesser arity. For example, tuple_impls!(A B C) +// will implement everything for (A, B, C), (A, B) and (A,). +macro_rules! tuple_impls { + // Stopping criteria (1-ary tuple) + ($T:ident) => { + tuple_impls!(@impl $T); + }; + // Running criteria (n-ary tuple, with n >= 2) + ($T:ident $( $U:ident )+) => { + tuple_impls!($( $U )+); + tuple_impls!(@impl $T $( $U )+); + }; + // "Private" internal implementation + (@impl $( $T:ident )+) => { + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($T: PartialEq),+> PartialEq for ($($T,)+) + where + last_type!($($T,)+): ?Sized + { + #[inline] + fn eq(&self, other: &($($T,)+)) -> bool { + $( ${ignore($T)} self.${index()} == other.${index()} )&&+ + } + #[inline] + fn ne(&self, other: &($($T,)+)) -> bool { + $( ${ignore($T)} self.${index()} != other.${index()} )||+ + } + } + } + + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($T: Eq),+> Eq for ($($T,)+) + where + last_type!($($T,)+): ?Sized + {} + } + + maybe_tuple_doc! { + $($T)+ @ + #[unstable(feature = "adt_const_params", issue = "95174")] + impl<$($T: ConstParamTy_),+> ConstParamTy_ for ($($T,)+) + {} + } + + maybe_tuple_doc! { + $($T)+ @ + #[unstable(feature = "unsized_const_params", issue = "95174")] + impl<$($T: UnsizedConstParamTy),+> UnsizedConstParamTy for ($($T,)+) + {} + } + + maybe_tuple_doc! { + $($T)+ @ + #[unstable(feature = "structural_match", issue = "31434")] + impl<$($T),+> StructuralPartialEq for ($($T,)+) + {} + } + + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($T: PartialOrd),+> PartialOrd for ($($T,)+) + where + last_type!($($T,)+): ?Sized + { + #[inline] + fn partial_cmp(&self, other: &($($T,)+)) -> Option { + lexical_partial_cmp!($( ${ignore($T)} self.${index()}, other.${index()} ),+) + } + #[inline] + fn lt(&self, other: &($($T,)+)) -> bool { + lexical_ord!(lt, Less, $( ${ignore($T)} self.${index()}, other.${index()} ),+) + } + #[inline] + fn le(&self, other: &($($T,)+)) -> bool { + lexical_ord!(le, Less, $( ${ignore($T)} self.${index()}, other.${index()} ),+) + } + #[inline] + fn ge(&self, other: &($($T,)+)) -> bool { + lexical_ord!(ge, Greater, $( ${ignore($T)} self.${index()}, other.${index()} ),+) + } + #[inline] + fn gt(&self, other: &($($T,)+)) -> bool { + lexical_ord!(gt, Greater, $( ${ignore($T)} self.${index()}, other.${index()} ),+) + } + } + } + + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($T: Ord),+> Ord for ($($T,)+) + where + last_type!($($T,)+): ?Sized + { + #[inline] + fn cmp(&self, other: &($($T,)+)) -> Ordering { + lexical_cmp!($( ${ignore($T)} self.${index()}, other.${index()} ),+) + } + } + } + + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "rust1", since = "1.0.0")] + impl<$($T: Default),+> Default for ($($T,)+) { + #[inline] + fn default() -> ($($T,)+) { + ($({ let x: $T = Default::default(); x},)+) + } + } + } + + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "array_tuple_conv", since = "1.71.0")] + impl From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) { + #[inline] + #[allow(non_snake_case)] + fn from(array: [T; ${count($T)}]) -> Self { + let [$($T,)+] = array; + ($($T,)+) + } + } + } + + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "array_tuple_conv", since = "1.71.0")] + impl From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] { + #[inline] + #[allow(non_snake_case)] + fn from(tuple: ($(${ignore($T)} T,)+)) -> Self { + let ($($T,)+) = tuple; + [$($T,)+] + } + } + } + } +} + +// If this is a unary tuple, it adds a doc comment. +// Otherwise, it hides the docs entirely. +macro_rules! maybe_tuple_doc { + ($a:ident @ #[$meta:meta] $item:item) => { + #[doc(fake_variadic)] + #[doc = "This trait is implemented for tuples up to twelve items long."] + #[$meta] + $item + }; + ($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => { + #[doc(hidden)] + #[$meta] + $item + }; +} + +// Constructs an expression that performs a lexical ordering using method `$rel`. +// The values are interleaved, so the macro invocation for +// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, opt_is_lt, a1, b1, +// a2, b2, a3, b3)` (and similarly for `lexical_cmp`) +// +// `$ne_rel` is only used to determine the result after checking that they're +// not equal, so `lt` and `le` can both just use `Less`. +macro_rules! lexical_ord { + ($rel: ident, $ne_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{ + let c = PartialOrd::partial_cmp(&$a, &$b); + if c != Some(Equal) { c == Some($ne_rel) } + else { lexical_ord!($rel, $ne_rel, $($rest_a, $rest_b),+) } + }}; + ($rel: ident, $ne_rel: ident, $a:expr, $b:expr) => { + // Use the specific method for the last element + PartialOrd::$rel(&$a, &$b) + }; +} + +macro_rules! lexical_partial_cmp { + ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { + match ($a).partial_cmp(&$b) { + Some(Equal) => lexical_partial_cmp!($($rest_a, $rest_b),+), + ordering => ordering + } + }; + ($a:expr, $b:expr) => { ($a).partial_cmp(&$b) }; +} + +macro_rules! lexical_cmp { + ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { + match ($a).cmp(&$b) { + Equal => lexical_cmp!($($rest_a, $rest_b),+), + ordering => ordering + } + }; + ($a:expr, $b:expr) => { ($a).cmp(&$b) }; +} + +macro_rules! last_type { + ($a:ident,) => { $a }; + ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; +} + +tuple_impls!(E D C B A Z Y X W V U T); diff --git a/CoqOfRust/core/ub_checks.rs b/CoqOfRust/core/ub_checks.rs new file mode 100644 index 000000000..b289f6026 --- /dev/null +++ b/CoqOfRust/core/ub_checks.rs @@ -0,0 +1,170 @@ +//! Provides the [`assert_unsafe_precondition`] macro as well as some utility functions that cover +//! common preconditions. + +use crate::intrinsics::{self, const_eval_select}; + +/// Checks that the preconditions of an unsafe function are followed. +/// +/// The check is enabled at runtime if debug assertions are enabled when the +/// caller is monomorphized. In const-eval/Miri checks implemented with this +/// macro for language UB are always ignored. +/// +/// This macro should be called as +/// `assert_unsafe_precondition!(check_{library,language}_ub, "message", (ident: type = expr, ident: type = expr) => check_expr)` +/// where each `expr` will be evaluated and passed in as function argument `ident: type`. Then all +/// those arguments are passed to a function with the body `check_expr`. +/// Pick `check_language_ub` when this is guarding a violation of language UB, i.e., immediate UB +/// according to the Rust Abstract Machine. Pick `check_library_ub` when this is guarding a violation +/// of a documented library precondition that does not *immediately* lead to language UB. +/// +/// If `check_library_ub` is used but the check is actually guarding language UB, the check will +/// slow down const-eval/Miri and we'll get the panic message instead of the interpreter's nice +/// diagnostic, but our ability to detect UB is unchanged. +/// But if `check_language_ub` is used when the check is actually for library UB, the check is +/// omitted in const-eval/Miri and thus if we eventually execute language UB which relies on the +/// library UB, the backtrace Miri reports may be far removed from original cause. +/// +/// These checks are behind a condition which is evaluated at codegen time, not expansion time like +/// [`debug_assert`]. This means that a standard library built with optimizations and debug +/// assertions disabled will have these checks optimized out of its monomorphizations, but if a +/// caller of the standard library has debug assertions enabled and monomorphizes an expansion of +/// this macro, that monomorphization will contain the check. +/// +/// Since these checks cannot be optimized out in MIR, some care must be taken in both call and +/// implementation to mitigate their compile-time overhead. Calls to this macro always expand to +/// this structure: +/// ```ignore (pseudocode) +/// if ::core::intrinsics::check_language_ub() { +/// precondition_check(args) +/// } +/// ``` +/// where `precondition_check` is monomorphic with the attributes `#[rustc_nounwind]`, `#[inline]` and +/// `#[rustc_no_mir_inline]`. This combination of attributes ensures that the actual check logic is +/// compiled only once and generates a minimal amount of IR because the check cannot be inlined in +/// MIR, but *can* be inlined and fully optimized by a codegen backend. +/// +/// Callers should avoid introducing any other `let` bindings or any code outside this macro in +/// order to call it. Since the precompiled standard library is built with full debuginfo and these +/// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough +/// debuginfo to have a measurable compile-time impact on debug builds. +#[macro_export] +#[unstable(feature = "ub_checks", issue = "none")] +macro_rules! assert_unsafe_precondition { + ($kind:ident, $message:expr, ($($name:ident:$ty:ty = $arg:expr),*$(,)?) => $e:expr $(,)?) => { + { + // This check is inlineable, but not by the MIR inliner. + // The reason for this is that the MIR inliner is in an exceptionally bad position + // to think about whether or not to inline this. In MIR, this call is gated behind `debug_assertions`, + // which will codegen to `false` in release builds. Inlining the check would be wasted work in that case and + // would be bad for compile times. + // + // LLVM on the other hand sees the constant branch, so if it's `false`, it can immediately delete it without + // inlining the check. If it's `true`, it can inline it and get significantly better performance. + #[rustc_no_mir_inline] + #[inline] + #[rustc_nounwind] + const fn precondition_check($($name:$ty),*) { + if !$e { + ::core::panicking::panic_nounwind( + concat!("unsafe precondition(s) violated: ", $message) + ); + } + } + + if ::core::ub_checks::$kind() { + precondition_check($($arg,)*); + } + } + }; +} +#[unstable(feature = "ub_checks", issue = "none")] +pub use assert_unsafe_precondition; +/// Checking library UB is always enabled when UB-checking is done +/// (and we use a reexport so that there is no unnecessary wrapper function). +#[unstable(feature = "ub_checks", issue = "none")] +pub use intrinsics::ub_checks as check_library_ub; + +/// Determines whether we should check for language UB. +/// +/// The intention is to not do that when running in the interpreter, as that one has its own +/// language UB checks which generally produce better errors. +#[inline] +#[rustc_allow_const_fn_unstable(const_eval_select)] +pub(crate) const fn check_language_ub() -> bool { + // Only used for UB checks so we may const_eval_select. + intrinsics::ub_checks() + && const_eval_select!( + @capture { } -> bool: + if const { + // Always disable UB checks. + false + } else { + // Disable UB checks in Miri. + !cfg!(miri) + } + ) +} + +/// Checks whether `ptr` is properly aligned with respect to the given alignment, and +/// if `is_zst == false`, that `ptr` is not null. +/// +/// In `const` this is approximate and can fail spuriously. It is primarily intended +/// for `assert_unsafe_precondition!` with `check_language_ub`, in which case the +/// check is anyway not executed in `const`. +#[inline] +#[rustc_allow_const_fn_unstable(const_eval_select)] +pub(crate) const fn maybe_is_aligned_and_not_null( + ptr: *const (), + align: usize, + is_zst: bool, +) -> bool { + // This is just for safety checks so we can const_eval_select. + const_eval_select!( + @capture { ptr: *const (), align: usize, is_zst: bool } -> bool: + if const { + is_zst || !ptr.is_null() + } else { + ptr.is_aligned_to(align) && (is_zst || !ptr.is_null()) + } + ) +} + +#[inline] +pub(crate) const fn is_valid_allocation_size(size: usize, len: usize) -> bool { + let max_len = if size == 0 { usize::MAX } else { isize::MAX as usize / size }; + len <= max_len +} + +/// Checks whether the regions of memory starting at `src` and `dst` of size +/// `count * size` do *not* overlap. +/// +/// Note that in const-eval this function just returns `true` and therefore must +/// only be used with `assert_unsafe_precondition!`, similar to `is_aligned_and_not_null`. +#[inline] +#[rustc_allow_const_fn_unstable(const_eval_select)] +pub(crate) const fn maybe_is_nonoverlapping( + src: *const (), + dst: *const (), + size: usize, + count: usize, +) -> bool { + // This is just for safety checks so we can const_eval_select. + const_eval_select!( + @capture { src: *const (), dst: *const (), size: usize, count: usize } -> bool: + if const { + true + } else { + let src_usize = src.addr(); + let dst_usize = dst.addr(); + let Some(size) = size.checked_mul(count) else { + crate::panicking::panic_nounwind( + "is_nonoverlapping: `size_of::() * count` overflows a usize", + ) + }; + let diff = src_usize.abs_diff(dst_usize); + // If the absolute distance between the ptrs is at least as big as the size of the buffer, + // they do not overlap. + diff >= size + } + ) +} diff --git a/CoqOfRust/core/unicode/mod.rs b/CoqOfRust/core/unicode/mod.rs new file mode 100644 index 000000000..6066aa992 --- /dev/null +++ b/CoqOfRust/core/unicode/mod.rs @@ -0,0 +1,33 @@ +#![unstable(feature = "unicode_internals", issue = "none")] +#![allow(missing_docs)] + +// for use in alloc, not re-exported in std. +#[rustfmt::skip] +pub use unicode_data::case_ignorable::lookup as Case_Ignorable; +pub use unicode_data::cased::lookup as Cased; +pub use unicode_data::conversions; + +#[rustfmt::skip] +pub(crate) use unicode_data::alphabetic::lookup as Alphabetic; +pub(crate) use unicode_data::cc::lookup as Cc; +pub(crate) use unicode_data::grapheme_extend::lookup as Grapheme_Extend; +pub(crate) use unicode_data::lowercase::lookup as Lowercase; +pub(crate) use unicode_data::n::lookup as N; +pub(crate) use unicode_data::uppercase::lookup as Uppercase; +pub(crate) use unicode_data::white_space::lookup as White_Space; + +pub(crate) mod printable; +mod unicode_data; + +/// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of +/// `char` and `str` methods are based on. +/// +/// New versions of Unicode are released regularly and subsequently all methods +/// in the standard library depending on Unicode are updated. Therefore the +/// behavior of some `char` and `str` methods and the value of this constant +/// changes over time. This is *not* considered to be a breaking change. +/// +/// The version numbering scheme is explained in +/// [Unicode 11.0 or later, Section 3.1 Versions of the Unicode Standard](https://www.unicode.org/versions/Unicode11.0.0/ch03.pdf#page=4). +#[stable(feature = "unicode_version", since = "1.45.0")] +pub const UNICODE_VERSION: (u8, u8, u8) = unicode_data::UNICODE_VERSION; diff --git a/CoqOfRust/core/unicode/printable.rs b/CoqOfRust/core/unicode/printable.rs new file mode 100644 index 000000000..d8fb50e4e --- /dev/null +++ b/CoqOfRust/core/unicode/printable.rs @@ -0,0 +1,604 @@ +// NOTE: The following code was generated by "library/core/src/unicode/printable.py", +// do not edit directly! + +fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], normal: &[u8]) -> bool { + let xupper = (x >> 8) as u8; + let mut lowerstart = 0; + for &(upper, lowercount) in singletonuppers { + let lowerend = lowerstart + lowercount as usize; + if xupper == upper { + for &lower in &singletonlowers[lowerstart..lowerend] { + if lower == x as u8 { + return false; + } + } + } else if xupper < upper { + break; + } + lowerstart = lowerend; + } + + let mut x = x as i32; + let mut normal = normal.iter().cloned(); + let mut current = true; + while let Some(v) = normal.next() { + let len = if v & 0x80 != 0 { + ((v & 0x7f) as i32) << 8 | normal.next().unwrap() as i32 + } else { + v as i32 + }; + x -= len; + if x < 0 { + break; + } + current = !current; + } + current +} + +pub(crate) fn is_printable(x: char) -> bool { + let x = x as u32; + let lower = x as u16; + + if x < 32 { + // ASCII fast path + false + } else if x < 127 { + // ASCII fast path + true + } else if x < 0x10000 { + check(lower, SINGLETONS0U, SINGLETONS0L, NORMAL0) + } else if x < 0x20000 { + check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1) + } else { + if 0x2a6e0 <= x && x < 0x2a700 { + return false; + } + if 0x2b73a <= x && x < 0x2b740 { + return false; + } + if 0x2b81e <= x && x < 0x2b820 { + return false; + } + if 0x2cea2 <= x && x < 0x2ceb0 { + return false; + } + if 0x2ebe1 <= x && x < 0x2ebf0 { + return false; + } + if 0x2ee5e <= x && x < 0x2f800 { + return false; + } + if 0x2fa1e <= x && x < 0x30000 { + return false; + } + if 0x3134b <= x && x < 0x31350 { + return false; + } + if 0x323b0 <= x && x < 0xe0100 { + return false; + } + if 0xe01f0 <= x && x < 0x110000 { + return false; + } + true + } +} + +#[rustfmt::skip] +const SINGLETONS0U: &[(u8, u8)] = &[ + (0x00, 1), + (0x03, 5), + (0x05, 6), + (0x06, 2), + (0x07, 6), + (0x08, 7), + (0x09, 17), + (0x0a, 28), + (0x0b, 25), + (0x0c, 26), + (0x0d, 16), + (0x0e, 12), + (0x0f, 4), + (0x10, 3), + (0x12, 18), + (0x13, 9), + (0x16, 1), + (0x17, 4), + (0x18, 1), + (0x19, 3), + (0x1a, 7), + (0x1b, 1), + (0x1c, 2), + (0x1f, 22), + (0x20, 3), + (0x2b, 3), + (0x2d, 11), + (0x2e, 1), + (0x30, 4), + (0x31, 2), + (0x32, 1), + (0xa7, 4), + (0xa9, 2), + (0xaa, 4), + (0xab, 8), + (0xfa, 2), + (0xfb, 5), + (0xfd, 2), + (0xfe, 3), + (0xff, 9), +]; +#[rustfmt::skip] +const SINGLETONS0L: &[u8] = &[ + 0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, + 0x58, 0x8b, 0x8c, 0x90, 0x1c, 0xdd, 0x0e, 0x0f, + 0x4b, 0x4c, 0xfb, 0xfc, 0x2e, 0x2f, 0x3f, 0x5c, + 0x5d, 0x5f, 0xe2, 0x84, 0x8d, 0x8e, 0x91, 0x92, + 0xa9, 0xb1, 0xba, 0xbb, 0xc5, 0xc6, 0xc9, 0xca, + 0xde, 0xe4, 0xe5, 0xff, 0x00, 0x04, 0x11, 0x12, + 0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, + 0x4a, 0x5d, 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, + 0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf, 0xe4, 0xe5, + 0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, + 0x34, 0x3a, 0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, + 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d, 0xc9, 0xce, + 0xcf, 0x0d, 0x11, 0x29, 0x3a, 0x3b, 0x45, 0x49, + 0x57, 0x5b, 0x5c, 0x5e, 0x5f, 0x64, 0x65, 0x8d, + 0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5, 0xc9, 0xdf, + 0xe4, 0xe5, 0xf0, 0x0d, 0x11, 0x45, 0x49, 0x64, + 0x65, 0x80, 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, + 0xd7, 0xf0, 0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, + 0xbe, 0xbf, 0xc5, 0xc7, 0xcf, 0xda, 0xdb, 0x48, + 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49, 0x4e, + 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, + 0xb1, 0xb6, 0xb7, 0xbf, 0xc1, 0xc6, 0xc7, 0xd7, + 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, 0xfe, + 0xff, 0x80, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x1f, + 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, + 0xaf, 0x4d, 0xbb, 0xbc, 0x16, 0x17, 0x1e, 0x1f, + 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, + 0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, + 0xf1, 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75, 0x96, + 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf, 0xc7, + 0xcf, 0xd7, 0xdf, 0x9a, 0x00, 0x40, 0x97, 0x98, + 0x30, 0x8f, 0x1f, 0xce, 0xcf, 0xd2, 0xd4, 0xce, + 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, + 0x10, 0x27, 0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, + 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91, 0x53, 0x67, + 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, + 0xfe, 0xff, +]; +#[rustfmt::skip] +const SINGLETONS1U: &[(u8, u8)] = &[ + (0x00, 6), + (0x01, 1), + (0x03, 1), + (0x04, 2), + (0x05, 7), + (0x07, 2), + (0x08, 8), + (0x09, 2), + (0x0a, 5), + (0x0b, 2), + (0x0e, 4), + (0x10, 1), + (0x11, 2), + (0x12, 5), + (0x13, 28), + (0x14, 1), + (0x15, 2), + (0x17, 2), + (0x19, 13), + (0x1c, 5), + (0x1d, 8), + (0x1f, 1), + (0x24, 1), + (0x6a, 4), + (0x6b, 2), + (0xaf, 3), + (0xb1, 2), + (0xbc, 2), + (0xcf, 2), + (0xd1, 2), + (0xd4, 12), + (0xd5, 9), + (0xd6, 2), + (0xd7, 2), + (0xda, 1), + (0xe0, 5), + (0xe1, 2), + (0xe7, 4), + (0xe8, 2), + (0xee, 32), + (0xf0, 4), + (0xf8, 2), + (0xfa, 4), + (0xfb, 1), +]; +#[rustfmt::skip] +const SINGLETONS1L: &[u8] = &[ + 0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, + 0x9e, 0x9f, 0x7b, 0x8b, 0x93, 0x96, 0xa2, 0xb2, + 0xba, 0x86, 0xb1, 0x06, 0x07, 0x09, 0x36, 0x3d, + 0x3e, 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, + 0x36, 0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, + 0xbd, 0x35, 0xe0, 0x12, 0x87, 0x89, 0x8e, 0x9e, + 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, + 0x3a, 0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, + 0x65, 0x8a, 0x8c, 0x8d, 0x8f, 0xb6, 0xc1, 0xc3, + 0xc4, 0xc6, 0xcb, 0xd6, 0x5c, 0xb6, 0xb7, 0x1b, + 0x1c, 0x07, 0x08, 0x0a, 0x0b, 0x14, 0x17, 0x36, + 0x39, 0x3a, 0xa8, 0xa9, 0xd8, 0xd9, 0x09, 0x37, + 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x66, + 0x69, 0x8f, 0x92, 0x11, 0x6f, 0x5f, 0xbf, 0xee, + 0xef, 0x5a, 0x62, 0xf4, 0xfc, 0xff, 0x53, 0x54, + 0x9a, 0x9b, 0x2e, 0x2f, 0x27, 0x28, 0x55, 0x9d, + 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad, 0xba, + 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d, 0x3a, + 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc, 0xcd, 0xa0, + 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f, 0xe7, + 0xec, 0xef, 0xff, 0xc5, 0xc6, 0x04, 0x20, 0x23, + 0x25, 0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, + 0x4c, 0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, + 0x5e, 0x60, 0x63, 0x65, 0x66, 0x6b, 0x73, 0x78, + 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, + 0xd0, 0xae, 0xaf, 0x6e, 0x6f, 0xdd, 0xde, 0x93, +]; +#[rustfmt::skip] +const NORMAL0: &[u8] = &[ + 0x00, 0x20, + 0x5f, 0x22, + 0x82, 0xdf, 0x04, + 0x82, 0x44, 0x08, + 0x1b, 0x04, + 0x06, 0x11, + 0x81, 0xac, 0x0e, + 0x80, 0xab, 0x05, + 0x1f, 0x08, + 0x81, 0x1c, 0x03, + 0x19, 0x08, + 0x01, 0x04, + 0x2f, 0x04, + 0x34, 0x04, + 0x07, 0x03, + 0x01, 0x07, + 0x06, 0x07, + 0x11, 0x0a, + 0x50, 0x0f, + 0x12, 0x07, + 0x55, 0x07, + 0x03, 0x04, + 0x1c, 0x0a, + 0x09, 0x03, + 0x08, 0x03, + 0x07, 0x03, + 0x02, 0x03, + 0x03, 0x03, + 0x0c, 0x04, + 0x05, 0x03, + 0x0b, 0x06, + 0x01, 0x0e, + 0x15, 0x05, + 0x4e, 0x07, + 0x1b, 0x07, + 0x57, 0x07, + 0x02, 0x06, + 0x17, 0x0c, + 0x50, 0x04, + 0x43, 0x03, + 0x2d, 0x03, + 0x01, 0x04, + 0x11, 0x06, + 0x0f, 0x0c, + 0x3a, 0x04, + 0x1d, 0x25, + 0x5f, 0x20, + 0x6d, 0x04, + 0x6a, 0x25, + 0x80, 0xc8, 0x05, + 0x82, 0xb0, 0x03, + 0x1a, 0x06, + 0x82, 0xfd, 0x03, + 0x59, 0x07, + 0x16, 0x09, + 0x18, 0x09, + 0x14, 0x0c, + 0x14, 0x0c, + 0x6a, 0x06, + 0x0a, 0x06, + 0x1a, 0x06, + 0x59, 0x07, + 0x2b, 0x05, + 0x46, 0x0a, + 0x2c, 0x04, + 0x0c, 0x04, + 0x01, 0x03, + 0x31, 0x0b, + 0x2c, 0x04, + 0x1a, 0x06, + 0x0b, 0x03, + 0x80, 0xac, 0x06, + 0x0a, 0x06, + 0x2f, 0x31, + 0x80, 0xf4, 0x08, + 0x3c, 0x03, + 0x0f, 0x03, + 0x3e, 0x05, + 0x38, 0x08, + 0x2b, 0x05, + 0x82, 0xff, 0x11, + 0x18, 0x08, + 0x2f, 0x11, + 0x2d, 0x03, + 0x21, 0x0f, + 0x21, 0x0f, + 0x80, 0x8c, 0x04, + 0x82, 0x9a, 0x16, + 0x0b, 0x15, + 0x88, 0x94, 0x05, + 0x2f, 0x05, + 0x3b, 0x07, + 0x02, 0x0e, + 0x18, 0x09, + 0x80, 0xbe, 0x22, + 0x74, 0x0c, + 0x80, 0xd6, 0x1a, + 0x81, 0x10, 0x05, + 0x80, 0xe1, 0x09, + 0xf2, 0x9e, 0x03, + 0x37, 0x09, + 0x81, 0x5c, 0x14, + 0x80, 0xb8, 0x08, + 0x80, 0xdd, 0x15, + 0x3b, 0x03, + 0x0a, 0x06, + 0x38, 0x08, + 0x46, 0x08, + 0x0c, 0x06, + 0x74, 0x0b, + 0x1e, 0x03, + 0x5a, 0x04, + 0x59, 0x09, + 0x80, 0x83, 0x18, + 0x1c, 0x0a, + 0x16, 0x09, + 0x4c, 0x04, + 0x80, 0x8a, 0x06, + 0xab, 0xa4, 0x0c, + 0x17, 0x04, + 0x31, 0xa1, 0x04, + 0x81, 0xda, 0x26, + 0x07, 0x0c, + 0x05, 0x05, + 0x80, 0xa6, 0x10, + 0x81, 0xf5, 0x07, + 0x01, 0x20, + 0x2a, 0x06, + 0x4c, 0x04, + 0x80, 0x8d, 0x04, + 0x80, 0xbe, 0x03, + 0x1b, 0x03, + 0x0f, 0x0d, +]; +#[rustfmt::skip] +const NORMAL1: &[u8] = &[ + 0x5e, 0x22, + 0x7b, 0x05, + 0x03, 0x04, + 0x2d, 0x03, + 0x66, 0x03, + 0x01, 0x2f, + 0x2e, 0x80, 0x82, + 0x1d, 0x03, + 0x31, 0x0f, + 0x1c, 0x04, + 0x24, 0x09, + 0x1e, 0x05, + 0x2b, 0x05, + 0x44, 0x04, + 0x0e, 0x2a, + 0x80, 0xaa, 0x06, + 0x24, 0x04, + 0x24, 0x04, + 0x28, 0x08, + 0x34, 0x0b, + 0x4e, 0x03, + 0x34, 0x0c, + 0x81, 0x37, 0x09, + 0x16, 0x0a, + 0x08, 0x18, + 0x3b, 0x45, + 0x39, 0x03, + 0x63, 0x08, + 0x09, 0x30, + 0x16, 0x05, + 0x21, 0x03, + 0x1b, 0x05, + 0x01, 0x40, + 0x38, 0x04, + 0x4b, 0x05, + 0x2f, 0x04, + 0x0a, 0x07, + 0x09, 0x07, + 0x40, 0x20, + 0x27, 0x04, + 0x0c, 0x09, + 0x36, 0x03, + 0x3a, 0x05, + 0x1a, 0x07, + 0x04, 0x0c, + 0x07, 0x50, + 0x49, 0x37, + 0x33, 0x0d, + 0x33, 0x07, + 0x2e, 0x08, + 0x0a, 0x06, + 0x26, 0x03, + 0x1d, 0x08, + 0x02, 0x80, 0xd0, + 0x52, 0x10, + 0x03, 0x37, + 0x2c, 0x08, + 0x2a, 0x16, + 0x1a, 0x26, + 0x1c, 0x14, + 0x17, 0x09, + 0x4e, 0x04, + 0x24, 0x09, + 0x44, 0x0d, + 0x19, 0x07, + 0x0a, 0x06, + 0x48, 0x08, + 0x27, 0x09, + 0x75, 0x0b, + 0x42, 0x3e, + 0x2a, 0x06, + 0x3b, 0x05, + 0x0a, 0x06, + 0x51, 0x06, + 0x01, 0x05, + 0x10, 0x03, + 0x05, 0x0b, + 0x59, 0x08, + 0x02, 0x1d, + 0x62, 0x1e, + 0x48, 0x08, + 0x0a, 0x80, 0xa6, + 0x5e, 0x22, + 0x45, 0x0b, + 0x0a, 0x06, + 0x0d, 0x13, + 0x3a, 0x06, + 0x0a, 0x06, + 0x14, 0x1c, + 0x2c, 0x04, + 0x17, 0x80, 0xb9, + 0x3c, 0x64, + 0x53, 0x0c, + 0x48, 0x09, + 0x0a, 0x46, + 0x45, 0x1b, + 0x48, 0x08, + 0x53, 0x0d, + 0x49, 0x07, + 0x0a, 0x80, 0xb6, + 0x22, 0x0e, + 0x0a, 0x06, + 0x46, 0x0a, + 0x1d, 0x03, + 0x47, 0x49, + 0x37, 0x03, + 0x0e, 0x08, + 0x0a, 0x06, + 0x39, 0x07, + 0x0a, 0x81, 0x36, + 0x19, 0x07, + 0x3b, 0x03, + 0x1d, 0x55, + 0x01, 0x0f, + 0x32, 0x0d, + 0x83, 0x9b, 0x66, + 0x75, 0x0b, + 0x80, 0xc4, 0x8a, 0x4c, + 0x63, 0x0d, + 0x84, 0x30, 0x10, + 0x16, 0x0a, + 0x8f, 0x9b, 0x05, + 0x82, 0x47, 0x9a, 0xb9, + 0x3a, 0x86, 0xc6, + 0x82, 0x39, 0x07, + 0x2a, 0x04, + 0x5c, 0x06, + 0x26, 0x0a, + 0x46, 0x0a, + 0x28, 0x05, + 0x13, 0x81, 0xb0, + 0x3a, 0x80, 0xc6, + 0x5b, 0x65, + 0x4b, 0x04, + 0x39, 0x07, + 0x11, 0x40, + 0x05, 0x0b, + 0x02, 0x0e, + 0x97, 0xf8, 0x08, + 0x84, 0xd6, 0x29, + 0x0a, 0xa2, 0xe7, + 0x81, 0x33, 0x0f, + 0x01, 0x1d, + 0x06, 0x0e, + 0x04, 0x08, + 0x81, 0x8c, 0x89, 0x04, + 0x6b, 0x05, + 0x0d, 0x03, + 0x09, 0x07, + 0x10, 0x8f, 0x60, + 0x80, 0xfa, 0x06, + 0x81, 0xb4, 0x4c, + 0x47, 0x09, + 0x74, 0x3c, + 0x80, 0xf6, 0x0a, + 0x73, 0x08, + 0x70, 0x15, + 0x46, 0x7a, + 0x14, 0x0c, + 0x14, 0x0c, + 0x57, 0x09, + 0x19, 0x80, 0x87, + 0x81, 0x47, 0x03, + 0x85, 0x42, 0x0f, + 0x15, 0x84, 0x50, + 0x1f, 0x06, + 0x06, 0x80, 0xd5, + 0x2b, 0x05, + 0x3e, 0x21, + 0x01, 0x70, + 0x2d, 0x03, + 0x1a, 0x04, + 0x02, 0x81, 0x40, + 0x1f, 0x11, + 0x3a, 0x05, + 0x01, 0x81, 0xd0, + 0x2a, 0x80, 0xd6, + 0x2b, 0x04, + 0x01, 0x81, 0xe0, + 0x80, 0xf7, 0x29, + 0x4c, 0x04, + 0x0a, 0x04, + 0x02, 0x83, 0x11, + 0x44, 0x4c, + 0x3d, 0x80, 0xc2, + 0x3c, 0x06, + 0x01, 0x04, + 0x55, 0x05, + 0x1b, 0x34, + 0x02, 0x81, 0x0e, + 0x2c, 0x04, + 0x64, 0x0c, + 0x56, 0x0a, + 0x80, 0xae, 0x38, + 0x1d, 0x0d, + 0x2c, 0x04, + 0x09, 0x07, + 0x02, 0x0e, + 0x06, 0x80, 0x9a, + 0x83, 0xd8, 0x04, + 0x11, 0x03, + 0x0d, 0x03, + 0x77, 0x04, + 0x5f, 0x06, + 0x0c, 0x04, + 0x01, 0x0f, + 0x0c, 0x04, + 0x38, 0x08, + 0x0a, 0x06, + 0x28, 0x08, + 0x2c, 0x04, + 0x02, 0x3e, + 0x81, 0x54, 0x0c, + 0x1d, 0x03, + 0x0a, 0x05, + 0x38, 0x07, + 0x1c, 0x06, + 0x09, 0x07, + 0x80, 0xfa, 0x84, 0x06, +]; diff --git a/CoqOfRust/core/unicode/unicode_data.rs b/CoqOfRust/core/unicode/unicode_data.rs new file mode 100644 index 000000000..4655d35e9 --- /dev/null +++ b/CoqOfRust/core/unicode/unicode_data.rs @@ -0,0 +1,1401 @@ +///! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually! + +#[inline(always)] +const fn bitset_search< + const N: usize, + const CHUNK_SIZE: usize, + const N1: usize, + const CANONICAL: usize, + const CANONICALIZED: usize, +>( + needle: u32, + chunk_idx_map: &[u8; N], + bitset_chunk_idx: &[[u8; CHUNK_SIZE]; N1], + bitset_canonical: &[u64; CANONICAL], + bitset_canonicalized: &[(u8, u8); CANONICALIZED], +) -> bool { + let bucket_idx = (needle / 64) as usize; + let chunk_map_idx = bucket_idx / CHUNK_SIZE; + let chunk_piece = bucket_idx % CHUNK_SIZE; + // FIXME(const-hack): Revert to `slice::get` when slice indexing becomes possible in const. + let chunk_idx = if chunk_map_idx < chunk_idx_map.len() { + chunk_idx_map[chunk_map_idx] + } else { + return false; + }; + let idx = bitset_chunk_idx[chunk_idx as usize][chunk_piece] as usize; + // FIXME(const-hack): Revert to `slice::get` when slice indexing becomes possible in const. + let word = if idx < bitset_canonical.len() { + bitset_canonical[idx] + } else { + let (real_idx, mapping) = bitset_canonicalized[idx - bitset_canonical.len()]; + let mut word = bitset_canonical[real_idx as usize]; + let should_invert = mapping & (1 << 6) != 0; + if should_invert { + word = !word; + } + // Lower 6 bits + let quantity = mapping & ((1 << 6) - 1); + if mapping & (1 << 7) != 0 { + // shift + word >>= quantity as u64; + } else { + word = word.rotate_left(quantity as u32); + } + word + }; + (word & (1 << (needle % 64) as u64)) != 0 +} + +fn decode_prefix_sum(short_offset_run_header: u32) -> u32 { + short_offset_run_header & ((1 << 21) - 1) +} + +fn decode_length(short_offset_run_header: u32) -> usize { + (short_offset_run_header >> 21) as usize +} + +#[inline(always)] +fn skip_search( + needle: u32, + short_offset_runs: &[u32; SOR], + offsets: &[u8; OFFSETS], +) -> bool { + // Note that this *cannot* be past the end of the array, as the last + // element is greater than std::char::MAX (the largest possible needle). + // + // So, we cannot have found it (i.e. Ok(idx) + 1 != length) and the correct + // location cannot be past it, so Err(idx) != length either. + // + // This means that we can avoid bounds checking for the accesses below, too. + let last_idx = + match short_offset_runs.binary_search_by_key(&(needle << 11), |header| header << 11) { + Ok(idx) => idx + 1, + Err(idx) => idx, + }; + + let mut offset_idx = decode_length(short_offset_runs[last_idx]); + let length = if let Some(next) = short_offset_runs.get(last_idx + 1) { + decode_length(*next) - offset_idx + } else { + offsets.len() - offset_idx + }; + let prev = + last_idx.checked_sub(1).map(|prev| decode_prefix_sum(short_offset_runs[prev])).unwrap_or(0); + + let total = needle - prev; + let mut prefix_sum = 0; + for _ in 0..(length - 1) { + let offset = offsets[offset_idx]; + prefix_sum += offset as u32; + if prefix_sum > total { + break; + } + offset_idx += 1; + } + offset_idx % 2 == 1 +} + +pub const UNICODE_VERSION: (u8, u8, u8) = (16, 0, 0); + +#[rustfmt::skip] +pub mod alphabetic { + static SHORT_OFFSET_RUNS: [u32; 53] = [ + 706, 33559113, 876615277, 956309270, 1166025910, 1314925568, 1319120901, 1398813696, + 1449151936, 1451271309, 1455465997, 1463867300, 1652619520, 1663105646, 1665203518, + 1711342208, 1797326647, 1895898848, 2560697242, 2583768976, 2594255920, 2600551419, + 2608940615, 2613141760, 2615240704, 2619435577, 2621533504, 2652997624, 2688650454, + 2692853744, 2699145507, 2713826044, 2734799872, 2736903168, 2757875366, 2835472128, + 2883707536, 2934039760, 2942429152, 2955013632, 2988568880, 3126984704, 3139610336, + 3141711674, 3145911970, 3154308065, 3158503006, 3162699776, 3164797470, 3166896128, + 3168998219, 3171099568, 3176407984, + ]; + static OFFSETS: [u8; 1515] = [ + 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 29, + 18, 1, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 2, 1, 6, 41, + 39, 14, 1, 1, 1, 2, 1, 2, 1, 1, 8, 27, 4, 4, 29, 11, 5, 56, 1, 7, 14, 102, 1, 8, 4, 8, 4, 3, + 10, 3, 2, 1, 16, 48, 13, 101, 24, 33, 9, 2, 4, 1, 5, 24, 2, 19, 19, 25, 7, 11, 5, 24, 1, 6, + 8, 1, 8, 42, 10, 12, 3, 7, 6, 76, 1, 16, 1, 3, 4, 15, 13, 19, 1, 8, 2, 2, 2, 22, 1, 7, 1, 1, + 3, 4, 3, 8, 2, 2, 2, 2, 1, 1, 8, 1, 4, 2, 1, 5, 12, 2, 10, 1, 4, 3, 1, 6, 4, 2, 2, 22, 1, 7, + 1, 2, 1, 2, 1, 2, 4, 5, 4, 2, 2, 2, 4, 1, 7, 4, 1, 1, 17, 6, 11, 3, 1, 9, 1, 3, 1, 22, 1, 7, + 1, 2, 1, 5, 3, 9, 1, 3, 1, 2, 3, 1, 15, 4, 21, 4, 4, 3, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, + 3, 8, 2, 2, 2, 2, 9, 2, 4, 2, 1, 5, 13, 1, 16, 2, 1, 6, 3, 3, 1, 4, 3, 2, 1, 1, 1, 2, 3, 2, + 3, 3, 3, 12, 4, 5, 3, 3, 1, 3, 3, 1, 6, 1, 40, 13, 1, 3, 1, 23, 1, 16, 3, 8, 1, 3, 1, 3, 8, + 2, 1, 3, 2, 1, 2, 4, 28, 4, 1, 8, 1, 3, 1, 23, 1, 10, 1, 5, 3, 8, 1, 3, 1, 3, 8, 2, 6, 2, 1, + 4, 13, 3, 12, 13, 1, 3, 1, 41, 2, 8, 1, 3, 1, 3, 1, 1, 5, 4, 7, 5, 22, 6, 1, 3, 1, 18, 3, + 24, 1, 9, 1, 1, 2, 7, 8, 6, 1, 1, 1, 8, 18, 2, 13, 58, 5, 7, 6, 1, 51, 2, 1, 1, 1, 5, 1, 24, + 1, 1, 1, 19, 1, 3, 2, 5, 1, 1, 6, 1, 14, 4, 32, 1, 63, 8, 1, 36, 4, 19, 4, 16, 1, 36, 67, + 55, 1, 1, 2, 5, 16, 64, 10, 4, 2, 38, 1, 1, 5, 1, 2, 43, 1, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2, + 41, 1, 4, 2, 33, 1, 4, 2, 7, 1, 1, 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 37, 16, 16, 86, 2, 6, 3, + 0, 2, 17, 1, 26, 5, 75, 3, 11, 7, 20, 11, 21, 12, 20, 12, 13, 1, 3, 1, 2, 12, 52, 2, 19, 14, + 1, 4, 1, 67, 89, 7, 43, 5, 70, 10, 31, 1, 12, 4, 9, 23, 30, 2, 5, 11, 44, 4, 26, 54, 28, 4, + 63, 2, 20, 50, 1, 23, 2, 11, 3, 49, 52, 1, 15, 1, 8, 51, 42, 2, 4, 10, 44, 1, 11, 14, 55, + 22, 3, 10, 36, 2, 11, 5, 43, 2, 3, 41, 4, 1, 6, 1, 2, 3, 1, 5, 192, 19, 34, 11, 0, 2, 6, 2, + 38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, + 5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, + 1, 11, 2, 4, 5, 5, 4, 1, 17, 41, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 2, 56, 7, 1, + 16, 23, 9, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 32, 47, 1, 0, 3, 25, 9, 7, 5, 2, + 5, 4, 86, 6, 3, 1, 90, 1, 4, 5, 43, 1, 94, 17, 32, 48, 16, 0, 0, 64, 0, 67, 46, 2, 0, 3, 16, + 10, 2, 20, 47, 5, 8, 3, 113, 39, 9, 2, 103, 2, 67, 2, 2, 1, 1, 1, 8, 21, 20, 1, 33, 24, 52, + 12, 68, 1, 1, 44, 6, 3, 1, 1, 3, 10, 33, 5, 35, 13, 29, 3, 51, 1, 12, 15, 1, 16, 16, 10, 5, + 1, 55, 9, 14, 18, 23, 3, 69, 1, 1, 1, 1, 24, 3, 2, 16, 2, 4, 11, 6, 2, 6, 2, 6, 9, 7, 1, 7, + 1, 43, 1, 14, 6, 123, 21, 0, 12, 23, 4, 49, 0, 0, 2, 106, 38, 7, 12, 5, 5, 12, 1, 13, 1, 5, + 1, 1, 1, 2, 1, 2, 1, 108, 33, 0, 18, 64, 2, 54, 40, 12, 116, 5, 1, 135, 36, 26, 6, 26, 11, + 89, 3, 6, 2, 6, 2, 6, 2, 3, 35, 12, 1, 26, 1, 19, 1, 2, 1, 15, 2, 14, 34, 123, 69, 53, 0, + 29, 3, 49, 47, 32, 13, 30, 5, 43, 5, 30, 2, 36, 4, 8, 1, 5, 42, 158, 18, 36, 4, 36, 4, 40, + 8, 52, 12, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 3, 52, 12, 0, 9, 22, 10, 8, 24, + 6, 1, 42, 1, 9, 69, 6, 2, 1, 1, 44, 1, 2, 3, 1, 2, 23, 10, 23, 9, 31, 65, 19, 1, 2, 10, 22, + 10, 26, 70, 56, 6, 2, 64, 4, 1, 2, 5, 8, 1, 3, 1, 29, 42, 29, 3, 29, 35, 8, 1, 28, 27, 54, + 10, 22, 10, 19, 13, 18, 110, 73, 55, 51, 13, 51, 13, 40, 34, 28, 3, 1, 5, 23, 250, 42, 1, 2, + 3, 2, 16, 3, 55, 1, 3, 29, 10, 1, 8, 22, 42, 18, 46, 21, 27, 23, 9, 70, 43, 5, 10, 57, 9, 1, + 13, 25, 23, 51, 17, 4, 8, 35, 3, 1, 9, 64, 1, 4, 9, 2, 10, 1, 1, 1, 35, 18, 1, 34, 2, 1, 6, + 4, 62, 7, 1, 1, 1, 4, 1, 15, 1, 10, 7, 57, 23, 4, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, + 2, 2, 2, 2, 3, 1, 6, 1, 5, 7, 28, 10, 1, 1, 2, 1, 1, 38, 1, 10, 1, 1, 2, 1, 1, 4, 1, 2, 3, + 1, 1, 1, 44, 66, 1, 3, 1, 4, 20, 3, 30, 66, 2, 2, 1, 1, 184, 54, 2, 7, 25, 6, 34, 63, 1, 1, + 3, 1, 59, 54, 2, 1, 71, 27, 2, 14, 21, 7, 185, 57, 103, 64, 31, 8, 2, 1, 2, 8, 1, 2, 1, 30, + 1, 2, 2, 2, 2, 4, 93, 8, 2, 46, 2, 6, 1, 1, 1, 2, 27, 51, 2, 10, 17, 72, 5, 1, 18, 73, 199, + 33, 31, 9, 1, 45, 1, 7, 1, 1, 49, 30, 2, 22, 1, 14, 73, 7, 1, 2, 1, 44, 3, 1, 1, 2, 1, 3, 1, + 1, 2, 2, 24, 6, 1, 2, 1, 37, 1, 2, 1, 4, 1, 1, 0, 23, 9, 17, 1, 41, 3, 3, 111, 1, 79, 0, + 102, 111, 17, 196, 0, 97, 15, 0, 17, 6, 25, 0, 5, 0, 0, 47, 0, 0, 7, 31, 17, 79, 17, 30, 18, + 48, 16, 4, 31, 21, 5, 19, 0, 45, 211, 64, 128, 75, 4, 57, 7, 17, 64, 2, 1, 1, 12, 2, 14, 0, + 8, 0, 41, 10, 0, 4, 1, 7, 1, 2, 1, 0, 15, 1, 29, 3, 2, 1, 14, 4, 8, 0, 0, 107, 5, 13, 3, 9, + 7, 10, 4, 1, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, + 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, + 25, 1, 31, 1, 25, 1, 8, 0, 31, 6, 6, 213, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 112, 45, + 10, 7, 16, 1, 0, 30, 18, 44, 0, 28, 228, 30, 2, 1, 0, 7, 1, 4, 1, 2, 1, 15, 1, 197, 59, 68, + 3, 1, 3, 1, 0, 4, 1, 27, 1, 2, 1, 1, 2, 1, 1, 10, 1, 4, 1, 1, 1, 1, 6, 1, 4, 1, 1, 1, 1, 1, + 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 4, 1, 7, 1, 4, 1, 4, 1, 1, 1, + 10, 1, 17, 5, 3, 1, 5, 1, 17, 0, 26, 6, 26, 6, 26, 0, 0, 32, 0, 6, 222, 2, 0, 14, 0, 15, 0, + 0, 0, 0, 0, 5, 0, 0, + ]; + pub fn lookup(c: char) -> bool { + super::skip_search( + c as u32, + &SHORT_OFFSET_RUNS, + &OFFSETS, + ) + } +} + +#[rustfmt::skip] +pub mod case_ignorable { + static SHORT_OFFSET_RUNS: [u32; 37] = [ + 688, 44045149, 572528402, 576724925, 807414908, 878718981, 903913493, 929080568, 933275148, + 937491230, 1138818560, 1147208189, 1210124160, 1222707713, 1235291428, 1260457643, + 1277237295, 1537284411, 1545673776, 1604394739, 1667314736, 1692492062, 1700883184, + 1709272384, 1721855823, 1730260976, 1747041437, 1759629056, 1768018279, 1776409088, + 1797382144, 1822548654, 1856103659, 1864493264, 1872884731, 1882062849, 1887371760, + ]; + static OFFSETS: [u8; 905] = [ + 39, 1, 6, 1, 11, 1, 35, 1, 1, 1, 71, 1, 4, 1, 1, 1, 4, 1, 2, 2, 0, 192, 4, 2, 4, 1, 9, 2, + 1, 1, 251, 7, 207, 1, 5, 1, 49, 45, 1, 1, 1, 2, 1, 2, 1, 1, 44, 1, 11, 6, 10, 11, 1, 1, 35, + 1, 10, 21, 16, 1, 101, 8, 1, 10, 1, 4, 33, 1, 1, 1, 30, 27, 91, 11, 58, 11, 4, 1, 2, 1, 24, + 24, 43, 3, 44, 1, 7, 2, 5, 9, 41, 58, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 13, 1, 15, 1, + 58, 1, 4, 4, 8, 1, 20, 2, 26, 1, 2, 2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, + 57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6, 1, 1, 58, 1, 2, 1, 1, 4, 8, 1, 7, 2, 11, 2, 30, 1, + 61, 1, 12, 1, 50, 1, 3, 1, 55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 6, 1, + 5, 2, 20, 2, 28, 2, 57, 2, 4, 4, 8, 1, 20, 2, 29, 1, 72, 1, 7, 3, 1, 1, 90, 1, 2, 7, 11, 9, + 98, 1, 2, 9, 9, 1, 1, 7, 73, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1, + 102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 94, 1, 0, 3, 0, 3, + 29, 2, 30, 2, 30, 2, 64, 2, 1, 7, 8, 1, 2, 11, 3, 1, 5, 1, 45, 5, 51, 1, 65, 2, 34, 1, 118, + 3, 4, 2, 9, 1, 6, 3, 219, 2, 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 39, 1, 8, 31, + 49, 4, 48, 1, 1, 5, 1, 1, 5, 1, 40, 9, 12, 2, 32, 4, 2, 2, 1, 3, 56, 1, 1, 2, 3, 1, 1, 3, + 58, 8, 2, 2, 64, 6, 82, 3, 1, 13, 1, 7, 4, 1, 6, 1, 3, 2, 50, 63, 13, 1, 34, 101, 0, 1, 1, + 3, 11, 3, 13, 3, 13, 3, 13, 2, 12, 5, 8, 2, 10, 1, 2, 1, 2, 5, 49, 5, 1, 10, 1, 1, 13, 1, + 16, 13, 51, 33, 0, 2, 113, 3, 125, 1, 15, 1, 96, 32, 47, 1, 0, 1, 36, 4, 3, 5, 5, 1, 93, 6, + 93, 3, 0, 1, 0, 6, 0, 1, 98, 4, 1, 10, 1, 1, 28, 4, 80, 2, 14, 34, 78, 1, 23, 3, 103, 3, 3, + 2, 8, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, 26, 18, 13, 1, 38, 8, 25, 11, 46, 3, 48, 1, 2, 4, + 2, 2, 17, 1, 21, 2, 66, 6, 2, 2, 2, 2, 12, 1, 8, 1, 35, 1, 11, 1, 51, 1, 1, 3, 2, 2, 5, 2, + 1, 1, 27, 1, 14, 2, 5, 2, 1, 1, 100, 5, 9, 3, 121, 1, 2, 1, 4, 1, 0, 1, 147, 17, 0, 16, 3, + 1, 12, 16, 34, 1, 2, 1, 169, 1, 7, 1, 6, 1, 11, 1, 35, 1, 1, 1, 47, 1, 45, 2, 67, 1, 21, 3, + 0, 1, 226, 1, 149, 5, 0, 6, 1, 42, 1, 9, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 38, 1, + 26, 5, 1, 1, 0, 2, 79, 4, 70, 11, 49, 4, 123, 1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 2, + 1, 4, 1, 10, 1, 50, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, + 1, 2, 1, 157, 1, 3, 8, 21, 2, 57, 2, 3, 1, 37, 7, 3, 5, 70, 6, 13, 1, 1, 1, 1, 1, 14, 2, 85, + 8, 2, 3, 1, 1, 23, 1, 84, 6, 1, 1, 4, 2, 1, 2, 238, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, + 106, 1, 1, 1, 2, 6, 1, 1, 101, 1, 1, 1, 2, 4, 1, 5, 0, 9, 1, 2, 0, 2, 1, 1, 4, 1, 144, 4, 2, + 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, + 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1, 0, 2, 11, 2, 52, 5, 5, 1, + 1, 1, 23, 1, 0, 17, 6, 15, 0, 12, 3, 3, 0, 5, 59, 7, 9, 4, 0, 3, 40, 2, 0, 1, 63, 17, 64, 2, + 1, 2, 0, 4, 1, 7, 1, 2, 0, 2, 1, 4, 0, 46, 2, 23, 0, 3, 9, 16, 2, 7, 30, 4, 148, 3, 0, 55, + 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 160, 14, 0, + 1, 61, 4, 0, 5, 254, 2, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0, + ]; + pub fn lookup(c: char) -> bool { + super::skip_search( + c as u32, + &SHORT_OFFSET_RUNS, + &OFFSETS, + ) + } +} + +#[rustfmt::skip] +pub mod cased { + static SHORT_OFFSET_RUNS: [u32; 22] = [ + 4256, 115348384, 136322176, 144711446, 163587254, 320875520, 325101120, 350268208, + 392231680, 404815649, 413205504, 421595008, 467733632, 484513952, 501313088, 505533440, + 509728422, 587325184, 635559984, 648145152, 652341552, 657650058, + ]; + static OFFSETS: [u8; 319] = [ + 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 195, 1, 4, 4, 208, 1, 36, 7, 2, 30, 5, + 96, 1, 42, 4, 2, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 9, + 41, 0, 38, 1, 1, 5, 1, 2, 43, 1, 4, 0, 86, 2, 6, 0, 11, 5, 43, 2, 3, 64, 192, 64, 0, 2, 6, + 2, 38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, + 13, 5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, + 4, 1, 6, 4, 1, 2, 4, 5, 5, 4, 1, 17, 32, 3, 2, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, + 1, 0, 46, 18, 30, 132, 102, 3, 4, 1, 62, 2, 2, 1, 1, 1, 8, 21, 5, 1, 3, 0, 43, 1, 14, 6, 80, + 0, 7, 12, 5, 0, 26, 6, 26, 0, 80, 96, 36, 4, 36, 116, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, + 1, 7, 1, 2, 0, 1, 2, 3, 1, 42, 1, 9, 0, 51, 13, 51, 93, 22, 10, 22, 0, 64, 0, 64, 0, 85, 1, + 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, + 1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, + 8, 0, 10, 1, 20, 6, 6, 0, 62, 0, 68, 0, 26, 6, 26, 6, 26, 0, + ]; + pub fn lookup(c: char) -> bool { + super::skip_search( + c as u32, + &SHORT_OFFSET_RUNS, + &OFFSETS, + ) + } +} + +#[rustfmt::skip] +pub mod cc { + static SHORT_OFFSET_RUNS: [u32; 1] = [ + 1114272, + ]; + static OFFSETS: [u8; 5] = [ + 0, 32, 95, 33, 0, + ]; + pub fn lookup(c: char) -> bool { + super::skip_search( + c as u32, + &SHORT_OFFSET_RUNS, + &OFFSETS, + ) + } +} + +#[rustfmt::skip] +pub mod grapheme_extend { + static SHORT_OFFSET_RUNS: [u32; 34] = [ + 768, 2098307, 6292881, 10490717, 522196754, 526393356, 723528943, 731918378, 744531567, + 752920578, 769719070, 908131840, 912326558, 920715773, 924912129, 937495844, 962662059, + 971053103, 1256266800, 1323376371, 1386296384, 1407279390, 1415670512, 1424060239, + 1432468637, 1449250560, 1453445477, 1461836288, 1487003648, 1512170158, 1541530860, + 1549920464, 1559101472, 1568604656, + ]; + static OFFSETS: [u8; 751] = [ + 0, 112, 0, 7, 0, 45, 1, 1, 1, 2, 1, 2, 1, 1, 72, 11, 48, 21, 16, 1, 101, 7, 2, 6, 2, 2, 1, + 4, 35, 1, 30, 27, 91, 11, 58, 9, 9, 1, 24, 4, 1, 9, 1, 3, 1, 5, 43, 3, 59, 9, 42, 24, 1, 32, + 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 29, 1, 58, 1, 1, 1, 2, 4, 8, 1, 9, 1, 10, 2, 26, 1, 2, + 2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, 57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6, + 1, 1, 58, 1, 1, 2, 1, 4, 8, 1, 7, 3, 10, 2, 30, 1, 59, 1, 1, 1, 12, 1, 9, 1, 40, 1, 3, 1, + 55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 2, 1, 1, 3, 3, 1, 4, 7, 2, 11, 2, 28, + 2, 57, 2, 1, 1, 2, 4, 8, 1, 9, 1, 10, 2, 29, 1, 72, 1, 4, 1, 2, 3, 1, 1, 8, 1, 81, 1, 2, 7, + 12, 8, 98, 1, 2, 9, 11, 7, 73, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1, + 102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 0, 3, 0, 4, 28, 3, + 29, 2, 30, 2, 64, 2, 1, 7, 8, 1, 2, 11, 9, 1, 45, 3, 1, 1, 117, 2, 34, 1, 118, 3, 4, 2, 9, + 1, 6, 3, 219, 2, 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 48, 31, 49, 4, 48, 10, 4, + 3, 38, 9, 12, 2, 32, 4, 2, 6, 56, 1, 1, 2, 3, 1, 1, 5, 56, 8, 2, 2, 152, 3, 1, 13, 1, 7, 4, + 1, 6, 1, 3, 2, 198, 64, 0, 1, 195, 33, 0, 3, 141, 1, 96, 32, 0, 6, 105, 2, 0, 4, 1, 10, 32, + 2, 80, 2, 0, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, 26, 18, 13, 1, 38, 8, 25, 11, 1, 1, 44, 3, + 48, 1, 2, 4, 2, 2, 2, 1, 36, 1, 67, 6, 2, 2, 2, 2, 12, 1, 8, 1, 47, 1, 51, 1, 1, 3, 2, 2, 5, + 2, 1, 1, 42, 2, 8, 1, 238, 1, 2, 1, 4, 1, 0, 1, 0, 16, 16, 16, 0, 2, 0, 1, 226, 1, 149, 5, + 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 65, 5, 0, 2, 79, 4, 70, 11, 49, 4, 123, 1, 54, + 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 7, 1, 61, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 1, 1, 8, + 4, 2, 1, 95, 3, 2, 4, 6, 1, 2, 1, 157, 1, 3, 8, 21, 2, 57, 2, 1, 1, 1, 1, 12, 1, 9, 1, 14, + 7, 3, 5, 67, 1, 2, 6, 1, 1, 2, 1, 1, 3, 4, 3, 1, 1, 14, 2, 85, 8, 2, 3, 1, 1, 23, 1, 81, 1, + 2, 6, 1, 1, 2, 1, 1, 2, 1, 2, 235, 1, 2, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, + 1, 2, 8, 101, 1, 1, 1, 2, 4, 1, 5, 0, 9, 1, 2, 245, 1, 10, 4, 4, 1, 144, 4, 2, 2, 4, 1, 32, + 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, + 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1, 0, 2, 11, 2, 52, 5, 5, 3, 23, 1, 0, 1, 6, + 15, 0, 12, 3, 3, 0, 5, 59, 7, 0, 1, 63, 4, 81, 1, 11, 2, 0, 2, 0, 46, 2, 23, 0, 5, 3, 6, 8, + 8, 2, 7, 30, 4, 148, 3, 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, + 5, 100, 1, 160, 7, 0, 1, 61, 4, 0, 4, 254, 2, 0, 7, 109, 7, 0, 96, 128, 240, 0, + ]; + #[inline] + pub fn lookup(c: char) -> bool { + (c as u32) >= 0x300 && lookup_slow(c) + } + fn lookup_slow(c: char) -> bool { + super::skip_search( + c as u32, + &SHORT_OFFSET_RUNS, + &OFFSETS, + ) + } +} + +#[rustfmt::skip] +pub mod lowercase { + static BITSET_CHUNKS_MAP: [u8; 123] = [ + 14, 17, 0, 0, 9, 0, 0, 12, 13, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 1, 0, 15, 0, 8, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, + 3, 18, 0, 7, + ]; + static BITSET_INDEX_CHUNKS: [[u8; 16]; 20] = [ + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 56, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 43, 0, 52, 48, 50, 33], + [0, 0, 0, 0, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 3, 0, 16, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27], + [0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 46, 0, 56, 56, 56, 0, 22, 22, 69, 22, 36, 25, 24, 37], + [0, 5, 70, 0, 29, 15, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 66, 34, 17, 23, 53, 54, 49, 47, 8, 35, 42, 0, 28, 13, 31], + [11, 60, 0, 6, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 32, 0], + [16, 26, 22, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [16, 51, 2, 21, 68, 9, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [16, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [65, 41, 55, 12, 77, 63, 18, 1, 7, 64, 76, 20, 73, 74, 4, 45], + ]; + static BITSET_CANONICAL: [u64; 56] = [ + 0b0000000000000000000000000000000000000000000000000000000000000000, + 0b1111111111111111110000000000000000000000000011111111111111111111, + 0b1010101010101010101010101010101010101010101010101010100000000010, + 0b0000000000000111111111111111111111111111111111111111111111111111, + 0b1111111111111111111111000000000000000000000000001111110111111111, + 0b1000000000000010000000000000000000000000000000000000000000000000, + 0b0000111111111111111111111111111111111111000000000000000000000000, + 0b0000111111111111111111111111110000000000000000000000000011111111, + 0b1111111111111111111111111111111111111111111111111010101010000101, + 0b1111111111111111111111111111111100000000000000000000000000000000, + 0b1111111111111111111111111111110000000000000000000000000000000000, + 0b1111111111111111111111110000000000000000000000000000000000000000, + 0b1111111111111111111111000000000000000000000000001111111111101111, + 0b1111111111111111111100000000000000000000000000010000000000000000, + 0b1111111111111111000000111111111111110111111111111111111111111111, + 0b1111111111111111000000000000000000000000000000000100001111000000, + 0b1111111111111111000000000000000000000000000000000000000000000000, + 0b1111111101111111111111111111111110000000000000000000000000000000, + 0b1111110000000000000000000000000011111111111111111111111111000000, + 0b1111011111111111111111111111111111111111111111110000000000000000, + 0b1111000000000000000000000000001111110111111111111111111111111100, + 0b1010101010101010101010101010101010101010101010101101010101010100, + 0b1010101010101010101010101010101010101010101010101010101010101010, + 0b0101010110101010101010101010101010101010101010101010101010101010, + 0b0100000011011111000000001111111100000000111111110000000011111111, + 0b0011111111111111000000001111111100000000111111110000000000111111, + 0b0011111111011010000101010110001011111111111111111111111111111111, + 0b0011111100000000000000000000000000000000000000000000000000000000, + 0b0011110010001010000000000000000000000000000000000000000000100000, + 0b0011001000010000100000000000000000000000000010001100010000000000, + 0b0001101111111011111111111111101111111111100000000000000000000000, + 0b0001100100101111101010101010101010101010111000110111111111111111, + 0b0000011111111101111111111111111111111111111111111111111110111001, + 0b0000011101011100000000000000000000001010101010100010010100001010, + 0b0000010000100000000001000000000000000000000000000000000000000000, + 0b0000000111111111111111111111111111111111111011111111111111111111, + 0b0000000011111111000000001111111100000000001111110000000011111111, + 0b0000000011011100000000001111111100000000110011110000000011011100, + 0b0000000000001000010100000001101010101010101010101010101010101010, + 0b0000000000000000001000001011111111111111111111111111111111111111, + 0b0000000000000000000001111110000001111111111111111111101111111111, + 0b0000000000000000000000001111111111111111110111111100000000000000, + 0b0000000000000000000000000001111100000000000000000000000000000011, + 0b0000000000000000000000000000000000111010101010101010101010101010, + 0b0000000000000000000000000000000000000000111110000000000001111111, + 0b0000000000000000000000000000000000000000000000000000101111110111, + 0b0000000000000000000000000000000000000000000000000000010111111111, + 0b1001001111111010101010101010101010101010101010101010101010101010, + 0b1001010111111111101010101010101010101010101010101010101010101010, + 0b1010101000101001101010101010101010110101010101010101001001000000, + 0b1010101010100000100000101010101010101010101110100101000010101010, + 0b1010101010101010101010101010101011111111111111111111111111111111, + 0b1010101010101011101010101010100000000000000000000000000000000000, + 0b1101010010101010101010101010101010101010101010101010101101010101, + 0b1110011001010001001011010010101001001110001001000011000100101001, + 0b1110101111000000000000000000000000001111111111111111111111111100, + ]; + static BITSET_MAPPING: [(u8, u8); 22] = [ + (0, 64), (1, 188), (1, 186), (1, 183), (1, 176), (1, 109), (1, 124), (1, 126), (1, 66), + (1, 70), (1, 77), (2, 146), (2, 144), (2, 83), (3, 93), (3, 147), (3, 133), (4, 12), (4, 6), + (5, 187), (6, 78), (7, 132), + ]; + + pub const fn lookup(c: char) -> bool { + super::bitset_search( + c as u32, + &BITSET_CHUNKS_MAP, + &BITSET_INDEX_CHUNKS, + &BITSET_CANONICAL, + &BITSET_MAPPING, + ) + } +} + +#[rustfmt::skip] +pub mod n { + static SHORT_OFFSET_RUNS: [u32; 42] = [ + 1632, 18876774, 31461440, 102765417, 111154926, 115349830, 132128880, 165684320, 186656630, + 195046653, 199241735, 203436434, 216049184, 241215536, 249605104, 274792208, 278987015, + 283181793, 295766104, 320933114, 383848032, 396432464, 438376016, 446765280, 463543280, + 471932752, 488711168, 497115440, 501312096, 505507184, 522284672, 526503152, 530698944, + 534894542, 547479872, 551674608, 555869424, 560064711, 568454257, 576844032, 597818352, + 603126778, + ]; + static OFFSETS: [u8; 289] = [ + 48, 10, 120, 2, 5, 1, 2, 3, 0, 10, 134, 10, 198, 10, 0, 10, 118, 10, 4, 6, 108, 10, 118, + 10, 118, 10, 2, 6, 110, 13, 115, 10, 8, 7, 103, 10, 104, 7, 7, 19, 109, 10, 96, 10, 118, 10, + 70, 20, 0, 10, 70, 10, 0, 20, 0, 3, 239, 10, 6, 10, 22, 10, 0, 10, 128, 11, 165, 10, 6, 10, + 182, 10, 86, 10, 134, 10, 6, 10, 0, 1, 3, 6, 6, 10, 198, 51, 2, 5, 0, 60, 78, 22, 0, 30, 0, + 1, 0, 1, 25, 9, 14, 3, 0, 4, 138, 10, 30, 8, 1, 15, 32, 10, 39, 15, 0, 10, 188, 10, 0, 6, + 154, 10, 38, 10, 198, 10, 22, 10, 86, 10, 0, 10, 0, 10, 0, 45, 12, 57, 17, 2, 0, 27, 36, 4, + 29, 1, 8, 1, 134, 5, 202, 10, 0, 8, 25, 7, 39, 9, 75, 5, 22, 6, 160, 2, 2, 16, 2, 46, 64, 9, + 52, 2, 30, 3, 75, 5, 104, 8, 24, 8, 41, 7, 0, 6, 48, 10, 6, 10, 0, 31, 158, 10, 42, 4, 112, + 7, 134, 30, 128, 10, 60, 10, 144, 10, 7, 20, 251, 10, 0, 10, 118, 10, 0, 10, 102, 10, 6, 20, + 76, 12, 0, 19, 93, 10, 0, 10, 86, 29, 227, 10, 70, 10, 0, 10, 102, 21, 0, 111, 0, 10, 0, 10, + 86, 10, 134, 10, 1, 7, 0, 10, 0, 23, 0, 10, 0, 20, 12, 20, 108, 25, 0, 50, 0, 10, 0, 10, 0, + 10, 247, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0, 10, 0, + ]; + pub fn lookup(c: char) -> bool { + super::skip_search( + c as u32, + &SHORT_OFFSET_RUNS, + &OFFSETS, + ) + } +} + +#[rustfmt::skip] +pub mod uppercase { + static BITSET_CHUNKS_MAP: [u8; 125] = [ + 12, 15, 6, 6, 0, 6, 6, 2, 4, 11, 6, 16, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 5, 6, 14, 6, 10, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 13, 6, 6, + 6, 6, 9, 6, 3, + ]; + static BITSET_INDEX_CHUNKS: [[u8; 16]; 17] = [ + [44, 44, 5, 35, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 5, 1], + [44, 44, 5, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 40, 44, 44, 44, 44, 44, 17, 17, 63, 17, 43, 29, 24, 23], + [44, 44, 44, 44, 9, 8, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 44, 44, 37, 28, 67, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 55, 44, 44, 44, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 62, 61, 44, 20, 14, 16, 4], + [44, 44, 44, 44, 56, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 59, 44, 44, 31, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 60, 46, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 49, 44, 32, 36, 21, 22, 15, 13, 34, 44, 44, 44, 11, 30, 39], + [52, 54, 26, 50, 12, 7, 25, 51, 41, 53, 6, 3, 66, 65, 64, 68], + [57, 44, 9, 47, 44, 42, 33, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [58, 19, 2, 18, 10, 48, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [58, 38, 17, 27, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + ]; + static BITSET_CANONICAL: [u64; 44] = [ + 0b0000011111111111111111111111111000000000000000000000000000000000, + 0b0000000000111111111111111111111111111111111111111111111111111111, + 0b0101010101010101010101010101010101010101010101010101010000000001, + 0b0000011111111111111111111111110000000000000000000000000000000001, + 0b0000000000100000000000000000000000010101010000010001101011110101, + 0b1111111111111111111111111111111100000000000000000000000000000000, + 0b1111111111111111111111110000000000000000000000000000001111111111, + 0b1111111111111111111100000000000000000000000000011111110001011111, + 0b1111111111111111000000111111111111111111111111110000001111111111, + 0b1111111111111111000000000000000000000000000000000000000000000000, + 0b1111111111111110010101010101010101010101010101010101010101010101, + 0b1000000001000101000000000000000000000000000000000000000000000000, + 0b0111101100000000000000000000000000011111110111111110011110110000, + 0b0110110000000101010101010101010101010101010101010101010101010101, + 0b0110101000000000010101010101010101010101010101010101010101010101, + 0b0101010111010010010101010101010101001010101010101010010010010000, + 0b0101010101011111011111010101010101010101010001010010100001010101, + 0b0101010101010101010101010101010101010101010101010101010101010101, + 0b0101010101010101010101010101010101010101010101010010101010101011, + 0b0101010101010101010101010101010100000000000000000000000000000000, + 0b0101010101010100010101010101010000000000000000000000000000000000, + 0b0010101101010101010101010101010101010101010101010101010010101010, + 0b0001000110101110110100101101010110110001110110111100111011010110, + 0b0000111100000000000111110000000000001111000000000000111100000000, + 0b0000111100000000000000000000000000000000000000000000000000000000, + 0b0000001111111111111111111111111100000000000000000000000000111111, + 0b0000000000111111110111100110010011010000000000000000000000000011, + 0b0000000000000100001010000000010101010101010101010101010101010101, + 0b0000000000000000111111111111111100000000000000000000000000100000, + 0b0000000000000000111111110000000010101010000000000011111100000000, + 0b0000000000000000000011111111101111111111111111101101011101000000, + 0b0000000000000000000000000011111111111111111111110000000000000000, + 0b0000000000000000000000000000000001111111011111111111111111111111, + 0b0000000000000000000000000000000000000000001101111111011111111111, + 0b0000000000000000000000000000000000000000000000000101010101111010, + 0b0000000000000000000000000000000000000000000000000010000010111111, + 0b1010101001010101010101010101010101010101010101010101010101010101, + 0b1100000000001111001111010101000000111110001001110011100010000100, + 0b1100000000100101111010101001110100000000000000000000000000000000, + 0b1110011010010000010101010101010101010101000111001000000000000000, + 0b1110011111111111111111111111111111111111111111110000001000000000, + 0b1111000000000000000000000000001111111111111111111111111100000000, + 0b1111011111111111000000000000000000000000000000000000000000000000, + 0b1111111100000000111111110000000000111111000000001111111100000000, + ]; + static BITSET_MAPPING: [(u8, u8); 25] = [ + (0, 187), (0, 177), (0, 171), (0, 167), (0, 164), (0, 32), (0, 47), (0, 51), (0, 121), + (0, 117), (0, 109), (1, 150), (1, 148), (1, 142), (1, 134), (1, 131), (1, 64), (2, 164), + (2, 146), (2, 20), (3, 146), (3, 140), (3, 134), (4, 178), (4, 171), + ]; + + pub const fn lookup(c: char) -> bool { + super::bitset_search( + c as u32, + &BITSET_CHUNKS_MAP, + &BITSET_INDEX_CHUNKS, + &BITSET_CANONICAL, + &BITSET_MAPPING, + ) + } +} + +#[rustfmt::skip] +pub mod white_space { + static WHITESPACE_MAP: [u8; 256] = [ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + #[inline] + pub const fn lookup(c: char) -> bool { + match c as u32 >> 8 { + 0 => WHITESPACE_MAP[c as usize & 0xff] & 1 != 0, + 22 => c as u32 == 0x1680, + 32 => WHITESPACE_MAP[c as usize & 0xff] & 2 != 0, + 48 => c as u32 == 0x3000, + _ => false, + } + } +} + +#[rustfmt::skip] +pub mod conversions { + const INDEX_MASK: u32 = 0x400000; + + pub fn to_lower(c: char) -> [char; 3] { + if c.is_ascii() { + [(c as u8).to_ascii_lowercase() as char, '\0', '\0'] + } else { + LOWERCASE_TABLE + .binary_search_by(|&(key, _)| key.cmp(&c)) + .map(|i| { + let u = LOWERCASE_TABLE[i].1; + char::from_u32(u).map(|c| [c, '\0', '\0']).unwrap_or_else(|| { + // SAFETY: Index comes from statically generated table + unsafe { *LOWERCASE_TABLE_MULTI.get_unchecked((u & (INDEX_MASK - 1)) as usize) } + }) + }) + .unwrap_or([c, '\0', '\0']) + } + } + + pub fn to_upper(c: char) -> [char; 3] { + if c.is_ascii() { + [(c as u8).to_ascii_uppercase() as char, '\0', '\0'] + } else { + UPPERCASE_TABLE + .binary_search_by(|&(key, _)| key.cmp(&c)) + .map(|i| { + let u = UPPERCASE_TABLE[i].1; + char::from_u32(u).map(|c| [c, '\0', '\0']).unwrap_or_else(|| { + // SAFETY: Index comes from statically generated table + unsafe { *UPPERCASE_TABLE_MULTI.get_unchecked((u & (INDEX_MASK - 1)) as usize) } + }) + }) + .unwrap_or([c, '\0', '\0']) + } + } + + static LOWERCASE_TABLE: &[(char, u32)] = &[ + ('\u{c0}', 224), ('\u{c1}', 225), ('\u{c2}', 226), ('\u{c3}', 227), ('\u{c4}', 228), + ('\u{c5}', 229), ('\u{c6}', 230), ('\u{c7}', 231), ('\u{c8}', 232), ('\u{c9}', 233), + ('\u{ca}', 234), ('\u{cb}', 235), ('\u{cc}', 236), ('\u{cd}', 237), ('\u{ce}', 238), + ('\u{cf}', 239), ('\u{d0}', 240), ('\u{d1}', 241), ('\u{d2}', 242), ('\u{d3}', 243), + ('\u{d4}', 244), ('\u{d5}', 245), ('\u{d6}', 246), ('\u{d8}', 248), ('\u{d9}', 249), + ('\u{da}', 250), ('\u{db}', 251), ('\u{dc}', 252), ('\u{dd}', 253), ('\u{de}', 254), + ('\u{100}', 257), ('\u{102}', 259), ('\u{104}', 261), ('\u{106}', 263), ('\u{108}', 265), + ('\u{10a}', 267), ('\u{10c}', 269), ('\u{10e}', 271), ('\u{110}', 273), ('\u{112}', 275), + ('\u{114}', 277), ('\u{116}', 279), ('\u{118}', 281), ('\u{11a}', 283), ('\u{11c}', 285), + ('\u{11e}', 287), ('\u{120}', 289), ('\u{122}', 291), ('\u{124}', 293), ('\u{126}', 295), + ('\u{128}', 297), ('\u{12a}', 299), ('\u{12c}', 301), ('\u{12e}', 303), + ('\u{130}', 4194304), ('\u{132}', 307), ('\u{134}', 309), ('\u{136}', 311), + ('\u{139}', 314), ('\u{13b}', 316), ('\u{13d}', 318), ('\u{13f}', 320), ('\u{141}', 322), + ('\u{143}', 324), ('\u{145}', 326), ('\u{147}', 328), ('\u{14a}', 331), ('\u{14c}', 333), + ('\u{14e}', 335), ('\u{150}', 337), ('\u{152}', 339), ('\u{154}', 341), ('\u{156}', 343), + ('\u{158}', 345), ('\u{15a}', 347), ('\u{15c}', 349), ('\u{15e}', 351), ('\u{160}', 353), + ('\u{162}', 355), ('\u{164}', 357), ('\u{166}', 359), ('\u{168}', 361), ('\u{16a}', 363), + ('\u{16c}', 365), ('\u{16e}', 367), ('\u{170}', 369), ('\u{172}', 371), ('\u{174}', 373), + ('\u{176}', 375), ('\u{178}', 255), ('\u{179}', 378), ('\u{17b}', 380), ('\u{17d}', 382), + ('\u{181}', 595), ('\u{182}', 387), ('\u{184}', 389), ('\u{186}', 596), ('\u{187}', 392), + ('\u{189}', 598), ('\u{18a}', 599), ('\u{18b}', 396), ('\u{18e}', 477), ('\u{18f}', 601), + ('\u{190}', 603), ('\u{191}', 402), ('\u{193}', 608), ('\u{194}', 611), ('\u{196}', 617), + ('\u{197}', 616), ('\u{198}', 409), ('\u{19c}', 623), ('\u{19d}', 626), ('\u{19f}', 629), + ('\u{1a0}', 417), ('\u{1a2}', 419), ('\u{1a4}', 421), ('\u{1a6}', 640), ('\u{1a7}', 424), + ('\u{1a9}', 643), ('\u{1ac}', 429), ('\u{1ae}', 648), ('\u{1af}', 432), ('\u{1b1}', 650), + ('\u{1b2}', 651), ('\u{1b3}', 436), ('\u{1b5}', 438), ('\u{1b7}', 658), ('\u{1b8}', 441), + ('\u{1bc}', 445), ('\u{1c4}', 454), ('\u{1c5}', 454), ('\u{1c7}', 457), ('\u{1c8}', 457), + ('\u{1ca}', 460), ('\u{1cb}', 460), ('\u{1cd}', 462), ('\u{1cf}', 464), ('\u{1d1}', 466), + ('\u{1d3}', 468), ('\u{1d5}', 470), ('\u{1d7}', 472), ('\u{1d9}', 474), ('\u{1db}', 476), + ('\u{1de}', 479), ('\u{1e0}', 481), ('\u{1e2}', 483), ('\u{1e4}', 485), ('\u{1e6}', 487), + ('\u{1e8}', 489), ('\u{1ea}', 491), ('\u{1ec}', 493), ('\u{1ee}', 495), ('\u{1f1}', 499), + ('\u{1f2}', 499), ('\u{1f4}', 501), ('\u{1f6}', 405), ('\u{1f7}', 447), ('\u{1f8}', 505), + ('\u{1fa}', 507), ('\u{1fc}', 509), ('\u{1fe}', 511), ('\u{200}', 513), ('\u{202}', 515), + ('\u{204}', 517), ('\u{206}', 519), ('\u{208}', 521), ('\u{20a}', 523), ('\u{20c}', 525), + ('\u{20e}', 527), ('\u{210}', 529), ('\u{212}', 531), ('\u{214}', 533), ('\u{216}', 535), + ('\u{218}', 537), ('\u{21a}', 539), ('\u{21c}', 541), ('\u{21e}', 543), ('\u{220}', 414), + ('\u{222}', 547), ('\u{224}', 549), ('\u{226}', 551), ('\u{228}', 553), ('\u{22a}', 555), + ('\u{22c}', 557), ('\u{22e}', 559), ('\u{230}', 561), ('\u{232}', 563), ('\u{23a}', 11365), + ('\u{23b}', 572), ('\u{23d}', 410), ('\u{23e}', 11366), ('\u{241}', 578), ('\u{243}', 384), + ('\u{244}', 649), ('\u{245}', 652), ('\u{246}', 583), ('\u{248}', 585), ('\u{24a}', 587), + ('\u{24c}', 589), ('\u{24e}', 591), ('\u{370}', 881), ('\u{372}', 883), ('\u{376}', 887), + ('\u{37f}', 1011), ('\u{386}', 940), ('\u{388}', 941), ('\u{389}', 942), ('\u{38a}', 943), + ('\u{38c}', 972), ('\u{38e}', 973), ('\u{38f}', 974), ('\u{391}', 945), ('\u{392}', 946), + ('\u{393}', 947), ('\u{394}', 948), ('\u{395}', 949), ('\u{396}', 950), ('\u{397}', 951), + ('\u{398}', 952), ('\u{399}', 953), ('\u{39a}', 954), ('\u{39b}', 955), ('\u{39c}', 956), + ('\u{39d}', 957), ('\u{39e}', 958), ('\u{39f}', 959), ('\u{3a0}', 960), ('\u{3a1}', 961), + ('\u{3a3}', 963), ('\u{3a4}', 964), ('\u{3a5}', 965), ('\u{3a6}', 966), ('\u{3a7}', 967), + ('\u{3a8}', 968), ('\u{3a9}', 969), ('\u{3aa}', 970), ('\u{3ab}', 971), ('\u{3cf}', 983), + ('\u{3d8}', 985), ('\u{3da}', 987), ('\u{3dc}', 989), ('\u{3de}', 991), ('\u{3e0}', 993), + ('\u{3e2}', 995), ('\u{3e4}', 997), ('\u{3e6}', 999), ('\u{3e8}', 1001), ('\u{3ea}', 1003), + ('\u{3ec}', 1005), ('\u{3ee}', 1007), ('\u{3f4}', 952), ('\u{3f7}', 1016), + ('\u{3f9}', 1010), ('\u{3fa}', 1019), ('\u{3fd}', 891), ('\u{3fe}', 892), ('\u{3ff}', 893), + ('\u{400}', 1104), ('\u{401}', 1105), ('\u{402}', 1106), ('\u{403}', 1107), + ('\u{404}', 1108), ('\u{405}', 1109), ('\u{406}', 1110), ('\u{407}', 1111), + ('\u{408}', 1112), ('\u{409}', 1113), ('\u{40a}', 1114), ('\u{40b}', 1115), + ('\u{40c}', 1116), ('\u{40d}', 1117), ('\u{40e}', 1118), ('\u{40f}', 1119), + ('\u{410}', 1072), ('\u{411}', 1073), ('\u{412}', 1074), ('\u{413}', 1075), + ('\u{414}', 1076), ('\u{415}', 1077), ('\u{416}', 1078), ('\u{417}', 1079), + ('\u{418}', 1080), ('\u{419}', 1081), ('\u{41a}', 1082), ('\u{41b}', 1083), + ('\u{41c}', 1084), ('\u{41d}', 1085), ('\u{41e}', 1086), ('\u{41f}', 1087), + ('\u{420}', 1088), ('\u{421}', 1089), ('\u{422}', 1090), ('\u{423}', 1091), + ('\u{424}', 1092), ('\u{425}', 1093), ('\u{426}', 1094), ('\u{427}', 1095), + ('\u{428}', 1096), ('\u{429}', 1097), ('\u{42a}', 1098), ('\u{42b}', 1099), + ('\u{42c}', 1100), ('\u{42d}', 1101), ('\u{42e}', 1102), ('\u{42f}', 1103), + ('\u{460}', 1121), ('\u{462}', 1123), ('\u{464}', 1125), ('\u{466}', 1127), + ('\u{468}', 1129), ('\u{46a}', 1131), ('\u{46c}', 1133), ('\u{46e}', 1135), + ('\u{470}', 1137), ('\u{472}', 1139), ('\u{474}', 1141), ('\u{476}', 1143), + ('\u{478}', 1145), ('\u{47a}', 1147), ('\u{47c}', 1149), ('\u{47e}', 1151), + ('\u{480}', 1153), ('\u{48a}', 1163), ('\u{48c}', 1165), ('\u{48e}', 1167), + ('\u{490}', 1169), ('\u{492}', 1171), ('\u{494}', 1173), ('\u{496}', 1175), + ('\u{498}', 1177), ('\u{49a}', 1179), ('\u{49c}', 1181), ('\u{49e}', 1183), + ('\u{4a0}', 1185), ('\u{4a2}', 1187), ('\u{4a4}', 1189), ('\u{4a6}', 1191), + ('\u{4a8}', 1193), ('\u{4aa}', 1195), ('\u{4ac}', 1197), ('\u{4ae}', 1199), + ('\u{4b0}', 1201), ('\u{4b2}', 1203), ('\u{4b4}', 1205), ('\u{4b6}', 1207), + ('\u{4b8}', 1209), ('\u{4ba}', 1211), ('\u{4bc}', 1213), ('\u{4be}', 1215), + ('\u{4c0}', 1231), ('\u{4c1}', 1218), ('\u{4c3}', 1220), ('\u{4c5}', 1222), + ('\u{4c7}', 1224), ('\u{4c9}', 1226), ('\u{4cb}', 1228), ('\u{4cd}', 1230), + ('\u{4d0}', 1233), ('\u{4d2}', 1235), ('\u{4d4}', 1237), ('\u{4d6}', 1239), + ('\u{4d8}', 1241), ('\u{4da}', 1243), ('\u{4dc}', 1245), ('\u{4de}', 1247), + ('\u{4e0}', 1249), ('\u{4e2}', 1251), ('\u{4e4}', 1253), ('\u{4e6}', 1255), + ('\u{4e8}', 1257), ('\u{4ea}', 1259), ('\u{4ec}', 1261), ('\u{4ee}', 1263), + ('\u{4f0}', 1265), ('\u{4f2}', 1267), ('\u{4f4}', 1269), ('\u{4f6}', 1271), + ('\u{4f8}', 1273), ('\u{4fa}', 1275), ('\u{4fc}', 1277), ('\u{4fe}', 1279), + ('\u{500}', 1281), ('\u{502}', 1283), ('\u{504}', 1285), ('\u{506}', 1287), + ('\u{508}', 1289), ('\u{50a}', 1291), ('\u{50c}', 1293), ('\u{50e}', 1295), + ('\u{510}', 1297), ('\u{512}', 1299), ('\u{514}', 1301), ('\u{516}', 1303), + ('\u{518}', 1305), ('\u{51a}', 1307), ('\u{51c}', 1309), ('\u{51e}', 1311), + ('\u{520}', 1313), ('\u{522}', 1315), ('\u{524}', 1317), ('\u{526}', 1319), + ('\u{528}', 1321), ('\u{52a}', 1323), ('\u{52c}', 1325), ('\u{52e}', 1327), + ('\u{531}', 1377), ('\u{532}', 1378), ('\u{533}', 1379), ('\u{534}', 1380), + ('\u{535}', 1381), ('\u{536}', 1382), ('\u{537}', 1383), ('\u{538}', 1384), + ('\u{539}', 1385), ('\u{53a}', 1386), ('\u{53b}', 1387), ('\u{53c}', 1388), + ('\u{53d}', 1389), ('\u{53e}', 1390), ('\u{53f}', 1391), ('\u{540}', 1392), + ('\u{541}', 1393), ('\u{542}', 1394), ('\u{543}', 1395), ('\u{544}', 1396), + ('\u{545}', 1397), ('\u{546}', 1398), ('\u{547}', 1399), ('\u{548}', 1400), + ('\u{549}', 1401), ('\u{54a}', 1402), ('\u{54b}', 1403), ('\u{54c}', 1404), + ('\u{54d}', 1405), ('\u{54e}', 1406), ('\u{54f}', 1407), ('\u{550}', 1408), + ('\u{551}', 1409), ('\u{552}', 1410), ('\u{553}', 1411), ('\u{554}', 1412), + ('\u{555}', 1413), ('\u{556}', 1414), ('\u{10a0}', 11520), ('\u{10a1}', 11521), + ('\u{10a2}', 11522), ('\u{10a3}', 11523), ('\u{10a4}', 11524), ('\u{10a5}', 11525), + ('\u{10a6}', 11526), ('\u{10a7}', 11527), ('\u{10a8}', 11528), ('\u{10a9}', 11529), + ('\u{10aa}', 11530), ('\u{10ab}', 11531), ('\u{10ac}', 11532), ('\u{10ad}', 11533), + ('\u{10ae}', 11534), ('\u{10af}', 11535), ('\u{10b0}', 11536), ('\u{10b1}', 11537), + ('\u{10b2}', 11538), ('\u{10b3}', 11539), ('\u{10b4}', 11540), ('\u{10b5}', 11541), + ('\u{10b6}', 11542), ('\u{10b7}', 11543), ('\u{10b8}', 11544), ('\u{10b9}', 11545), + ('\u{10ba}', 11546), ('\u{10bb}', 11547), ('\u{10bc}', 11548), ('\u{10bd}', 11549), + ('\u{10be}', 11550), ('\u{10bf}', 11551), ('\u{10c0}', 11552), ('\u{10c1}', 11553), + ('\u{10c2}', 11554), ('\u{10c3}', 11555), ('\u{10c4}', 11556), ('\u{10c5}', 11557), + ('\u{10c7}', 11559), ('\u{10cd}', 11565), ('\u{13a0}', 43888), ('\u{13a1}', 43889), + ('\u{13a2}', 43890), ('\u{13a3}', 43891), ('\u{13a4}', 43892), ('\u{13a5}', 43893), + ('\u{13a6}', 43894), ('\u{13a7}', 43895), ('\u{13a8}', 43896), ('\u{13a9}', 43897), + ('\u{13aa}', 43898), ('\u{13ab}', 43899), ('\u{13ac}', 43900), ('\u{13ad}', 43901), + ('\u{13ae}', 43902), ('\u{13af}', 43903), ('\u{13b0}', 43904), ('\u{13b1}', 43905), + ('\u{13b2}', 43906), ('\u{13b3}', 43907), ('\u{13b4}', 43908), ('\u{13b5}', 43909), + ('\u{13b6}', 43910), ('\u{13b7}', 43911), ('\u{13b8}', 43912), ('\u{13b9}', 43913), + ('\u{13ba}', 43914), ('\u{13bb}', 43915), ('\u{13bc}', 43916), ('\u{13bd}', 43917), + ('\u{13be}', 43918), ('\u{13bf}', 43919), ('\u{13c0}', 43920), ('\u{13c1}', 43921), + ('\u{13c2}', 43922), ('\u{13c3}', 43923), ('\u{13c4}', 43924), ('\u{13c5}', 43925), + ('\u{13c6}', 43926), ('\u{13c7}', 43927), ('\u{13c8}', 43928), ('\u{13c9}', 43929), + ('\u{13ca}', 43930), ('\u{13cb}', 43931), ('\u{13cc}', 43932), ('\u{13cd}', 43933), + ('\u{13ce}', 43934), ('\u{13cf}', 43935), ('\u{13d0}', 43936), ('\u{13d1}', 43937), + ('\u{13d2}', 43938), ('\u{13d3}', 43939), ('\u{13d4}', 43940), ('\u{13d5}', 43941), + ('\u{13d6}', 43942), ('\u{13d7}', 43943), ('\u{13d8}', 43944), ('\u{13d9}', 43945), + ('\u{13da}', 43946), ('\u{13db}', 43947), ('\u{13dc}', 43948), ('\u{13dd}', 43949), + ('\u{13de}', 43950), ('\u{13df}', 43951), ('\u{13e0}', 43952), ('\u{13e1}', 43953), + ('\u{13e2}', 43954), ('\u{13e3}', 43955), ('\u{13e4}', 43956), ('\u{13e5}', 43957), + ('\u{13e6}', 43958), ('\u{13e7}', 43959), ('\u{13e8}', 43960), ('\u{13e9}', 43961), + ('\u{13ea}', 43962), ('\u{13eb}', 43963), ('\u{13ec}', 43964), ('\u{13ed}', 43965), + ('\u{13ee}', 43966), ('\u{13ef}', 43967), ('\u{13f0}', 5112), ('\u{13f1}', 5113), + ('\u{13f2}', 5114), ('\u{13f3}', 5115), ('\u{13f4}', 5116), ('\u{13f5}', 5117), + ('\u{1c89}', 7306), ('\u{1c90}', 4304), ('\u{1c91}', 4305), ('\u{1c92}', 4306), + ('\u{1c93}', 4307), ('\u{1c94}', 4308), ('\u{1c95}', 4309), ('\u{1c96}', 4310), + ('\u{1c97}', 4311), ('\u{1c98}', 4312), ('\u{1c99}', 4313), ('\u{1c9a}', 4314), + ('\u{1c9b}', 4315), ('\u{1c9c}', 4316), ('\u{1c9d}', 4317), ('\u{1c9e}', 4318), + ('\u{1c9f}', 4319), ('\u{1ca0}', 4320), ('\u{1ca1}', 4321), ('\u{1ca2}', 4322), + ('\u{1ca3}', 4323), ('\u{1ca4}', 4324), ('\u{1ca5}', 4325), ('\u{1ca6}', 4326), + ('\u{1ca7}', 4327), ('\u{1ca8}', 4328), ('\u{1ca9}', 4329), ('\u{1caa}', 4330), + ('\u{1cab}', 4331), ('\u{1cac}', 4332), ('\u{1cad}', 4333), ('\u{1cae}', 4334), + ('\u{1caf}', 4335), ('\u{1cb0}', 4336), ('\u{1cb1}', 4337), ('\u{1cb2}', 4338), + ('\u{1cb3}', 4339), ('\u{1cb4}', 4340), ('\u{1cb5}', 4341), ('\u{1cb6}', 4342), + ('\u{1cb7}', 4343), ('\u{1cb8}', 4344), ('\u{1cb9}', 4345), ('\u{1cba}', 4346), + ('\u{1cbd}', 4349), ('\u{1cbe}', 4350), ('\u{1cbf}', 4351), ('\u{1e00}', 7681), + ('\u{1e02}', 7683), ('\u{1e04}', 7685), ('\u{1e06}', 7687), ('\u{1e08}', 7689), + ('\u{1e0a}', 7691), ('\u{1e0c}', 7693), ('\u{1e0e}', 7695), ('\u{1e10}', 7697), + ('\u{1e12}', 7699), ('\u{1e14}', 7701), ('\u{1e16}', 7703), ('\u{1e18}', 7705), + ('\u{1e1a}', 7707), ('\u{1e1c}', 7709), ('\u{1e1e}', 7711), ('\u{1e20}', 7713), + ('\u{1e22}', 7715), ('\u{1e24}', 7717), ('\u{1e26}', 7719), ('\u{1e28}', 7721), + ('\u{1e2a}', 7723), ('\u{1e2c}', 7725), ('\u{1e2e}', 7727), ('\u{1e30}', 7729), + ('\u{1e32}', 7731), ('\u{1e34}', 7733), ('\u{1e36}', 7735), ('\u{1e38}', 7737), + ('\u{1e3a}', 7739), ('\u{1e3c}', 7741), ('\u{1e3e}', 7743), ('\u{1e40}', 7745), + ('\u{1e42}', 7747), ('\u{1e44}', 7749), ('\u{1e46}', 7751), ('\u{1e48}', 7753), + ('\u{1e4a}', 7755), ('\u{1e4c}', 7757), ('\u{1e4e}', 7759), ('\u{1e50}', 7761), + ('\u{1e52}', 7763), ('\u{1e54}', 7765), ('\u{1e56}', 7767), ('\u{1e58}', 7769), + ('\u{1e5a}', 7771), ('\u{1e5c}', 7773), ('\u{1e5e}', 7775), ('\u{1e60}', 7777), + ('\u{1e62}', 7779), ('\u{1e64}', 7781), ('\u{1e66}', 7783), ('\u{1e68}', 7785), + ('\u{1e6a}', 7787), ('\u{1e6c}', 7789), ('\u{1e6e}', 7791), ('\u{1e70}', 7793), + ('\u{1e72}', 7795), ('\u{1e74}', 7797), ('\u{1e76}', 7799), ('\u{1e78}', 7801), + ('\u{1e7a}', 7803), ('\u{1e7c}', 7805), ('\u{1e7e}', 7807), ('\u{1e80}', 7809), + ('\u{1e82}', 7811), ('\u{1e84}', 7813), ('\u{1e86}', 7815), ('\u{1e88}', 7817), + ('\u{1e8a}', 7819), ('\u{1e8c}', 7821), ('\u{1e8e}', 7823), ('\u{1e90}', 7825), + ('\u{1e92}', 7827), ('\u{1e94}', 7829), ('\u{1e9e}', 223), ('\u{1ea0}', 7841), + ('\u{1ea2}', 7843), ('\u{1ea4}', 7845), ('\u{1ea6}', 7847), ('\u{1ea8}', 7849), + ('\u{1eaa}', 7851), ('\u{1eac}', 7853), ('\u{1eae}', 7855), ('\u{1eb0}', 7857), + ('\u{1eb2}', 7859), ('\u{1eb4}', 7861), ('\u{1eb6}', 7863), ('\u{1eb8}', 7865), + ('\u{1eba}', 7867), ('\u{1ebc}', 7869), ('\u{1ebe}', 7871), ('\u{1ec0}', 7873), + ('\u{1ec2}', 7875), ('\u{1ec4}', 7877), ('\u{1ec6}', 7879), ('\u{1ec8}', 7881), + ('\u{1eca}', 7883), ('\u{1ecc}', 7885), ('\u{1ece}', 7887), ('\u{1ed0}', 7889), + ('\u{1ed2}', 7891), ('\u{1ed4}', 7893), ('\u{1ed6}', 7895), ('\u{1ed8}', 7897), + ('\u{1eda}', 7899), ('\u{1edc}', 7901), ('\u{1ede}', 7903), ('\u{1ee0}', 7905), + ('\u{1ee2}', 7907), ('\u{1ee4}', 7909), ('\u{1ee6}', 7911), ('\u{1ee8}', 7913), + ('\u{1eea}', 7915), ('\u{1eec}', 7917), ('\u{1eee}', 7919), ('\u{1ef0}', 7921), + ('\u{1ef2}', 7923), ('\u{1ef4}', 7925), ('\u{1ef6}', 7927), ('\u{1ef8}', 7929), + ('\u{1efa}', 7931), ('\u{1efc}', 7933), ('\u{1efe}', 7935), ('\u{1f08}', 7936), + ('\u{1f09}', 7937), ('\u{1f0a}', 7938), ('\u{1f0b}', 7939), ('\u{1f0c}', 7940), + ('\u{1f0d}', 7941), ('\u{1f0e}', 7942), ('\u{1f0f}', 7943), ('\u{1f18}', 7952), + ('\u{1f19}', 7953), ('\u{1f1a}', 7954), ('\u{1f1b}', 7955), ('\u{1f1c}', 7956), + ('\u{1f1d}', 7957), ('\u{1f28}', 7968), ('\u{1f29}', 7969), ('\u{1f2a}', 7970), + ('\u{1f2b}', 7971), ('\u{1f2c}', 7972), ('\u{1f2d}', 7973), ('\u{1f2e}', 7974), + ('\u{1f2f}', 7975), ('\u{1f38}', 7984), ('\u{1f39}', 7985), ('\u{1f3a}', 7986), + ('\u{1f3b}', 7987), ('\u{1f3c}', 7988), ('\u{1f3d}', 7989), ('\u{1f3e}', 7990), + ('\u{1f3f}', 7991), ('\u{1f48}', 8000), ('\u{1f49}', 8001), ('\u{1f4a}', 8002), + ('\u{1f4b}', 8003), ('\u{1f4c}', 8004), ('\u{1f4d}', 8005), ('\u{1f59}', 8017), + ('\u{1f5b}', 8019), ('\u{1f5d}', 8021), ('\u{1f5f}', 8023), ('\u{1f68}', 8032), + ('\u{1f69}', 8033), ('\u{1f6a}', 8034), ('\u{1f6b}', 8035), ('\u{1f6c}', 8036), + ('\u{1f6d}', 8037), ('\u{1f6e}', 8038), ('\u{1f6f}', 8039), ('\u{1f88}', 8064), + ('\u{1f89}', 8065), ('\u{1f8a}', 8066), ('\u{1f8b}', 8067), ('\u{1f8c}', 8068), + ('\u{1f8d}', 8069), ('\u{1f8e}', 8070), ('\u{1f8f}', 8071), ('\u{1f98}', 8080), + ('\u{1f99}', 8081), ('\u{1f9a}', 8082), ('\u{1f9b}', 8083), ('\u{1f9c}', 8084), + ('\u{1f9d}', 8085), ('\u{1f9e}', 8086), ('\u{1f9f}', 8087), ('\u{1fa8}', 8096), + ('\u{1fa9}', 8097), ('\u{1faa}', 8098), ('\u{1fab}', 8099), ('\u{1fac}', 8100), + ('\u{1fad}', 8101), ('\u{1fae}', 8102), ('\u{1faf}', 8103), ('\u{1fb8}', 8112), + ('\u{1fb9}', 8113), ('\u{1fba}', 8048), ('\u{1fbb}', 8049), ('\u{1fbc}', 8115), + ('\u{1fc8}', 8050), ('\u{1fc9}', 8051), ('\u{1fca}', 8052), ('\u{1fcb}', 8053), + ('\u{1fcc}', 8131), ('\u{1fd8}', 8144), ('\u{1fd9}', 8145), ('\u{1fda}', 8054), + ('\u{1fdb}', 8055), ('\u{1fe8}', 8160), ('\u{1fe9}', 8161), ('\u{1fea}', 8058), + ('\u{1feb}', 8059), ('\u{1fec}', 8165), ('\u{1ff8}', 8056), ('\u{1ff9}', 8057), + ('\u{1ffa}', 8060), ('\u{1ffb}', 8061), ('\u{1ffc}', 8179), ('\u{2126}', 969), + ('\u{212a}', 107), ('\u{212b}', 229), ('\u{2132}', 8526), ('\u{2160}', 8560), + ('\u{2161}', 8561), ('\u{2162}', 8562), ('\u{2163}', 8563), ('\u{2164}', 8564), + ('\u{2165}', 8565), ('\u{2166}', 8566), ('\u{2167}', 8567), ('\u{2168}', 8568), + ('\u{2169}', 8569), ('\u{216a}', 8570), ('\u{216b}', 8571), ('\u{216c}', 8572), + ('\u{216d}', 8573), ('\u{216e}', 8574), ('\u{216f}', 8575), ('\u{2183}', 8580), + ('\u{24b6}', 9424), ('\u{24b7}', 9425), ('\u{24b8}', 9426), ('\u{24b9}', 9427), + ('\u{24ba}', 9428), ('\u{24bb}', 9429), ('\u{24bc}', 9430), ('\u{24bd}', 9431), + ('\u{24be}', 9432), ('\u{24bf}', 9433), ('\u{24c0}', 9434), ('\u{24c1}', 9435), + ('\u{24c2}', 9436), ('\u{24c3}', 9437), ('\u{24c4}', 9438), ('\u{24c5}', 9439), + ('\u{24c6}', 9440), ('\u{24c7}', 9441), ('\u{24c8}', 9442), ('\u{24c9}', 9443), + ('\u{24ca}', 9444), ('\u{24cb}', 9445), ('\u{24cc}', 9446), ('\u{24cd}', 9447), + ('\u{24ce}', 9448), ('\u{24cf}', 9449), ('\u{2c00}', 11312), ('\u{2c01}', 11313), + ('\u{2c02}', 11314), ('\u{2c03}', 11315), ('\u{2c04}', 11316), ('\u{2c05}', 11317), + ('\u{2c06}', 11318), ('\u{2c07}', 11319), ('\u{2c08}', 11320), ('\u{2c09}', 11321), + ('\u{2c0a}', 11322), ('\u{2c0b}', 11323), ('\u{2c0c}', 11324), ('\u{2c0d}', 11325), + ('\u{2c0e}', 11326), ('\u{2c0f}', 11327), ('\u{2c10}', 11328), ('\u{2c11}', 11329), + ('\u{2c12}', 11330), ('\u{2c13}', 11331), ('\u{2c14}', 11332), ('\u{2c15}', 11333), + ('\u{2c16}', 11334), ('\u{2c17}', 11335), ('\u{2c18}', 11336), ('\u{2c19}', 11337), + ('\u{2c1a}', 11338), ('\u{2c1b}', 11339), ('\u{2c1c}', 11340), ('\u{2c1d}', 11341), + ('\u{2c1e}', 11342), ('\u{2c1f}', 11343), ('\u{2c20}', 11344), ('\u{2c21}', 11345), + ('\u{2c22}', 11346), ('\u{2c23}', 11347), ('\u{2c24}', 11348), ('\u{2c25}', 11349), + ('\u{2c26}', 11350), ('\u{2c27}', 11351), ('\u{2c28}', 11352), ('\u{2c29}', 11353), + ('\u{2c2a}', 11354), ('\u{2c2b}', 11355), ('\u{2c2c}', 11356), ('\u{2c2d}', 11357), + ('\u{2c2e}', 11358), ('\u{2c2f}', 11359), ('\u{2c60}', 11361), ('\u{2c62}', 619), + ('\u{2c63}', 7549), ('\u{2c64}', 637), ('\u{2c67}', 11368), ('\u{2c69}', 11370), + ('\u{2c6b}', 11372), ('\u{2c6d}', 593), ('\u{2c6e}', 625), ('\u{2c6f}', 592), + ('\u{2c70}', 594), ('\u{2c72}', 11379), ('\u{2c75}', 11382), ('\u{2c7e}', 575), + ('\u{2c7f}', 576), ('\u{2c80}', 11393), ('\u{2c82}', 11395), ('\u{2c84}', 11397), + ('\u{2c86}', 11399), ('\u{2c88}', 11401), ('\u{2c8a}', 11403), ('\u{2c8c}', 11405), + ('\u{2c8e}', 11407), ('\u{2c90}', 11409), ('\u{2c92}', 11411), ('\u{2c94}', 11413), + ('\u{2c96}', 11415), ('\u{2c98}', 11417), ('\u{2c9a}', 11419), ('\u{2c9c}', 11421), + ('\u{2c9e}', 11423), ('\u{2ca0}', 11425), ('\u{2ca2}', 11427), ('\u{2ca4}', 11429), + ('\u{2ca6}', 11431), ('\u{2ca8}', 11433), ('\u{2caa}', 11435), ('\u{2cac}', 11437), + ('\u{2cae}', 11439), ('\u{2cb0}', 11441), ('\u{2cb2}', 11443), ('\u{2cb4}', 11445), + ('\u{2cb6}', 11447), ('\u{2cb8}', 11449), ('\u{2cba}', 11451), ('\u{2cbc}', 11453), + ('\u{2cbe}', 11455), ('\u{2cc0}', 11457), ('\u{2cc2}', 11459), ('\u{2cc4}', 11461), + ('\u{2cc6}', 11463), ('\u{2cc8}', 11465), ('\u{2cca}', 11467), ('\u{2ccc}', 11469), + ('\u{2cce}', 11471), ('\u{2cd0}', 11473), ('\u{2cd2}', 11475), ('\u{2cd4}', 11477), + ('\u{2cd6}', 11479), ('\u{2cd8}', 11481), ('\u{2cda}', 11483), ('\u{2cdc}', 11485), + ('\u{2cde}', 11487), ('\u{2ce0}', 11489), ('\u{2ce2}', 11491), ('\u{2ceb}', 11500), + ('\u{2ced}', 11502), ('\u{2cf2}', 11507), ('\u{a640}', 42561), ('\u{a642}', 42563), + ('\u{a644}', 42565), ('\u{a646}', 42567), ('\u{a648}', 42569), ('\u{a64a}', 42571), + ('\u{a64c}', 42573), ('\u{a64e}', 42575), ('\u{a650}', 42577), ('\u{a652}', 42579), + ('\u{a654}', 42581), ('\u{a656}', 42583), ('\u{a658}', 42585), ('\u{a65a}', 42587), + ('\u{a65c}', 42589), ('\u{a65e}', 42591), ('\u{a660}', 42593), ('\u{a662}', 42595), + ('\u{a664}', 42597), ('\u{a666}', 42599), ('\u{a668}', 42601), ('\u{a66a}', 42603), + ('\u{a66c}', 42605), ('\u{a680}', 42625), ('\u{a682}', 42627), ('\u{a684}', 42629), + ('\u{a686}', 42631), ('\u{a688}', 42633), ('\u{a68a}', 42635), ('\u{a68c}', 42637), + ('\u{a68e}', 42639), ('\u{a690}', 42641), ('\u{a692}', 42643), ('\u{a694}', 42645), + ('\u{a696}', 42647), ('\u{a698}', 42649), ('\u{a69a}', 42651), ('\u{a722}', 42787), + ('\u{a724}', 42789), ('\u{a726}', 42791), ('\u{a728}', 42793), ('\u{a72a}', 42795), + ('\u{a72c}', 42797), ('\u{a72e}', 42799), ('\u{a732}', 42803), ('\u{a734}', 42805), + ('\u{a736}', 42807), ('\u{a738}', 42809), ('\u{a73a}', 42811), ('\u{a73c}', 42813), + ('\u{a73e}', 42815), ('\u{a740}', 42817), ('\u{a742}', 42819), ('\u{a744}', 42821), + ('\u{a746}', 42823), ('\u{a748}', 42825), ('\u{a74a}', 42827), ('\u{a74c}', 42829), + ('\u{a74e}', 42831), ('\u{a750}', 42833), ('\u{a752}', 42835), ('\u{a754}', 42837), + ('\u{a756}', 42839), ('\u{a758}', 42841), ('\u{a75a}', 42843), ('\u{a75c}', 42845), + ('\u{a75e}', 42847), ('\u{a760}', 42849), ('\u{a762}', 42851), ('\u{a764}', 42853), + ('\u{a766}', 42855), ('\u{a768}', 42857), ('\u{a76a}', 42859), ('\u{a76c}', 42861), + ('\u{a76e}', 42863), ('\u{a779}', 42874), ('\u{a77b}', 42876), ('\u{a77d}', 7545), + ('\u{a77e}', 42879), ('\u{a780}', 42881), ('\u{a782}', 42883), ('\u{a784}', 42885), + ('\u{a786}', 42887), ('\u{a78b}', 42892), ('\u{a78d}', 613), ('\u{a790}', 42897), + ('\u{a792}', 42899), ('\u{a796}', 42903), ('\u{a798}', 42905), ('\u{a79a}', 42907), + ('\u{a79c}', 42909), ('\u{a79e}', 42911), ('\u{a7a0}', 42913), ('\u{a7a2}', 42915), + ('\u{a7a4}', 42917), ('\u{a7a6}', 42919), ('\u{a7a8}', 42921), ('\u{a7aa}', 614), + ('\u{a7ab}', 604), ('\u{a7ac}', 609), ('\u{a7ad}', 620), ('\u{a7ae}', 618), + ('\u{a7b0}', 670), ('\u{a7b1}', 647), ('\u{a7b2}', 669), ('\u{a7b3}', 43859), + ('\u{a7b4}', 42933), ('\u{a7b6}', 42935), ('\u{a7b8}', 42937), ('\u{a7ba}', 42939), + ('\u{a7bc}', 42941), ('\u{a7be}', 42943), ('\u{a7c0}', 42945), ('\u{a7c2}', 42947), + ('\u{a7c4}', 42900), ('\u{a7c5}', 642), ('\u{a7c6}', 7566), ('\u{a7c7}', 42952), + ('\u{a7c9}', 42954), ('\u{a7cb}', 612), ('\u{a7cc}', 42957), ('\u{a7d0}', 42961), + ('\u{a7d6}', 42967), ('\u{a7d8}', 42969), ('\u{a7da}', 42971), ('\u{a7dc}', 411), + ('\u{a7f5}', 42998), ('\u{ff21}', 65345), ('\u{ff22}', 65346), ('\u{ff23}', 65347), + ('\u{ff24}', 65348), ('\u{ff25}', 65349), ('\u{ff26}', 65350), ('\u{ff27}', 65351), + ('\u{ff28}', 65352), ('\u{ff29}', 65353), ('\u{ff2a}', 65354), ('\u{ff2b}', 65355), + ('\u{ff2c}', 65356), ('\u{ff2d}', 65357), ('\u{ff2e}', 65358), ('\u{ff2f}', 65359), + ('\u{ff30}', 65360), ('\u{ff31}', 65361), ('\u{ff32}', 65362), ('\u{ff33}', 65363), + ('\u{ff34}', 65364), ('\u{ff35}', 65365), ('\u{ff36}', 65366), ('\u{ff37}', 65367), + ('\u{ff38}', 65368), ('\u{ff39}', 65369), ('\u{ff3a}', 65370), ('\u{10400}', 66600), + ('\u{10401}', 66601), ('\u{10402}', 66602), ('\u{10403}', 66603), ('\u{10404}', 66604), + ('\u{10405}', 66605), ('\u{10406}', 66606), ('\u{10407}', 66607), ('\u{10408}', 66608), + ('\u{10409}', 66609), ('\u{1040a}', 66610), ('\u{1040b}', 66611), ('\u{1040c}', 66612), + ('\u{1040d}', 66613), ('\u{1040e}', 66614), ('\u{1040f}', 66615), ('\u{10410}', 66616), + ('\u{10411}', 66617), ('\u{10412}', 66618), ('\u{10413}', 66619), ('\u{10414}', 66620), + ('\u{10415}', 66621), ('\u{10416}', 66622), ('\u{10417}', 66623), ('\u{10418}', 66624), + ('\u{10419}', 66625), ('\u{1041a}', 66626), ('\u{1041b}', 66627), ('\u{1041c}', 66628), + ('\u{1041d}', 66629), ('\u{1041e}', 66630), ('\u{1041f}', 66631), ('\u{10420}', 66632), + ('\u{10421}', 66633), ('\u{10422}', 66634), ('\u{10423}', 66635), ('\u{10424}', 66636), + ('\u{10425}', 66637), ('\u{10426}', 66638), ('\u{10427}', 66639), ('\u{104b0}', 66776), + ('\u{104b1}', 66777), ('\u{104b2}', 66778), ('\u{104b3}', 66779), ('\u{104b4}', 66780), + ('\u{104b5}', 66781), ('\u{104b6}', 66782), ('\u{104b7}', 66783), ('\u{104b8}', 66784), + ('\u{104b9}', 66785), ('\u{104ba}', 66786), ('\u{104bb}', 66787), ('\u{104bc}', 66788), + ('\u{104bd}', 66789), ('\u{104be}', 66790), ('\u{104bf}', 66791), ('\u{104c0}', 66792), + ('\u{104c1}', 66793), ('\u{104c2}', 66794), ('\u{104c3}', 66795), ('\u{104c4}', 66796), + ('\u{104c5}', 66797), ('\u{104c6}', 66798), ('\u{104c7}', 66799), ('\u{104c8}', 66800), + ('\u{104c9}', 66801), ('\u{104ca}', 66802), ('\u{104cb}', 66803), ('\u{104cc}', 66804), + ('\u{104cd}', 66805), ('\u{104ce}', 66806), ('\u{104cf}', 66807), ('\u{104d0}', 66808), + ('\u{104d1}', 66809), ('\u{104d2}', 66810), ('\u{104d3}', 66811), ('\u{10570}', 66967), + ('\u{10571}', 66968), ('\u{10572}', 66969), ('\u{10573}', 66970), ('\u{10574}', 66971), + ('\u{10575}', 66972), ('\u{10576}', 66973), ('\u{10577}', 66974), ('\u{10578}', 66975), + ('\u{10579}', 66976), ('\u{1057a}', 66977), ('\u{1057c}', 66979), ('\u{1057d}', 66980), + ('\u{1057e}', 66981), ('\u{1057f}', 66982), ('\u{10580}', 66983), ('\u{10581}', 66984), + ('\u{10582}', 66985), ('\u{10583}', 66986), ('\u{10584}', 66987), ('\u{10585}', 66988), + ('\u{10586}', 66989), ('\u{10587}', 66990), ('\u{10588}', 66991), ('\u{10589}', 66992), + ('\u{1058a}', 66993), ('\u{1058c}', 66995), ('\u{1058d}', 66996), ('\u{1058e}', 66997), + ('\u{1058f}', 66998), ('\u{10590}', 66999), ('\u{10591}', 67000), ('\u{10592}', 67001), + ('\u{10594}', 67003), ('\u{10595}', 67004), ('\u{10c80}', 68800), ('\u{10c81}', 68801), + ('\u{10c82}', 68802), ('\u{10c83}', 68803), ('\u{10c84}', 68804), ('\u{10c85}', 68805), + ('\u{10c86}', 68806), ('\u{10c87}', 68807), ('\u{10c88}', 68808), ('\u{10c89}', 68809), + ('\u{10c8a}', 68810), ('\u{10c8b}', 68811), ('\u{10c8c}', 68812), ('\u{10c8d}', 68813), + ('\u{10c8e}', 68814), ('\u{10c8f}', 68815), ('\u{10c90}', 68816), ('\u{10c91}', 68817), + ('\u{10c92}', 68818), ('\u{10c93}', 68819), ('\u{10c94}', 68820), ('\u{10c95}', 68821), + ('\u{10c96}', 68822), ('\u{10c97}', 68823), ('\u{10c98}', 68824), ('\u{10c99}', 68825), + ('\u{10c9a}', 68826), ('\u{10c9b}', 68827), ('\u{10c9c}', 68828), ('\u{10c9d}', 68829), + ('\u{10c9e}', 68830), ('\u{10c9f}', 68831), ('\u{10ca0}', 68832), ('\u{10ca1}', 68833), + ('\u{10ca2}', 68834), ('\u{10ca3}', 68835), ('\u{10ca4}', 68836), ('\u{10ca5}', 68837), + ('\u{10ca6}', 68838), ('\u{10ca7}', 68839), ('\u{10ca8}', 68840), ('\u{10ca9}', 68841), + ('\u{10caa}', 68842), ('\u{10cab}', 68843), ('\u{10cac}', 68844), ('\u{10cad}', 68845), + ('\u{10cae}', 68846), ('\u{10caf}', 68847), ('\u{10cb0}', 68848), ('\u{10cb1}', 68849), + ('\u{10cb2}', 68850), ('\u{10d50}', 68976), ('\u{10d51}', 68977), ('\u{10d52}', 68978), + ('\u{10d53}', 68979), ('\u{10d54}', 68980), ('\u{10d55}', 68981), ('\u{10d56}', 68982), + ('\u{10d57}', 68983), ('\u{10d58}', 68984), ('\u{10d59}', 68985), ('\u{10d5a}', 68986), + ('\u{10d5b}', 68987), ('\u{10d5c}', 68988), ('\u{10d5d}', 68989), ('\u{10d5e}', 68990), + ('\u{10d5f}', 68991), ('\u{10d60}', 68992), ('\u{10d61}', 68993), ('\u{10d62}', 68994), + ('\u{10d63}', 68995), ('\u{10d64}', 68996), ('\u{10d65}', 68997), ('\u{118a0}', 71872), + ('\u{118a1}', 71873), ('\u{118a2}', 71874), ('\u{118a3}', 71875), ('\u{118a4}', 71876), + ('\u{118a5}', 71877), ('\u{118a6}', 71878), ('\u{118a7}', 71879), ('\u{118a8}', 71880), + ('\u{118a9}', 71881), ('\u{118aa}', 71882), ('\u{118ab}', 71883), ('\u{118ac}', 71884), + ('\u{118ad}', 71885), ('\u{118ae}', 71886), ('\u{118af}', 71887), ('\u{118b0}', 71888), + ('\u{118b1}', 71889), ('\u{118b2}', 71890), ('\u{118b3}', 71891), ('\u{118b4}', 71892), + ('\u{118b5}', 71893), ('\u{118b6}', 71894), ('\u{118b7}', 71895), ('\u{118b8}', 71896), + ('\u{118b9}', 71897), ('\u{118ba}', 71898), ('\u{118bb}', 71899), ('\u{118bc}', 71900), + ('\u{118bd}', 71901), ('\u{118be}', 71902), ('\u{118bf}', 71903), ('\u{16e40}', 93792), + ('\u{16e41}', 93793), ('\u{16e42}', 93794), ('\u{16e43}', 93795), ('\u{16e44}', 93796), + ('\u{16e45}', 93797), ('\u{16e46}', 93798), ('\u{16e47}', 93799), ('\u{16e48}', 93800), + ('\u{16e49}', 93801), ('\u{16e4a}', 93802), ('\u{16e4b}', 93803), ('\u{16e4c}', 93804), + ('\u{16e4d}', 93805), ('\u{16e4e}', 93806), ('\u{16e4f}', 93807), ('\u{16e50}', 93808), + ('\u{16e51}', 93809), ('\u{16e52}', 93810), ('\u{16e53}', 93811), ('\u{16e54}', 93812), + ('\u{16e55}', 93813), ('\u{16e56}', 93814), ('\u{16e57}', 93815), ('\u{16e58}', 93816), + ('\u{16e59}', 93817), ('\u{16e5a}', 93818), ('\u{16e5b}', 93819), ('\u{16e5c}', 93820), + ('\u{16e5d}', 93821), ('\u{16e5e}', 93822), ('\u{16e5f}', 93823), ('\u{1e900}', 125218), + ('\u{1e901}', 125219), ('\u{1e902}', 125220), ('\u{1e903}', 125221), ('\u{1e904}', 125222), + ('\u{1e905}', 125223), ('\u{1e906}', 125224), ('\u{1e907}', 125225), ('\u{1e908}', 125226), + ('\u{1e909}', 125227), ('\u{1e90a}', 125228), ('\u{1e90b}', 125229), ('\u{1e90c}', 125230), + ('\u{1e90d}', 125231), ('\u{1e90e}', 125232), ('\u{1e90f}', 125233), ('\u{1e910}', 125234), + ('\u{1e911}', 125235), ('\u{1e912}', 125236), ('\u{1e913}', 125237), ('\u{1e914}', 125238), + ('\u{1e915}', 125239), ('\u{1e916}', 125240), ('\u{1e917}', 125241), ('\u{1e918}', 125242), + ('\u{1e919}', 125243), ('\u{1e91a}', 125244), ('\u{1e91b}', 125245), ('\u{1e91c}', 125246), + ('\u{1e91d}', 125247), ('\u{1e91e}', 125248), ('\u{1e91f}', 125249), ('\u{1e920}', 125250), + ('\u{1e921}', 125251), + ]; + + static LOWERCASE_TABLE_MULTI: &[[char; 3]] = &[ + ['i', '\u{307}', '\u{0}'], + ]; + + static UPPERCASE_TABLE: &[(char, u32)] = &[ + ('\u{b5}', 924), ('\u{df}', 4194304), ('\u{e0}', 192), ('\u{e1}', 193), ('\u{e2}', 194), + ('\u{e3}', 195), ('\u{e4}', 196), ('\u{e5}', 197), ('\u{e6}', 198), ('\u{e7}', 199), + ('\u{e8}', 200), ('\u{e9}', 201), ('\u{ea}', 202), ('\u{eb}', 203), ('\u{ec}', 204), + ('\u{ed}', 205), ('\u{ee}', 206), ('\u{ef}', 207), ('\u{f0}', 208), ('\u{f1}', 209), + ('\u{f2}', 210), ('\u{f3}', 211), ('\u{f4}', 212), ('\u{f5}', 213), ('\u{f6}', 214), + ('\u{f8}', 216), ('\u{f9}', 217), ('\u{fa}', 218), ('\u{fb}', 219), ('\u{fc}', 220), + ('\u{fd}', 221), ('\u{fe}', 222), ('\u{ff}', 376), ('\u{101}', 256), ('\u{103}', 258), + ('\u{105}', 260), ('\u{107}', 262), ('\u{109}', 264), ('\u{10b}', 266), ('\u{10d}', 268), + ('\u{10f}', 270), ('\u{111}', 272), ('\u{113}', 274), ('\u{115}', 276), ('\u{117}', 278), + ('\u{119}', 280), ('\u{11b}', 282), ('\u{11d}', 284), ('\u{11f}', 286), ('\u{121}', 288), + ('\u{123}', 290), ('\u{125}', 292), ('\u{127}', 294), ('\u{129}', 296), ('\u{12b}', 298), + ('\u{12d}', 300), ('\u{12f}', 302), ('\u{131}', 73), ('\u{133}', 306), ('\u{135}', 308), + ('\u{137}', 310), ('\u{13a}', 313), ('\u{13c}', 315), ('\u{13e}', 317), ('\u{140}', 319), + ('\u{142}', 321), ('\u{144}', 323), ('\u{146}', 325), ('\u{148}', 327), + ('\u{149}', 4194305), ('\u{14b}', 330), ('\u{14d}', 332), ('\u{14f}', 334), + ('\u{151}', 336), ('\u{153}', 338), ('\u{155}', 340), ('\u{157}', 342), ('\u{159}', 344), + ('\u{15b}', 346), ('\u{15d}', 348), ('\u{15f}', 350), ('\u{161}', 352), ('\u{163}', 354), + ('\u{165}', 356), ('\u{167}', 358), ('\u{169}', 360), ('\u{16b}', 362), ('\u{16d}', 364), + ('\u{16f}', 366), ('\u{171}', 368), ('\u{173}', 370), ('\u{175}', 372), ('\u{177}', 374), + ('\u{17a}', 377), ('\u{17c}', 379), ('\u{17e}', 381), ('\u{17f}', 83), ('\u{180}', 579), + ('\u{183}', 386), ('\u{185}', 388), ('\u{188}', 391), ('\u{18c}', 395), ('\u{192}', 401), + ('\u{195}', 502), ('\u{199}', 408), ('\u{19a}', 573), ('\u{19b}', 42972), ('\u{19e}', 544), + ('\u{1a1}', 416), ('\u{1a3}', 418), ('\u{1a5}', 420), ('\u{1a8}', 423), ('\u{1ad}', 428), + ('\u{1b0}', 431), ('\u{1b4}', 435), ('\u{1b6}', 437), ('\u{1b9}', 440), ('\u{1bd}', 444), + ('\u{1bf}', 503), ('\u{1c5}', 452), ('\u{1c6}', 452), ('\u{1c8}', 455), ('\u{1c9}', 455), + ('\u{1cb}', 458), ('\u{1cc}', 458), ('\u{1ce}', 461), ('\u{1d0}', 463), ('\u{1d2}', 465), + ('\u{1d4}', 467), ('\u{1d6}', 469), ('\u{1d8}', 471), ('\u{1da}', 473), ('\u{1dc}', 475), + ('\u{1dd}', 398), ('\u{1df}', 478), ('\u{1e1}', 480), ('\u{1e3}', 482), ('\u{1e5}', 484), + ('\u{1e7}', 486), ('\u{1e9}', 488), ('\u{1eb}', 490), ('\u{1ed}', 492), ('\u{1ef}', 494), + ('\u{1f0}', 4194306), ('\u{1f2}', 497), ('\u{1f3}', 497), ('\u{1f5}', 500), + ('\u{1f9}', 504), ('\u{1fb}', 506), ('\u{1fd}', 508), ('\u{1ff}', 510), ('\u{201}', 512), + ('\u{203}', 514), ('\u{205}', 516), ('\u{207}', 518), ('\u{209}', 520), ('\u{20b}', 522), + ('\u{20d}', 524), ('\u{20f}', 526), ('\u{211}', 528), ('\u{213}', 530), ('\u{215}', 532), + ('\u{217}', 534), ('\u{219}', 536), ('\u{21b}', 538), ('\u{21d}', 540), ('\u{21f}', 542), + ('\u{223}', 546), ('\u{225}', 548), ('\u{227}', 550), ('\u{229}', 552), ('\u{22b}', 554), + ('\u{22d}', 556), ('\u{22f}', 558), ('\u{231}', 560), ('\u{233}', 562), ('\u{23c}', 571), + ('\u{23f}', 11390), ('\u{240}', 11391), ('\u{242}', 577), ('\u{247}', 582), + ('\u{249}', 584), ('\u{24b}', 586), ('\u{24d}', 588), ('\u{24f}', 590), ('\u{250}', 11375), + ('\u{251}', 11373), ('\u{252}', 11376), ('\u{253}', 385), ('\u{254}', 390), + ('\u{256}', 393), ('\u{257}', 394), ('\u{259}', 399), ('\u{25b}', 400), ('\u{25c}', 42923), + ('\u{260}', 403), ('\u{261}', 42924), ('\u{263}', 404), ('\u{264}', 42955), + ('\u{265}', 42893), ('\u{266}', 42922), ('\u{268}', 407), ('\u{269}', 406), + ('\u{26a}', 42926), ('\u{26b}', 11362), ('\u{26c}', 42925), ('\u{26f}', 412), + ('\u{271}', 11374), ('\u{272}', 413), ('\u{275}', 415), ('\u{27d}', 11364), + ('\u{280}', 422), ('\u{282}', 42949), ('\u{283}', 425), ('\u{287}', 42929), + ('\u{288}', 430), ('\u{289}', 580), ('\u{28a}', 433), ('\u{28b}', 434), ('\u{28c}', 581), + ('\u{292}', 439), ('\u{29d}', 42930), ('\u{29e}', 42928), ('\u{345}', 921), + ('\u{371}', 880), ('\u{373}', 882), ('\u{377}', 886), ('\u{37b}', 1021), ('\u{37c}', 1022), + ('\u{37d}', 1023), ('\u{390}', 4194307), ('\u{3ac}', 902), ('\u{3ad}', 904), + ('\u{3ae}', 905), ('\u{3af}', 906), ('\u{3b0}', 4194308), ('\u{3b1}', 913), + ('\u{3b2}', 914), ('\u{3b3}', 915), ('\u{3b4}', 916), ('\u{3b5}', 917), ('\u{3b6}', 918), + ('\u{3b7}', 919), ('\u{3b8}', 920), ('\u{3b9}', 921), ('\u{3ba}', 922), ('\u{3bb}', 923), + ('\u{3bc}', 924), ('\u{3bd}', 925), ('\u{3be}', 926), ('\u{3bf}', 927), ('\u{3c0}', 928), + ('\u{3c1}', 929), ('\u{3c2}', 931), ('\u{3c3}', 931), ('\u{3c4}', 932), ('\u{3c5}', 933), + ('\u{3c6}', 934), ('\u{3c7}', 935), ('\u{3c8}', 936), ('\u{3c9}', 937), ('\u{3ca}', 938), + ('\u{3cb}', 939), ('\u{3cc}', 908), ('\u{3cd}', 910), ('\u{3ce}', 911), ('\u{3d0}', 914), + ('\u{3d1}', 920), ('\u{3d5}', 934), ('\u{3d6}', 928), ('\u{3d7}', 975), ('\u{3d9}', 984), + ('\u{3db}', 986), ('\u{3dd}', 988), ('\u{3df}', 990), ('\u{3e1}', 992), ('\u{3e3}', 994), + ('\u{3e5}', 996), ('\u{3e7}', 998), ('\u{3e9}', 1000), ('\u{3eb}', 1002), ('\u{3ed}', 1004), + ('\u{3ef}', 1006), ('\u{3f0}', 922), ('\u{3f1}', 929), ('\u{3f2}', 1017), ('\u{3f3}', 895), + ('\u{3f5}', 917), ('\u{3f8}', 1015), ('\u{3fb}', 1018), ('\u{430}', 1040), + ('\u{431}', 1041), ('\u{432}', 1042), ('\u{433}', 1043), ('\u{434}', 1044), + ('\u{435}', 1045), ('\u{436}', 1046), ('\u{437}', 1047), ('\u{438}', 1048), + ('\u{439}', 1049), ('\u{43a}', 1050), ('\u{43b}', 1051), ('\u{43c}', 1052), + ('\u{43d}', 1053), ('\u{43e}', 1054), ('\u{43f}', 1055), ('\u{440}', 1056), + ('\u{441}', 1057), ('\u{442}', 1058), ('\u{443}', 1059), ('\u{444}', 1060), + ('\u{445}', 1061), ('\u{446}', 1062), ('\u{447}', 1063), ('\u{448}', 1064), + ('\u{449}', 1065), ('\u{44a}', 1066), ('\u{44b}', 1067), ('\u{44c}', 1068), + ('\u{44d}', 1069), ('\u{44e}', 1070), ('\u{44f}', 1071), ('\u{450}', 1024), + ('\u{451}', 1025), ('\u{452}', 1026), ('\u{453}', 1027), ('\u{454}', 1028), + ('\u{455}', 1029), ('\u{456}', 1030), ('\u{457}', 1031), ('\u{458}', 1032), + ('\u{459}', 1033), ('\u{45a}', 1034), ('\u{45b}', 1035), ('\u{45c}', 1036), + ('\u{45d}', 1037), ('\u{45e}', 1038), ('\u{45f}', 1039), ('\u{461}', 1120), + ('\u{463}', 1122), ('\u{465}', 1124), ('\u{467}', 1126), ('\u{469}', 1128), + ('\u{46b}', 1130), ('\u{46d}', 1132), ('\u{46f}', 1134), ('\u{471}', 1136), + ('\u{473}', 1138), ('\u{475}', 1140), ('\u{477}', 1142), ('\u{479}', 1144), + ('\u{47b}', 1146), ('\u{47d}', 1148), ('\u{47f}', 1150), ('\u{481}', 1152), + ('\u{48b}', 1162), ('\u{48d}', 1164), ('\u{48f}', 1166), ('\u{491}', 1168), + ('\u{493}', 1170), ('\u{495}', 1172), ('\u{497}', 1174), ('\u{499}', 1176), + ('\u{49b}', 1178), ('\u{49d}', 1180), ('\u{49f}', 1182), ('\u{4a1}', 1184), + ('\u{4a3}', 1186), ('\u{4a5}', 1188), ('\u{4a7}', 1190), ('\u{4a9}', 1192), + ('\u{4ab}', 1194), ('\u{4ad}', 1196), ('\u{4af}', 1198), ('\u{4b1}', 1200), + ('\u{4b3}', 1202), ('\u{4b5}', 1204), ('\u{4b7}', 1206), ('\u{4b9}', 1208), + ('\u{4bb}', 1210), ('\u{4bd}', 1212), ('\u{4bf}', 1214), ('\u{4c2}', 1217), + ('\u{4c4}', 1219), ('\u{4c6}', 1221), ('\u{4c8}', 1223), ('\u{4ca}', 1225), + ('\u{4cc}', 1227), ('\u{4ce}', 1229), ('\u{4cf}', 1216), ('\u{4d1}', 1232), + ('\u{4d3}', 1234), ('\u{4d5}', 1236), ('\u{4d7}', 1238), ('\u{4d9}', 1240), + ('\u{4db}', 1242), ('\u{4dd}', 1244), ('\u{4df}', 1246), ('\u{4e1}', 1248), + ('\u{4e3}', 1250), ('\u{4e5}', 1252), ('\u{4e7}', 1254), ('\u{4e9}', 1256), + ('\u{4eb}', 1258), ('\u{4ed}', 1260), ('\u{4ef}', 1262), ('\u{4f1}', 1264), + ('\u{4f3}', 1266), ('\u{4f5}', 1268), ('\u{4f7}', 1270), ('\u{4f9}', 1272), + ('\u{4fb}', 1274), ('\u{4fd}', 1276), ('\u{4ff}', 1278), ('\u{501}', 1280), + ('\u{503}', 1282), ('\u{505}', 1284), ('\u{507}', 1286), ('\u{509}', 1288), + ('\u{50b}', 1290), ('\u{50d}', 1292), ('\u{50f}', 1294), ('\u{511}', 1296), + ('\u{513}', 1298), ('\u{515}', 1300), ('\u{517}', 1302), ('\u{519}', 1304), + ('\u{51b}', 1306), ('\u{51d}', 1308), ('\u{51f}', 1310), ('\u{521}', 1312), + ('\u{523}', 1314), ('\u{525}', 1316), ('\u{527}', 1318), ('\u{529}', 1320), + ('\u{52b}', 1322), ('\u{52d}', 1324), ('\u{52f}', 1326), ('\u{561}', 1329), + ('\u{562}', 1330), ('\u{563}', 1331), ('\u{564}', 1332), ('\u{565}', 1333), + ('\u{566}', 1334), ('\u{567}', 1335), ('\u{568}', 1336), ('\u{569}', 1337), + ('\u{56a}', 1338), ('\u{56b}', 1339), ('\u{56c}', 1340), ('\u{56d}', 1341), + ('\u{56e}', 1342), ('\u{56f}', 1343), ('\u{570}', 1344), ('\u{571}', 1345), + ('\u{572}', 1346), ('\u{573}', 1347), ('\u{574}', 1348), ('\u{575}', 1349), + ('\u{576}', 1350), ('\u{577}', 1351), ('\u{578}', 1352), ('\u{579}', 1353), + ('\u{57a}', 1354), ('\u{57b}', 1355), ('\u{57c}', 1356), ('\u{57d}', 1357), + ('\u{57e}', 1358), ('\u{57f}', 1359), ('\u{580}', 1360), ('\u{581}', 1361), + ('\u{582}', 1362), ('\u{583}', 1363), ('\u{584}', 1364), ('\u{585}', 1365), + ('\u{586}', 1366), ('\u{587}', 4194309), ('\u{10d0}', 7312), ('\u{10d1}', 7313), + ('\u{10d2}', 7314), ('\u{10d3}', 7315), ('\u{10d4}', 7316), ('\u{10d5}', 7317), + ('\u{10d6}', 7318), ('\u{10d7}', 7319), ('\u{10d8}', 7320), ('\u{10d9}', 7321), + ('\u{10da}', 7322), ('\u{10db}', 7323), ('\u{10dc}', 7324), ('\u{10dd}', 7325), + ('\u{10de}', 7326), ('\u{10df}', 7327), ('\u{10e0}', 7328), ('\u{10e1}', 7329), + ('\u{10e2}', 7330), ('\u{10e3}', 7331), ('\u{10e4}', 7332), ('\u{10e5}', 7333), + ('\u{10e6}', 7334), ('\u{10e7}', 7335), ('\u{10e8}', 7336), ('\u{10e9}', 7337), + ('\u{10ea}', 7338), ('\u{10eb}', 7339), ('\u{10ec}', 7340), ('\u{10ed}', 7341), + ('\u{10ee}', 7342), ('\u{10ef}', 7343), ('\u{10f0}', 7344), ('\u{10f1}', 7345), + ('\u{10f2}', 7346), ('\u{10f3}', 7347), ('\u{10f4}', 7348), ('\u{10f5}', 7349), + ('\u{10f6}', 7350), ('\u{10f7}', 7351), ('\u{10f8}', 7352), ('\u{10f9}', 7353), + ('\u{10fa}', 7354), ('\u{10fd}', 7357), ('\u{10fe}', 7358), ('\u{10ff}', 7359), + ('\u{13f8}', 5104), ('\u{13f9}', 5105), ('\u{13fa}', 5106), ('\u{13fb}', 5107), + ('\u{13fc}', 5108), ('\u{13fd}', 5109), ('\u{1c80}', 1042), ('\u{1c81}', 1044), + ('\u{1c82}', 1054), ('\u{1c83}', 1057), ('\u{1c84}', 1058), ('\u{1c85}', 1058), + ('\u{1c86}', 1066), ('\u{1c87}', 1122), ('\u{1c88}', 42570), ('\u{1c8a}', 7305), + ('\u{1d79}', 42877), ('\u{1d7d}', 11363), ('\u{1d8e}', 42950), ('\u{1e01}', 7680), + ('\u{1e03}', 7682), ('\u{1e05}', 7684), ('\u{1e07}', 7686), ('\u{1e09}', 7688), + ('\u{1e0b}', 7690), ('\u{1e0d}', 7692), ('\u{1e0f}', 7694), ('\u{1e11}', 7696), + ('\u{1e13}', 7698), ('\u{1e15}', 7700), ('\u{1e17}', 7702), ('\u{1e19}', 7704), + ('\u{1e1b}', 7706), ('\u{1e1d}', 7708), ('\u{1e1f}', 7710), ('\u{1e21}', 7712), + ('\u{1e23}', 7714), ('\u{1e25}', 7716), ('\u{1e27}', 7718), ('\u{1e29}', 7720), + ('\u{1e2b}', 7722), ('\u{1e2d}', 7724), ('\u{1e2f}', 7726), ('\u{1e31}', 7728), + ('\u{1e33}', 7730), ('\u{1e35}', 7732), ('\u{1e37}', 7734), ('\u{1e39}', 7736), + ('\u{1e3b}', 7738), ('\u{1e3d}', 7740), ('\u{1e3f}', 7742), ('\u{1e41}', 7744), + ('\u{1e43}', 7746), ('\u{1e45}', 7748), ('\u{1e47}', 7750), ('\u{1e49}', 7752), + ('\u{1e4b}', 7754), ('\u{1e4d}', 7756), ('\u{1e4f}', 7758), ('\u{1e51}', 7760), + ('\u{1e53}', 7762), ('\u{1e55}', 7764), ('\u{1e57}', 7766), ('\u{1e59}', 7768), + ('\u{1e5b}', 7770), ('\u{1e5d}', 7772), ('\u{1e5f}', 7774), ('\u{1e61}', 7776), + ('\u{1e63}', 7778), ('\u{1e65}', 7780), ('\u{1e67}', 7782), ('\u{1e69}', 7784), + ('\u{1e6b}', 7786), ('\u{1e6d}', 7788), ('\u{1e6f}', 7790), ('\u{1e71}', 7792), + ('\u{1e73}', 7794), ('\u{1e75}', 7796), ('\u{1e77}', 7798), ('\u{1e79}', 7800), + ('\u{1e7b}', 7802), ('\u{1e7d}', 7804), ('\u{1e7f}', 7806), ('\u{1e81}', 7808), + ('\u{1e83}', 7810), ('\u{1e85}', 7812), ('\u{1e87}', 7814), ('\u{1e89}', 7816), + ('\u{1e8b}', 7818), ('\u{1e8d}', 7820), ('\u{1e8f}', 7822), ('\u{1e91}', 7824), + ('\u{1e93}', 7826), ('\u{1e95}', 7828), ('\u{1e96}', 4194310), ('\u{1e97}', 4194311), + ('\u{1e98}', 4194312), ('\u{1e99}', 4194313), ('\u{1e9a}', 4194314), ('\u{1e9b}', 7776), + ('\u{1ea1}', 7840), ('\u{1ea3}', 7842), ('\u{1ea5}', 7844), ('\u{1ea7}', 7846), + ('\u{1ea9}', 7848), ('\u{1eab}', 7850), ('\u{1ead}', 7852), ('\u{1eaf}', 7854), + ('\u{1eb1}', 7856), ('\u{1eb3}', 7858), ('\u{1eb5}', 7860), ('\u{1eb7}', 7862), + ('\u{1eb9}', 7864), ('\u{1ebb}', 7866), ('\u{1ebd}', 7868), ('\u{1ebf}', 7870), + ('\u{1ec1}', 7872), ('\u{1ec3}', 7874), ('\u{1ec5}', 7876), ('\u{1ec7}', 7878), + ('\u{1ec9}', 7880), ('\u{1ecb}', 7882), ('\u{1ecd}', 7884), ('\u{1ecf}', 7886), + ('\u{1ed1}', 7888), ('\u{1ed3}', 7890), ('\u{1ed5}', 7892), ('\u{1ed7}', 7894), + ('\u{1ed9}', 7896), ('\u{1edb}', 7898), ('\u{1edd}', 7900), ('\u{1edf}', 7902), + ('\u{1ee1}', 7904), ('\u{1ee3}', 7906), ('\u{1ee5}', 7908), ('\u{1ee7}', 7910), + ('\u{1ee9}', 7912), ('\u{1eeb}', 7914), ('\u{1eed}', 7916), ('\u{1eef}', 7918), + ('\u{1ef1}', 7920), ('\u{1ef3}', 7922), ('\u{1ef5}', 7924), ('\u{1ef7}', 7926), + ('\u{1ef9}', 7928), ('\u{1efb}', 7930), ('\u{1efd}', 7932), ('\u{1eff}', 7934), + ('\u{1f00}', 7944), ('\u{1f01}', 7945), ('\u{1f02}', 7946), ('\u{1f03}', 7947), + ('\u{1f04}', 7948), ('\u{1f05}', 7949), ('\u{1f06}', 7950), ('\u{1f07}', 7951), + ('\u{1f10}', 7960), ('\u{1f11}', 7961), ('\u{1f12}', 7962), ('\u{1f13}', 7963), + ('\u{1f14}', 7964), ('\u{1f15}', 7965), ('\u{1f20}', 7976), ('\u{1f21}', 7977), + ('\u{1f22}', 7978), ('\u{1f23}', 7979), ('\u{1f24}', 7980), ('\u{1f25}', 7981), + ('\u{1f26}', 7982), ('\u{1f27}', 7983), ('\u{1f30}', 7992), ('\u{1f31}', 7993), + ('\u{1f32}', 7994), ('\u{1f33}', 7995), ('\u{1f34}', 7996), ('\u{1f35}', 7997), + ('\u{1f36}', 7998), ('\u{1f37}', 7999), ('\u{1f40}', 8008), ('\u{1f41}', 8009), + ('\u{1f42}', 8010), ('\u{1f43}', 8011), ('\u{1f44}', 8012), ('\u{1f45}', 8013), + ('\u{1f50}', 4194315), ('\u{1f51}', 8025), ('\u{1f52}', 4194316), ('\u{1f53}', 8027), + ('\u{1f54}', 4194317), ('\u{1f55}', 8029), ('\u{1f56}', 4194318), ('\u{1f57}', 8031), + ('\u{1f60}', 8040), ('\u{1f61}', 8041), ('\u{1f62}', 8042), ('\u{1f63}', 8043), + ('\u{1f64}', 8044), ('\u{1f65}', 8045), ('\u{1f66}', 8046), ('\u{1f67}', 8047), + ('\u{1f70}', 8122), ('\u{1f71}', 8123), ('\u{1f72}', 8136), ('\u{1f73}', 8137), + ('\u{1f74}', 8138), ('\u{1f75}', 8139), ('\u{1f76}', 8154), ('\u{1f77}', 8155), + ('\u{1f78}', 8184), ('\u{1f79}', 8185), ('\u{1f7a}', 8170), ('\u{1f7b}', 8171), + ('\u{1f7c}', 8186), ('\u{1f7d}', 8187), ('\u{1f80}', 4194319), ('\u{1f81}', 4194320), + ('\u{1f82}', 4194321), ('\u{1f83}', 4194322), ('\u{1f84}', 4194323), ('\u{1f85}', 4194324), + ('\u{1f86}', 4194325), ('\u{1f87}', 4194326), ('\u{1f88}', 4194327), ('\u{1f89}', 4194328), + ('\u{1f8a}', 4194329), ('\u{1f8b}', 4194330), ('\u{1f8c}', 4194331), ('\u{1f8d}', 4194332), + ('\u{1f8e}', 4194333), ('\u{1f8f}', 4194334), ('\u{1f90}', 4194335), ('\u{1f91}', 4194336), + ('\u{1f92}', 4194337), ('\u{1f93}', 4194338), ('\u{1f94}', 4194339), ('\u{1f95}', 4194340), + ('\u{1f96}', 4194341), ('\u{1f97}', 4194342), ('\u{1f98}', 4194343), ('\u{1f99}', 4194344), + ('\u{1f9a}', 4194345), ('\u{1f9b}', 4194346), ('\u{1f9c}', 4194347), ('\u{1f9d}', 4194348), + ('\u{1f9e}', 4194349), ('\u{1f9f}', 4194350), ('\u{1fa0}', 4194351), ('\u{1fa1}', 4194352), + ('\u{1fa2}', 4194353), ('\u{1fa3}', 4194354), ('\u{1fa4}', 4194355), ('\u{1fa5}', 4194356), + ('\u{1fa6}', 4194357), ('\u{1fa7}', 4194358), ('\u{1fa8}', 4194359), ('\u{1fa9}', 4194360), + ('\u{1faa}', 4194361), ('\u{1fab}', 4194362), ('\u{1fac}', 4194363), ('\u{1fad}', 4194364), + ('\u{1fae}', 4194365), ('\u{1faf}', 4194366), ('\u{1fb0}', 8120), ('\u{1fb1}', 8121), + ('\u{1fb2}', 4194367), ('\u{1fb3}', 4194368), ('\u{1fb4}', 4194369), ('\u{1fb6}', 4194370), + ('\u{1fb7}', 4194371), ('\u{1fbc}', 4194372), ('\u{1fbe}', 921), ('\u{1fc2}', 4194373), + ('\u{1fc3}', 4194374), ('\u{1fc4}', 4194375), ('\u{1fc6}', 4194376), ('\u{1fc7}', 4194377), + ('\u{1fcc}', 4194378), ('\u{1fd0}', 8152), ('\u{1fd1}', 8153), ('\u{1fd2}', 4194379), + ('\u{1fd3}', 4194380), ('\u{1fd6}', 4194381), ('\u{1fd7}', 4194382), ('\u{1fe0}', 8168), + ('\u{1fe1}', 8169), ('\u{1fe2}', 4194383), ('\u{1fe3}', 4194384), ('\u{1fe4}', 4194385), + ('\u{1fe5}', 8172), ('\u{1fe6}', 4194386), ('\u{1fe7}', 4194387), ('\u{1ff2}', 4194388), + ('\u{1ff3}', 4194389), ('\u{1ff4}', 4194390), ('\u{1ff6}', 4194391), ('\u{1ff7}', 4194392), + ('\u{1ffc}', 4194393), ('\u{214e}', 8498), ('\u{2170}', 8544), ('\u{2171}', 8545), + ('\u{2172}', 8546), ('\u{2173}', 8547), ('\u{2174}', 8548), ('\u{2175}', 8549), + ('\u{2176}', 8550), ('\u{2177}', 8551), ('\u{2178}', 8552), ('\u{2179}', 8553), + ('\u{217a}', 8554), ('\u{217b}', 8555), ('\u{217c}', 8556), ('\u{217d}', 8557), + ('\u{217e}', 8558), ('\u{217f}', 8559), ('\u{2184}', 8579), ('\u{24d0}', 9398), + ('\u{24d1}', 9399), ('\u{24d2}', 9400), ('\u{24d3}', 9401), ('\u{24d4}', 9402), + ('\u{24d5}', 9403), ('\u{24d6}', 9404), ('\u{24d7}', 9405), ('\u{24d8}', 9406), + ('\u{24d9}', 9407), ('\u{24da}', 9408), ('\u{24db}', 9409), ('\u{24dc}', 9410), + ('\u{24dd}', 9411), ('\u{24de}', 9412), ('\u{24df}', 9413), ('\u{24e0}', 9414), + ('\u{24e1}', 9415), ('\u{24e2}', 9416), ('\u{24e3}', 9417), ('\u{24e4}', 9418), + ('\u{24e5}', 9419), ('\u{24e6}', 9420), ('\u{24e7}', 9421), ('\u{24e8}', 9422), + ('\u{24e9}', 9423), ('\u{2c30}', 11264), ('\u{2c31}', 11265), ('\u{2c32}', 11266), + ('\u{2c33}', 11267), ('\u{2c34}', 11268), ('\u{2c35}', 11269), ('\u{2c36}', 11270), + ('\u{2c37}', 11271), ('\u{2c38}', 11272), ('\u{2c39}', 11273), ('\u{2c3a}', 11274), + ('\u{2c3b}', 11275), ('\u{2c3c}', 11276), ('\u{2c3d}', 11277), ('\u{2c3e}', 11278), + ('\u{2c3f}', 11279), ('\u{2c40}', 11280), ('\u{2c41}', 11281), ('\u{2c42}', 11282), + ('\u{2c43}', 11283), ('\u{2c44}', 11284), ('\u{2c45}', 11285), ('\u{2c46}', 11286), + ('\u{2c47}', 11287), ('\u{2c48}', 11288), ('\u{2c49}', 11289), ('\u{2c4a}', 11290), + ('\u{2c4b}', 11291), ('\u{2c4c}', 11292), ('\u{2c4d}', 11293), ('\u{2c4e}', 11294), + ('\u{2c4f}', 11295), ('\u{2c50}', 11296), ('\u{2c51}', 11297), ('\u{2c52}', 11298), + ('\u{2c53}', 11299), ('\u{2c54}', 11300), ('\u{2c55}', 11301), ('\u{2c56}', 11302), + ('\u{2c57}', 11303), ('\u{2c58}', 11304), ('\u{2c59}', 11305), ('\u{2c5a}', 11306), + ('\u{2c5b}', 11307), ('\u{2c5c}', 11308), ('\u{2c5d}', 11309), ('\u{2c5e}', 11310), + ('\u{2c5f}', 11311), ('\u{2c61}', 11360), ('\u{2c65}', 570), ('\u{2c66}', 574), + ('\u{2c68}', 11367), ('\u{2c6a}', 11369), ('\u{2c6c}', 11371), ('\u{2c73}', 11378), + ('\u{2c76}', 11381), ('\u{2c81}', 11392), ('\u{2c83}', 11394), ('\u{2c85}', 11396), + ('\u{2c87}', 11398), ('\u{2c89}', 11400), ('\u{2c8b}', 11402), ('\u{2c8d}', 11404), + ('\u{2c8f}', 11406), ('\u{2c91}', 11408), ('\u{2c93}', 11410), ('\u{2c95}', 11412), + ('\u{2c97}', 11414), ('\u{2c99}', 11416), ('\u{2c9b}', 11418), ('\u{2c9d}', 11420), + ('\u{2c9f}', 11422), ('\u{2ca1}', 11424), ('\u{2ca3}', 11426), ('\u{2ca5}', 11428), + ('\u{2ca7}', 11430), ('\u{2ca9}', 11432), ('\u{2cab}', 11434), ('\u{2cad}', 11436), + ('\u{2caf}', 11438), ('\u{2cb1}', 11440), ('\u{2cb3}', 11442), ('\u{2cb5}', 11444), + ('\u{2cb7}', 11446), ('\u{2cb9}', 11448), ('\u{2cbb}', 11450), ('\u{2cbd}', 11452), + ('\u{2cbf}', 11454), ('\u{2cc1}', 11456), ('\u{2cc3}', 11458), ('\u{2cc5}', 11460), + ('\u{2cc7}', 11462), ('\u{2cc9}', 11464), ('\u{2ccb}', 11466), ('\u{2ccd}', 11468), + ('\u{2ccf}', 11470), ('\u{2cd1}', 11472), ('\u{2cd3}', 11474), ('\u{2cd5}', 11476), + ('\u{2cd7}', 11478), ('\u{2cd9}', 11480), ('\u{2cdb}', 11482), ('\u{2cdd}', 11484), + ('\u{2cdf}', 11486), ('\u{2ce1}', 11488), ('\u{2ce3}', 11490), ('\u{2cec}', 11499), + ('\u{2cee}', 11501), ('\u{2cf3}', 11506), ('\u{2d00}', 4256), ('\u{2d01}', 4257), + ('\u{2d02}', 4258), ('\u{2d03}', 4259), ('\u{2d04}', 4260), ('\u{2d05}', 4261), + ('\u{2d06}', 4262), ('\u{2d07}', 4263), ('\u{2d08}', 4264), ('\u{2d09}', 4265), + ('\u{2d0a}', 4266), ('\u{2d0b}', 4267), ('\u{2d0c}', 4268), ('\u{2d0d}', 4269), + ('\u{2d0e}', 4270), ('\u{2d0f}', 4271), ('\u{2d10}', 4272), ('\u{2d11}', 4273), + ('\u{2d12}', 4274), ('\u{2d13}', 4275), ('\u{2d14}', 4276), ('\u{2d15}', 4277), + ('\u{2d16}', 4278), ('\u{2d17}', 4279), ('\u{2d18}', 4280), ('\u{2d19}', 4281), + ('\u{2d1a}', 4282), ('\u{2d1b}', 4283), ('\u{2d1c}', 4284), ('\u{2d1d}', 4285), + ('\u{2d1e}', 4286), ('\u{2d1f}', 4287), ('\u{2d20}', 4288), ('\u{2d21}', 4289), + ('\u{2d22}', 4290), ('\u{2d23}', 4291), ('\u{2d24}', 4292), ('\u{2d25}', 4293), + ('\u{2d27}', 4295), ('\u{2d2d}', 4301), ('\u{a641}', 42560), ('\u{a643}', 42562), + ('\u{a645}', 42564), ('\u{a647}', 42566), ('\u{a649}', 42568), ('\u{a64b}', 42570), + ('\u{a64d}', 42572), ('\u{a64f}', 42574), ('\u{a651}', 42576), ('\u{a653}', 42578), + ('\u{a655}', 42580), ('\u{a657}', 42582), ('\u{a659}', 42584), ('\u{a65b}', 42586), + ('\u{a65d}', 42588), ('\u{a65f}', 42590), ('\u{a661}', 42592), ('\u{a663}', 42594), + ('\u{a665}', 42596), ('\u{a667}', 42598), ('\u{a669}', 42600), ('\u{a66b}', 42602), + ('\u{a66d}', 42604), ('\u{a681}', 42624), ('\u{a683}', 42626), ('\u{a685}', 42628), + ('\u{a687}', 42630), ('\u{a689}', 42632), ('\u{a68b}', 42634), ('\u{a68d}', 42636), + ('\u{a68f}', 42638), ('\u{a691}', 42640), ('\u{a693}', 42642), ('\u{a695}', 42644), + ('\u{a697}', 42646), ('\u{a699}', 42648), ('\u{a69b}', 42650), ('\u{a723}', 42786), + ('\u{a725}', 42788), ('\u{a727}', 42790), ('\u{a729}', 42792), ('\u{a72b}', 42794), + ('\u{a72d}', 42796), ('\u{a72f}', 42798), ('\u{a733}', 42802), ('\u{a735}', 42804), + ('\u{a737}', 42806), ('\u{a739}', 42808), ('\u{a73b}', 42810), ('\u{a73d}', 42812), + ('\u{a73f}', 42814), ('\u{a741}', 42816), ('\u{a743}', 42818), ('\u{a745}', 42820), + ('\u{a747}', 42822), ('\u{a749}', 42824), ('\u{a74b}', 42826), ('\u{a74d}', 42828), + ('\u{a74f}', 42830), ('\u{a751}', 42832), ('\u{a753}', 42834), ('\u{a755}', 42836), + ('\u{a757}', 42838), ('\u{a759}', 42840), ('\u{a75b}', 42842), ('\u{a75d}', 42844), + ('\u{a75f}', 42846), ('\u{a761}', 42848), ('\u{a763}', 42850), ('\u{a765}', 42852), + ('\u{a767}', 42854), ('\u{a769}', 42856), ('\u{a76b}', 42858), ('\u{a76d}', 42860), + ('\u{a76f}', 42862), ('\u{a77a}', 42873), ('\u{a77c}', 42875), ('\u{a77f}', 42878), + ('\u{a781}', 42880), ('\u{a783}', 42882), ('\u{a785}', 42884), ('\u{a787}', 42886), + ('\u{a78c}', 42891), ('\u{a791}', 42896), ('\u{a793}', 42898), ('\u{a794}', 42948), + ('\u{a797}', 42902), ('\u{a799}', 42904), ('\u{a79b}', 42906), ('\u{a79d}', 42908), + ('\u{a79f}', 42910), ('\u{a7a1}', 42912), ('\u{a7a3}', 42914), ('\u{a7a5}', 42916), + ('\u{a7a7}', 42918), ('\u{a7a9}', 42920), ('\u{a7b5}', 42932), ('\u{a7b7}', 42934), + ('\u{a7b9}', 42936), ('\u{a7bb}', 42938), ('\u{a7bd}', 42940), ('\u{a7bf}', 42942), + ('\u{a7c1}', 42944), ('\u{a7c3}', 42946), ('\u{a7c8}', 42951), ('\u{a7ca}', 42953), + ('\u{a7cd}', 42956), ('\u{a7d1}', 42960), ('\u{a7d7}', 42966), ('\u{a7d9}', 42968), + ('\u{a7db}', 42970), ('\u{a7f6}', 42997), ('\u{ab53}', 42931), ('\u{ab70}', 5024), + ('\u{ab71}', 5025), ('\u{ab72}', 5026), ('\u{ab73}', 5027), ('\u{ab74}', 5028), + ('\u{ab75}', 5029), ('\u{ab76}', 5030), ('\u{ab77}', 5031), ('\u{ab78}', 5032), + ('\u{ab79}', 5033), ('\u{ab7a}', 5034), ('\u{ab7b}', 5035), ('\u{ab7c}', 5036), + ('\u{ab7d}', 5037), ('\u{ab7e}', 5038), ('\u{ab7f}', 5039), ('\u{ab80}', 5040), + ('\u{ab81}', 5041), ('\u{ab82}', 5042), ('\u{ab83}', 5043), ('\u{ab84}', 5044), + ('\u{ab85}', 5045), ('\u{ab86}', 5046), ('\u{ab87}', 5047), ('\u{ab88}', 5048), + ('\u{ab89}', 5049), ('\u{ab8a}', 5050), ('\u{ab8b}', 5051), ('\u{ab8c}', 5052), + ('\u{ab8d}', 5053), ('\u{ab8e}', 5054), ('\u{ab8f}', 5055), ('\u{ab90}', 5056), + ('\u{ab91}', 5057), ('\u{ab92}', 5058), ('\u{ab93}', 5059), ('\u{ab94}', 5060), + ('\u{ab95}', 5061), ('\u{ab96}', 5062), ('\u{ab97}', 5063), ('\u{ab98}', 5064), + ('\u{ab99}', 5065), ('\u{ab9a}', 5066), ('\u{ab9b}', 5067), ('\u{ab9c}', 5068), + ('\u{ab9d}', 5069), ('\u{ab9e}', 5070), ('\u{ab9f}', 5071), ('\u{aba0}', 5072), + ('\u{aba1}', 5073), ('\u{aba2}', 5074), ('\u{aba3}', 5075), ('\u{aba4}', 5076), + ('\u{aba5}', 5077), ('\u{aba6}', 5078), ('\u{aba7}', 5079), ('\u{aba8}', 5080), + ('\u{aba9}', 5081), ('\u{abaa}', 5082), ('\u{abab}', 5083), ('\u{abac}', 5084), + ('\u{abad}', 5085), ('\u{abae}', 5086), ('\u{abaf}', 5087), ('\u{abb0}', 5088), + ('\u{abb1}', 5089), ('\u{abb2}', 5090), ('\u{abb3}', 5091), ('\u{abb4}', 5092), + ('\u{abb5}', 5093), ('\u{abb6}', 5094), ('\u{abb7}', 5095), ('\u{abb8}', 5096), + ('\u{abb9}', 5097), ('\u{abba}', 5098), ('\u{abbb}', 5099), ('\u{abbc}', 5100), + ('\u{abbd}', 5101), ('\u{abbe}', 5102), ('\u{abbf}', 5103), ('\u{fb00}', 4194394), + ('\u{fb01}', 4194395), ('\u{fb02}', 4194396), ('\u{fb03}', 4194397), ('\u{fb04}', 4194398), + ('\u{fb05}', 4194399), ('\u{fb06}', 4194400), ('\u{fb13}', 4194401), ('\u{fb14}', 4194402), + ('\u{fb15}', 4194403), ('\u{fb16}', 4194404), ('\u{fb17}', 4194405), ('\u{ff41}', 65313), + ('\u{ff42}', 65314), ('\u{ff43}', 65315), ('\u{ff44}', 65316), ('\u{ff45}', 65317), + ('\u{ff46}', 65318), ('\u{ff47}', 65319), ('\u{ff48}', 65320), ('\u{ff49}', 65321), + ('\u{ff4a}', 65322), ('\u{ff4b}', 65323), ('\u{ff4c}', 65324), ('\u{ff4d}', 65325), + ('\u{ff4e}', 65326), ('\u{ff4f}', 65327), ('\u{ff50}', 65328), ('\u{ff51}', 65329), + ('\u{ff52}', 65330), ('\u{ff53}', 65331), ('\u{ff54}', 65332), ('\u{ff55}', 65333), + ('\u{ff56}', 65334), ('\u{ff57}', 65335), ('\u{ff58}', 65336), ('\u{ff59}', 65337), + ('\u{ff5a}', 65338), ('\u{10428}', 66560), ('\u{10429}', 66561), ('\u{1042a}', 66562), + ('\u{1042b}', 66563), ('\u{1042c}', 66564), ('\u{1042d}', 66565), ('\u{1042e}', 66566), + ('\u{1042f}', 66567), ('\u{10430}', 66568), ('\u{10431}', 66569), ('\u{10432}', 66570), + ('\u{10433}', 66571), ('\u{10434}', 66572), ('\u{10435}', 66573), ('\u{10436}', 66574), + ('\u{10437}', 66575), ('\u{10438}', 66576), ('\u{10439}', 66577), ('\u{1043a}', 66578), + ('\u{1043b}', 66579), ('\u{1043c}', 66580), ('\u{1043d}', 66581), ('\u{1043e}', 66582), + ('\u{1043f}', 66583), ('\u{10440}', 66584), ('\u{10441}', 66585), ('\u{10442}', 66586), + ('\u{10443}', 66587), ('\u{10444}', 66588), ('\u{10445}', 66589), ('\u{10446}', 66590), + ('\u{10447}', 66591), ('\u{10448}', 66592), ('\u{10449}', 66593), ('\u{1044a}', 66594), + ('\u{1044b}', 66595), ('\u{1044c}', 66596), ('\u{1044d}', 66597), ('\u{1044e}', 66598), + ('\u{1044f}', 66599), ('\u{104d8}', 66736), ('\u{104d9}', 66737), ('\u{104da}', 66738), + ('\u{104db}', 66739), ('\u{104dc}', 66740), ('\u{104dd}', 66741), ('\u{104de}', 66742), + ('\u{104df}', 66743), ('\u{104e0}', 66744), ('\u{104e1}', 66745), ('\u{104e2}', 66746), + ('\u{104e3}', 66747), ('\u{104e4}', 66748), ('\u{104e5}', 66749), ('\u{104e6}', 66750), + ('\u{104e7}', 66751), ('\u{104e8}', 66752), ('\u{104e9}', 66753), ('\u{104ea}', 66754), + ('\u{104eb}', 66755), ('\u{104ec}', 66756), ('\u{104ed}', 66757), ('\u{104ee}', 66758), + ('\u{104ef}', 66759), ('\u{104f0}', 66760), ('\u{104f1}', 66761), ('\u{104f2}', 66762), + ('\u{104f3}', 66763), ('\u{104f4}', 66764), ('\u{104f5}', 66765), ('\u{104f6}', 66766), + ('\u{104f7}', 66767), ('\u{104f8}', 66768), ('\u{104f9}', 66769), ('\u{104fa}', 66770), + ('\u{104fb}', 66771), ('\u{10597}', 66928), ('\u{10598}', 66929), ('\u{10599}', 66930), + ('\u{1059a}', 66931), ('\u{1059b}', 66932), ('\u{1059c}', 66933), ('\u{1059d}', 66934), + ('\u{1059e}', 66935), ('\u{1059f}', 66936), ('\u{105a0}', 66937), ('\u{105a1}', 66938), + ('\u{105a3}', 66940), ('\u{105a4}', 66941), ('\u{105a5}', 66942), ('\u{105a6}', 66943), + ('\u{105a7}', 66944), ('\u{105a8}', 66945), ('\u{105a9}', 66946), ('\u{105aa}', 66947), + ('\u{105ab}', 66948), ('\u{105ac}', 66949), ('\u{105ad}', 66950), ('\u{105ae}', 66951), + ('\u{105af}', 66952), ('\u{105b0}', 66953), ('\u{105b1}', 66954), ('\u{105b3}', 66956), + ('\u{105b4}', 66957), ('\u{105b5}', 66958), ('\u{105b6}', 66959), ('\u{105b7}', 66960), + ('\u{105b8}', 66961), ('\u{105b9}', 66962), ('\u{105bb}', 66964), ('\u{105bc}', 66965), + ('\u{10cc0}', 68736), ('\u{10cc1}', 68737), ('\u{10cc2}', 68738), ('\u{10cc3}', 68739), + ('\u{10cc4}', 68740), ('\u{10cc5}', 68741), ('\u{10cc6}', 68742), ('\u{10cc7}', 68743), + ('\u{10cc8}', 68744), ('\u{10cc9}', 68745), ('\u{10cca}', 68746), ('\u{10ccb}', 68747), + ('\u{10ccc}', 68748), ('\u{10ccd}', 68749), ('\u{10cce}', 68750), ('\u{10ccf}', 68751), + ('\u{10cd0}', 68752), ('\u{10cd1}', 68753), ('\u{10cd2}', 68754), ('\u{10cd3}', 68755), + ('\u{10cd4}', 68756), ('\u{10cd5}', 68757), ('\u{10cd6}', 68758), ('\u{10cd7}', 68759), + ('\u{10cd8}', 68760), ('\u{10cd9}', 68761), ('\u{10cda}', 68762), ('\u{10cdb}', 68763), + ('\u{10cdc}', 68764), ('\u{10cdd}', 68765), ('\u{10cde}', 68766), ('\u{10cdf}', 68767), + ('\u{10ce0}', 68768), ('\u{10ce1}', 68769), ('\u{10ce2}', 68770), ('\u{10ce3}', 68771), + ('\u{10ce4}', 68772), ('\u{10ce5}', 68773), ('\u{10ce6}', 68774), ('\u{10ce7}', 68775), + ('\u{10ce8}', 68776), ('\u{10ce9}', 68777), ('\u{10cea}', 68778), ('\u{10ceb}', 68779), + ('\u{10cec}', 68780), ('\u{10ced}', 68781), ('\u{10cee}', 68782), ('\u{10cef}', 68783), + ('\u{10cf0}', 68784), ('\u{10cf1}', 68785), ('\u{10cf2}', 68786), ('\u{10d70}', 68944), + ('\u{10d71}', 68945), ('\u{10d72}', 68946), ('\u{10d73}', 68947), ('\u{10d74}', 68948), + ('\u{10d75}', 68949), ('\u{10d76}', 68950), ('\u{10d77}', 68951), ('\u{10d78}', 68952), + ('\u{10d79}', 68953), ('\u{10d7a}', 68954), ('\u{10d7b}', 68955), ('\u{10d7c}', 68956), + ('\u{10d7d}', 68957), ('\u{10d7e}', 68958), ('\u{10d7f}', 68959), ('\u{10d80}', 68960), + ('\u{10d81}', 68961), ('\u{10d82}', 68962), ('\u{10d83}', 68963), ('\u{10d84}', 68964), + ('\u{10d85}', 68965), ('\u{118c0}', 71840), ('\u{118c1}', 71841), ('\u{118c2}', 71842), + ('\u{118c3}', 71843), ('\u{118c4}', 71844), ('\u{118c5}', 71845), ('\u{118c6}', 71846), + ('\u{118c7}', 71847), ('\u{118c8}', 71848), ('\u{118c9}', 71849), ('\u{118ca}', 71850), + ('\u{118cb}', 71851), ('\u{118cc}', 71852), ('\u{118cd}', 71853), ('\u{118ce}', 71854), + ('\u{118cf}', 71855), ('\u{118d0}', 71856), ('\u{118d1}', 71857), ('\u{118d2}', 71858), + ('\u{118d3}', 71859), ('\u{118d4}', 71860), ('\u{118d5}', 71861), ('\u{118d6}', 71862), + ('\u{118d7}', 71863), ('\u{118d8}', 71864), ('\u{118d9}', 71865), ('\u{118da}', 71866), + ('\u{118db}', 71867), ('\u{118dc}', 71868), ('\u{118dd}', 71869), ('\u{118de}', 71870), + ('\u{118df}', 71871), ('\u{16e60}', 93760), ('\u{16e61}', 93761), ('\u{16e62}', 93762), + ('\u{16e63}', 93763), ('\u{16e64}', 93764), ('\u{16e65}', 93765), ('\u{16e66}', 93766), + ('\u{16e67}', 93767), ('\u{16e68}', 93768), ('\u{16e69}', 93769), ('\u{16e6a}', 93770), + ('\u{16e6b}', 93771), ('\u{16e6c}', 93772), ('\u{16e6d}', 93773), ('\u{16e6e}', 93774), + ('\u{16e6f}', 93775), ('\u{16e70}', 93776), ('\u{16e71}', 93777), ('\u{16e72}', 93778), + ('\u{16e73}', 93779), ('\u{16e74}', 93780), ('\u{16e75}', 93781), ('\u{16e76}', 93782), + ('\u{16e77}', 93783), ('\u{16e78}', 93784), ('\u{16e79}', 93785), ('\u{16e7a}', 93786), + ('\u{16e7b}', 93787), ('\u{16e7c}', 93788), ('\u{16e7d}', 93789), ('\u{16e7e}', 93790), + ('\u{16e7f}', 93791), ('\u{1e922}', 125184), ('\u{1e923}', 125185), ('\u{1e924}', 125186), + ('\u{1e925}', 125187), ('\u{1e926}', 125188), ('\u{1e927}', 125189), ('\u{1e928}', 125190), + ('\u{1e929}', 125191), ('\u{1e92a}', 125192), ('\u{1e92b}', 125193), ('\u{1e92c}', 125194), + ('\u{1e92d}', 125195), ('\u{1e92e}', 125196), ('\u{1e92f}', 125197), ('\u{1e930}', 125198), + ('\u{1e931}', 125199), ('\u{1e932}', 125200), ('\u{1e933}', 125201), ('\u{1e934}', 125202), + ('\u{1e935}', 125203), ('\u{1e936}', 125204), ('\u{1e937}', 125205), ('\u{1e938}', 125206), + ('\u{1e939}', 125207), ('\u{1e93a}', 125208), ('\u{1e93b}', 125209), ('\u{1e93c}', 125210), + ('\u{1e93d}', 125211), ('\u{1e93e}', 125212), ('\u{1e93f}', 125213), ('\u{1e940}', 125214), + ('\u{1e941}', 125215), ('\u{1e942}', 125216), ('\u{1e943}', 125217), + ]; + + static UPPERCASE_TABLE_MULTI: &[[char; 3]] = &[ + ['S', 'S', '\u{0}'], ['\u{2bc}', 'N', '\u{0}'], ['J', '\u{30c}', '\u{0}'], + ['\u{399}', '\u{308}', '\u{301}'], ['\u{3a5}', '\u{308}', '\u{301}'], + ['\u{535}', '\u{552}', '\u{0}'], ['H', '\u{331}', '\u{0}'], ['T', '\u{308}', '\u{0}'], + ['W', '\u{30a}', '\u{0}'], ['Y', '\u{30a}', '\u{0}'], ['A', '\u{2be}', '\u{0}'], + ['\u{3a5}', '\u{313}', '\u{0}'], ['\u{3a5}', '\u{313}', '\u{300}'], + ['\u{3a5}', '\u{313}', '\u{301}'], ['\u{3a5}', '\u{313}', '\u{342}'], + ['\u{1f08}', '\u{399}', '\u{0}'], ['\u{1f09}', '\u{399}', '\u{0}'], + ['\u{1f0a}', '\u{399}', '\u{0}'], ['\u{1f0b}', '\u{399}', '\u{0}'], + ['\u{1f0c}', '\u{399}', '\u{0}'], ['\u{1f0d}', '\u{399}', '\u{0}'], + ['\u{1f0e}', '\u{399}', '\u{0}'], ['\u{1f0f}', '\u{399}', '\u{0}'], + ['\u{1f08}', '\u{399}', '\u{0}'], ['\u{1f09}', '\u{399}', '\u{0}'], + ['\u{1f0a}', '\u{399}', '\u{0}'], ['\u{1f0b}', '\u{399}', '\u{0}'], + ['\u{1f0c}', '\u{399}', '\u{0}'], ['\u{1f0d}', '\u{399}', '\u{0}'], + ['\u{1f0e}', '\u{399}', '\u{0}'], ['\u{1f0f}', '\u{399}', '\u{0}'], + ['\u{1f28}', '\u{399}', '\u{0}'], ['\u{1f29}', '\u{399}', '\u{0}'], + ['\u{1f2a}', '\u{399}', '\u{0}'], ['\u{1f2b}', '\u{399}', '\u{0}'], + ['\u{1f2c}', '\u{399}', '\u{0}'], ['\u{1f2d}', '\u{399}', '\u{0}'], + ['\u{1f2e}', '\u{399}', '\u{0}'], ['\u{1f2f}', '\u{399}', '\u{0}'], + ['\u{1f28}', '\u{399}', '\u{0}'], ['\u{1f29}', '\u{399}', '\u{0}'], + ['\u{1f2a}', '\u{399}', '\u{0}'], ['\u{1f2b}', '\u{399}', '\u{0}'], + ['\u{1f2c}', '\u{399}', '\u{0}'], ['\u{1f2d}', '\u{399}', '\u{0}'], + ['\u{1f2e}', '\u{399}', '\u{0}'], ['\u{1f2f}', '\u{399}', '\u{0}'], + ['\u{1f68}', '\u{399}', '\u{0}'], ['\u{1f69}', '\u{399}', '\u{0}'], + ['\u{1f6a}', '\u{399}', '\u{0}'], ['\u{1f6b}', '\u{399}', '\u{0}'], + ['\u{1f6c}', '\u{399}', '\u{0}'], ['\u{1f6d}', '\u{399}', '\u{0}'], + ['\u{1f6e}', '\u{399}', '\u{0}'], ['\u{1f6f}', '\u{399}', '\u{0}'], + ['\u{1f68}', '\u{399}', '\u{0}'], ['\u{1f69}', '\u{399}', '\u{0}'], + ['\u{1f6a}', '\u{399}', '\u{0}'], ['\u{1f6b}', '\u{399}', '\u{0}'], + ['\u{1f6c}', '\u{399}', '\u{0}'], ['\u{1f6d}', '\u{399}', '\u{0}'], + ['\u{1f6e}', '\u{399}', '\u{0}'], ['\u{1f6f}', '\u{399}', '\u{0}'], + ['\u{1fba}', '\u{399}', '\u{0}'], ['\u{391}', '\u{399}', '\u{0}'], + ['\u{386}', '\u{399}', '\u{0}'], ['\u{391}', '\u{342}', '\u{0}'], + ['\u{391}', '\u{342}', '\u{399}'], ['\u{391}', '\u{399}', '\u{0}'], + ['\u{1fca}', '\u{399}', '\u{0}'], ['\u{397}', '\u{399}', '\u{0}'], + ['\u{389}', '\u{399}', '\u{0}'], ['\u{397}', '\u{342}', '\u{0}'], + ['\u{397}', '\u{342}', '\u{399}'], ['\u{397}', '\u{399}', '\u{0}'], + ['\u{399}', '\u{308}', '\u{300}'], ['\u{399}', '\u{308}', '\u{301}'], + ['\u{399}', '\u{342}', '\u{0}'], ['\u{399}', '\u{308}', '\u{342}'], + ['\u{3a5}', '\u{308}', '\u{300}'], ['\u{3a5}', '\u{308}', '\u{301}'], + ['\u{3a1}', '\u{313}', '\u{0}'], ['\u{3a5}', '\u{342}', '\u{0}'], + ['\u{3a5}', '\u{308}', '\u{342}'], ['\u{1ffa}', '\u{399}', '\u{0}'], + ['\u{3a9}', '\u{399}', '\u{0}'], ['\u{38f}', '\u{399}', '\u{0}'], + ['\u{3a9}', '\u{342}', '\u{0}'], ['\u{3a9}', '\u{342}', '\u{399}'], + ['\u{3a9}', '\u{399}', '\u{0}'], ['F', 'F', '\u{0}'], ['F', 'I', '\u{0}'], + ['F', 'L', '\u{0}'], ['F', 'F', 'I'], ['F', 'F', 'L'], ['S', 'T', '\u{0}'], + ['S', 'T', '\u{0}'], ['\u{544}', '\u{546}', '\u{0}'], ['\u{544}', '\u{535}', '\u{0}'], + ['\u{544}', '\u{53b}', '\u{0}'], ['\u{54e}', '\u{546}', '\u{0}'], + ['\u{544}', '\u{53d}', '\u{0}'], + ]; +} diff --git a/CoqOfRust/core/unit.rs b/CoqOfRust/core/unit.rs new file mode 100644 index 000000000..d656005f3 --- /dev/null +++ b/CoqOfRust/core/unit.rs @@ -0,0 +1,19 @@ +/// Collapses all unit items from an iterator into one. +/// +/// This is more useful when combined with higher-level abstractions, like +/// collecting to a `Result<(), E>` where you only care about errors: +/// +/// ``` +/// use std::io::*; +/// let data = vec![1, 2, 3, 4, 5]; +/// let res: Result<()> = data.iter() +/// .map(|x| writeln!(stdout(), "{x}")) +/// .collect(); +/// assert!(res.is_ok()); +/// ``` +#[stable(feature = "unit_from_iter", since = "1.23.0")] +impl FromIterator<()> for () { + fn from_iter>(iter: I) -> Self { + iter.into_iter().for_each(|()| {}) + } +} diff --git a/CoqOfRust/move_sui/translations/move_abstract_stack/lib.rs b/CoqOfRust/move_sui/translations/move_abstract_stack/lib.rs new file mode 100644 index 000000000..7a0be80e5 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_abstract_stack/lib.rs @@ -0,0 +1,169 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! This module defines an abstract stack used by various verifier passes + +#[cfg(test)] +mod unit_tests; + +use std::cmp::Ordering; +use std::fmt::{self, Debug}; +use std::num::NonZeroU64; + +#[derive(Default, Debug)] +/// An abstract value that compresses runs of the same value to reduce space usage +pub struct AbstractStack { + values: Vec<(u64, T)>, + len: u64, +} + +impl AbstractStack { + /// Creates an empty stack + pub fn new() -> Self { + Self { + values: vec![], + len: 0, + } + } + + /// Returns true iff the stack is empty + pub fn is_empty(&self) -> bool { + // empty ==> len is 0 + debug_assert!(!self.values.is_empty() || self.len == 0); + // !empty ==> last element len <= len + debug_assert!(self.values.is_empty() || self.values.last().unwrap().0 <= self.len); + self.values.is_empty() + } + + /// Returns the logical length of the stack as if there was no space + /// compression + pub fn len(&self) -> u64 { + // len is 0 ==> empty + debug_assert!(self.len != 0 || self.values.is_empty()); + // len not 0 ==> !empty and last element len <= len + debug_assert!( + self.len == 0 || (!self.values.is_empty() && self.values.last().unwrap().0 <= self.len) + ); + self.len + } + + /// Pushes a single value on the stack + pub fn push(&mut self, item: T) -> Result<(), AbsStackError> { + self.push_n(item, 1) + } + + /// Push n copies of an item on the stack + pub fn push_n(&mut self, item: T, n: u64) -> Result<(), AbsStackError> { + if n == 0 { + return Ok(()); + } + + let Some(new_len) = self.len.checked_add(n) else { + return Err(AbsStackError::Overflow); + }; + self.len = new_len; + match self.values.last_mut() { + Some((count, last_item)) if &item == last_item => { + debug_assert!(*count > 0); + *count += n + } + _ => self.values.push((n, item)), + } + Ok(()) + } + + /// Pops a single value off the stack + pub fn pop(&mut self) -> Result { + self.pop_eq_n(NonZeroU64::new(1).unwrap()) + } + + /// Pops n values off the stack, erroring if there are not enough items or if the n items are + /// not equal + pub fn pop_eq_n(&mut self, n: NonZeroU64) -> Result { + let n: u64 = n.get(); + if self.is_empty() || n > self.len { + return Err(AbsStackError::Underflow); + } + let (count, last) = self.values.last_mut().unwrap(); + debug_assert!(*count > 0); + let ret = match (*count).cmp(&n) { + Ordering::Less => return Err(AbsStackError::ElementNotEqual), + Ordering::Equal => { + let (_, last) = self.values.pop().unwrap(); + last + } + Ordering::Greater => { + *count -= n; + last.clone() + } + }; + self.len -= n; + Ok(ret) + } + + /// Pop any n items off the stack. Unlike `pop_n`, items do not have to be equal + pub fn pop_any_n(&mut self, n: NonZeroU64) -> Result<(), AbsStackError> { + let n: u64 = n.get(); + if self.is_empty() || n > self.len { + return Err(AbsStackError::Underflow); + } + let mut rem: u64 = n; + while rem > 0 { + let (count, _last) = self.values.last_mut().unwrap(); + debug_assert!(*count > 0); + match (*count).cmp(&rem) { + Ordering::Less | Ordering::Equal => { + rem -= *count; + self.values.pop().unwrap(); + } + Ordering::Greater => { + *count -= rem; + break; + } + } + } + self.len -= n; + Ok(()) + } + + #[cfg(test)] + pub(crate) fn assert_run_lengths(&self, lengths: Items) + where + Item: std::borrow::Borrow, + Items: IntoIterator, + ::IntoIter: ExactSizeIterator, + { + let lengths_iter = lengths.into_iter(); + assert_eq!(self.values.len(), lengths_iter.len()); + let mut sum = 0; + for ((actual, _), expected) in self.values.iter().zip(lengths_iter) { + let expected = expected.borrow(); + assert_eq!(actual, expected); + sum += *expected; + } + assert_eq!(self.len, sum); + } +} + +#[derive(Eq, PartialEq, PartialOrd, Ord, Clone, Copy, Debug)] +pub enum AbsStackError { + ElementNotEqual, + Underflow, + Overflow, +} + +impl fmt::Display for AbsStackError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + AbsStackError::ElementNotEqual => { + write!(f, "Popped element is not equal to specified item") + } + AbsStackError::Underflow => { + write!(f, "Popped more values than are on the stack") + } + AbsStackError::Overflow => { + write!(f, "Pushed too many elements on the stack") + } + } + } +} diff --git a/CoqOfRust/move_sui/translations/move_abstract_stack/unit_tests/mod.rs b/CoqOfRust/move_sui/translations/move_abstract_stack/unit_tests/mod.rs new file mode 100644 index 000000000..f4824dd8f --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_abstract_stack/unit_tests/mod.rs @@ -0,0 +1,295 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::*; + +#[test] +fn test_empty_stack() { + let mut empty = AbstractStack::::new(); + assert!(empty.is_empty()); + + // pop on empty stack + assert_eq!(empty.pop(), Err(AbsStackError::Underflow)); + assert_eq!(empty.pop_any_n(nonzero(1)), Err(AbsStackError::Underflow)); + assert_eq!(empty.pop_any_n(nonzero(100)), Err(AbsStackError::Underflow)); + assert_eq!(empty.pop_eq_n(nonzero(12)), Err(AbsStackError::Underflow)); + assert_eq!(empty.pop_eq_n(nonzero(112)), Err(AbsStackError::Underflow)); + + assert!(empty.is_empty()); +} + +#[test] +fn test_simple_push_pop() { + let mut s = AbstractStack::new(); + s.push(1).unwrap(); + assert!(!s.is_empty()); + assert_eq!(s.len(), 1); + s.assert_run_lengths([1]); + assert_eq!(s.pop(), Ok(1)); + assert!(s.is_empty()); + assert_eq!(s.len(), 0); + + s.push(1).unwrap(); + s.push(2).unwrap(); + s.push(3).unwrap(); + assert!(!s.is_empty()); + assert_eq!(s.len(), 3); + s.assert_run_lengths([1, 1, 1]); + assert_eq!(s.pop(), Ok(3)); + assert_eq!(s.pop(), Ok(2)); + assert_eq!(s.pop(), Ok(1)); + assert!(s.is_empty()); + assert_eq!(s.len(), 0); + + s.push_n(1, 1).unwrap(); + s.push_n(2, 2).unwrap(); + s.push_n(3, 3).unwrap(); + assert!(!s.is_empty()); + assert_eq!(s.len(), 6); + s.assert_run_lengths([1, 2, 3]); + assert_eq!(s.pop(), Ok(3)); + assert_eq!(s.pop(), Ok(3)); + assert_eq!(s.pop(), Ok(3)); + assert_eq!(s.pop(), Ok(2)); + assert_eq!(s.pop(), Ok(2)); + assert_eq!(s.pop(), Ok(1)); + assert!(s.is_empty()); + assert_eq!(s.len(), 0); + + s.push_n(1, 1).unwrap(); + s.push_n(2, 2).unwrap(); + s.push_n(3, 3).unwrap(); + assert!(!s.is_empty()); + assert_eq!(s.len(), 6); + s.assert_run_lengths([1, 2, 3]); + assert_eq!(s.pop_eq_n(nonzero(3)), Ok(3)); + assert_eq!(s.pop_eq_n(nonzero(2)), Ok(2)); + assert_eq!(s.pop_eq_n(nonzero(1)), Ok(1)); + assert!(s.is_empty()); + assert_eq!(s.len(), 0); + + s.push(1).unwrap(); + s.push(2).unwrap(); + s.push(2).unwrap(); + s.push(3).unwrap(); + s.push(3).unwrap(); + s.push(3).unwrap(); + assert!(!s.is_empty()); + s.assert_run_lengths([1, 2, 3]); + assert_eq!(s.len(), 6); + assert_eq!(s.pop_eq_n(nonzero(3)), Ok(3)); + assert_eq!(s.pop_eq_n(nonzero(2)), Ok(2)); + assert_eq!(s.pop_eq_n(nonzero(1)), Ok(1)); + assert!(s.is_empty()); + assert_eq!(s.len(), 0); + + s.push_n(1, 1).unwrap(); + s.push_n(2, 2).unwrap(); + s.push_n(3, 3).unwrap(); + assert!(!s.is_empty()); + s.assert_run_lengths([1, 2, 3]); + assert_eq!(s.len(), 6); + s.pop_any_n(nonzero(6)).unwrap(); + assert_eq!(s.len(), 0); + assert!(s.is_empty()); + + s.push(1).unwrap(); + s.push(2).unwrap(); + s.push(2).unwrap(); + s.push(3).unwrap(); + s.push(3).unwrap(); + s.push(3).unwrap(); + assert!(!s.is_empty()); + s.assert_run_lengths([1, 2, 3]); + assert_eq!(s.len(), 6); + s.pop_any_n(nonzero(4)).unwrap(); + s.pop_any_n(nonzero(2)).unwrap(); + assert!(s.is_empty()); + assert_eq!(s.len(), 0); +} + +#[test] +fn test_not_eq() { + let mut s = AbstractStack::new(); + s.push(1).unwrap(); + s.push(2).unwrap(); + s.push(2).unwrap(); + s.push(3).unwrap(); + s.push(3).unwrap(); + s.push(3).unwrap(); + assert_eq!(s.len(), 6); + s.assert_run_lengths([1, 2, 3]); + assert_eq!(s.pop_eq_n(nonzero(4)), Err(AbsStackError::ElementNotEqual)); + assert_eq!(s.pop_eq_n(nonzero(5)), Err(AbsStackError::ElementNotEqual)); + assert_eq!(s.len(), 6); + s.assert_run_lengths([1, 2, 3]); +} + +#[test] +fn test_not_enough_values() { + let mut s = AbstractStack::new(); + s.push(1).unwrap(); + s.push(2).unwrap(); + s.push(2).unwrap(); + s.push(3).unwrap(); + s.push(3).unwrap(); + s.push(3).unwrap(); + assert_eq!(s.len(), 6); + s.assert_run_lengths([1, 2, 3]); + assert_eq!(s.pop_eq_n(nonzero(7)), Err(AbsStackError::Underflow)); + assert_eq!(s.pop_any_n(nonzero(7)), Err(AbsStackError::Underflow)); + assert_eq!(s.len(), 6); + s.assert_run_lengths([1, 2, 3]); +} + +#[test] +fn test_exhaustive() { + fn run_lengths(bits: &[bool]) -> Vec { + let mut cur = bits[0]; + let mut runs = vec![0]; + for bit in bits.iter().copied() { + if cur == bit { + let last = runs.last_mut().unwrap(); + *last += 1; + } else { + cur = bit; + runs.push(1); + } + } + runs + } + fn push_pop(bits: &[bool]) { + let mut s = AbstractStack::new(); + for bit in bits.iter().copied() { + s.push(bit).unwrap(); + } + s.assert_run_lengths(run_lengths(bits)); + + for bit in bits.iter().copied().rev() { + assert_eq!(s.pop(), Ok(bit)); + } + assert!(s.is_empty()) + } + fn pushn_pop(bits: &[bool]) { + let mut s = AbstractStack::new(); + let mut push_cur = false; + let mut push_count = 0; + for bit in bits.iter().copied() { + if push_cur == bit { + push_count += 1; + } else { + s.push_n(push_cur, push_count).unwrap(); + push_cur = bit; + push_count = 1; + } + } + s.push_n(push_cur, push_count).unwrap(); + assert_eq!(s.len(), bits.len() as u64); + s.assert_run_lengths(run_lengths(bits)); + + let mut n = bits.len() as u64; + for bit in bits.iter().copied().rev() { + assert_eq!(s.pop(), Ok(bit)); + n -= 1; + assert_eq!(s.len(), n); + } + assert!(s.is_empty()) + } + fn push_popn(bits: &[bool]) { + let mut s = AbstractStack::new(); + let mut s_no_eq = AbstractStack::new(); + for bit in bits { + s.push(*bit).unwrap(); + s_no_eq.push(*bit).unwrap(); + } + assert_eq!(s.len(), bits.len() as u64); + assert_eq!(s_no_eq.len(), bits.len() as u64); + let rl = run_lengths(bits); + s.assert_run_lengths(&rl); + s_no_eq.assert_run_lengths(&rl); + + let mut pop_cur = false; + let mut pop_count = 0; + let mut n = bits.len() as u64; + for bit in bits.iter().copied().rev() { + if pop_cur == bit { + pop_count += 1 + } else { + if pop_count > 0 { + assert_eq!(s.pop_eq_n(nonzero(pop_count)), Ok(pop_cur)); + n -= pop_count; + assert_eq!(s.len(), n); + } + pop_cur = bit; + pop_count = 1; + } + } + if pop_count > 0 { + assert_eq!(s.pop_eq_n(nonzero(pop_count)), Ok(pop_cur)); + } + if !bits.is_empty() { + s_no_eq.pop_any_n(nonzero(bits.len() as u64)).unwrap(); + } + assert!(s.is_empty()); + assert!(s_no_eq.is_empty()); + } + fn pushn_popn(bits: &[bool]) { + let mut s = AbstractStack::new(); + let mut s_no_eq = AbstractStack::new(); + let mut push_cur = false; + let mut push_count = 0; + let mut n = 0; + for bit in bits.iter().copied() { + if push_cur == bit { + push_count += 1; + } else { + s.push_n(push_cur, push_count).unwrap(); + s_no_eq.push_n(push_cur, push_count).unwrap(); + n += push_count; + assert_eq!(s.len(), n); + assert_eq!(s_no_eq.len(), n); + push_cur = bit; + push_count = 1; + } + } + s.push_n(push_cur, push_count).unwrap(); + s_no_eq.push_n(push_cur, push_count).unwrap(); + assert_eq!(s.len(), bits.len() as u64); + assert_eq!(s_no_eq.len(), bits.len() as u64); + let rl = run_lengths(bits); + s.assert_run_lengths(&rl); + s_no_eq.assert_run_lengths(&rl); + + let mut pop_cur = false; + let mut pop_count = 0; + let mut n = bits.len() as u64; + for bit in bits.iter().copied().rev() { + if pop_cur == bit { + pop_count += 1 + } else { + if pop_count > 0 { + assert_eq!(s.pop_eq_n(nonzero(pop_count)), Ok(pop_cur)); + n -= pop_count; + assert_eq!(s.len(), n); + } + pop_cur = bit; + pop_count = 1; + } + } + assert_eq!(s.pop_eq_n(nonzero(pop_count)), Ok(pop_cur)); + s_no_eq.pop_any_n(nonzero(bits.len() as u64)).unwrap(); + assert!(s.is_empty()); + assert!(s_no_eq.is_empty()); + } + for n in 0u8..=255 { + let bits: Vec = (0..=7).map(|i| (n & (1 << i)) != 0).collect(); + push_pop(&bits); + pushn_pop(&bits); + push_popn(&bits); + pushn_popn(&bits); + } +} + +fn nonzero(x: u64) -> NonZeroU64 { + NonZeroU64::new(x).unwrap() +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/binary_config.rs b/CoqOfRust/move_sui/translations/move_binary_format/binary_config.rs new file mode 100644 index 000000000..64a87d2e3 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/binary_config.rs @@ -0,0 +1,99 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::file_format_common::VERSION_MAX; + +/// Configuration for the binary format related to table size. +/// Maps to all tables in the binary format. +#[derive(Clone, Debug)] +pub struct TableConfig { + pub module_handles: u16, + pub struct_handles: u16, + pub function_handles: u16, + pub function_instantiations: u16, + pub signatures: u16, + pub constant_pool: u16, + pub identifiers: u16, + pub address_identifiers: u16, + pub struct_defs: u16, + pub struct_def_instantiations: u16, + pub function_defs: u16, + pub field_handles: u16, + pub field_instantiations: u16, + pub friend_decls: u16, +} + +impl TableConfig { + // The deserializer and other parts of the system already have limits in place, + // this is the "legacy" configuration that is effectively the "no limits" setup. + // This table is a noop with `u16::MAX`. + pub fn legacy() -> Self { + TableConfig { + module_handles: u16::MAX, + struct_handles: u16::MAX, + function_handles: u16::MAX, + function_instantiations: u16::MAX, + signatures: u16::MAX, + constant_pool: u16::MAX, + identifiers: u16::MAX, + address_identifiers: u16::MAX, + struct_defs: u16::MAX, + struct_def_instantiations: u16::MAX, + function_defs: u16::MAX, + field_handles: u16::MAX, + field_instantiations: u16::MAX, + friend_decls: u16::MAX, + } + } +} + +/// Configuration information for deserializing a binary. +/// Controls multiple aspects of the deserialization process. +#[derive(Clone, Debug)] +pub struct BinaryConfig { + pub max_binary_format_version: u32, + pub check_no_extraneous_bytes: bool, + pub table_config: TableConfig, +} + +impl BinaryConfig { + pub fn new( + max_binary_format_version: u32, + check_no_extraneous_bytes: bool, + table_config: TableConfig, + ) -> Self { + Self { + max_binary_format_version, + check_no_extraneous_bytes, + table_config, + } + } + + // We want to make this disappear from the public API in favor of a "true" config + pub fn legacy(max_binary_format_version: u32, check_no_extraneous_bytes: bool) -> Self { + Self { + max_binary_format_version, + check_no_extraneous_bytes, + table_config: TableConfig::legacy(), + } + } + + /// Run always with the max version but with controllable "extraneous bytes check" + pub fn with_extraneous_bytes_check(check_no_extraneous_bytes: bool) -> Self { + Self { + max_binary_format_version: VERSION_MAX, + check_no_extraneous_bytes, + table_config: TableConfig::legacy(), + } + } + + /// VERSION_MAX and check_no_extraneous_bytes = true + /// common "standard/default" in code base now + pub fn standard() -> Self { + Self { + max_binary_format_version: VERSION_MAX, + check_no_extraneous_bytes: true, + table_config: TableConfig::legacy(), + } + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/check_bounds.rs b/CoqOfRust/move_sui/translations/move_binary_format/check_bounds.rs new file mode 100644 index 000000000..1f2f61ea2 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/check_bounds.rs @@ -0,0 +1,668 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + errors::{ + bounds_error, offset_out_of_bounds as offset_out_of_bounds_error, verification_error, + PartialVMError, PartialVMResult, + }, + file_format::{ + AbilitySet, Bytecode, CodeOffset, CodeUnit, CompiledModule, Constant, FieldHandle, + FieldInstantiation, FunctionDefinition, FunctionDefinitionIndex, FunctionHandle, + FunctionInstantiation, LocalIndex, ModuleHandle, Signature, SignatureToken, + StructDefInstantiation, StructDefinition, StructFieldInformation, StructHandle, TableIndex, + }, + internals::ModuleIndex, + IndexKind, +}; +use move_core_types::vm_status::StatusCode; + +enum BoundsCheckingContext { + Module, + ModuleFunction(FunctionDefinitionIndex), +} +pub struct BoundsChecker<'a> { + module: &'a CompiledModule, + context: BoundsCheckingContext, +} + +impl<'a> BoundsChecker<'a> { + pub fn verify_module(module: &'a CompiledModule) -> PartialVMResult<()> { + let mut bounds_check = Self { + module, + context: BoundsCheckingContext::Module, + }; + if bounds_check.module.module_handles().is_empty() { + let status = + verification_error(StatusCode::NO_MODULE_HANDLES, IndexKind::ModuleHandle, 0); + return Err(status); + } + bounds_check.verify_impl() + } + + fn verify_impl(&mut self) -> PartialVMResult<()> { + self.check_signatures()?; + self.check_constants()?; + self.check_module_handles()?; + self.check_self_module_handle()?; + self.check_struct_handles()?; + self.check_function_handles()?; + self.check_field_handles()?; + self.check_friend_decls()?; + self.check_struct_instantiations()?; + self.check_function_instantiations()?; + self.check_field_instantiations()?; + self.check_struct_defs()?; + self.check_function_defs() + } + + fn check_signatures(&self) -> PartialVMResult<()> { + for signature in self.module.signatures() { + self.check_signature(signature)? + } + Ok(()) + } + + fn check_constants(&self) -> PartialVMResult<()> { + for constant in self.module.constant_pool() { + self.check_constant(constant)? + } + Ok(()) + } + + fn check_module_handles(&self) -> PartialVMResult<()> { + for script_handle in self.module.module_handles() { + self.check_module_handle(script_handle)? + } + Ok(()) + } + + fn check_struct_handles(&self) -> PartialVMResult<()> { + for struct_handle in self.module.struct_handles() { + self.check_struct_handle(struct_handle)? + } + Ok(()) + } + + fn check_function_handles(&self) -> PartialVMResult<()> { + for function_handle in self.module.function_handles() { + self.check_function_handle(function_handle)? + } + Ok(()) + } + + fn check_field_handles(&self) -> PartialVMResult<()> { + for field_handle in self.module.field_handles() { + self.check_field_handle(field_handle)? + } + Ok(()) + } + + fn check_friend_decls(&self) -> PartialVMResult<()> { + for friend_decl in self.module.friend_decls() { + self.check_module_handle(friend_decl)? + } + Ok(()) + } + + fn check_struct_instantiations(&self) -> PartialVMResult<()> { + for struct_instantiation in self.module.struct_instantiations() { + self.check_struct_instantiation(struct_instantiation)? + } + Ok(()) + } + + fn check_function_instantiations(&self) -> PartialVMResult<()> { + for function_instantiation in self.module.function_instantiations() { + self.check_function_instantiation(function_instantiation)? + } + Ok(()) + } + + fn check_field_instantiations(&self) -> PartialVMResult<()> { + for field_instantiation in self.module.field_instantiations() { + self.check_field_instantiation(field_instantiation)? + } + Ok(()) + } + + fn check_struct_defs(&self) -> PartialVMResult<()> { + for struct_def in self.module.struct_defs() { + self.check_struct_def(struct_def)? + } + Ok(()) + } + + fn check_function_defs(&mut self) -> PartialVMResult<()> { + for (function_def_idx, function_def) in self.module.function_defs().iter().enumerate() { + self.check_function_def(function_def_idx, function_def)? + } + Ok(()) + } + + fn check_module_handle(&self, module_handle: &ModuleHandle) -> PartialVMResult<()> { + check_bounds_impl(self.module.address_identifiers(), module_handle.address)?; + check_bounds_impl(self.module.identifiers(), module_handle.name) + } + + fn check_self_module_handle(&self) -> PartialVMResult<()> { + check_bounds_impl(self.module.module_handles(), self.module.self_handle_idx()) + } + + fn check_struct_handle(&self, struct_handle: &StructHandle) -> PartialVMResult<()> { + check_bounds_impl(self.module.module_handles(), struct_handle.module)?; + check_bounds_impl(self.module.identifiers(), struct_handle.name) + } + + fn check_function_handle(&self, function_handle: &FunctionHandle) -> PartialVMResult<()> { + check_bounds_impl(self.module.module_handles(), function_handle.module)?; + check_bounds_impl(self.module.identifiers(), function_handle.name)?; + check_bounds_impl(self.module.signatures(), function_handle.parameters)?; + check_bounds_impl(self.module.signatures(), function_handle.return_)?; + // function signature type paramters must be in bounds to the function type parameters + let type_param_count = function_handle.type_parameters.len(); + if let Some(sig) = self + .module + .signatures() + .get(function_handle.parameters.into_index()) + { + for ty in &sig.0 { + self.check_type_parameter(ty, type_param_count)? + } + } + if let Some(sig) = self + .module + .signatures() + .get(function_handle.return_.into_index()) + { + for ty in &sig.0 { + self.check_type_parameter(ty, type_param_count)? + } + } + Ok(()) + } + + fn check_field_handle(&self, field_handle: &FieldHandle) -> PartialVMResult<()> { + check_bounds_impl(self.module.struct_defs(), field_handle.owner)?; + // field offset must be in bounds, struct def just checked above must exist + if let Some(struct_def) = &self + .module + .struct_defs() + .get(field_handle.owner.into_index()) + { + let fields_count = match &struct_def.field_information { + StructFieldInformation::Native => 0, + StructFieldInformation::Declared(fields) => fields.len(), + }; + if field_handle.field as usize >= fields_count { + return Err(bounds_error( + StatusCode::INDEX_OUT_OF_BOUNDS, + IndexKind::MemberCount, + field_handle.field, + fields_count, + )); + } + } + Ok(()) + } + + fn check_struct_instantiation( + &self, + struct_instantiation: &StructDefInstantiation, + ) -> PartialVMResult<()> { + check_bounds_impl(self.module.struct_defs(), struct_instantiation.def)?; + check_bounds_impl( + self.module.signatures(), + struct_instantiation.type_parameters, + ) + } + + fn check_function_instantiation( + &self, + function_instantiation: &FunctionInstantiation, + ) -> PartialVMResult<()> { + check_bounds_impl( + self.module.function_handles(), + function_instantiation.handle, + )?; + check_bounds_impl( + self.module.signatures(), + function_instantiation.type_parameters, + ) + } + + fn check_field_instantiation( + &self, + field_instantiation: &FieldInstantiation, + ) -> PartialVMResult<()> { + check_bounds_impl(self.module.field_handles(), field_instantiation.handle)?; + check_bounds_impl( + self.module.signatures(), + field_instantiation.type_parameters, + ) + } + + fn check_signature(&self, signature: &Signature) -> PartialVMResult<()> { + for ty in &signature.0 { + self.check_type(ty)? + } + Ok(()) + } + + fn check_constant(&self, constant: &Constant) -> PartialVMResult<()> { + self.check_type(&constant.type_) + } + + fn check_struct_def(&self, struct_def: &StructDefinition) -> PartialVMResult<()> { + check_bounds_impl(self.module.struct_handles(), struct_def.struct_handle)?; + // check signature (type) and type parameter for the field type + if let StructFieldInformation::Declared(fields) = &struct_def.field_information { + let type_param_count = self + .module + .struct_handles() + .get(struct_def.struct_handle.into_index()) + .map_or(0, |sh| sh.type_parameters.len()); + // field signatures are inlined + for field in fields { + check_bounds_impl(self.module.identifiers(), field.name)?; + self.check_type(&field.signature.0)?; + self.check_type_parameter(&field.signature.0, type_param_count)?; + } + } + Ok(()) + } + + fn check_function_def( + &mut self, + function_def_idx: usize, + function_def: &FunctionDefinition, + ) -> PartialVMResult<()> { + self.context = BoundsCheckingContext::ModuleFunction(FunctionDefinitionIndex( + function_def_idx as TableIndex, + )); + check_bounds_impl(self.module.function_handles(), function_def.function)?; + for ty in &function_def.acquires_global_resources { + check_bounds_impl(self.module.struct_defs(), *ty)?; + } + + let code_unit = match &function_def.code { + Some(code) => code, + None => return Ok(()), + }; + + if function_def.function.into_index() >= self.module.function_handles().len() { + return Err(verification_error( + StatusCode::INDEX_OUT_OF_BOUNDS, + IndexKind::FunctionDefinition, + function_def_idx as TableIndex, + )); + } + let function_handle = &self.module.function_handles()[function_def.function.into_index()]; + if function_handle.parameters.into_index() >= self.module.signatures().len() { + return Err(verification_error( + StatusCode::INDEX_OUT_OF_BOUNDS, + IndexKind::FunctionDefinition, + function_def_idx as TableIndex, + )); + } + let parameters = &self.module.signatures()[function_handle.parameters.into_index()]; + + self.check_code( + code_unit, + &function_handle.type_parameters, + parameters, + function_def_idx, + ) + } + + fn check_code( + &self, + code_unit: &CodeUnit, + type_parameters: &[AbilitySet], + parameters: &Signature, + index: usize, + ) -> PartialVMResult<()> { + check_bounds_impl(self.module.signatures(), code_unit.locals)?; + + let locals = self.get_locals(code_unit)?; + // Use saturating add for stability + let locals_count = locals.len().saturating_add(parameters.len()); + + if locals_count > LocalIndex::MAX as usize { + return Err(verification_error( + StatusCode::TOO_MANY_LOCALS, + IndexKind::FunctionDefinition, + index as TableIndex, + )); + } + + // if there are locals check that the type parameters in local signature are in bounds. + let type_param_count = type_parameters.len(); + for local in locals { + self.check_type_parameter(local, type_param_count)? + } + + // check bytecodes + let code_len = code_unit.code.len(); + for (bytecode_offset, bytecode) in code_unit.code.iter().enumerate() { + use self::Bytecode::*; + + match bytecode { + LdConst(idx) => self.check_code_unit_bounds_impl( + self.module.constant_pool(), + *idx, + bytecode_offset, + )?, + MutBorrowField(idx) | ImmBorrowField(idx) => self.check_code_unit_bounds_impl( + self.module.field_handles(), + *idx, + bytecode_offset, + )?, + MutBorrowFieldGeneric(idx) | ImmBorrowFieldGeneric(idx) => { + self.check_code_unit_bounds_impl( + self.module.field_instantiations(), + *idx, + bytecode_offset, + )?; + // check type parameters in borrow are bound to the function type parameters + if let Some(field_inst) = + self.module.field_instantiations().get(idx.into_index()) + { + if let Some(sig) = self + .module + .signatures() + .get(field_inst.type_parameters.into_index()) + { + for ty in &sig.0 { + self.check_type_parameter(ty, type_param_count)? + } + } + } + } + Call(idx) => self.check_code_unit_bounds_impl( + self.module.function_handles(), + *idx, + bytecode_offset, + )?, + CallGeneric(idx) => { + self.check_code_unit_bounds_impl( + self.module.function_instantiations(), + *idx, + bytecode_offset, + )?; + // check type parameters in call are bound to the function type parameters + if let Some(func_inst) = + self.module.function_instantiations().get(idx.into_index()) + { + if let Some(sig) = self + .module + .signatures() + .get(func_inst.type_parameters.into_index()) + { + for ty in &sig.0 { + self.check_type_parameter(ty, type_param_count)? + } + } + } + } + Pack(idx) + | Unpack(idx) + | ExistsDeprecated(idx) + | ImmBorrowGlobalDeprecated(idx) + | MutBorrowGlobalDeprecated(idx) + | MoveFromDeprecated(idx) + | MoveToDeprecated(idx) => self.check_code_unit_bounds_impl( + self.module.struct_defs(), + *idx, + bytecode_offset, + )?, + PackGeneric(idx) + | UnpackGeneric(idx) + | ExistsGenericDeprecated(idx) + | ImmBorrowGlobalGenericDeprecated(idx) + | MutBorrowGlobalGenericDeprecated(idx) + | MoveFromGenericDeprecated(idx) + | MoveToGenericDeprecated(idx) => { + self.check_code_unit_bounds_impl( + self.module.struct_instantiations(), + *idx, + bytecode_offset, + )?; + // check type parameters in type operations are bound to the function type parameters + if let Some(struct_inst) = + self.module.struct_instantiations().get(idx.into_index()) + { + if let Some(sig) = self + .module + .signatures() + .get(struct_inst.type_parameters.into_index()) + { + for ty in &sig.0 { + self.check_type_parameter(ty, type_param_count)? + } + } + } + } + // Instructions that refer to this code block. + BrTrue(offset) | BrFalse(offset) | Branch(offset) => { + let offset = *offset as usize; + if offset >= code_len { + return Err(self.offset_out_of_bounds( + StatusCode::INDEX_OUT_OF_BOUNDS, + IndexKind::CodeDefinition, + offset, + code_len, + bytecode_offset as CodeOffset, + )); + } + } + // Instructions that refer to the locals. + CopyLoc(idx) | MoveLoc(idx) | StLoc(idx) | MutBorrowLoc(idx) + | ImmBorrowLoc(idx) => { + let idx = *idx as usize; + if idx >= locals_count { + return Err(self.offset_out_of_bounds( + StatusCode::INDEX_OUT_OF_BOUNDS, + IndexKind::LocalPool, + idx, + locals_count, + bytecode_offset as CodeOffset, + )); + } + } + + // Instructions that refer to a signature + VecPack(idx, _) + | VecLen(idx) + | VecImmBorrow(idx) + | VecMutBorrow(idx) + | VecPushBack(idx) + | VecPopBack(idx) + | VecUnpack(idx, _) + | VecSwap(idx) => { + self.check_code_unit_bounds_impl( + self.module.signatures(), + *idx, + bytecode_offset, + )?; + if let Some(sig) = self.module.signatures().get(idx.into_index()) { + for ty in &sig.0 { + self.check_type_parameter(ty, type_param_count)?; + } + } + } + + // List out the other options explicitly so there's a compile error if a new + // bytecode gets added. + FreezeRef | Pop | Ret | LdU8(_) | LdU16(_) | LdU32(_) | LdU64(_) | LdU256(_) + | LdU128(_) | CastU8 | CastU16 | CastU32 | CastU64 | CastU128 | CastU256 + | LdTrue | LdFalse | ReadRef | WriteRef | Add | Sub | Mul | Mod | Div | BitOr + | BitAnd | Xor | Shl | Shr | Or | And | Not | Eq | Neq | Lt | Gt | Le | Ge + | Abort | Nop => (), + } + } + Ok(()) + } + + fn check_type(&self, ty: &SignatureToken) -> PartialVMResult<()> { + use self::SignatureToken::*; + + for ty in ty.preorder_traversal() { + match ty { + Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address | Signer | TypeParameter(_) + | Reference(_) | MutableReference(_) | Vector(_) => (), + Struct(idx) => { + check_bounds_impl(self.module.struct_handles(), *idx)?; + if let Some(sh) = self.module.struct_handles().get(idx.into_index()) { + if !sh.type_parameters.is_empty() { + return Err(PartialVMError::new( + StatusCode::NUMBER_OF_TYPE_ARGUMENTS_MISMATCH, + ) + .with_message(format!( + "expected {} type parameters got 0 (Struct)", + sh.type_parameters.len(), + ))); + } + } + } + StructInstantiation(struct_inst) => { + let (idx, type_params) = &**struct_inst; + check_bounds_impl(self.module.struct_handles(), *idx)?; + if let Some(sh) = self.module.struct_handles().get(idx.into_index()) { + if sh.type_parameters.len() != type_params.len() { + return Err(PartialVMError::new( + StatusCode::NUMBER_OF_TYPE_ARGUMENTS_MISMATCH, + ) + .with_message(format!( + "expected {} type parameters got {}", + sh.type_parameters.len(), + type_params.len(), + ))); + } + } + } + } + } + Ok(()) + } + + fn check_type_parameter( + &self, + ty: &SignatureToken, + type_param_count: usize, + ) -> PartialVMResult<()> { + use self::SignatureToken::*; + + for ty in ty.preorder_traversal() { + match ty { + SignatureToken::TypeParameter(idx) => { + if *idx as usize >= type_param_count { + return Err(bounds_error( + StatusCode::INDEX_OUT_OF_BOUNDS, + IndexKind::TypeParameter, + *idx, + type_param_count, + )); + } + } + + Bool + | U8 + | U16 + | U32 + | U64 + | U128 + | U256 + | Address + | Signer + | Struct(_) + | Reference(_) + | MutableReference(_) + | Vector(_) + | StructInstantiation(_) => (), + } + } + Ok(()) + } + + fn check_code_unit_bounds_impl( + &self, + pool: &[T], + idx: I, + bytecode_offset: usize, + ) -> PartialVMResult<()> + where + I: ModuleIndex, + { + let idx = idx.into_index(); + let len = pool.len(); + if idx >= len { + Err(self.offset_out_of_bounds( + StatusCode::INDEX_OUT_OF_BOUNDS, + I::KIND, + idx, + len, + bytecode_offset as CodeOffset, + )) + } else { + Ok(()) + } + } + + fn get_locals(&self, code_unit: &CodeUnit) -> PartialVMResult<&[SignatureToken]> { + match self.module.signatures().get(code_unit.locals.into_index()) { + Some(signature) => Ok(&signature.0), + None => Err(bounds_error( + StatusCode::INDEX_OUT_OF_BOUNDS, + IndexKind::Signature, + code_unit.locals.into_index() as u16, + self.module.signatures().len(), + )), + } + } + + fn offset_out_of_bounds( + &self, + status: StatusCode, + kind: IndexKind, + target_offset: usize, + target_pool_len: usize, + cur_bytecode_offset: CodeOffset, + ) -> PartialVMError { + match self.context { + BoundsCheckingContext::Module => { + let msg = format!("Indexing into bytecode {} during bounds checking but 'current_function' was not set", cur_bytecode_offset); + PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR).with_message(msg) + } + BoundsCheckingContext::ModuleFunction(current_function_index) => { + offset_out_of_bounds_error( + status, + kind, + target_offset, + target_pool_len, + current_function_index, + cur_bytecode_offset, + ) + } + } + } +} + +fn check_bounds_impl(pool: &[T], idx: I) -> PartialVMResult<()> +where + I: ModuleIndex, +{ + let idx = idx.into_index(); + let len = pool.len(); + if idx >= len { + Err(bounds_error( + StatusCode::INDEX_OUT_OF_BOUNDS, + I::KIND, + idx as TableIndex, + len, + )) + } else { + Ok(()) + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/compatibility.rs b/CoqOfRust/move_sui/translations/move_binary_format/compatibility.rs new file mode 100644 index 000000000..4266d20aa --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/compatibility.rs @@ -0,0 +1,368 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use std::collections::BTreeSet; + +use crate::{ + errors::{PartialVMError, PartialVMResult}, + file_format::{AbilitySet, StructTypeParameter, Visibility}, + file_format_common::VERSION_5, + normalized::Module, +}; +use move_core_types::vm_status::StatusCode; + +/// The result of a linking and layout compatibility check. Here is what the different combinations. NOTE that if `check_struct_layout` is false, type safety over a series of upgrades cannot be guaranteed. +/// mean: +/// `{ check_struct_and_pub_function_linking: true, check_struct_layout: true, check_friend_linking: true, check_private_entry_linking: true }`: fully backward compatible +/// `{ check_struct_and_pub_function_linking: true, check_struct_layout: true, check_friend_linking: true, check_private_entry_linking: false }`: Backwards compatible, private entry function signatures can change +/// `{ check_struct_and_pub_function_linking: true, check_struct_layout: true, check_friend_linking: false, check_private_entry_linking: true }`: Backward compatible, exclude the friend module declare and friend functions +/// `{ check_struct_and_pub_function_linking: true, check_struct_layout: true, check_friend_linking: false, check_private_entry_linking: false }`: Backward compatible, exclude the friend module declarations, friend functions, and private and friend entry function +/// `{ check_struct_and_pub_function_linking: false, check_struct_layout: true, check_friend_linking: false, check_private_entry_linking: _ }`: Dependent modules that reference functions or types in this module may not link. However, fixing, recompiling, and redeploying all dependent modules will work--no data migration needed. +/// `{ check_struct_and_pub_function_linking: true, check_struct_layout: false, check_friend_linking: true, check_private_entry_linking: _ }`: Attempting to read structs published by this module will now fail at runtime. However, dependent modules will continue to link. Requires data migration, but no changes to dependent modules. +/// `{ check_struct_and_pub_function_linking: false, check_struct_layout: false, check_friend_linking: false, check_private_entry_linking: _ }`: Everything is broken. Need both a data migration and changes to dependent modules. +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub struct Compatibility { + /// if false, do not ensure the dependent modules that reference public functions or structs in this module can link + pub check_struct_and_pub_function_linking: bool, + /// if false, do not ensure the struct layout capability + pub check_struct_layout: bool, + /// if false, treat `friend` as `private` when `check_struct_and_pub_function_linking`. + pub check_friend_linking: bool, + /// if false, treat `entry` as `private` when `check_struct_and_pub_function_linking`. + pub check_private_entry_linking: bool, + /// The set of abilities that cannot be added to an already exisiting type. + pub disallowed_new_abilities: AbilitySet, + /// Don't allow generic type parameters in structs to change their abilities or constraints. + pub disallow_change_struct_type_params: bool, +} + +impl Default for Compatibility { + fn default() -> Self { + Self { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: true, + check_private_entry_linking: true, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: true, + } + } +} + +impl Compatibility { + pub fn full_check() -> Self { + Self::default() + } + + pub fn no_check() -> Self { + Self { + check_struct_and_pub_function_linking: false, + check_struct_layout: false, + check_friend_linking: false, + check_private_entry_linking: false, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: false, + } + } + + pub fn need_check_compat(&self) -> bool { + self != &Self::no_check() + } + + /// Check compatibility for `new_module` relative to old module `old_module`. + pub fn check(&self, old_module: &Module, new_module: &Module) -> PartialVMResult<()> { + let mut struct_and_function_linking = true; + let mut struct_layout = true; + let mut friend_linking = true; + let mut entry_linking = true; + + // module's name and address are unchanged + if old_module.address != new_module.address || old_module.name != new_module.name { + struct_and_function_linking = false; + } + + // old module's structs are a subset of the new module's structs + for (name, old_struct) in &old_module.structs { + let Some(new_struct) = new_module.structs.get(name) else { + // Struct not present in new . Existing modules that depend on this struct will fail to link with the new version of the module. + // Also, struct layout cannot be guaranteed transitively, because after + // removing the struct, it could be re-added later with a different layout. + struct_and_function_linking = false; + struct_layout = false; + break; + }; + + if !struct_abilities_compatible( + self.disallowed_new_abilities, + old_struct.abilities, + new_struct.abilities, + ) || !struct_type_parameters_compatible( + self.disallow_change_struct_type_params, + &old_struct.type_parameters, + &new_struct.type_parameters, + ) { + struct_and_function_linking = false; + } + if new_struct.fields != old_struct.fields { + // Fields changed. Code in this module will fail at runtime if it tries to + // read a previously published struct value + // TODO: this is a stricter definition than required. We could in principle + // choose that changing the name (but not position or type) of a field is + // compatible. The VM does not care about the name of a field + // (it's purely informational), but clients presumably do. + struct_layout = false + } + } + + // The modules are considered as compatible function-wise when all the conditions are met: + // + // - old module's public functions are a subset of the new module's public functions + // (i.e. we cannot remove or change public functions) + // - old module's script functions are a subset of the new module's script functions + // (i.e. we cannot remove or change script functions) + // - for any friend function that is removed or changed in the old module + // - if the function visibility is upgraded to public, it is OK + // - otherwise, it is considered as incompatible. + // + // NOTE: it is possible to relax the compatibility checking for a friend function, i.e., + // we can remove/change a friend function if the function is not used by any module in the + // friend list. But for simplicity, we decided to go to the more restrictive form now and + // we may revisit this in the future. + for (name, old_func) in &old_module.functions { + let Some(new_func) = new_module.functions.get(name) else { + if old_func.visibility == Visibility::Friend { + friend_linking = false; + } else if old_func.visibility != Visibility::Private { + struct_and_function_linking = false; + } else if old_func.is_entry && self.check_private_entry_linking { + // This must be a private entry function. So set the link breakage if we're + // checking for that. + entry_linking = false; + } + continue; + }; + + // Check visibility compatibility + match (old_func.visibility, new_func.visibility) { + (Visibility::Public, Visibility::Private | Visibility::Friend) => { + struct_and_function_linking = false + } + (Visibility::Friend, Visibility::Private) => friend_linking = false, + _ => (), + } + + // Check entry compatibility + if old_module.file_format_version < VERSION_5 + && new_module.file_format_version < VERSION_5 + && old_func.visibility != Visibility::Private + && old_func.is_entry != new_func.is_entry + { + entry_linking = false + } else if old_func.is_entry && !new_func.is_entry { + entry_linking = false; + } + + // Check signature compatibility + if old_func.parameters != new_func.parameters + || old_func.return_ != new_func.return_ + || !fun_type_parameters_compatible( + &old_func.type_parameters, + &new_func.type_parameters, + ) + { + match old_func.visibility { + Visibility::Friend => friend_linking = false, + Visibility::Public => struct_and_function_linking = false, + Visibility::Private => (), + } + + if old_func.is_entry { + entry_linking = false; + } + } + } + + // check friend declarations compatibility + // + // - additions to the list are allowed + // - removals are not allowed + // + let old_friend_module_ids: BTreeSet<_> = old_module.friends.iter().cloned().collect(); + let new_friend_module_ids: BTreeSet<_> = new_module.friends.iter().cloned().collect(); + if !old_friend_module_ids.is_subset(&new_friend_module_ids) { + friend_linking = false; + } + + if self.check_struct_and_pub_function_linking && !struct_and_function_linking { + return Err(PartialVMError::new( + StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE, + )); + } + if self.check_struct_layout && !struct_layout { + return Err(PartialVMError::new( + StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE, + )); + } + if self.check_friend_linking && !friend_linking { + return Err(PartialVMError::new( + StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE, + )); + } + if self.check_private_entry_linking && !entry_linking { + return Err(PartialVMError::new( + StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE, + )); + } + + Ok(()) + } +} + +// When upgrading, the new abilities must be a superset of the old abilities. +// Adding an ability is fine as long as it's not in the disallowed_new_abilities, +// but removing an ability could cause existing usages to fail. +fn struct_abilities_compatible( + disallowed_new_abilities: AbilitySet, + old_abilities: AbilitySet, + new_abilities: AbilitySet, +) -> bool { + old_abilities.is_subset(new_abilities) + && disallowed_new_abilities.into_iter().all(|ability| { + // If the new abilities have the ability the old ones must have it to + !new_abilities.has_ability(ability) || old_abilities.has_ability(ability) + }) +} + +// When upgrading, the new type parameters must be the same length, and the new type parameter +// constraints must be compatible +fn fun_type_parameters_compatible( + old_type_parameters: &[AbilitySet], + new_type_parameters: &[AbilitySet], +) -> bool { + old_type_parameters.len() == new_type_parameters.len() + && old_type_parameters.iter().zip(new_type_parameters).all( + |(old_type_parameter_constraint, new_type_parameter_constraint)| { + type_parameter_constraints_compatible( + false, // generic abilities can change for functions + *old_type_parameter_constraint, + *new_type_parameter_constraint, + ) + }, + ) +} + +fn struct_type_parameters_compatible( + disallow_changing_generic_abilities: bool, + old_type_parameters: &[StructTypeParameter], + new_type_parameters: &[StructTypeParameter], +) -> bool { + old_type_parameters.len() == new_type_parameters.len() + && old_type_parameters.iter().zip(new_type_parameters).all( + |(old_type_parameter, new_type_parameter)| { + type_parameter_phantom_decl_compatible( + disallow_changing_generic_abilities, + old_type_parameter, + new_type_parameter, + ) && type_parameter_constraints_compatible( + disallow_changing_generic_abilities, + old_type_parameter.constraints, + new_type_parameter.constraints, + ) + }, + ) +} + +// When upgrading, the new constraints must be a subset of (or equal to) the old constraints. +// Removing an ability is fine, but adding an ability could cause existing callsites to fail +fn type_parameter_constraints_compatible( + disallow_changing_generic_abilities: bool, + old_type_constraints: AbilitySet, + new_type_constraints: AbilitySet, +) -> bool { + if disallow_changing_generic_abilities { + old_type_constraints == new_type_constraints + } else { + new_type_constraints.is_subset(old_type_constraints) + } +} + +// Adding a phantom annotation to a parameter won't break clients because that can only increase the +// the set of abilities in struct instantiations. Put it differently, adding phantom declarations +// relaxes the requirements for clients. +fn type_parameter_phantom_decl_compatible( + disallow_changing_generic_abilities: bool, + old_type_parameter: &StructTypeParameter, + new_type_parameter: &StructTypeParameter, +) -> bool { + if disallow_changing_generic_abilities { + // phantom/non-phantom cannot change from one version to the next. + old_type_parameter.is_phantom == new_type_parameter.is_phantom + } else { + // old_type_paramter.is_phantom => new_type_parameter.is_phantom + !old_type_parameter.is_phantom || new_type_parameter.is_phantom + } +} + +/// A simpler, and stricter compatibility checker relating to the inclusion of the old module in +/// the new. +#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq)] +pub enum InclusionCheck { + Subset, + Equal, +} + +impl InclusionCheck { + // Check that all code in `old_module` is included `new_module`. If `Exact` no new code can be + // in `new_module` (Note: `new_module` may have larger pools, but they are not accessed by the + // code). + pub fn check(&self, old_module: &Module, new_module: &Module) -> PartialVMResult<()> { + let err = Err(PartialVMError::new( + StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE, + )); + + // Module checks + if old_module.address != new_module.address + || old_module.name != new_module.name + || old_module.file_format_version > new_module.file_format_version + { + return err; + } + + // If we're checking exactness we make sure there's an inclusion, and that the size of all + // of the tables are the exact same except for constants. + if (self == &Self::Equal) + && (old_module.structs.len() != new_module.structs.len() + || old_module.functions.len() != new_module.functions.len() + || old_module.friends.len() != new_module.friends.len()) + { + return err; + } + + // Struct checks + for (name, old_struct) in &old_module.structs { + match new_module.structs.get(name) { + Some(new_struct) if old_struct == new_struct => (), + _ => { + return err; + } + }; + } + + // Function checks + for (name, old_func) in &old_module.functions { + match new_module + .functions + .get(name) + .or_else(|| new_module.functions.get(name)) + { + Some(new_func) if old_func == new_func => (), + _ => { + return err; + } + } + } + + Ok(()) + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/constant.rs b/CoqOfRust/move_sui/translations/move_binary_format/constant.rs new file mode 100644 index 000000000..7e0e7c7c8 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/constant.rs @@ -0,0 +1,57 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::file_format::{Constant, SignatureToken}; + +use move_core_types::runtime_value::{MoveTypeLayout, MoveValue}; + +fn sig_to_ty(sig: &SignatureToken) -> Option { + match sig { + SignatureToken::Signer => Some(MoveTypeLayout::Signer), + SignatureToken::Address => Some(MoveTypeLayout::Address), + SignatureToken::Bool => Some(MoveTypeLayout::Bool), + SignatureToken::U8 => Some(MoveTypeLayout::U8), + SignatureToken::U16 => Some(MoveTypeLayout::U16), + SignatureToken::U32 => Some(MoveTypeLayout::U32), + SignatureToken::U64 => Some(MoveTypeLayout::U64), + SignatureToken::U128 => Some(MoveTypeLayout::U128), + SignatureToken::U256 => Some(MoveTypeLayout::U256), + SignatureToken::Vector(v) => Some(MoveTypeLayout::Vector(Box::new(sig_to_ty(v.as_ref())?))), + SignatureToken::Reference(_) + | SignatureToken::MutableReference(_) + | SignatureToken::Struct(_) + | SignatureToken::TypeParameter(_) + | SignatureToken::StructInstantiation(_) => None, + } +} + +fn ty_to_sig(ty: &MoveTypeLayout) -> Option { + match ty { + MoveTypeLayout::Address => Some(SignatureToken::Address), + MoveTypeLayout::Signer => Some(SignatureToken::Signer), + MoveTypeLayout::U8 => Some(SignatureToken::U8), + MoveTypeLayout::U16 => Some(SignatureToken::U16), + MoveTypeLayout::U32 => Some(SignatureToken::U32), + MoveTypeLayout::U64 => Some(SignatureToken::U64), + MoveTypeLayout::U128 => Some(SignatureToken::U128), + MoveTypeLayout::U256 => Some(SignatureToken::U256), + MoveTypeLayout::Vector(v) => Some(SignatureToken::Vector(Box::new(ty_to_sig(v.as_ref())?))), + MoveTypeLayout::Struct(_) => None, + MoveTypeLayout::Bool => Some(SignatureToken::Bool), + } +} + +impl Constant { + pub fn serialize_constant(ty: &MoveTypeLayout, v: &MoveValue) -> Option { + Some(Self { + type_: ty_to_sig(ty)?, + data: v.simple_serialize()?, + }) + } + + pub fn deserialize_constant(&self) -> Option { + let ty = sig_to_ty(&self.type_)?; + MoveValue::simple_deserialize(&self.data, &ty).ok() + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/control_flow_graph.rs b/CoqOfRust/move_sui/translations/move_binary_format/control_flow_graph.rs new file mode 100644 index 000000000..63ac1e0a2 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/control_flow_graph.rs @@ -0,0 +1,337 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! This module defines the control-flow graph uses for bytecode verification. +use crate::file_format::{Bytecode, CodeOffset}; +use std::collections::{btree_map::Entry, BTreeMap, BTreeSet}; + +// BTree/Hash agnostic type wrappers +type Map = BTreeMap; +type Set = BTreeSet; + +pub type BlockId = CodeOffset; + +/// A trait that specifies the basic requirements for a CFG +pub trait ControlFlowGraph { + /// Start index of the block ID in the bytecode vector + fn block_start(&self, block_id: BlockId) -> CodeOffset; + + /// End index of the block ID in the bytecode vector + fn block_end(&self, block_id: BlockId) -> CodeOffset; + + /// Successors of the block ID in the bytecode vector + fn successors(&self, block_id: BlockId) -> &Vec; + + /// Return the next block in traversal order + fn next_block(&self, block_id: BlockId) -> Option; + + /// Iterator over the indexes of instructions in this block + fn instr_indexes(&self, block_id: BlockId) -> Box>; + + /// Return an iterator over the blocks of the CFG + fn blocks(&self) -> Vec; + + /// Return the number of blocks (vertices) in the control flow graph + fn num_blocks(&self) -> u16; + + /// Return the id of the entry block for this control-flow graph + /// Note: even a CFG with no instructions has an (empty) entry block. + fn entry_block_id(&self) -> BlockId; + + /// Checks if the block ID is a loop head + fn is_loop_head(&self, block_id: BlockId) -> bool; + + /// Checks if the the edge from cur->next is a back edge + /// returns false if the edge is not in the cfg + fn is_back_edge(&self, cur: BlockId, next: BlockId) -> bool; + + /// Return the number of back edges in the cfg + fn num_back_edges(&self) -> usize; +} + +struct BasicBlock { + exit: CodeOffset, + successors: Vec, +} + +/// The control flow graph that we build from the bytecode. +pub struct VMControlFlowGraph { + /// The basic blocks + blocks: Map, + /// Basic block ordering for traversal + traversal_successors: Map, + /// Map of loop heads with all of their back edges + loop_heads: Map>, +} + +impl BasicBlock { + pub fn display(&self, entry: BlockId) { + println!("+=======================+"); + println!("| Enter: {} |", entry); + println!("+-----------------------+"); + println!("==> Children: {:?}", self.successors); + println!("+-----------------------+"); + println!("| Exit: {} |", self.exit); + println!("+=======================+"); + } +} + +const ENTRY_BLOCK_ID: BlockId = 0; + +impl VMControlFlowGraph { + pub fn new(code: &[Bytecode]) -> Self { + let code_len = code.len() as CodeOffset; + // First go through and collect block ids, i.e., offsets that begin basic blocks. + // Need to do this first in order to handle backwards edges. + let mut block_ids = Set::new(); + block_ids.insert(ENTRY_BLOCK_ID); + for pc in 0..code.len() { + VMControlFlowGraph::record_block_ids(pc as CodeOffset, code, &mut block_ids); + } + + // Create basic blocks + let mut blocks = Map::new(); + let mut entry = 0; + let mut exit_to_entry = Map::new(); + for pc in 0..code.len() { + let co_pc = pc as CodeOffset; + + // Create a basic block + if Self::is_end_of_block(co_pc, code, &block_ids) { + let exit = co_pc; + exit_to_entry.insert(exit, entry); + let successors = Bytecode::get_successors(co_pc, code); + let bb = BasicBlock { exit, successors }; + blocks.insert(entry, bb); + entry = co_pc + 1; + } + } + let blocks = blocks; + assert_eq!(entry, code_len); + + // # Loop analysis + // + // This section identifies loops in the control-flow graph, picks a back edge and loop head + // (the basic block the back edge returns to), and decides the order that blocks are + // traversed during abstract interpretation (reverse post-order). + // + // The implementation is based on the algorithm for finding widening points in Section 4.1, + // "Depth-first numbering" of Bourdoncle [1993], "Efficient chaotic iteration strategies + // with widenings." + // + // NB. The comments below refer to a block's sub-graph -- the reflexive transitive closure + // of its successor edges, modulo cycles. + + #[derive(Copy, Clone)] + enum Exploration { + InProgress, + Done, + } + + let mut exploration: Map = Map::new(); + let mut stack = vec![ENTRY_BLOCK_ID]; + + // For every loop in the CFG that is reachable from the entry block, there is an entry in + // `loop_heads` mapping to all the back edges pointing to it, and vice versa. + // + // Entry in `loop_heads` implies loop in the CFG is justified by the comments in the loop + // below. Loop in the CFG implies entry in `loop_heads` is justified by considering the + // point at which the first node in that loop, `F` is added to the `exploration` map: + // + // - By definition `F` is part of a loop, meaning there is a block `L` such that: + // + // F - ... -> L -> F + // + // - `F` will not transition to `Done` until all the nodes reachable from it (including `L`) + // have been visited. + // - Because `F` is the first node seen in the loop, all the other nodes in the loop + // (including `L`) will be visited while `F` is `InProgress`. + // - Therefore, we will process the `L -> F` edge while `F` is `InProgress`. + // - Therefore, we will record a back edge to it. + let mut loop_heads: Map> = Map::new(); + + // Blocks appear in `post_order` after all the blocks in their (non-reflexive) sub-graph. + let mut post_order = Vec::with_capacity(blocks.len()); + + while let Some(block) = stack.pop() { + match exploration.entry(block) { + Entry::Vacant(entry) => { + // Record the fact that exploration of this block and its sub-graph has started. + entry.insert(Exploration::InProgress); + + // Push the block back on the stack to finish processing it, and mark it as done + // once its sub-graph has been traversed. + stack.push(block); + + for succ in &blocks[&block].successors { + match exploration.get(succ) { + // This successor has never been visited before, add it to the stack to + // be explored before `block` gets marked `Done`. + None => stack.push(*succ), + + // This block's sub-graph was being explored, meaning it is a (reflexive + // transitive) predecessor of `block` as well as being a successor, + // implying a loop has been detected -- greedily choose the successor + // block as the loop head. + Some(Exploration::InProgress) => { + loop_heads.entry(*succ).or_default().insert(block); + } + + // Cross-edge detected, this block and its entire sub-graph (modulo + // cycles) has already been explored via a different path, and is + // already present in `post_order`. + Some(Exploration::Done) => { /* skip */ } + }; + } + } + + Entry::Occupied(mut entry) => match entry.get() { + // Already traversed the sub-graph reachable from this block, so skip it. + Exploration::Done => continue, + + // Finish up the traversal by adding this block to the post-order traversal + // after its sub-graph (modulo cycles). + Exploration::InProgress => { + post_order.push(block); + entry.insert(Exploration::Done); + } + }, + } + } + + let traversal_order = { + // This reverse post order is akin to a topological sort (ignoring cycles) and is + // different from a pre-order in the presence of diamond patterns in the graph. + post_order.reverse(); + post_order + }; + + // build a mapping from a block id to the next block id in the traversal order + let traversal_successors = traversal_order + .windows(2) + .map(|window| { + debug_assert!(window.len() == 2); + (window[0], window[1]) + }) + .collect(); + + VMControlFlowGraph { + blocks, + traversal_successors, + loop_heads, + } + } + + pub fn display(&self) { + for (entry, block) in &self.blocks { + block.display(*entry); + } + println!("Traversal: {:#?}", self.traversal_successors); + } + + fn is_end_of_block(pc: CodeOffset, code: &[Bytecode], block_ids: &Set) -> bool { + pc + 1 == (code.len() as CodeOffset) || block_ids.contains(&(pc + 1)) + } + + fn record_block_ids(pc: CodeOffset, code: &[Bytecode], block_ids: &mut Set) { + let bytecode = &code[pc as usize]; + + if let Some(offset) = bytecode.offset() { + block_ids.insert(*offset); + } + + if bytecode.is_branch() && pc + 1 < (code.len() as CodeOffset) { + block_ids.insert(pc + 1); + } + } + + /// A utility function that implements BFS-reachability from block_id with + /// respect to get_targets function + fn traverse_by(&self, block_id: BlockId) -> Vec { + let mut ret = Vec::new(); + // We use this index to keep track of our frontier. + let mut index = 0; + // Guard against cycles + let mut seen = Set::new(); + + ret.push(block_id); + seen.insert(&block_id); + + while index < ret.len() { + let block_id = ret[index]; + index += 1; + let successors = self.successors(block_id); + for block_id in successors.iter() { + if !seen.contains(&block_id) { + ret.push(*block_id); + seen.insert(block_id); + } + } + } + + ret + } + + pub fn reachable_from(&self, block_id: BlockId) -> Vec { + self.traverse_by(block_id) + } +} + +impl ControlFlowGraph for VMControlFlowGraph { + // Note: in the following procedures, it's safe not to check bounds because: + // - Every CFG (even one with no instructions) has a block at ENTRY_BLOCK_ID + // - The only way to acquire new BlockId's is via block_successors() + // - block_successors only() returns valid BlockId's + // Note: it is still possible to get a BlockId from one CFG and use it in another CFG where it + // is not valid. The design does not attempt to prevent this abuse of the API. + + fn block_start(&self, block_id: BlockId) -> CodeOffset { + block_id + } + + fn block_end(&self, block_id: BlockId) -> CodeOffset { + self.blocks[&block_id].exit + } + + fn successors(&self, block_id: BlockId) -> &Vec { + &self.blocks[&block_id].successors + } + + fn next_block(&self, block_id: BlockId) -> Option { + debug_assert!(self.blocks.contains_key(&block_id)); + self.traversal_successors.get(&block_id).copied() + } + + fn instr_indexes(&self, block_id: BlockId) -> Box> { + Box::new(self.block_start(block_id)..=self.block_end(block_id)) + } + + fn blocks(&self) -> Vec { + self.blocks.keys().cloned().collect() + } + + fn num_blocks(&self) -> u16 { + self.blocks.len() as u16 + } + + fn entry_block_id(&self) -> BlockId { + ENTRY_BLOCK_ID + } + + fn is_loop_head(&self, block_id: BlockId) -> bool { + self.loop_heads.contains_key(&block_id) + } + + fn is_back_edge(&self, cur: BlockId, next: BlockId) -> bool { + self.loop_heads + .get(&next) + .map_or(false, |back_edges| back_edges.contains(&cur)) + } + + fn num_back_edges(&self) -> usize { + self.loop_heads + .iter() + .fold(0, |acc, (_, edges)| acc + edges.len()) + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/deserializer.rs b/CoqOfRust/move_sui/translations/move_binary_format/deserializer.rs new file mode 100644 index 000000000..25670b3a7 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/deserializer.rs @@ -0,0 +1,1884 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + binary_config::{BinaryConfig, TableConfig}, + check_bounds::BoundsChecker, + errors::*, + file_format::*, + file_format_common::*, +}; +use move_core_types::{ + account_address::AccountAddress, identifier::Identifier, metadata::Metadata, + vm_status::StatusCode, +}; +use std::{ + collections::HashSet, + convert::TryInto, + io::{Cursor, Read}, +}; + +impl CompiledModule { + /// Deserialize a &[u8] slice into a `CompiledModule` instance. + pub fn deserialize_with_defaults(binary: &[u8]) -> BinaryLoaderResult { + Self::deserialize_with_config(binary, &BinaryConfig::with_extraneous_bytes_check(false)) + } + + /// Deserialize a &[u8] slice into a `CompiledModule` instance with settings + /// - Can specify up to the specified version. + /// - Can specify if the deserializer should error on trailing bytes + pub fn deserialize_with_config( + binary: &[u8], + binary_config: &BinaryConfig, + ) -> BinaryLoaderResult { + let module = deserialize_compiled_module(binary, binary_config)?; + BoundsChecker::verify_module(&module)?; + Ok(module) + } + + // exposed as a public function to enable testing the deserializer + #[doc(hidden)] + pub fn deserialize_no_check_bounds(binary: &[u8]) -> BinaryLoaderResult { + deserialize_compiled_module(binary, &BinaryConfig::with_extraneous_bytes_check(false)) + } +} + +/// Table info: table type, offset where the table content starts from, count of bytes for +/// the table content. +#[derive(Clone, Debug)] +struct Table { + kind: TableType, + offset: u32, + count: u32, +} + +impl Table { + fn new(kind: TableType, offset: u32, count: u32) -> Table { + Table { + kind, + offset, + count, + } + } +} + +fn read_u16_internal(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + let mut u16_bytes = [0; 2]; + cursor + .read_exact(&mut u16_bytes) + .map_err(|_| PartialVMError::new(StatusCode::BAD_U16))?; + Ok(u16::from_le_bytes(u16_bytes)) +} + +fn read_u32_internal(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + let mut u32_bytes = [0; 4]; + cursor + .read_exact(&mut u32_bytes) + .map_err(|_| PartialVMError::new(StatusCode::BAD_U32))?; + Ok(u32::from_le_bytes(u32_bytes)) +} + +fn read_u64_internal(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + let mut u64_bytes = [0; 8]; + cursor + .read_exact(&mut u64_bytes) + .map_err(|_| PartialVMError::new(StatusCode::BAD_U64))?; + Ok(u64::from_le_bytes(u64_bytes)) +} + +fn read_u128_internal(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + let mut u128_bytes = [0; 16]; + cursor + .read_exact(&mut u128_bytes) + .map_err(|_| PartialVMError::new(StatusCode::BAD_U128))?; + Ok(u128::from_le_bytes(u128_bytes)) +} + +fn read_u256_internal( + cursor: &mut VersionedCursor, +) -> BinaryLoaderResult { + let mut u256_bytes = [0; 32]; + cursor + .read_exact(&mut u256_bytes) + .map_err(|_| PartialVMError::new(StatusCode::BAD_U256))?; + Ok(move_core_types::u256::U256::from_le_bytes(&u256_bytes)) +} + +// +// Helpers to read all uleb128 encoded integers. +// +fn read_uleb_internal(cursor: &mut VersionedCursor, max: u64) -> BinaryLoaderResult +where + u64: TryInto, +{ + let x = cursor.read_uleb128_as_u64().map_err(|_| { + PartialVMError::new(StatusCode::MALFORMED).with_message("Bad Uleb".to_string()) + })?; + if x > max { + return Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Uleb greater than max requested".to_string())); + } + + x.try_into().map_err(|_| { + // TODO: review this status code. + let msg = "Failed to convert u64 to target integer type. This should not happen. Is the maximum value correct?".to_string(); + PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR).with_message(msg) + }) +} + +fn load_signature_index(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + Ok(SignatureIndex(read_uleb_internal( + cursor, + SIGNATURE_INDEX_MAX, + )?)) +} + +fn load_module_handle_index(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + Ok(ModuleHandleIndex(read_uleb_internal( + cursor, + MODULE_HANDLE_INDEX_MAX, + )?)) +} + +fn load_identifier_index(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + Ok(IdentifierIndex(read_uleb_internal( + cursor, + IDENTIFIER_INDEX_MAX, + )?)) +} + +fn load_struct_handle_index(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + Ok(StructHandleIndex(read_uleb_internal( + cursor, + STRUCT_HANDLE_INDEX_MAX, + )?)) +} + +fn load_address_identifier_index( + cursor: &mut VersionedCursor, +) -> BinaryLoaderResult { + Ok(AddressIdentifierIndex(read_uleb_internal( + cursor, + ADDRESS_INDEX_MAX, + )?)) +} + +fn load_struct_def_index( + cursor: &mut VersionedCursor, +) -> BinaryLoaderResult { + Ok(StructDefinitionIndex(read_uleb_internal( + cursor, + STRUCT_DEF_INDEX_MAX, + )?)) +} + +fn load_function_handle_index( + cursor: &mut VersionedCursor, +) -> BinaryLoaderResult { + Ok(FunctionHandleIndex(read_uleb_internal( + cursor, + FUNCTION_HANDLE_INDEX_MAX, + )?)) +} + +fn load_field_handle_index(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + Ok(FieldHandleIndex(read_uleb_internal( + cursor, + FIELD_HANDLE_INDEX_MAX, + )?)) +} + +fn load_field_inst_index( + cursor: &mut VersionedCursor, +) -> BinaryLoaderResult { + Ok(FieldInstantiationIndex(read_uleb_internal( + cursor, + FIELD_INST_INDEX_MAX, + )?)) +} + +fn load_function_inst_index( + cursor: &mut VersionedCursor, +) -> BinaryLoaderResult { + Ok(FunctionInstantiationIndex(read_uleb_internal( + cursor, + FUNCTION_INST_INDEX_MAX, + )?)) +} + +fn load_struct_def_inst_index( + cursor: &mut VersionedCursor, +) -> BinaryLoaderResult { + Ok(StructDefInstantiationIndex(read_uleb_internal( + cursor, + STRUCT_DEF_INST_INDEX_MAX, + )?)) +} + +fn load_constant_pool_index(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + Ok(ConstantPoolIndex(read_uleb_internal( + cursor, + CONSTANT_INDEX_MAX, + )?)) +} + +fn load_bytecode_count(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, BYTECODE_COUNT_MAX) +} + +fn load_bytecode_index(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, BYTECODE_INDEX_MAX) +} + +fn load_acquires_count(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, ACQUIRES_COUNT_MAX) +} + +fn load_field_count(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, FIELD_COUNT_MAX) +} + +fn load_type_parameter_count(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, TYPE_PARAMETER_COUNT_MAX) +} + +fn load_signature_size(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, SIGNATURE_SIZE_MAX) +} + +fn load_constant_size(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, CONSTANT_SIZE_MAX) +} + +fn load_metadata_key_size(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, METADATA_KEY_SIZE_MAX) +} + +fn load_metadata_value_size(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, METADATA_VALUE_SIZE_MAX) +} + +fn load_identifier_size(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, IDENTIFIER_SIZE_MAX) +} + +fn load_type_parameter_index(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, TYPE_PARAMETER_INDEX_MAX) +} + +fn load_field_offset(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, FIELD_OFFSET_MAX) +} + +fn load_table_count(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, TABLE_COUNT_MAX) +} + +fn load_table_offset(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, TABLE_OFFSET_MAX) +} + +fn load_table_size(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, TABLE_SIZE_MAX) +} + +fn load_local_index(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + read_uleb_internal(cursor, LOCAL_INDEX_MAX) +} + +/// Module internal function that manages deserialization of modules. +fn deserialize_compiled_module( + binary: &[u8], + binary_config: &BinaryConfig, +) -> BinaryLoaderResult { + let versioned_binary = VersionedBinary::initialize(binary, binary_config, true)?; + let version = versioned_binary.version(); + let self_module_handle_idx = versioned_binary.module_idx(); + let mut module = CompiledModule { + version, + self_module_handle_idx, + ..Default::default() + }; + + build_compiled_module(&mut module, &versioned_binary, &versioned_binary.tables)?; + + let end_pos = versioned_binary.binary_end_offset(); + let had_remaining_bytes = end_pos < binary.len(); + if binary_config.check_no_extraneous_bytes && had_remaining_bytes { + return Err(PartialVMError::new(StatusCode::TRAILING_BYTES)); + } + Ok(module) +} + +/// Reads all the table headers. +/// +/// Return a Vec that contains all the table headers defined and checked. +fn read_tables( + cursor: &mut VersionedCursor, + table_count: u8, + tables: &mut Vec
, +) -> BinaryLoaderResult<()> { + for _count in 0..table_count { + tables.push(read_table(cursor)?); + } + Ok(()) +} + +/// Reads a table from a slice at a given offset. +/// If a table is not recognized an error is returned. +fn read_table(cursor: &mut VersionedCursor) -> BinaryLoaderResult
{ + let kind = match cursor.read_u8() { + Ok(kind) => kind, + Err(_) => { + return Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Error reading table".to_string())) + } + }; + let table_offset = load_table_offset(cursor)?; + let count = load_table_size(cursor)?; + Ok(Table::new(TableType::from_u8(kind)?, table_offset, count)) +} + +/// Verify correctness of tables. +/// +/// Tables cannot have duplicates, must cover the entire blob and must be disjoint. +fn check_tables(tables: &mut Vec
, binary_len: usize) -> BinaryLoaderResult { + // there is no real reason to pass a mutable reference but we are sorting next line + tables.sort_by(|t1, t2| t1.offset.cmp(&t2.offset)); + + let mut current_offset: u32 = 0; + let mut table_types = HashSet::new(); + for table in tables { + if table.offset != current_offset { + return Err(PartialVMError::new(StatusCode::BAD_HEADER_TABLE)); + } + if table.count == 0 { + return Err(PartialVMError::new(StatusCode::BAD_HEADER_TABLE)); + } + match current_offset.checked_add(table.count) { + Some(checked_offset) => current_offset = checked_offset, + None => return Err(PartialVMError::new(StatusCode::BAD_HEADER_TABLE)), + } + if !table_types.insert(table.kind) { + return Err(PartialVMError::new(StatusCode::DUPLICATE_TABLE)); + } + if current_offset as usize > binary_len { + return Err(PartialVMError::new(StatusCode::BAD_HEADER_TABLE)); + } + } + Ok(current_offset) +} + +// +// Trait to read common tables from CompiledScript or CompiledModule +// + +trait CommonTables { + fn get_module_handles(&mut self) -> &mut Vec; + fn get_struct_handles(&mut self) -> &mut Vec; + fn get_function_handles(&mut self) -> &mut Vec; + fn get_function_instantiations(&mut self) -> &mut Vec; + fn get_signatures(&mut self) -> &mut SignaturePool; + fn get_identifiers(&mut self) -> &mut IdentifierPool; + fn get_address_identifiers(&mut self) -> &mut AddressIdentifierPool; + fn get_constant_pool(&mut self) -> &mut ConstantPool; + fn get_metadata(&mut self) -> &mut Vec; +} + +impl CommonTables for CompiledModule { + fn get_module_handles(&mut self) -> &mut Vec { + &mut self.module_handles + } + + fn get_struct_handles(&mut self) -> &mut Vec { + &mut self.struct_handles + } + + fn get_function_handles(&mut self) -> &mut Vec { + &mut self.function_handles + } + + fn get_function_instantiations(&mut self) -> &mut Vec { + &mut self.function_instantiations + } + + fn get_signatures(&mut self) -> &mut SignaturePool { + &mut self.signatures + } + + fn get_identifiers(&mut self) -> &mut IdentifierPool { + &mut self.identifiers + } + + fn get_address_identifiers(&mut self) -> &mut AddressIdentifierPool { + &mut self.address_identifiers + } + + fn get_constant_pool(&mut self) -> &mut ConstantPool { + &mut self.constant_pool + } + + fn get_metadata(&mut self) -> &mut Vec { + &mut self.metadata + } +} + +/// Builds and returns a `CompiledModule`. +fn build_compiled_module( + module: &mut CompiledModule, + binary: &VersionedBinary, + tables: &[Table], +) -> BinaryLoaderResult<()> { + build_common_tables(binary, tables, module)?; + build_module_tables(binary, tables, module)?; + Ok(()) +} + +/// Builds the common tables in a compiled unit. +fn build_common_tables( + binary: &VersionedBinary, + tables: &[Table], + common: &mut impl CommonTables, +) -> BinaryLoaderResult<()> { + let TableConfig { + // common tables + module_handles: module_handles_max, + struct_handles: struct_handles_max, + function_handles: function_handles_max, + function_instantiations: function_instantiations_max, + signatures: signatures_max, + constant_pool: constant_pool_max, + identifiers: identifiers_max, + address_identifiers: address_identifiers_max, + // module tables + struct_defs: _, + struct_def_instantiations: _, + function_defs: _, + field_handles: _, + field_instantiations: _, + friend_decls: _, + } = &binary.binary_config.table_config; + for table in tables { + // minimize code that checks limits with a local macro that knows the context (`table: &Table`) + macro_rules! check_table_size { + ($vec:expr, $max:expr) => { + if $vec.len() > $max as usize { + return Err( + PartialVMError::new(StatusCode::MALFORMED).with_message(format!( + "Exceeded size ({} > {}) in {:?}", + $vec.len(), + $max, + table.kind, + )), + ); + } + }; + } + + match table.kind { + TableType::MODULE_HANDLES => { + let module_handles = common.get_module_handles(); + load_module_handles(binary, table, module_handles)?; + check_table_size!(module_handles, *module_handles_max); + } + TableType::STRUCT_HANDLES => { + let struct_handles = common.get_struct_handles(); + load_struct_handles(binary, table, struct_handles)?; + check_table_size!(struct_handles, *struct_handles_max); + } + TableType::FUNCTION_HANDLES => { + let function_handles = common.get_function_handles(); + load_function_handles(binary, table, function_handles)?; + check_table_size!(function_handles, *function_handles_max); + } + TableType::FUNCTION_INST => { + let function_instantiations = common.get_function_instantiations(); + load_function_instantiations(binary, table, function_instantiations)?; + check_table_size!(function_instantiations, *function_instantiations_max); + } + TableType::SIGNATURES => { + let signatures = common.get_signatures(); + load_signatures(binary, table, signatures)?; + check_table_size!(signatures, *signatures_max); + } + TableType::CONSTANT_POOL => { + let constant_pool = common.get_constant_pool(); + load_constant_pool(binary, table, constant_pool)?; + check_table_size!(constant_pool, *constant_pool_max); + } + TableType::METADATA => { + if binary.check_no_extraneous_bytes() || binary.version() < VERSION_5 { + return Err( + PartialVMError::new(StatusCode::MALFORMED).with_message(format!( + "metadata declarations not applicable in bytecode version {}", + binary.version() + )), + ); + } + load_metadata(binary, table, common.get_metadata())?; + // we do not read metadata, nothing to check + } + TableType::IDENTIFIERS => { + let identifiers = common.get_identifiers(); + load_identifiers(binary, table, identifiers)?; + check_table_size!(identifiers, *identifiers_max); + } + TableType::ADDRESS_IDENTIFIERS => { + let address_identifiers = common.get_address_identifiers(); + load_address_identifiers(binary, table, address_identifiers)?; + check_table_size!(address_identifiers, *address_identifiers_max); + } + TableType::FUNCTION_DEFS + | TableType::STRUCT_DEFS + | TableType::STRUCT_DEF_INST + | TableType::FIELD_HANDLE + | TableType::FIELD_INST => (), + TableType::FRIEND_DECLS => { + // friend declarations do not exist before VERSION_2 + if binary.version() < VERSION_2 { + return Err(PartialVMError::new(StatusCode::MALFORMED).with_message( + "Friend declarations not applicable in bytecode version 1".to_string(), + )); + } + } + } + } + Ok(()) +} + +/// Builds tables related to a `CompiledModule`. +fn build_module_tables( + binary: &VersionedBinary, + tables: &[Table], + module: &mut CompiledModule, +) -> BinaryLoaderResult<()> { + let TableConfig { + // common tables + module_handles: _, + struct_handles: _, + function_handles: _, + function_instantiations: _, + signatures: _, + constant_pool: _, + identifiers: _, + address_identifiers: _, + // module tables + struct_defs: struct_defs_max, + struct_def_instantiations: struct_def_instantiations_max, + function_defs: function_defs_max, + field_handles: field_handles_max, + field_instantiations: field_instantiations_max, + friend_decls: friend_decls_max, + } = &binary.binary_config.table_config; + for table in tables { + // minimize code that checks limits bu a local macro that know the context + macro_rules! check_table_size { + ($vec:expr, $max:expr) => { + if $vec.len() > $max as usize { + return Err( + PartialVMError::new(StatusCode::MALFORMED).with_message(format!( + "Exceeded size ({} > {}) in {:?}", + $vec.len(), + $max, + table.kind, + )), + ); + } + }; + } + + match table.kind { + TableType::STRUCT_DEFS => { + load_struct_defs(binary, table, &mut module.struct_defs)?; + check_table_size!(&module.struct_defs, *struct_defs_max); + } + TableType::STRUCT_DEF_INST => { + load_struct_instantiations(binary, table, &mut module.struct_def_instantiations)?; + check_table_size!( + &module.struct_def_instantiations, + *struct_def_instantiations_max + ); + } + TableType::FUNCTION_DEFS => { + load_function_defs(binary, table, &mut module.function_defs)?; + check_table_size!(&module.function_defs, *function_defs_max); + } + TableType::FIELD_HANDLE => { + load_field_handles(binary, table, &mut module.field_handles)?; + check_table_size!(&module.field_handles, *field_handles_max); + } + TableType::FIELD_INST => { + load_field_instantiations(binary, table, &mut module.field_instantiations)?; + check_table_size!(&module.field_instantiations, *field_instantiations_max); + } + TableType::FRIEND_DECLS => { + load_module_handles(binary, table, &mut module.friend_decls)?; + check_table_size!(&module.friend_decls, *friend_decls_max); + } + TableType::MODULE_HANDLES + | TableType::STRUCT_HANDLES + | TableType::FUNCTION_HANDLES + | TableType::FUNCTION_INST + | TableType::IDENTIFIERS + | TableType::ADDRESS_IDENTIFIERS + | TableType::CONSTANT_POOL + | TableType::METADATA + | TableType::SIGNATURES => (), + } + } + Ok(()) +} + +/// Builds the `ModuleHandle` table. +fn load_module_handles( + binary: &VersionedBinary, + table: &Table, + module_handles: &mut Vec, +) -> BinaryLoaderResult<()> { + let start = table.offset as usize; + let end = start + table.count as usize; + let mut cursor = binary.new_cursor(start, end); + while cursor.position() < table.count as u64 { + let address = load_address_identifier_index(&mut cursor)?; + let name = load_identifier_index(&mut cursor)?; + module_handles.push(ModuleHandle { address, name }); + } + Ok(()) +} + +/// Builds the `StructHandle` table. +fn load_struct_handles( + binary: &VersionedBinary, + table: &Table, + struct_handles: &mut Vec, +) -> BinaryLoaderResult<()> { + let start = table.offset as usize; + let end = start + table.count as usize; + let mut cursor = binary.new_cursor(start, end); + while cursor.position() < table.count as u64 { + let module = load_module_handle_index(&mut cursor)?; + let name = load_identifier_index(&mut cursor)?; + let abilities = load_ability_set(&mut cursor, AbilitySetPosition::StructHandle)?; + let type_parameters = load_struct_type_parameters(&mut cursor)?; + struct_handles.push(StructHandle { + module, + name, + abilities, + type_parameters, + }); + } + Ok(()) +} + +/// Builds the `FunctionHandle` table. +fn load_function_handles( + binary: &VersionedBinary, + table: &Table, + function_handles: &mut Vec, +) -> BinaryLoaderResult<()> { + let start = table.offset as usize; + let end = start + table.count as usize; + let mut cursor = binary.new_cursor(start, end); + while cursor.position() < table.count as u64 { + let module = load_module_handle_index(&mut cursor)?; + let name = load_identifier_index(&mut cursor)?; + let parameters = load_signature_index(&mut cursor)?; + let return_ = load_signature_index(&mut cursor)?; + let type_parameters = + load_ability_sets(&mut cursor, AbilitySetPosition::FunctionTypeParameters)?; + + function_handles.push(FunctionHandle { + module, + name, + parameters, + return_, + type_parameters, + }); + } + Ok(()) +} + +/// Builds the `StructInstantiation` table. +fn load_struct_instantiations( + binary: &VersionedBinary, + table: &Table, + struct_insts: &mut Vec, +) -> BinaryLoaderResult<()> { + let start = table.offset as usize; + let end = start + table.count as usize; + let mut cursor = binary.new_cursor(start, end); + + while cursor.position() < table.count as u64 { + let def = load_struct_def_index(&mut cursor)?; + let type_parameters = load_signature_index(&mut cursor)?; + struct_insts.push(StructDefInstantiation { + def, + type_parameters, + }); + } + Ok(()) +} + +/// Builds the `FunctionInstantiation` table. +fn load_function_instantiations( + binary: &VersionedBinary, + table: &Table, + func_insts: &mut Vec, +) -> BinaryLoaderResult<()> { + let start = table.offset as usize; + let end = start + table.count as usize; + let mut cursor = binary.new_cursor(start, end); + while cursor.position() < table.count as u64 { + let handle = load_function_handle_index(&mut cursor)?; + let type_parameters = load_signature_index(&mut cursor)?; + func_insts.push(FunctionInstantiation { + handle, + type_parameters, + }); + } + Ok(()) +} + +/// Builds the `IdentifierPool`. +fn load_identifiers( + binary: &VersionedBinary, + table: &Table, + identifiers: &mut IdentifierPool, +) -> BinaryLoaderResult<()> { + let start = table.offset as usize; + let end = start + table.count as usize; + let mut cursor = binary.new_cursor(start, end); + while cursor.position() < u64::from(table.count) { + let size = load_identifier_size(&mut cursor)?; + let mut buffer: Vec = vec![0u8; size]; + if let Ok(count) = cursor.read(&mut buffer) { + if count != size { + return Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Bad Identifier pool size".to_string())); + } + let s = Identifier::from_utf8(buffer).map_err(|_| { + PartialVMError::new(StatusCode::MALFORMED) + .with_message("Invalid Identifier".to_string()) + })?; + identifiers.push(s); + } + } + Ok(()) +} + +/// Builds the `AddressIdentifierPool`. +fn load_address_identifiers( + binary: &VersionedBinary, + table: &Table, + addresses: &mut AddressIdentifierPool, +) -> BinaryLoaderResult<()> { + let mut start = table.offset as usize; + if table.count as usize % AccountAddress::LENGTH != 0 { + return Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Bad Address Identifier pool size".to_string())); + } + for _i in 0..table.count as usize / AccountAddress::LENGTH { + let end_addr = start + AccountAddress::LENGTH; + let address = binary.slice(start, end_addr).try_into(); + if address.is_err() { + return Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Invalid Address format".to_string())); + } + start = end_addr; + + addresses.push(address.unwrap()); + } + Ok(()) +} + +/// Builds the `ConstantPool`. +fn load_constant_pool( + binary: &VersionedBinary, + table: &Table, + constants: &mut ConstantPool, +) -> BinaryLoaderResult<()> { + let start = table.offset as usize; + let end = start + table.count as usize; + let mut cursor = binary.new_cursor(start, end); + while cursor.position() < u64::from(table.count) { + constants.push(load_constant(&mut cursor)?) + } + Ok(()) +} + +/// Build a single `Constant` +fn load_constant(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + let type_ = load_signature_token(cursor)?; + let data = load_byte_blob(cursor, load_constant_size)?; + Ok(Constant { type_, data }) +} + +/// Builds a metadata vector. +fn load_metadata( + binary: &VersionedBinary, + table: &Table, + metadata: &mut Vec, +) -> BinaryLoaderResult<()> { + let start = table.offset as usize; + let end = start + table.count as usize; + let mut cursor = binary.new_cursor(start, end); + while cursor.position() < u64::from(table.count) { + metadata.push(load_metadata_entry(&mut cursor)?) + } + Ok(()) +} + +/// Build a single metadata entry. +fn load_metadata_entry(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + let key = load_byte_blob(cursor, load_metadata_key_size)?; + let value = load_byte_blob(cursor, load_metadata_value_size)?; + Ok(Metadata { key, value }) +} + +/// Helper to load a byte blob with specific size loader. +fn load_byte_blob( + cursor: &mut VersionedCursor, + size_loader: impl Fn(&mut VersionedCursor) -> BinaryLoaderResult, +) -> BinaryLoaderResult> { + let size = size_loader(cursor)?; + let mut data: Vec = vec![0u8; size]; + let count = cursor.read(&mut data).map_err(|_| { + PartialVMError::new(StatusCode::MALFORMED) + .with_message("Unexpected end of table".to_string()) + })?; + if count != size { + return Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Bad byte blob size".to_string())); + } + Ok(data) +} + +/// Builds the `SignaturePool`. +fn load_signatures( + binary: &VersionedBinary, + table: &Table, + signatures: &mut SignaturePool, +) -> BinaryLoaderResult<()> { + let start = table.offset as usize; + let end = start + table.count as usize; + let mut cursor = binary.new_cursor(start, end); + while cursor.position() < u64::from(table.count) { + signatures.push(Signature(load_signature_tokens(&mut cursor)?)); + } + Ok(()) +} + +fn load_signature_tokens(cursor: &mut VersionedCursor) -> BinaryLoaderResult> { + let len = load_signature_size(cursor)?; + let mut tokens = vec![]; + for _ in 0..len { + tokens.push(load_signature_token(cursor)?); + } + Ok(tokens) +} + +#[cfg(test)] +pub fn load_signature_token_test_entry( + cursor: std::io::Cursor<&[u8]>, +) -> BinaryLoaderResult { + load_signature_token(&mut VersionedCursor::new_for_test(VERSION_MAX, cursor)) +} + +/// Deserializes a `SignatureToken`. +fn load_signature_token(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + // The following algorithm works by storing partially constructed types on a stack. + // + // Example: + // + // SignatureToken: `Foo, address>` + // Byte Stream: Foo u8 Foo u64 bool Bar address + // + // Stack Transitions: + // [] + // [Foo] + // [Foo, u8] + // [Foo] + // [Foo, Foo] + // [Foo, Foo, u64] + // [Foo, Foo] + // [Foo, Foo, bool] + // [Foo, Foo] + // [Foo, Foo, Bar] + // [Foo, Foo] + // [Foo, ?>] + // [Foo, ?>, address] + // [Foo, address>] (done) + + use SerializedType as S; + + enum TypeBuilder { + Saturated(SignatureToken), + Vector, + Reference, + MutableReference, + StructInst { + sh_idx: StructHandleIndex, + arity: usize, + ty_args: Vec, + }, + } + + impl TypeBuilder { + fn apply(self, tok: SignatureToken) -> Self { + match self { + T::Vector => T::Saturated(SignatureToken::Vector(Box::new(tok))), + T::Reference => T::Saturated(SignatureToken::Reference(Box::new(tok))), + T::MutableReference => { + T::Saturated(SignatureToken::MutableReference(Box::new(tok))) + } + T::StructInst { + sh_idx, + arity, + mut ty_args, + } => { + ty_args.push(tok); + if ty_args.len() >= arity { + T::Saturated(SignatureToken::StructInstantiation(Box::new(( + sh_idx, ty_args, + )))) + } else { + T::StructInst { + sh_idx, + arity, + ty_args, + } + } + } + _ => unreachable!("invalid type constructor application"), + } + } + + fn is_saturated(&self) -> bool { + matches!(self, T::Saturated(_)) + } + + fn unwrap_saturated(self) -> SignatureToken { + match self { + T::Saturated(tok) => tok, + _ => unreachable!("cannot unwrap unsaturated type constructor"), + } + } + } + + use TypeBuilder as T; + + let mut read_next = || { + if let Ok(byte) = cursor.read_u8() { + match S::from_u8(byte)? { + S::U16 | S::U32 | S::U256 if (cursor.version() < VERSION_6) => { + return Err( + PartialVMError::new(StatusCode::MALFORMED).with_message(format!( + "u16, u32, u256 integers not supported in bytecode version {}", + cursor.version() + )), + ); + } + _ => (), + }; + + Ok(match S::from_u8(byte)? { + S::BOOL => T::Saturated(SignatureToken::Bool), + S::U8 => T::Saturated(SignatureToken::U8), + S::U16 => T::Saturated(SignatureToken::U16), + S::U32 => T::Saturated(SignatureToken::U32), + S::U64 => T::Saturated(SignatureToken::U64), + S::U128 => T::Saturated(SignatureToken::U128), + S::U256 => T::Saturated(SignatureToken::U256), + S::ADDRESS => T::Saturated(SignatureToken::Address), + S::SIGNER => T::Saturated(SignatureToken::Signer), + S::VECTOR => T::Vector, + S::REFERENCE => T::Reference, + S::MUTABLE_REFERENCE => T::MutableReference, + S::STRUCT => { + let sh_idx = load_struct_handle_index(cursor)?; + T::Saturated(SignatureToken::Struct(sh_idx)) + } + S::STRUCT_INST => { + let sh_idx = load_struct_handle_index(cursor)?; + let arity = load_type_parameter_count(cursor)?; + if arity == 0 { + return Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Struct inst with arity 0".to_string())); + } + T::StructInst { + sh_idx, + arity, + ty_args: vec![], + } + } + S::TYPE_PARAMETER => { + let idx = load_type_parameter_index(cursor)?; + T::Saturated(SignatureToken::TypeParameter(idx)) + } + }) + } else { + Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Unexpected EOF".to_string())) + } + }; + + let mut stack = match read_next()? { + T::Saturated(tok) => return Ok(tok), + t => vec![t], + }; + + loop { + if stack.len() > SIGNATURE_TOKEN_DEPTH_MAX { + return Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Maximum recursion depth reached".to_string())); + } + if stack.last().unwrap().is_saturated() { + let tok = stack.pop().unwrap().unwrap_saturated(); + match stack.pop() { + Some(t) => stack.push(t.apply(tok)), + None => return Ok(tok), + } + } else { + stack.push(read_next()?) + } + } +} + +#[derive(Copy, Clone)] +enum AbilitySetPosition { + FunctionTypeParameters, + StructTypeParameters, + StructHandle, +} + +fn load_ability_set( + cursor: &mut VersionedCursor, + pos: AbilitySetPosition, +) -> BinaryLoaderResult { + // If the module was on the old kind system: + // - For struct declarations + // - resource kind structs become store+resource structs + // - copyable kind structs become store+copy+drop structs + // - For function type parameter constraints + // - all kind becomes store, since it might be used in global storage + // - resource kind becomes store+resource + // - copyable kind becomes store+copy+drop + // - For struct type parameter constraints + // - all kind becomes empty + // - resource kind becomes resource + // - copyable kind becomes copy+drop + // In summary, we do not need store on the struct type parameter case for backwards + // compatibility because any old code paths or entry points will use them with store types. + // Any new code paths gain flexibility by being able to use the struct with possibly non-store + // instantiations + if cursor.version() < 2 { + let byte = match cursor.read_u8() { + Ok(byte) => byte, + Err(_) => { + return Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Unexpected EOF".to_string())) + } + }; + match pos { + AbilitySetPosition::StructHandle => { + Ok(match DeprecatedNominalResourceFlag::from_u8(byte)? { + DeprecatedNominalResourceFlag::NOMINAL_RESOURCE => { + AbilitySet::EMPTY | Ability::Store | Ability::Key + } + DeprecatedNominalResourceFlag::NORMAL_STRUCT => { + AbilitySet::EMPTY | Ability::Store | Ability::Copy | Ability::Drop + } + }) + } + AbilitySetPosition::FunctionTypeParameters + | AbilitySetPosition::StructTypeParameters => { + let set = match DeprecatedKind::from_u8(byte)? { + DeprecatedKind::ALL => AbilitySet::EMPTY, + DeprecatedKind::COPYABLE => AbilitySet::EMPTY | Ability::Copy | Ability::Drop, + DeprecatedKind::RESOURCE => AbilitySet::EMPTY | Ability::Key, + }; + Ok(match pos { + AbilitySetPosition::StructHandle => unreachable!(), + AbilitySetPosition::FunctionTypeParameters => set | Ability::Store, + AbilitySetPosition::StructTypeParameters => set, + }) + } + } + } else { + // The uleb here doesn't really do anything as it is bounded currently to 0xF, but the + // if we get many more constraints in the future, uleb will be helpful. + let u = read_uleb_internal(cursor, AbilitySet::ALL.into_u8() as u64)?; + match AbilitySet::from_u8(u) { + Some(abilities) => Ok(abilities), + None => Err(PartialVMError::new(StatusCode::UNKNOWN_ABILITY)), + } + } +} + +fn load_ability_sets( + cursor: &mut VersionedCursor, + pos: AbilitySetPosition, +) -> BinaryLoaderResult> { + let len = load_type_parameter_count(cursor)?; + let mut kinds = vec![]; + for _ in 0..len { + kinds.push(load_ability_set(cursor, pos)?); + } + Ok(kinds) +} + +fn load_struct_type_parameters( + cursor: &mut VersionedCursor, +) -> BinaryLoaderResult> { + let len = load_type_parameter_count(cursor)?; + let mut type_params = Vec::with_capacity(len); + for _ in 0..len { + type_params.push(load_struct_type_parameter(cursor)?); + } + Ok(type_params) +} + +fn load_struct_type_parameter( + cursor: &mut VersionedCursor, +) -> BinaryLoaderResult { + let constraints = load_ability_set(cursor, AbilitySetPosition::StructTypeParameters)?; + let is_phantom = if cursor.version() < VERSION_3 { + false + } else { + let byte: u8 = read_uleb_internal(cursor, 1)?; + byte != 0 + }; + Ok(StructTypeParameter { + constraints, + is_phantom, + }) +} + +/// Builds the `StructDefinition` table. +fn load_struct_defs( + binary: &VersionedBinary, + table: &Table, + struct_defs: &mut Vec, +) -> BinaryLoaderResult<()> { + let start = table.offset as usize; + let end = start + table.count as usize; + let mut cursor = binary.new_cursor(start, end); + while cursor.position() < u64::from(table.count) { + let struct_handle = load_struct_handle_index(&mut cursor)?; + let field_information_flag = match cursor.read_u8() { + Ok(byte) => SerializedNativeStructFlag::from_u8(byte)?, + Err(_) => { + return Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Invalid field info in struct".to_string())) + } + }; + let field_information = match field_information_flag { + SerializedNativeStructFlag::NATIVE => StructFieldInformation::Native, + SerializedNativeStructFlag::DECLARED => { + let fields = load_field_defs(&mut cursor)?; + StructFieldInformation::Declared(fields) + } + }; + struct_defs.push(StructDefinition { + struct_handle, + field_information, + }); + } + Ok(()) +} + +fn load_field_defs(cursor: &mut VersionedCursor) -> BinaryLoaderResult> { + let mut fields = Vec::new(); + let field_count = load_field_count(cursor)?; + for _ in 0..field_count { + fields.push(load_field_def(cursor)?); + } + Ok(fields) +} + +fn load_field_def(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + let name = load_identifier_index(cursor)?; + let signature = load_signature_token(cursor)?; + Ok(FieldDefinition { + name, + signature: TypeSignature(signature), + }) +} + +/// Builds the `FunctionDefinition` table. +fn load_function_defs( + binary: &VersionedBinary, + table: &Table, + func_defs: &mut Vec, +) -> BinaryLoaderResult<()> { + let start = table.offset as usize; + let end = start + table.count as usize; + let mut cursor = binary.new_cursor(start, end); + while cursor.position() < u64::from(table.count) { + let func_def = load_function_def(&mut cursor)?; + func_defs.push(func_def); + } + Ok(()) +} + +fn load_field_handles( + binary: &VersionedBinary, + table: &Table, + field_handles: &mut Vec, +) -> BinaryLoaderResult<()> { + let start = table.offset as usize; + let end = start + table.count as usize; + let mut cursor = binary.new_cursor(start, end); + loop { + if cursor.position() == u64::from(table.count) { + break; + } + let struct_idx = load_struct_def_index(&mut cursor)?; + let offset = load_field_offset(&mut cursor)?; + field_handles.push(FieldHandle { + owner: struct_idx, + field: offset, + }); + } + Ok(()) +} + +fn load_field_instantiations( + binary: &VersionedBinary, + table: &Table, + field_insts: &mut Vec, +) -> BinaryLoaderResult<()> { + let start = table.offset as usize; + let end = start + table.count as usize; + let mut cursor = binary.new_cursor(start, end); + loop { + if cursor.position() == u64::from(table.count) { + break; + } + let handle = load_field_handle_index(&mut cursor)?; + let type_parameters = load_signature_index(&mut cursor)?; + field_insts.push(FieldInstantiation { + handle, + type_parameters, + }); + } + Ok(()) +} + +/// Deserializes a `FunctionDefinition`. +fn load_function_def(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + let function = load_function_handle_index(cursor)?; + + let mut flags = cursor.read_u8().map_err(|_| { + PartialVMError::new(StatusCode::MALFORMED).with_message("Unexpected EOF".to_string()) + })?; + + // NOTE: changes compared with VERSION_1 + // - in VERSION_1: the flags is a byte compositing both the visibility info and whether + // the function is a native function + // - in VERSION_2 onwards: the flags only represent the visibility info and we need to + // advance the cursor to read up the next byte as flags + // - in VERSION_5 onwards: script visibility has been deprecated for an entry function flag + let (visibility, is_entry, mut extra_flags) = if cursor.version() == VERSION_1 { + let vis = if (flags & FunctionDefinition::DEPRECATED_PUBLIC_BIT) != 0 { + flags ^= FunctionDefinition::DEPRECATED_PUBLIC_BIT; + Visibility::Public + } else { + Visibility::Private + }; + (vis, false, flags) + } else if cursor.version() < VERSION_5 { + let (vis, is_entry) = if flags == Visibility::DEPRECATED_SCRIPT { + (Visibility::Public, true) + } else { + let vis = flags.try_into().map_err(|_| { + PartialVMError::new(StatusCode::MALFORMED) + .with_message("Invalid visibility byte".to_string()) + })?; + (vis, false) + }; + let extra_flags = cursor.read_u8().map_err(|_| { + PartialVMError::new(StatusCode::MALFORMED).with_message("Unexpected EOF".to_string()) + })?; + (vis, is_entry, extra_flags) + } else { + let vis = flags.try_into().map_err(|_| { + PartialVMError::new(StatusCode::MALFORMED) + .with_message("Invalid visibility byte".to_string()) + })?; + + let mut extra_flags = cursor.read_u8().map_err(|_| { + PartialVMError::new(StatusCode::MALFORMED).with_message("Unexpected EOF".to_string()) + })?; + let is_entry = (extra_flags & FunctionDefinition::ENTRY) != 0; + if is_entry { + extra_flags ^= FunctionDefinition::ENTRY; + } + (vis, is_entry, extra_flags) + }; + + let acquires_global_resources = load_struct_definition_indices(cursor)?; + let code_unit = if (extra_flags & FunctionDefinition::NATIVE) != 0 { + extra_flags ^= FunctionDefinition::NATIVE; + None + } else { + Some(load_code_unit(cursor)?) + }; + + // check that the bits unused in the flags are not set, otherwise it might cause some trouble + // if later we decide to assign meaning to these bits. + if extra_flags != 0 { + return Err(PartialVMError::new(StatusCode::INVALID_FLAG_BITS)); + } + + Ok(FunctionDefinition { + function, + visibility, + is_entry, + acquires_global_resources, + code: code_unit, + }) +} + +/// Deserializes a `Vec`. +fn load_struct_definition_indices( + cursor: &mut VersionedCursor, +) -> BinaryLoaderResult> { + let len = load_acquires_count(cursor)?; + let mut indices = vec![]; + for _ in 0..len { + indices.push(load_struct_def_index(cursor)?); + } + Ok(indices) +} + +/// Deserializes a `CodeUnit`. +fn load_code_unit(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + let locals = load_signature_index(cursor)?; + + let mut code_unit = CodeUnit { + locals, + code: vec![], + }; + + load_code(cursor, &mut code_unit.code)?; + Ok(code_unit) +} + +/// Deserializes a code stream (`Bytecode`s). +fn load_code(cursor: &mut VersionedCursor, code: &mut Vec) -> BinaryLoaderResult<()> { + let bytecode_count = load_bytecode_count(cursor)?; + + while code.len() < bytecode_count { + let byte = cursor.read_u8().map_err(|_| { + PartialVMError::new(StatusCode::MALFORMED).with_message("Unexpected EOF".to_string()) + })?; + let opcode = Opcodes::from_u8(byte)?; + // version checking + match opcode { + Opcodes::VEC_PACK + | Opcodes::VEC_LEN + | Opcodes::VEC_IMM_BORROW + | Opcodes::VEC_MUT_BORROW + | Opcodes::VEC_PUSH_BACK + | Opcodes::VEC_POP_BACK + | Opcodes::VEC_UNPACK + | Opcodes::VEC_SWAP => { + if cursor.version() < VERSION_4 { + return Err( + PartialVMError::new(StatusCode::MALFORMED).with_message(format!( + "Vector operations not available before bytecode version {}", + VERSION_4 + )), + ); + } + } + _ => {} + }; + + match opcode { + Opcodes::LD_U16 + | Opcodes::LD_U32 + | Opcodes::LD_U256 + | Opcodes::CAST_U16 + | Opcodes::CAST_U32 + | Opcodes::CAST_U256 + if (cursor.version() < VERSION_6) => + { + return Err( + PartialVMError::new(StatusCode::MALFORMED).with_message(format!( + "Loading or casting u16, u32, u256 integers not supported in bytecode version {}", + cursor.version() + )), + ); + } + _ => (), + }; + + // conversion + let bytecode = match opcode { + Opcodes::POP => Bytecode::Pop, + Opcodes::RET => Bytecode::Ret, + Opcodes::BR_TRUE => Bytecode::BrTrue(load_bytecode_index(cursor)?), + Opcodes::BR_FALSE => Bytecode::BrFalse(load_bytecode_index(cursor)?), + Opcodes::BRANCH => Bytecode::Branch(load_bytecode_index(cursor)?), + Opcodes::LD_U8 => { + let value = cursor.read_u8().map_err(|_| { + PartialVMError::new(StatusCode::MALFORMED) + .with_message("Unexpected EOF".to_string()) + })?; + Bytecode::LdU8(value) + } + Opcodes::LD_U64 => { + let value = read_u64_internal(cursor)?; + Bytecode::LdU64(value) + } + Opcodes::LD_U128 => { + let value = read_u128_internal(cursor)?; + Bytecode::LdU128(Box::new(value)) + } + Opcodes::CAST_U8 => Bytecode::CastU8, + Opcodes::CAST_U64 => Bytecode::CastU64, + Opcodes::CAST_U128 => Bytecode::CastU128, + Opcodes::LD_CONST => Bytecode::LdConst(load_constant_pool_index(cursor)?), + Opcodes::LD_TRUE => Bytecode::LdTrue, + Opcodes::LD_FALSE => Bytecode::LdFalse, + Opcodes::COPY_LOC => Bytecode::CopyLoc(load_local_index(cursor)?), + Opcodes::MOVE_LOC => Bytecode::MoveLoc(load_local_index(cursor)?), + Opcodes::ST_LOC => Bytecode::StLoc(load_local_index(cursor)?), + Opcodes::MUT_BORROW_LOC => Bytecode::MutBorrowLoc(load_local_index(cursor)?), + Opcodes::IMM_BORROW_LOC => Bytecode::ImmBorrowLoc(load_local_index(cursor)?), + Opcodes::MUT_BORROW_FIELD => Bytecode::MutBorrowField(load_field_handle_index(cursor)?), + Opcodes::MUT_BORROW_FIELD_GENERIC => { + Bytecode::MutBorrowFieldGeneric(load_field_inst_index(cursor)?) + } + Opcodes::IMM_BORROW_FIELD => Bytecode::ImmBorrowField(load_field_handle_index(cursor)?), + Opcodes::IMM_BORROW_FIELD_GENERIC => { + Bytecode::ImmBorrowFieldGeneric(load_field_inst_index(cursor)?) + } + Opcodes::CALL => Bytecode::Call(load_function_handle_index(cursor)?), + Opcodes::CALL_GENERIC => Bytecode::CallGeneric(load_function_inst_index(cursor)?), + Opcodes::PACK => Bytecode::Pack(load_struct_def_index(cursor)?), + Opcodes::PACK_GENERIC => Bytecode::PackGeneric(load_struct_def_inst_index(cursor)?), + Opcodes::UNPACK => Bytecode::Unpack(load_struct_def_index(cursor)?), + Opcodes::UNPACK_GENERIC => Bytecode::UnpackGeneric(load_struct_def_inst_index(cursor)?), + Opcodes::READ_REF => Bytecode::ReadRef, + Opcodes::WRITE_REF => Bytecode::WriteRef, + Opcodes::ADD => Bytecode::Add, + Opcodes::SUB => Bytecode::Sub, + Opcodes::MUL => Bytecode::Mul, + Opcodes::MOD => Bytecode::Mod, + Opcodes::DIV => Bytecode::Div, + Opcodes::BIT_OR => Bytecode::BitOr, + Opcodes::BIT_AND => Bytecode::BitAnd, + Opcodes::XOR => Bytecode::Xor, + Opcodes::SHL => Bytecode::Shl, + Opcodes::SHR => Bytecode::Shr, + Opcodes::OR => Bytecode::Or, + Opcodes::AND => Bytecode::And, + Opcodes::NOT => Bytecode::Not, + Opcodes::EQ => Bytecode::Eq, + Opcodes::NEQ => Bytecode::Neq, + Opcodes::LT => Bytecode::Lt, + Opcodes::GT => Bytecode::Gt, + Opcodes::LE => Bytecode::Le, + Opcodes::GE => Bytecode::Ge, + Opcodes::ABORT => Bytecode::Abort, + Opcodes::NOP => Bytecode::Nop, + Opcodes::FREEZE_REF => Bytecode::FreezeRef, + Opcodes::VEC_PACK => { + Bytecode::VecPack(load_signature_index(cursor)?, read_u64_internal(cursor)?) + } + Opcodes::VEC_LEN => Bytecode::VecLen(load_signature_index(cursor)?), + Opcodes::VEC_IMM_BORROW => Bytecode::VecImmBorrow(load_signature_index(cursor)?), + Opcodes::VEC_MUT_BORROW => Bytecode::VecMutBorrow(load_signature_index(cursor)?), + Opcodes::VEC_PUSH_BACK => Bytecode::VecPushBack(load_signature_index(cursor)?), + Opcodes::VEC_POP_BACK => Bytecode::VecPopBack(load_signature_index(cursor)?), + Opcodes::VEC_UNPACK => { + Bytecode::VecUnpack(load_signature_index(cursor)?, read_u64_internal(cursor)?) + } + Opcodes::VEC_SWAP => Bytecode::VecSwap(load_signature_index(cursor)?), + Opcodes::LD_U16 => { + let value = read_u16_internal(cursor)?; + Bytecode::LdU16(value) + } + Opcodes::LD_U32 => { + let value = read_u32_internal(cursor)?; + Bytecode::LdU32(value) + } + Opcodes::LD_U256 => { + let value = read_u256_internal(cursor)?; + Bytecode::LdU256(Box::new(value)) + } + Opcodes::CAST_U16 => Bytecode::CastU16, + Opcodes::CAST_U32 => Bytecode::CastU32, + Opcodes::CAST_U256 => Bytecode::CastU256, + // ******** DEPRECATED BYTECODES ******** + Opcodes::EXISTS_DEPRECATED => { + Bytecode::ExistsDeprecated(load_struct_def_index(cursor)?) + } + Opcodes::EXISTS_GENERIC_DEPRECATED => { + Bytecode::ExistsGenericDeprecated(load_struct_def_inst_index(cursor)?) + } + Opcodes::MUT_BORROW_GLOBAL_DEPRECATED => { + Bytecode::MutBorrowGlobalDeprecated(load_struct_def_index(cursor)?) + } + Opcodes::MUT_BORROW_GLOBAL_GENERIC_DEPRECATED => { + Bytecode::MutBorrowGlobalGenericDeprecated(load_struct_def_inst_index(cursor)?) + } + Opcodes::IMM_BORROW_GLOBAL_DEPRECATED => { + Bytecode::ImmBorrowGlobalDeprecated(load_struct_def_index(cursor)?) + } + Opcodes::IMM_BORROW_GLOBAL_GENERIC_DEPRECATED => { + Bytecode::ImmBorrowGlobalGenericDeprecated(load_struct_def_inst_index(cursor)?) + } + Opcodes::MOVE_FROM_DEPRECATED => { + Bytecode::MoveFromDeprecated(load_struct_def_index(cursor)?) + } + Opcodes::MOVE_FROM_GENERIC_DEPRECATED => { + Bytecode::MoveFromGenericDeprecated(load_struct_def_inst_index(cursor)?) + } + Opcodes::MOVE_TO_DEPRECATED => { + Bytecode::MoveToDeprecated(load_struct_def_index(cursor)?) + } + Opcodes::MOVE_TO_GENERIC_DEPRECATED => { + Bytecode::MoveToGenericDeprecated(load_struct_def_inst_index(cursor)?) + } + }; + code.push(bytecode); + } + Ok(()) +} + +impl TableType { + fn from_u8(value: u8) -> BinaryLoaderResult { + match value { + 0x1 => Ok(TableType::MODULE_HANDLES), + 0x2 => Ok(TableType::STRUCT_HANDLES), + 0x3 => Ok(TableType::FUNCTION_HANDLES), + 0x4 => Ok(TableType::FUNCTION_INST), + 0x5 => Ok(TableType::SIGNATURES), + 0x6 => Ok(TableType::CONSTANT_POOL), + 0x7 => Ok(TableType::IDENTIFIERS), + 0x8 => Ok(TableType::ADDRESS_IDENTIFIERS), + 0xA => Ok(TableType::STRUCT_DEFS), + 0xB => Ok(TableType::STRUCT_DEF_INST), + 0xC => Ok(TableType::FUNCTION_DEFS), + 0xD => Ok(TableType::FIELD_HANDLE), + 0xE => Ok(TableType::FIELD_INST), + 0xF => Ok(TableType::FRIEND_DECLS), + 0x10 => Ok(TableType::METADATA), + _ => Err(PartialVMError::new(StatusCode::UNKNOWN_TABLE_TYPE)), + } + } +} + +impl SerializedType { + fn from_u8(value: u8) -> BinaryLoaderResult { + match value { + 0x1 => Ok(SerializedType::BOOL), + 0x2 => Ok(SerializedType::U8), + 0x3 => Ok(SerializedType::U64), + 0x4 => Ok(SerializedType::U128), + 0x5 => Ok(SerializedType::ADDRESS), + 0x6 => Ok(SerializedType::REFERENCE), + 0x7 => Ok(SerializedType::MUTABLE_REFERENCE), + 0x8 => Ok(SerializedType::STRUCT), + 0x9 => Ok(SerializedType::TYPE_PARAMETER), + 0xA => Ok(SerializedType::VECTOR), + 0xB => Ok(SerializedType::STRUCT_INST), + 0xC => Ok(SerializedType::SIGNER), + 0xD => Ok(SerializedType::U16), + 0xE => Ok(SerializedType::U32), + 0xF => Ok(SerializedType::U256), + _ => Err(PartialVMError::new(StatusCode::UNKNOWN_SERIALIZED_TYPE)), + } + } +} + +#[rustfmt::skip] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[derive(Clone, Copy, Debug)] +pub enum DeprecatedNominalResourceFlag { + NOMINAL_RESOURCE = 0x1, + NORMAL_STRUCT = 0x2, +} + +impl DeprecatedNominalResourceFlag { + fn from_u8(value: u8) -> BinaryLoaderResult { + match value { + 0x1 => Ok(DeprecatedNominalResourceFlag::NOMINAL_RESOURCE), + 0x2 => Ok(DeprecatedNominalResourceFlag::NORMAL_STRUCT), + _ => Err(PartialVMError::new(StatusCode::UNKNOWN_ABILITY)), + } + } +} +#[rustfmt::skip] +#[allow(non_camel_case_types)] +#[repr(u8)] +enum DeprecatedKind { + ALL = 0x1, + COPYABLE = 0x2, + RESOURCE = 0x3, +} + +impl DeprecatedKind { + fn from_u8(value: u8) -> BinaryLoaderResult { + match value { + 0x1 => Ok(DeprecatedKind::ALL), + 0x2 => Ok(DeprecatedKind::COPYABLE), + 0x3 => Ok(DeprecatedKind::RESOURCE), + _ => Err(PartialVMError::new(StatusCode::UNKNOWN_ABILITY)), + } + } +} + +impl SerializedNativeStructFlag { + fn from_u8(value: u8) -> BinaryLoaderResult { + match value { + 0x1 => Ok(SerializedNativeStructFlag::NATIVE), + 0x2 => Ok(SerializedNativeStructFlag::DECLARED), + _ => Err(PartialVMError::new(StatusCode::UNKNOWN_NATIVE_STRUCT_FLAG)), + } + } +} + +impl Opcodes { + fn from_u8(value: u8) -> BinaryLoaderResult { + match value { + 0x01 => Ok(Opcodes::POP), + 0x02 => Ok(Opcodes::RET), + 0x03 => Ok(Opcodes::BR_TRUE), + 0x04 => Ok(Opcodes::BR_FALSE), + 0x05 => Ok(Opcodes::BRANCH), + 0x06 => Ok(Opcodes::LD_U64), + 0x07 => Ok(Opcodes::LD_CONST), + 0x08 => Ok(Opcodes::LD_TRUE), + 0x09 => Ok(Opcodes::LD_FALSE), + 0x0A => Ok(Opcodes::COPY_LOC), + 0x0B => Ok(Opcodes::MOVE_LOC), + 0x0C => Ok(Opcodes::ST_LOC), + 0x0D => Ok(Opcodes::MUT_BORROW_LOC), + 0x0E => Ok(Opcodes::IMM_BORROW_LOC), + 0x0F => Ok(Opcodes::MUT_BORROW_FIELD), + 0x10 => Ok(Opcodes::IMM_BORROW_FIELD), + 0x11 => Ok(Opcodes::CALL), + 0x12 => Ok(Opcodes::PACK), + 0x13 => Ok(Opcodes::UNPACK), + 0x14 => Ok(Opcodes::READ_REF), + 0x15 => Ok(Opcodes::WRITE_REF), + 0x16 => Ok(Opcodes::ADD), + 0x17 => Ok(Opcodes::SUB), + 0x18 => Ok(Opcodes::MUL), + 0x19 => Ok(Opcodes::MOD), + 0x1A => Ok(Opcodes::DIV), + 0x1B => Ok(Opcodes::BIT_OR), + 0x1C => Ok(Opcodes::BIT_AND), + 0x1D => Ok(Opcodes::XOR), + 0x1E => Ok(Opcodes::OR), + 0x1F => Ok(Opcodes::AND), + 0x20 => Ok(Opcodes::NOT), + 0x21 => Ok(Opcodes::EQ), + 0x22 => Ok(Opcodes::NEQ), + 0x23 => Ok(Opcodes::LT), + 0x24 => Ok(Opcodes::GT), + 0x25 => Ok(Opcodes::LE), + 0x26 => Ok(Opcodes::GE), + 0x27 => Ok(Opcodes::ABORT), + 0x28 => Ok(Opcodes::NOP), + 0x29 => Ok(Opcodes::EXISTS_DEPRECATED), + 0x2A => Ok(Opcodes::MUT_BORROW_GLOBAL_DEPRECATED), + 0x2B => Ok(Opcodes::IMM_BORROW_GLOBAL_DEPRECATED), + 0x2C => Ok(Opcodes::MOVE_FROM_DEPRECATED), + 0x2D => Ok(Opcodes::MOVE_TO_DEPRECATED), + 0x2E => Ok(Opcodes::FREEZE_REF), + 0x2F => Ok(Opcodes::SHL), + 0x30 => Ok(Opcodes::SHR), + 0x31 => Ok(Opcodes::LD_U8), + 0x32 => Ok(Opcodes::LD_U128), + 0x33 => Ok(Opcodes::CAST_U8), + 0x34 => Ok(Opcodes::CAST_U64), + 0x35 => Ok(Opcodes::CAST_U128), + 0x36 => Ok(Opcodes::MUT_BORROW_FIELD_GENERIC), + 0x37 => Ok(Opcodes::IMM_BORROW_FIELD_GENERIC), + 0x38 => Ok(Opcodes::CALL_GENERIC), + 0x39 => Ok(Opcodes::PACK_GENERIC), + 0x3A => Ok(Opcodes::UNPACK_GENERIC), + 0x3B => Ok(Opcodes::EXISTS_GENERIC_DEPRECATED), + 0x3C => Ok(Opcodes::MUT_BORROW_GLOBAL_GENERIC_DEPRECATED), + 0x3D => Ok(Opcodes::IMM_BORROW_GLOBAL_GENERIC_DEPRECATED), + 0x3E => Ok(Opcodes::MOVE_FROM_GENERIC_DEPRECATED), + 0x3F => Ok(Opcodes::MOVE_TO_GENERIC_DEPRECATED), + 0x40 => Ok(Opcodes::VEC_PACK), + 0x41 => Ok(Opcodes::VEC_LEN), + 0x42 => Ok(Opcodes::VEC_IMM_BORROW), + 0x43 => Ok(Opcodes::VEC_MUT_BORROW), + 0x44 => Ok(Opcodes::VEC_PUSH_BACK), + 0x45 => Ok(Opcodes::VEC_POP_BACK), + 0x46 => Ok(Opcodes::VEC_UNPACK), + 0x47 => Ok(Opcodes::VEC_SWAP), + 0x48 => Ok(Opcodes::LD_U16), + 0x49 => Ok(Opcodes::LD_U32), + 0x4A => Ok(Opcodes::LD_U256), + 0x4B => Ok(Opcodes::CAST_U16), + 0x4C => Ok(Opcodes::CAST_U32), + 0x4D => Ok(Opcodes::CAST_U256), + _ => Err(PartialVMError::new(StatusCode::UNKNOWN_OPCODE)), + } + } +} + +// +// Cursor API +// + +#[derive(Debug)] +struct VersionedBinary<'a, 'b> { + binary_config: &'b BinaryConfig, + binary: &'a [u8], + version: u32, + tables: Vec
, + module_idx: ModuleHandleIndex, + // index after the binary header (including table info) + data_offset: usize, + binary_end_offset: usize, +} + +#[derive(Debug)] +struct VersionedCursor<'a> { + version: u32, + cursor: Cursor<&'a [u8]>, +} + +impl<'a, 'b> VersionedBinary<'a, 'b> { + fn initialize( + binary: &'a [u8], + binary_config: &'b BinaryConfig, + load_module_idx: bool, + ) -> BinaryLoaderResult { + let binary_len = binary.len(); + let mut cursor = Cursor::<&'a [u8]>::new(binary); + // check magic + let mut magic = [0u8; BinaryConstants::MOVE_MAGIC_SIZE]; + if let Ok(count) = cursor.read(&mut magic) { + if count != BinaryConstants::MOVE_MAGIC_SIZE || magic != BinaryConstants::MOVE_MAGIC { + return Err(PartialVMError::new(StatusCode::BAD_MAGIC)); + } + } else { + return Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Bad binary header".to_string())); + } + // load binary version + let version = match read_u32(&mut cursor) { + Ok(v) => v, + Err(_) => { + return Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Bad binary header".to_string())); + } + }; + if version == 0 || version > u32::min(binary_config.max_binary_format_version, VERSION_MAX) + { + return Err(PartialVMError::new(StatusCode::UNKNOWN_VERSION)); + } + + let mut versioned_cursor = VersionedCursor { version, cursor }; + // load table info + let table_count = load_table_count(&mut versioned_cursor)?; + let mut tables: Vec
= Vec::new(); + read_tables(&mut versioned_cursor, table_count, &mut tables)?; + let table_size = check_tables(&mut tables, binary_len)?; + if table_size as u64 + versioned_cursor.position() > binary_len as u64 { + return Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Table size too big".to_string())); + } + + // save "start offset" for table content (data) + let data_offset = versioned_cursor.position() as usize; + + // load module idx (self id) - at the end of the binary. Why? + let module_idx = if load_module_idx { + versioned_cursor.set_position((data_offset + table_size as usize) as u64); + load_module_handle_index(&mut versioned_cursor)? + } else { + ModuleHandleIndex(0) + }; + // end of binary + let binary_end_offset = versioned_cursor.position() as usize; + Ok(Self { + binary_config, + binary, + version, + tables, + module_idx, + data_offset, + binary_end_offset, + }) + } + + fn version(&self) -> u32 { + self.version + } + + fn module_idx(&self) -> ModuleHandleIndex { + self.module_idx + } + + fn binary_end_offset(&self) -> usize { + self.binary_end_offset + } + + fn new_cursor(&self, start: usize, end: usize) -> VersionedCursor<'a> { + VersionedCursor { + cursor: Cursor::new(&self.binary[start + self.data_offset..end + self.data_offset]), + version: self.version(), + } + } + + fn slice(&self, start: usize, end: usize) -> &'a [u8] { + &self.binary[start + self.data_offset..end + self.data_offset] + } + + fn check_no_extraneous_bytes(&self) -> bool { + self.binary_config.check_no_extraneous_bytes + } +} + +impl<'a> VersionedCursor<'a> { + fn version(&self) -> u32 { + self.version + } + + fn position(&self) -> u64 { + self.cursor.position() + } + + fn read_u8(&mut self) -> anyhow::Result { + read_u8(&mut self.cursor) + } + + fn set_position(&mut self, pos: u64) { + self.cursor.set_position(pos); + } + + #[allow(dead_code)] + fn read_u32(&mut self) -> anyhow::Result { + read_u32(&mut self.cursor) + } + + fn read_uleb128_as_u64(&mut self) -> anyhow::Result { + read_uleb128_as_u64(&mut self.cursor) + } + + #[cfg(test)] + fn new_for_test(version: u32, cursor: Cursor<&'a [u8]>) -> Self { + Self { version, cursor } + } +} + +impl<'a> Read for VersionedCursor<'a> { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + self.cursor.read(buf) + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/errors.rs b/CoqOfRust/move_sui/translations/move_binary_format/errors.rs new file mode 100644 index 000000000..c67943312 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/errors.rs @@ -0,0 +1,449 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + file_format::{CodeOffset, FunctionDefinitionIndex, TableIndex}, + IndexKind, +}; +use move_core_types::{ + language_storage::ModuleId, + vm_status::{StatusCode, StatusType}, +}; +use std::fmt; + +pub type VMResult = ::std::result::Result; +pub type BinaryLoaderResult = ::std::result::Result; +pub type PartialVMResult = ::std::result::Result; + +#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub enum Location { + Undefined, + Module(ModuleId), +} + +/// A representation of the execution state (e.g., stack trace) at an +/// error point. +#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct ExecutionState { + stack_trace: Vec<(ModuleId, FunctionDefinitionIndex, CodeOffset)>, + // we may consider adding more state if necessary +} + +impl ExecutionState { + pub fn new(stack_trace: Vec<(ModuleId, FunctionDefinitionIndex, CodeOffset)>) -> Self { + Self { stack_trace } + } + + pub fn stack_trace(&self) -> &Vec<(ModuleId, FunctionDefinitionIndex, CodeOffset)> { + &self.stack_trace + } +} + +#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)] +pub struct VMError(Box); + +#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)] +struct VMError_ { + major_status: StatusCode, + sub_status: Option, + message: Option, + exec_state: Option, + location: Location, + indices: Vec<(IndexKind, TableIndex)>, + offsets: Vec<(FunctionDefinitionIndex, CodeOffset)>, +} + +impl VMError { + pub fn major_status(&self) -> StatusCode { + self.0.major_status + } + + pub fn sub_status(&self) -> Option { + self.0.sub_status + } + + pub fn message(&self) -> Option<&String> { + self.0.message.as_ref() + } + + pub fn exec_state(&self) -> Option<&ExecutionState> { + self.0.exec_state.as_ref() + } + + pub fn remove_exec_state(&mut self) { + self.0.exec_state = None; + } + + pub fn location(&self) -> &Location { + &self.0.location + } + + pub fn indices(&self) -> &Vec<(IndexKind, TableIndex)> { + &self.0.indices + } + + pub fn offsets(&self) -> &Vec<(FunctionDefinitionIndex, CodeOffset)> { + &self.0.offsets + } + + pub fn status_type(&self) -> StatusType { + self.0.major_status.status_type() + } + + pub fn all_data( + self, + ) -> ( + StatusCode, + Option, + Option, + Option, + Location, + Vec<(IndexKind, TableIndex)>, + Vec<(FunctionDefinitionIndex, CodeOffset)>, + ) { + let VMError_ { + major_status, + sub_status, + message, + exec_state, + location, + indices, + offsets, + } = *self.0; + ( + major_status, + sub_status, + message, + exec_state, + location, + indices, + offsets, + ) + } + + pub fn to_partial(self) -> PartialVMError { + let VMError_ { + major_status, + sub_status, + message, + exec_state, + indices, + offsets, + .. + } = *self.0; + PartialVMError(Box::new(PartialVMError_ { + major_status, + sub_status, + message, + exec_state, + indices, + offsets, + })) + } +} + +impl fmt::Debug for VMError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl fmt::Debug for VMError_ { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { + major_status, + sub_status, + message, + exec_state, + location, + indices, + offsets, + } = self; + f.debug_struct("VMError") + .field("major_status", major_status) + .field("sub_status", sub_status) + .field("message", message) + .field("exec_state", exec_state) + .field("location", location) + .field("indices", indices) + .field("offsets", offsets) + .finish() + } +} + +impl std::error::Error for VMError {} + +#[derive(Clone)] +pub struct PartialVMError(Box); + +#[derive(Clone)] +struct PartialVMError_ { + major_status: StatusCode, + sub_status: Option, + message: Option, + exec_state: Option, + indices: Vec<(IndexKind, TableIndex)>, + offsets: Vec<(FunctionDefinitionIndex, CodeOffset)>, +} + +impl PartialVMError { + pub fn all_data( + self, + ) -> ( + StatusCode, + Option, + Option, + Option, + Vec<(IndexKind, TableIndex)>, + Vec<(FunctionDefinitionIndex, CodeOffset)>, + ) { + let PartialVMError_ { + major_status, + sub_status, + message, + exec_state, + indices, + offsets, + } = *self.0; + ( + major_status, + sub_status, + message, + exec_state, + indices, + offsets, + ) + } + + pub fn finish(self, location: Location) -> VMError { + let PartialVMError_ { + major_status, + sub_status, + message, + exec_state, + indices, + offsets, + } = *self.0; + VMError(Box::new(VMError_ { + major_status, + sub_status, + message, + exec_state, + location, + indices, + offsets, + })) + } + + pub fn new(major_status: StatusCode) -> Self { + Self(Box::new(PartialVMError_ { + major_status, + sub_status: None, + message: None, + exec_state: None, + indices: vec![], + offsets: vec![], + })) + } + + pub fn major_status(&self) -> StatusCode { + self.0.major_status + } + + pub fn with_sub_status(mut self, sub_status: u64) -> Self { + debug_assert!(self.0.sub_status.is_none()); + self.0.sub_status = Some(sub_status); + self + } + + pub fn with_message(mut self, message: String) -> Self { + debug_assert!(self.0.message.is_none()); + self.0.message = Some(message); + self + } + + pub fn with_exec_state(mut self, exec_state: ExecutionState) -> Self { + debug_assert!(self.0.exec_state.is_none()); + self.0.exec_state = Some(exec_state); + self + } + + pub fn at_index(mut self, kind: IndexKind, index: TableIndex) -> Self { + self.0.indices.push((kind, index)); + self + } + + pub fn at_indices(mut self, additional_indices: Vec<(IndexKind, TableIndex)>) -> Self { + self.0.indices.extend(additional_indices); + self + } + + pub fn at_code_offset(mut self, function: FunctionDefinitionIndex, offset: CodeOffset) -> Self { + self.0.offsets.push((function, offset)); + self + } + + pub fn at_code_offsets( + mut self, + additional_offsets: Vec<(FunctionDefinitionIndex, CodeOffset)>, + ) -> Self { + self.0.offsets.extend(additional_offsets); + self + } + + /// Append the message `message` to the message field of the VM status, and insert a seperator + /// if the original message is non-empty. + pub fn append_message_with_separator( + mut self, + separator: char, + additional_message: String, + ) -> Self { + match self.0.message.as_mut() { + Some(msg) => { + if !msg.is_empty() { + msg.push(separator); + } + msg.push_str(&additional_message); + } + None => self.0.message = Some(additional_message), + }; + self + } +} + +impl fmt::Display for Location { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Location::Undefined => write!(f, "UNDEFINED"), + Location::Module(id) => write!(f, "Module {:?}", id), + } + } +} + +impl fmt::Display for PartialVMError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut status = format!("PartialVMError with status {:#?}", self.0.major_status); + + if let Some(sub_status) = self.0.sub_status { + status = format!("{} with sub status {}", status, sub_status); + } + + if let Some(msg) = &self.0.message { + status = format!("{} and message {}", status, msg); + } + + for (kind, index) in &self.0.indices { + status = format!("{} at index {} for {}", status, index, kind); + } + for (fdef, code_offset) in &self.0.offsets { + status = format!( + "{} at code offset {} in function definition {}", + status, code_offset, fdef + ); + } + + write!(f, "{}", status) + } +} + +impl fmt::Display for VMError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut status = format!("VMError with status {:#?}", self.0.major_status); + + if let Some(sub_status) = self.0.sub_status { + status = format!("{} with sub status {}", status, sub_status); + } + + status = format!("{} at location {}", status, self.0.location); + + if let Some(msg) = &self.0.message { + status = format!("{} and message {}", status, msg); + } + + for (kind, index) in &self.0.indices { + status = format!("{} at index {} for {}", status, index, kind); + } + for (fdef, code_offset) in &self.0.offsets { + status = format!( + "{} at code offset {} in function definition {}", + status, code_offset, fdef + ); + } + + write!(f, "{}", status) + } +} + +//////////////////////////////////////////////////////////////////////////// +/// Conversion functions from internal VM statuses into external VM statuses +//////////////////////////////////////////////////////////////////////////// + +pub fn offset_out_of_bounds( + status: StatusCode, + kind: IndexKind, + target_offset: usize, + target_pool_len: usize, + cur_function: FunctionDefinitionIndex, + cur_bytecode_offset: CodeOffset, +) -> PartialVMError { + let msg = format!( + "Index {} out of bounds for {} at bytecode offset {} in function {} while indexing {}", + target_offset, target_pool_len, cur_bytecode_offset, cur_function, kind + ); + PartialVMError::new(status) + .with_message(msg) + .at_code_offset(cur_function, cur_bytecode_offset) +} + +pub fn bounds_error( + status: StatusCode, + kind: IndexKind, + idx: TableIndex, + len: usize, +) -> PartialVMError { + let msg = format!( + "Index {} out of bounds for {} while indexing {}", + idx, len, kind + ); + PartialVMError::new(status) + .at_index(kind, idx) + .with_message(msg) +} + +pub fn verification_error(status: StatusCode, kind: IndexKind, idx: TableIndex) -> PartialVMError { + PartialVMError::new(status).at_index(kind, idx) +} + +impl fmt::Debug for PartialVMError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl fmt::Debug for PartialVMError_ { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { + major_status, + sub_status, + message, + exec_state, + indices, + offsets, + } = self; + f.debug_struct("PartialVMError") + .field("major_status", major_status) + .field("sub_status", sub_status) + .field("message", message) + .field("exec_state", exec_state) + .field("indices", indices) + .field("offsets", offsets) + .finish() + } +} + +impl std::error::Error for PartialVMError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + None + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/file_format.rs b/CoqOfRust/move_sui/translations/move_binary_format/file_format.rs new file mode 100644 index 000000000..dcac56516 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/file_format.rs @@ -0,0 +1,2254 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! Binary format for transactions and modules. +//! +//! This module provides a simple Rust abstraction over the binary format. That is the format of +//! modules stored on chain or the format of the code section of a transaction. +//! +//! `file_format_common.rs` provides the constant values for entities in the binary format. +//! (*The binary format is evolving so please come back here in time to check evolutions.*) +//! +//! Overall the binary format is structured in a number of sections: +//! - **Header**: this must start at offset 0 in the binary. It contains a blob that starts every +//! Diem binary, followed by the version of the VM used to compile the code, and last is the +//! number of tables present in this binary. +//! - **Table Specification**: it's a number of tuple of the form +//! `(table type, starting_offset, byte_count)`. The number of entries is specified in the +//! header (last entry in header). There can only be a single entry per table type. The +//! `starting offset` is from the beginning of the binary. Tables must cover the entire size of +//! the binary blob and cannot overlap. +//! - **Table Content**: the serialized form of the specific entries in the table. Those roughly +//! map to the structs defined in this module. Entries in each table must be unique. +//! +//! We have two formats: one for modules here represented by `CompiledModule`, another +//! for transaction scripts which is `CompiledScript`. Building those tables and passing them +//! to the serializer (`serializer.rs`) generates a binary of the form described. Vectors in +//! those structs translate to tables and table specifications. + +use crate::{ + errors::{PartialVMError, PartialVMResult}, + file_format_common, + internals::ModuleIndex, + IndexKind, SignatureTokenKind, +}; +use move_core_types::{ + account_address::AccountAddress, + identifier::{IdentStr, Identifier}, + language_storage::ModuleId, + metadata::Metadata, + vm_status::StatusCode, +}; +#[cfg(any(test, feature = "fuzzing"))] +use proptest::{collection::vec, prelude::*, strategy::BoxedStrategy}; +use ref_cast::RefCast; +use serde::{Deserialize, Serialize}; +use std::ops::BitOr; +use variant_count::VariantCount; + +/// Generic index into one of the tables in the binary format. +pub type TableIndex = u16; + +macro_rules! define_index { + { + name: $name: ident, + kind: $kind: ident, + doc: $comment: literal, + } => { + #[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] + #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] + #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] + #[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] + #[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] + #[doc=$comment] + pub struct $name(pub TableIndex); + + /// Returns an instance of the given `Index`. + impl $name { + pub fn new(idx: TableIndex) -> Self { + Self(idx) + } + } + + impl ::std::fmt::Display for $name { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", self.0) + } + } + + impl ::std::fmt::Debug for $name { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}({})", stringify!($name), self.0) + } + } + + impl ModuleIndex for $name { + const KIND: IndexKind = IndexKind::$kind; + + #[inline] + fn into_index(self) -> usize { + self.0 as usize + } + } + }; +} + +define_index! { + name: ModuleHandleIndex, + kind: ModuleHandle, + doc: "Index into the `ModuleHandle` table.", +} +define_index! { + name: StructHandleIndex, + kind: StructHandle, + doc: "Index into the `StructHandle` table.", +} +define_index! { + name: FunctionHandleIndex, + kind: FunctionHandle, + doc: "Index into the `FunctionHandle` table.", +} +define_index! { + name: FieldHandleIndex, + kind: FieldHandle, + doc: "Index into the `FieldHandle` table.", +} +define_index! { + name: StructDefInstantiationIndex, + kind: StructDefInstantiation, + doc: "Index into the `StructInstantiation` table.", +} +define_index! { + name: FunctionInstantiationIndex, + kind: FunctionInstantiation, + doc: "Index into the `FunctionInstantiation` table.", +} +define_index! { + name: FieldInstantiationIndex, + kind: FieldInstantiation, + doc: "Index into the `FieldInstantiation` table.", +} +define_index! { + name: IdentifierIndex, + kind: Identifier, + doc: "Index into the `Identifier` table.", +} +define_index! { + name: AddressIdentifierIndex, + kind: AddressIdentifier, + doc: "Index into the `AddressIdentifier` table.", +} +define_index! { + name: ConstantPoolIndex, + kind: ConstantPool, + doc: "Index into the `ConstantPool` table.", +} +define_index! { + name: SignatureIndex, + kind: Signature, + doc: "Index into the `Signature` table.", +} +define_index! { + name: StructDefinitionIndex, + kind: StructDefinition, + doc: "Index into the `StructDefinition` table.", +} +define_index! { + name: FunctionDefinitionIndex, + kind: FunctionDefinition, + doc: "Index into the `FunctionDefinition` table.", +} + +/// Index of a local variable in a function. +/// +/// Bytecodes that operate on locals carry indexes to the locals of a function. +pub type LocalIndex = u8; +/// Max number of fields in a `StructDefinition`. +pub type MemberCount = u16; +/// Index into the code stream for a jump. The offset is relative to the beginning of +/// the instruction stream. +pub type CodeOffset = u16; + +/// The pool of identifiers. +pub type IdentifierPool = Vec; +/// The pool of address identifiers (addresses used in ModuleHandles/ModuleIds). +/// Does not include runtime values. Those are placed in the `ConstantPool` +pub type AddressIdentifierPool = Vec; +/// The pool of `Constant` values +pub type ConstantPool = Vec; +/// The pool of `TypeSignature` instances. Those are system and user types used and +/// their composition (e.g. &U64). +pub type TypeSignaturePool = Vec; +/// The pool of `Signature` instances. Every function definition must define the set of +/// locals used and their types. +pub type SignaturePool = Vec; + +// TODO: "" only passes the validator for identifiers because it is special cased. Whenever +// "" is removed, so should the special case in identifier.rs. +pub fn self_module_name() -> &'static IdentStr { + IdentStr::ref_cast("") +} + +/// Index 0 into the LocalsSignaturePool, which is guaranteed to be an empty list. +/// Used to represent function/struct instantiation with no type arguments -- effectively +/// non-generic functions and structs. +pub const NO_TYPE_ARGUMENTS: SignatureIndex = SignatureIndex(0); + +// HANDLES: +// Handles are structs that accompany opcodes that need references: a type reference, +// or a function reference (a field reference being available only within the module that +// defines the field can be a definition). +// Handles refer to both internal and external "entities" and are embedded as indexes +// in the instruction stream. +// Handles define resolution. Resolution is assumed to be by (name, signature) + +/// A `ModuleHandle` is a reference to a MOVE module. It is composed by an `address` and a `name`. +/// +/// A `ModuleHandle` uniquely identifies a code entity in the blockchain. +/// The `address` is a reference to the account that holds the code and the `name` is used as a +/// key in order to load the module. +/// +/// Modules live in the *code* namespace of an DiemAccount. +/// +/// Modules introduce a scope made of all types defined in the module and all functions. +/// Type definitions (fields) are private to the module. Outside the module a +/// Type is an opaque handle. +#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct ModuleHandle { + /// Index into the `AddressIdentifierIndex`. Identifies module-holding account's address. + pub address: AddressIdentifierIndex, + /// The name of the module published in the code section for the account in `address`. + pub name: IdentifierIndex, +} + +/// A `StructHandle` is a reference to a user defined type. It is composed by a `ModuleHandle` +/// and the name of the type within that module. +/// +/// A type in a module is uniquely identified by its name and as such the name is enough +/// to perform resolution. +/// +/// The `StructHandle` is polymorphic: it can have type parameters in its fields and carries the +/// ability constraints for these type parameters (empty list for non-generic structs). It also +/// carries the abilities of the struct itself so that the verifier can check +/// ability semantics without having to load the referenced type. +/// +/// At link time ability/constraint checking is performed and an error is reported if there is a +/// mismatch with the definition. +#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct StructHandle { + /// The module that defines the type. + pub module: ModuleHandleIndex, + /// The name of the type. + pub name: IdentifierIndex, + /// Contains the abilities for this struct + /// For any instantiation of this type, the abilities of this type are predicated on + /// that ability being satisfied for all type parameters. + pub abilities: AbilitySet, + /// The type formals (identified by their index into the vec) + pub type_parameters: Vec, +} + +impl StructHandle { + pub fn type_param_constraints(&self) -> impl ExactSizeIterator + '_ { + self.type_parameters.iter().map(|param| param.constraints) + } +} + +/// A type parameter used in the declaration of a struct. +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +pub struct StructTypeParameter { + /// The type parameter constraints. + pub constraints: AbilitySet, + /// Whether the parameter is declared as phantom. + pub is_phantom: bool, +} + +/// A `FunctionHandle` is a reference to a function. It is composed by a +/// `ModuleHandle` and the name and signature of that function within the module. +/// +/// A function within a module is uniquely identified by its name. No overloading is allowed +/// and the verifier enforces that property. The signature of the function is used at link time to +/// ensure the function reference is valid and it is also used by the verifier to type check +/// function calls. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(params = "usize"))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct FunctionHandle { + /// The module that defines the function. + pub module: ModuleHandleIndex, + /// The name of the function. + pub name: IdentifierIndex, + /// The list of arguments to the function. + pub parameters: SignatureIndex, + /// The list of return types. + pub return_: SignatureIndex, + /// The type formals (identified by their index into the vec) and their constraints + pub type_parameters: Vec, +} + +/// A field access info (owner type and offset) +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct FieldHandle { + pub owner: StructDefinitionIndex, + pub field: MemberCount, +} + +// DEFINITIONS: +// Definitions are the module code. So the set of types and functions in the module. + +/// `StructFieldInformation` indicates whether a struct is native or has user-specified fields +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub enum StructFieldInformation { + Native, + Declared(Vec), +} + +// +// Instantiations +// +// Instantiations point to a generic handle and its instantiation. +// The instantiation can be partial. +// So, for example, `S`, `S`, `S`, `S, address>` are all +// `StructInstantiation`s + +/// A complete or partial instantiation of a generic struct +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct StructDefInstantiation { + pub def: StructDefinitionIndex, + pub type_parameters: SignatureIndex, +} + +/// A complete or partial instantiation of a function +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct FunctionInstantiation { + pub handle: FunctionHandleIndex, + pub type_parameters: SignatureIndex, +} + +/// A complete or partial instantiation of a field (or the type of it). +/// +/// A `FieldInstantiation` points to a generic `FieldHandle` and the instantiation +/// of the owner type. +/// E.g. for `S.f` where `f` is a field of any type, `instantiation` +/// would be `[u8, boo]` +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct FieldInstantiation { + pub handle: FieldHandleIndex, + pub type_parameters: SignatureIndex, +} + +/// A `StructDefinition` is a type definition. It either indicates it is native or defines all the +/// user-specified fields declared on the type. +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct StructDefinition { + /// The `StructHandle` for this `StructDefinition`. This has the name and the abilities + /// for the type. + pub struct_handle: StructHandleIndex, + /// Contains either + /// - Information indicating the struct is native and has no accessible fields + /// - Information indicating the number of fields and the start `FieldDefinition`s + pub field_information: StructFieldInformation, +} + +impl StructDefinition { + pub fn declared_field_count(&self) -> PartialVMResult { + match &self.field_information { + // TODO we might want a more informative error here + StructFieldInformation::Native => Err(PartialVMError::new(StatusCode::LINKER_ERROR) + .with_message("Looking for field in native structure".to_string())), + StructFieldInformation::Declared(fields) => Ok(fields.len() as u16), + } + } + + pub fn field(&self, offset: usize) -> Option<&FieldDefinition> { + match &self.field_information { + StructFieldInformation::Native => None, + StructFieldInformation::Declared(fields) => fields.get(offset), + } + } + + pub fn fields(&self) -> Option<&[FieldDefinition]> { + match &self.field_information { + StructFieldInformation::Native => None, + StructFieldInformation::Declared(fields) => Some(fields), + } + } +} + +/// A `FieldDefinition` is the definition of a field: its name and the field type. +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct FieldDefinition { + /// The name of the field. + pub name: IdentifierIndex, + /// The type of the field. + pub signature: TypeSignature, +} + +/// `Visibility` restricts the accessibility of the associated entity. +/// - For function visibility, it restricts who may call into the associated function. +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[repr(u8)] +#[derive(Default)] +pub enum Visibility { + /// Accessible within its defining module only. + #[default] + Private = 0x0, + /// Accessible by any module or script outside of its declaring module. + Public = 0x1, + // DEPRECATED for separate entry modifier + // Accessible by any script or other `Script` functions from any module + // Script = 0x2, + /// Accessible by this module as well as modules declared in the friend list. + Friend = 0x3, +} + +impl Visibility { + pub const DEPRECATED_SCRIPT: u8 = 0x2; +} + +impl std::convert::TryFrom for Visibility { + type Error = (); + + fn try_from(v: u8) -> Result { + match v { + x if x == Visibility::Private as u8 => Ok(Visibility::Private), + x if x == Visibility::Public as u8 => Ok(Visibility::Public), + x if x == Visibility::Friend as u8 => Ok(Visibility::Friend), + _ => Err(()), + } + } +} + +/// A `FunctionDefinition` is the implementation of a function. It defines +/// the *prototype* of the function and the function body. +#[derive(Clone, Debug, Default, Eq, PartialEq)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(params = "usize"))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct FunctionDefinition { + /// The prototype of the function (module, name, signature). + pub function: FunctionHandleIndex, + /// The visibility of this function. + pub visibility: Visibility, + /// Marker if the function is intended as an entry function. That is + pub is_entry: bool, + /// List of locally defined types (declared in this module) with the `Key` ability + /// that the procedure might access, either through: BorrowGlobal, MoveFrom, or transitively + /// through another procedure + /// This list of acquires grants the borrow checker the ability to statically verify the safety + /// of references into global storage + /// + /// Not in the signature as it is not needed outside of the declaring module + /// + /// Note, there is no SignatureIndex with each struct definition index, so all instantiations of + /// that type are considered as being acquired + pub acquires_global_resources: Vec, + /// Code for this function. + #[cfg_attr( + any(test, feature = "fuzzing"), + proptest(strategy = "any_with::(params).prop_map(Some)") + )] + pub code: Option, +} + +impl FunctionDefinition { + /// Returns whether the FunctionDefinition is native. + pub fn is_native(&self) -> bool { + self.code.is_none() + } + + // Deprecated public bit, deprecated in favor a the Visibility enum + pub const DEPRECATED_PUBLIC_BIT: u8 = 0b01; + + /// A native function implemented in Rust. + pub const NATIVE: u8 = 0b10; + + /// An entry function, intended to be used as an entry point to execution + pub const ENTRY: u8 = 0b100; +} + +// Signature +// A signature can be for a type (field, local) or for a function - return type: (arguments). +// They both go into the signature table so there is a marker that tags the signature. +// Signature usually don't carry a size and you have to read them to get to the end. + +/// A type definition. `SignatureToken` allows the definition of the set of known types and their +/// composition. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct TypeSignature(pub SignatureToken); + +// TODO: remove at some point or move it in the front end (language/move-ir-compiler) +/// A `FunctionSignature` in internally used to create a unique representation of the overall +/// signature as need. Consider deprecated... +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(params = "usize"))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct FunctionSignature { + /// The list of return types. + #[cfg_attr( + any(test, feature = "fuzzing"), + proptest(strategy = "vec(any::(), 0..=params)") + )] + pub return_: Vec, + /// The list of arguments to the function. + #[cfg_attr( + any(test, feature = "fuzzing"), + proptest(strategy = "vec(any::(), 0..=params)") + )] + pub parameters: Vec, + /// The type formals (identified by their index into the vec) and their constraints + pub type_parameters: Vec, +} + +/// A `Signature` is the list of locals used by a function. +/// +/// Locals include the arguments to the function from position `0` to argument `count - 1`. +/// The remaining elements are the type of each local. +#[derive(Clone, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(params = "usize"))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct Signature( + #[cfg_attr( + any(test, feature = "fuzzing"), + proptest(strategy = "vec(any::(), 0..=params)") + )] + pub Vec, +); + +impl Signature { + /// Length of the `Signature`. + #[inline] + pub fn len(&self) -> usize { + self.0.len() + } + + /// Whether the function has no locals (both arguments or locals). + #[inline] + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +/// Type parameters are encoded as indices. This index can also be used to lookup the kind of a +/// type parameter in the `FunctionHandle` and `StructHandle`. +pub type TypeParameterIndex = u16; + +/// An `Ability` classifies what operations are permitted for a given type +#[repr(u8)] +#[derive(Debug, Clone, Eq, Copy, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub enum Ability { + /// Allows values of types with this ability to be copied, via CopyLoc or ReadRef + Copy = 0x1, + /// Allows values of types with this ability to be dropped, via Pop, WriteRef, StLoc, Eq, Neq, + /// or if left in a local when Ret is invoked + /// Technically also needed for numeric operations (Add, BitAnd, Shift, etc), but all + /// of the types that can be used with those operations have Drop + Drop = 0x2, + /// Allows values of types with this ability to exist inside a struct in global storage + Store = 0x4, + /// Allows the type to serve as a key for global storage operations: MoveTo, MoveFrom, etc. + Key = 0x8, +} + +impl Ability { + fn from_u8(u: u8) -> Option { + match u { + 0x1 => Some(Ability::Copy), + 0x2 => Some(Ability::Drop), + 0x4 => Some(Ability::Store), + 0x8 => Some(Ability::Key), + _ => None, + } + } + + /// For a struct with ability `a`, each field needs to have the ability `a.requires()`. + /// Consider a generic type Foo, for Foo to have ability `a`, Foo must + /// have been declared with `a` and each type argument ti must have the ability `a.requires()` + pub fn requires(self) -> Self { + match self { + Self::Copy => Ability::Copy, + Self::Drop => Ability::Drop, + Self::Store => Ability::Store, + Self::Key => Ability::Store, + } + } + + /// An inverse of `requires`, where x is in a.required_by() iff x.requires() == a + pub fn required_by(self) -> AbilitySet { + match self { + Self::Copy => AbilitySet::EMPTY | Ability::Copy, + Self::Drop => AbilitySet::EMPTY | Ability::Drop, + Self::Store => AbilitySet::EMPTY | Ability::Store | Ability::Key, + Self::Key => AbilitySet::EMPTY, + } + } +} + +/// A set of `Ability`s +#[derive(Clone, Eq, Copy, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +pub struct AbilitySet(u8); + +impl AbilitySet { + /// The empty ability set + pub const EMPTY: Self = Self(0); + /// Abilities for `Bool`, `U8`, `U16`, `U32`, `U64`, `U128`, `U256`, and `Address` + pub const PRIMITIVES: AbilitySet = + Self((Ability::Copy as u8) | (Ability::Drop as u8) | (Ability::Store as u8)); + /// Abilities for `Reference` and `MutableReference` + pub const REFERENCES: AbilitySet = Self((Ability::Copy as u8) | (Ability::Drop as u8)); + /// Abilities for `Signer` + pub const SIGNER: AbilitySet = Self(Ability::Drop as u8); + /// Abilities for `Vector`, note they are predicated on the type argument + pub const VECTOR: AbilitySet = + Self((Ability::Copy as u8) | (Ability::Drop as u8) | (Ability::Store as u8)); + + /// Ability set containing all abilities + pub const ALL: Self = Self( + // Cannot use AbilitySet bitor because it is not const + (Ability::Copy as u8) + | (Ability::Drop as u8) + | (Ability::Store as u8) + | (Ability::Key as u8), + ); + + pub fn singleton(ability: Ability) -> Self { + Self(ability as u8) + } + + pub fn has_ability(self, ability: Ability) -> bool { + let a = ability as u8; + (a & self.0) == a + } + + pub fn has_copy(self) -> bool { + self.has_ability(Ability::Copy) + } + + pub fn has_drop(self) -> bool { + self.has_ability(Ability::Drop) + } + + pub fn has_store(self) -> bool { + self.has_ability(Ability::Store) + } + + pub fn has_key(self) -> bool { + self.has_ability(Ability::Key) + } + + pub fn remove(self, ability: Ability) -> Self { + Self(self.0 & (!(ability as u8))) + } + + pub fn intersect(self, other: Self) -> Self { + Self(self.0 & other.0) + } + + pub fn union(self, other: Self) -> Self { + Self(self.0 | other.0) + } + + #[inline] + fn is_subset_bits(sub: u8, sup: u8) -> bool { + (sub & sup) == sub + } + + pub fn is_subset(self, other: Self) -> bool { + Self::is_subset_bits(self.0, other.0) + } + + /// For a polymorphic type, its actual abilities correspond to its declared abilities but + /// predicated on its non-phantom type arguments having that ability. For `Key`, instead of needing + /// the same ability, the type arguments need `Store`. + pub fn polymorphic_abilities( + declared_abilities: Self, + declared_phantom_parameters: I1, + type_arguments: I2, + ) -> PartialVMResult + where + I1: IntoIterator, + I2: IntoIterator, + I1::IntoIter: ExactSizeIterator, + I2::IntoIter: ExactSizeIterator, + { + let declared_phantom_parameters = declared_phantom_parameters.into_iter(); + let type_arguments = type_arguments.into_iter(); + + if declared_phantom_parameters.len() != type_arguments.len() { + return Err( + PartialVMError::new(StatusCode::VERIFIER_INVARIANT_VIOLATION).with_message( + "the length of `declared_phantom_parameters` doesn't match the length of `type_arguments`".to_string(), + ), + ); + } + + // Conceptually this is performing the following operation: + // For any ability 'a' in `declared_abilities` + // 'a' is in the result only if + // for all (abi_i, is_phantom_i) in `type_arguments` s.t. !is_phantom then a.required() is a subset of abi_i + // + // So to do this efficiently, we can determine the required_by set for each ti + // and intersect them together along with the declared abilities + // This only works because for any ability y, |y.requires()| == 1 + let abs = type_arguments + .zip(declared_phantom_parameters) + .filter(|(_, is_phantom)| !is_phantom) + .map(|(ty_arg_abilities, _)| { + ty_arg_abilities + .into_iter() + .map(|a| a.required_by()) + .fold(AbilitySet::EMPTY, AbilitySet::union) + }) + .fold(declared_abilities, |acc, ty_arg_abilities| { + acc.intersect(ty_arg_abilities) + }); + Ok(abs) + } + + pub fn from_u8(byte: u8) -> Option { + // If there is a bit set in the read `byte`, that bit must be set in the + // `AbilitySet` containing all `Ability`s + // This corresponds the byte being a bit set subset of ALL + // The byte is a subset of ALL if the intersection of the two is the original byte + if Self::is_subset_bits(byte, Self::ALL.0) { + Some(Self(byte)) + } else { + None + } + } + + pub fn into_u8(self) -> u8 { + self.0 + } +} + +impl BitOr for AbilitySet { + type Output = Self; + fn bitor(self, rhs: Ability) -> Self { + AbilitySet(self.0 | (rhs as u8)) + } +} + +impl BitOr for AbilitySet { + type Output = Self; + fn bitor(self, rhs: Self) -> Self { + AbilitySet(self.0 | rhs.0) + } +} + +pub struct AbilitySetIterator { + set: AbilitySet, + idx: u8, +} + +impl Iterator for AbilitySetIterator { + type Item = Ability; + + fn next(&mut self) -> Option { + while self.idx <= 0x8 { + let next = Ability::from_u8(self.set.0 & self.idx); + self.idx <<= 1; + if next.is_some() { + return next; + } + } + None + } +} + +impl IntoIterator for AbilitySet { + type Item = Ability; + type IntoIter = AbilitySetIterator; + fn into_iter(self) -> Self::IntoIter { + AbilitySetIterator { + idx: 0x1, + set: self, + } + } +} + +impl std::fmt::Debug for AbilitySet { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + write!(f, "[")?; + for ability in *self { + write!(f, "{:?}, ", ability)?; + } + write!(f, "]") + } +} + +#[cfg(any(test, feature = "fuzzing"))] +impl Arbitrary for AbilitySet { + type Strategy = BoxedStrategy; + type Parameters = (); + + fn arbitrary_with(_params: Self::Parameters) -> Self::Strategy { + proptest::bits::u8::masked(AbilitySet::ALL.0) + .prop_map(|u| AbilitySet::from_u8(u).expect("proptest mask failed for AbilitySet")) + .boxed() + } +} + +/// A `SignatureToken` is a type declaration for a location. +/// +/// Any location in the system has a TypeSignature. +/// A TypeSignature is also used in composed signatures. +/// +/// A SignatureToken can express more types than the VM can handle safely, and correctness is +/// enforced by the verifier. +#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub enum SignatureToken { + /// Boolean, `true` or `false`. + Bool, + /// Unsigned integers, 8 bits length. + U8, + /// Unsigned integers, 64 bits length. + U64, + /// Unsigned integers, 128 bits length. + U128, + /// Address, a 16 bytes immutable type. + Address, + /// Signer, a 16 bytes immutable type representing the capability to publish at an address + Signer, + /// Vector + Vector(Box), + /// User defined type + Struct(StructHandleIndex), + StructInstantiation(Box<(StructHandleIndex, Vec)>), + /// Reference to a type. + Reference(Box), + /// Mutable reference to a type. + MutableReference(Box), + /// Type parameter. + TypeParameter(TypeParameterIndex), + /// Unsigned integers, 16 bits length. + U16, + /// Unsigned integers, 32 bits length. + U32, + /// Unsigned integers, 256 bits length. + U256, +} + +/// An iterator to help traverse the `SignatureToken` in a non-recursive fashion to avoid +/// overflowing the stack. +/// +/// Traversal order: root -> left -> right +pub struct SignatureTokenPreorderTraversalIter<'a> { + stack: Vec<&'a SignatureToken>, +} + +impl<'a> Iterator for SignatureTokenPreorderTraversalIter<'a> { + type Item = &'a SignatureToken; + + fn next(&mut self) -> Option { + use SignatureToken::*; + + match self.stack.pop() { + Some(tok) => { + match tok { + Reference(inner_tok) | MutableReference(inner_tok) | Vector(inner_tok) => { + self.stack.push(inner_tok) + } + + StructInstantiation(struct_inst) => { + let (_, inner_toks) = &**struct_inst; + self.stack.extend(inner_toks.iter().rev()) + } + + Signer | Bool | Address | U8 | U16 | U32 | U64 | U128 | U256 | Struct(_) + | TypeParameter(_) => (), + } + Some(tok) + } + None => None, + } + } +} + +/// Alternative preorder traversal iterator for SignatureToken that also returns the depth at each +/// node. +pub struct SignatureTokenPreorderTraversalIterWithDepth<'a> { + stack: Vec<(&'a SignatureToken, usize)>, +} + +impl<'a> Iterator for SignatureTokenPreorderTraversalIterWithDepth<'a> { + type Item = (&'a SignatureToken, usize); + + fn next(&mut self) -> Option { + use SignatureToken::*; + + match self.stack.pop() { + Some((tok, depth)) => { + match tok { + Reference(inner_tok) | MutableReference(inner_tok) | Vector(inner_tok) => { + self.stack.push((inner_tok, depth + 1)) + } + + StructInstantiation(struct_inst) => { + let (_, inner_toks) = &**struct_inst; + self.stack + .extend(inner_toks.iter().map(|tok| (tok, depth + 1)).rev()) + } + + Signer | Bool | Address | U8 | U16 | U32 | U64 | U128 | U256 | Struct(_) + | TypeParameter(_) => (), + } + Some((tok, depth)) + } + None => None, + } + } +} + +/// `Arbitrary` for `SignatureToken` cannot be derived automatically as it's a recursive type. +#[cfg(any(test, feature = "fuzzing"))] +impl Arbitrary for SignatureToken { + type Strategy = BoxedStrategy; + type Parameters = (); + + fn arbitrary_with(_params: Self::Parameters) -> Self::Strategy { + use SignatureToken::*; + + let leaf = prop_oneof![ + Just(Bool), + Just(U8), + Just(U16), + Just(U32), + Just(U64), + Just(U128), + Just(U256), + Just(Address), + any::().prop_map(Struct), + any::().prop_map(TypeParameter), + ]; + leaf.prop_recursive( + 8, // levels deep + 16, // max size + 1, // items per collection + |inner| { + prop_oneof![ + inner.clone().prop_map(|token| Vector(Box::new(token))), + inner.clone().prop_map(|token| Reference(Box::new(token))), + inner.prop_map(|token| MutableReference(Box::new(token))), + ] + }, + ) + .boxed() + } +} + +impl std::fmt::Debug for SignatureToken { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + SignatureToken::Bool => write!(f, "Bool"), + SignatureToken::U8 => write!(f, "U8"), + SignatureToken::U16 => write!(f, "U16"), + SignatureToken::U32 => write!(f, "U32"), + SignatureToken::U64 => write!(f, "U64"), + SignatureToken::U128 => write!(f, "U128"), + SignatureToken::U256 => write!(f, "U256"), + SignatureToken::Address => write!(f, "Address"), + SignatureToken::Signer => write!(f, "Signer"), + SignatureToken::Vector(boxed) => write!(f, "Vector({:?})", boxed), + SignatureToken::Struct(idx) => write!(f, "Struct({:?})", idx), + SignatureToken::StructInstantiation(struct_inst) => { + let (idx, types) = &**struct_inst; + write!(f, "StructInstantiation({:?}, {:?})", idx, types) + } + SignatureToken::Reference(boxed) => write!(f, "Reference({:?})", boxed), + SignatureToken::MutableReference(boxed) => write!(f, "MutableReference({:?})", boxed), + SignatureToken::TypeParameter(idx) => write!(f, "TypeParameter({:?})", idx), + } + } +} + +impl SignatureToken { + /// Returns the "value kind" for the `SignatureToken` + #[inline] + pub fn signature_token_kind(&self) -> SignatureTokenKind { + // TODO: SignatureTokenKind is out-dated. fix/update/remove SignatureTokenKind and see if + // this function needs to be cleaned up + use SignatureToken::*; + + match self { + Reference(_) => SignatureTokenKind::Reference, + MutableReference(_) => SignatureTokenKind::MutableReference, + Bool + | U8 + | U16 + | U32 + | U64 + | U128 + | U256 + | Address + | Signer + | Struct(_) + | StructInstantiation(_) + | Vector(_) => SignatureTokenKind::Value, + // TODO: This is a temporary hack to please the verifier. SignatureTokenKind will soon + // be completely removed. `SignatureTokenView::kind()` should be used instead. + TypeParameter(_) => SignatureTokenKind::Value, + } + } + + // Returns `true` if the `SignatureToken` is an integer type. + pub fn is_integer(&self) -> bool { + use SignatureToken::*; + match self { + U8 | U16 | U32 | U64 | U128 | U256 => true, + Bool + | Address + | Signer + | Vector(_) + | Struct(_) + | StructInstantiation(_) + | Reference(_) + | MutableReference(_) + | TypeParameter(_) => false, + } + } + + /// Returns true if the `SignatureToken` is any kind of reference (mutable and immutable). + pub fn is_reference(&self) -> bool { + use SignatureToken::*; + + matches!(self, Reference(_) | MutableReference(_)) + } + + /// Returns true if the `SignatureToken` is a mutable reference. + pub fn is_mutable_reference(&self) -> bool { + use SignatureToken::*; + + matches!(self, MutableReference(_)) + } + + /// Returns true if the `SignatureToken` is a signer + pub fn is_signer(&self) -> bool { + use SignatureToken::*; + + matches!(self, Signer) + } + + /// Returns true if the `SignatureToken` can represent a constant (as in representable in + /// the constants table). + pub fn is_valid_for_constant(&self) -> bool { + use SignatureToken::*; + + match self { + Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address => true, + Vector(inner) => inner.is_valid_for_constant(), + Signer + | Struct(_) + | StructInstantiation(_) + | Reference(_) + | MutableReference(_) + | TypeParameter(_) => false, + } + } + + /// Set the index to this one. Useful for random testing. + /// + /// Panics if this token doesn't contain a struct handle. + pub fn debug_set_sh_idx(&mut self, sh_idx: StructHandleIndex) { + match self { + SignatureToken::Struct(ref mut wrapped) => *wrapped = sh_idx, + SignatureToken::StructInstantiation(ref mut struct_inst) => { + Box::as_mut(struct_inst).0 = sh_idx + } + SignatureToken::Reference(ref mut token) + | SignatureToken::MutableReference(ref mut token) => token.debug_set_sh_idx(sh_idx), + other => panic!( + "debug_set_sh_idx (to {}) called for non-struct token {:?}", + sh_idx, other + ), + } + } + + pub fn preorder_traversal(&self) -> SignatureTokenPreorderTraversalIter<'_> { + SignatureTokenPreorderTraversalIter { stack: vec![self] } + } + + pub fn preorder_traversal_with_depth( + &self, + ) -> SignatureTokenPreorderTraversalIterWithDepth<'_> { + SignatureTokenPreorderTraversalIterWithDepth { + stack: vec![(self, 1)], + } + } +} + +/// A `Constant` is a serialized value along with its type. That type will be deserialized by the +/// loader/evauluator +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct Constant { + pub type_: SignatureToken, + pub data: Vec, +} + +/// A `CodeUnit` is the body of a function. It has the function header and the instruction stream. +#[derive(Clone, Debug, Default, Eq, PartialEq)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(params = "usize"))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct CodeUnit { + /// List of locals type. All locals are typed. + pub locals: SignatureIndex, + /// Code stream, function body. + #[cfg_attr( + any(test, feature = "fuzzing"), + proptest(strategy = "vec(any::(), 0..=params)") + )] + pub code: Vec, +} + +/// `Bytecode` is a VM instruction of variable size. The type of the bytecode (opcode) defines +/// the size of the bytecode. +/// +/// Bytecodes operate on a stack machine and each bytecode has side effect on the stack and the +/// instruction stream. +#[derive(Clone, Hash, Eq, VariantCount, PartialEq)] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub enum Bytecode { + /// Pop and discard the value at the top of the stack. + /// The value on the stack must be an copyable type. + /// + /// Stack transition: + /// + /// ```..., value -> ...``` + Pop, + /// Return from function, possibly with values according to the return types in the + /// function signature. The returned values are pushed on the stack. + /// The function signature of the function being executed defines the semantic of + /// the Ret opcode. + /// + /// Stack transition: + /// + /// ```..., arg_val(1), ..., arg_val(n) -> ..., return_val(1), ..., return_val(n)``` + Ret, + /// Branch to the instruction at position `CodeOffset` if the value at the top of the stack + /// is true. Code offsets are relative to the start of the instruction stream. + /// + /// Stack transition: + /// + /// ```..., bool_value -> ...``` + BrTrue(CodeOffset), + /// Branch to the instruction at position `CodeOffset` if the value at the top of the stack + /// is false. Code offsets are relative to the start of the instruction stream. + /// + /// Stack transition: + /// + /// ```..., bool_value -> ...``` + BrFalse(CodeOffset), + /// Branch unconditionally to the instruction at position `CodeOffset`. Code offsets are + /// relative to the start of the instruction stream. + /// + /// Stack transition: none + Branch(CodeOffset), + /// Push a U8 constant onto the stack. + /// + /// Stack transition: + /// + /// ```... -> ..., u8_value``` + LdU8(u8), + /// Push a U64 constant onto the stack. + /// + /// Stack transition: + /// + /// ```... -> ..., u64_value``` + LdU64(u64), + /// Push a U128 constant onto the stack. + /// + /// Stack transition: + /// + /// ```... -> ..., u128_value``` + LdU128(Box), + /// Convert the value at the top of the stack into u8. + /// + /// Stack transition: + /// + /// ```..., integer_value -> ..., u8_value``` + CastU8, + /// Convert the value at the top of the stack into u64. + /// + /// Stack transition: + /// + /// ```..., integer_value -> ..., u8_value``` + CastU64, + /// Convert the value at the top of the stack into u128. + /// + /// Stack transition: + /// + /// ```..., integer_value -> ..., u128_value``` + CastU128, + /// Push a `Constant` onto the stack. The value is loaded and deserialized (according to its + /// type) from the the `ConstantPool` via `ConstantPoolIndex` + /// + /// Stack transition: + /// + /// ```... -> ..., value``` + LdConst(ConstantPoolIndex), + /// Push `true` onto the stack. + /// + /// Stack transition: + /// + /// ```... -> ..., true``` + LdTrue, + /// Push `false` onto the stack. + /// + /// Stack transition: + /// + /// ```... -> ..., false``` + LdFalse, + /// Push the local identified by `LocalIndex` onto the stack. The value is copied and the + /// local is still safe to use. + /// + /// Stack transition: + /// + /// ```... -> ..., value``` + CopyLoc(LocalIndex), + /// Push the local identified by `LocalIndex` onto the stack. The local is moved and it is + /// invalid to use from that point on, unless a store operation writes to the local before + /// any read to that local. + /// + /// Stack transition: + /// + /// ```... -> ..., value``` + MoveLoc(LocalIndex), + /// Pop value from the top of the stack and store it into the function locals at + /// position `LocalIndex`. + /// + /// Stack transition: + /// + /// ```..., value -> ...``` + StLoc(LocalIndex), + /// Call a function. The stack has the arguments pushed first to last. + /// The arguments are consumed and pushed to the locals of the function. + /// Return values are pushed on the stack and available to the caller. + /// + /// Stack transition: + /// + /// ```..., arg(1), arg(2), ..., arg(n) -> ..., return_value(1), return_value(2), ..., + /// return_value(k)``` + Call(FunctionHandleIndex), + CallGeneric(FunctionInstantiationIndex), + /// Create an instance of the type specified via `StructHandleIndex` and push it on the stack. + /// The values of the fields of the struct, in the order they appear in the struct declaration, + /// must be pushed on the stack. All fields must be provided. + /// + /// A Pack instruction must fully initialize an instance. + /// + /// Stack transition: + /// + /// ```..., field(1)_value, field(2)_value, ..., field(n)_value -> ..., instance_value``` + Pack(StructDefinitionIndex), + PackGeneric(StructDefInstantiationIndex), + /// Destroy an instance of a type and push the values bound to each field on the + /// stack. + /// + /// The values of the fields of the instance appear on the stack in the order defined + /// in the struct definition. + /// + /// This order makes Unpack the inverse of Pack. So `Unpack; Pack` is the identity + /// for struct T. + /// + /// Stack transition: + /// + /// ```..., instance_value -> ..., field(1)_value, field(2)_value, ..., field(n)_value``` + Unpack(StructDefinitionIndex), + UnpackGeneric(StructDefInstantiationIndex), + /// Read a reference. The reference is on the stack, it is consumed and the value read is + /// pushed on the stack. + /// + /// Reading a reference performs a copy of the value referenced. + /// As such, ReadRef requires that the type of the value has the `Copy` ability. + /// + /// Stack transition: + /// + /// ```..., reference_value -> ..., value``` + ReadRef, + /// Write to a reference. The reference and the value are on the stack and are consumed. + /// + /// + /// WriteRef requires that the type of the value has the `Drop` ability as the previous value + /// is lost + /// + /// Stack transition: + /// + /// ```..., value, reference_value -> ...``` + WriteRef, + /// Convert a mutable reference to an immutable reference. + /// + /// Stack transition: + /// + /// ```..., reference_value -> ..., reference_value``` + FreezeRef, + /// Load a mutable reference to a local identified by LocalIndex. + /// + /// The local must not be a reference. + /// + /// Stack transition: + /// + /// ```... -> ..., reference``` + MutBorrowLoc(LocalIndex), + /// Load an immutable reference to a local identified by LocalIndex. + /// + /// The local must not be a reference. + /// + /// Stack transition: + /// + /// ```... -> ..., reference``` + ImmBorrowLoc(LocalIndex), + /// Load a mutable reference to a field identified by `FieldHandleIndex`. + /// The top of the stack must be a mutable reference to a type that contains the field + /// definition. + /// + /// Stack transition: + /// + /// ```..., reference -> ..., field_reference``` + MutBorrowField(FieldHandleIndex), + /// Load a mutable reference to a field identified by `FieldInstantiationIndex`. + /// The top of the stack must be a mutable reference to a type that contains the field + /// definition. + /// + /// Stack transition: + /// + /// ```..., reference -> ..., field_reference``` + MutBorrowFieldGeneric(FieldInstantiationIndex), + /// Load an immutable reference to a field identified by `FieldHandleIndex`. + /// The top of the stack must be a reference to a type that contains the field definition. + /// + /// Stack transition: + /// + /// ```..., reference -> ..., field_reference``` + ImmBorrowField(FieldHandleIndex), + /// Load an immutable reference to a field identified by `FieldInstantiationIndex`. + /// The top of the stack must be a reference to a type that contains the field definition. + /// + /// Stack transition: + /// + /// ```..., reference -> ..., field_reference``` + ImmBorrowFieldGeneric(FieldInstantiationIndex), + /// Add the 2 u64 at the top of the stack and pushes the result on the stack. + /// The operation aborts the transaction in case of overflow. + /// + /// Stack transition: + /// + /// ```..., u64_value(1), u64_value(2) -> ..., u64_value``` + Add, + /// Subtract the 2 u64 at the top of the stack and pushes the result on the stack. + /// The operation aborts the transaction in case of underflow. + /// + /// Stack transition: + /// + /// ```..., u64_value(1), u64_value(2) -> ..., u64_value``` + Sub, + /// Multiply the 2 u64 at the top of the stack and pushes the result on the stack. + /// The operation aborts the transaction in case of overflow. + /// + /// Stack transition: + /// + /// ```..., u64_value(1), u64_value(2) -> ..., u64_value``` + Mul, + /// Perform a modulo operation on the 2 u64 at the top of the stack and pushes the + /// result on the stack. + /// + /// Stack transition: + /// + /// ```..., u64_value(1), u64_value(2) -> ..., u64_value``` + Mod, + /// Divide the 2 u64 at the top of the stack and pushes the result on the stack. + /// The operation aborts the transaction in case of "divide by 0". + /// + /// Stack transition: + /// + /// ```..., u64_value(1), u64_value(2) -> ..., u64_value``` + Div, + /// Bitwise OR the 2 u64 at the top of the stack and pushes the result on the stack. + /// + /// Stack transition: + /// + /// ```..., u64_value(1), u64_value(2) -> ..., u64_value``` + BitOr, + /// Bitwise AND the 2 u64 at the top of the stack and pushes the result on the stack. + /// + /// Stack transition: + /// + /// ```..., u64_value(1), u64_value(2) -> ..., u64_value``` + BitAnd, + /// Bitwise XOR the 2 u64 at the top of the stack and pushes the result on the stack. + /// + /// Stack transition: + /// + /// ```..., u64_value(1), u64_value(2) -> ..., u64_value``` + Xor, + /// Logical OR the 2 bool at the top of the stack and pushes the result on the stack. + /// + /// Stack transition: + /// + /// ```..., bool_value(1), bool_value(2) -> ..., bool_value``` + Or, + /// Logical AND the 2 bool at the top of the stack and pushes the result on the stack. + /// + /// Stack transition: + /// + /// ```..., bool_value(1), bool_value(2) -> ..., bool_value``` + And, + /// Logical NOT the bool at the top of the stack and pushes the result on the stack. + /// + /// Stack transition: + /// + /// ```..., bool_value -> ..., bool_value``` + Not, + /// Compare for equality the 2 value at the top of the stack and pushes the + /// result on the stack. + /// The values on the stack must have `Drop` as they will be consumed and destroyed. + /// + /// Stack transition: + /// + /// ```..., value(1), value(2) -> ..., bool_value``` + Eq, + /// Compare for inequality the 2 value at the top of the stack and pushes the + /// result on the stack. + /// The values on the stack must have `Drop` as they will be consumed and destroyed. + /// + /// Stack transition: + /// + /// ```..., value(1), value(2) -> ..., bool_value``` + Neq, + /// Perform a "less than" operation of the 2 u64 at the top of the stack and pushes the + /// result on the stack. + /// + /// Stack transition: + /// + /// ```..., u64_value(1), u64_value(2) -> ..., bool_value``` + Lt, + /// Perform a "greater than" operation of the 2 u64 at the top of the stack and pushes the + /// result on the stack. + /// + /// Stack transition: + /// + /// ```..., u64_value(1), u64_value(2) -> ..., bool_value``` + Gt, + /// Perform a "less than or equal" operation of the 2 u64 at the top of the stack and pushes + /// the result on the stack. + /// + /// Stack transition: + /// + /// ```..., u64_value(1), u64_value(2) -> ..., bool_value``` + Le, + /// Perform a "greater than or equal" than operation of the 2 u64 at the top of the stack + /// and pushes the result on the stack. + /// + /// Stack transition: + /// + /// ```..., u64_value(1), u64_value(2) -> ..., bool_value``` + Ge, + /// Abort execution with errorcode + /// + /// + /// Stack transition: + /// + /// ```..., errorcode -> ...``` + Abort, + /// No operation. + /// + /// Stack transition: none + Nop, + /// Shift the (second top value) left (top value) bits and pushes the result on the stack. + /// + /// Stack transition: + /// + /// ```..., u64_value(1), u64_value(2) -> ..., u64_value``` + Shl, + /// Shift the (second top value) right (top value) bits and pushes the result on the stack. + /// + /// Stack transition: + /// + /// ```..., u64_value(1), u64_value(2) -> ..., u64_value``` + Shr, + /// Create a vector by packing a statically known number of elements from the stack. Abort the + /// execution if there are not enough number of elements on the stack to pack from or they don't + /// have the same type identified by the SignatureIndex. + /// + /// Stack transition: + /// + /// ```..., e1, e2, ..., eN -> ..., vec[e1, e2, ..., eN]``` + VecPack(SignatureIndex, u64), + /// Return the length of the vector, + /// + /// Stack transition: + /// + /// ```..., vector_reference -> ..., u64_value``` + VecLen(SignatureIndex), + /// Acquire an immutable reference to the element at a given index of the vector. Abort the + /// execution if the index is out of bounds. + /// + /// Stack transition: + /// + /// ```..., vector_reference, u64_value -> .., element_reference``` + VecImmBorrow(SignatureIndex), + /// Acquire a mutable reference to the element at a given index of the vector. Abort the + /// execution if the index is out of bounds. + /// + /// Stack transition: + /// + /// ```..., vector_reference, u64_value -> .., element_reference``` + VecMutBorrow(SignatureIndex), + /// Add an element to the end of the vector. + /// + /// Stack transition: + /// + /// ```..., vector_reference, element -> ...``` + VecPushBack(SignatureIndex), + /// Pop an element from the end of vector. Aborts if the vector is empty. + /// + /// Stack transition: + /// + /// ```..., vector_reference -> ..., element``` + VecPopBack(SignatureIndex), + /// Destroy the vector and unpack a statically known number of elements onto the stack. Aborts + /// if the vector does not have a length N. + /// + /// Stack transition: + /// + /// ```..., vec[e1, e2, ..., eN] -> ..., e1, e2, ..., eN``` + VecUnpack(SignatureIndex, u64), + /// Swaps the elements at two indices in the vector. Abort the execution if any of the indice + /// is out of bounds. + /// + /// ```..., vector_reference, u64_value(1), u64_value(2) -> ...``` + VecSwap(SignatureIndex), + /// Push a U16 constant onto the stack. + /// + /// Stack transition: + /// + /// ```... -> ..., u16_value``` + LdU16(u16), + /// Push a U32 constant onto the stack. + /// + /// Stack transition: + /// + /// ```... -> ..., u32_value``` + LdU32(u32), + /// Push a U256 constant onto the stack. + /// + /// Stack transition: + /// + /// ```... -> ..., u256_value``` + LdU256(Box), + /// Convert the value at the top of the stack into u16. + /// + /// Stack transition: + /// + /// ```..., integer_value -> ..., u16_value``` + CastU16, + /// Convert the value at the top of the stack into u32. + /// + /// Stack transition: + /// + /// ```..., integer_value -> ..., u32_value``` + CastU32, + /// Convert the value at the top of the stack into u256. + /// + /// Stack transition: + /// + /// ```..., integer_value -> ..., u256_value``` + CastU256, + + // ******** DEPRECATED BYTECODES ******** + ExistsDeprecated(StructDefinitionIndex), + ExistsGenericDeprecated(StructDefInstantiationIndex), + MoveFromDeprecated(StructDefinitionIndex), + MoveFromGenericDeprecated(StructDefInstantiationIndex), + MoveToDeprecated(StructDefinitionIndex), + MoveToGenericDeprecated(StructDefInstantiationIndex), + MutBorrowGlobalDeprecated(StructDefinitionIndex), + MutBorrowGlobalGenericDeprecated(StructDefInstantiationIndex), + ImmBorrowGlobalDeprecated(StructDefinitionIndex), + ImmBorrowGlobalGenericDeprecated(StructDefInstantiationIndex), +} + +impl ::std::fmt::Debug for Bytecode { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + Bytecode::Pop => write!(f, "Pop"), + Bytecode::Ret => write!(f, "Ret"), + Bytecode::BrTrue(a) => write!(f, "BrTrue({})", a), + Bytecode::BrFalse(a) => write!(f, "BrFalse({})", a), + Bytecode::Branch(a) => write!(f, "Branch({})", a), + Bytecode::LdU8(a) => write!(f, "LdU8({})", a), + Bytecode::LdU16(a) => write!(f, "LdU16({})", a), + Bytecode::LdU32(a) => write!(f, "LdU32({})", a), + Bytecode::LdU64(a) => write!(f, "LdU64({})", a), + Bytecode::LdU128(a) => write!(f, "LdU128({})", a), + Bytecode::LdU256(a) => write!(f, "LdU256({})", a), + Bytecode::CastU8 => write!(f, "CastU8"), + Bytecode::CastU16 => write!(f, "CastU16"), + Bytecode::CastU32 => write!(f, "CastU32"), + Bytecode::CastU64 => write!(f, "CastU64"), + Bytecode::CastU128 => write!(f, "CastU128"), + Bytecode::CastU256 => write!(f, "CastU256"), + Bytecode::LdConst(a) => write!(f, "LdConst({})", a), + Bytecode::LdTrue => write!(f, "LdTrue"), + Bytecode::LdFalse => write!(f, "LdFalse"), + Bytecode::CopyLoc(a) => write!(f, "CopyLoc({})", a), + Bytecode::MoveLoc(a) => write!(f, "MoveLoc({})", a), + Bytecode::StLoc(a) => write!(f, "StLoc({})", a), + Bytecode::Call(a) => write!(f, "Call({})", a), + Bytecode::CallGeneric(a) => write!(f, "CallGeneric({})", a), + Bytecode::Pack(a) => write!(f, "Pack({})", a), + Bytecode::PackGeneric(a) => write!(f, "PackGeneric({})", a), + Bytecode::Unpack(a) => write!(f, "Unpack({})", a), + Bytecode::UnpackGeneric(a) => write!(f, "UnpackGeneric({})", a), + Bytecode::ReadRef => write!(f, "ReadRef"), + Bytecode::WriteRef => write!(f, "WriteRef"), + Bytecode::FreezeRef => write!(f, "FreezeRef"), + Bytecode::MutBorrowLoc(a) => write!(f, "MutBorrowLoc({})", a), + Bytecode::ImmBorrowLoc(a) => write!(f, "ImmBorrowLoc({})", a), + Bytecode::MutBorrowField(a) => write!(f, "MutBorrowField({:?})", a), + Bytecode::MutBorrowFieldGeneric(a) => write!(f, "MutBorrowFieldGeneric({:?})", a), + Bytecode::ImmBorrowField(a) => write!(f, "ImmBorrowField({:?})", a), + Bytecode::ImmBorrowFieldGeneric(a) => write!(f, "ImmBorrowFieldGeneric({:?})", a), + Bytecode::MutBorrowGlobalDeprecated(a) => write!(f, "MutBorrowGlobal({:?})", a), + Bytecode::MutBorrowGlobalGenericDeprecated(a) => { + write!(f, "MutBorrowGlobalGeneric({:?})", a) + } + Bytecode::ImmBorrowGlobalDeprecated(a) => write!(f, "ImmBorrowGlobal({:?})", a), + Bytecode::ImmBorrowGlobalGenericDeprecated(a) => { + write!(f, "ImmBorrowGlobalGeneric({:?})", a) + } + Bytecode::Add => write!(f, "Add"), + Bytecode::Sub => write!(f, "Sub"), + Bytecode::Mul => write!(f, "Mul"), + Bytecode::Mod => write!(f, "Mod"), + Bytecode::Div => write!(f, "Div"), + Bytecode::BitOr => write!(f, "BitOr"), + Bytecode::BitAnd => write!(f, "BitAnd"), + Bytecode::Xor => write!(f, "Xor"), + Bytecode::Shl => write!(f, "Shl"), + Bytecode::Shr => write!(f, "Shr"), + Bytecode::Or => write!(f, "Or"), + Bytecode::And => write!(f, "And"), + Bytecode::Not => write!(f, "Not"), + Bytecode::Eq => write!(f, "Eq"), + Bytecode::Neq => write!(f, "Neq"), + Bytecode::Lt => write!(f, "Lt"), + Bytecode::Gt => write!(f, "Gt"), + Bytecode::Le => write!(f, "Le"), + Bytecode::Ge => write!(f, "Ge"), + Bytecode::Abort => write!(f, "Abort"), + Bytecode::Nop => write!(f, "Nop"), + Bytecode::ExistsDeprecated(a) => write!(f, "Exists({:?})", a), + Bytecode::ExistsGenericDeprecated(a) => write!(f, "ExistsGeneric({:?})", a), + Bytecode::MoveFromDeprecated(a) => write!(f, "MoveFrom({:?})", a), + Bytecode::MoveFromGenericDeprecated(a) => write!(f, "MoveFromGeneric({:?})", a), + Bytecode::MoveToDeprecated(a) => write!(f, "MoveTo({:?})", a), + Bytecode::MoveToGenericDeprecated(a) => write!(f, "MoveToGeneric({:?})", a), + Bytecode::VecPack(a, n) => write!(f, "VecPack({}, {})", a, n), + Bytecode::VecLen(a) => write!(f, "VecLen({})", a), + Bytecode::VecImmBorrow(a) => write!(f, "VecImmBorrow({})", a), + Bytecode::VecMutBorrow(a) => write!(f, "VecMutBorrow({})", a), + Bytecode::VecPushBack(a) => write!(f, "VecPushBack({})", a), + Bytecode::VecPopBack(a) => write!(f, "VecPopBack({})", a), + Bytecode::VecUnpack(a, n) => write!(f, "VecUnpack({}, {})", a, n), + Bytecode::VecSwap(a) => write!(f, "VecSwap({})", a), + } + } +} + +impl Bytecode { + /// Return true if this bytecode instruction always branches + pub fn is_unconditional_branch(&self) -> bool { + matches!(self, Bytecode::Ret | Bytecode::Abort | Bytecode::Branch(_)) + } + + /// Return true if the branching behavior of this bytecode instruction depends on a runtime + /// value + pub fn is_conditional_branch(&self) -> bool { + matches!(self, Bytecode::BrFalse(_) | Bytecode::BrTrue(_)) + } + + /// Returns true if this bytecode instruction is either a conditional or an unconditional branch + pub fn is_branch(&self) -> bool { + self.is_conditional_branch() || self.is_unconditional_branch() + } + + /// Returns the offset that this bytecode instruction branches to, if any. + /// Note that return and abort are branch instructions, but have no offset. + pub fn offset(&self) -> Option<&CodeOffset> { + match self { + Bytecode::BrFalse(offset) | Bytecode::BrTrue(offset) | Bytecode::Branch(offset) => { + Some(offset) + } + _ => None, + } + } + + /// Return the successor offsets of this bytecode instruction. + pub fn get_successors(pc: CodeOffset, code: &[Bytecode]) -> Vec { + assert!( + // The program counter must remain within the bounds of the code + pc < u16::MAX && (pc as usize) < code.len(), + "Program counter out of bounds" + ); + + let bytecode = &code[pc as usize]; + let mut v = vec![]; + + if let Some(offset) = bytecode.offset() { + v.push(*offset); + } + + let next_pc = pc + 1; + if next_pc >= code.len() as CodeOffset { + return v; + } + + if !bytecode.is_unconditional_branch() && !v.contains(&next_pc) { + // avoid duplicates + v.push(pc + 1); + } + + // always give successors in ascending order + if v.len() > 1 && v[0] > v[1] { + v.swap(0, 1); + } + + v + } +} + +#[cfg(any(test, feature = "fuzzing"))] +impl Arbitrary for CompiledModule { + type Strategy = BoxedStrategy; + /// The size of the compiled module. + type Parameters = usize; + + fn arbitrary_with(size: Self::Parameters) -> Self::Strategy { + ( + ( + vec(any::(), 0..=size), + vec(any::(), 0..=size), + vec(any::(), 0..=size), + ), + any::(), + vec(any::(), 0..=size), + vec(any_with::(size), 0..=size), + ( + vec(any::(), 0..=size), + vec(any::(), 0..=size), + ), + ( + vec(any::(), 0..=size), + vec(any_with::(size), 0..=size), + ), + ) + .prop_map( + |( + (module_handles, struct_handles, function_handles), + self_module_handle_idx, + friend_decls, + signatures, + (identifiers, address_identifiers), + (struct_defs, function_defs), + )| { + // TODO actual constant generation + CompiledModule { + version: file_format_common::VERSION_MAX, + module_handles, + struct_handles, + function_handles, + self_module_handle_idx, + field_handles: vec![], + friend_decls, + struct_def_instantiations: vec![], + function_instantiations: vec![], + field_instantiations: vec![], + signatures, + identifiers, + address_identifiers, + constant_pool: vec![], + metadata: vec![], + struct_defs, + function_defs, + } + }, + ) + .boxed() + } +} + +/// A `CompiledModule` defines the structure of a module which is the unit of published code. +/// +/// A `CompiledModule` contains a definition of types (with their fields) and functions. +/// It is a unit of code that can be used by transactions or other modules. +/// +/// A module is published as a single entry and it is retrieved as a single blob. +#[derive(Clone, Debug, Default, Eq, PartialEq)] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "wasm", derive(Serialize, Deserialize))] +pub struct CompiledModule { + /// Version number found during deserialization + pub version: u32, + /// Handle to self. + pub self_module_handle_idx: ModuleHandleIndex, + /// Handles to external dependency modules and self. + pub module_handles: Vec, + /// Handles to external and internal types. + pub struct_handles: Vec, + /// Handles to external and internal functions. + pub function_handles: Vec, + /// Handles to fields. + pub field_handles: Vec, + /// Friend declarations, represented as a collection of handles to external friend modules. + pub friend_decls: Vec, + + /// Struct instantiations. + pub struct_def_instantiations: Vec, + /// Function instantiations. + pub function_instantiations: Vec, + /// Field instantiations. + pub field_instantiations: Vec, + + /// Locals signature pool. The signature for all locals of the functions defined in the module. + pub signatures: SignaturePool, + + /// All identifiers used in this module. + pub identifiers: IdentifierPool, + /// All address identifiers used in this module. + pub address_identifiers: AddressIdentifierPool, + /// Constant pool. The constant values used in the module. + pub constant_pool: ConstantPool, + + pub metadata: Vec, + + /// Types defined in this module. + pub struct_defs: Vec, + /// Function defined in this module. + pub function_defs: Vec, +} + +impl CompiledModule { + /// Returns the count of a specific `IndexKind` + pub fn kind_count(&self, kind: IndexKind) -> usize { + debug_assert!(!matches!( + kind, + IndexKind::LocalPool + | IndexKind::CodeDefinition + | IndexKind::FieldDefinition + | IndexKind::TypeParameter + | IndexKind::MemberCount + )); + match kind { + IndexKind::ModuleHandle => self.module_handles.len(), + IndexKind::StructHandle => self.struct_handles.len(), + IndexKind::FunctionHandle => self.function_handles.len(), + IndexKind::FieldHandle => self.field_handles.len(), + IndexKind::FriendDeclaration => self.friend_decls.len(), + IndexKind::StructDefInstantiation => self.struct_def_instantiations.len(), + IndexKind::FunctionInstantiation => self.function_instantiations.len(), + IndexKind::FieldInstantiation => self.field_instantiations.len(), + IndexKind::StructDefinition => self.struct_defs.len(), + IndexKind::FunctionDefinition => self.function_defs.len(), + IndexKind::Signature => self.signatures.len(), + IndexKind::Identifier => self.identifiers.len(), + IndexKind::AddressIdentifier => self.address_identifiers.len(), + IndexKind::ConstantPool => self.constant_pool.len(), + // XXX these two don't seem to belong here + other @ IndexKind::LocalPool + | other @ IndexKind::CodeDefinition + | other @ IndexKind::FieldDefinition + | other @ IndexKind::TypeParameter + | other @ IndexKind::MemberCount => unreachable!("invalid kind for count: {:?}", other), + } + } + + pub fn self_handle_idx(&self) -> ModuleHandleIndex { + self.self_module_handle_idx + } + + /// Returns the `ModuleHandle` for `self`. + pub fn self_handle(&self) -> &ModuleHandle { + let handle = self.module_handle_at(self.self_handle_idx()); + debug_assert!(handle.address.into_index() < self.address_identifiers.len()); // invariant + debug_assert!(handle.name.into_index() < self.identifiers.len()); // invariant + handle + } + + /// Returns the name of the module. + pub fn name(&self) -> &IdentStr { + self.identifier_at(self.self_handle().name) + } + + /// Returns the address of the module. + pub fn address(&self) -> &AccountAddress { + self.address_identifier_at(self.self_handle().address) + } + + pub fn struct_name(&self, idx: StructDefinitionIndex) -> &IdentStr { + let struct_def = self.struct_def_at(idx); + let handle = self.struct_handle_at(struct_def.struct_handle); + self.identifier_at(handle.name) + } + + pub fn module_handle_at(&self, idx: ModuleHandleIndex) -> &ModuleHandle { + let handle = &self.module_handles[idx.into_index()]; + debug_assert!(handle.address.into_index() < self.address_identifiers.len()); // invariant + debug_assert!(handle.name.into_index() < self.identifiers.len()); // invariant + handle + } + + pub fn struct_handle_at(&self, idx: StructHandleIndex) -> &StructHandle { + let handle = &self.struct_handles[idx.into_index()]; + debug_assert!(handle.module.into_index() < self.module_handles.len()); // invariant + handle + } + + pub fn function_handle_at(&self, idx: FunctionHandleIndex) -> &FunctionHandle { + let handle = &self.function_handles[idx.into_index()]; + debug_assert!(handle.parameters.into_index() < self.signatures.len()); // invariant + debug_assert!(handle.return_.into_index() < self.signatures.len()); // invariant + handle + } + + pub fn field_handle_at(&self, idx: FieldHandleIndex) -> &FieldHandle { + let handle = &self.field_handles[idx.into_index()]; + debug_assert!(handle.owner.into_index() < self.struct_defs.len()); // invariant + handle + } + + pub fn struct_instantiation_at( + &self, + idx: StructDefInstantiationIndex, + ) -> &StructDefInstantiation { + &self.struct_def_instantiations[idx.into_index()] + } + + pub fn function_instantiation_at( + &self, + idx: FunctionInstantiationIndex, + ) -> &FunctionInstantiation { + &self.function_instantiations[idx.into_index()] + } + + pub fn field_instantiation_at(&self, idx: FieldInstantiationIndex) -> &FieldInstantiation { + &self.field_instantiations[idx.into_index()] + } + + pub fn signature_at(&self, idx: SignatureIndex) -> &Signature { + &self.signatures[idx.into_index()] + } + + pub fn identifier_at(&self, idx: IdentifierIndex) -> &IdentStr { + &self.identifiers[idx.into_index()] + } + + pub fn address_identifier_at(&self, idx: AddressIdentifierIndex) -> &AccountAddress { + &self.address_identifiers[idx.into_index()] + } + + pub fn constant_at(&self, idx: ConstantPoolIndex) -> &Constant { + &self.constant_pool[idx.into_index()] + } + + pub fn struct_def_at(&self, idx: StructDefinitionIndex) -> &StructDefinition { + &self.struct_defs[idx.into_index()] + } + + pub fn function_def_at(&self, idx: FunctionDefinitionIndex) -> &FunctionDefinition { + let result = &self.function_defs[idx.into_index()]; + debug_assert!(result.function.into_index() < self.function_handles().len()); // invariant + debug_assert!(match &result.code { + Some(code) => code.locals.into_index() < self.signatures().len(), + None => true, + }); // invariant + result + } + + pub fn module_handles(&self) -> &[ModuleHandle] { + &self.module_handles + } + + pub fn struct_handles(&self) -> &[StructHandle] { + &self.struct_handles + } + + pub fn function_handles(&self) -> &[FunctionHandle] { + &self.function_handles + } + + pub fn field_handles(&self) -> &[FieldHandle] { + &self.field_handles + } + + pub fn struct_instantiations(&self) -> &[StructDefInstantiation] { + &self.struct_def_instantiations + } + + pub fn function_instantiations(&self) -> &[FunctionInstantiation] { + &self.function_instantiations + } + + pub fn field_instantiations(&self) -> &[FieldInstantiation] { + &self.field_instantiations + } + + pub fn signatures(&self) -> &[Signature] { + &self.signatures + } + + pub fn constant_pool(&self) -> &[Constant] { + &self.constant_pool + } + + pub fn identifiers(&self) -> &[Identifier] { + &self.identifiers + } + + pub fn address_identifiers(&self) -> &[AccountAddress] { + &self.address_identifiers + } + + pub fn struct_defs(&self) -> &[StructDefinition] { + &self.struct_defs + } + + pub fn function_defs(&self) -> &[FunctionDefinition] { + &self.function_defs + } + + pub fn friend_decls(&self) -> &[ModuleHandle] { + &self.friend_decls + } + + pub fn version(&self) -> u32 { + self.version + } + + pub fn immediate_dependencies(&self) -> Vec { + let self_handle = self.self_handle(); + self.module_handles() + .iter() + .filter(|&handle| handle != self_handle) + .map(|handle| self.module_id_for_handle(handle)) + .collect() + } + + pub fn immediate_friends(&self) -> Vec { + self.friend_decls() + .iter() + .map(|handle| self.module_id_for_handle(handle)) + .collect() + } + + pub fn find_struct_def(&self, idx: StructHandleIndex) -> Option<&StructDefinition> { + self.struct_defs().iter().find(|d| d.struct_handle == idx) + } + + pub fn find_struct_def_by_name(&self, name: &IdentStr) -> Option<&StructDefinition> { + self.struct_defs().iter().find(|def| { + let handle = self.struct_handle_at(def.struct_handle); + name == self.identifier_at(handle.name) + }) + } + + // Return the `AbilitySet` of a `SignatureToken` given a context. + // A `TypeParameter` has the abilities of its `constraints`. + // `StructInstantiation` abilities are predicated on the particular instantiation + pub fn abilities( + &self, + ty: &SignatureToken, + constraints: &[AbilitySet], + ) -> PartialVMResult { + use SignatureToken::*; + + match ty { + Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address => Ok(AbilitySet::PRIMITIVES), + + Reference(_) | MutableReference(_) => Ok(AbilitySet::REFERENCES), + Signer => Ok(AbilitySet::SIGNER), + TypeParameter(idx) => Ok(constraints[*idx as usize]), + Vector(ty) => AbilitySet::polymorphic_abilities( + AbilitySet::VECTOR, + vec![false], + vec![self.abilities(ty, constraints)?], + ), + Struct(idx) => { + let sh = self.struct_handle_at(*idx); + Ok(sh.abilities) + } + StructInstantiation(struct_inst) => { + let (idx, type_args) = &**struct_inst; + let sh = self.struct_handle_at(*idx); + let declared_abilities = sh.abilities; + let type_arguments = type_args + .iter() + .map(|arg| self.abilities(arg, constraints)) + .collect::>>()?; + AbilitySet::polymorphic_abilities( + declared_abilities, + sh.type_parameters.iter().map(|param| param.is_phantom), + type_arguments, + ) + } + } + } + + /// Returns the code key of `module_handle` + pub fn module_id_for_handle(&self, module_handle: &ModuleHandle) -> ModuleId { + ModuleId::new( + *self.address_identifier_at(module_handle.address), + self.identifier_at(module_handle.name).to_owned(), + ) + } + + /// Returns the code key of `self` + pub fn self_id(&self) -> ModuleId { + self.module_id_for_handle(self.self_handle()) + } +} + +/// Return the simplest module that will pass the bounds checker +pub fn empty_module() -> CompiledModule { + CompiledModule { + version: file_format_common::VERSION_MAX, + module_handles: vec![ModuleHandle { + address: AddressIdentifierIndex(0), + name: IdentifierIndex(0), + }], + self_module_handle_idx: ModuleHandleIndex(0), + identifiers: vec![self_module_name().to_owned()], + address_identifiers: vec![AccountAddress::ZERO], + constant_pool: vec![], + metadata: vec![], + function_defs: vec![], + struct_defs: vec![], + struct_handles: vec![], + function_handles: vec![], + field_handles: vec![], + friend_decls: vec![], + struct_def_instantiations: vec![], + function_instantiations: vec![], + field_instantiations: vec![], + signatures: vec![Signature(vec![])], + } +} + +/// Create the following module which is convenient in tests: +/// // module { +/// // struct Bar { x: u64 } +/// // +/// // foo() { +/// // } +/// // } +pub fn basic_test_module() -> CompiledModule { + let mut m = empty_module(); + + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(m.identifiers.len() as u16), + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.identifiers + .push(Identifier::new("foo".to_string()).unwrap()); + + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(0), + visibility: Visibility::Private, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::Ret], + }), + }); + + m.struct_handles.push(StructHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(m.identifiers.len() as u16), + abilities: AbilitySet::EMPTY, + type_parameters: vec![], + }); + m.identifiers + .push(Identifier::new("Bar".to_string()).unwrap()); + + m.struct_defs.push(StructDefinition { + struct_handle: StructHandleIndex(0), + field_information: StructFieldInformation::Declared(vec![FieldDefinition { + name: IdentifierIndex(m.identifiers.len() as u16), + signature: TypeSignature(SignatureToken::U64), + }]), + }); + m.identifiers + .push(Identifier::new("x".to_string()).unwrap()); + + m +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/file_format_common.rs b/CoqOfRust/move_sui/translations/move_binary_format/file_format_common.rs new file mode 100644 index 000000000..d795db4ce --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/file_format_common.rs @@ -0,0 +1,504 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! Constants for the binary format. +//! +//! Definition for the constants of the binary format, used by the serializer and the deserializer. +//! This module also offers helpers for the serialization and deserialization of certain +//! integer indexes. +//! +//! We use LEB128 for integer compression. LEB128 is a representation from the DWARF3 spec, +//! http://dwarfstd.org/Dwarf3Std.php or https://en.wikipedia.org/wiki/LEB128. +//! It's used to compress mostly indexes into the main binary tables. +use crate::file_format::Bytecode; +use anyhow::{bail, Result}; +use std::{ + io::{Cursor, Read}, + mem::size_of, +}; + +/// Constant values for the binary format header. +/// +/// The binary header is magic + version info + table count. +pub enum BinaryConstants {} +impl BinaryConstants { + /// The blob that must start a binary. + pub const MOVE_MAGIC_SIZE: usize = 4; + pub const MOVE_MAGIC: [u8; BinaryConstants::MOVE_MAGIC_SIZE] = [0xA1, 0x1C, 0xEB, 0x0B]; + /// The `DIEM_MAGIC` size, 4 byte for major version and 1 byte for table count. + pub const HEADER_SIZE: usize = BinaryConstants::MOVE_MAGIC_SIZE + 5; + /// A (Table Type, Start Offset, Byte Count) size, which is 1 byte for the type and + /// 4 bytes for the offset/count. + pub const TABLE_HEADER_SIZE: u8 = size_of::() as u8 * 2 + 1; +} + +pub const TABLE_COUNT_MAX: u64 = 255; + +pub const TABLE_OFFSET_MAX: u64 = 0xffff_ffff; +pub const TABLE_SIZE_MAX: u64 = 0xffff_ffff; +pub const TABLE_CONTENT_SIZE_MAX: u64 = 0xffff_ffff; + +pub const TABLE_INDEX_MAX: u64 = 65535; +pub const SIGNATURE_INDEX_MAX: u64 = TABLE_INDEX_MAX; +pub const ADDRESS_INDEX_MAX: u64 = TABLE_INDEX_MAX; +pub const IDENTIFIER_INDEX_MAX: u64 = TABLE_INDEX_MAX; +pub const MODULE_HANDLE_INDEX_MAX: u64 = TABLE_INDEX_MAX; +pub const STRUCT_HANDLE_INDEX_MAX: u64 = TABLE_INDEX_MAX; +pub const STRUCT_DEF_INDEX_MAX: u64 = TABLE_INDEX_MAX; +pub const FUNCTION_HANDLE_INDEX_MAX: u64 = TABLE_INDEX_MAX; +pub const FUNCTION_INST_INDEX_MAX: u64 = TABLE_INDEX_MAX; +pub const FIELD_HANDLE_INDEX_MAX: u64 = TABLE_INDEX_MAX; +pub const FIELD_INST_INDEX_MAX: u64 = TABLE_INDEX_MAX; +pub const STRUCT_DEF_INST_INDEX_MAX: u64 = TABLE_INDEX_MAX; +pub const CONSTANT_INDEX_MAX: u64 = TABLE_INDEX_MAX; + +pub const BYTECODE_COUNT_MAX: u64 = 65535; +pub const BYTECODE_INDEX_MAX: u64 = 65535; + +pub const LOCAL_INDEX_MAX: u64 = 255; + +pub const IDENTIFIER_SIZE_MAX: u64 = 65535; + +pub const CONSTANT_SIZE_MAX: u64 = 65535; + +pub const METADATA_KEY_SIZE_MAX: u64 = 1023; +pub const METADATA_VALUE_SIZE_MAX: u64 = 65535; + +pub const SIGNATURE_SIZE_MAX: u64 = 255; + +pub const ACQUIRES_COUNT_MAX: u64 = 255; + +pub const FIELD_COUNT_MAX: u64 = 255; +pub const FIELD_OFFSET_MAX: u64 = 255; + +pub const TYPE_PARAMETER_COUNT_MAX: u64 = 255; +pub const TYPE_PARAMETER_INDEX_MAX: u64 = 65536; + +pub const SIGNATURE_TOKEN_DEPTH_MAX: usize = 256; + +/// Constants for table types in the binary. +/// +/// The binary contains a subset of those tables. A table specification is a tuple (table type, +/// start offset, byte count) for a given table. +#[rustfmt::skip] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub enum TableType { + MODULE_HANDLES = 0x1, + STRUCT_HANDLES = 0x2, + FUNCTION_HANDLES = 0x3, + FUNCTION_INST = 0x4, + SIGNATURES = 0x5, + CONSTANT_POOL = 0x6, + IDENTIFIERS = 0x7, + ADDRESS_IDENTIFIERS = 0x8, + STRUCT_DEFS = 0xA, + STRUCT_DEF_INST = 0xB, + FUNCTION_DEFS = 0xC, + FIELD_HANDLE = 0xD, + FIELD_INST = 0xE, + FRIEND_DECLS = 0xF, + METADATA = 0x10, +} + +/// Constants for signature blob values. +#[rustfmt::skip] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[derive(Clone, Copy, Debug)] +pub enum SerializedType { + BOOL = 0x1, + U8 = 0x2, + U64 = 0x3, + U128 = 0x4, + ADDRESS = 0x5, + REFERENCE = 0x6, + MUTABLE_REFERENCE = 0x7, + STRUCT = 0x8, + TYPE_PARAMETER = 0x9, + VECTOR = 0xA, + STRUCT_INST = 0xB, + SIGNER = 0xC, + U16 = 0xD, + U32 = 0xE, + U256 = 0xF, +} + +#[rustfmt::skip] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[derive(Clone, Copy, Debug)] +pub enum SerializedNativeStructFlag { + NATIVE = 0x1, + DECLARED = 0x2, +} + +/// List of opcodes constants. +#[rustfmt::skip] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[derive(Clone, Copy, Debug)] +pub enum Opcodes { + POP = 0x01, + RET = 0x02, + BR_TRUE = 0x03, + BR_FALSE = 0x04, + BRANCH = 0x05, + LD_U64 = 0x06, + LD_CONST = 0x07, + LD_TRUE = 0x08, + LD_FALSE = 0x09, + COPY_LOC = 0x0A, + MOVE_LOC = 0x0B, + ST_LOC = 0x0C, + MUT_BORROW_LOC = 0x0D, + IMM_BORROW_LOC = 0x0E, + MUT_BORROW_FIELD = 0x0F, + IMM_BORROW_FIELD = 0x10, + CALL = 0x11, + PACK = 0x12, + UNPACK = 0x13, + READ_REF = 0x14, + WRITE_REF = 0x15, + ADD = 0x16, + SUB = 0x17, + MUL = 0x18, + MOD = 0x19, + DIV = 0x1A, + BIT_OR = 0x1B, + BIT_AND = 0x1C, + XOR = 0x1D, + OR = 0x1E, + AND = 0x1F, + NOT = 0x20, + EQ = 0x21, + NEQ = 0x22, + LT = 0x23, + GT = 0x24, + LE = 0x25, + GE = 0x26, + ABORT = 0x27, + NOP = 0x28, + // gap for deprecated bytecodes, see bottom of enum + FREEZE_REF = 0x2E, + SHL = 0x2F, + SHR = 0x30, + LD_U8 = 0x31, + LD_U128 = 0x32, + CAST_U8 = 0x33, + CAST_U64 = 0x34, + CAST_U128 = 0x35, + MUT_BORROW_FIELD_GENERIC = 0x36, + IMM_BORROW_FIELD_GENERIC = 0x37, + CALL_GENERIC = 0x38, + PACK_GENERIC = 0x39, + UNPACK_GENERIC = 0x3A, + VEC_PACK = 0x40, + VEC_LEN = 0x41, + VEC_IMM_BORROW = 0x42, + VEC_MUT_BORROW = 0x43, + VEC_PUSH_BACK = 0x44, + VEC_POP_BACK = 0x45, + VEC_UNPACK = 0x46, + VEC_SWAP = 0x47, + LD_U16 = 0x48, + LD_U32 = 0x49, + LD_U256 = 0x4A, + CAST_U16 = 0x4B, + CAST_U32 = 0x4C, + CAST_U256 = 0x4D, + + // ******** DEPRECATED BYTECODES ******** + // global storage opcodes are unused and deprecated + EXISTS_DEPRECATED = 0x29, + MUT_BORROW_GLOBAL_DEPRECATED = 0x2A, + IMM_BORROW_GLOBAL_DEPRECATED = 0x2B, + MOVE_FROM_DEPRECATED = 0x2C, + MOVE_TO_DEPRECATED = 0x2D, + EXISTS_GENERIC_DEPRECATED = 0x3B, + MUT_BORROW_GLOBAL_GENERIC_DEPRECATED = 0x3C, + IMM_BORROW_GLOBAL_GENERIC_DEPRECATED = 0x3D, + MOVE_FROM_GENERIC_DEPRECATED = 0x3E, + MOVE_TO_GENERIC_DEPRECATED = 0x3F, +} + +/// Upper limit on the binary size +pub const BINARY_SIZE_LIMIT: usize = usize::max_value(); + +/// A wrapper for the binary vector +#[derive(Default, Debug)] +pub(crate) struct BinaryData { + _binary: Vec, +} + +/// The wrapper mirrors Vector operations but provides additional checks against overflow +impl BinaryData { + pub fn new() -> Self { + BinaryData { + _binary: Vec::new(), + } + } + + pub fn as_inner(&self) -> &[u8] { + &self._binary + } + + pub fn into_inner(self) -> Vec { + self._binary + } + + pub fn push(&mut self, item: u8) -> Result<()> { + if self.len().checked_add(1).is_some() { + self._binary.push(item); + } else { + bail!( + "binary size ({}) + 1 is greater than limit ({})", + self.len(), + BINARY_SIZE_LIMIT, + ); + } + Ok(()) + } + + pub fn extend(&mut self, vec: &[u8]) -> Result<()> { + let vec_len: usize = vec.len(); + if self.len().checked_add(vec_len).is_some() { + self._binary.extend(vec); + } else { + bail!( + "binary size ({}) + {} is greater than limit ({})", + self.len(), + vec.len(), + BINARY_SIZE_LIMIT, + ); + } + Ok(()) + } + + pub fn len(&self) -> usize { + self._binary.len() + } + + #[allow(dead_code)] + pub fn is_empty(&self) -> bool { + self._binary.is_empty() + } + + #[allow(dead_code)] + pub fn clear(&mut self) { + self._binary.clear(); + } +} + +impl From> for BinaryData { + fn from(vec: Vec) -> Self { + BinaryData { _binary: vec } + } +} + +pub(crate) fn write_u64_as_uleb128(binary: &mut BinaryData, mut val: u64) -> Result<()> { + loop { + let cur = val & 0x7f; + if cur != val { + binary.push((cur | 0x80) as u8)?; + val >>= 7; + } else { + binary.push(cur as u8)?; + break; + } + } + Ok(()) +} + +/// Write a `u16` in Little Endian format. +#[allow(dead_code)] +pub(crate) fn write_u16(binary: &mut BinaryData, value: u16) -> Result<()> { + binary.extend(&value.to_le_bytes()) +} + +/// Write a `u32` in Little Endian format. +pub(crate) fn write_u32(binary: &mut BinaryData, value: u32) -> Result<()> { + binary.extend(&value.to_le_bytes()) +} + +/// Write a `u64` in Little Endian format. +pub(crate) fn write_u64(binary: &mut BinaryData, value: u64) -> Result<()> { + binary.extend(&value.to_le_bytes()) +} + +/// Write a `u128` in Little Endian format. +pub(crate) fn write_u128(binary: &mut BinaryData, value: u128) -> Result<()> { + binary.extend(&value.to_le_bytes()) +} + +/// Write a `u256` in Little Endian format. +pub(crate) fn write_u256( + binary: &mut BinaryData, + value: move_core_types::u256::U256, +) -> Result<()> { + binary.extend(&value.to_le_bytes()) +} + +pub fn read_u8(cursor: &mut Cursor<&[u8]>) -> Result { + let mut buf = [0; 1]; + cursor.read_exact(&mut buf)?; + Ok(buf[0]) +} + +pub fn read_u32(cursor: &mut Cursor<&[u8]>) -> Result { + let mut buf = [0; 4]; + cursor.read_exact(&mut buf)?; + Ok(u32::from_le_bytes(buf)) +} + +pub fn read_uleb128_as_u64(cursor: &mut Cursor<&[u8]>) -> Result { + let mut value: u64 = 0; + let mut shift = 0; + while let Ok(byte) = read_u8(cursor) { + let cur = (byte & 0x7f) as u64; + if (cur << shift) >> shift != cur { + bail!("invalid ULEB128 repr for usize"); + } + value |= cur << shift; + + if (byte & 0x80) == 0 { + if shift > 0 && cur == 0 { + bail!("invalid ULEB128 repr for usize"); + } + return Ok(value); + } + + shift += 7; + if shift > u64::BITS { + break; + } + } + bail!("invalid ULEB128 repr for usize"); +} + +// +// Bytecode evolution +// + +/// Version 1: the initial version +pub const VERSION_1: u32 = 1; + +/// Version 2: changes compared with version 1 +/// + function visibility stored in separate byte before the flags byte +/// + the flags byte now contains only the is_native information (at bit 0x2) +/// + new visibility modifiers for "friend" and "script" functions +/// + friend list for modules +pub const VERSION_2: u32 = 2; + +/// Version 3: changes compared with version 2 +/// + phantom type parameters +pub const VERSION_3: u32 = 3; + +/// Version 4: changes compared with version 3 +/// + bytecode for vector operations +pub const VERSION_4: u32 = 4; + +/// Version 5: changes compared with version 4 +/// +/- script and public(script) verification is now adapter specific +/// + metadata +pub const VERSION_5: u32 = 5; + +/// Version 6: changes compared with version 5 +/// + u16, u32, u256 integers and corresponding Ld, Cast bytecodes +pub const VERSION_6: u32 = 6; + +// Mark which version is the latest version +pub const VERSION_MAX: u32 = VERSION_6; + +// Mark which oldest version is supported. +// TODO(#145): finish v4 compatibility; as of now, only metadata is implemented +pub const VERSION_MIN: u32 = VERSION_5; + +/// The encoding of the instruction is the serialized form of it, but disregarding the +/// serialization of the instruction's argument(s). +pub fn instruction_key(instruction: &Bytecode) -> u8 { + use Bytecode::*; + let opcode = match instruction { + Pop => Opcodes::POP, + Ret => Opcodes::RET, + BrTrue(_) => Opcodes::BR_TRUE, + BrFalse(_) => Opcodes::BR_FALSE, + Branch(_) => Opcodes::BRANCH, + LdU8(_) => Opcodes::LD_U8, + LdU64(_) => Opcodes::LD_U64, + LdU128(_) => Opcodes::LD_U128, + CastU8 => Opcodes::CAST_U8, + CastU64 => Opcodes::CAST_U64, + CastU128 => Opcodes::CAST_U128, + LdConst(_) => Opcodes::LD_CONST, + LdTrue => Opcodes::LD_TRUE, + LdFalse => Opcodes::LD_FALSE, + CopyLoc(_) => Opcodes::COPY_LOC, + MoveLoc(_) => Opcodes::MOVE_LOC, + StLoc(_) => Opcodes::ST_LOC, + Call(_) => Opcodes::CALL, + CallGeneric(_) => Opcodes::CALL_GENERIC, + Pack(_) => Opcodes::PACK, + PackGeneric(_) => Opcodes::PACK_GENERIC, + Unpack(_) => Opcodes::UNPACK, + UnpackGeneric(_) => Opcodes::UNPACK_GENERIC, + ReadRef => Opcodes::READ_REF, + WriteRef => Opcodes::WRITE_REF, + FreezeRef => Opcodes::FREEZE_REF, + MutBorrowLoc(_) => Opcodes::MUT_BORROW_LOC, + ImmBorrowLoc(_) => Opcodes::IMM_BORROW_LOC, + MutBorrowField(_) => Opcodes::MUT_BORROW_FIELD, + MutBorrowFieldGeneric(_) => Opcodes::MUT_BORROW_FIELD_GENERIC, + ImmBorrowField(_) => Opcodes::IMM_BORROW_FIELD, + ImmBorrowFieldGeneric(_) => Opcodes::IMM_BORROW_FIELD_GENERIC, + Add => Opcodes::ADD, + Sub => Opcodes::SUB, + Mul => Opcodes::MUL, + Mod => Opcodes::MOD, + Div => Opcodes::DIV, + BitOr => Opcodes::BIT_OR, + BitAnd => Opcodes::BIT_AND, + Xor => Opcodes::XOR, + Shl => Opcodes::SHL, + Shr => Opcodes::SHR, + Or => Opcodes::OR, + And => Opcodes::AND, + Not => Opcodes::NOT, + Eq => Opcodes::EQ, + Neq => Opcodes::NEQ, + Lt => Opcodes::LT, + Gt => Opcodes::GT, + Le => Opcodes::LE, + Ge => Opcodes::GE, + Abort => Opcodes::ABORT, + Nop => Opcodes::NOP, + VecPack(..) => Opcodes::VEC_PACK, + VecLen(_) => Opcodes::VEC_LEN, + VecImmBorrow(_) => Opcodes::VEC_IMM_BORROW, + VecMutBorrow(_) => Opcodes::VEC_MUT_BORROW, + VecPushBack(_) => Opcodes::VEC_PUSH_BACK, + VecPopBack(_) => Opcodes::VEC_POP_BACK, + VecUnpack(..) => Opcodes::VEC_UNPACK, + VecSwap(_) => Opcodes::VEC_SWAP, + LdU16(_) => Opcodes::LD_U16, + LdU32(_) => Opcodes::LD_U32, + LdU256(_) => Opcodes::LD_U256, + CastU16 => Opcodes::CAST_U16, + CastU32 => Opcodes::CAST_U32, + CastU256 => Opcodes::CAST_U256, + // ******** DEPRECATED BYTECODES ******** + ExistsDeprecated(_) => Opcodes::EXISTS_DEPRECATED, + ExistsGenericDeprecated(_) => Opcodes::EXISTS_GENERIC_DEPRECATED, + MoveFromDeprecated(_) => Opcodes::MOVE_FROM_DEPRECATED, + MoveFromGenericDeprecated(_) => Opcodes::MOVE_FROM_GENERIC_DEPRECATED, + MoveToDeprecated(_) => Opcodes::MOVE_TO_DEPRECATED, + MoveToGenericDeprecated(_) => Opcodes::MOVE_TO_GENERIC_DEPRECATED, + MutBorrowGlobalDeprecated(_) => Opcodes::MUT_BORROW_GLOBAL_DEPRECATED, + MutBorrowGlobalGenericDeprecated(_) => Opcodes::MUT_BORROW_GLOBAL_GENERIC_DEPRECATED, + ImmBorrowGlobalDeprecated(_) => Opcodes::IMM_BORROW_GLOBAL_DEPRECATED, + ImmBorrowGlobalGenericDeprecated(_) => Opcodes::IMM_BORROW_GLOBAL_GENERIC_DEPRECATED, + }; + opcode as u8 +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/internals.rs b/CoqOfRust/move_sui/translations/move_binary_format/internals.rs new file mode 100644 index 000000000..b9d877c6f --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/internals.rs @@ -0,0 +1,15 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! Types meant for use by other parts of this crate, and by other crates that are designed to +//! work with the internals of these data structures. + +use crate::IndexKind; + +/// Represents a module index. +pub trait ModuleIndex { + const KIND: IndexKind; + + fn into_index(self) -> usize; +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/lib.rs b/CoqOfRust/move_sui/translations/move_binary_format/lib.rs new file mode 100644 index 000000000..b402ea4c9 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/lib.rs @@ -0,0 +1,192 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +#![forbid(unsafe_code)] + +use std::fmt; + +pub mod binary_config; +pub mod check_bounds; +pub mod compatibility; +#[macro_use] +pub mod errors; +pub mod constant; +pub mod control_flow_graph; +pub mod deserializer; +pub mod file_format; +pub mod file_format_common; +pub mod internals; +pub mod normalized; +#[cfg(any(test, feature = "fuzzing"))] +pub mod proptest_types; +pub mod serializer; + +#[cfg(test)] +mod unit_tests; + +pub use file_format::CompiledModule; + +/// Represents a kind of index -- useful for error messages. +#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub enum IndexKind { + ModuleHandle, + StructHandle, + FunctionHandle, + FieldHandle, + FriendDeclaration, + FunctionInstantiation, + FieldInstantiation, + StructDefinition, + StructDefInstantiation, + FunctionDefinition, + FieldDefinition, + Signature, + Identifier, + AddressIdentifier, + ConstantPool, + LocalPool, + CodeDefinition, + TypeParameter, + MemberCount, +} + +impl IndexKind { + pub fn variants() -> &'static [IndexKind] { + use IndexKind::*; + + // XXX ensure this list stays up to date! + &[ + ModuleHandle, + StructHandle, + FunctionHandle, + FieldHandle, + FriendDeclaration, + StructDefInstantiation, + FunctionInstantiation, + FieldInstantiation, + StructDefinition, + FunctionDefinition, + FieldDefinition, + Signature, + Identifier, + ConstantPool, + LocalPool, + CodeDefinition, + TypeParameter, + MemberCount, + ] + } +} + +impl fmt::Display for IndexKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use IndexKind::*; + + let desc = match self { + ModuleHandle => "module handle", + StructHandle => "struct handle", + FunctionHandle => "function handle", + FieldHandle => "field handle", + FriendDeclaration => "friend declaration", + StructDefInstantiation => "struct instantiation", + FunctionInstantiation => "function instantiation", + FieldInstantiation => "field instantiation", + StructDefinition => "struct definition", + FunctionDefinition => "function definition", + FieldDefinition => "field definition", + Signature => "signature", + Identifier => "identifier", + AddressIdentifier => "address identifier", + ConstantPool => "constant pool", + LocalPool => "local pool", + CodeDefinition => "code definition pool", + TypeParameter => "type parameter", + MemberCount => "field offset", + }; + + f.write_str(desc) + } +} + +// TODO: is this outdated? +/// Represents the kind of a signature token. +#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub enum SignatureTokenKind { + /// Any sort of owned value that isn't an array (Integer, Bool, Struct etc). + Value, + /// A reference. + Reference, + /// A mutable reference. + MutableReference, +} + +impl fmt::Display for SignatureTokenKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use SignatureTokenKind::*; + + let desc = match self { + Value => "value", + Reference => "reference", + MutableReference => "mutable reference", + }; + + f.write_str(desc) + } +} + +/// A macro which should be preferred in critical runtime paths for unwrapping an option +/// if a `PartialVMError` is expected. In debug mode, this will panic. Otherwise +/// we return an Err. +#[macro_export] +macro_rules! safe_unwrap { + ($e:expr) => {{ + match $e { + Some(x) => x, + None => { + let err = PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) + .with_message(format!("{}:{} (none)", file!(), line!())); + if cfg!(debug_assertions) { + panic!("{:?}", err); + } else { + return Err(err); + } + } + } + }}; +} + +/// Similar as above but for Result +#[macro_export] +macro_rules! safe_unwrap_err { + ($e:expr) => {{ + match $e { + Ok(x) => x, + Err(e) => { + let err = PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) + .with_message(format!("{}:{} {:#}", file!(), line!(), e)); + if cfg!(debug_assertions) { + panic!("{:?}", err); + } else { + return Err(err); + } + } + } + }}; +} + +/// Similar as above, but asserts a boolean expression to be true. +#[macro_export] +macro_rules! safe_assert { + ($e:expr) => {{ + if !$e { + let err = PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) + .with_message(format!("{}:{} (assert)", file!(), line!())); + if cfg!(debug_assertions) { + panic!("{:?}", err) + } else { + return Err(err); + } + } + }}; +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/normalized.rs b/CoqOfRust/move_sui/translations/move_binary_format/normalized.rs new file mode 100644 index 000000000..380fefea1 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/normalized.rs @@ -0,0 +1,742 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::file_format::{ + AbilitySet, Bytecode as FBytecode, CodeOffset, CompiledModule, FieldDefinition, FieldHandle, + FieldHandleIndex, FieldInstantiation, FieldInstantiationIndex, FunctionDefinition, + FunctionHandle, FunctionHandleIndex, FunctionInstantiation, LocalIndex, SignatureIndex, + SignatureToken, StructDefInstantiation, StructDefInstantiationIndex, StructDefinition, + StructDefinitionIndex, StructFieldInformation, StructTypeParameter, TypeParameterIndex, + Visibility, +}; +use move_core_types::{ + account_address::AccountAddress, + identifier::{IdentStr, Identifier}, + language_storage::{ModuleId, StructTag, TypeTag}, +}; +use move_proc_macros::test_variant_order; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; + +/// Defines normalized representations of Move types, fields, kinds, structs, functions, and +/// modules. These representations are useful in situations that require require comparing +/// functions, resources, and types across modules. This arises in linking, compatibility checks +/// (e.g., "is it safe to deploy this new module without updating its dependents and/or restarting +/// genesis?"), defining schemas for resources stored on-chain, and (possibly in the future) +/// allowing module updates transactions. + +/// A normalized version of `SignatureToken`, a type expression appearing in struct or function +/// declarations. Unlike `SignatureToken`s, `normalized::Type`s from different modules can safely be +/// compared. +#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)] +#[test_variant_order(src/unit_tests/staged_enum_variant_order/type.yaml)] +pub enum Type { + #[serde(rename = "bool")] + Bool, + #[serde(rename = "u8")] + U8, + #[serde(rename = "u64")] + U64, + #[serde(rename = "u128")] + U128, + #[serde(rename = "address")] + Address, + #[serde(rename = "signer")] + Signer, + Struct { + address: AccountAddress, + module: Identifier, + name: Identifier, + type_arguments: Vec, + }, + #[serde(rename = "vector")] + Vector(Box), + TypeParameter(TypeParameterIndex), + Reference(Box), + MutableReference(Box), + // NOTE: Added in bytecode version v6, do not reorder! + #[serde(rename = "u16")] + U16, + #[serde(rename = "u32")] + U32, + #[serde(rename = "u256")] + U256, +} + +/// Normalized version of a `FieldDefinition`. The `name` is included even though it is +/// metadata that it is ignored by the VM. The reason: names are important to clients. We would +/// want a change from `Account { bal: u64, seq: u64 }` to `Account { seq: u64, bal: u64 }` to be +/// marked as incompatible. Not safe to compare without an enclosing `Struct`. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)] +pub struct Field { + pub name: Identifier, + pub type_: Type, +} + +/// Normalized version of a `Constant`. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)] +pub struct Constant { + pub type_: Type, + pub data: Vec, +} + +/// Normalized version of a `StructDefinition`. Not safe to compare without an associated +/// `ModuleId` or `Module`. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)] +pub struct Struct { + pub abilities: AbilitySet, + pub type_parameters: Vec, + pub fields: Vec, +} + +/// Normalized version of a `FunctionDefinition`. Not safe to compare without an associated +/// `ModuleId` or `Module`. +#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)] +pub struct Function { + pub visibility: Visibility, + pub is_entry: bool, + pub type_parameters: Vec, + pub parameters: Vec, + pub return_: Vec, + pub code: Vec, +} + +#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)] +pub struct FieldRef { + pub struct_name: Identifier, + pub field_index: u16, +} + +// Functions can reference external modules. We don't track the exact type parameters and the like +// since we know they can't change, or don't matter since: +// * Either we allow compatible upgrades in which case the changing of the call parameters/types +// doesn't matter since this will align with the callee signature, and that callee must go through +// the compatibility checker for any upgrades. +// * We are in an inclusion scenario. In which case either: +// - The callee is in the same package as this call, in which case the callee couldn't have changed; or +// - The callee was in a different package and therefore public, and therefore the API of that +// function must not have changed by compatibility rules. +#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)] +pub struct FunctionRef { + pub module_id: ModuleId, + pub function_ident: Identifier, +} + +/// Normalized representation of bytecode. +#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)] +pub enum Bytecode { + Pop, + Ret, + BrTrue(CodeOffset), + BrFalse(CodeOffset), + Branch(CodeOffset), + LdU8(u8), + LdU64(u64), + LdU128(u128), + CastU8, + CastU64, + CastU128, + LdConst(Constant), + LdTrue, + LdFalse, + CopyLoc(LocalIndex), + MoveLoc(LocalIndex), + StLoc(LocalIndex), + Call(FunctionRef), + CallGeneric((FunctionRef, Vec)), + Pack(Identifier), + PackGeneric((Identifier, Vec)), + Unpack(Identifier), + UnpackGeneric((Identifier, Vec)), + ReadRef, + WriteRef, + FreezeRef, + MutBorrowLoc(LocalIndex), + ImmBorrowLoc(LocalIndex), + MutBorrowField(FieldRef), + MutBorrowFieldGeneric((FieldRef, Vec)), + ImmBorrowField(FieldRef), + ImmBorrowFieldGeneric((FieldRef, Vec)), + Add, + Sub, + Mul, + Mod, + Div, + BitOr, + BitAnd, + Xor, + Or, + And, + Not, + Eq, + Neq, + Lt, + Gt, + Le, + Ge, + Abort, + Nop, + Shl, + Shr, + VecPack(Type, u64), + VecLen(Type), + VecImmBorrow(Type), + VecMutBorrow(Type), + VecPushBack(Type), + VecPopBack(Type), + VecUnpack(Type, u64), + VecSwap(Type), + LdU16(u16), + LdU32(u32), + LdU256(move_core_types::u256::U256), + CastU16, + CastU32, + CastU256, + // ******** DEPRECATED BYTECODES ******** + MutBorrowGlobalDeprecated(Identifier), + MutBorrowGlobalGenericDeprecated((Identifier, Vec)), + ImmBorrowGlobalDeprecated(Identifier), + ImmBorrowGlobalGenericDeprecated((Identifier, Vec)), + ExistsDeprecated(Identifier), + ExistsGenericDeprecated((Identifier, Vec)), + MoveFromDeprecated(Identifier), + MoveFromGenericDeprecated((Identifier, Vec)), + MoveToDeprecated(Identifier), + MoveToGenericDeprecated((Identifier, Vec)), +} + +impl Constant { + pub fn new(m: &CompiledModule, constant: &crate::file_format::Constant) -> Self { + Self { + type_: Type::new(m, &constant.type_), + data: constant.data.clone(), + } + } +} + +/// Normalized version of a `CompiledModule`: its address, name, struct declarations, and public +/// function declarations. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct Module { + pub file_format_version: u32, + pub address: AccountAddress, + pub name: Identifier, + pub dependencies: Vec, + pub friends: Vec, + pub structs: BTreeMap, + pub functions: BTreeMap, + pub constants: Vec, +} + +impl Module { + /// Extract a normalized module from a `CompiledModule`. The module `m` should be verified. + /// Nothing will break here if that is not the case, but there is little point in computing a + /// normalized representation of a module that won't verify (since it can't be published). + pub fn new(m: &CompiledModule) -> Self { + let friends = m.immediate_friends(); + let structs = m.struct_defs().iter().map(|d| Struct::new(m, d)).collect(); + let dependencies = m.immediate_dependencies(); + let constants = m + .constant_pool() + .iter() + .map(|constant| Constant::new(m, constant)) + .collect(); + let functions = m + .function_defs() + .iter() + .map(|func_def| Function::new(m, func_def)) + .collect(); + Self { + file_format_version: m.version(), + address: *m.address(), + name: m.name().to_owned(), + friends, + structs, + functions, + dependencies, + constants, + } + } + + pub fn module_id(&self) -> ModuleId { + ModuleId::new(self.address, self.name.clone()) + } +} + +impl Type { + /// Create a normalized `Type` for `SignatureToken` `s` in module `m`. + pub fn new(m: &CompiledModule, s: &SignatureToken) -> Self { + use SignatureToken::*; + match s { + Struct(shi) => { + let s_handle = m.struct_handle_at(*shi); + assert!(s_handle.type_parameters.is_empty(), "A struct with N type parameters should be encoded as StructModuleInstantiation with type_arguments = [TypeParameter(1), ..., TypeParameter(N)]"); + let m_handle = m.module_handle_at(s_handle.module); + Type::Struct { + address: *m.address_identifier_at(m_handle.address), + module: m.identifier_at(m_handle.name).to_owned(), + name: m.identifier_at(s_handle.name).to_owned(), + type_arguments: Vec::new(), + } + } + StructInstantiation(struct_inst) => { + let (shi, type_actuals) = &**struct_inst; + let s_handle = m.struct_handle_at(*shi); + let m_handle = m.module_handle_at(s_handle.module); + Type::Struct { + address: *m.address_identifier_at(m_handle.address), + module: m.identifier_at(m_handle.name).to_owned(), + name: m.identifier_at(s_handle.name).to_owned(), + type_arguments: type_actuals.iter().map(|t| Type::new(m, t)).collect(), + } + } + Bool => Type::Bool, + U8 => Type::U8, + U16 => Type::U16, + U32 => Type::U32, + U64 => Type::U64, + U128 => Type::U128, + U256 => Type::U256, + Address => Type::Address, + Signer => Type::Signer, + Vector(t) => Type::Vector(Box::new(Type::new(m, t))), + TypeParameter(i) => Type::TypeParameter(*i), + Reference(t) => Type::Reference(Box::new(Type::new(m, t))), + MutableReference(t) => Type::MutableReference(Box::new(Type::new(m, t))), + } + } + + /// Return true if `self` is a closed type with no free type variables + pub fn is_closed(&self) -> bool { + use Type::*; + match self { + TypeParameter(_) => false, + Bool => true, + U8 => true, + U16 => true, + U32 => true, + U64 => true, + U128 => true, + U256 => true, + Address => true, + Signer => true, + Struct { type_arguments, .. } => type_arguments.iter().all(|t| t.is_closed()), + Vector(t) | Reference(t) | MutableReference(t) => t.is_closed(), + } + } + + pub fn into_type_tag(self) -> Option { + use Type::*; + Some(if self.is_closed() { + match self { + Reference(_) | MutableReference(_) => return None, + Bool => TypeTag::Bool, + U8 => TypeTag::U8, + U16 => TypeTag::U16, + U32 => TypeTag::U32, + U64 => TypeTag::U64, + U128 => TypeTag::U128, + U256 => TypeTag::U256, + Address => TypeTag::Address, + Signer => TypeTag::Signer, + Vector(t) => TypeTag::Vector(Box::new( + t.into_type_tag() + .expect("Invariant violation: vector type argument contains reference"), + )), + Struct { + address, + module, + name, + type_arguments, + } => TypeTag::Struct(Box::new(StructTag { + address, + module, + name, + type_params: type_arguments + .into_iter() + .map(|t| { + t.into_type_tag().expect( + "Invariant violation: struct type argument contains reference", + ) + }) + .collect(), + })), + TypeParameter(_) => unreachable!(), + } + } else { + return None; + }) + } + + pub fn into_struct_tag(self) -> Option { + match self.into_type_tag()? { + TypeTag::Struct(s) => Some(*s), + _ => None, + } + } + + pub fn subst(&self, type_args: &[Type]) -> Self { + use Type::*; + match self { + Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address | Signer => self.clone(), + Reference(ty) => Reference(Box::new(ty.subst(type_args))), + MutableReference(ty) => MutableReference(Box::new(ty.subst(type_args))), + Vector(t) => Vector(Box::new(t.subst(type_args))), + Struct { + address, + module, + name, + type_arguments, + } => Struct { + address: *address, + module: module.clone(), + name: name.clone(), + type_arguments: type_arguments + .iter() + .map(|t| t.subst(type_args)) + .collect::>(), + }, + TypeParameter(i) => type_args + .get(*i as usize) + .expect("Type parameter index out of bound") + .clone(), + } + } +} + +impl Field { + /// Create a `Field` for `FieldDefinition` `f` in module `m`. + pub fn new(m: &CompiledModule, f: &FieldDefinition) -> Self { + Field { + name: m.identifier_at(f.name).to_owned(), + type_: Type::new(m, &f.signature.0), + } + } +} + +impl Struct { + /// Create a `Struct` for `StructDefinition` `def` in module `m`. Panics if `def` is a + /// a native struct definition. + pub fn new(m: &CompiledModule, def: &StructDefinition) -> (Identifier, Self) { + let handle = m.struct_handle_at(def.struct_handle); + let fields = match &def.field_information { + StructFieldInformation::Native => { + // Pretend for compatibility checking no fields + vec![] + } + StructFieldInformation::Declared(fields) => { + fields.iter().map(|f| Field::new(m, f)).collect() + } + }; + let name = m.identifier_at(handle.name).to_owned(); + let s = Struct { + abilities: handle.abilities, + type_parameters: handle.type_parameters.clone(), + fields, + }; + (name, s) + } + + pub fn from_idx(m: &CompiledModule, idx: &StructDefinitionIndex) -> (Identifier, Self) { + Self::new(m, m.struct_def_at(*idx)) + } + + pub fn type_param_constraints(&self) -> impl ExactSizeIterator { + self.type_parameters.iter().map(|param| ¶m.constraints) + } +} + +impl Function { + /// Create a `FunctionSignature` for `FunctionHandle` `f` in module `m`. + pub fn new(m: &CompiledModule, def: &FunctionDefinition) -> (Identifier, Self) { + let fhandle = m.function_handle_at(def.function); + let name = m.identifier_at(fhandle.name).to_owned(); + let code: Vec<_> = def + .code + .as_ref() + .map(|code| { + code.code + .iter() + .map(|bytecode| Bytecode::new(m, bytecode)) + .collect() + }) + .unwrap_or_default(); + + let f = Function { + visibility: def.visibility, + is_entry: def.is_entry, + type_parameters: fhandle.type_parameters.clone(), + parameters: m + .signature_at(fhandle.parameters) + .0 + .iter() + .map(|s| Type::new(m, s)) + .collect(), + return_: m + .signature_at(fhandle.return_) + .0 + .iter() + .map(|s| Type::new(m, s)) + .collect(), + code, + }; + (name, f) + } + + /// Create a `Function` for function named `func_name` in module `m`. + pub fn new_from_name(m: &CompiledModule, func_name: &IdentStr) -> Option { + for func_defs in &m.function_defs { + if m.identifier_at(m.function_handle_at(func_defs.function).name) == func_name { + return Some(Self::new(m, func_defs).1); + } + } + None + } +} + +impl From for Type { + fn from(ty: TypeTag) -> Type { + use Type::*; + match ty { + TypeTag::Bool => Bool, + TypeTag::U8 => U8, + TypeTag::U16 => U16, + TypeTag::U32 => U32, + TypeTag::U64 => U64, + TypeTag::U128 => U128, + TypeTag::U256 => U256, + TypeTag::Address => Address, + TypeTag::Signer => Signer, + TypeTag::Vector(ty) => Vector(Box::new(Type::from(*ty))), + TypeTag::Struct(s) => Struct { + address: s.address, + module: s.module, + name: s.name, + type_arguments: s.type_params.into_iter().map(|ty| ty.into()).collect(), + }, + } + } +} + +impl FieldRef { + pub fn new(m: &CompiledModule, field_handle: &FieldHandle) -> Self { + Self { + struct_name: m.struct_name(field_handle.owner).to_owned(), + field_index: field_handle.field, + } + } + + pub fn from_idx(m: &CompiledModule, field_handle_idx: &FieldHandleIndex) -> Self { + Self::new(m, m.field_handle_at(*field_handle_idx)) + } +} + +impl FunctionRef { + pub fn new(m: &CompiledModule, function_handle: &FunctionHandle) -> Self { + Self { + module_id: m.module_id_for_handle(m.module_handle_at(function_handle.module)), + function_ident: m.identifier_at(function_handle.name).to_owned(), + } + } + + pub fn from_idx(m: &CompiledModule, function_handle_idx: &FunctionHandleIndex) -> Self { + Self::new(m, m.function_handle_at(*function_handle_idx)) + } +} + +impl Bytecode { + pub fn new(m: &CompiledModule, bytecode: &FBytecode) -> Self { + use Bytecode as B; + use FBytecode as FB; + match bytecode { + FB::Pop => B::Pop, + FB::Ret => B::Ret, + FB::CastU8 => B::CastU8, + FB::CastU64 => B::CastU64, + FB::CastU128 => B::CastU128, + FB::LdTrue => B::LdTrue, + FB::LdFalse => B::LdFalse, + FB::ReadRef => B::ReadRef, + FB::WriteRef => B::WriteRef, + FB::FreezeRef => B::FreezeRef, + FB::Add => B::Add, + FB::Sub => B::Sub, + FB::Mul => B::Mul, + FB::Mod => B::Mod, + FB::Div => B::Div, + FB::BitOr => B::BitOr, + FB::BitAnd => B::BitAnd, + FB::Xor => B::Xor, + FB::Or => B::Or, + FB::And => B::And, + FB::Not => B::Not, + FB::Eq => B::Eq, + FB::Neq => B::Neq, + FB::Lt => B::Lt, + FB::Gt => B::Gt, + FB::Le => B::Le, + FB::Ge => B::Ge, + FB::Abort => B::Abort, + FB::Nop => B::Nop, + FB::Shl => B::Shl, + FB::Shr => B::Shr, + FB::CastU16 => B::CastU16, + FB::CastU32 => B::CastU32, + FB::CastU256 => B::CastU256, + FB::BrTrue(x) => B::BrTrue(*x), + FB::BrFalse(x) => B::BrFalse(*x), + FB::Branch(x) => B::Branch(*x), + FB::LdU8(x) => B::LdU8(*x), + FB::LdU64(x) => B::LdU64(*x), + FB::LdU128(x) => B::LdU128(**x), + FB::CopyLoc(x) => B::CopyLoc(*x), + FB::MoveLoc(x) => B::MoveLoc(*x), + FB::StLoc(x) => B::StLoc(*x), + FB::LdU16(x) => B::LdU16(*x), + FB::LdU32(x) => B::LdU32(*x), + FB::LdU256(x) => B::LdU256(**x), + FB::LdConst(const_idx) => B::LdConst(Constant::new(m, m.constant_at(*const_idx))), + FB::Call(fh_idx) => B::Call(FunctionRef::from_idx(m, fh_idx)), + FB::CallGeneric(fhi_idx) => { + let FunctionInstantiation { + handle, + type_parameters, + } = m.function_instantiation_at(*fhi_idx); + let type_params = m.signature_at(*type_parameters); + B::CallGeneric(( + FunctionRef::from_idx(m, handle), + type_params.0.iter().map(|tok| Type::new(m, tok)).collect(), + )) + } + FB::Pack(s_idx) => B::Pack(m.struct_name(*s_idx).to_owned()), + FB::PackGeneric(s_idx) => B::PackGeneric(struct_instantiation(m, s_idx)), + FB::Unpack(s_idx) => B::Unpack(m.struct_name(*s_idx).to_owned()), + FB::UnpackGeneric(si_idx) => B::UnpackGeneric(struct_instantiation(m, si_idx)), + FB::MutBorrowLoc(x) => B::MutBorrowLoc(*x), + FB::ImmBorrowLoc(x) => B::ImmBorrowLoc(*x), + FB::MutBorrowField(fh_ixd) => B::MutBorrowField(FieldRef::from_idx(m, fh_ixd)), + FB::MutBorrowFieldGeneric(fhi_idx) => { + B::MutBorrowFieldGeneric(field_instantiation(m, fhi_idx)) + } + FB::ImmBorrowField(fh_idx) => B::ImmBorrowField(FieldRef::from_idx(m, fh_idx)), + FB::ImmBorrowFieldGeneric(fhi_idx) => { + B::ImmBorrowFieldGeneric(field_instantiation(m, fhi_idx)) + } + FB::MutBorrowGlobalDeprecated(s_idx) => { + B::MutBorrowGlobalDeprecated(m.struct_name(*s_idx).to_owned()) + } + FB::MutBorrowGlobalGenericDeprecated(si_idx) => { + B::MutBorrowGlobalGenericDeprecated(struct_instantiation(m, si_idx)) + } + FB::ImmBorrowGlobalDeprecated(s_idx) => { + B::ImmBorrowGlobalDeprecated(m.struct_name(*s_idx).to_owned()) + } + FB::ImmBorrowGlobalGenericDeprecated(si_idx) => { + B::ImmBorrowGlobalGenericDeprecated(struct_instantiation(m, si_idx)) + } + FB::ExistsDeprecated(s_idx) => B::ExistsDeprecated(m.struct_name(*s_idx).to_owned()), + FB::ExistsGenericDeprecated(si_idx) => { + B::ExistsGenericDeprecated(struct_instantiation(m, si_idx)) + } + FB::MoveFromDeprecated(s_idx) => { + B::MoveFromDeprecated(m.struct_name(*s_idx).to_owned()) + } + FB::MoveFromGenericDeprecated(si_idx) => { + B::MoveFromGenericDeprecated(struct_instantiation(m, si_idx)) + } + FB::MoveToDeprecated(s_idx) => B::MoveToDeprecated(m.struct_name(*s_idx).to_owned()), + FB::MoveToGenericDeprecated(si_idx) => { + B::MoveToGenericDeprecated(struct_instantiation(m, si_idx)) + } + FB::VecPack(sig_idx, len) => B::VecPack(signature_to_single_type(m, sig_idx), *len), + FB::VecLen(sig_idx) => B::VecLen(signature_to_single_type(m, sig_idx)), + FB::VecImmBorrow(sig_idx) => B::VecImmBorrow(signature_to_single_type(m, sig_idx)), + FB::VecMutBorrow(sig_idx) => B::VecMutBorrow(signature_to_single_type(m, sig_idx)), + FB::VecPushBack(sig_idx) => B::VecPushBack(signature_to_single_type(m, sig_idx)), + FB::VecPopBack(sig_idx) => B::VecPopBack(signature_to_single_type(m, sig_idx)), + FB::VecUnpack(sig_idx, len) => B::VecUnpack(signature_to_single_type(m, sig_idx), *len), + FB::VecSwap(sig_idx) => B::VecSwap(signature_to_single_type(m, sig_idx)), + } + } +} + +impl std::fmt::Display for Type { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Type::Struct { + address, + module, + name, + type_arguments, + } => { + write!( + f, + "0x{}::{}::{}", + address.short_str_lossless(), + module, + name + )?; + if let Some(first_ty) = type_arguments.first() { + write!(f, "<")?; + write!(f, "{}", first_ty)?; + for ty in type_arguments.iter().skip(1) { + write!(f, ", {}", ty)?; + } + write!(f, ">")?; + } + Ok(()) + } + Type::Vector(ty) => write!(f, "vector<{}>", ty), + Type::U8 => write!(f, "u8"), + Type::U16 => write!(f, "u16"), + Type::U32 => write!(f, "u32"), + Type::U64 => write!(f, "u64"), + Type::U128 => write!(f, "u128"), + Type::U256 => write!(f, "u256"), + Type::Address => write!(f, "address"), + Type::Signer => write!(f, "signer"), + Type::Bool => write!(f, "bool"), + Type::Reference(r) => write!(f, "&{}", r), + Type::MutableReference(r) => write!(f, "&mut {}", r), + Type::TypeParameter(i) => write!(f, "T{:?}", i), + } + } +} + +fn struct_instantiation( + m: &CompiledModule, + si_idx: &StructDefInstantiationIndex, +) -> (Identifier, Vec) { + let StructDefInstantiation { + def, + type_parameters, + } = m.struct_instantiation_at(*si_idx); + let (name, _) = Struct::new(m, m.struct_def_at(*def)); + let types = m + .signature_at(*type_parameters) + .0 + .iter() + .map(|tok| Type::new(m, tok)) + .collect(); + (name, types) +} + +fn field_instantiation(m: &CompiledModule, idx: &FieldInstantiationIndex) -> (FieldRef, Vec) { + let FieldInstantiation { + handle, + type_parameters, + } = m.field_instantiation_at(*idx); + let field_ref = FieldRef::new(m, m.field_handle_at(*handle)); + let types = m + .signature_at(*type_parameters) + .0 + .iter() + .map(|tok| Type::new(m, tok)) + .collect(); + (field_ref, types) +} + +fn signature_to_single_type(m: &CompiledModule, sig_idx: &SignatureIndex) -> Type { + Type::new(m, &m.signature_at(*sig_idx).0[0]) +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/proptest_types.rs b/CoqOfRust/move_sui/translations/move_binary_format/proptest_types.rs new file mode 100644 index 000000000..21c7f205f --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/proptest_types.rs @@ -0,0 +1,412 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! Utilities for property-based testing. + +use crate::file_format::{ + AddressIdentifierIndex, CompiledModule, FunctionDefinition, FunctionHandle, IdentifierIndex, + ModuleHandle, ModuleHandleIndex, StructDefinition, TableIndex, +}; +use move_core_types::{account_address::AccountAddress, identifier::Identifier}; +use proptest::{ + collection::{btree_set, vec, SizeRange}, + prelude::*, + sample::Index as PropIndex, +}; + +mod constants; +mod functions; +mod metadata; +mod signature; +mod types; + +use constants::ConstantPoolGen; +use functions::{ + FnDefnMaterializeState, FnHandleMaterializeState, FunctionDefinitionGen, FunctionHandleGen, +}; + +use crate::proptest_types::{ + metadata::MetadataGen, + signature::SignatureGen, + types::{StDefnMaterializeState, StructDefinitionGen, StructHandleGen}, +}; +use std::collections::{BTreeSet, HashMap}; + +/// Represents how large [`CompiledModule`] tables can be. +pub type TableSize = u16; + +impl CompiledModule { + /// Convenience wrapper around [`CompiledModuleStrategyGen`][CompiledModuleStrategyGen] that + /// generates valid modules with the given size. + pub fn valid_strategy(size: usize) -> impl Strategy { + CompiledModuleStrategyGen::new(size as TableSize).generate() + } +} + +/// Contains configuration to generate [`CompiledModule`] instances. +/// +/// If you don't care about customizing these parameters, see [`CompiledModule::valid_strategy`]. +/// +/// A `CompiledModule` can be looked at as a graph, with several kinds of nodes, and a nest of +/// pointers among those nodes. This graph has some properties: +/// +/// 1. The graph has cycles. Generating DAGs is often simpler, but is not an option in this case. +/// 2. The actual structure of the graph is well-defined in terms of the kinds of nodes and +/// pointers that exist. +/// +/// TODO: the graph also has pointers *out* of it, via address references to other modules. +/// This doesn't need to be handled when viewing modules in isolation, but some verification passes +/// will need to look at the entire set of modules. The work to make generating such modules +/// possible remains to be done. +/// +/// Intermediate types +/// ------------------ +/// +/// The pointers are represented as indexes into vectors of other kinds of nodes. One of the +/// bigger problems is that the number of types, functions etc isn't known upfront so it is +/// impossible to know what range to pick from for the index types (`ModuleHandleIndex`, +/// `StructHandleIndex`, etc). To deal with this, the code generates a bunch of intermediate +/// structures (sometimes tuples, other times more complicated structures with their own internal +/// constraints), with "holes" represented by [`Index`](proptest::sample::Index) instances. Once all +/// the lengths are known, there's a final "materialize" step at the end that "fills in" these +/// holes. +/// +/// One alternative would have been to generate lengths up front, then create vectors of those +/// lengths. This would have worked fine for generation but would have made shrinking take much +/// longer, because the shrinker would be less aware of the overall structure of the problem and +/// would have ended up redoing a lot of work. The approach taken here does end up being more +/// verbose but should perform optimally. +/// +/// See [`proptest` issue #130](https://github.com/AltSysrq/proptest/issues/130) for more discussion +/// about this. +#[derive(Clone, Debug)] +pub struct CompiledModuleStrategyGen { + size: usize, + field_count: SizeRange, + struct_type_params: SizeRange, + parameters_count: SizeRange, + return_count: SizeRange, + func_type_params: SizeRange, + acquires_count: SizeRange, + random_sigs_count: SizeRange, + tokens_per_random_sig_count: SizeRange, + code_len: SizeRange, +} + +impl CompiledModuleStrategyGen { + /// Create a new configuration for randomly generating [`CompiledModule`] instances. + pub fn new(size: TableSize) -> Self { + Self { + size: size as usize, + field_count: (0..5).into(), + struct_type_params: (0..3).into(), + parameters_count: (0..4).into(), + return_count: (0..3).into(), + func_type_params: (0..3).into(), + acquires_count: (0..2).into(), + random_sigs_count: (0..5).into(), + tokens_per_random_sig_count: (0..5).into(), + code_len: (0..50).into(), + } + } + + /// Zero out all fields, type parameters, arguments and return types of struct and functions. + #[inline] + pub fn zeros_all(&mut self) -> &mut Self { + self.field_count = 0.into(); + self.struct_type_params = 0.into(); + self.parameters_count = 0.into(); + self.return_count = 0.into(); + self.func_type_params = 0.into(); + self.acquires_count = 0.into(); + self.random_sigs_count = 0.into(); + self.tokens_per_random_sig_count = 0.into(); + self + } + + /// Create a `proptest` strategy for `CompiledModule` instances using this configuration. + pub fn generate(self) -> impl Strategy { + // + // leaf pool generator + // + let self_idx_strat = any::(); + let address_pool_strat = btree_set(any::(), 1..=self.size); + let identifiers_strat = btree_set(any::(), 5..=self.size + 5); + let constant_pool_strat = ConstantPoolGen::strategy(0..=self.size, 0..=self.size); + let metadata_strat = MetadataGen::strategy(0..=self.size); + + // The number of PropIndex instances in each tuple represents the number of pointers out + // from an instance of that particular kind of node. + + // + // Module handle generator + // + let module_handles_strat = vec(any::<(PropIndex, PropIndex)>(), 1..=self.size); + + // + // Struct generators + // + let struct_handles_strat = vec( + StructHandleGen::strategy(self.struct_type_params.clone()), + 1..=self.size, + ); + let struct_defs_strat = vec( + StructDefinitionGen::strategy( + self.field_count.clone(), + self.struct_type_params.clone(), + ), + 1..=self.size, + ); + + // + // Random signatures generator + // + // These signatures may or may not be used in the bytecode. One way to use these signatures + // is the Vec* bytecode (e.g. VecEmpty), which will grab a random index from the pool. + // + let random_sigs_strat = vec( + SignatureGen::strategy(self.tokens_per_random_sig_count), + self.random_sigs_count, + ); + + // + // Functions generators + // + + // FunctionHandle will add to the Signature table + // FunctionDefinition will also add the following pool: + // FieldHandle, StructInstantiation, FunctionInstantiation, FieldInstantiation + let function_handles_strat = vec( + FunctionHandleGen::strategy( + self.parameters_count.clone(), + self.return_count.clone(), + self.func_type_params.clone(), + ), + 1..=self.size, + ); + let function_defs_strat = vec( + FunctionDefinitionGen::strategy( + self.return_count.clone(), + self.parameters_count.clone(), + self.func_type_params.clone(), + self.acquires_count.clone(), + self.code_len, + ), + 1..=self.size, + ); + + // + // Friend generator + // + let friends_strat = vec(any::<(PropIndex, PropIndex)>(), 1..=self.size); + + // Note that prop_test only allows a tuple of length up to 10 + ( + self_idx_strat, + ( + address_pool_strat, + identifiers_strat, + constant_pool_strat, + metadata_strat, + ), + module_handles_strat, + (struct_handles_strat, struct_defs_strat), + random_sigs_strat, + (function_handles_strat, function_defs_strat), + friends_strat, + ) + .prop_map( + |( + self_idx_gen, + (address_identifier_gens, identifier_gens, constant_pool_gen, metdata_gen), + module_handles_gen, + (struct_handle_gens, struct_def_gens), + random_sigs_gens, + (function_handle_gens, function_def_gens), + friend_decl_gens, + )| { + // + // leaf pools + let address_identifiers: Vec<_> = address_identifier_gens.into_iter().collect(); + let address_identifiers_len = address_identifiers.len(); + let identifiers: Vec<_> = identifier_gens.into_iter().collect(); + let identifiers_len = identifiers.len(); + let constant_pool = constant_pool_gen.constant_pool(); + let constant_pool_len = constant_pool.len(); + let metadata = metdata_gen.metadata(); + + // + // module handles + let mut module_handles_set = BTreeSet::new(); + let mut module_handles = vec![]; + for (address, name) in module_handles_gen { + let mh = ModuleHandle { + address: AddressIdentifierIndex( + address.index(address_identifiers_len) as TableIndex + ), + name: IdentifierIndex(name.index(identifiers_len) as TableIndex), + }; + if module_handles_set.insert((mh.address, mh.name)) { + module_handles.push(mh); + } + } + let module_handles_len = module_handles.len(); + + // + // self module handle index + let self_module_handle_idx = + ModuleHandleIndex(self_idx_gen.index(module_handles_len) as TableIndex); + + // + // Friend Declarations + let friend_decl_set: BTreeSet<_> = friend_decl_gens + .into_iter() + .map(|(address_gen, name_gen)| ModuleHandle { + address: AddressIdentifierIndex( + address_gen.index(address_identifiers_len) as TableIndex, + ), + name: IdentifierIndex(name_gen.index(identifiers_len) as TableIndex), + }) + .collect(); + let friend_decls = friend_decl_set.into_iter().collect(); + + // + // struct handles + let mut struct_handles = vec![]; + if module_handles_len > 1 { + let mut struct_handles_set = BTreeSet::new(); + for struct_handle_gen in struct_handle_gens.into_iter() { + let sh = struct_handle_gen.materialize( + self_module_handle_idx, + module_handles_len, + identifiers_len, + ); + if struct_handles_set.insert((sh.module, sh.name)) { + struct_handles.push(sh); + } + } + } + + // + // Struct definitions. + // Struct handles for the definitions are generated in this step + let mut state = StDefnMaterializeState::new( + self_module_handle_idx, + identifiers_len, + struct_handles, + ); + let mut struct_def_to_field_count: HashMap = HashMap::new(); + let mut struct_defs: Vec = vec![]; + for struct_def_gen in struct_def_gens { + if let (Some(struct_def), offset) = struct_def_gen.materialize(&mut state) { + struct_defs.push(struct_def); + if offset > 0 { + struct_def_to_field_count.insert(struct_defs.len() - 1, offset); + } + } + } + let StDefnMaterializeState { struct_handles, .. } = state; + + // + // Create some random signatures. + let mut signatures: Vec<_> = random_sigs_gens + .into_iter() + .map(|sig_gen| sig_gen.materialize(&struct_handles)) + .collect(); + + // + // Function handles. + let mut function_handles: Vec = vec![]; + if module_handles_len > 1 { + let mut state = FnHandleMaterializeState::new( + self_module_handle_idx, + module_handles_len, + identifiers_len, + &struct_handles, + signatures, + ); + for function_handle_gen in function_handle_gens { + if let Some(function_handle) = + function_handle_gen.materialize(&mut state) + { + function_handles.push(function_handle); + } + } + signatures = state.signatures(); + } + + // + // Function Definitions + // Here we need pretty much everything if we are going to emit instructions. + // signatures and function handles + let mut state = FnDefnMaterializeState::new( + self_module_handle_idx, + identifiers_len, + constant_pool_len, + &struct_handles, + &struct_defs, + signatures, + function_handles, + struct_def_to_field_count, + ); + let mut function_defs: Vec = vec![]; + for function_def_gen in function_def_gens { + if let Some(function_def) = function_def_gen.materialize(&mut state) { + function_defs.push(function_def); + } + } + let ( + signatures, + function_handles, + field_handles, + struct_def_instantiations, + function_instantiations, + field_instantiations, + ) = state.return_tables(); + + // Build a compiled module + CompiledModule { + version: crate::file_format_common::VERSION_MAX, + module_handles, + self_module_handle_idx, + struct_handles, + function_handles, + field_handles, + friend_decls, + + struct_def_instantiations, + function_instantiations, + field_instantiations, + + struct_defs, + function_defs, + + signatures, + + identifiers, + address_identifiers, + constant_pool, + metadata, + } + }, + ) + } +} + +/// A utility function that produces a prop_index but also avoiding the given index. If the random +/// index at the first choice collides with the avoidance, then try +/- 1 from the chosen value and +/// pick the one that does not over/under-flow. +pub(crate) fn prop_index_avoid(gen: PropIndex, avoid: usize, pool_size: usize) -> usize { + assert!(pool_size > 1); + assert!(pool_size > avoid); + let rand = gen.index(pool_size); + if rand != avoid { + return rand; + } + let rand_inc = rand.checked_add(1).unwrap(); + if rand_inc != pool_size { + return rand_inc; + } + rand.checked_sub(1).unwrap() +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/constants.rs b/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/constants.rs new file mode 100644 index 000000000..4f8d112f2 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/constants.rs @@ -0,0 +1,65 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::file_format::{Constant, SignatureToken}; +use move_core_types::account_address::AccountAddress; +use proptest::{ + arbitrary::any, + collection::{btree_set, vec, SizeRange}, + strategy::Strategy, +}; + +// A `ConstantPoolGen` gives you back a `Strategy` that makes a constant pool with +// `Address` and `Vector` only. +// TODO: make it more general and plug in a constant API +#[derive(Clone, Debug)] +pub struct ConstantPoolGen { + addresses: Vec, + byte_arrays: Vec>, +} + +impl ConstantPoolGen { + // Return a `Strategy` that builds a ConstantPool with a number of `addresse`s and + // `vector` respectively driven by `address_count` and `byte_array_count` + pub fn strategy( + address_count: impl Into, + byte_array_count: impl Into, + ) -> impl Strategy { + // get unique sets of addresses and vector (empty vector allowed) + ( + btree_set(any::(), address_count), + btree_set(vec(any::(), 0..=20), byte_array_count), + ) + .prop_map(|(addresses, byte_arrays)| Self { + addresses: addresses.into_iter().collect(), + byte_arrays: byte_arrays.into_iter().collect(), + }) + } + + // Return the `ConstantPool` + pub fn constant_pool(self) -> Vec { + let mut constants = vec![]; + for address in self.addresses { + constants.push(Constant { + type_: SignatureToken::Address, + data: address.to_vec(), + }); + } + for mut byte_array in self.byte_arrays { + // TODO: below is a trick to make serialization easy (size being one byte) + // This can hopefully help soon in defining an API for constants + // As a restriction is a non issue as we don't have input over big numbers (>100) + if byte_array.len() > 127 { + continue; + } + byte_array.push(byte_array.len() as u8); + byte_array.reverse(); + constants.push(Constant { + type_: SignatureToken::Vector(Box::new(SignatureToken::U8)), + data: byte_array, + }); + } + constants + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/functions.rs b/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/functions.rs new file mode 100644 index 000000000..96079b741 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/functions.rs @@ -0,0 +1,860 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + file_format::{ + AbilitySet, Bytecode, CodeOffset, CodeUnit, ConstantPoolIndex, FieldHandle, + FieldHandleIndex, FieldInstantiation, FieldInstantiationIndex, FunctionDefinition, + FunctionHandle, FunctionHandleIndex, FunctionInstantiation, FunctionInstantiationIndex, + IdentifierIndex, LocalIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, + StructDefInstantiation, StructDefInstantiationIndex, StructDefinition, + StructDefinitionIndex, StructHandle, TableIndex, Visibility, + }, + internals::ModuleIndex, + proptest_types::{ + prop_index_avoid, + signature::{AbilitySetGen, SignatureGen, SignatureTokenGen}, + TableSize, + }, +}; +use move_core_types::u256::U256; +use proptest::{ + collection::{vec, SizeRange}, + prelude::*, + sample::{select, Index as PropIndex}, +}; +use std::{ + collections::{BTreeSet, HashMap, HashSet}, + hash::Hash, +}; + +#[derive(Debug, Default)] +struct SignatureState { + signatures: Vec, + signature_map: HashMap, +} + +impl SignatureState { + fn new(signatures: Vec) -> Self { + let mut state = Self::default(); + for sig in signatures { + state.add_signature(sig); + } + state + } + + fn signatures(self) -> Vec { + self.signatures + } + + fn add_signature(&mut self, sig: Signature) -> SignatureIndex { + debug_assert!(self.signatures.len() < TableSize::max_value() as usize); + if let Some(idx) = self.signature_map.get(&sig) { + return *idx; + } + let idx = SignatureIndex(self.signatures.len() as u16); + self.signatures.push(sig.clone()); + self.signature_map.insert(sig, idx); + idx + } +} + +#[derive(Debug, Default)] +#[allow(unused)] +struct FieldHandleState { + field_handles: Vec, + field_map: HashMap, +} + +impl FieldHandleState { + #[allow(unused)] + pub fn field_handles(self) -> Vec { + self.field_handles + } + + #[allow(unused)] + fn add_field_handle(&mut self, fh: FieldHandle) -> FieldHandleIndex { + debug_assert!(self.field_handles.len() < TableSize::max_value() as usize); + if let Some(idx) = self.field_map.get(&fh) { + return *idx; + } + let idx = FieldHandleIndex(self.field_handles.len() as u16); + self.field_handles.push(fh.clone()); + self.field_map.insert(fh, idx); + idx + } +} + +#[derive(Debug)] +#[allow(unused)] +struct InstantiationState +where + T: Eq + Clone + Hash, +{ + instantiations: Vec, + instantiation_map: HashMap, +} + +impl InstantiationState +where + T: Eq + Clone + Hash, +{ + fn new() -> Self { + InstantiationState { + instantiations: vec![], + instantiation_map: HashMap::new(), + } + } + + #[allow(unused)] + pub fn instantiations(self) -> Vec { + self.instantiations + } + + #[allow(unused)] + fn add_instantiation(&mut self, inst: T) -> TableIndex { + debug_assert!(self.instantiations.len() < TableSize::max_value() as usize); + if let Some(idx) = self.instantiation_map.get(&inst) { + return *idx; + } + let idx = self.instantiations.len() as TableIndex; + self.instantiations.push(inst.clone()); + self.instantiation_map.insert(inst, idx); + idx + } +} + +/// Represents state required to materialize final data structures for function handles. +#[derive(Debug)] +pub struct FnHandleMaterializeState<'a> { + self_module_handle_idx: ModuleHandleIndex, + module_handles_len: usize, + identifiers_len: usize, + struct_handles: &'a [StructHandle], + signatures: SignatureState, + function_handles: HashSet<(ModuleHandleIndex, IdentifierIndex)>, +} + +impl<'a> FnHandleMaterializeState<'a> { + pub fn new( + self_module_handle_idx: ModuleHandleIndex, + module_handles_len: usize, + identifiers_len: usize, + struct_handles: &'a [StructHandle], + signatures: Vec, + ) -> Self { + Self { + self_module_handle_idx, + module_handles_len, + identifiers_len, + struct_handles, + signatures: SignatureState::new(signatures), + function_handles: HashSet::new(), + } + } + + pub fn signatures(self) -> Vec { + self.signatures.signatures() + } + + fn add_signature(&mut self, sig: Signature) -> SignatureIndex { + self.signatures.add_signature(sig) + } +} + +#[derive(Clone, Debug)] +pub struct FunctionHandleGen { + module: PropIndex, + name: PropIndex, + parameters: SignatureGen, + return_: SignatureGen, + type_parameters: Vec, +} + +impl FunctionHandleGen { + pub fn strategy( + param_count: impl Into, + return_count: impl Into, + type_parameter_count: impl Into, + ) -> impl Strategy { + let return_count = return_count.into(); + let param_count = param_count.into(); + ( + any::(), + any::(), + SignatureGen::strategy(param_count), + SignatureGen::strategy(return_count), + vec(AbilitySetGen::strategy(), type_parameter_count), + ) + .prop_map( + |(module, name, parameters, return_, type_parameters)| Self { + module, + name, + parameters, + return_, + type_parameters, + }, + ) + } + + pub fn materialize(self, state: &mut FnHandleMaterializeState) -> Option { + let idx = prop_index_avoid( + self.module, + state.self_module_handle_idx.into_index(), + state.module_handles_len, + ); + let mod_idx = ModuleHandleIndex(idx as TableIndex); + let iden_idx = IdentifierIndex(self.name.index(state.identifiers_len) as TableIndex); + if state.function_handles.contains(&(mod_idx, iden_idx)) { + return None; + } + state.function_handles.insert((mod_idx, iden_idx)); + let parameters = self.parameters.materialize(state.struct_handles); + let params_idx = state.add_signature(parameters); + let return_ = self.return_.materialize(state.struct_handles); + let return_idx = state.add_signature(return_); + let type_parameters = self + .type_parameters + .into_iter() + .map(|abilities| abilities.materialize()) + .collect(); + Some(FunctionHandle { + module: mod_idx, + name: iden_idx, + parameters: params_idx, + return_: return_idx, + type_parameters, + }) + } +} + +/// Represents state required to materialize final data structures for function definitions. +#[derive(Debug)] +pub struct FnDefnMaterializeState<'a> { + self_module_handle_idx: ModuleHandleIndex, + identifiers_len: usize, + constant_pool_len: usize, + struct_handles: &'a [StructHandle], + struct_defs: &'a [StructDefinition], + signatures: SignatureState, + function_handles: Vec, + struct_def_to_field_count: HashMap, + def_function_handles: HashSet<(ModuleHandleIndex, IdentifierIndex)>, + field_handles: FieldHandleState, + type_instantiations: InstantiationState, + function_instantiations: InstantiationState, + field_instantiations: InstantiationState, +} + +impl<'a> FnDefnMaterializeState<'a> { + pub fn new( + self_module_handle_idx: ModuleHandleIndex, + identifiers_len: usize, + constant_pool_len: usize, + struct_handles: &'a [StructHandle], + struct_defs: &'a [StructDefinition], + signatures: Vec, + function_handles: Vec, + struct_def_to_field_count: HashMap, + ) -> Self { + Self { + self_module_handle_idx, + identifiers_len, + constant_pool_len, + struct_handles, + struct_defs, + signatures: SignatureState::new(signatures), + function_handles, + struct_def_to_field_count, + def_function_handles: HashSet::new(), + field_handles: FieldHandleState::default(), + type_instantiations: InstantiationState::new(), + function_instantiations: InstantiationState::new(), + field_instantiations: InstantiationState::new(), + } + } + + pub fn return_tables( + self, + ) -> ( + Vec, + Vec, + Vec, + Vec, + Vec, + Vec, + ) { + ( + self.signatures.signatures(), + self.function_handles, + self.field_handles.field_handles(), + self.type_instantiations.instantiations(), + self.function_instantiations.instantiations(), + self.field_instantiations.instantiations(), + ) + } + + fn add_signature(&mut self, sig: Signature) -> SignatureIndex { + self.signatures.add_signature(sig) + } + + fn add_function_handle(&mut self, handle: FunctionHandle) -> FunctionHandleIndex { + debug_assert!(self.function_handles.len() < TableSize::max_value() as usize); + self.function_handles.push(handle); + FunctionHandleIndex((self.function_handles.len() - 1) as TableIndex) + } + + fn get_signature_from_type_params( + &mut self, + abilities: impl IntoIterator, + ) -> Signature { + let mut type_params = vec![]; + for abs in abilities { + assert!(!abs.has_key()); + match (abs.has_copy(), abs.has_drop(), abs.has_store()) { + (false, true, false) => type_params.push(SignatureToken::Signer), + _ => type_params.push(SignatureToken::U64), + } + } + Signature(type_params) + } + + fn add_signature_from_type_params( + &mut self, + abilities: impl IntoIterator, + ) -> SignatureIndex { + let sig = self.get_signature_from_type_params(abilities); + self.signatures.add_signature(sig) + } + + fn get_function_instantiation(&mut self, fh_idx: usize) -> FunctionInstantiationIndex { + let abilities = self.function_handles[fh_idx].type_parameters.clone(); + let sig_idx = self.add_signature_from_type_params(abilities.iter().copied()); + let fi = FunctionInstantiation { + handle: FunctionHandleIndex(fh_idx as TableIndex), + type_parameters: sig_idx, + }; + FunctionInstantiationIndex(self.function_instantiations.add_instantiation(fi)) + } + + fn get_type_instantiation(&mut self, sd_idx: usize) -> StructDefInstantiationIndex { + let sd = &self.struct_defs[sd_idx]; + let struct_handle = &self.struct_handles[sd.struct_handle.0 as usize]; + let sig_idx = self.add_signature_from_type_params(struct_handle.type_param_constraints()); + let si = StructDefInstantiation { + def: StructDefinitionIndex(sd_idx as TableIndex), + type_parameters: sig_idx, + }; + StructDefInstantiationIndex(self.type_instantiations.add_instantiation(si)) + } +} + +#[derive(Clone, Debug)] +pub struct FunctionDefinitionGen { + name: PropIndex, + parameters: SignatureGen, + return_: SignatureGen, + visibility: Visibility, + is_entry: bool, + acquires: Vec, + code: CodeUnitGen, +} + +impl FunctionDefinitionGen { + pub fn strategy( + return_count: impl Into, + arg_count: impl Into, + _type_parameter_count: impl Into, + acquires_count: impl Into, + code_len: impl Into, + ) -> impl Strategy { + let return_count = return_count.into(); + let arg_count = arg_count.into(); + ( + any::(), + SignatureGen::strategy(arg_count.clone()), + SignatureGen::strategy(return_count), + any::(), + any::(), + vec(any::(), acquires_count.into()), + CodeUnitGen::strategy(arg_count, code_len), + ) + .prop_map( + |(name, parameters, return_, visibility, is_entry, acquires, code)| Self { + name, + parameters, + return_, + visibility, + is_entry, + acquires, + code, + }, + ) + } + + pub fn materialize(self, state: &mut FnDefnMaterializeState) -> Option { + // This precondition should never fail because the table size cannot be greater + // than TableSize::max_value() + let iden_idx = IdentifierIndex(self.name.index(state.identifiers_len) as TableIndex); + if state + .def_function_handles + .contains(&(state.self_module_handle_idx, iden_idx)) + { + return None; + } + state + .def_function_handles + .insert((state.self_module_handle_idx, iden_idx)); + + let parameters = self.parameters.materialize(state.struct_handles); + let params_idx = state.add_signature(parameters); + let return_ = self.return_.materialize(state.struct_handles); + let return_idx = state.add_signature(return_); + let handle = FunctionHandle { + module: state.self_module_handle_idx, + name: iden_idx, + parameters: params_idx, + return_: return_idx, + type_parameters: vec![], + }; + let function_handle = state.add_function_handle(handle); + let mut acquires_set = BTreeSet::new(); + for acquire in self.acquires { + acquires_set.insert(StructDefinitionIndex( + acquire.index(state.struct_defs.len()) as TableIndex, + )); + } + let acquires_global_resources = acquires_set.into_iter().collect(); + // TODO: consider generating native functions? + Some(FunctionDefinition { + function: function_handle, + visibility: self.visibility, + is_entry: self.is_entry, + acquires_global_resources, + code: Some(self.code.materialize(state)), + }) + } +} + +#[derive(Clone, Debug)] +struct CodeUnitGen { + locals_signature: Vec, + code: Vec, +} + +impl CodeUnitGen { + fn strategy( + arg_count: impl Into, + code_len: impl Into, + ) -> impl Strategy { + ( + vec(SignatureTokenGen::strategy(), arg_count), + vec(BytecodeGen::garbage_strategy(), code_len), + ) + .prop_map(|(locals_signature, code)| Self { + locals_signature, + code, + }) + } + + fn materialize(self, state: &mut FnDefnMaterializeState) -> CodeUnit { + let locals_signature = Signature( + self.locals_signature + .into_iter() + .map(|sig| sig.materialize(state.struct_handles)) + .collect(), + ); + + let mut code = vec![]; + for bytecode_gen in self.code { + if let Some(bytecode) = bytecode_gen.materialize(state, code.len(), &locals_signature) { + code.push(bytecode) + } + } + + CodeUnit { + locals: state.add_signature(locals_signature), + code, + } + } +} + +#[derive(Clone, Debug)] +enum BytecodeGen { + // "Simple" means this doesn't refer to any other indexes. + Simple(Bytecode), + // All of these refer to other indexes. + LdConst(PropIndex), + + MutBorrowField((PropIndex, PropIndex)), + ImmBorrowField((PropIndex, PropIndex)), + + Call(PropIndex), + + Pack(PropIndex), + Unpack(PropIndex), + BrTrue(PropIndex), + BrFalse(PropIndex), + Branch(PropIndex), + CopyLoc(PropIndex), + MoveLoc(PropIndex), + StLoc(PropIndex), + MutBorrowLoc(PropIndex), + ImmBorrowLoc(PropIndex), + + VecPack((PropIndex, u64)), + VecLen(PropIndex), + VecImmBorrow(PropIndex), + VecMutBorrow(PropIndex), + VecPushBack(PropIndex), + VecPopBack(PropIndex), + VecUnpack((PropIndex, u64)), + VecSwap(PropIndex), +} + +impl BytecodeGen { + // This just generates nonsensical bytecodes. This will be cleaned up later as the generation + // model is refined. + fn garbage_strategy() -> impl Strategy { + use BytecodeGen::*; + + prop_oneof![ + Self::simple_bytecode_strategy().prop_map(Simple), + any::().prop_map(LdConst), + (any::(), any::()).prop_map(ImmBorrowField), + (any::(), any::()).prop_map(MutBorrowField), + any::().prop_map(Call), + any::().prop_map(Pack), + any::().prop_map(Unpack), + any::().prop_map(BrTrue), + any::().prop_map(BrFalse), + any::().prop_map(Branch), + any::().prop_map(CopyLoc), + any::().prop_map(MoveLoc), + any::().prop_map(StLoc), + any::().prop_map(MutBorrowLoc), + any::().prop_map(ImmBorrowLoc), + (any::(), any::()).prop_map(VecPack), + any::().prop_map(VecLen), + any::().prop_map(VecImmBorrow), + any::().prop_map(VecMutBorrow), + any::().prop_map(VecPushBack), + any::().prop_map(VecPopBack), + (any::(), any::()).prop_map(VecUnpack), + any::().prop_map(VecSwap), + ] + } + + fn materialize( + self, + state: &mut FnDefnMaterializeState, + code_len: usize, + locals_signature: &Signature, + ) -> Option { + let bytecode = match self { + BytecodeGen::Simple(bytecode) => bytecode, + BytecodeGen::LdConst(idx) => { + if state.constant_pool_len == 0 { + return None; + } + Bytecode::LdConst(ConstantPoolIndex( + idx.index(state.constant_pool_len) as TableIndex + )) + } + BytecodeGen::MutBorrowField((def, field)) => { + let sd_idx = def.index(state.struct_defs.len()); + let field_count = state.struct_def_to_field_count.get(&sd_idx)?; + if *field_count == 0 { + return None; + } + let fh_idx = state.field_handles.add_field_handle(FieldHandle { + owner: StructDefinitionIndex(sd_idx as TableIndex), + field: field.index(*field_count) as TableIndex, + }); + + let struct_handle = + &state.struct_handles[state.struct_defs[sd_idx].struct_handle.0 as usize]; + if struct_handle.type_parameters.is_empty() { + Bytecode::MutBorrowField(fh_idx) + } else { + let sig_idx = state + .add_signature_from_type_params(struct_handle.type_param_constraints()); + let fi_idx = state + .field_instantiations + .add_instantiation(FieldInstantiation { + handle: fh_idx, + type_parameters: sig_idx, + }); + Bytecode::MutBorrowFieldGeneric(FieldInstantiationIndex(fi_idx)) + } + } + BytecodeGen::ImmBorrowField((def, field)) => { + let sd_idx = def.index(state.struct_defs.len()); + let field_count = state.struct_def_to_field_count.get(&sd_idx)?; + if *field_count == 0 { + return None; + } + let fh_idx = state.field_handles.add_field_handle(FieldHandle { + owner: StructDefinitionIndex(sd_idx as TableIndex), + field: field.index(*field_count) as TableIndex, + }); + + let struct_handle = + &state.struct_handles[state.struct_defs[sd_idx].struct_handle.0 as usize]; + if struct_handle.type_parameters.is_empty() { + Bytecode::ImmBorrowField(fh_idx) + } else { + let sig_idx = state + .add_signature_from_type_params(struct_handle.type_param_constraints()); + let fi_idx = state + .field_instantiations + .add_instantiation(FieldInstantiation { + handle: fh_idx, + type_parameters: sig_idx, + }); + Bytecode::ImmBorrowFieldGeneric(FieldInstantiationIndex(fi_idx)) + } + } + BytecodeGen::Call(idx) => { + let func_handles_len = state.function_handles.len(); + let fh_idx = idx.index(func_handles_len); + + if state.function_handles[fh_idx].type_parameters.is_empty() { + Bytecode::Call(FunctionHandleIndex(fh_idx as TableIndex)) + } else { + Bytecode::CallGeneric(state.get_function_instantiation(fh_idx)) + } + } + BytecodeGen::Pack(idx) => { + let struct_defs_len = state.struct_defs.len(); + let sd_idx = idx.index(struct_defs_len); + + let sd = &state.struct_defs[sd_idx]; + if state.struct_handles[sd.struct_handle.0 as usize] + .type_parameters + .is_empty() + { + Bytecode::Pack(StructDefinitionIndex(sd_idx as TableIndex)) + } else { + Bytecode::PackGeneric(state.get_type_instantiation(sd_idx)) + } + } + BytecodeGen::Unpack(idx) => { + let struct_defs_len = state.struct_defs.len(); + let sd_idx = idx.index(struct_defs_len); + + let sd = &state.struct_defs[sd_idx]; + if state.struct_handles[sd.struct_handle.0 as usize] + .type_parameters + .is_empty() + { + Bytecode::Unpack(StructDefinitionIndex(sd_idx as TableIndex)) + } else { + Bytecode::UnpackGeneric(state.get_type_instantiation(sd_idx)) + } + } + BytecodeGen::BrTrue(idx) => { + if code_len == 0 { + return None; + } + Bytecode::BrTrue(idx.index(code_len) as CodeOffset) + } + BytecodeGen::BrFalse(idx) => { + if code_len == 0 { + return None; + } + Bytecode::BrFalse(idx.index(code_len) as CodeOffset) + } + BytecodeGen::Branch(idx) => { + if code_len == 0 { + return None; + } + Bytecode::Branch(idx.index(code_len) as CodeOffset) + } + BytecodeGen::CopyLoc(idx) => { + if locals_signature.is_empty() { + return None; + } + Bytecode::CopyLoc(idx.index(locals_signature.len()) as LocalIndex) + } + BytecodeGen::MoveLoc(idx) => { + if locals_signature.is_empty() { + return None; + } + Bytecode::MoveLoc(idx.index(locals_signature.len()) as LocalIndex) + } + BytecodeGen::StLoc(idx) => { + if locals_signature.is_empty() { + return None; + } + Bytecode::StLoc(idx.index(locals_signature.len()) as LocalIndex) + } + BytecodeGen::MutBorrowLoc(idx) => { + if locals_signature.is_empty() { + return None; + } + Bytecode::MutBorrowLoc(idx.index(locals_signature.len()) as LocalIndex) + } + BytecodeGen::ImmBorrowLoc(idx) => { + if locals_signature.is_empty() { + return None; + } + Bytecode::ImmBorrowLoc(idx.index(locals_signature.len()) as LocalIndex) + } + BytecodeGen::VecPack((idx, num)) => { + if num > u16::MAX as u64 { + return None; + } + let sigs_len = state.signatures.signatures.len(); + if sigs_len == 0 { + return None; + } + let sig_idx = idx.index(sigs_len); + let sig = &state.signatures.signatures[sig_idx]; + if !BytecodeGen::is_valid_vector_element_sig(sig) { + return None; + } + Bytecode::VecPack(SignatureIndex(sig_idx as TableIndex), num) + } + BytecodeGen::VecLen(idx) => { + let sigs_len = state.signatures.signatures.len(); + if sigs_len == 0 { + return None; + } + let sig_idx = idx.index(sigs_len); + let sig = &state.signatures.signatures[sig_idx]; + if !BytecodeGen::is_valid_vector_element_sig(sig) { + return None; + } + Bytecode::VecLen(SignatureIndex(sig_idx as TableIndex)) + } + BytecodeGen::VecImmBorrow(idx) => { + let sigs_len = state.signatures.signatures.len(); + if sigs_len == 0 { + return None; + } + let sig_idx = idx.index(sigs_len); + let sig = &state.signatures.signatures[sig_idx]; + if !BytecodeGen::is_valid_vector_element_sig(sig) { + return None; + } + Bytecode::VecImmBorrow(SignatureIndex(sig_idx as TableIndex)) + } + BytecodeGen::VecMutBorrow(idx) => { + let sigs_len = state.signatures.signatures.len(); + if sigs_len == 0 { + return None; + } + let sig_idx = idx.index(sigs_len); + let sig = &state.signatures.signatures[sig_idx]; + if !BytecodeGen::is_valid_vector_element_sig(sig) { + return None; + } + Bytecode::VecMutBorrow(SignatureIndex(sig_idx as TableIndex)) + } + BytecodeGen::VecPushBack(idx) => { + let sigs_len = state.signatures.signatures.len(); + if sigs_len == 0 { + return None; + } + let sig_idx = idx.index(sigs_len); + let sig = &state.signatures.signatures[sig_idx]; + if !BytecodeGen::is_valid_vector_element_sig(sig) { + return None; + } + Bytecode::VecPushBack(SignatureIndex(sig_idx as TableIndex)) + } + BytecodeGen::VecPopBack(idx) => { + let sigs_len = state.signatures.signatures.len(); + if sigs_len == 0 { + return None; + } + let sig_idx = idx.index(sigs_len); + let sig = &state.signatures.signatures[sig_idx]; + if !BytecodeGen::is_valid_vector_element_sig(sig) { + return None; + } + Bytecode::VecPopBack(SignatureIndex(sig_idx as TableIndex)) + } + BytecodeGen::VecUnpack((idx, num)) => { + if num > u16::MAX as u64 { + return None; + } + let sigs_len = state.signatures.signatures.len(); + if sigs_len == 0 { + return None; + } + let sig_idx = idx.index(sigs_len); + let sig = &state.signatures.signatures[sig_idx]; + if !BytecodeGen::is_valid_vector_element_sig(sig) { + return None; + } + Bytecode::VecUnpack(SignatureIndex(sig_idx as TableIndex), num) + } + BytecodeGen::VecSwap(idx) => { + let sigs_len = state.signatures.signatures.len(); + if sigs_len == 0 { + return None; + } + let sig_idx = idx.index(sigs_len); + let sig = &state.signatures.signatures[sig_idx]; + if !BytecodeGen::is_valid_vector_element_sig(sig) { + return None; + } + Bytecode::VecSwap(SignatureIndex(sig_idx as TableIndex)) + } + }; + + Some(bytecode) + } + + /// Checks if the given type is well defined in the given context. + /// No references are permitted. + fn check_signature_token(token: &SignatureToken) -> bool { + use SignatureToken::*; + match token { + U8 | U16 | U32 | U64 | U128 | U256 | Bool | Address | Signer | Struct(_) + | TypeParameter(_) => true, + Vector(element_token) => BytecodeGen::check_signature_token(element_token), + StructInstantiation(struct_inst) => { + let (_, type_arguments) = &**struct_inst; + type_arguments + .iter() + .all(BytecodeGen::check_signature_token) + } + Reference(_) | MutableReference(_) => false, + } + } + + fn is_valid_vector_element_sig(sig: &Signature) -> bool { + if sig.len() != 1 { + return false; + } + BytecodeGen::check_signature_token(&sig.0[0]) + } + + fn simple_bytecode_strategy() -> impl Strategy { + prop_oneof![ + // The numbers are relative weights, somewhat arbitrarily picked. + 9 => Self::just_bytecode_strategy(), + 1 => any::().prop_map(Bytecode::LdU64), + 1 => any::().prop_map(Bytecode::LdU8), + 1 => any::>().prop_map(Bytecode::LdU128), + 1 => any::().prop_map(Bytecode::LdU16), + 1 => any::().prop_map(Bytecode::LdU32), + 1 => any::>().prop_map(Bytecode::LdU256), + ] + } + + fn just_bytecode_strategy() -> impl Strategy { + use Bytecode::*; + + static JUST_BYTECODES: &[Bytecode] = &[ + FreezeRef, Pop, Ret, LdTrue, LdFalse, ReadRef, WriteRef, Add, Sub, Mul, Mod, Div, + BitOr, BitAnd, Xor, Or, And, Eq, Neq, Lt, Gt, Le, Ge, Abort, CastU8, CastU64, CastU128, + CastU16, CastU32, CastU256, Not, Nop, Shl, Shr, + ]; + select(JUST_BYTECODES) + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/metadata.rs b/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/metadata.rs new file mode 100644 index 000000000..2cb0425d8 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/metadata.rs @@ -0,0 +1,37 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use move_core_types::metadata::Metadata; +use proptest::{ + arbitrary::any, + collection::{btree_set, vec, SizeRange}, + strategy::Strategy, +}; + +// A metadata generation strategy. +#[derive(Clone, Debug)] +pub struct MetadataGen { + blobs: Vec>, +} + +impl MetadataGen { + // Return a `Strategy` that builds Metadata vectors based on the given size. + pub fn strategy(blob_size: impl Into) -> impl Strategy { + btree_set(vec(any::(), 0..=20), blob_size).prop_map(|blobs| Self { + blobs: blobs.into_iter().collect(), + }) + } + + // Return the metadata + pub fn metadata(self) -> Vec { + let mut metadata = vec![]; + for blob in self.blobs { + metadata.push(Metadata { + key: blob.clone(), + value: blob, + }) + } + metadata + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/signature.rs b/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/signature.rs new file mode 100644 index 000000000..b957f5d20 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/signature.rs @@ -0,0 +1,212 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::file_format::{ + Ability, AbilitySet, Signature, SignatureToken, StructHandle, StructHandleIndex, TableIndex, + TypeParameterIndex, +}; +use proptest::{ + collection::{vec, SizeRange}, + prelude::*, + sample::{select, Index as PropIndex}, +}; + +#[derive(Clone, Debug)] +pub enum AbilitySetGen { + Empty, + Copy, + Drop, + Store, + CopyDrop, + CopyStore, + DropStore, + CopyDropStore, +} + +impl AbilitySetGen { + pub fn strategy() -> impl Strategy { + use AbilitySetGen as G; + + static KINDS: &[AbilitySetGen] = &[ + G::Empty, + G::Copy, + G::Drop, + G::Store, + G::CopyDrop, + G::CopyStore, + G::DropStore, + G::CopyDropStore, + ]; + + select(KINDS) + } + + pub fn materialize(self) -> AbilitySet { + use AbilitySetGen as G; + + let empty = AbilitySet::EMPTY; + match self { + G::Empty => empty, + G::Copy => empty | Ability::Copy, + G::Drop => empty | Ability::Drop, + G::Store => empty | Ability::Store, + G::CopyDrop => empty | Ability::Copy | Ability::Drop, + G::CopyStore => empty | Ability::Copy | Ability::Store, + G::DropStore => empty | Ability::Drop | Ability::Store, + G::CopyDropStore => empty | Ability::Copy | Ability::Drop | Ability::Store, + } + } +} + +#[derive(Clone, Debug)] +pub struct SignatureGen { + signatures: Vec, +} + +impl SignatureGen { + pub fn strategy(sig_count: impl Into) -> impl Strategy { + vec(SignatureTokenGen::strategy(), sig_count).prop_map(|signatures| Self { signatures }) + } + + pub fn materialize(self, struct_handles: &[StructHandle]) -> Signature { + Signature( + self.signatures + .into_iter() + .map(move |token| token.materialize(struct_handles)) + .collect(), + ) + } +} + +#[derive(Clone, Debug)] +pub enum SignatureTokenGen { + // Atomic signature tokens. + Bool, + U8, + U16, + U32, + U64, + U128, + U256, + Address, + Signer, + TypeParameter(PropIndex), + + // Composite signature tokens. + Struct(PropIndex), + Vector(Box), + Reference(Box), + MutableReference(Box), +} + +impl SignatureTokenGen { + pub fn strategy() -> impl Strategy { + prop::strategy::Union::new_weighted(vec![ + (5, Self::atom_strategy().boxed()), + (1, Self::reference_strategy().boxed()), + (1, Self::mutable_reference_strategy().boxed()), + (1, Self::vector_strategy().boxed()), + ]) + } + + /// Generates a signature token for an owned (non-reference) type. + pub fn owned_strategy() -> impl Strategy { + prop::strategy::Union::new_weighted(vec![(3, Self::atom_strategy().boxed())]) + } + + pub fn atom_strategy() -> impl Strategy { + prop_oneof![ + 9 => Self::owned_non_struct_strategy(), + 1 => Self::struct_strategy(), + // 1=> Self::type_parameter_strategy(), + ] + } + + /// Generates a signature token for a non-struct owned type. + pub fn owned_non_struct_strategy() -> impl Strategy { + use SignatureTokenGen::*; + + static OWNED_NON_STRUCTS: &[SignatureTokenGen] = + &[Bool, U8, U16, U32, U64, U128, U256, Address, Signer]; + + select(OWNED_NON_STRUCTS) + } + + // TODO: remove allow(dead_code) once related features are implemented + #[allow(dead_code)] + pub fn type_parameter_strategy() -> impl Strategy { + any::().prop_map(SignatureTokenGen::TypeParameter) + } + + pub fn struct_strategy() -> impl Strategy { + any::().prop_map(SignatureTokenGen::Struct) + } + + pub fn vector_strategy() -> impl Strategy { + Self::owned_strategy().prop_map(|atom| SignatureTokenGen::Vector(Box::new(atom))) + } + + pub fn reference_strategy() -> impl Strategy { + // References to references are not supported. + Self::owned_strategy().prop_map(|atom| SignatureTokenGen::Reference(Box::new(atom))) + } + + pub fn mutable_reference_strategy() -> impl Strategy { + // References to references are not supported. + Self::owned_strategy().prop_map(|atom| SignatureTokenGen::MutableReference(Box::new(atom))) + } + + pub fn materialize(self, struct_handles: &[StructHandle]) -> SignatureToken { + use SignatureTokenGen::*; + match self { + Bool => SignatureToken::Bool, + U8 => SignatureToken::U8, + U16 => SignatureToken::U16, + U32 => SignatureToken::U32, + U64 => SignatureToken::U64, + U128 => SignatureToken::U128, + U256 => SignatureToken::U256, + Address => SignatureToken::Address, + Signer => SignatureToken::Signer, + Struct(idx) => { + let struct_handles_len = struct_handles.len(); + if struct_handles_len == 0 { + // we are asked to create a type of a struct that cannot exist + // so we fake a U64 instead... + SignatureToken::U64 + } else { + let struct_idx = idx.index(struct_handles_len); + let sh = &struct_handles[struct_idx]; + if sh.type_parameters.is_empty() { + SignatureToken::Struct(StructHandleIndex(struct_idx as TableIndex)) + } else { + let mut type_params = vec![]; + for type_param in &sh.type_parameters { + let abs = type_param.constraints; + assert!(!abs.has_key()); + match (abs.has_copy(), abs.has_drop(), abs.has_store()) { + (false, true, false) => type_params.push(SignatureToken::Signer), + _ => type_params.push(SignatureToken::U64), + } + } + SignatureToken::StructInstantiation(Box::new(( + StructHandleIndex(struct_idx as TableIndex), + type_params, + ))) + } + } + } + Vector(token) => SignatureToken::Vector(Box::new(token.materialize(struct_handles))), + Reference(token) => { + SignatureToken::Reference(Box::new(token.materialize(struct_handles))) + } + MutableReference(token) => { + SignatureToken::MutableReference(Box::new(token.materialize(struct_handles))) + } + TypeParameter(idx) => { + SignatureToken::TypeParameter(idx.index(struct_handles.len()) as TypeParameterIndex) + } + } + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/types.rs b/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/types.rs new file mode 100644 index 000000000..48e8a39c2 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/proptest_types/types.rs @@ -0,0 +1,266 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + file_format::{ + AbilitySet, FieldDefinition, IdentifierIndex, ModuleHandleIndex, SignatureToken, + StructDefinition, StructFieldInformation, StructHandle, StructHandleIndex, + StructTypeParameter, TableIndex, TypeSignature, + }, + internals::ModuleIndex, + proptest_types::{ + prop_index_avoid, + signature::{AbilitySetGen, SignatureTokenGen}, + }, +}; +use proptest::{ + collection::{vec, SizeRange}, + option, + prelude::*, + sample::Index as PropIndex, + std_facade::hash_set::HashSet, +}; +use std::collections::BTreeSet; + +#[derive(Debug)] +struct TypeSignatureIndex(u16); + +#[derive(Debug)] +pub struct StDefnMaterializeState { + pub self_module_handle_idx: ModuleHandleIndex, + pub identifiers_len: usize, + pub struct_handles: Vec, + pub new_handles: BTreeSet<(ModuleHandleIndex, IdentifierIndex)>, +} + +impl StDefnMaterializeState { + pub fn new( + self_module_handle_idx: ModuleHandleIndex, + identifiers_len: usize, + struct_handles: Vec, + ) -> Self { + Self { + self_module_handle_idx, + identifiers_len, + struct_handles, + new_handles: BTreeSet::new(), + } + } + + fn add_struct_handle(&mut self, handle: StructHandle) -> Option { + if self.new_handles.insert((handle.module, handle.name)) { + self.struct_handles.push(handle); + Some(StructHandleIndex((self.struct_handles.len() - 1) as u16)) + } else { + None + } + } + + fn potential_abilities(&self, ty: &SignatureToken) -> AbilitySet { + use SignatureToken::*; + + match ty { + Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address => AbilitySet::PRIMITIVES, + + Reference(_) | MutableReference(_) => AbilitySet::REFERENCES, + Signer => AbilitySet::SIGNER, + TypeParameter(_) => AbilitySet::ALL, + Vector(ty) => { + let inner = self.potential_abilities(ty); + inner.intersect(AbilitySet::VECTOR) + } + Struct(idx) => { + let sh = &self.struct_handles[idx.0 as usize]; + sh.abilities + } + StructInstantiation(struct_inst) => { + let (idx, type_args) = &**struct_inst; + let sh = &self.struct_handles[idx.0 as usize]; + + // Gather the abilities of the type actuals. + let type_args_abilities = type_args.iter().map(|ty| self.potential_abilities(ty)); + type_args_abilities.fold(sh.abilities, |acc, ty_arg_abilities| { + acc.intersect(ty_arg_abilities) + }) + } + } + } +} + +#[derive(Clone, Debug)] +pub struct StructHandleGen { + module_idx: PropIndex, + name_idx: PropIndex, + abilities: AbilitySetGen, + type_parameters: Vec<(AbilitySetGen, bool)>, +} + +impl StructHandleGen { + pub fn strategy(ability_count: impl Into) -> impl Strategy { + let ability_count = ability_count.into(); + ( + any::(), + any::(), + AbilitySetGen::strategy(), + vec((AbilitySetGen::strategy(), any::()), ability_count), + ) + .prop_map(|(module_idx, name_idx, abilities, type_parameters)| Self { + module_idx, + name_idx, + abilities, + type_parameters, + }) + } + + pub fn materialize( + self, + self_module_handle_idx: ModuleHandleIndex, + module_len: usize, + identifiers_len: usize, + ) -> StructHandle { + let idx = prop_index_avoid( + self.module_idx, + self_module_handle_idx.into_index(), + module_len, + ); + let type_parameters = self + .type_parameters + .into_iter() + .map(|(constraints, is_phantom)| StructTypeParameter { + constraints: constraints.materialize(), + is_phantom, + }) + .collect(); + StructHandle { + module: ModuleHandleIndex(idx as TableIndex), + name: IdentifierIndex(self.name_idx.index(identifiers_len) as TableIndex), + abilities: self.abilities.materialize(), + type_parameters, + } + } +} + +#[derive(Clone, Debug)] +pub struct StructDefinitionGen { + name_idx: PropIndex, + abilities: AbilitySetGen, + type_parameters: Vec<(AbilitySetGen, bool)>, + #[allow(dead_code)] + is_public: bool, + field_defs: Option>, +} + +impl StructDefinitionGen { + pub fn strategy( + field_count: impl Into, + type_parameter_count: impl Into, + ) -> impl Strategy { + ( + any::(), + AbilitySetGen::strategy(), + vec( + (AbilitySetGen::strategy(), any::()), + type_parameter_count, + ), + any::(), + option::of(vec(FieldDefinitionGen::strategy(), field_count)), + ) + .prop_map( + |(name_idx, abilities, type_parameters, is_public, field_defs)| Self { + name_idx, + abilities, + type_parameters, + is_public, + field_defs, + }, + ) + } + + pub fn materialize( + self, + state: &mut StDefnMaterializeState, + ) -> (Option, usize) { + let mut field_names = HashSet::new(); + let mut fields = vec![]; + match self.field_defs { + None => (), + Some(field_defs_gen) => { + for fd_gen in field_defs_gen { + let field = fd_gen.materialize(state); + if field_names.insert(field.name) { + fields.push(field); + } + } + } + }; + let abilities = fields + .iter() + .fold(self.abilities.materialize(), |acc, field| { + acc.intersect(state.potential_abilities(&field.signature.0)) + }); + + let type_parameters = self + .type_parameters + .into_iter() + .map(|(constraints, is_phantom)| StructTypeParameter { + constraints: constraints.materialize(), + is_phantom, + }) + .collect(); + let handle = StructHandle { + module: state.self_module_handle_idx, + name: IdentifierIndex(self.name_idx.index(state.identifiers_len) as TableIndex), + abilities, + type_parameters, + }; + match state.add_struct_handle(handle) { + Some(struct_handle) => { + if fields.is_empty() { + ( + Some(StructDefinition { + struct_handle, + field_information: StructFieldInformation::Native, + }), + 0, + ) + } else { + let field_count = fields.len(); + let field_information = StructFieldInformation::Declared(fields); + ( + Some(StructDefinition { + struct_handle, + field_information, + }), + field_count, + ) + } + } + None => (None, 0), + } + } +} + +#[derive(Clone, Debug)] +struct FieldDefinitionGen { + name_idx: PropIndex, + signature_gen: SignatureTokenGen, +} + +impl FieldDefinitionGen { + fn strategy() -> impl Strategy { + (any::(), SignatureTokenGen::atom_strategy()).prop_map( + |(name_idx, signature_gen)| Self { + name_idx, + signature_gen, + }, + ) + } + + fn materialize(self, state: &StDefnMaterializeState) -> FieldDefinition { + FieldDefinition { + name: IdentifierIndex(self.name_idx.index(state.identifiers_len) as TableIndex), + signature: TypeSignature(self.signature_gen.materialize(&state.struct_handles)), + } + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/serializer.rs b/CoqOfRust/move_sui/translations/move_binary_format/serializer.rs new file mode 100644 index 000000000..a72919299 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/serializer.rs @@ -0,0 +1,1376 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! Serialization of transactions and modules. +//! +//! This module exposes two entry points for serialization of `CompiledScript` and +//! `CompiledModule`. The entry points are exposed on the main structs `CompiledScript` and +//! `CompiledModule`. +//! +//! **Versioning** +//! +//! A note about versioning. The serializer supports writing file_format versions >= v5. The +//! entry points get the version number passed in and generate compatible formats. However, +//! not all of the newer language constructs might be supported for older versions, leading to +//! serialization errors. + +use crate::{file_format::*, file_format_common::*}; +use anyhow::{anyhow, bail, Result}; +use move_core_types::{ + account_address::AccountAddress, identifier::Identifier, metadata::Metadata, +}; + +fn write_as_uleb128(binary: &mut BinaryData, x: T1, max: T2) -> Result<()> +where + T1: Into, + T2: Into, +{ + let x: u64 = x.into(); + let max: u64 = max.into(); + if x > max { + bail!("value ({}) cannot exceed ({})", x, max) + } + write_u64_as_uleb128(binary, x) +} + +fn serialize_signature_index(binary: &mut BinaryData, idx: &SignatureIndex) -> Result<()> { + write_as_uleb128(binary, idx.0, SIGNATURE_INDEX_MAX) +} + +fn serialize_module_handle_index(binary: &mut BinaryData, idx: &ModuleHandleIndex) -> Result<()> { + write_as_uleb128(binary, idx.0, MODULE_HANDLE_INDEX_MAX) +} + +fn serialize_identifier_index(binary: &mut BinaryData, idx: &IdentifierIndex) -> Result<()> { + write_as_uleb128(binary, idx.0, IDENTIFIER_INDEX_MAX) +} + +fn serialize_struct_handle_index(binary: &mut BinaryData, idx: &StructHandleIndex) -> Result<()> { + write_as_uleb128(binary, idx.0, STRUCT_HANDLE_INDEX_MAX) +} + +fn serialize_address_identifier_index( + binary: &mut BinaryData, + idx: &AddressIdentifierIndex, +) -> Result<()> { + write_as_uleb128(binary, idx.0, ADDRESS_INDEX_MAX) +} + +fn serialize_struct_def_index(binary: &mut BinaryData, idx: &StructDefinitionIndex) -> Result<()> { + write_as_uleb128(binary, idx.0, STRUCT_DEF_INDEX_MAX) +} + +fn serialize_function_handle_index( + binary: &mut BinaryData, + idx: &FunctionHandleIndex, +) -> Result<()> { + write_as_uleb128(binary, idx.0, FUNCTION_HANDLE_INDEX_MAX) +} + +fn serialize_field_handle_index(binary: &mut BinaryData, idx: &FieldHandleIndex) -> Result<()> { + write_as_uleb128(binary, idx.0, FIELD_HANDLE_INDEX_MAX) +} + +fn serialize_field_inst_index( + binary: &mut BinaryData, + idx: &FieldInstantiationIndex, +) -> Result<()> { + write_as_uleb128(binary, idx.0, FIELD_INST_INDEX_MAX) +} + +fn serialize_function_inst_index( + binary: &mut BinaryData, + idx: &FunctionInstantiationIndex, +) -> Result<()> { + write_as_uleb128(binary, idx.0, FUNCTION_INST_INDEX_MAX) +} + +fn serialize_struct_def_inst_index( + binary: &mut BinaryData, + idx: &StructDefInstantiationIndex, +) -> Result<()> { + write_as_uleb128(binary, idx.0, STRUCT_DEF_INST_INDEX_MAX) +} + +fn seiralize_table_offset(binary: &mut BinaryData, offset: u32) -> Result<()> { + write_as_uleb128(binary, offset, TABLE_OFFSET_MAX) +} + +fn serialize_table_size(binary: &mut BinaryData, size: u32) -> Result<()> { + write_as_uleb128(binary, size, TABLE_SIZE_MAX) +} + +fn serialize_constant_pool_index(binary: &mut BinaryData, idx: &ConstantPoolIndex) -> Result<()> { + write_as_uleb128(binary, idx.0, CONSTANT_INDEX_MAX) +} + +fn serialize_bytecode_count(binary: &mut BinaryData, len: usize) -> Result<()> { + write_as_uleb128(binary, len as u64, BYTECODE_COUNT_MAX) +} + +fn serialize_identifier_size(binary: &mut BinaryData, len: usize) -> Result<()> { + write_as_uleb128(binary, len as u64, IDENTIFIER_SIZE_MAX) +} + +fn serialize_constant_size(binary: &mut BinaryData, len: usize) -> Result<()> { + write_as_uleb128(binary, len as u64, CONSTANT_SIZE_MAX) +} + +fn serialize_metadata_key_size(binary: &mut BinaryData, len: usize) -> Result<()> { + write_as_uleb128(binary, len as u64, METADATA_KEY_SIZE_MAX) +} + +fn serialize_metadata_value_size(binary: &mut BinaryData, len: usize) -> Result<()> { + write_as_uleb128(binary, len as u64, METADATA_VALUE_SIZE_MAX) +} + +fn serialize_field_count(binary: &mut BinaryData, len: usize) -> Result<()> { + write_as_uleb128(binary, len as u64, FIELD_COUNT_MAX) +} + +fn serialize_field_offset(binary: &mut BinaryData, offset: u16) -> Result<()> { + write_as_uleb128(binary, offset, FIELD_OFFSET_MAX) +} + +fn serialize_acquires_count(binary: &mut BinaryData, len: usize) -> Result<()> { + write_as_uleb128(binary, len as u64, ACQUIRES_COUNT_MAX) +} + +fn serialize_signature_size(binary: &mut BinaryData, len: usize) -> Result<()> { + write_as_uleb128(binary, len as u64, SIGNATURE_SIZE_MAX) +} + +fn serialize_type_parameter_index(binary: &mut BinaryData, idx: u16) -> Result<()> { + write_as_uleb128(binary, idx, TYPE_PARAMETER_INDEX_MAX) +} + +fn serialize_type_parameter_count(binary: &mut BinaryData, len: usize) -> Result<()> { + write_as_uleb128(binary, len as u64, TYPE_PARAMETER_COUNT_MAX) +} + +fn serialize_bytecode_offset(binary: &mut BinaryData, offset: u16) -> Result<()> { + write_as_uleb128(binary, offset, BYTECODE_INDEX_MAX) +} + +fn serialize_table_count(binary: &mut BinaryData, len: u8) -> Result<()> { + write_as_uleb128(binary, len, TABLE_COUNT_MAX) +} + +fn serialize_local_index(binary: &mut BinaryData, idx: u8) -> Result<()> { + write_as_uleb128(binary, idx, LOCAL_INDEX_MAX) +} + +fn validate_version(version: u32) -> Result<()> { + if !(VERSION_MIN..=VERSION_MAX).contains(&version) { + bail!( + "The requested bytecode version {} is not supported. Only {} to {} are.", + version, + VERSION_MIN, + VERSION_MAX + ) + } else { + Ok(()) + } +} + +impl CompiledModule { + /// Serializes a `CompiledModule` into a binary. The mutable `Vec` will contain the + /// binary blob on return. + pub fn serialize(&self, binary: &mut Vec) -> Result<()> { + self.serialize_for_version(None, binary) + } + + /// Serialize into binary, at given version. + pub fn serialize_for_version( + &self, + bytecode_version: Option, + binary: &mut Vec, + ) -> Result<()> { + let version = bytecode_version.unwrap_or(VERSION_MAX); + validate_version(version)?; + let mut binary_data = BinaryData::from(binary.clone()); + let mut ser = ModuleSerializer::new(version); + let mut temp = BinaryData::new(); + ser.serialize_tables(&mut temp, self)?; + if temp.len() > u32::max_value() as usize { + bail!( + "table content size ({}) cannot exceed ({})", + temp.len(), + u32::max_value() + ); + } + ser.common.serialize_header(&mut binary_data)?; + ser.serialize_table_indices(&mut binary_data)?; + + binary_data.extend(temp.as_inner())?; + + serialize_module_handle_index(&mut binary_data, &self.self_module_handle_idx)?; + + *binary = binary_data.into_inner(); + Ok(()) + } +} + +/// Holds data to compute the header of a generic binary. +/// +/// A binary header contains information about the tables serialized. +/// The serializer needs to serialize the tables in order to compute the offset and size +/// of each table. +/// `CommonSerializer` keeps track of the tables common to `CompiledScript` and +/// `CompiledModule`. +#[derive(Debug)] +struct CommonSerializer { + major_version: u32, + table_count: u8, + module_handles: (u32, u32), + struct_handles: (u32, u32), + function_handles: (u32, u32), + function_instantiations: (u32, u32), + signatures: (u32, u32), + identifiers: (u32, u32), + address_identifiers: (u32, u32), + constant_pool: (u32, u32), + metadata: (u32, u32), +} + +/// Holds data to compute the header of a module binary. +#[derive(Debug)] +struct ModuleSerializer { + common: CommonSerializer, + struct_defs: (u32, u32), + struct_def_instantiations: (u32, u32), + function_defs: (u32, u32), + field_handles: (u32, u32), + field_instantiations: (u32, u32), + friend_decls: (u32, u32), +} + +// +// Helpers +// +fn check_index_in_binary(index: usize) -> Result { + if index > u32::max_value() as usize { + bail!( + "Compilation unit too big ({}) cannot exceed {}", + index, + u32::max_value() + ) + } + Ok(index as u32) +} + +fn serialize_table_index( + binary: &mut BinaryData, + kind: TableType, + offset: u32, + count: u32, +) -> Result<()> { + if count != 0 { + binary.push(kind as u8)?; + seiralize_table_offset(binary, offset)?; + serialize_table_size(binary, count)?; + } + Ok(()) +} + +fn serialize_magic(binary: &mut BinaryData) -> Result<()> { + for byte in &BinaryConstants::MOVE_MAGIC { + binary.push(*byte)?; + } + Ok(()) +} + +/// Trait to access tables for both `CompiledScript` and `CompiledModule`, +/// used by `CommonSerializer`. +trait CommonTables { + fn get_module_handles(&self) -> &[ModuleHandle]; + fn get_struct_handles(&self) -> &[StructHandle]; + fn get_function_handles(&self) -> &[FunctionHandle]; + fn get_function_instantiations(&self) -> &[FunctionInstantiation]; + fn get_identifiers(&self) -> &[Identifier]; + fn get_address_identifiers(&self) -> &[AccountAddress]; + fn get_constant_pool(&self) -> &[Constant]; + fn get_signatures(&self) -> &[Signature]; + fn get_metadata(&self) -> &[Metadata]; +} + +impl CommonTables for CompiledModule { + fn get_module_handles(&self) -> &[ModuleHandle] { + &self.module_handles + } + + fn get_struct_handles(&self) -> &[StructHandle] { + &self.struct_handles + } + + fn get_function_handles(&self) -> &[FunctionHandle] { + &self.function_handles + } + + fn get_function_instantiations(&self) -> &[FunctionInstantiation] { + &self.function_instantiations + } + + fn get_identifiers(&self) -> &[Identifier] { + &self.identifiers + } + + fn get_address_identifiers(&self) -> &[AccountAddress] { + &self.address_identifiers + } + + fn get_constant_pool(&self) -> &[Constant] { + &self.constant_pool + } + + fn get_signatures(&self) -> &[Signature] { + &self.signatures + } + + fn get_metadata(&self) -> &[Metadata] { + &self.metadata + } +} + +/// Serializes a `ModuleHandle`. +/// +/// A `ModuleHandle` gets serialized as follows: +/// - `ModuleHandle.address` as a ULEB128 (index into the `AddressPool`) +/// - `ModuleHandle.name` as a ULEB128 (index into the `IdentifierPool`) +fn serialize_module_handle(binary: &mut BinaryData, module_handle: &ModuleHandle) -> Result<()> { + serialize_address_identifier_index(binary, &module_handle.address)?; + serialize_identifier_index(binary, &module_handle.name)?; + Ok(()) +} + +/// Serializes a `StructHandle`. +/// +/// A `StructHandle` gets serialized as follows: +/// - `StructHandle.module` as a ULEB128 (index into the `ModuleHandle` table) +/// - `StructHandle.name` as a ULEB128 (index into the `IdentifierPool`) +/// - `StructHandle.is_nominal_resource` as a 1 byte boolean (0 for false, 1 for true) +fn serialize_struct_handle(binary: &mut BinaryData, struct_handle: &StructHandle) -> Result<()> { + serialize_module_handle_index(binary, &struct_handle.module)?; + serialize_identifier_index(binary, &struct_handle.name)?; + serialize_ability_set(binary, struct_handle.abilities)?; + serialize_type_parameters(binary, &struct_handle.type_parameters) +} + +fn serialize_type_parameters( + binary: &mut BinaryData, + type_parameters: &[StructTypeParameter], +) -> Result<()> { + serialize_type_parameter_count(binary, type_parameters.len())?; + for type_param in type_parameters { + serialize_type_parameter(binary, type_param)?; + } + Ok(()) +} + +fn serialize_type_parameter( + binary: &mut BinaryData, + type_param: &StructTypeParameter, +) -> Result<()> { + serialize_ability_set(binary, type_param.constraints)?; + write_as_uleb128(binary, type_param.is_phantom as u8, 1u64) +} + +/// Serializes a `FunctionHandle`. +/// +/// A `FunctionHandle` gets serialized as follows: +/// - `FunctionHandle.module` as a ULEB128 (index into the `ModuleHandle` table) +/// - `FunctionHandle.name` as a ULEB128 (index into the `IdentifierPool`) +/// - `FunctionHandle.parameters` as a ULEB128 (index into the `SignaturePool`) +/// - `FunctionHandle.return_` as a ULEB128 (index into the `SignaturePool`) +/// - `FunctionHandle.type_parameters` as a `Vec` +fn serialize_function_handle( + binary: &mut BinaryData, + function_handle: &FunctionHandle, +) -> Result<()> { + serialize_module_handle_index(binary, &function_handle.module)?; + serialize_identifier_index(binary, &function_handle.name)?; + serialize_signature_index(binary, &function_handle.parameters)?; + serialize_signature_index(binary, &function_handle.return_)?; + serialize_ability_sets(binary, &function_handle.type_parameters) +} + +fn serialize_function_instantiation( + binary: &mut BinaryData, + func_inst: &FunctionInstantiation, +) -> Result<()> { + serialize_function_handle_index(binary, &func_inst.handle)?; + serialize_signature_index(binary, &func_inst.type_parameters)?; + Ok(()) +} + +/// Serializes a string (identifier or user string). +/// +/// A `String` gets serialized as follows: +/// - `String` size as a ULEB128 +/// - `String` bytes - *exact format to be defined, Rust utf8 right now* +fn serialize_identifier(binary: &mut BinaryData, string: &str) -> Result<()> { + let bytes = string.as_bytes(); + serialize_identifier_size(binary, bytes.len())?; + for byte in bytes { + binary.push(*byte)?; + } + Ok(()) +} + +/// Serializes an `AccountAddress`. +/// +/// A `AccountAddress` gets serialized as follows: +/// - 32 bytes in increasing index order +fn serialize_address(binary: &mut BinaryData, address: &AccountAddress) -> Result<()> { + for byte in address.as_ref() { + binary.push(*byte)?; + } + Ok(()) +} + +/// Serializes a `Constant`. +/// +/// A `Constant` gets serialized as follows: +/// - `type_` serialized (see `serialize_signature_token`) +/// - `data` size as a ULEB128 +/// - `data` bytes in increasing index order +fn serialize_constant(binary: &mut BinaryData, constant: &Constant) -> Result<()> { + serialize_signature_token(binary, &constant.type_)?; + serialize_byte_blob(binary, serialize_constant_size, &constant.data) +} + +/// Serialize a metadata entry. +fn serialize_metadata_entry(binary: &mut BinaryData, metadata: &Metadata) -> Result<()> { + serialize_byte_blob(binary, serialize_metadata_key_size, &metadata.key)?; + serialize_byte_blob(binary, serialize_metadata_value_size, &metadata.value) +} + +/// Serialize a byte blob. +fn serialize_byte_blob( + binary: &mut BinaryData, + size_serializer: impl Fn(&mut BinaryData, usize) -> Result<()>, + blob: &[u8], +) -> Result<()> { + size_serializer(binary, blob.len())?; + for byte in blob { + binary.push(*byte)?; + } + Ok(()) +} + +/// Serializes a `StructDefinition`. +/// +/// A `StructDefinition` gets serialized as follows: +/// - `StructDefinition.handle` as a ULEB128 (index into the `ModuleHandle` table) +/// - `StructDefinition.field_count` as a ULEB128 (number of fields defined in the type) +/// - `StructDefinition.fields` as a ULEB128 (index into the `FieldDefinition` table) +fn serialize_struct_definition( + binary: &mut BinaryData, + struct_definition: &StructDefinition, +) -> Result<()> { + serialize_struct_handle_index(binary, &struct_definition.struct_handle)?; + match &struct_definition.field_information { + StructFieldInformation::Native => binary.push(SerializedNativeStructFlag::NATIVE as u8), + StructFieldInformation::Declared(fields) => { + binary.push(SerializedNativeStructFlag::DECLARED as u8)?; + serialize_field_definitions(binary, fields) + } + } +} + +fn serialize_struct_def_instantiation( + binary: &mut BinaryData, + struct_inst: &StructDefInstantiation, +) -> Result<()> { + serialize_struct_def_index(binary, &struct_inst.def)?; + serialize_signature_index(binary, &struct_inst.type_parameters)?; + Ok(()) +} + +/// Serializes `FieldDefinition` within a struct. +fn serialize_field_definitions(binary: &mut BinaryData, fields: &[FieldDefinition]) -> Result<()> { + serialize_field_count(binary, fields.len())?; + for field_definition in fields { + serialize_field_definition(binary, field_definition)?; + } + Ok(()) +} + +/// Serializes a `FieldDefinition`. +/// +/// A `FieldDefinition` gets serialized as follows: +/// - `FieldDefinition.struct_` as a ULEB128 (index into the `StructHandle` table) +/// - `StructDefinition.name` as a ULEB128 (index into the `IdentifierPool` table) +/// - `StructDefinition.signature` a serialized `TypeSignatureToekn`) +fn serialize_field_definition( + binary: &mut BinaryData, + field_definition: &FieldDefinition, +) -> Result<()> { + serialize_identifier_index(binary, &field_definition.name)?; + serialize_signature_token(binary, &field_definition.signature.0) +} + +fn serialize_field_handle(binary: &mut BinaryData, field_handle: &FieldHandle) -> Result<()> { + serialize_struct_def_index(binary, &field_handle.owner)?; + serialize_field_offset(binary, field_handle.field)?; + Ok(()) +} + +fn serialize_field_instantiation( + binary: &mut BinaryData, + field_inst: &FieldInstantiation, +) -> Result<()> { + serialize_field_handle_index(binary, &field_inst.handle)?; + serialize_signature_index(binary, &field_inst.type_parameters)?; + Ok(()) +} + +/// Serializes a `Vec`. +fn serialize_acquires(binary: &mut BinaryData, indices: &[StructDefinitionIndex]) -> Result<()> { + serialize_acquires_count(binary, indices.len())?; + for def_idx in indices { + serialize_struct_def_index(binary, def_idx)?; + } + Ok(()) +} + +/// Serializes a `Signature`. +/// +/// A `Signature` gets serialized as follows the vector of `SignatureToken`s for locals +fn serialize_signature(binary: &mut BinaryData, signature: &Signature) -> Result<()> { + serialize_signature_tokens(binary, &signature.0) +} + +/// Serializes a slice of `SignatureToken`s. +fn serialize_signature_tokens(binary: &mut BinaryData, tokens: &[SignatureToken]) -> Result<()> { + serialize_signature_size(binary, tokens.len())?; + for token in tokens { + serialize_signature_token(binary, token)?; + } + Ok(()) +} + +fn serialize_signature_token_single_node_impl( + binary: &mut BinaryData, + token: &SignatureToken, +) -> Result<()> { + match token { + SignatureToken::Bool => binary.push(SerializedType::BOOL as u8)?, + SignatureToken::U8 => binary.push(SerializedType::U8 as u8)?, + SignatureToken::U16 => binary.push(SerializedType::U16 as u8)?, + SignatureToken::U32 => binary.push(SerializedType::U32 as u8)?, + SignatureToken::U64 => binary.push(SerializedType::U64 as u8)?, + SignatureToken::U128 => binary.push(SerializedType::U128 as u8)?, + SignatureToken::U256 => binary.push(SerializedType::U256 as u8)?, + SignatureToken::Address => binary.push(SerializedType::ADDRESS as u8)?, + SignatureToken::Signer => binary.push(SerializedType::SIGNER as u8)?, + SignatureToken::Vector(_) => { + binary.push(SerializedType::VECTOR as u8)?; + } + SignatureToken::Struct(idx) => { + binary.push(SerializedType::STRUCT as u8)?; + serialize_struct_handle_index(binary, idx)?; + } + SignatureToken::StructInstantiation(struct_inst) => { + let (idx, type_params) = &**struct_inst; + binary.push(SerializedType::STRUCT_INST as u8)?; + serialize_struct_handle_index(binary, idx)?; + serialize_signature_size(binary, type_params.len())?; + } + SignatureToken::Reference(_) => { + binary.push(SerializedType::REFERENCE as u8)?; + } + SignatureToken::MutableReference(_) => { + binary.push(SerializedType::MUTABLE_REFERENCE as u8)?; + } + SignatureToken::TypeParameter(idx) => { + binary.push(SerializedType::TYPE_PARAMETER as u8)?; + serialize_type_parameter_index(binary, *idx)?; + } + } + Ok(()) +} + +#[cfg(test)] +pub(crate) fn serialize_signature_token_unchecked( + binary: &mut BinaryData, + token: &SignatureToken, +) -> Result<()> { + for token in token.preorder_traversal() { + serialize_signature_token_single_node_impl(binary, token)?; + } + Ok(()) +} + +/// Serializes a `SignatureToken`. +/// +/// A `SignatureToken` gets serialized as a variable size blob depending on composition. +/// Values for types are defined in `SerializedType`. +pub(crate) fn serialize_signature_token( + binary: &mut BinaryData, + token: &SignatureToken, +) -> Result<()> { + // Non-recursive implementation to avoid overflowing the stack. + for (token, depth) in token.preorder_traversal_with_depth() { + if depth > SIGNATURE_TOKEN_DEPTH_MAX { + bail!("max recursion depth reached") + } + serialize_signature_token_single_node_impl(binary, token)?; + } + Ok(()) +} + +fn serialize_ability_set(binary: &mut BinaryData, set: AbilitySet) -> Result<()> { + write_as_uleb128(binary, set.into_u8(), AbilitySet::ALL.into_u8())?; + Ok(()) +} + +fn serialize_ability_sets(binary: &mut BinaryData, sets: &[AbilitySet]) -> Result<()> { + serialize_type_parameter_count(binary, sets.len())?; + for set in sets { + serialize_ability_set(binary, *set)?; + } + Ok(()) +} + +/// Serializes a `CodeUnit`. +/// +/// A `CodeUnit` is serialized as the code field of a `FunctionDefinition`. +/// A `CodeUnit` gets serialized as follows: +/// - `CodeUnit.max_stack_size` as a ULEB128 +/// - `CodeUnit.locals` as a ULEB128 (index into the `LocalSignaturePool`) +/// - `CodeUnit.code` as variable size byte stream for the bytecode +fn serialize_code_unit(major_version: u32, binary: &mut BinaryData, code: &CodeUnit) -> Result<()> { + serialize_signature_index(binary, &code.locals)?; + serialize_code(major_version, binary, &code.code) +} + +/// Serializes a single `Bytecode` instruction. +fn serialize_instruction_inner( + major_version: u32, + binary: &mut BinaryData, + opcode: &Bytecode, +) -> Result<()> { + match opcode { + Bytecode::LdU16(_) + | Bytecode::LdU32(_) + | Bytecode::LdU256(_) + | Bytecode::CastU16 + | Bytecode::CastU32 + | Bytecode::CastU256 + if (major_version < VERSION_6) => + { + return Err(anyhow!( + "Loading or casting u16, u32, u256 integers not supported in bytecode version {}", + major_version + )); + } + _ => (), + }; + + let res = match opcode { + Bytecode::FreezeRef => binary.push(Opcodes::FREEZE_REF as u8), + Bytecode::Pop => binary.push(Opcodes::POP as u8), + Bytecode::Ret => binary.push(Opcodes::RET as u8), + Bytecode::BrTrue(code_offset) => { + binary.push(Opcodes::BR_TRUE as u8)?; + serialize_bytecode_offset(binary, *code_offset) + } + Bytecode::BrFalse(code_offset) => { + binary.push(Opcodes::BR_FALSE as u8)?; + serialize_bytecode_offset(binary, *code_offset) + } + Bytecode::Branch(code_offset) => { + binary.push(Opcodes::BRANCH as u8)?; + serialize_bytecode_offset(binary, *code_offset) + } + Bytecode::LdU8(value) => { + binary.push(Opcodes::LD_U8 as u8)?; + binary.push(*value) + } + Bytecode::LdU64(value) => { + binary.push(Opcodes::LD_U64 as u8)?; + write_u64(binary, *value) + } + Bytecode::LdU128(value) => { + binary.push(Opcodes::LD_U128 as u8)?; + write_u128(binary, **value) + } + Bytecode::CastU8 => binary.push(Opcodes::CAST_U8 as u8), + Bytecode::CastU64 => binary.push(Opcodes::CAST_U64 as u8), + Bytecode::CastU128 => binary.push(Opcodes::CAST_U128 as u8), + Bytecode::LdConst(const_idx) => { + binary.push(Opcodes::LD_CONST as u8)?; + serialize_constant_pool_index(binary, const_idx) + } + Bytecode::LdTrue => binary.push(Opcodes::LD_TRUE as u8), + Bytecode::LdFalse => binary.push(Opcodes::LD_FALSE as u8), + Bytecode::CopyLoc(local_idx) => { + binary.push(Opcodes::COPY_LOC as u8)?; + serialize_local_index(binary, *local_idx) + } + Bytecode::MoveLoc(local_idx) => { + binary.push(Opcodes::MOVE_LOC as u8)?; + serialize_local_index(binary, *local_idx) + } + Bytecode::StLoc(local_idx) => { + binary.push(Opcodes::ST_LOC as u8)?; + serialize_local_index(binary, *local_idx) + } + Bytecode::MutBorrowLoc(local_idx) => { + binary.push(Opcodes::MUT_BORROW_LOC as u8)?; + serialize_local_index(binary, *local_idx) + } + Bytecode::ImmBorrowLoc(local_idx) => { + binary.push(Opcodes::IMM_BORROW_LOC as u8)?; + serialize_local_index(binary, *local_idx) + } + Bytecode::MutBorrowField(field_idx) => { + binary.push(Opcodes::MUT_BORROW_FIELD as u8)?; + serialize_field_handle_index(binary, field_idx) + } + Bytecode::MutBorrowFieldGeneric(field_idx) => { + binary.push(Opcodes::MUT_BORROW_FIELD_GENERIC as u8)?; + serialize_field_inst_index(binary, field_idx) + } + Bytecode::ImmBorrowField(field_idx) => { + binary.push(Opcodes::IMM_BORROW_FIELD as u8)?; + serialize_field_handle_index(binary, field_idx) + } + Bytecode::ImmBorrowFieldGeneric(field_idx) => { + binary.push(Opcodes::IMM_BORROW_FIELD_GENERIC as u8)?; + serialize_field_inst_index(binary, field_idx) + } + Bytecode::Call(method_idx) => { + binary.push(Opcodes::CALL as u8)?; + serialize_function_handle_index(binary, method_idx) + } + Bytecode::Pack(class_idx) => { + binary.push(Opcodes::PACK as u8)?; + serialize_struct_def_index(binary, class_idx) + } + Bytecode::Unpack(class_idx) => { + binary.push(Opcodes::UNPACK as u8)?; + serialize_struct_def_index(binary, class_idx) + } + Bytecode::CallGeneric(method_idx) => { + binary.push(Opcodes::CALL_GENERIC as u8)?; + serialize_function_inst_index(binary, method_idx) + } + Bytecode::PackGeneric(class_idx) => { + binary.push(Opcodes::PACK_GENERIC as u8)?; + serialize_struct_def_inst_index(binary, class_idx) + } + Bytecode::UnpackGeneric(class_idx) => { + binary.push(Opcodes::UNPACK_GENERIC as u8)?; + serialize_struct_def_inst_index(binary, class_idx) + } + Bytecode::ReadRef => binary.push(Opcodes::READ_REF as u8), + Bytecode::WriteRef => binary.push(Opcodes::WRITE_REF as u8), + Bytecode::Add => binary.push(Opcodes::ADD as u8), + Bytecode::Sub => binary.push(Opcodes::SUB as u8), + Bytecode::Mul => binary.push(Opcodes::MUL as u8), + Bytecode::Mod => binary.push(Opcodes::MOD as u8), + Bytecode::Div => binary.push(Opcodes::DIV as u8), + Bytecode::BitOr => binary.push(Opcodes::BIT_OR as u8), + Bytecode::BitAnd => binary.push(Opcodes::BIT_AND as u8), + Bytecode::Xor => binary.push(Opcodes::XOR as u8), + Bytecode::Shl => binary.push(Opcodes::SHL as u8), + Bytecode::Shr => binary.push(Opcodes::SHR as u8), + Bytecode::Or => binary.push(Opcodes::OR as u8), + Bytecode::And => binary.push(Opcodes::AND as u8), + Bytecode::Not => binary.push(Opcodes::NOT as u8), + Bytecode::Eq => binary.push(Opcodes::EQ as u8), + Bytecode::Neq => binary.push(Opcodes::NEQ as u8), + Bytecode::Lt => binary.push(Opcodes::LT as u8), + Bytecode::Gt => binary.push(Opcodes::GT as u8), + Bytecode::Le => binary.push(Opcodes::LE as u8), + Bytecode::Ge => binary.push(Opcodes::GE as u8), + Bytecode::Abort => binary.push(Opcodes::ABORT as u8), + Bytecode::Nop => binary.push(Opcodes::NOP as u8), + Bytecode::ExistsDeprecated(class_idx) => { + binary.push(Opcodes::EXISTS_DEPRECATED as u8)?; + serialize_struct_def_index(binary, class_idx) + } + Bytecode::MutBorrowGlobalDeprecated(class_idx) => { + binary.push(Opcodes::MUT_BORROW_GLOBAL_DEPRECATED as u8)?; + serialize_struct_def_index(binary, class_idx) + } + Bytecode::ImmBorrowGlobalDeprecated(class_idx) => { + binary.push(Opcodes::IMM_BORROW_GLOBAL_DEPRECATED as u8)?; + serialize_struct_def_index(binary, class_idx) + } + Bytecode::MoveFromDeprecated(class_idx) => { + binary.push(Opcodes::MOVE_FROM_DEPRECATED as u8)?; + serialize_struct_def_index(binary, class_idx) + } + Bytecode::MoveToDeprecated(class_idx) => { + binary.push(Opcodes::MOVE_TO_DEPRECATED as u8)?; + serialize_struct_def_index(binary, class_idx) + } + Bytecode::ExistsGenericDeprecated(class_idx) => { + binary.push(Opcodes::EXISTS_GENERIC_DEPRECATED as u8)?; + serialize_struct_def_inst_index(binary, class_idx) + } + Bytecode::MutBorrowGlobalGenericDeprecated(class_idx) => { + binary.push(Opcodes::MUT_BORROW_GLOBAL_GENERIC_DEPRECATED as u8)?; + serialize_struct_def_inst_index(binary, class_idx) + } + Bytecode::ImmBorrowGlobalGenericDeprecated(class_idx) => { + binary.push(Opcodes::IMM_BORROW_GLOBAL_GENERIC_DEPRECATED as u8)?; + serialize_struct_def_inst_index(binary, class_idx) + } + Bytecode::MoveFromGenericDeprecated(class_idx) => { + binary.push(Opcodes::MOVE_FROM_GENERIC_DEPRECATED as u8)?; + serialize_struct_def_inst_index(binary, class_idx) + } + Bytecode::MoveToGenericDeprecated(class_idx) => { + binary.push(Opcodes::MOVE_TO_GENERIC_DEPRECATED as u8)?; + serialize_struct_def_inst_index(binary, class_idx) + } + Bytecode::VecPack(sig_idx, num) => { + binary.push(Opcodes::VEC_PACK as u8)?; + serialize_signature_index(binary, sig_idx)?; + write_u64(binary, *num) + } + Bytecode::VecLen(sig_idx) => { + binary.push(Opcodes::VEC_LEN as u8)?; + serialize_signature_index(binary, sig_idx) + } + Bytecode::VecImmBorrow(sig_idx) => { + binary.push(Opcodes::VEC_IMM_BORROW as u8)?; + serialize_signature_index(binary, sig_idx) + } + Bytecode::VecMutBorrow(sig_idx) => { + binary.push(Opcodes::VEC_MUT_BORROW as u8)?; + serialize_signature_index(binary, sig_idx) + } + Bytecode::VecPushBack(sig_idx) => { + binary.push(Opcodes::VEC_PUSH_BACK as u8)?; + serialize_signature_index(binary, sig_idx) + } + Bytecode::VecPopBack(sig_idx) => { + binary.push(Opcodes::VEC_POP_BACK as u8)?; + serialize_signature_index(binary, sig_idx) + } + Bytecode::VecUnpack(sig_idx, num) => { + binary.push(Opcodes::VEC_UNPACK as u8)?; + serialize_signature_index(binary, sig_idx)?; + write_u64(binary, *num) + } + Bytecode::VecSwap(sig_idx) => { + binary.push(Opcodes::VEC_SWAP as u8)?; + serialize_signature_index(binary, sig_idx) + } + Bytecode::LdU16(value) => { + binary.push(Opcodes::LD_U16 as u8)?; + write_u16(binary, *value) + } + Bytecode::LdU32(value) => { + binary.push(Opcodes::LD_U32 as u8)?; + write_u32(binary, *value) + } + Bytecode::LdU256(value) => { + binary.push(Opcodes::LD_U256 as u8)?; + write_u256(binary, **value) + } + Bytecode::CastU16 => binary.push(Opcodes::CAST_U16 as u8), + Bytecode::CastU32 => binary.push(Opcodes::CAST_U32 as u8), + Bytecode::CastU256 => binary.push(Opcodes::CAST_U256 as u8), + }; + res?; + Ok(()) +} + +/// Serializes a `Bytecode` stream. Serialization of the function body. +fn serialize_code(major_version: u32, binary: &mut BinaryData, code: &[Bytecode]) -> Result<()> { + serialize_bytecode_count(binary, code.len())?; + for opcode in code { + serialize_instruction_inner(major_version, binary, opcode)?; + } + Ok(()) +} + +/// Compute the table size with a check for underflow +fn checked_calculate_table_size(binary: &mut BinaryData, start: u32) -> Result { + let offset = check_index_in_binary(binary.len())?; + assert!(offset >= start, "table start must be before end"); + Ok(offset - start) +} + +impl CommonSerializer { + pub fn new(major_version: u32) -> CommonSerializer { + CommonSerializer { + major_version, + table_count: 0, + module_handles: (0, 0), + struct_handles: (0, 0), + function_handles: (0, 0), + function_instantiations: (0, 0), + signatures: (0, 0), + identifiers: (0, 0), + address_identifiers: (0, 0), + constant_pool: (0, 0), + metadata: (0, 0), + } + } + + fn serialize_header(&mut self, binary: &mut BinaryData) -> Result<()> { + serialize_magic(binary)?; + write_u32(binary, self.major_version)?; + Ok(()) + } + + /// Common binary header serialization. + fn serialize_table_indices(&mut self, binary: &mut BinaryData) -> Result<()> { + serialize_table_count(binary, self.table_count)?; + + serialize_table_index( + binary, + TableType::MODULE_HANDLES, + self.module_handles.0, + self.module_handles.1, + )?; + serialize_table_index( + binary, + TableType::STRUCT_HANDLES, + self.struct_handles.0, + self.struct_handles.1, + )?; + serialize_table_index( + binary, + TableType::FUNCTION_HANDLES, + self.function_handles.0, + self.function_handles.1, + )?; + serialize_table_index( + binary, + TableType::FUNCTION_INST, + self.function_instantiations.0, + self.function_instantiations.1, + )?; + serialize_table_index( + binary, + TableType::SIGNATURES, + self.signatures.0, + self.signatures.1, + )?; + serialize_table_index( + binary, + TableType::IDENTIFIERS, + self.identifiers.0, + self.identifiers.1, + )?; + serialize_table_index( + binary, + TableType::ADDRESS_IDENTIFIERS, + self.address_identifiers.0, + self.address_identifiers.1, + )?; + serialize_table_index( + binary, + TableType::CONSTANT_POOL, + self.constant_pool.0, + self.constant_pool.1, + )?; + if self.major_version >= VERSION_5 { + // Metadata was not introduced before v5, so do not generate it for lower versions. + serialize_table_index( + binary, + TableType::METADATA, + self.metadata.0, + self.metadata.1, + )?; + } + Ok(()) + } + + fn serialize_common_tables( + &mut self, + binary: &mut BinaryData, + tables: &T, + ) -> Result<()> { + debug_assert!(self.table_count == 0); + self.serialize_module_handles(binary, tables.get_module_handles())?; + self.serialize_struct_handles(binary, tables.get_struct_handles())?; + self.serialize_function_handles(binary, tables.get_function_handles())?; + debug_assert!(self.table_count < 6); + self.serialize_function_instantiations(binary, tables.get_function_instantiations())?; + self.serialize_signatures(binary, tables.get_signatures())?; + self.serialize_identifiers(binary, tables.get_identifiers())?; + self.serialize_address_identifiers(binary, tables.get_address_identifiers())?; + self.serialize_constants(binary, tables.get_constant_pool())?; + if self.major_version >= VERSION_5 { + self.serialize_metadata(binary, tables.get_metadata())?; + } + Ok(()) + } + + /// Serializes `ModuleHandle` table. + fn serialize_module_handles( + &mut self, + binary: &mut BinaryData, + module_handles: &[ModuleHandle], + ) -> Result<()> { + if !module_handles.is_empty() { + self.table_count += 1; + self.module_handles.0 = check_index_in_binary(binary.len())?; + for module_handle in module_handles { + serialize_module_handle(binary, module_handle)?; + } + self.module_handles.1 = checked_calculate_table_size(binary, self.module_handles.0)?; + } + Ok(()) + } + + /// Serializes `StructHandle` table. + fn serialize_struct_handles( + &mut self, + binary: &mut BinaryData, + struct_handles: &[StructHandle], + ) -> Result<()> { + if !struct_handles.is_empty() { + self.table_count += 1; + self.struct_handles.0 = check_index_in_binary(binary.len())?; + for struct_handle in struct_handles { + serialize_struct_handle(binary, struct_handle)?; + } + self.struct_handles.1 = checked_calculate_table_size(binary, self.struct_handles.0)?; + } + Ok(()) + } + + /// Serializes `FunctionHandle` table. + fn serialize_function_handles( + &mut self, + binary: &mut BinaryData, + function_handles: &[FunctionHandle], + ) -> Result<()> { + if !function_handles.is_empty() { + self.table_count += 1; + self.function_handles.0 = check_index_in_binary(binary.len())?; + for function_handle in function_handles { + serialize_function_handle(binary, function_handle)?; + } + self.function_handles.1 = + checked_calculate_table_size(binary, self.function_handles.0)?; + } + Ok(()) + } + + /// Serializes `FunctionInstantiation` table. + fn serialize_function_instantiations( + &mut self, + binary: &mut BinaryData, + function_instantiations: &[FunctionInstantiation], + ) -> Result<()> { + if !function_instantiations.is_empty() { + self.table_count += 1; + self.function_instantiations.0 = check_index_in_binary(binary.len())?; + for function_instantiation in function_instantiations { + serialize_function_instantiation(binary, function_instantiation)?; + } + self.function_instantiations.1 = + checked_calculate_table_size(binary, self.function_instantiations.0)?; + } + Ok(()) + } + + /// Serializes `Identifiers`. + fn serialize_identifiers( + &mut self, + binary: &mut BinaryData, + identifiers: &[Identifier], + ) -> Result<()> { + if !identifiers.is_empty() { + self.table_count += 1; + self.identifiers.0 = check_index_in_binary(binary.len())?; + for identifier in identifiers { + // User strings and identifiers use the same serialization. + serialize_identifier(binary, identifier.as_str())?; + } + self.identifiers.1 = checked_calculate_table_size(binary, self.identifiers.0)?; + } + Ok(()) + } + + /// Serializes `AddressIdentifiers`. + fn serialize_address_identifiers( + &mut self, + binary: &mut BinaryData, + addresses: &[AccountAddress], + ) -> Result<()> { + if !addresses.is_empty() { + self.table_count += 1; + self.address_identifiers.0 = check_index_in_binary(binary.len())?; + for address in addresses { + serialize_address(binary, address)?; + } + self.address_identifiers.1 = + checked_calculate_table_size(binary, self.address_identifiers.0)?; + } + Ok(()) + } + + /// Serializes `ConstantPool`. + fn serialize_constants( + &mut self, + binary: &mut BinaryData, + constants: &[Constant], + ) -> Result<()> { + if !constants.is_empty() { + self.table_count += 1; + self.constant_pool.0 = check_index_in_binary(binary.len())?; + for constant in constants { + serialize_constant(binary, constant)?; + } + self.constant_pool.1 = checked_calculate_table_size(binary, self.constant_pool.0)?; + } + Ok(()) + } + + /// Serializes metadata. + fn serialize_metadata(&mut self, binary: &mut BinaryData, metadata: &[Metadata]) -> Result<()> { + if !metadata.is_empty() { + self.table_count += 1; + self.metadata.0 = check_index_in_binary(binary.len())?; + for entry in metadata { + serialize_metadata_entry(binary, entry)?; + } + self.metadata.1 = checked_calculate_table_size(binary, self.metadata.0)?; + } + Ok(()) + } + + /// Serializes `SignaturePool` table. + fn serialize_signatures( + &mut self, + binary: &mut BinaryData, + signatures: &[Signature], + ) -> Result<()> { + if !signatures.is_empty() { + self.table_count += 1; + self.signatures.0 = check_index_in_binary(binary.len())?; + for signature in signatures { + serialize_signature(binary, signature)?; + } + self.signatures.1 = checked_calculate_table_size(binary, self.signatures.0)?; + } + Ok(()) + } + + pub fn major_version(&self) -> u32 { + self.major_version + } +} + +impl ModuleSerializer { + fn new(major_version: u32) -> ModuleSerializer { + ModuleSerializer { + common: CommonSerializer::new(major_version), + struct_defs: (0, 0), + struct_def_instantiations: (0, 0), + function_defs: (0, 0), + field_handles: (0, 0), + field_instantiations: (0, 0), + friend_decls: (0, 0), + } + } + + fn serialize_tables(&mut self, binary: &mut BinaryData, module: &CompiledModule) -> Result<()> { + self.common.serialize_common_tables(binary, module)?; + self.serialize_struct_definitions(binary, &module.struct_defs)?; + self.serialize_struct_def_instantiations(binary, &module.struct_def_instantiations)?; + self.serialize_function_definitions(binary, &module.function_defs)?; + self.serialize_field_handles(binary, &module.field_handles)?; + self.serialize_field_instantiations(binary, &module.field_instantiations)?; + self.serialize_friend_declarations(binary, &module.friend_decls) + } + + fn serialize_table_indices(&mut self, binary: &mut BinaryData) -> Result<()> { + self.common.serialize_table_indices(binary)?; + serialize_table_index( + binary, + TableType::STRUCT_DEFS, + self.struct_defs.0, + self.struct_defs.1, + )?; + serialize_table_index( + binary, + TableType::STRUCT_DEF_INST, + self.struct_def_instantiations.0, + self.struct_def_instantiations.1, + )?; + serialize_table_index( + binary, + TableType::FUNCTION_DEFS, + self.function_defs.0, + self.function_defs.1, + )?; + serialize_table_index( + binary, + TableType::FIELD_HANDLE, + self.field_handles.0, + self.field_handles.1, + )?; + serialize_table_index( + binary, + TableType::FIELD_INST, + self.field_instantiations.0, + self.field_instantiations.1, + )?; + serialize_table_index( + binary, + TableType::FRIEND_DECLS, + self.friend_decls.0, + self.friend_decls.1, + )?; + Ok(()) + } + + /// Serializes `StructDefinition` table. + fn serialize_struct_definitions( + &mut self, + binary: &mut BinaryData, + struct_definitions: &[StructDefinition], + ) -> Result<()> { + if !struct_definitions.is_empty() { + self.common.table_count = self.common.table_count.wrapping_add(1); // the count will bound to a small number + self.struct_defs.0 = check_index_in_binary(binary.len())?; + for struct_definition in struct_definitions { + serialize_struct_definition(binary, struct_definition)?; + } + self.struct_defs.1 = checked_calculate_table_size(binary, self.struct_defs.0)?; + } + Ok(()) + } + + /// Serializes `StructInstantiation` table. + fn serialize_struct_def_instantiations( + &mut self, + binary: &mut BinaryData, + struct_def_instantiations: &[StructDefInstantiation], + ) -> Result<()> { + if !struct_def_instantiations.is_empty() { + self.common.table_count = self.common.table_count.wrapping_add(1); // the count will bound to a small number + self.struct_def_instantiations.0 = check_index_in_binary(binary.len())?; + for struct_instantiation in struct_def_instantiations { + serialize_struct_def_instantiation(binary, struct_instantiation)?; + } + self.struct_def_instantiations.1 = + checked_calculate_table_size(binary, self.struct_def_instantiations.0)?; + } + Ok(()) + } + + /// Serializes `FunctionDefinition` table. + fn serialize_field_handles( + &mut self, + binary: &mut BinaryData, + field_handles: &[FieldHandle], + ) -> Result<()> { + if !field_handles.is_empty() { + self.common.table_count += 1; + self.field_handles.0 = check_index_in_binary(binary.len())?; + for field_handle in field_handles { + serialize_field_handle(binary, field_handle)?; + } + self.field_handles.1 = checked_calculate_table_size(binary, self.field_handles.0)?; + } + Ok(()) + } + + fn serialize_field_instantiations( + &mut self, + binary: &mut BinaryData, + field_instantiations: &[FieldInstantiation], + ) -> Result<()> { + if !field_instantiations.is_empty() { + self.common.table_count += 1; + self.field_instantiations.0 = check_index_in_binary(binary.len())?; + for field_instantiation in field_instantiations { + serialize_field_instantiation(binary, field_instantiation)?; + } + self.field_instantiations.1 = + checked_calculate_table_size(binary, self.field_instantiations.0)?; + } + Ok(()) + } + + fn serialize_function_definitions( + &mut self, + binary: &mut BinaryData, + function_definitions: &[FunctionDefinition], + ) -> Result<()> { + if !function_definitions.is_empty() { + self.common.table_count = self.common.table_count.wrapping_add(1); // the count will bound to a small number + self.function_defs.0 = check_index_in_binary(binary.len())?; + for function_definition in function_definitions { + self.serialize_function_definition(binary, function_definition)?; + } + self.function_defs.1 = checked_calculate_table_size(binary, self.function_defs.0)?; + } + Ok(()) + } + + /// Serializes a `FunctionDefinition`. + /// + /// A `FunctionDefinition` gets serialized as follows: + /// - `FunctionDefinition.function` as a ULEB128 (index into the `FunctionHandle` table) + /// - `FunctionDefinition.visibility` 1 byte for the visibility modifier of the function + /// - `FunctionDefinition.flags` 1 byte for the flags of the function + /// The flags now has only one bit used: + /// - bit 0x2: native indicator, indicates whether the function is a native function. + /// - `FunctionDefinition.code` a variable size stream for the `CodeUnit` + fn serialize_function_definition( + &mut self, + binary: &mut BinaryData, + function_definition: &FunctionDefinition, + ) -> Result<()> { + serialize_function_handle_index(binary, &function_definition.function)?; + + let mut flags = 0; + if self.common.major_version < VERSION_5 { + let visibility = if function_definition.visibility == Visibility::Public + && function_definition.is_entry + { + Visibility::DEPRECATED_SCRIPT + } else { + function_definition.visibility as u8 + }; + binary.push(visibility)?; + } else { + binary.push(function_definition.visibility as u8)?; + if function_definition.is_entry { + flags |= FunctionDefinition::ENTRY; + } + } + if function_definition.is_native() { + flags |= FunctionDefinition::NATIVE + } + binary.push(flags)?; + + serialize_acquires(binary, &function_definition.acquires_global_resources)?; + if let Some(code) = &function_definition.code { + serialize_code_unit(self.common.major_version(), binary, code)?; + } + Ok(()) + } + + fn serialize_friend_declarations( + &mut self, + binary: &mut BinaryData, + friend_declarations: &[ModuleHandle], + ) -> Result<()> { + if !friend_declarations.is_empty() { + self.common.table_count = self.common.table_count.wrapping_add(1); // the count will bound to a small number + self.friend_decls.0 = check_index_in_binary(binary.len())?; + for module in friend_declarations { + serialize_module_handle(binary, module)?; + } + self.friend_decls.1 = checked_calculate_table_size(binary, self.friend_decls.0)?; + } + Ok(()) + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/binary_limits_tests.rs b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/binary_limits_tests.rs new file mode 100644 index 000000000..f655efc1d --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/binary_limits_tests.rs @@ -0,0 +1,332 @@ +// Copyright (c) 2021, Facebook, Inc. and its affiliates +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + binary_config::{BinaryConfig, TableConfig}, + errors::BinaryLoaderResult, + file_format::*, + CompiledModule, +}; +use move_core_types::{ + account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode, +}; +// Add simple proptest tests +// use proptest::prelude::*; + +// Serialize a `CompiledModule` and deserialize with a given config (round trip) +fn deserialize( + module: &CompiledModule, + binary_config: &BinaryConfig, +) -> BinaryLoaderResult { + // serialize the module + let mut bytes = vec![]; + module.serialize(&mut bytes).unwrap(); + // deserialize the module just serialized (round trip) + CompiledModule::deserialize_with_config(&bytes, binary_config) +} + +// +// macro helpers +// + +// check that the error is for limits on the specific table +macro_rules! assert_limit_failure { + ($result:expr, $table:expr) => { + assert!($result.is_err()); + let err = $result.unwrap_err(); + let (major_status, _, message, _, _, _) = err.all_data(); + assert_eq!(major_status, StatusCode::MALFORMED); + assert!(message.as_ref().unwrap().contains($table)); + }; +} + +// check with values below, equal and above the given limit +macro_rules! check_limit { + ($module:expr, $field:ident, $elem:expr, $config:expr, $table_kind:expr) => { + let max_size = $config.table_config.$field; + // under max ok + $module.$field = vec![$elem.clone(); max_size as usize - 1]; + assert!(deserialize($module, $config).is_ok()); + // max ok + $module.$field = vec![$elem.clone(); max_size as usize]; + assert!(deserialize($module, $config).is_ok()); + // over max error + $module.$field = vec![$elem; max_size as usize + 1]; + assert_limit_failure!(deserialize($module, $config), $table_kind); + }; +} + +#[test] +fn binary_limits_test() { + let module = empty_module(); + let mut binary_config = BinaryConfig::standard(); + + // legacy config should work + let res = deserialize(&module, &binary_config); + assert!(res.is_ok()); + + // make given max size for different tables + binary_config.table_config = TableConfig { + module_handles: 10, + struct_handles: 15, + function_handles: 11, + function_instantiations: 5, + signatures: 20, + constant_pool: 12, + identifiers: 10, + address_identifiers: 8, + struct_defs: 12, + struct_def_instantiations: 13, + function_defs: 9, + field_handles: 11, + field_instantiations: 16, + friend_decls: 12, + }; + + // From file_format_common.rs::TableType test table type of interest (no METADATA + + // MODULE_HANDLES + let module_test = &mut module.clone(); + check_limit!( + module_test, + module_handles, + ModuleHandle { + address: AddressIdentifierIndex::new(0), + name: IdentifierIndex::new(0) + }, + &binary_config, + "MODULE_HANDLES" + ); + + // STRUCT_HANDLES + let module_test = &mut module.clone(); + check_limit!( + module_test, + struct_handles, + StructHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + abilities: AbilitySet::EMPTY, + type_parameters: vec![], + }, + &binary_config, + "STRUCT_HANDLES" + ); + + // FUNCTION_HANDLES + let module_test = &mut module.clone(); + check_limit!( + module_test, + function_handles, + FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: vec![], + }, + &binary_config, + "FUNCTION_HANDLES" + ); + + // FUNCTION_INST + let module_test = &mut module.clone(); + module_test.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + check_limit!( + module_test, + function_instantiations, + FunctionInstantiation { + handle: FunctionHandleIndex(0), + type_parameters: SignatureIndex(0), + }, + &binary_config, + "FUNCTION_INST" + ); + + // SIGNATURES + let module_test = &mut module.clone(); + check_limit!( + module_test, + signatures, + Signature(vec![]), + &binary_config, + "SIGNATURES" + ); + + // CONSTANT_POOL + let module_test = &mut module.clone(); + check_limit!( + module_test, + constant_pool, + Constant { + type_: SignatureToken::U64, + data: vec![0; 8], + }, + &binary_config, + "CONSTANT_POOL" + ); + + // IDENTIFIERS + let module_test = &mut module.clone(); + check_limit!( + module_test, + identifiers, + Identifier::new("ident").unwrap(), + &binary_config, + "IDENTIFIERS" + ); + + // ADDRESS_IDENTIFIERS + let module_test = &mut module.clone(); + check_limit!( + module_test, + address_identifiers, + AccountAddress::random(), + &binary_config, + "ADDRESS_IDENTIFIERS" + ); + + // STRUCT_DEFS + let module_test = &mut module.clone(); + module_test.struct_handles.push(StructHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + abilities: AbilitySet::EMPTY, + type_parameters: vec![], + }); + check_limit!( + module_test, + struct_defs, + StructDefinition { + struct_handle: StructHandleIndex(0), + field_information: StructFieldInformation::Declared(vec![]), + }, + &binary_config, + "STRUCT_DEFS" + ); + + // STRUCT_DEF_INST + let module_test = &mut module.clone(); + module_test.struct_handles.push(StructHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + abilities: AbilitySet::EMPTY, + type_parameters: vec![], + }); + module_test.struct_defs.push(StructDefinition { + struct_handle: StructHandleIndex(0), + field_information: StructFieldInformation::Declared(vec![]), + }); + check_limit!( + module_test, + struct_def_instantiations, + StructDefInstantiation { + def: StructDefinitionIndex(0), + type_parameters: SignatureIndex(0), + }, + &binary_config, + "STRUCT_DEF_INST" + ); + + // FUNCTION_DEFS + let module_test = &mut module.clone(); + module_test.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + check_limit!( + module_test, + function_defs, + FunctionDefinition { + function: FunctionHandleIndex(0), + visibility: Visibility::Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::Ret], + }), + }, + &binary_config, + "FUNCTION_DEFS" + ); + + // FIELD_HANDLE + let module_test = &mut module.clone(); + module_test.struct_handles.push(StructHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + abilities: AbilitySet::EMPTY, + type_parameters: vec![], + }); + module_test.struct_defs.push(StructDefinition { + struct_handle: StructHandleIndex(0), + field_information: StructFieldInformation::Declared(vec![FieldDefinition { + name: IdentifierIndex(0), + signature: TypeSignature(SignatureToken::Bool), + }]), + }); + check_limit!( + module_test, + field_handles, + FieldHandle { + owner: StructDefinitionIndex(0), + field: 0, + }, + &binary_config, + "FIELD_HANDLE" + ); + + // FIELD_INST + let module_test = &mut module.clone(); + module_test.struct_handles.push(StructHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + abilities: AbilitySet::EMPTY, + type_parameters: vec![], + }); + module_test.struct_defs.push(StructDefinition { + struct_handle: StructHandleIndex(0), + field_information: StructFieldInformation::Declared(vec![FieldDefinition { + name: IdentifierIndex(0), + signature: TypeSignature(SignatureToken::Bool), + }]), + }); + module_test.field_handles.push(FieldHandle { + owner: StructDefinitionIndex(0), + field: 0, + }); + check_limit!( + module_test, + field_instantiations, + FieldInstantiation { + handle: FieldHandleIndex(0), + type_parameters: SignatureIndex(0), + }, + &binary_config, + "FIELD_INST" + ); + + // FRIEND_DECLS + let module_test = &mut module.clone(); + check_limit!( + module_test, + friend_decls, + ModuleHandle { + address: AddressIdentifierIndex::new(0), + name: IdentifierIndex::new(0) + }, + &binary_config, + "FRIEND_DECLS" + ); +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/binary_tests.rs b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/binary_tests.rs new file mode 100644 index 000000000..492a9fbf6 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/binary_tests.rs @@ -0,0 +1,65 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::{file_format::Bytecode, file_format_common::*}; +use proptest::prelude::*; + +#[test] +fn size_canary() { + use crate::file_format::SignatureToken; + use std::mem::size_of; + assert_eq!(size_of::(), 16); + assert_eq!(size_of::(), 16); +} + +#[test] +fn binary_len() { + let mut binary_data = BinaryData::new(); + for _ in 0..100 { + binary_data.push(1).unwrap(); + } + assert_eq!(binary_data.len(), 100); +} + +#[test] +fn test_max_number_of_bytecode() { + let mut nops = vec![]; + for _ in 0..u16::MAX - 1 { + nops.push(Bytecode::Nop); + } + nops.push(Bytecode::Branch(0)); + + let result = Bytecode::get_successors(u16::MAX - 1, &nops); + assert_eq!(result, vec![0]); +} + +proptest! { + #[test] + fn vec_to_binary(vec in any::>()) { + let binary_data = BinaryData::from(vec.clone()); + let vec2 = binary_data.into_inner(); + assert_eq!(vec.len(), vec2.len()); + } +} + +proptest! { + #[test] + fn binary_push(item in any::()) { + let mut binary_data = BinaryData::new(); + binary_data.push(item).unwrap(); + assert_eq!(binary_data.into_inner()[0], item); + } +} + +proptest! { + #[test] + fn binary_extend(vec in any::>()) { + let mut binary_data = BinaryData::new(); + binary_data.extend(&vec).unwrap(); + assert_eq!(binary_data.len(), vec.len()); + for (index, item) in vec.iter().enumerate() { + assert_eq!(*item, binary_data.as_inner()[index]); + } + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/compatibility_tests.rs b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/compatibility_tests.rs new file mode 100644 index 000000000..2f3af751f --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/compatibility_tests.rs @@ -0,0 +1,845 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use std::{collections::BTreeMap, convert::TryFrom}; + +use crate::{ + compatibility::{Compatibility, InclusionCheck}, + file_format::*, + normalized::{self, Type}, +}; +use move_core_types::{account_address::AccountAddress, ident_str, identifier::Identifier}; + +// A way to permute pools, and index into them still. +pub struct Permutation { + permutation: Vec, + inverse: Vec, +} + +impl Permutation { + pub fn new(permutation: Vec) -> Self { + let inverse: Vec<_> = (0..permutation.len() as u16) + .map(|i| permutation.iter().position(|p| *p == i).unwrap() as u16) + .collect(); + Self { + permutation, + inverse, + } + } + + pub fn pool(&self, pool: Vec) -> Vec { + (0..pool.len() as u16) + .map(|i| pool[*self.permutation.get(i as usize).unwrap_or(&i) as usize].clone()) + .collect() + } + + pub fn permute(&self, i: u16) -> u16 { + // If we don't have it in the permutation default to the identity + *self.inverse.get(i as usize).unwrap_or(&i) + } +} + +fn mk_module(vis: u8) -> normalized::Module { + mk_module_entry(vis, false) +} + +fn max_version(mut module: normalized::Module) -> normalized::Module { + module.file_format_version = crate::file_format_common::VERSION_MAX; + module +} + +fn mk_module_entry(vis: u8, is_entry: bool) -> normalized::Module { + let (visibility, is_entry) = if vis == Visibility::DEPRECATED_SCRIPT { + (Visibility::Public, true) + } else { + (Visibility::try_from(vis).unwrap(), is_entry) + }; + let m = CompiledModule { + version: crate::file_format_common::VERSION_4, + module_handles: vec![ + // only self module + ModuleHandle { + address: AddressIdentifierIndex(0), + name: IdentifierIndex(0), + }, + ], + self_module_handle_idx: ModuleHandleIndex(0), + identifiers: vec![ + Identifier::new("M").unwrap(), // Module name + Identifier::new("fn").unwrap(), // Function name + ], + address_identifiers: vec![ + AccountAddress::ZERO, // Module address + ], + function_handles: vec![ + // fun fn() + FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(1), + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: vec![], + }, + ], + function_defs: vec![ + // public(script) fun fn() { return; } + FunctionDefinition { + function: FunctionHandleIndex(0), + visibility, + is_entry, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![ + Bytecode::LdConst(ConstantPoolIndex(0)), + Bytecode::LdConst(ConstantPoolIndex(1)), + Bytecode::LdConst(ConstantPoolIndex(2)), + Bytecode::Ret, + ], + }), + }, + ], + signatures: vec![ + Signature(vec![]), // void + Signature(vec![SignatureToken::U64]), // u64 + ], + struct_defs: vec![], + struct_handles: vec![], + constant_pool: vec![ + Constant { + type_: SignatureToken::U8, + data: vec![0], + }, + Constant { + type_: SignatureToken::U8, + data: vec![1], + }, + Constant { + type_: SignatureToken::Bool, + data: vec![1], + }, + ], + metadata: vec![], + field_handles: vec![], + friend_decls: vec![], + struct_def_instantiations: vec![], + function_instantiations: vec![], + field_instantiations: vec![], + }; + normalized::Module::new(&m) +} + +fn mk_module_plus_code(vis: u8, code: Vec) -> normalized::Module { + mk_module_plus_code_perm(vis, code, Permutation::new(vec![])) +} + +fn mk_module_plus_code_perm(vis: u8, code: Vec, p: Permutation) -> normalized::Module { + let (visibility, is_entry) = if vis == Visibility::DEPRECATED_SCRIPT { + (Visibility::Public, true) + } else { + (Visibility::try_from(vis).unwrap(), false) + }; + let m = CompiledModule { + version: crate::file_format_common::VERSION_4, + module_handles: vec![ + // only self module + ModuleHandle { + address: AddressIdentifierIndex(0), + name: IdentifierIndex(p.permute(0)), + }, + ], + self_module_handle_idx: ModuleHandleIndex(0), + identifiers: p.pool(vec![ + Identifier::new("M").unwrap(), // Module name + Identifier::new("fn").unwrap(), // Function name + Identifier::new("fn1").unwrap(), // Function name + ]), + address_identifiers: vec![ + AccountAddress::ZERO, // Module address + ], + function_handles: p.pool(vec![ + // fun fn() + FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(p.permute(1)), + parameters: SignatureIndex(p.permute(0)), + return_: SignatureIndex(p.permute(0)), + type_parameters: vec![], + }, + FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(p.permute(2)), + parameters: SignatureIndex(p.permute(1)), + return_: SignatureIndex(p.permute(0)), + type_parameters: vec![], + }, + ]), + function_defs: p.pool(vec![ + // public(script) fun fn1(u64) { return; } + FunctionDefinition { + function: FunctionHandleIndex(p.permute(1)), + visibility, + is_entry, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(p.permute(0)), + code, + }), + }, + // public(script) fun fn() { return; } + FunctionDefinition { + function: FunctionHandleIndex(p.permute(0)), + visibility, + is_entry, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(p.permute(0)), + code: vec![ + Bytecode::LdConst(ConstantPoolIndex(p.permute(0))), + Bytecode::LdConst(ConstantPoolIndex(p.permute(1))), + Bytecode::LdConst(ConstantPoolIndex(p.permute(2))), + Bytecode::Ret, + ], + }), + }, + ]), + signatures: p.pool(vec![ + Signature(vec![]), // void + Signature(vec![SignatureToken::U64]), // u64 + ]), + struct_defs: vec![], + struct_handles: vec![], + constant_pool: p.pool(vec![ + Constant { + type_: SignatureToken::U8, + data: vec![0], + }, + Constant { + type_: SignatureToken::U8, + data: vec![1], + }, + Constant { + type_: SignatureToken::Bool, + data: vec![1], + }, + ]), + metadata: vec![], + field_handles: vec![], + friend_decls: vec![], + struct_def_instantiations: vec![], + function_instantiations: vec![], + field_instantiations: vec![], + }; + normalized::Module::new(&m) +} + +fn mk_module_plus(vis: u8) -> normalized::Module { + mk_module_plus_code(vis, vec![Bytecode::Ret]) +} + +fn mk_module_plus_perm(vis: u8, permutation: Permutation) -> normalized::Module { + mk_module_plus_code_perm(vis, vec![Bytecode::Ret], permutation) +} + +fn make_complex_module_perm(p: Permutation) -> normalized::Module { + let m = CompiledModule { + version: crate::file_format_common::VERSION_MAX, + module_handles: vec![ + // only self module + ModuleHandle { + address: AddressIdentifierIndex(0), + name: IdentifierIndex(p.permute(0)), + }, + ], + self_module_handle_idx: ModuleHandleIndex(0), + identifiers: p.pool(vec![ + Identifier::new("M").unwrap(), // Module name + Identifier::new("S").unwrap(), // Struct name + Identifier::new("GS").unwrap(), // Generic struct name + Identifier::new("R").unwrap(), // Resource name + Identifier::new("GR").unwrap(), // Generic resource name + Identifier::new("f").unwrap(), // Field name + Identifier::new("fn").unwrap(), // Function name + Identifier::new("g_fn").unwrap(), // Generic function name + Identifier::new("test_fn").unwrap(), // Test function name + ]), + address_identifiers: vec![ + AccountAddress::ZERO, // Module address + ], + struct_handles: p.pool(vec![ + StructHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(p.permute(1)), + abilities: AbilitySet::PRIMITIVES, + type_parameters: vec![], + }, + StructHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(p.permute(2)), + abilities: AbilitySet::PRIMITIVES, + type_parameters: vec![StructTypeParameter { + constraints: AbilitySet::PRIMITIVES, + is_phantom: false, + }], + }, + StructHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(p.permute(3)), + abilities: AbilitySet::EMPTY | Ability::Key, + type_parameters: vec![], + }, + StructHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(p.permute(4)), + abilities: AbilitySet::EMPTY | Ability::Key, + type_parameters: vec![StructTypeParameter { + constraints: AbilitySet::PRIMITIVES, + is_phantom: false, + }], + }, + ]), + struct_defs: p.pool(vec![ + // struct S { f: u64 } + StructDefinition { + struct_handle: StructHandleIndex(p.permute(0)), + field_information: StructFieldInformation::Declared(vec![FieldDefinition { + name: IdentifierIndex(p.permute(5)), + signature: TypeSignature(SignatureToken::U64), + }]), + }, + // struct GS { f: T } + StructDefinition { + struct_handle: StructHandleIndex(p.permute(1)), + field_information: StructFieldInformation::Declared(vec![FieldDefinition { + name: IdentifierIndex(p.permute(5)), + signature: TypeSignature(SignatureToken::TypeParameter(0)), + }]), + }, + // struct R has key { f: u64 } + StructDefinition { + struct_handle: StructHandleIndex(p.permute(2)), + field_information: StructFieldInformation::Declared(vec![FieldDefinition { + name: IdentifierIndex(p.permute(5)), + signature: TypeSignature(SignatureToken::U64), + }]), + }, + // struct GR has key { f: T } + StructDefinition { + struct_handle: StructHandleIndex(p.permute(3)), + field_information: StructFieldInformation::Declared(vec![FieldDefinition { + name: IdentifierIndex(p.permute(5)), + signature: TypeSignature(SignatureToken::TypeParameter(0)), + }]), + }, + ]), + function_handles: p.pool(vec![ + // fun fn() + FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(p.permute(6)), + parameters: SignatureIndex(p.permute(0)), + return_: SignatureIndex(p.permute(0)), + type_parameters: vec![], + }, + // fun g_fn(): u64 + FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(p.permute(7)), + parameters: SignatureIndex(p.permute(0)), + return_: SignatureIndex(p.permute(2)), + type_parameters: vec![AbilitySet::EMPTY | Ability::Key], + }, + // fun test_fn(Sender) + FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(p.permute(8)), + parameters: SignatureIndex(p.permute(1)), + return_: SignatureIndex(p.permute(0)), + type_parameters: vec![], + }, + ]), + function_defs: p.pool(vec![ + // public fun fn() { return; } + FunctionDefinition { + function: FunctionHandleIndex(p.permute(0)), + visibility: Visibility::Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(p.permute(0)), + code: vec![Bytecode::Ret], + }), + }, + // fun g_fn() { return; } + FunctionDefinition { + function: FunctionHandleIndex(p.permute(1)), + visibility: Visibility::Private, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(p.permute(0)), + code: vec![Bytecode::Ret], + }), + }, + FunctionDefinition { + function: FunctionHandleIndex(p.permute(2)), + visibility: Visibility::Private, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(p.permute(0)), + code: vec![], + }), + }, + ]), + signatures: p.pool(vec![ + Signature(vec![]), // void + Signature(vec![SignatureToken::Address]), // address + Signature(vec![SignatureToken::U64]), // u64 + ]), + constant_pool: p.pool(vec![ + Constant { + type_: SignatureToken::U8, + data: vec![0], + }, + Constant { + type_: SignatureToken::U8, + data: vec![1], + }, + Constant { + type_: SignatureToken::Bool, + data: vec![1], + }, + // an address + Constant { + type_: SignatureToken::Address, + data: AccountAddress::random().to_vec(), + }, + ]), + metadata: vec![], + field_handles: vec![], + friend_decls: vec![], + struct_def_instantiations: vec![], + function_instantiations: vec![], + field_instantiations: vec![], + }; + normalized::Module::new(&m) +} + +#[test] +fn deprecated_unchanged_script_visibility() { + let script_module = mk_module(Visibility::DEPRECATED_SCRIPT); + assert!(Compatibility::full_check() + .check(&script_module, &script_module) + .is_ok(),); +} + +#[test] +fn deprecated_remove_script_visibility() { + let script_module = mk_module(Visibility::DEPRECATED_SCRIPT); + // script -> private, not allowed + let private_module = mk_module(Visibility::Private as u8); + assert!(Compatibility::full_check() + .check(&script_module, &private_module) + .is_err()); + // script -> public, not allowed + let public_module = mk_module(Visibility::Public as u8); + assert!(Compatibility::full_check() + .check(&script_module, &public_module) + .is_err()); + // script -> friend, not allowed + let friend_module = mk_module(Visibility::Friend as u8); + assert!(Compatibility::full_check() + .check(&script_module, &friend_module) + .is_err()); +} + +#[test] +fn deprecated_add_script_visibility() { + let script_module = mk_module(Visibility::DEPRECATED_SCRIPT); + // private -> script, allowed + let private_module = mk_module(Visibility::Private as u8); + assert!(Compatibility::full_check() + .check(&private_module, &script_module) + .is_ok()); + // public -> script, not allowed + let public_module = mk_module(Visibility::Public as u8); + assert!(Compatibility::full_check() + .check(&public_module, &script_module) + .is_err()); + // friend -> script, not allowed + let friend_module = mk_module(Visibility::Friend as u8); + assert!(Compatibility::full_check() + .check(&friend_module, &script_module) + .is_err()); +} + +#[test] +fn private_entry_to_public_entry_allowed() { + let private_module = max_version(mk_module_entry(Visibility::Private as u8, true)); + let public_module = max_version(mk_module_entry(Visibility::Public as u8, true)); + assert!(Compatibility::full_check() + .check(&private_module, &public_module) + .is_ok()); + + assert!(Compatibility::full_check() + .check(&public_module, &private_module) + .is_err()); +} + +#[test] +fn public_loses_entry() { + let public_entry = max_version(mk_module_entry(Visibility::Public as u8, true)); + let public = max_version(mk_module_entry(Visibility::Public as u8, false)); + assert!(Compatibility::full_check() + .check(&public, &public_entry) + .is_ok()); + + assert!(Compatibility::full_check() + .check(&public_entry, &public) + .is_err()); +} + +#[test] +fn private_entry_signature_change_allowed() { + // Create a private entry function + let module = max_version(mk_module_entry(Visibility::Private as u8, true)); + let mut updated_module = module.clone(); + // Update the signature of the entry fun to now take a u64 argument. + updated_module + .functions + .get_mut(ident_str!("fn")) + .unwrap() + .parameters = vec![Type::U64]; + + // allow updating signatures of private entry functions + assert!(Compatibility { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: true, + check_private_entry_linking: false, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: false, + } + .check(&module, &updated_module) + .is_ok()); + + // allow updating signatures of private entry functions + assert!(Compatibility { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: true, + check_private_entry_linking: false, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: false, + } + .check(&updated_module, &module) + .is_ok()); + + // disallow updating signatures of private entry functions + assert!(Compatibility::full_check() + .check(&module, &updated_module) + .is_err()); +} + +#[test] +fn entry_fun_compat_tests() { + // fun + let private_fun = max_version(mk_module_entry(Visibility::Private as u8, false)); + // entry fun + let entry_fun = max_version(mk_module_entry(Visibility::Private as u8, true)); + // public(friend) fun + let friend_fun = max_version(mk_module_entry(Visibility::Friend as u8, false)); + // public(friend) entry fun + let friend_entry_fun = max_version(mk_module_entry(Visibility::Friend as u8, true)); + // public fun + let public_fun = max_version(mk_module_entry(Visibility::Public as u8, false)); + // public entry fun + let public_entry_fun = max_version(mk_module_entry(Visibility::Public as u8, true)); + // NO function + let mut no_fun = private_fun.clone(); + no_fun.functions = BTreeMap::new(); + + let mut valid_combos = vec![ + // Can transition from a private entry fun to anything + // see the adding of `invalid_private_entry_breakages` below to this table. + (&entry_fun, &friend_entry_fun), + // Can transition from a private fun to anything + (&private_fun, &entry_fun), + (&private_fun, &friend_fun), + (&private_fun, &friend_entry_fun), + (&private_fun, &public_fun), + (&private_fun, &public_entry_fun), + (&private_fun, &no_fun), + // Can transition from public fun to a public entry fun (post version 5) + (&public_fun, &public_entry_fun), + (&friend_entry_fun, &public_entry_fun), + (&friend_entry_fun, &friend_fun), + (&friend_fun, &public_entry_fun), + (&friend_fun, &public_fun), + (&friend_fun, &friend_entry_fun), + (&public_entry_fun, &public_fun), + ]; + + let invalid_combos = vec![ + (&public_entry_fun, &entry_fun), + (&public_entry_fun, &private_fun), + (&public_entry_fun, &friend_entry_fun), + (&public_entry_fun, &friend_fun), + (&public_entry_fun, &no_fun), + (&friend_entry_fun, &no_fun), + (&friend_entry_fun, &private_fun), + (&friend_entry_fun, &entry_fun), + ]; + + let invalid_private_entry_breakages = vec![ + (&entry_fun, &private_fun), + (&entry_fun, &friend_fun), + (&entry_fun, &public_fun), + (&entry_fun, &no_fun), + ]; + + valid_combos.extend_from_slice(&invalid_private_entry_breakages); + + // These would all be invalid combos unless we also allow friend breakage. + let valid_entry_fun_changes_with_friend_api_breakage = vec![ + (&friend_entry_fun, &no_fun), + (&friend_entry_fun, &private_fun), + (&friend_entry_fun, &entry_fun), + (&friend_fun, &no_fun), + (&friend_fun, &private_fun), + (&friend_fun, &entry_fun), + ]; + + // Every valid combo is valid under `check_private_entry_linking = false` + for (prev, new) in valid_combos.into_iter() { + assert!(Compatibility { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: true, + check_private_entry_linking: false, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: false, + } + .check(prev, new) + .is_ok()); + } + + // Every + for (prev, new) in invalid_private_entry_breakages.into_iter() { + assert!(Compatibility::full_check().check(prev, new).is_err()); + } + + // Every valid combo is valid under `check_private_entry_linking = false` + for (prev, new) in valid_entry_fun_changes_with_friend_api_breakage.into_iter() { + assert!(Compatibility { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: false, + check_private_entry_linking: false, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: false, + } + .check(prev, new) + .is_ok()); + + assert!(Compatibility { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: true, + check_private_entry_linking: false, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: false, + } + .check(prev, new) + .is_err()); + } + + for (prev, new) in invalid_combos.into_iter() { + assert!(Compatibility { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: true, + check_private_entry_linking: false, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: false, + } + .check(prev, new) + .is_err()); + } +} + +#[test] +fn public_entry_signature_change_disallowed() { + // Create a public entry function + let module = max_version(mk_module_entry(Visibility::Public as u8, true)); + let mut updated_module = module.clone(); + // Update the signature of the entry fun to now take a u64 argument. + updated_module + .functions + .get_mut(ident_str!("fn")) + .unwrap() + .parameters = vec![Type::U64]; + + assert!(Compatibility { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: true, + check_private_entry_linking: false, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: false, + } + .check(&module, &updated_module) + .is_err()); + + assert!(Compatibility { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: true, + check_private_entry_linking: false, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: false, + } + .check(&updated_module, &module) + .is_err()); + + assert!(Compatibility { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: true, + check_private_entry_linking: true, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: false, + } + .check(&module, &updated_module) + .is_err()); +} + +#[test] +fn friend_entry_signature_change_allowed() { + let module = max_version(mk_module_entry(Visibility::Friend as u8, true)); + let mut updated_module = module.clone(); + // Update the signature of the entry fun to now take a u64 argument. + updated_module + .functions + .get_mut(ident_str!("fn")) + .unwrap() + .parameters = vec![Type::U64]; + + assert!(Compatibility { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: false, + check_private_entry_linking: false, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: false, + } + .check(&module, &updated_module) + .is_ok()); + + assert!(Compatibility { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: true, + check_private_entry_linking: false, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: false, + } + .check(&module, &updated_module) + .is_err()); + + assert!(Compatibility { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: false, + check_private_entry_linking: true, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: false, + } + .check(&module, &updated_module) + .is_err()); + + assert!(Compatibility { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: true, + check_private_entry_linking: true, + disallowed_new_abilities: AbilitySet::EMPTY, + disallow_change_struct_type_params: false, + } + .check(&module, &updated_module) + .is_err()); +} + +#[test] +fn check_exact_and_unchange_same_module() { + let m1 = max_version(mk_module(Visibility::Private as u8)); + assert!(InclusionCheck::Subset.check(&m1, &m1).is_ok()); + assert!(InclusionCheck::Equal.check(&m1, &m1).is_ok()); + + // m1 + an extra function + let m2 = max_version(mk_module_plus(Visibility::Private as u8)); + assert!(InclusionCheck::Subset.check(&m1, &m2).is_ok()); + assert!(InclusionCheck::Subset.check(&m2, &m1).is_err()); + assert!(InclusionCheck::Equal.check(&m1, &m2).is_err()); + assert!(InclusionCheck::Equal.check(&m2, &m1).is_err()); + + // m1 + a change in the bytecode of fn + let m3 = max_version(mk_module_plus_code( + Visibility::Private as u8, + vec![Bytecode::LdU8(0), Bytecode::Ret], + )); + assert!(InclusionCheck::Subset.check(&m2, &m3).is_err()); + // fn1 is not in m1 so the changed bytecode doesn't matter. + assert!(InclusionCheck::Subset.check(&m1, &m3).is_ok()); + assert!(InclusionCheck::Subset.check(&m3, &m2).is_err()); + assert!(InclusionCheck::Subset.check(&m3, &m1).is_err()); + assert!(InclusionCheck::Equal.check(&m1, &m3).is_err()); + assert!(InclusionCheck::Equal.check(&m2, &m3).is_err()); +} + +#[test] +fn check_exact_and_unchange_same_module_permutations() { + let m1 = max_version(mk_module(Visibility::Private as u8)); + let m2 = max_version(mk_module_plus(Visibility::Private as u8)); + let m3 = max_version(mk_module_plus_perm( + Visibility::Private as u8, + Permutation::new(vec![1, 0]), + )); + assert_ne!(m2, m3); + assert!(InclusionCheck::Equal.check(&m2, &m3).is_ok()); + assert!(InclusionCheck::Equal.check(&m3, &m2).is_ok()); + // double inclusion + assert!(InclusionCheck::Subset.check(&m3, &m2).is_ok()); + assert!(InclusionCheck::Subset.check(&m2, &m3).is_ok()); + + assert!(InclusionCheck::Subset.check(&m1, &m3).is_ok()); + assert!(InclusionCheck::Subset.check(&m3, &m1).is_err()); + assert!(InclusionCheck::Equal.check(&m1, &m3).is_err()); + assert!(InclusionCheck::Equal.check(&m3, &m1).is_err()); +} + +#[test] +fn check_exact_and_unchange_same_complex_module_permutations() { + let perms = vec![ + vec![0, 1, 2], + vec![0, 2, 1], + vec![1, 0, 2], + vec![1, 2, 0], + vec![2, 0, 1], + vec![2, 1, 0], + ]; + let modules: Vec<_> = perms + .into_iter() + .map(|permutation| max_version(make_complex_module_perm(Permutation::new(permutation)))) + .collect(); + + for m0 in &modules { + for m1 in &modules { + assert!(InclusionCheck::Equal.check(m0, m1).is_ok()); + assert!(InclusionCheck::Equal.check(m1, m0).is_ok()); + assert!(InclusionCheck::Subset.check(m0, m1).is_ok()); + assert!(InclusionCheck::Subset.check(m1, m0).is_ok()); + } + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/control_flow_graph_tests.rs b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/control_flow_graph_tests.rs new file mode 100644 index 000000000..064aa151b --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/control_flow_graph_tests.rs @@ -0,0 +1,74 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + control_flow_graph::{BlockId, ControlFlowGraph, VMControlFlowGraph}, + file_format::Bytecode, +}; + +#[test] +fn traversal_no_loops() { + let cfg = { + use Bytecode::*; + VMControlFlowGraph::new(&[ + /* L0 */ LdTrue, + /* */ BrTrue(3), + /* L2 */ Branch(3), + /* L3 */ Ret, + ]) + }; + + cfg.display(); + assert_eq!(cfg.num_blocks(), 3); + assert_eq!(traversal(&cfg), vec![0, 2, 3]); +} + +#[test] +fn traversal_loops() { + let cfg = { + use Bytecode::*; + VMControlFlowGraph::new(&[ + /* L0: Outer head */ LdTrue, + /* Outer break */ BrTrue(6), + /* L2: Inner head */ LdTrue, + /* Inner break */ BrTrue(5), + /* L4: Inner continue */ Branch(2), + /* Outer continue */ Branch(0), + /* L6: */ Ret, + ]) + }; + + cfg.display(); + assert_eq!(cfg.num_blocks(), 5); + assert_eq!(traversal(&cfg), vec![0, 2, 4, 5, 6]); +} + +#[test] +fn traversal_non_loop_back_branch() { + let cfg = { + use Bytecode::*; + VMControlFlowGraph::new(&[ + /* L0 */ Branch(2), + /* L1 */ Ret, + /* L2 */ Branch(1), + ]) + }; + + cfg.display(); + assert_eq!(cfg.num_blocks(), 3); + assert_eq!(traversal(&cfg), vec![0, 2, 1]); +} + +/// Return a vector containing the `BlockId`s from `cfg` in the order suggested by successively +/// calling `ControlFlowGraph::next_block` starting from the entry block. +fn traversal(cfg: &dyn ControlFlowGraph) -> Vec { + let mut order = Vec::with_capacity(cfg.num_blocks() as usize); + let mut next = Some(cfg.entry_block_id()); + + while let Some(block) = next { + order.push(block); + next = cfg.next_block(block); + } + + order +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/deserializer_tests.rs b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/deserializer_tests.rs new file mode 100644 index 000000000..ea0024b08 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/deserializer_tests.rs @@ -0,0 +1,333 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + binary_config::BinaryConfig, + file_format::{basic_test_module, CompiledModule}, + file_format_common::*, +}; +use move_core_types::{metadata::Metadata, vm_status::StatusCode}; + +fn malformed_simple_versioned_test(version: u32) { + // bad uleb (more than allowed for table count) + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version + binary.push(150); // table count (high bit 1) + binary.push(150); // table count (high bit 1) + binary.push(1); + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected bad uleb").major_status(), + StatusCode::MALFORMED + ); + + // bad uleb (too big) + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version + binary.push(150); // table count (high bit 1) + binary.push(150); // table count again (high bit 1) + binary.push(150); // table count again (high bit 1) + binary.push(150); // table count again (high bit 1) + binary.push(150); // table count again (high bit 1) + binary.push(150); // table count again (high bit 1) + binary.push(150); // table count again (high bit 1) + binary.push(150); // table count again (high bit 1) + binary.push(150); // table count again (high bit 1) + binary.push(150); // table count again (high bit 1) + binary.push(150); // table count again (high bit 1) + binary.push(0); // table count again + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected bad uleb").major_status(), + StatusCode::MALFORMED + ); + + // no tables + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version + binary.push(0); // table count + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected no table count").major_status(), + StatusCode::MALFORMED + ); + + // missing tables + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version + binary.push(10); // table count + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected no table header").major_status(), + StatusCode::MALFORMED + ); + + // missing table content + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version + binary.push(1); // table count + binary.push(1); // table type + binary.push(0); // table offset + binary.push(10); // table length + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected no table content").major_status(), + StatusCode::MALFORMED + ); + + // bad table header (bad offset) + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version + binary.push(1); // table count + binary.push(1); // table type + binary.push(100); // bad table offset + binary.push(10); // table length + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected bad table offset").major_status(), + StatusCode::BAD_HEADER_TABLE + ); + + // bad table header (bad offset) + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version + binary.push(2); // table count + binary.push(1); // table type + binary.push(0); // table offset + binary.push(10); // table length + binary.push(2); // table type + binary.push(100); // bad table offset + binary.push(10); // table length + binary.resize(binary.len() + 5000, 0); + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected bad table offset").major_status(), + StatusCode::BAD_HEADER_TABLE + ); + + // incomplete table + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version + binary.push(1); // table count + binary.push(1); // table type + binary.push(0); // table offset + binary.push(10); // table length + binary.resize(binary.len() + 5, 0); + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected bad table content").major_status(), + StatusCode::MALFORMED + ); + + // unknown table + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version + binary.push(1); // table count + binary.push(100); // table type + binary.push(0); // table offset + binary.push(10); // table length + binary.resize(binary.len() + 10, 0); + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected unknown table").major_status(), + StatusCode::UNKNOWN_TABLE_TYPE + ); + + // duplicate table + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version + binary.push(3); // table count + binary.push(1); // table type + binary.push(0); // table offset + binary.push(10); // table length + binary.push(2); // table type + binary.push(10); // table offset + binary.push(10); // table length + binary.push(1); // table type + binary.push(20); // table offset + binary.push(10); // table length + binary.resize(binary.len() + 5000, 0); + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected table offset overflow") + .major_status(), + StatusCode::DUPLICATE_TABLE + ); +} + +#[test] +#[allow(clippy::same_item_push)] +fn malformed_simple() { + // empty binary + let binary = vec![]; + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected malformed binary").major_status(), + StatusCode::BAD_MAGIC + ); + + // under-sized binary + let binary = vec![0u8, 0u8, 0u8]; + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected malformed binary").major_status(), + StatusCode::BAD_MAGIC + ); + + // bad magic + let binary = vec![0u8; 4]; + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected bad magic").major_status(), + StatusCode::BAD_MAGIC + ); + + // only magic + let binary = BinaryConstants::MOVE_MAGIC.to_vec(); + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected malformed binary").major_status(), + StatusCode::MALFORMED + ); + + // bad version + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend((VERSION_MAX.checked_add(1).unwrap()).to_le_bytes()); // version + binary.push(10); // table count + binary.push(0); // rest of binary + let res = CompiledModule::deserialize_with_defaults(&binary); + assert_eq!( + res.expect_err("Expected unknown version").major_status(), + StatusCode::UNKNOWN_VERSION + ); + + // versioned tests + for version in VERSION_1..VERSION_MAX { + malformed_simple_versioned_test(version); + } +} + +#[test] +fn max_version_lower_than_hardcoded() { + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend((VERSION_MAX).to_le_bytes()); // version + binary.push(10); // table count + binary.push(0); // rest of binary + + let res = CompiledModule::deserialize_with_config( + &binary, + &BinaryConfig::legacy(VERSION_MAX.checked_sub(1).unwrap(), false), + ); + assert_eq!( + res.expect_err("Expected unknown version").major_status(), + StatusCode::UNKNOWN_VERSION + ); +} + +#[test] +fn deserialize_trailing_bytes() { + let module = basic_test_module(); + let bytes = { + let mut v = vec![]; + module.serialize(&mut v).unwrap(); + v + }; + let test = |bytes| { + // ok with flag false + CompiledModule::deserialize_with_config( + bytes, + &BinaryConfig::with_extraneous_bytes_check(false), + ) + .unwrap(); + // error with flag true + let status_code = CompiledModule::deserialize_with_config( + bytes, + &BinaryConfig::with_extraneous_bytes_check(true), + ) + .unwrap_err() + .major_status(); + assert_eq!(status_code, StatusCode::TRAILING_BYTES); + }; + // simple trailing byte + let test1 = { + let mut v = bytes.clone(); + v.push(0); + v + }; + test(&test1); + + // many bytes + let test2 = { + let mut v = bytes.clone(); + v.push(3); + v.push(1); + v.push(0); + v.push(10); + v + }; + test(&test2); + + // another module + let test3 = { + let mut v = bytes.clone(); + v.extend(bytes); + v + }; + test(&test3); +} + +#[test] +fn no_metadata() { + let test = |bytes| { + // ok with flag false + CompiledModule::deserialize_with_config( + bytes, + &BinaryConfig::with_extraneous_bytes_check(false), + ) + .unwrap(); + // error with flag true + let status_code = CompiledModule::deserialize_with_config( + bytes, + &BinaryConfig::with_extraneous_bytes_check(true), + ) + .unwrap_err() + .major_status(); + assert_eq!(status_code, StatusCode::MALFORMED); + }; + // empty metadata + let mut module = basic_test_module(); + module.metadata.push(Metadata { + key: vec![], + value: vec![], + }); + let test2 = { + let mut v = vec![]; + module.serialize(&mut v).unwrap(); + v + }; + test(&test2); + + // lots of metadata + let metadata_bytes = { + let module = basic_test_module(); + let mut v = vec![]; + module.serialize(&mut v).unwrap(); + v + }; + let mut module = basic_test_module(); + module.metadata.push(Metadata { + key: metadata_bytes.clone(), + value: metadata_bytes.clone(), + }); + module.metadata.push(Metadata { + key: metadata_bytes.clone(), + value: metadata_bytes.clone(), + }); + let test2 = { + let mut v = vec![]; + module.serialize(&mut v).unwrap(); + v + }; + test(&test2); +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/mod.rs b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/mod.rs new file mode 100644 index 000000000..ce190b99f --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/mod.rs @@ -0,0 +1,11 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +mod binary_limits_tests; +mod binary_tests; +mod compatibility_tests; +mod control_flow_graph_tests; +mod deserializer_tests; +mod number_tests; +mod signature_token_tests; diff --git a/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/number_tests.rs b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/number_tests.rs new file mode 100644 index 000000000..b99e94bb6 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/number_tests.rs @@ -0,0 +1,118 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::file_format_common::*; +use proptest::prelude::*; +use std::io::{Cursor, Read}; + +// verify all bytes in the vector have the high bit set except the last one +fn check_vector(buf: &[u8]) { + let mut last_byte: bool = false; + for byte in buf { + assert!(!last_byte); + if *byte & 0x80 == 0 { + last_byte = true; + } + if !last_byte { + assert!(*byte & 0x80 > 0, "{} & 0x80", *byte); + } + } + assert!(last_byte); +} + +fn uleb128_test_u64(value: u64, expected_bytes: usize) { + let mut buf = BinaryData::new(); + write_u64_as_uleb128(&mut buf, value).expect("serialization should work"); + assert_eq!(buf.len(), expected_bytes); + let buf = buf.into_inner(); + check_vector(&buf); + let mut cursor = Cursor::new(&buf[..]); + let val = read_uleb128_as_u64(&mut cursor).expect("deserialization should work"); + assert_eq!(value, val); +} + +#[test] +fn uleb128_test() { + uleb128_test_u64(0, 1); + let mut n: usize = 1; + while n * 7 < 64 { + let exp = (n * 7) as u32; + uleb128_test_u64(2u64.pow(exp) - 1, n); + uleb128_test_u64(2u64.pow(exp), n + 1); + n += 1; + } + uleb128_test_u64(u64::max_value() - 1, 10); + uleb128_test_u64(u64::max_value(), 10); +} + +#[test] +fn uleb128_malformed_test() { + assert!(read_uleb128_as_u64(&mut Cursor::new(&[])).is_err()); + assert!(read_uleb128_as_u64(&mut Cursor::new(&[0x80])).is_err()); + assert!(read_uleb128_as_u64(&mut Cursor::new(&[0x80, 0x80])).is_err()); + assert!(read_uleb128_as_u64(&mut Cursor::new(&[0x80, 0x80, 0x80, 0x80])).is_err()); + assert!(read_uleb128_as_u64(&mut Cursor::new(&[ + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x2 + ])) + .is_err()); +} + +#[test] +fn uleb128_canonicity_test() { + assert!(read_uleb128_as_u64(&mut Cursor::new(&[0x80, 0x00])).is_err()); + assert!(read_uleb128_as_u64(&mut Cursor::new(&[0x80, 0x00, 0x00])).is_err()); + assert!(read_uleb128_as_u64(&mut Cursor::new(&[0x80, 0x80, 0x80, 0x80, 0x0f])).is_ok()); + assert!(read_uleb128_as_u64(&mut Cursor::new(&[ + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1 + ])) + .is_ok()); +} + +proptest! { + #[test] + fn uleb128_roundtrip(input in any::()) { + let mut serialized = BinaryData::new(); + write_u64_as_uleb128(&mut serialized, input).expect("serialization should work"); + let serialized = serialized.into_inner(); + let mut cursor = Cursor::new(&serialized[..]); + let output = read_uleb128_as_u64(&mut cursor).expect("deserialization should work"); + prop_assert_eq!(input, output); + } + + #[test] + fn u16_roundtrip(input in any::()) { + let mut serialized = BinaryData::new(); + write_u16(&mut serialized, input).expect("serialization should work"); + let serialized = serialized.into_inner(); + let mut cursor = Cursor::new(&serialized[..]); + let mut u16_bytes = [0; 2]; + cursor.read_exact(&mut u16_bytes).expect("deserialization should work"); + let output = u16::from_le_bytes(u16_bytes); + prop_assert_eq!(input, output); + } + + #[test] + fn u32_roundtrip(input in any::()) { + let mut serialized = BinaryData::new(); + write_u32(&mut serialized, input).expect("serialization should work"); + let serialized = serialized.into_inner(); + let mut cursor = Cursor::new(&serialized[..]); + let mut u32_bytes = [0; 4]; + cursor.read_exact(&mut u32_bytes).expect("deserialization should work"); + let output = u32::from_le_bytes(u32_bytes); + prop_assert_eq!(input, output); + } + + #[test] + fn u64_roundtrip(input in any::()) { + let mut serialized = BinaryData::new(); + write_u64(&mut serialized, input).expect("serialization should work"); + let serialized = serialized.into_inner(); + let mut cursor = Cursor::new(&serialized[..]); + let mut u64_bytes = [0; 8]; + cursor.read_exact(&mut u64_bytes).expect("deserialization should work"); + let output = u64::from_le_bytes(u64_bytes); + prop_assert_eq!(input, output); + } +} diff --git a/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/signature_token_tests.rs b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/signature_token_tests.rs new file mode 100644 index 000000000..c2e2d8213 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_binary_format/unit_tests/signature_token_tests.rs @@ -0,0 +1,89 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + deserializer::load_signature_token_test_entry, + file_format::{SignatureToken, StructHandleIndex}, + file_format_common::{BinaryData, SerializedType, SIGNATURE_TOKEN_DEPTH_MAX}, + serializer::{serialize_signature_token, serialize_signature_token_unchecked}, +}; +use std::io::Cursor; + +#[test] +fn serialize_and_deserialize_nested_types_max() { + let mut ty = SignatureToken::Struct(StructHandleIndex::new(0)); + for _ in 1..SIGNATURE_TOKEN_DEPTH_MAX { + ty = SignatureToken::Vector(Box::new(ty)); + let mut binary = BinaryData::new(); + serialize_signature_token(&mut binary, &ty).expect("serialization should succeed"); + + let cursor = Cursor::new(binary.as_inner()); + load_signature_token_test_entry(cursor).expect("deserialization should succeed"); + } +} + +#[test] +fn serialize_nested_types_too_deep() { + let mut ty = SignatureToken::Struct(StructHandleIndex::new(0)); + for _ in 1..SIGNATURE_TOKEN_DEPTH_MAX { + ty = SignatureToken::Vector(Box::new(ty)); + } + + for _ in 0..10 { + ty = SignatureToken::Vector(Box::new(ty)); + + let mut binary = BinaryData::new(); + serialize_signature_token(&mut binary, &ty).expect_err("serialization should fail"); + + let mut binary = BinaryData::new(); + serialize_signature_token_unchecked(&mut binary, &ty) + .expect("serialization (unchecked) should succeed"); + + let cursor = Cursor::new(binary.as_inner()); + load_signature_token_test_entry(cursor).expect_err("deserialization should fail"); + } +} + +#[test] +fn deserialize_struct_inst_arity_0() { + let cursor = Cursor::new( + [ + SerializedType::STRUCT_INST as u8, + 0x0, /* struct handle idx */ + 0x0, /* arity */ + SerializedType::BOOL as u8, + ] + .as_slice(), + ); + load_signature_token_test_entry(cursor).expect_err("deserialization should fail"); +} + +#[test] +fn deserialize_struct_inst_arity_1() { + let cursor = Cursor::new( + [ + SerializedType::STRUCT_INST as u8, + 0x0, /* struct handle idx */ + 0x1, /* arity */ + SerializedType::BOOL as u8, + ] + .as_slice(), + ); + load_signature_token_test_entry(cursor).expect("deserialization should succeed"); +} + +#[test] +fn deserialize_struct_inst_arity_2() { + let cursor = Cursor::new( + [ + SerializedType::STRUCT_INST as u8, + 0x0, /* struct handle idx */ + 0x2, /* arity */ + SerializedType::BOOL as u8, + SerializedType::BOOL as u8, + ] + .as_slice(), + ); + load_signature_token_test_entry(cursor).expect("deserialization should succeed"); +} diff --git a/CoqOfRust/move_sui/translations/move_bytecode_verifier/ability_field_requirements.rs b/CoqOfRust/move_sui/translations/move_bytecode_verifier/ability_field_requirements.rs new file mode 100644 index 000000000..e90c86efa --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_bytecode_verifier/ability_field_requirements.rs @@ -0,0 +1,50 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! This module implements a checker for verifying that all of the struct's fields satisfy the +//! abilities required by the struct's abilities +use move_binary_format::{ + errors::{verification_error, Location, PartialVMResult, VMResult}, + file_format::{AbilitySet, CompiledModule, StructFieldInformation, TableIndex}, + IndexKind, +}; +use move_core_types::vm_status::StatusCode; + +pub fn verify_module(module: &CompiledModule) -> VMResult<()> { + verify_module_impl(module).map_err(|e| e.finish(Location::Module(module.self_id()))) +} + +fn verify_module_impl(module: &CompiledModule) -> PartialVMResult<()> { + for (idx, struct_def) in module.struct_defs().iter().enumerate() { + let sh = module.struct_handle_at(struct_def.struct_handle); + let fields = match &struct_def.field_information { + StructFieldInformation::Native => continue, + StructFieldInformation::Declared(fields) => fields, + }; + let required_abilities = sh + .abilities + .into_iter() + .map(|a| a.requires()) + .fold(AbilitySet::EMPTY, |acc, required| acc | required); + // Assume type parameters have all abilities, as the struct's abilities will be dependent on + // them + let type_parameter_abilities = sh + .type_parameters + .iter() + .map(|_| AbilitySet::ALL) + .collect::>(); + for field in fields { + let field_abilities = + module.abilities(&field.signature.0, &type_parameter_abilities)?; + if !required_abilities.is_subset(field_abilities) { + return Err(verification_error( + StatusCode::FIELD_MISSING_TYPE_ABILITY, + IndexKind::StructDefinition, + idx as TableIndex, + )); + } + } + } + Ok(()) +} diff --git a/CoqOfRust/move_sui/translations/move_bytecode_verifier/absint.rs b/CoqOfRust/move_sui/translations/move_bytecode_verifier/absint.rs new file mode 100644 index 000000000..9f11fb5f7 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_bytecode_verifier/absint.rs @@ -0,0 +1,228 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use move_binary_format::{ + control_flow_graph::{BlockId, ControlFlowGraph, VMControlFlowGraph}, + errors::PartialVMResult, + file_format::{ + AbilitySet, Bytecode, CodeOffset, CodeUnit, FunctionDefinitionIndex, FunctionHandle, + Signature, + }, + CompiledModule, +}; +use move_bytecode_verifier_meter::{Meter, Scope}; +use std::collections::BTreeMap; + +/// A `FunctionContext` holds all the information needed by the verifier for `FunctionDefinition`.` +/// A control flow graph is built for a function when the `FunctionContext` is created. +pub struct FunctionContext<'a> { + index: Option, + code: &'a CodeUnit, + parameters: &'a Signature, + return_: &'a Signature, + locals: &'a Signature, + type_parameters: &'a [AbilitySet], + cfg: VMControlFlowGraph, +} + +/// Trait for finite-height abstract domains. Infinite height domains would require a more complex +/// trait with widening and a partial order. +pub trait AbstractDomain: Clone + Sized { + fn join( + &mut self, + other: &Self, + meter: &mut (impl Meter + ?Sized), + ) -> PartialVMResult; +} + +#[derive(Debug)] +pub enum JoinResult { + Changed, + Unchanged, +} + +#[allow(dead_code)] +#[derive(Clone)] +pub struct BlockInvariant { + /// Precondition of the block + pre: State, +} + +/// A map from block id's to the pre/post of each block after a fixed point is reached. +#[allow(dead_code)] +pub type InvariantMap = BTreeMap>; + +/// Costs for metered verification +const ANALYZE_FUNCTION_BASE_COST: u128 = 10; +const EXECUTE_BLOCK_BASE_COST: u128 = 10; +const PER_BACKEDGE_COST: u128 = 10; +const PER_SUCCESSOR_COST: u128 = 10; + +/// Take a pre-state + instruction and mutate it to produce a post-state +/// Auxiliary data can be stored in self. +pub trait TransferFunctions { + type State: AbstractDomain; + type Error; + + /// Execute local@instr found at index local@index in the current basic block from pre-state + /// local@pre. + /// Should return an AnalysisError if executing the instruction is unsuccessful, and () if + /// the effects of successfully executing local@instr have been reflected by mutatating + /// local@pre. + /// Auxilary data from the analysis that is not part of the abstract state can be collected by + /// mutating local@self. + /// The last instruction index in the current block is local@last_index. Knowing this + /// information allows clients to detect the end of a basic block and special-case appropriately + /// (e.g., normalizing the abstract state before a join). + fn execute( + &mut self, + pre: &mut Self::State, + instr: &Bytecode, + index: CodeOffset, + last_index: CodeOffset, + meter: &mut (impl Meter + ?Sized), + ) -> PartialVMResult<()>; +} + +pub trait AbstractInterpreter: TransferFunctions { + /// Analyze procedure local@function_context starting from pre-state local@initial_state. + fn analyze_function( + &mut self, + initial_state: Self::State, + function_context: &FunctionContext, + meter: &mut (impl Meter + ?Sized), + ) -> PartialVMResult<()> { + meter.add(Scope::Function, ANALYZE_FUNCTION_BASE_COST)?; + let mut inv_map = InvariantMap::new(); + let entry_block_id = function_context.cfg().entry_block_id(); + let mut next_block = Some(entry_block_id); + inv_map.insert(entry_block_id, BlockInvariant { pre: initial_state }); + + while let Some(block_id) = next_block { + let block_invariant = match inv_map.get_mut(&block_id) { + Some(invariant) => invariant, + None => { + // This can only happen when all predecessors have errors, + // so skip the block and move on to the next one + next_block = function_context.cfg().next_block(block_id); + continue; + } + }; + + let pre_state = &block_invariant.pre; + // Note: this will stop analysis after the first error occurs, to avoid the risk of + // subsequent crashes + let post_state = self.execute_block(block_id, pre_state, function_context, meter)?; + + let mut next_block_candidate = function_context.cfg().next_block(block_id); + // propagate postcondition of this block to successor blocks + for successor_block_id in function_context.cfg().successors(block_id) { + meter.add(Scope::Function, PER_SUCCESSOR_COST)?; + match inv_map.get_mut(successor_block_id) { + Some(next_block_invariant) => { + let join_result = { + let old_pre = &mut next_block_invariant.pre; + old_pre.join(&post_state, meter) + }?; + match join_result { + JoinResult::Unchanged => { + // Pre is the same after join. Reanalyzing this block would produce + // the same post + } + JoinResult::Changed => { + // If the cur->successor is a back edge, jump back to the beginning + // of the loop, instead of the normal next block + if function_context + .cfg() + .is_back_edge(block_id, *successor_block_id) + { + meter.add(Scope::Function, PER_BACKEDGE_COST)?; + next_block_candidate = Some(*successor_block_id); + break; + } + } + } + } + None => { + // Haven't visited the next block yet. Use the post of the current block as + // its pre + inv_map.insert( + *successor_block_id, + BlockInvariant { + pre: post_state.clone(), + }, + ); + } + } + } + next_block = next_block_candidate; + } + Ok(()) + } + + fn execute_block( + &mut self, + block_id: BlockId, + pre_state: &Self::State, + function_context: &FunctionContext, + meter: &mut (impl Meter + ?Sized), + ) -> PartialVMResult { + meter.add(Scope::Function, EXECUTE_BLOCK_BASE_COST)?; + let mut state_acc = pre_state.clone(); + let block_end = function_context.cfg().block_end(block_id); + for offset in function_context.cfg().instr_indexes(block_id) { + let instr = &function_context.code().code[offset as usize]; + self.execute(&mut state_acc, instr, offset, block_end, meter)? + } + Ok(state_acc) + } +} + +impl<'a> FunctionContext<'a> { + // Creates a `FunctionContext` for a module function. + pub fn new( + module: &'a CompiledModule, + index: FunctionDefinitionIndex, + code: &'a CodeUnit, + function_handle: &'a FunctionHandle, + ) -> Self { + Self { + index: Some(index), + code, + parameters: module.signature_at(function_handle.parameters), + return_: module.signature_at(function_handle.return_), + locals: module.signature_at(code.locals), + type_parameters: &function_handle.type_parameters, + cfg: VMControlFlowGraph::new(&code.code), + } + } + + pub fn index(&self) -> Option { + self.index + } + + pub fn code(&self) -> &CodeUnit { + self.code + } + + pub fn parameters(&self) -> &Signature { + self.parameters + } + + pub fn return_(&self) -> &Signature { + self.return_ + } + + pub fn locals(&self) -> &Signature { + self.locals + } + + pub fn type_parameters(&self) -> &[AbilitySet] { + self.type_parameters + } + + pub fn cfg(&self) -> &VMControlFlowGraph { + &self.cfg + } +} diff --git a/CoqOfRust/move_sui/translations/move_bytecode_verifier/acquires_list_verifier.rs b/CoqOfRust/move_sui/translations/move_bytecode_verifier/acquires_list_verifier.rs new file mode 100644 index 000000000..cab0b6b9a --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_bytecode_verifier/acquires_list_verifier.rs @@ -0,0 +1,225 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! This module implements a checker for verifying properties about the acquires list on function +//! definitions. Function definitions must annotate the global resources (declared in that module) +//! accesssed by `BorrowGlobal`, `MoveFrom`, and any transitive function calls +//! The list of acquired resources (stored in `FunctionDefinition`'s `acquires_global_resources` +//! field) must have: +//! - No duplicate resources (checked by `check_duplication`) +//! - No missing resources (any resource acquired must be present) +//! - No additional resources (no extraneous resources not actually acquired) + +use std::collections::{BTreeSet, HashMap}; + +use move_binary_format::{ + errors::{PartialVMError, PartialVMResult}, + file_format::{ + Bytecode, CodeOffset, CompiledModule, FunctionDefinition, FunctionDefinitionIndex, + FunctionHandle, FunctionHandleIndex, StructDefinitionIndex, + }, + safe_unwrap, +}; +use move_bytecode_verifier_meter::Meter; +use move_core_types::vm_status::StatusCode; + +pub(crate) struct AcquiresVerifier<'a> { + module: &'a CompiledModule, + current_function: FunctionDefinitionIndex, + annotated_acquires: BTreeSet, + actual_acquires: BTreeSet, + handle_to_def: HashMap, +} + +impl<'a> AcquiresVerifier<'a> { + pub(crate) fn verify( + module: &'a CompiledModule, + index: FunctionDefinitionIndex, + function_definition: &'a FunctionDefinition, + _meter: &mut (impl Meter + ?Sized), // currently unused + ) -> PartialVMResult<()> { + let annotated_acquires: BTreeSet<_> = function_definition + .acquires_global_resources + .iter() + .cloned() + .collect(); + let mut handle_to_def = HashMap::new(); + for func_def in module.function_defs() { + handle_to_def.insert(func_def.function, func_def); + } + let mut verifier = Self { + module, + current_function: index, + annotated_acquires, + actual_acquires: BTreeSet::new(), + handle_to_def, + }; + + for (offset, instruction) in safe_unwrap!(function_definition.code.as_ref()) + .code + .iter() + .enumerate() + { + verifier.verify_instruction(instruction, offset as CodeOffset)? + } + + for annotation in verifier.annotated_acquires { + if !verifier.actual_acquires.contains(&annotation) { + return Err(PartialVMError::new( + StatusCode::EXTRANEOUS_ACQUIRES_ANNOTATION, + )); + } + + let struct_def = safe_unwrap!(module.struct_defs().get(annotation.0 as usize)); + let struct_handle = module.struct_handle_at(struct_def.struct_handle); + if !struct_handle.abilities.has_key() { + return Err(PartialVMError::new(StatusCode::INVALID_ACQUIRES_ANNOTATION)); + } + } + + Ok(()) + } + + fn verify_instruction( + &mut self, + instruction: &Bytecode, + offset: CodeOffset, + ) -> PartialVMResult<()> { + match instruction { + Bytecode::Call(idx) => self.call_acquire(*idx, offset), + Bytecode::CallGeneric(idx) => { + let fi = self.module.function_instantiation_at(*idx); + self.call_acquire(fi.handle, offset) + } + Bytecode::MoveFromDeprecated(idx) + | Bytecode::MutBorrowGlobalDeprecated(idx) + | Bytecode::ImmBorrowGlobalDeprecated(idx) => self.struct_acquire(*idx, offset), + Bytecode::MoveFromGenericDeprecated(idx) + | Bytecode::MutBorrowGlobalGenericDeprecated(idx) + | Bytecode::ImmBorrowGlobalGenericDeprecated(idx) => { + let si = self.module.struct_instantiation_at(*idx); + self.struct_acquire(si.def, offset) + } + + Bytecode::Pop + | Bytecode::BrTrue(_) + | Bytecode::BrFalse(_) + | Bytecode::Abort + | Bytecode::Branch(_) + | Bytecode::Nop + | Bytecode::Ret + | Bytecode::StLoc(_) + | Bytecode::MoveLoc(_) + | Bytecode::CopyLoc(_) + | Bytecode::ImmBorrowLoc(_) + | Bytecode::MutBorrowLoc(_) + | Bytecode::FreezeRef + | Bytecode::MutBorrowField(_) + | Bytecode::MutBorrowFieldGeneric(_) + | Bytecode::ImmBorrowField(_) + | Bytecode::ImmBorrowFieldGeneric(_) + | Bytecode::LdU8(_) + | Bytecode::LdU16(_) + | Bytecode::LdU32(_) + | Bytecode::LdU64(_) + | Bytecode::LdU128(_) + | Bytecode::LdU256(_) + | Bytecode::LdConst(_) + | Bytecode::LdTrue + | Bytecode::LdFalse + | Bytecode::Pack(_) + | Bytecode::PackGeneric(_) + | Bytecode::Unpack(_) + | Bytecode::UnpackGeneric(_) + | Bytecode::ReadRef + | Bytecode::WriteRef + | Bytecode::CastU8 + | Bytecode::CastU16 + | Bytecode::CastU32 + | Bytecode::CastU64 + | Bytecode::CastU128 + | Bytecode::CastU256 + | Bytecode::Add + | Bytecode::Sub + | Bytecode::Mul + | Bytecode::Mod + | Bytecode::Div + | Bytecode::BitOr + | Bytecode::BitAnd + | Bytecode::Xor + | Bytecode::Shl + | Bytecode::Shr + | Bytecode::Or + | Bytecode::And + | Bytecode::Not + | Bytecode::Eq + | Bytecode::Neq + | Bytecode::Lt + | Bytecode::Gt + | Bytecode::Le + | Bytecode::Ge + | Bytecode::ExistsDeprecated(_) + | Bytecode::ExistsGenericDeprecated(_) + | Bytecode::MoveToDeprecated(_) + | Bytecode::MoveToGenericDeprecated(_) + | Bytecode::VecPack(..) + | Bytecode::VecLen(_) + | Bytecode::VecImmBorrow(_) + | Bytecode::VecMutBorrow(_) + | Bytecode::VecPushBack(_) + | Bytecode::VecPopBack(_) + | Bytecode::VecUnpack(..) + | Bytecode::VecSwap(_) => Ok(()), + } + } + + fn call_acquire( + &mut self, + fh_idx: FunctionHandleIndex, + offset: CodeOffset, + ) -> PartialVMResult<()> { + let function_handle = self.module.function_handle_at(fh_idx); + let mut function_acquired_resources = + self.function_acquired_resources(function_handle, fh_idx); + for acquired_resource in &function_acquired_resources { + if !self.annotated_acquires.contains(acquired_resource) { + return Err(self.error(StatusCode::MISSING_ACQUIRES_ANNOTATION, offset)); + } + } + self.actual_acquires + .append(&mut function_acquired_resources); + Ok(()) + } + + fn struct_acquire( + &mut self, + sd_idx: StructDefinitionIndex, + offset: CodeOffset, + ) -> PartialVMResult<()> { + if self.annotated_acquires.contains(&sd_idx) { + self.actual_acquires.insert(sd_idx); + Ok(()) + } else { + Err(self.error(StatusCode::MISSING_ACQUIRES_ANNOTATION, offset)) + } + } + + fn function_acquired_resources( + &self, + function_handle: &FunctionHandle, + fh_idx: FunctionHandleIndex, + ) -> BTreeSet { + if function_handle.module != self.module.self_handle_idx() { + return BTreeSet::new(); + } + match self.handle_to_def.get(&fh_idx) { + Some(func_def) => func_def.acquires_global_resources.iter().cloned().collect(), + None => BTreeSet::new(), + } + } + + fn error(&self, status: StatusCode, offset: CodeOffset) -> PartialVMError { + PartialVMError::new(status).at_code_offset(self.current_function, offset) + } +} diff --git a/CoqOfRust/move_sui/translations/move_bytecode_verifier/check_duplication.rs b/CoqOfRust/move_sui/translations/move_bytecode_verifier/check_duplication.rs new file mode 100644 index 000000000..6e26a4b63 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_bytecode_verifier/check_duplication.rs @@ -0,0 +1,312 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! This module implements a checker for verifying that each vector in a CompiledModule contains +//! distinct values. Successful verification implies that an index in vector can be used to +//! uniquely name the entry at that index. Additionally, the checker also verifies the +//! following: +//! - struct and field definitions are consistent +//! - the handles in struct and function definitions point to the self module index +//! - all struct and function handles pointing to the self module index have a definition +use move_binary_format::{ + errors::{verification_error, Location, PartialVMResult, VMResult}, + file_format::{ + CompiledModule, Constant, FunctionHandle, FunctionHandleIndex, FunctionInstantiation, + ModuleHandle, Signature, StructFieldInformation, StructHandle, StructHandleIndex, + TableIndex, + }, + IndexKind, +}; +use move_core_types::{ + account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode, +}; +use std::{collections::HashSet, hash::Hash}; + +pub struct DuplicationChecker<'a> { + module: &'a CompiledModule, +} + +impl<'a> DuplicationChecker<'a> { + pub fn verify_module(module: &'a CompiledModule) -> VMResult<()> { + Self::verify_module_impl(module).map_err(|e| e.finish(Location::Module(module.self_id()))) + } + + fn verify_module_impl(module: &'a CompiledModule) -> PartialVMResult<()> { + Self::check_identifiers(module.identifiers())?; + Self::check_address_identifiers(module.address_identifiers())?; + Self::check_constants(module.constant_pool())?; + Self::check_signatures(module.signatures())?; + Self::check_module_handles(module.module_handles())?; + Self::check_module_handles(module.friend_decls())?; + Self::check_struct_handles(module.struct_handles())?; + Self::check_function_handles(module.function_handles())?; + Self::check_function_instantiations(module.function_instantiations())?; + + let checker = Self { module }; + checker.check_field_handles()?; + checker.check_field_instantiations()?; + checker.check_function_defintions()?; + checker.check_struct_definitions()?; + checker.check_struct_instantiations() + } + + fn check_identifiers(identifiers: &[Identifier]) -> PartialVMResult<()> { + match Self::first_duplicate_element(identifiers) { + Some(idx) => Err(verification_error( + StatusCode::DUPLICATE_ELEMENT, + IndexKind::Identifier, + idx, + )), + None => Ok(()), + } + } + + fn check_address_identifiers(address_identifiers: &[AccountAddress]) -> PartialVMResult<()> { + match Self::first_duplicate_element(address_identifiers) { + Some(idx) => Err(verification_error( + StatusCode::DUPLICATE_ELEMENT, + IndexKind::AddressIdentifier, + idx, + )), + None => Ok(()), + } + } + + fn check_constants(constant_pool: &[Constant]) -> PartialVMResult<()> { + match Self::first_duplicate_element(constant_pool) { + Some(idx) => Err(verification_error( + StatusCode::DUPLICATE_ELEMENT, + IndexKind::ConstantPool, + idx, + )), + None => Ok(()), + } + } + + fn check_signatures(signatures: &[Signature]) -> PartialVMResult<()> { + match Self::first_duplicate_element(signatures) { + Some(idx) => Err(verification_error( + StatusCode::DUPLICATE_ELEMENT, + IndexKind::Signature, + idx, + )), + None => Ok(()), + } + } + + fn check_module_handles(module_handles: &[ModuleHandle]) -> PartialVMResult<()> { + match Self::first_duplicate_element(module_handles) { + Some(idx) => Err(verification_error( + StatusCode::DUPLICATE_ELEMENT, + IndexKind::ModuleHandle, + idx, + )), + None => Ok(()), + } + } + + // StructHandles - module and name define uniqueness + fn check_struct_handles(struct_handles: &[StructHandle]) -> PartialVMResult<()> { + match Self::first_duplicate_element(struct_handles.iter().map(|x| (x.module, x.name))) { + Some(idx) => Err(verification_error( + StatusCode::DUPLICATE_ELEMENT, + IndexKind::StructHandle, + idx, + )), + None => Ok(()), + } + } + + fn check_function_instantiations( + function_instantiations: &[FunctionInstantiation], + ) -> PartialVMResult<()> { + match Self::first_duplicate_element(function_instantiations) { + Some(idx) => Err(verification_error( + StatusCode::DUPLICATE_ELEMENT, + IndexKind::FunctionInstantiation, + idx, + )), + None => Ok(()), + } + } + + // FunctionHandles - module and name define uniqueness + fn check_function_handles(function_handles: &[FunctionHandle]) -> PartialVMResult<()> { + match Self::first_duplicate_element(function_handles.iter().map(|x| (x.module, x.name))) { + Some(idx) => Err(verification_error( + StatusCode::DUPLICATE_ELEMENT, + IndexKind::FunctionHandle, + idx, + )), + None => Ok(()), + } + } + + // + // Module only code + // + + fn check_field_handles(&self) -> PartialVMResult<()> { + match Self::first_duplicate_element(self.module.field_handles()) { + Some(idx) => Err(verification_error( + StatusCode::DUPLICATE_ELEMENT, + IndexKind::FieldHandle, + idx, + )), + None => Ok(()), + } + } + + fn check_struct_instantiations(&self) -> PartialVMResult<()> { + match Self::first_duplicate_element(self.module.struct_instantiations()) { + Some(idx) => Err(verification_error( + StatusCode::DUPLICATE_ELEMENT, + IndexKind::StructDefInstantiation, + idx, + )), + None => Ok(()), + } + } + + fn check_field_instantiations(&self) -> PartialVMResult<()> { + if let Some(idx) = Self::first_duplicate_element(self.module.field_instantiations()) { + return Err(verification_error( + StatusCode::DUPLICATE_ELEMENT, + IndexKind::FieldInstantiation, + idx, + )); + } + Ok(()) + } + + fn check_struct_definitions(&self) -> PartialVMResult<()> { + // StructDefinition - contained StructHandle defines uniqueness + if let Some(idx) = + Self::first_duplicate_element(self.module.struct_defs().iter().map(|x| x.struct_handle)) + { + return Err(verification_error( + StatusCode::DUPLICATE_ELEMENT, + IndexKind::StructDefinition, + idx, + )); + } + // Field names in structs must be unique + for (struct_idx, struct_def) in self.module.struct_defs().iter().enumerate() { + let fields = match &struct_def.field_information { + StructFieldInformation::Native => continue, + StructFieldInformation::Declared(fields) => fields, + }; + if fields.is_empty() { + return Err(verification_error( + StatusCode::ZERO_SIZED_STRUCT, + IndexKind::StructDefinition, + struct_idx as TableIndex, + )); + } + if let Some(idx) = Self::first_duplicate_element(fields.iter().map(|x| x.name)) { + return Err(verification_error( + StatusCode::DUPLICATE_ELEMENT, + IndexKind::FieldDefinition, + idx, + )); + } + } + // Check that each struct definition is pointing to the self module + if let Some(idx) = self.module.struct_defs().iter().position(|x| { + self.module.struct_handle_at(x.struct_handle).module != self.module.self_handle_idx() + }) { + return Err(verification_error( + StatusCode::INVALID_MODULE_HANDLE, + IndexKind::StructDefinition, + idx as TableIndex, + )); + } + // Check that each struct handle in self module is implemented (has a declaration) + let implemented_struct_handles: HashSet = self + .module + .struct_defs() + .iter() + .map(|x| x.struct_handle) + .collect(); + if let Some(idx) = (0..self.module.struct_handles().len()).position(|x| { + let y = StructHandleIndex::new(x as u16); + self.module.struct_handle_at(y).module == self.module.self_handle_idx() + && !implemented_struct_handles.contains(&y) + }) { + return Err(verification_error( + StatusCode::UNIMPLEMENTED_HANDLE, + IndexKind::StructHandle, + idx as TableIndex, + )); + } + Ok(()) + } + + fn check_function_defintions(&self) -> PartialVMResult<()> { + // FunctionDefinition - contained FunctionHandle defines uniqueness + if let Some(idx) = + Self::first_duplicate_element(self.module.function_defs().iter().map(|x| x.function)) + { + return Err(verification_error( + StatusCode::DUPLICATE_ELEMENT, + IndexKind::FunctionDefinition, + idx, + )); + } + // Acquires in function declarations contain unique struct definitions + for (idx, function_def) in self.module.function_defs().iter().enumerate() { + let acquires = function_def.acquires_global_resources.iter(); + if Self::first_duplicate_element(acquires).is_some() { + return Err(verification_error( + StatusCode::DUPLICATE_ACQUIRES_ANNOTATION, + IndexKind::FunctionDefinition, + idx as TableIndex, + )); + } + } + // Check that each function definition is pointing to the self module + if let Some(idx) = self.module.function_defs().iter().position(|x| { + self.module.function_handle_at(x.function).module != self.module.self_handle_idx() + }) { + return Err(verification_error( + StatusCode::INVALID_MODULE_HANDLE, + IndexKind::FunctionDefinition, + idx as TableIndex, + )); + } + // Check that each function handle in self module is implemented (has a declaration) + let implemented_function_handles: HashSet = self + .module + .function_defs() + .iter() + .map(|x| x.function) + .collect(); + if let Some(idx) = (0..self.module.function_handles().len()).position(|x| { + let y = FunctionHandleIndex::new(x as u16); + self.module.function_handle_at(y).module == self.module.self_handle_idx() + && !implemented_function_handles.contains(&y) + }) { + return Err(verification_error( + StatusCode::UNIMPLEMENTED_HANDLE, + IndexKind::FunctionHandle, + idx as TableIndex, + )); + } + Ok(()) + } + + fn first_duplicate_element(iter: T) -> Option + where + T: IntoIterator, + T::Item: Eq + Hash, + { + let mut uniq = HashSet::new(); + for (i, x) in iter.into_iter().enumerate() { + if !uniq.insert(x) { + return Some(i as TableIndex); + } + } + None + } +} diff --git a/CoqOfRust/move_sui/translations/move_bytecode_verifier/code_unit_verifier.rs b/CoqOfRust/move_sui/translations/move_bytecode_verifier/code_unit_verifier.rs new file mode 100644 index 000000000..6a4b80b2c --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_bytecode_verifier/code_unit_verifier.rs @@ -0,0 +1,149 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! This module implements the checker for verifying correctness of function bodies. +//! The overall verification is split between stack_usage_verifier.rs and +//! abstract_interpreter.rs. CodeUnitVerifier simply orchestrates calls into these two files. +use crate::{ + absint::FunctionContext, acquires_list_verifier::AcquiresVerifier, control_flow, locals_safety, + reference_safety, stack_usage_verifier::StackUsageVerifier, type_safety, +}; +use move_binary_format::{ + control_flow_graph::ControlFlowGraph, + errors::{Location, PartialVMError, PartialVMResult, VMResult}, + file_format::{ + CompiledModule, FunctionDefinition, FunctionDefinitionIndex, IdentifierIndex, TableIndex, + }, + IndexKind, +}; +use move_bytecode_verifier_meter::{Meter, Scope}; +use move_core_types::vm_status::StatusCode; +use move_vm_config::verifier::VerifierConfig; +use std::collections::HashMap; + +pub struct CodeUnitVerifier<'a> { + module: &'a CompiledModule, + function_context: FunctionContext<'a>, + name_def_map: &'a HashMap, +} + +impl<'a> CodeUnitVerifier<'a> { + pub fn verify_module( + verifier_config: &VerifierConfig, + module: &'a CompiledModule, + meter: &mut (impl Meter + ?Sized), + ) -> VMResult<()> { + Self::verify_module_impl(verifier_config, module, meter) + .map_err(|e| e.finish(Location::Module(module.self_id()))) + } + + fn verify_module_impl( + verifier_config: &VerifierConfig, + module: &CompiledModule, + meter: &mut (impl Meter + ?Sized), + ) -> PartialVMResult<()> { + let mut name_def_map = HashMap::new(); + for (idx, func_def) in module.function_defs().iter().enumerate() { + let fh = module.function_handle_at(func_def.function); + name_def_map.insert(fh.name, FunctionDefinitionIndex(idx as u16)); + } + let mut total_back_edges = 0; + for (idx, function_definition) in module.function_defs().iter().enumerate() { + let index = FunctionDefinitionIndex(idx as TableIndex); + let num_back_edges = Self::verify_function( + verifier_config, + index, + function_definition, + module, + &name_def_map, + meter, + ) + .map_err(|err| err.at_index(IndexKind::FunctionDefinition, index.0))?; + total_back_edges += num_back_edges; + } + if let Some(limit) = verifier_config.max_back_edges_per_module { + if total_back_edges > limit { + return Err(PartialVMError::new(StatusCode::TOO_MANY_BACK_EDGES)); + } + } + Ok(()) + } + + fn verify_function( + verifier_config: &VerifierConfig, + index: FunctionDefinitionIndex, + function_definition: &FunctionDefinition, + module: &CompiledModule, + name_def_map: &HashMap, + meter: &mut (impl Meter + ?Sized), + ) -> PartialVMResult { + meter.enter_scope( + module + .identifier_at(module.function_handle_at(function_definition.function).name) + .as_str(), + Scope::Function, + ); + // nothing to verify for native function + let code = match &function_definition.code { + Some(code) => code, + None => return Ok(0), + }; + + // create `FunctionContext` and `BinaryIndexedView` + let function_context = control_flow::verify_function( + verifier_config, + module, + index, + function_definition, + code, + meter, + )?; + + if let Some(limit) = verifier_config.max_basic_blocks { + if function_context.cfg().blocks().len() > limit { + return Err( + PartialVMError::new(StatusCode::TOO_MANY_BASIC_BLOCKS).at_code_offset(index, 0) + ); + } + } + + let num_back_edges = function_context.cfg().num_back_edges(); + if let Some(limit) = verifier_config.max_back_edges_per_function { + if num_back_edges > limit { + return Err( + PartialVMError::new(StatusCode::TOO_MANY_BACK_EDGES).at_code_offset(index, 0) + ); + } + } + + // verify + let code_unit_verifier = CodeUnitVerifier { + module, + function_context, + name_def_map, + }; + code_unit_verifier.verify_common(verifier_config, meter)?; + AcquiresVerifier::verify(module, index, function_definition, meter)?; + + meter.transfer(Scope::Function, Scope::Module, 1.0)?; + + Ok(num_back_edges) + } + + fn verify_common( + &self, + verifier_config: &VerifierConfig, + meter: &mut (impl Meter + ?Sized), + ) -> PartialVMResult<()> { + StackUsageVerifier::verify(verifier_config, self.module, &self.function_context, meter)?; + type_safety::verify(self.module, &self.function_context, meter)?; + locals_safety::verify(self.module, &self.function_context, meter)?; + reference_safety::verify( + self.module, + &self.function_context, + self.name_def_map, + meter, + ) + } +} diff --git a/CoqOfRust/move_sui/translations/move_bytecode_verifier/constants.rs b/CoqOfRust/move_sui/translations/move_bytecode_verifier/constants.rs new file mode 100644 index 000000000..f5c23ee94 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_bytecode_verifier/constants.rs @@ -0,0 +1,52 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! This module implements a checker for verifying that +//! - a constant's type only refers to primitive types +//! - a constant's data serializes correctly for that type +use move_binary_format::{ + errors::{verification_error, Location, PartialVMResult, VMResult}, + file_format::{CompiledModule, Constant, SignatureToken, TableIndex}, + IndexKind, +}; +use move_core_types::vm_status::StatusCode; + +pub fn verify_module(module: &CompiledModule) -> VMResult<()> { + verify_module_impl(module).map_err(|e| e.finish(Location::Module(module.self_id()))) +} + +fn verify_module_impl(module: &CompiledModule) -> PartialVMResult<()> { + for (idx, constant) in module.constant_pool().iter().enumerate() { + verify_constant(idx, constant)? + } + Ok(()) +} + +fn verify_constant(idx: usize, constant: &Constant) -> PartialVMResult<()> { + verify_constant_type(idx, &constant.type_)?; + verify_constant_data(idx, constant) +} + +fn verify_constant_type(idx: usize, type_: &SignatureToken) -> PartialVMResult<()> { + if type_.is_valid_for_constant() { + Ok(()) + } else { + Err(verification_error( + StatusCode::INVALID_CONSTANT_TYPE, + IndexKind::ConstantPool, + idx as TableIndex, + )) + } +} + +fn verify_constant_data(idx: usize, constant: &Constant) -> PartialVMResult<()> { + match constant.deserialize_constant() { + Some(_) => Ok(()), + None => Err(verification_error( + StatusCode::MALFORMED_CONSTANT_DATA, + IndexKind::ConstantPool, + idx as TableIndex, + )), + } +} diff --git a/CoqOfRust/move_sui/translations/move_bytecode_verifier/control_flow.rs b/CoqOfRust/move_sui/translations/move_bytecode_verifier/control_flow.rs new file mode 100644 index 000000000..f80df81a5 --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_bytecode_verifier/control_flow.rs @@ -0,0 +1,164 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! This module implements control flow checks. +//! +//! For bytecode versions 6 and up, the following properties are ensured: +//! - The CFG is not empty and the last block ends in an unconditional jump, so it's not possible to +//! fall off the end of a function. +//! - The CFG is reducible (and optionally max loop depth is bounded), to limit the potential for +//! pathologically long abstract interpretation runtimes (through poor choice of loop heads and +//! back edges). +//! +//! For bytecode versions 5 and below, delegates to `control_flow_v5`. +use crate::{ + absint::FunctionContext, + control_flow_v5, + loop_summary::{LoopPartition, LoopSummary}, +}; +use move_binary_format::{ + errors::{PartialVMError, PartialVMResult}, + file_format::{CodeOffset, CodeUnit, FunctionDefinition, FunctionDefinitionIndex}, + CompiledModule, +}; +use move_bytecode_verifier_meter::Meter; +use move_core_types::vm_status::StatusCode; +use move_vm_config::verifier::VerifierConfig; +use std::collections::BTreeSet; + +/// Perform control flow verification on the compiled function, returning its `FunctionContext` if +/// verification was successful. +pub fn verify_function<'a>( + verifier_config: &'a VerifierConfig, + module: &'a CompiledModule, + index: FunctionDefinitionIndex, + function_definition: &'a FunctionDefinition, + code: &'a CodeUnit, + _meter: &mut (impl Meter + ?Sized), // TODO: metering +) -> PartialVMResult> { + let function_handle = module.function_handle_at(function_definition.function); + + if module.version() <= 5 { + control_flow_v5::verify(verifier_config, Some(index), code)?; + Ok(FunctionContext::new(module, index, code, function_handle)) + } else { + verify_fallthrough(Some(index), code)?; + let function_context = FunctionContext::new(module, index, code, function_handle); + verify_reducibility(verifier_config, &function_context)?; + Ok(function_context) + } +} + +/// Check to make sure that the bytecode vector is non-empty and ends with a branching instruction. +fn verify_fallthrough( + current_function_opt: Option, + code: &CodeUnit, +) -> PartialVMResult<()> { + let current_function = current_function_opt.unwrap_or(FunctionDefinitionIndex(0)); + match code.code.last() { + None => Err(PartialVMError::new(StatusCode::EMPTY_CODE_UNIT)), + Some(last) if !last.is_unconditional_branch() => { + Err(PartialVMError::new(StatusCode::INVALID_FALL_THROUGH) + .at_code_offset(current_function, (code.code.len() - 1) as CodeOffset)) + } + Some(_) => Ok(()), + } +} + +/// Test that `function_context`'s control-flow graph is reducible using Tarjan's algorithm [1]. +/// Optionally test loop depth bounded by `verifier_config.max_loop_depth`. +/// +/// A CFG, `G`, with starting block `s` is reducible if and only if [2] any of the following +/// equivalent properties hold: +/// +/// 1. G has a unique set of back-edges `u -> v` where `v` dominates `u`, that corresponds to the +/// set of back-edges for any depth-first spanning tree of G. +/// +/// 2. Every loop in G contains a unique node `h` (the "head") which dominates all other nodes in +/// the loop. +/// +/// 3. G has a unique maximal (in terms of number of edges) acyclic sub-graph. +/// +/// 4. G can be reduced to a CFG containing just `s` through a sequence of the following two +/// operations: +/// a. Delete a cyclic edge `v -> v` +/// b. For an edge `e: u -> v` where `e` is the only incident edge to `v`, collapse `v` into `u` +/// by deleting `e` and `v` and replacing all `v -> w` edges with `u -> w` edges. +/// +/// Reducibility means that a control-flow graph can be decomposed into a series of nested loops +/// (strongly connected subgraphs), which leads to more predictable abstract interpretation +/// performance. +/// +/// ## References +/// +/// 1. Tarjan, R. 1974. Testing Flow Graph Reducibility. +/// 2. Hecht, M. S., Ullman J. D. 1974. Characterizations of Reducible Flow Graphs. +fn verify_reducibility<'a>( + verifier_config: &VerifierConfig, + function_context: &'a FunctionContext<'a>, +) -> PartialVMResult<()> { + let current_function = function_context + .index() + .unwrap_or(FunctionDefinitionIndex(0)); + let err = move |code: StatusCode, offset: CodeOffset| { + Err(PartialVMError::new(code).at_code_offset(current_function, offset)) + }; + + let summary = LoopSummary::new(function_context.cfg()); + let mut partition = LoopPartition::new(&summary); + + // Iterate through nodes in reverse pre-order so more deeply nested loops (which would appear + // later in the pre-order) are processed first. + for head in summary.preorder().rev() { + // If a node has no back edges, it is not a loop head, so doesn't need to be processed. + let back = summary.back_edges(head); + if back.is_empty() { + continue; + } + + // Collect the rest of the nodes in `head`'s loop, in `body`. Start with the nodes that + // jump back to the head, and grow `body` by repeatedly following predecessor edges until + // `head` is found again. + + let mut body = BTreeSet::new(); + for node in back { + let node = partition.containing_loop(*node); + + if node != head { + body.insert(node); + } + } + + let mut frontier: Vec<_> = body.iter().copied().collect(); + while let Some(node) = frontier.pop() { + for pred in summary.pred_edges(node) { + let pred = partition.containing_loop(*pred); + + // `pred` can eventually jump back to `head`, so is part of its body. If it is not + // a descendant of `head`, it implies that `head` does not dominate a node in its + // loop, therefore the CFG is not reducible, according to Property 1 (see doc + // comment). + if !summary.is_descendant(/* ancestor */ head, /* descendant */ pred) { + return err(StatusCode::INVALID_LOOP_SPLIT, summary.block(pred)); + } + + let body_extended = pred != head && body.insert(pred); + if body_extended { + frontier.push(pred); + } + } + } + + // Collapse all the nodes in `body` into `head`, so it appears as one node when processing + // outer loops (this performs a sequence of Operation 4(b), followed by a 4(a)). + let depth = partition.collapse_loop(head, &body); + if let Some(max_depth) = verifier_config.max_loop_depth { + if depth as usize > max_depth { + return err(StatusCode::LOOP_MAX_DEPTH_REACHED, summary.block(head)); + } + } + } + + Ok(()) +} diff --git a/CoqOfRust/move_sui/translations/move_bytecode_verifier/control_flow_v5.rs b/CoqOfRust/move_sui/translations/move_bytecode_verifier/control_flow_v5.rs new file mode 100644 index 000000000..b24d7aeca --- /dev/null +++ b/CoqOfRust/move_sui/translations/move_bytecode_verifier/control_flow_v5.rs @@ -0,0 +1,283 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! This module implements a checker to verify control flow in bytecode version 5 and below. The +//! following properties are ensured: +//! - All forward jumps do not enter into the middle of a loop +//! - All "breaks" (forward, loop-exiting jumps) go to the "end" of the loop +//! - All "continues" (back jumps in a loop) are only to the current loop +use move_binary_format::{ + errors::{PartialVMError, PartialVMResult}, + file_format::{Bytecode, CodeOffset, CodeUnit, FunctionDefinitionIndex}, + safe_unwrap, +}; +use move_core_types::vm_status::StatusCode; +use move_vm_config::verifier::VerifierConfig; +use std::{collections::HashSet, convert::TryInto}; + +pub fn verify( + verifier_config: &VerifierConfig, + current_function_opt: Option, + code: &CodeUnit, +) -> PartialVMResult<()> { + let current_function = current_function_opt.unwrap_or(FunctionDefinitionIndex(0)); + + // check fallthrough + verify_fallthrough(current_function, &code.code)?; + + // check jumps + let context = &ControlFlowVerifier { + current_function, + code: &code.code, + }; + let labels = instruction_labels(context); + check_jumps(verifier_config, context, labels) +} + +fn verify_fallthrough( + current_function: FunctionDefinitionIndex, + code: &Vec, +) -> PartialVMResult<()> { + // Check to make sure that the bytecode vector ends with a branching instruction. + match code.last() { + None => Err(PartialVMError::new(StatusCode::EMPTY_CODE_UNIT)), + Some(last) if !last.is_unconditional_branch() => { + Err(PartialVMError::new(StatusCode::INVALID_FALL_THROUGH) + .at_code_offset(current_function, (code.len() - 1) as CodeOffset)) + } + Some(_) => Ok(()), + } +} + +#[derive(Clone, Copy)] +enum Label { + Loop { last_continue: u16 }, + Code, +} + +struct ControlFlowVerifier<'a> { + current_function: FunctionDefinitionIndex, + code: &'a Vec, +} + +impl<'a> ControlFlowVerifier<'a> { + fn code(&self) -> impl Iterator { + self.code + .iter() + .enumerate() + .map(|(idx, instr)| (idx.try_into().unwrap(), instr)) + } + + fn labeled_code<'b: 'a>( + &self, + labels: &'b [Label], + ) -> impl Iterator { + self.code() + .zip(labels) + .map(|((i, instr), lbl)| (i, instr, lbl)) + } + + fn error(&self, status: StatusCode, offset: CodeOffset) -> PartialVMError { + PartialVMError::new(status).at_code_offset(self.current_function, offset) + } +} + +fn instruction_labels(context: &ControlFlowVerifier) -> Vec

(&self, mut pred: P) -> usize + where + P: FnMut(&T) -> bool, + { + let (front, back) = self.as_slices(); + + if let Some(true) = back.first().map(|v| pred(v)) { + back.partition_point(pred) + front.len() + } else { + front.partition_point(pred) + } + } +} + +impl VecDeque { + /// Modifies the deque in-place so that `len()` is equal to new_len, + /// either by removing excess elements from the back or by appending clones of `value` + /// to the back. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(5); + /// buf.push_back(10); + /// buf.push_back(15); + /// assert_eq!(buf, [5, 10, 15]); + /// + /// buf.resize(2, 0); + /// assert_eq!(buf, [5, 10]); + /// + /// buf.resize(5, 20); + /// assert_eq!(buf, [5, 10, 20, 20, 20]); + /// ``` + #[stable(feature = "deque_extras", since = "1.16.0")] + #[track_caller] + pub fn resize(&mut self, new_len: usize, value: T) { + if new_len > self.len() { + let extra = new_len - self.len(); + self.extend(repeat_n(value, extra)) + } else { + self.truncate(new_len); + } + } +} + +/// Returns the index in the underlying buffer for a given logical element index. +#[inline] +fn wrap_index(logical_index: usize, capacity: usize) -> usize { + debug_assert!( + (logical_index == 0 && capacity == 0) + || logical_index < capacity + || (logical_index - capacity) < capacity + ); + if logical_index >= capacity { logical_index - capacity } else { logical_index } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for VecDeque { + fn eq(&self, other: &Self) -> bool { + if self.len != other.len() { + return false; + } + let (sa, sb) = self.as_slices(); + let (oa, ob) = other.as_slices(); + if sa.len() == oa.len() { + sa == oa && sb == ob + } else if sa.len() < oa.len() { + // Always divisible in three sections, for example: + // self: [a b c|d e f] + // other: [0 1 2 3|4 5] + // front = 3, mid = 1, + // [a b c] == [0 1 2] && [d] == [3] && [e f] == [4 5] + let front = sa.len(); + let mid = oa.len() - front; + + let (oa_front, oa_mid) = oa.split_at(front); + let (sb_mid, sb_back) = sb.split_at(mid); + debug_assert_eq!(sa.len(), oa_front.len()); + debug_assert_eq!(sb_mid.len(), oa_mid.len()); + debug_assert_eq!(sb_back.len(), ob.len()); + sa == oa_front && sb_mid == oa_mid && sb_back == ob + } else { + let front = oa.len(); + let mid = sa.len() - front; + + let (sa_front, sa_mid) = sa.split_at(front); + let (ob_mid, ob_back) = ob.split_at(mid); + debug_assert_eq!(sa_front.len(), oa.len()); + debug_assert_eq!(sa_mid.len(), ob_mid.len()); + debug_assert_eq!(sb.len(), ob_back.len()); + sa_front == oa && sa_mid == ob_mid && sb == ob_back + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for VecDeque {} + +__impl_slice_eq1! { [] VecDeque, Vec, } +__impl_slice_eq1! { [] VecDeque, &[U], } +__impl_slice_eq1! { [] VecDeque, &mut [U], } +__impl_slice_eq1! { [const N: usize] VecDeque, [U; N], } +__impl_slice_eq1! { [const N: usize] VecDeque, &[U; N], } +__impl_slice_eq1! { [const N: usize] VecDeque, &mut [U; N], } + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for VecDeque { + fn partial_cmp(&self, other: &Self) -> Option { + self.iter().partial_cmp(other.iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for VecDeque { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.iter().cmp(other.iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for VecDeque { + fn hash(&self, state: &mut H) { + state.write_length_prefix(self.len); + // It's not possible to use Hash::hash_slice on slices + // returned by as_slices method as their length can vary + // in otherwise identical deques. + // + // Hasher only guarantees equivalence for the exact same + // set of calls to its methods. + self.iter().for_each(|elem| elem.hash(state)); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Index for VecDeque { + type Output = T; + + #[inline] + fn index(&self, index: usize) -> &T { + self.get(index).expect("Out of bounds access") + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IndexMut for VecDeque { + #[inline] + fn index_mut(&mut self, index: usize) -> &mut T { + self.get_mut(index).expect("Out of bounds access") + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for VecDeque { + #[track_caller] + fn from_iter>(iter: I) -> VecDeque { + SpecFromIter::spec_from_iter(iter.into_iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for VecDeque { + type Item = T; + type IntoIter = IntoIter; + + /// Consumes the deque into a front-to-back iterator yielding elements by + /// value. + fn into_iter(self) -> IntoIter { + IntoIter::new(self) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, A: Allocator> IntoIterator for &'a VecDeque { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, A: Allocator> IntoIterator for &'a mut VecDeque { + type Item = &'a mut T; + type IntoIter = IterMut<'a, T>; + + fn into_iter(self) -> IterMut<'a, T> { + self.iter_mut() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for VecDeque { + #[track_caller] + fn extend>(&mut self, iter: I) { + >::spec_extend(self, iter.into_iter()); + } + + #[inline] + #[track_caller] + fn extend_one(&mut self, elem: T) { + self.push_back(elem); + } + + #[inline] + #[track_caller] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } + + #[inline] + unsafe fn extend_one_unchecked(&mut self, item: T) { + // SAFETY: Our preconditions ensure the space has been reserved, and `extend_reserve` is implemented correctly. + unsafe { + self.push_unchecked(item); + } + } +} + +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, T: 'a + Copy, A: Allocator> Extend<&'a T> for VecDeque { + #[track_caller] + fn extend>(&mut self, iter: I) { + self.spec_extend(iter.into_iter()); + } + + #[inline] + #[track_caller] + fn extend_one(&mut self, &elem: &'a T) { + self.push_back(elem); + } + + #[inline] + #[track_caller] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } + + #[inline] + unsafe fn extend_one_unchecked(&mut self, &item: &'a T) { + // SAFETY: Our preconditions ensure the space has been reserved, and `extend_reserve` is implemented correctly. + unsafe { + self.push_unchecked(item); + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for VecDeque { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.iter()).finish() + } +} + +#[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")] +impl From> for VecDeque { + /// Turn a [`Vec`] into a [`VecDeque`]. + /// + /// [`Vec`]: crate::vec::Vec + /// [`VecDeque`]: crate::collections::VecDeque + /// + /// This conversion is guaranteed to run in *O*(1) time + /// and to not re-allocate the `Vec`'s buffer or allocate + /// any additional memory. + #[inline] + fn from(other: Vec) -> Self { + let (ptr, len, cap, alloc) = other.into_raw_parts_with_alloc(); + Self { head: 0, len, buf: unsafe { RawVec::from_raw_parts_in(ptr, cap, alloc) } } + } +} + +#[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")] +impl From> for Vec { + /// Turn a [`VecDeque`] into a [`Vec`]. + /// + /// [`Vec`]: crate::vec::Vec + /// [`VecDeque`]: crate::collections::VecDeque + /// + /// This never needs to re-allocate, but does need to do *O*(*n*) data movement if + /// the circular buffer doesn't happen to be at the beginning of the allocation. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// // This one is *O*(1). + /// let deque: VecDeque<_> = (1..5).collect(); + /// let ptr = deque.as_slices().0.as_ptr(); + /// let vec = Vec::from(deque); + /// assert_eq!(vec, [1, 2, 3, 4]); + /// assert_eq!(vec.as_ptr(), ptr); + /// + /// // This one needs data rearranging. + /// let mut deque: VecDeque<_> = (1..5).collect(); + /// deque.push_front(9); + /// deque.push_front(8); + /// let ptr = deque.as_slices().1.as_ptr(); + /// let vec = Vec::from(deque); + /// assert_eq!(vec, [8, 9, 1, 2, 3, 4]); + /// assert_eq!(vec.as_ptr(), ptr); + /// ``` + fn from(mut other: VecDeque) -> Self { + other.make_contiguous(); + + unsafe { + let other = ManuallyDrop::new(other); + let buf = other.buf.ptr(); + let len = other.len(); + let cap = other.capacity(); + let alloc = ptr::read(other.allocator()); + + if other.head != 0 { + ptr::copy(buf.add(other.head), buf, len); + } + Vec::from_raw_parts_in(buf, len, cap, alloc) + } + } +} + +#[stable(feature = "std_collections_from_array", since = "1.56.0")] +impl From<[T; N]> for VecDeque { + /// Converts a `[T; N]` into a `VecDeque`. + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let deq1 = VecDeque::from([1, 2, 3, 4]); + /// let deq2: VecDeque<_> = [1, 2, 3, 4].into(); + /// assert_eq!(deq1, deq2); + /// ``` + #[track_caller] + fn from(arr: [T; N]) -> Self { + let mut deq = VecDeque::with_capacity(N); + let arr = ManuallyDrop::new(arr); + if !::IS_ZST { + // SAFETY: VecDeque::with_capacity ensures that there is enough capacity. + unsafe { + ptr::copy_nonoverlapping(arr.as_ptr(), deq.ptr(), N); + } + } + deq.head = 0; + deq.len = N; + deq + } +} diff --git a/CoqOfRust/alloc/collections/vec_deque/spec_extend.rs b/CoqOfRust/alloc/collections/vec_deque/spec_extend.rs new file mode 100644 index 000000000..d246385ca --- /dev/null +++ b/CoqOfRust/alloc/collections/vec_deque/spec_extend.rs @@ -0,0 +1,120 @@ +use core::iter::TrustedLen; +use core::slice; + +use super::VecDeque; +use crate::alloc::Allocator; +use crate::vec; + +// Specialization trait used for VecDeque::extend +pub(super) trait SpecExtend { + #[track_caller] + fn spec_extend(&mut self, iter: I); +} + +impl SpecExtend for VecDeque +where + I: Iterator, +{ + #[track_caller] + default fn spec_extend(&mut self, mut iter: I) { + // This function should be the moral equivalent of: + // + // for item in iter { + // self.push_back(item); + // } + + while let Some(element) = iter.next() { + let (lower, _) = iter.size_hint(); + self.reserve(lower.saturating_add(1)); + + // SAFETY: We just reserved space for at least one element. + unsafe { self.push_unchecked(element) }; + + // Inner loop to avoid repeatedly calling `reserve`. + while self.len < self.capacity() { + let Some(element) = iter.next() else { + return; + }; + // SAFETY: The loop condition guarantees that `self.len() < self.capacity()`. + unsafe { self.push_unchecked(element) }; + } + } + } +} + +impl SpecExtend for VecDeque +where + I: TrustedLen, +{ + #[track_caller] + default fn spec_extend(&mut self, iter: I) { + // This is the case for a TrustedLen iterator. + let (low, high) = iter.size_hint(); + if let Some(additional) = high { + debug_assert_eq!( + low, + additional, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + self.reserve(additional); + + let written = unsafe { + self.write_iter_wrapping(self.to_physical_idx(self.len), iter, additional) + }; + + debug_assert_eq!( + additional, written, + "The number of items written to VecDeque doesn't match the TrustedLen size hint" + ); + } else { + // Per TrustedLen contract a `None` upper bound means that the iterator length + // truly exceeds usize::MAX, which would eventually lead to a capacity overflow anyway. + // Since the other branch already panics eagerly (via `reserve()`) we do the same here. + // This avoids additional codegen for a fallback code path which would eventually + // panic anyway. + panic!("capacity overflow"); + } + } +} + +impl SpecExtend> for VecDeque { + #[track_caller] + fn spec_extend(&mut self, mut iterator: vec::IntoIter) { + let slice = iterator.as_slice(); + self.reserve(slice.len()); + + unsafe { + self.copy_slice(self.to_physical_idx(self.len), slice); + self.len += slice.len(); + } + iterator.forget_remaining_elements(); + } +} + +impl<'a, T: 'a, I, A: Allocator> SpecExtend<&'a T, I> for VecDeque +where + I: Iterator, + T: Copy, +{ + #[track_caller] + default fn spec_extend(&mut self, iterator: I) { + self.spec_extend(iterator.copied()) + } +} + +impl<'a, T: 'a, A: Allocator> SpecExtend<&'a T, slice::Iter<'a, T>> for VecDeque +where + T: Copy, +{ + #[track_caller] + fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { + let slice = iterator.as_slice(); + self.reserve(slice.len()); + + unsafe { + self.copy_slice(self.to_physical_idx(self.len), slice); + self.len += slice.len(); + } + } +} diff --git a/CoqOfRust/alloc/collections/vec_deque/spec_from_iter.rs b/CoqOfRust/alloc/collections/vec_deque/spec_from_iter.rs new file mode 100644 index 000000000..1efe84d6d --- /dev/null +++ b/CoqOfRust/alloc/collections/vec_deque/spec_from_iter.rs @@ -0,0 +1,34 @@ +use super::{IntoIter, VecDeque}; + +/// Specialization trait used for `VecDeque::from_iter` +pub(super) trait SpecFromIter { + fn spec_from_iter(iter: I) -> Self; +} + +impl SpecFromIter for VecDeque +where + I: Iterator, +{ + #[track_caller] + default fn spec_from_iter(iterator: I) -> Self { + // Since converting is O(1) now, just re-use the `Vec` logic for + // anything where we can't do something extra-special for `VecDeque`, + // especially as that could save us some monomorphization work + // if one uses the same iterators (like slice ones) with both. + crate::vec::Vec::from_iter(iterator).into() + } +} + +impl SpecFromIter> for VecDeque { + #[inline] + fn spec_from_iter(iterator: crate::vec::IntoIter) -> Self { + iterator.into_vecdeque() + } +} + +impl SpecFromIter> for VecDeque { + #[inline] + fn spec_from_iter(iterator: IntoIter) -> Self { + iterator.into_vecdeque() + } +} diff --git a/CoqOfRust/alloc/collections/vec_deque/tests.rs b/CoqOfRust/alloc/collections/vec_deque/tests.rs new file mode 100644 index 000000000..6328b3b4d --- /dev/null +++ b/CoqOfRust/alloc/collections/vec_deque/tests.rs @@ -0,0 +1,1176 @@ +// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] + +use core::iter::TrustedLen; + +use super::*; + +#[bench] +fn bench_push_back_100(b: &mut test::Bencher) { + let mut deq = VecDeque::with_capacity(101); + b.iter(|| { + for i in 0..100 { + deq.push_back(i); + } + deq.head = 0; + deq.len = 0; + }) +} + +#[bench] +fn bench_push_front_100(b: &mut test::Bencher) { + let mut deq = VecDeque::with_capacity(101); + b.iter(|| { + for i in 0..100 { + deq.push_front(i); + } + deq.head = 0; + deq.len = 0; + }) +} + +#[bench] +fn bench_pop_back_100(b: &mut test::Bencher) { + let size = 100; + let mut deq = VecDeque::::with_capacity(size + 1); + // We'll mess with private state to pretend like `deq` is filled. + // Make sure the buffer is initialized so that we don't read uninit memory. + unsafe { deq.ptr().write_bytes(0u8, size + 1) }; + + b.iter(|| { + deq.head = 0; + deq.len = 100; + while !deq.is_empty() { + test::black_box(deq.pop_back()); + } + }) +} + +#[bench] +fn bench_retain_whole_10000(b: &mut test::Bencher) { + let size = if cfg!(miri) { 1000 } else { 100000 }; + let v = (1..size).collect::>(); + + b.iter(|| { + let mut v = v.clone(); + v.retain(|x| *x > 0) + }) +} + +#[bench] +fn bench_retain_odd_10000(b: &mut test::Bencher) { + let size = if cfg!(miri) { 1000 } else { 100000 }; + let v = (1..size).collect::>(); + + b.iter(|| { + let mut v = v.clone(); + v.retain(|x| x & 1 == 0) + }) +} + +#[bench] +fn bench_retain_half_10000(b: &mut test::Bencher) { + let size = if cfg!(miri) { 1000 } else { 100000 }; + let v = (1..size).collect::>(); + + b.iter(|| { + let mut v = v.clone(); + v.retain(|x| *x > size / 2) + }) +} + +#[bench] +fn bench_pop_front_100(b: &mut test::Bencher) { + let size = 100; + let mut deq = VecDeque::::with_capacity(size + 1); + // We'll mess with private state to pretend like `deq` is filled. + // Make sure the buffer is initialized so that we don't read uninit memory. + unsafe { deq.ptr().write_bytes(0u8, size + 1) }; + + b.iter(|| { + deq.head = 0; + deq.len = 100; + while !deq.is_empty() { + test::black_box(deq.pop_front()); + } + }) +} + +#[test] +fn test_swap_front_back_remove() { + fn test(back: bool) { + // This test checks that every single combination of tail position and length is tested. + // Capacity 15 should be large enough to cover every case. + let mut tester = VecDeque::with_capacity(15); + let usable_cap = tester.capacity(); + let final_len = usable_cap / 2; + + for len in 0..final_len { + let expected: VecDeque<_> = + if back { (0..len).collect() } else { (0..len).rev().collect() }; + for head_pos in 0..usable_cap { + tester.head = head_pos; + tester.len = 0; + if back { + for i in 0..len * 2 { + tester.push_front(i); + } + for i in 0..len { + assert_eq!(tester.swap_remove_back(i), Some(len * 2 - 1 - i)); + } + } else { + for i in 0..len * 2 { + tester.push_back(i); + } + for i in 0..len { + let idx = tester.len() - 1 - i; + assert_eq!(tester.swap_remove_front(idx), Some(len * 2 - 1 - i)); + } + } + assert!(tester.head <= tester.capacity()); + assert!(tester.len <= tester.capacity()); + assert_eq!(tester, expected); + } + } + } + test(true); + test(false); +} + +#[test] +fn test_insert() { + // This test checks that every single combination of tail position, length, and + // insertion position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + // len is the length *after* insertion + let minlen = if cfg!(miri) { cap - 1 } else { 1 }; // Miri is too slow + for len in minlen..cap { + // 0, 1, 2, .., len - 1 + let expected = (0..).take(len).collect::>(); + for head_pos in 0..cap { + for to_insert in 0..len { + tester.head = head_pos; + tester.len = 0; + for i in 0..len { + if i != to_insert { + tester.push_back(i); + } + } + tester.insert(to_insert, to_insert); + assert!(tester.head <= tester.capacity()); + assert!(tester.len <= tester.capacity()); + assert_eq!(tester, expected); + } + } + } +} + +#[test] +fn test_get() { + let mut tester = VecDeque::new(); + tester.push_back(1); + tester.push_back(2); + tester.push_back(3); + + assert_eq!(tester.len(), 3); + + assert_eq!(tester.get(1), Some(&2)); + assert_eq!(tester.get(2), Some(&3)); + assert_eq!(tester.get(0), Some(&1)); + assert_eq!(tester.get(3), None); + + tester.remove(0); + + assert_eq!(tester.len(), 2); + assert_eq!(tester.get(0), Some(&2)); + assert_eq!(tester.get(1), Some(&3)); + assert_eq!(tester.get(2), None); +} + +#[test] +fn test_get_mut() { + let mut tester = VecDeque::new(); + tester.push_back(1); + tester.push_back(2); + tester.push_back(3); + + assert_eq!(tester.len(), 3); + + if let Some(elem) = tester.get_mut(0) { + assert_eq!(*elem, 1); + *elem = 10; + } + + if let Some(elem) = tester.get_mut(2) { + assert_eq!(*elem, 3); + *elem = 30; + } + + assert_eq!(tester.get(0), Some(&10)); + assert_eq!(tester.get(2), Some(&30)); + assert_eq!(tester.get_mut(3), None); + + tester.remove(2); + + assert_eq!(tester.len(), 2); + assert_eq!(tester.get(0), Some(&10)); + assert_eq!(tester.get(1), Some(&2)); + assert_eq!(tester.get(2), None); +} + +#[test] +fn test_swap() { + let mut tester = VecDeque::new(); + tester.push_back(1); + tester.push_back(2); + tester.push_back(3); + + assert_eq!(tester, [1, 2, 3]); + + tester.swap(0, 0); + assert_eq!(tester, [1, 2, 3]); + tester.swap(0, 1); + assert_eq!(tester, [2, 1, 3]); + tester.swap(2, 1); + assert_eq!(tester, [2, 3, 1]); + tester.swap(1, 2); + assert_eq!(tester, [2, 1, 3]); + tester.swap(0, 2); + assert_eq!(tester, [3, 1, 2]); + tester.swap(2, 2); + assert_eq!(tester, [3, 1, 2]); +} + +#[test] +#[should_panic = "assertion failed: j < self.len()"] +fn test_swap_panic() { + let mut tester = VecDeque::new(); + tester.push_back(1); + tester.push_back(2); + tester.push_back(3); + tester.swap(2, 3); +} + +#[test] +fn test_reserve_exact() { + let mut tester: VecDeque = VecDeque::with_capacity(1); + assert_eq!(tester.capacity(), 1); + tester.reserve_exact(50); + assert_eq!(tester.capacity(), 50); + tester.reserve_exact(40); + // reserving won't shrink the buffer + assert_eq!(tester.capacity(), 50); + tester.reserve_exact(200); + assert_eq!(tester.capacity(), 200); +} + +#[test] +#[should_panic = "capacity overflow"] +fn test_reserve_exact_panic() { + let mut tester: VecDeque = VecDeque::new(); + tester.reserve_exact(usize::MAX); +} + +#[test] +fn test_try_reserve_exact() { + let mut tester: VecDeque = VecDeque::with_capacity(1); + assert!(tester.capacity() == 1); + assert_eq!(tester.try_reserve_exact(100), Ok(())); + assert!(tester.capacity() >= 100); + assert_eq!(tester.try_reserve_exact(50), Ok(())); + assert!(tester.capacity() >= 100); + assert_eq!(tester.try_reserve_exact(200), Ok(())); + assert!(tester.capacity() >= 200); + assert_eq!(tester.try_reserve_exact(0), Ok(())); + assert!(tester.capacity() >= 200); + assert!(tester.try_reserve_exact(usize::MAX).is_err()); +} + +#[test] +fn test_try_reserve() { + let mut tester: VecDeque = VecDeque::with_capacity(1); + assert!(tester.capacity() == 1); + assert_eq!(tester.try_reserve(100), Ok(())); + assert!(tester.capacity() >= 100); + assert_eq!(tester.try_reserve(50), Ok(())); + assert!(tester.capacity() >= 100); + assert_eq!(tester.try_reserve(200), Ok(())); + assert!(tester.capacity() >= 200); + assert_eq!(tester.try_reserve(0), Ok(())); + assert!(tester.capacity() >= 200); + assert!(tester.try_reserve(usize::MAX).is_err()); +} + +#[test] +fn test_contains() { + let mut tester = VecDeque::new(); + tester.push_back(1); + tester.push_back(2); + tester.push_back(3); + + assert!(tester.contains(&1)); + assert!(tester.contains(&3)); + assert!(!tester.contains(&0)); + assert!(!tester.contains(&4)); + tester.remove(0); + assert!(!tester.contains(&1)); + assert!(tester.contains(&2)); + assert!(tester.contains(&3)); +} + +#[test] +fn test_rotate_left_right() { + let mut tester: VecDeque<_> = (1..=10).collect(); + tester.reserve(1); + + assert_eq!(tester.len(), 10); + + tester.rotate_left(0); + assert_eq!(tester, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + + tester.rotate_right(0); + assert_eq!(tester, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + + tester.rotate_left(3); + assert_eq!(tester, [4, 5, 6, 7, 8, 9, 10, 1, 2, 3]); + + tester.rotate_right(5); + assert_eq!(tester, [9, 10, 1, 2, 3, 4, 5, 6, 7, 8]); + + tester.rotate_left(tester.len()); + assert_eq!(tester, [9, 10, 1, 2, 3, 4, 5, 6, 7, 8]); + + tester.rotate_right(tester.len()); + assert_eq!(tester, [9, 10, 1, 2, 3, 4, 5, 6, 7, 8]); + + tester.rotate_left(1); + assert_eq!(tester, [10, 1, 2, 3, 4, 5, 6, 7, 8, 9]); +} + +#[test] +#[should_panic = "assertion failed: n <= self.len()"] +fn test_rotate_left_panic() { + let mut tester: VecDeque<_> = (1..=10).collect(); + tester.rotate_left(tester.len() + 1); +} + +#[test] +#[should_panic = "assertion failed: n <= self.len()"] +fn test_rotate_right_panic() { + let mut tester: VecDeque<_> = (1..=10).collect(); + tester.rotate_right(tester.len() + 1); +} + +#[test] +fn test_binary_search() { + // If the givin VecDeque is not sorted, the returned result is unspecified and meaningless, + // as this method performs a binary search. + + let tester: VecDeque<_> = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into(); + + assert_eq!(tester.binary_search(&0), Ok(0)); + assert_eq!(tester.binary_search(&5), Ok(5)); + assert_eq!(tester.binary_search(&55), Ok(10)); + assert_eq!(tester.binary_search(&4), Err(5)); + assert_eq!(tester.binary_search(&-1), Err(0)); + assert!(matches!(tester.binary_search(&1), Ok(1..=2))); + + let tester: VecDeque<_> = [1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3].into(); + assert_eq!(tester.binary_search(&1), Ok(0)); + assert!(matches!(tester.binary_search(&2), Ok(1..=4))); + assert!(matches!(tester.binary_search(&3), Ok(5..=13))); + assert_eq!(tester.binary_search(&-2), Err(0)); + assert_eq!(tester.binary_search(&0), Err(0)); + assert_eq!(tester.binary_search(&4), Err(14)); + assert_eq!(tester.binary_search(&5), Err(14)); +} + +#[test] +fn test_binary_search_by() { + // If the givin VecDeque is not sorted, the returned result is unspecified and meaningless, + // as this method performs a binary search. + + let tester: VecDeque<_> = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into(); + + assert_eq!(tester.binary_search_by(|x| x.cmp(&0)), Ok(0)); + assert_eq!(tester.binary_search_by(|x| x.cmp(&5)), Ok(5)); + assert_eq!(tester.binary_search_by(|x| x.cmp(&55)), Ok(10)); + assert_eq!(tester.binary_search_by(|x| x.cmp(&4)), Err(5)); + assert_eq!(tester.binary_search_by(|x| x.cmp(&-1)), Err(0)); + assert!(matches!(tester.binary_search_by(|x| x.cmp(&1)), Ok(1..=2))); +} + +#[test] +fn test_binary_search_key() { + // If the givin VecDeque is not sorted, the returned result is unspecified and meaningless, + // as this method performs a binary search. + + let tester: VecDeque<_> = [ + (-1, 0), + (2, 10), + (6, 5), + (7, 1), + (8, 10), + (10, 2), + (20, 3), + (24, 5), + (25, 18), + (28, 13), + (31, 21), + (32, 4), + (54, 25), + ] + .into(); + + assert_eq!(tester.binary_search_by_key(&-1, |&(a, _b)| a), Ok(0)); + assert_eq!(tester.binary_search_by_key(&8, |&(a, _b)| a), Ok(4)); + assert_eq!(tester.binary_search_by_key(&25, |&(a, _b)| a), Ok(8)); + assert_eq!(tester.binary_search_by_key(&54, |&(a, _b)| a), Ok(12)); + assert_eq!(tester.binary_search_by_key(&-2, |&(a, _b)| a), Err(0)); + assert_eq!(tester.binary_search_by_key(&1, |&(a, _b)| a), Err(1)); + assert_eq!(tester.binary_search_by_key(&4, |&(a, _b)| a), Err(2)); + assert_eq!(tester.binary_search_by_key(&13, |&(a, _b)| a), Err(6)); + assert_eq!(tester.binary_search_by_key(&55, |&(a, _b)| a), Err(13)); + assert_eq!(tester.binary_search_by_key(&100, |&(a, _b)| a), Err(13)); + + let tester: VecDeque<_> = [ + (0, 0), + (2, 1), + (6, 1), + (5, 1), + (3, 1), + (1, 2), + (2, 3), + (4, 5), + (5, 8), + (8, 13), + (1, 21), + (2, 34), + (4, 55), + ] + .into(); + + assert_eq!(tester.binary_search_by_key(&0, |&(_a, b)| b), Ok(0)); + assert!(matches!(tester.binary_search_by_key(&1, |&(_a, b)| b), Ok(1..=4))); + assert_eq!(tester.binary_search_by_key(&8, |&(_a, b)| b), Ok(8)); + assert_eq!(tester.binary_search_by_key(&13, |&(_a, b)| b), Ok(9)); + assert_eq!(tester.binary_search_by_key(&55, |&(_a, b)| b), Ok(12)); + assert_eq!(tester.binary_search_by_key(&-1, |&(_a, b)| b), Err(0)); + assert_eq!(tester.binary_search_by_key(&4, |&(_a, b)| b), Err(7)); + assert_eq!(tester.binary_search_by_key(&56, |&(_a, b)| b), Err(13)); + assert_eq!(tester.binary_search_by_key(&100, |&(_a, b)| b), Err(13)); +} + +#[test] +fn make_contiguous_big_head() { + let mut tester = VecDeque::with_capacity(15); + + for i in 0..3 { + tester.push_back(i); + } + + for i in 3..10 { + tester.push_front(i); + } + + // 012......9876543 + assert_eq!(tester.capacity(), 15); + assert_eq!((&[9, 8, 7, 6, 5, 4, 3] as &[_], &[0, 1, 2] as &[_]), tester.as_slices()); + + let expected_start = tester.as_slices().1.len(); + tester.make_contiguous(); + assert_eq!(tester.head, expected_start); + assert_eq!((&[9, 8, 7, 6, 5, 4, 3, 0, 1, 2] as &[_], &[] as &[_]), tester.as_slices()); +} + +#[test] +fn make_contiguous_big_tail() { + let mut tester = VecDeque::with_capacity(15); + + for i in 0..8 { + tester.push_back(i); + } + + for i in 8..10 { + tester.push_front(i); + } + + // 01234567......98 + let expected_start = 0; + tester.make_contiguous(); + assert_eq!(tester.head, expected_start); + assert_eq!((&[9, 8, 0, 1, 2, 3, 4, 5, 6, 7] as &[_], &[] as &[_]), tester.as_slices()); +} + +#[test] +fn make_contiguous_small_free() { + let mut tester = VecDeque::with_capacity(16); + + for i in b'A'..b'I' { + tester.push_back(i as char); + } + + for i in b'I'..b'N' { + tester.push_front(i as char); + } + + assert_eq!(tester, ['M', 'L', 'K', 'J', 'I', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']); + + // ABCDEFGH...MLKJI + let expected_start = 0; + tester.make_contiguous(); + assert_eq!(tester.head, expected_start); + assert_eq!( + (&['M', 'L', 'K', 'J', 'I', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] as &[_], &[] as &[_]), + tester.as_slices() + ); + + tester.clear(); + for i in b'I'..b'N' { + tester.push_back(i as char); + } + + for i in b'A'..b'I' { + tester.push_front(i as char); + } + + // IJKLM...HGFEDCBA + let expected_start = 3; + tester.make_contiguous(); + assert_eq!(tester.head, expected_start); + assert_eq!( + (&['H', 'G', 'F', 'E', 'D', 'C', 'B', 'A', 'I', 'J', 'K', 'L', 'M'] as &[_], &[] as &[_]), + tester.as_slices() + ); +} + +#[test] +fn make_contiguous_head_to_end() { + let mut tester = VecDeque::with_capacity(16); + + for i in b'A'..b'L' { + tester.push_back(i as char); + } + + for i in b'L'..b'Q' { + tester.push_front(i as char); + } + + assert_eq!(tester, [ + 'P', 'O', 'N', 'M', 'L', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K' + ]); + + // ABCDEFGHIJKPONML + let expected_start = 0; + tester.make_contiguous(); + assert_eq!(tester.head, expected_start); + assert_eq!( + ( + &['P', 'O', 'N', 'M', 'L', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'] + as &[_], + &[] as &[_] + ), + tester.as_slices() + ); + + tester.clear(); + for i in b'L'..b'Q' { + tester.push_back(i as char); + } + + for i in b'A'..b'L' { + tester.push_front(i as char); + } + + // LMNOPKJIHGFEDCBA + let expected_start = 0; + tester.make_contiguous(); + assert_eq!(tester.head, expected_start); + assert_eq!( + ( + &['K', 'J', 'I', 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A', 'L', 'M', 'N', 'O', 'P'] + as &[_], + &[] as &[_] + ), + tester.as_slices() + ); +} + +#[test] +fn make_contiguous_head_to_end_2() { + // Another test case for #79808, taken from #80293. + + let mut dq = VecDeque::from_iter(0..6); + dq.pop_front(); + dq.pop_front(); + dq.push_back(6); + dq.push_back(7); + dq.push_back(8); + dq.make_contiguous(); + let collected: Vec<_> = dq.iter().copied().collect(); + assert_eq!(dq.as_slices(), (&collected[..], &[] as &[_])); +} + +#[test] +fn test_remove() { + // This test checks that every single combination of tail position, length, and + // removal position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + // len is the length *after* removal + let minlen = if cfg!(miri) { cap - 2 } else { 0 }; // Miri is too slow + for len in minlen..cap - 1 { + // 0, 1, 2, .., len - 1 + let expected = (0..).take(len).collect::>(); + for head_pos in 0..cap { + for to_remove in 0..=len { + tester.head = head_pos; + tester.len = 0; + for i in 0..len { + if i == to_remove { + tester.push_back(1234); + } + tester.push_back(i); + } + if to_remove == len { + tester.push_back(1234); + } + tester.remove(to_remove); + assert!(tester.head <= tester.capacity()); + assert!(tester.len <= tester.capacity()); + assert_eq!(tester, expected); + } + } + } +} + +#[test] +fn test_range() { + let mut tester: VecDeque = VecDeque::with_capacity(7); + + let cap = tester.capacity(); + let minlen = if cfg!(miri) { cap - 1 } else { 0 }; // Miri is too slow + for len in minlen..=cap { + for head in 0..=cap { + for start in 0..=len { + for end in start..=len { + tester.head = head; + tester.len = 0; + for i in 0..len { + tester.push_back(i); + } + + // Check that we iterate over the correct values + let range: VecDeque<_> = tester.range(start..end).copied().collect(); + let expected: VecDeque<_> = (start..end).collect(); + assert_eq!(range, expected); + } + } + } + } +} + +#[test] +fn test_range_mut() { + let mut tester: VecDeque = VecDeque::with_capacity(7); + + let cap = tester.capacity(); + for len in 0..=cap { + for head in 0..=cap { + for start in 0..=len { + for end in start..=len { + tester.head = head; + tester.len = 0; + for i in 0..len { + tester.push_back(i); + } + + let head_was = tester.head; + let len_was = tester.len; + + // Check that we iterate over the correct values + let range: VecDeque<_> = tester.range_mut(start..end).map(|v| *v).collect(); + let expected: VecDeque<_> = (start..end).collect(); + assert_eq!(range, expected); + + // We shouldn't have changed the capacity or made the + // head or tail out of bounds + assert_eq!(tester.capacity(), cap); + assert_eq!(tester.head, head_was); + assert_eq!(tester.len, len_was); + } + } + } + } +} + +#[test] +fn test_drain() { + let mut tester: VecDeque = VecDeque::with_capacity(7); + + let cap = tester.capacity(); + for len in 0..=cap { + for head in 0..cap { + for drain_start in 0..=len { + for drain_end in drain_start..=len { + tester.head = head; + tester.len = 0; + for i in 0..len { + tester.push_back(i); + } + + // Check that we drain the correct values + let drained: VecDeque<_> = tester.drain(drain_start..drain_end).collect(); + let drained_expected: VecDeque<_> = (drain_start..drain_end).collect(); + assert_eq!(drained, drained_expected); + + // We shouldn't have changed the capacity or made the + // head or tail out of bounds + assert_eq!(tester.capacity(), cap); + assert!(tester.head <= tester.capacity()); + assert!(tester.len <= tester.capacity()); + + // We should see the correct values in the VecDeque + let expected: VecDeque<_> = (0..drain_start).chain(drain_end..len).collect(); + assert_eq!(expected, tester); + } + } + } + } +} + +#[test] +fn issue_108453() { + let mut deque = VecDeque::with_capacity(10); + + deque.push_back(1u8); + deque.push_back(2); + deque.push_back(3); + + deque.push_front(10); + deque.push_front(9); + + deque.shrink_to(9); + + assert_eq!(deque.into_iter().collect::>(), vec![9, 10, 1, 2, 3]); +} + +#[test] +fn test_shrink_to() { + // test deques with capacity 16 with all possible head positions, lengths and target capacities. + let cap = 16; + + for len in 0..cap { + for head in 0..cap { + let expected = (1..=len).collect::>(); + + for target_cap in len..cap { + let mut deque = VecDeque::with_capacity(cap); + // currently, `with_capacity` always allocates the exact capacity if it's greater than 8. + assert_eq!(deque.capacity(), cap); + + // we can let the head point anywhere in the buffer since the deque is empty. + deque.head = head; + deque.extend(1..=len); + + deque.shrink_to(target_cap); + + assert_eq!(deque, expected); + } + } + } +} + +#[test] +fn test_shrink_to_fit() { + // This test checks that every single combination of head and tail position, + // is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + tester.reserve(63); + let max_cap = tester.capacity(); + + for len in 0..=cap { + // 0, 1, 2, .., len - 1 + let expected = (0..).take(len).collect::>(); + for head_pos in 0..=max_cap { + tester.reserve(head_pos); + tester.head = head_pos; + tester.len = 0; + tester.reserve(63); + for i in 0..len { + tester.push_back(i); + } + tester.shrink_to_fit(); + assert!(tester.capacity() <= cap); + assert!(tester.head <= tester.capacity()); + assert!(tester.len <= tester.capacity()); + assert_eq!(tester, expected); + } + } +} + +#[test] +fn test_split_off() { + // This test checks that every single combination of tail position, length, and + // split position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + // len is the length *before* splitting + let minlen = if cfg!(miri) { cap - 1 } else { 0 }; // Miri is too slow + for len in minlen..cap { + // index to split at + for at in 0..=len { + // 0, 1, 2, .., at - 1 (may be empty) + let expected_self = (0..).take(at).collect::>(); + // at, at + 1, .., len - 1 (may be empty) + let expected_other = (at..).take(len - at).collect::>(); + + for head_pos in 0..cap { + tester.head = head_pos; + tester.len = 0; + for i in 0..len { + tester.push_back(i); + } + let result = tester.split_off(at); + assert!(tester.head <= tester.capacity()); + assert!(tester.len <= tester.capacity()); + assert!(result.head <= result.capacity()); + assert!(result.len <= result.capacity()); + assert_eq!(tester, expected_self); + assert_eq!(result, expected_other); + } + } + } +} + +#[test] +fn test_from_vec() { + use crate::vec::Vec; + for cap in 0..35 { + for len in 0..=cap { + let mut vec = Vec::with_capacity(cap); + vec.extend(0..len); + + let vd = VecDeque::from(vec.clone()); + assert_eq!(vd.len(), vec.len()); + assert!(vd.into_iter().eq(vec)); + } + } +} + +#[test] +fn test_extend_basic() { + test_extend_impl(false); +} + +#[test] +fn test_extend_trusted_len() { + test_extend_impl(true); +} + +fn test_extend_impl(trusted_len: bool) { + struct VecDequeTester { + test: VecDeque, + expected: VecDeque, + trusted_len: bool, + } + + impl VecDequeTester { + fn new(trusted_len: bool) -> Self { + Self { test: VecDeque::new(), expected: VecDeque::new(), trusted_len } + } + + fn test_extend(&mut self, iter: I) + where + I: Iterator + TrustedLen + Clone, + { + struct BasicIterator(I); + impl Iterator for BasicIterator + where + I: Iterator, + { + type Item = usize; + + fn next(&mut self) -> Option { + self.0.next() + } + } + + if self.trusted_len { + self.test.extend(iter.clone()); + } else { + self.test.extend(BasicIterator(iter.clone())); + } + + for item in iter { + self.expected.push_back(item) + } + + assert_eq!(self.test, self.expected); + } + + fn drain + Clone>(&mut self, range: R) { + self.test.drain(range.clone()); + self.expected.drain(range); + + assert_eq!(self.test, self.expected); + } + + fn clear(&mut self) { + self.test.clear(); + self.expected.clear(); + } + + fn remaining_capacity(&self) -> usize { + self.test.capacity() - self.test.len() + } + } + + let mut tester = VecDequeTester::new(trusted_len); + + // Initial capacity + tester.test_extend(0..tester.remaining_capacity()); + + // Grow + tester.test_extend(1024..2048); + + // Wrap around + tester.drain(..128); + + tester.test_extend(0..tester.remaining_capacity()); + + // Continue + tester.drain(256..); + tester.test_extend(4096..8196); + + tester.clear(); + + // Start again + tester.test_extend(0..32); +} + +#[test] +fn test_from_array() { + fn test() { + let mut array: [usize; N] = [0; N]; + + for i in 0..N { + array[i] = i; + } + + let deq: VecDeque<_> = array.into(); + + for i in 0..N { + assert_eq!(deq[i], i); + } + + assert_eq!(deq.len(), N); + } + test::<0>(); + test::<1>(); + test::<2>(); + test::<32>(); + test::<35>(); +} + +#[test] +fn test_vec_from_vecdeque() { + use crate::vec::Vec; + + fn create_vec_and_test_convert(capacity: usize, offset: usize, len: usize) { + let mut vd = VecDeque::with_capacity(capacity); + for _ in 0..offset { + vd.push_back(0); + vd.pop_front(); + } + vd.extend(0..len); + + let vec: Vec<_> = Vec::from(vd.clone()); + assert_eq!(vec.len(), vd.len()); + assert!(vec.into_iter().eq(vd)); + } + + // Miri is too slow + let max_pwr = if cfg!(miri) { 5 } else { 7 }; + + for cap_pwr in 0..max_pwr { + // Make capacity as a (2^x)-1, so that the ring size is 2^x + let cap = (2i32.pow(cap_pwr) - 1) as usize; + + // In these cases there is enough free space to solve it with copies + for len in 0..((cap + 1) / 2) { + // Test contiguous cases + for offset in 0..(cap - len) { + create_vec_and_test_convert(cap, offset, len) + } + + // Test cases where block at end of buffer is bigger than block at start + for offset in (cap - len)..(cap - (len / 2)) { + create_vec_and_test_convert(cap, offset, len) + } + + // Test cases where block at start of buffer is bigger than block at end + for offset in (cap - (len / 2))..cap { + create_vec_and_test_convert(cap, offset, len) + } + } + + // Now there's not (necessarily) space to straighten the ring with simple copies, + // the ring will use swapping when: + // (cap + 1 - offset) > (cap + 1 - len) && (len - (cap + 1 - offset)) > (cap + 1 - len)) + // right block size > free space && left block size > free space + for len in ((cap + 1) / 2)..cap { + // Test contiguous cases + for offset in 0..(cap - len) { + create_vec_and_test_convert(cap, offset, len) + } + + // Test cases where block at end of buffer is bigger than block at start + for offset in (cap - len)..(cap - (len / 2)) { + create_vec_and_test_convert(cap, offset, len) + } + + // Test cases where block at start of buffer is bigger than block at end + for offset in (cap - (len / 2))..cap { + create_vec_and_test_convert(cap, offset, len) + } + } + } +} + +#[test] +fn test_clone_from() { + let m = vec![1; 8]; + let n = vec![2; 12]; + let limit = if cfg!(miri) { 4 } else { 8 }; // Miri is too slow + for pfv in 0..limit { + for pfu in 0..limit { + for longer in 0..2 { + let (vr, ur) = if longer == 0 { (&m, &n) } else { (&n, &m) }; + let mut v = VecDeque::from(vr.clone()); + for _ in 0..pfv { + v.push_front(1); + } + let mut u = VecDeque::from(ur.clone()); + for _ in 0..pfu { + u.push_front(2); + } + v.clone_from(&u); + assert_eq!(&v, &u); + } + } + } +} + +#[test] +fn test_vec_deque_truncate_drop() { + static mut DROPS: u32 = 0; + #[derive(Clone)] + struct Elem(#[allow(dead_code)] i32); + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)]; + for push_front in 0..=v.len() { + let v = v.clone(); + let mut tester = VecDeque::with_capacity(5); + for (index, elem) in v.into_iter().enumerate() { + if index < push_front { + tester.push_front(elem); + } else { + tester.push_back(elem); + } + } + assert_eq!(unsafe { DROPS }, 0); + tester.truncate(3); + assert_eq!(unsafe { DROPS }, 2); + tester.truncate(0); + assert_eq!(unsafe { DROPS }, 5); + unsafe { + DROPS = 0; + } + } +} + +#[test] +fn issue_53529() { + use crate::boxed::Box; + + let mut dst = VecDeque::new(); + dst.push_front(Box::new(1)); + dst.push_front(Box::new(2)); + assert_eq!(*dst.pop_back().unwrap(), 1); + + let mut src = VecDeque::new(); + src.push_front(Box::new(2)); + dst.append(&mut src); + for a in dst { + assert_eq!(*a, 2); + } +} + +#[test] +fn issue_80303() { + use core::iter; + use core::num::Wrapping; + + // This is a valid, albeit rather bad hash function implementation. + struct SimpleHasher(Wrapping); + + impl Hasher for SimpleHasher { + fn finish(&self) -> u64 { + self.0.0 + } + + fn write(&mut self, bytes: &[u8]) { + // This particular implementation hashes value 24 in addition to bytes. + // Such an implementation is valid as Hasher only guarantees equivalence + // for the exact same set of calls to its methods. + for &v in iter::once(&24).chain(bytes) { + self.0 = Wrapping(31) * self.0 + Wrapping(u64::from(v)); + } + } + } + + fn hash_code(value: impl Hash) -> u64 { + let mut hasher = SimpleHasher(Wrapping(1)); + value.hash(&mut hasher); + hasher.finish() + } + + // This creates two deques for which values returned by as_slices + // method differ. + let vda: VecDeque = (0..10).collect(); + let mut vdb = VecDeque::with_capacity(10); + vdb.extend(5..10); + (0..5).rev().for_each(|elem| vdb.push_front(elem)); + assert_ne!(vda.as_slices(), vdb.as_slices()); + assert_eq!(vda, vdb); + assert_eq!(hash_code(vda), hash_code(vdb)); +} diff --git a/CoqOfRust/alloc/ffi/c_str.rs b/CoqOfRust/alloc/ffi/c_str.rs new file mode 100644 index 000000000..9c074383a --- /dev/null +++ b/CoqOfRust/alloc/ffi/c_str.rs @@ -0,0 +1,1204 @@ +//! [`CString`] and its related types. + +#[cfg(test)] +mod tests; + +use core::borrow::Borrow; +use core::ffi::{CStr, c_char}; +use core::num::NonZero; +use core::slice::memchr; +use core::str::{self, FromStr, Utf8Error}; +use core::{fmt, mem, ops, ptr, slice}; + +use crate::borrow::{Cow, ToOwned}; +use crate::boxed::Box; +use crate::rc::Rc; +use crate::slice::hack::into_vec; +use crate::string::String; +#[cfg(target_has_atomic = "ptr")] +use crate::sync::Arc; +use crate::vec::Vec; + +/// A type representing an owned, C-compatible, nul-terminated string with no nul bytes in the +/// middle. +/// +/// This type serves the purpose of being able to safely generate a +/// C-compatible string from a Rust byte slice or vector. An instance of this +/// type is a static guarantee that the underlying bytes contain no interior 0 +/// bytes ("nul characters") and that the final byte is 0 ("nul terminator"). +/// +/// `CString` is to &[CStr] as [`String`] is to &[str]: the former +/// in each pair are owned strings; the latter are borrowed +/// references. +/// +/// # Creating a `CString` +/// +/// A `CString` is created from either a byte slice or a byte vector, +/// or anything that implements [Into]<[Vec]<[u8]>> (for +/// example, you can build a `CString` straight out of a [`String`] or +/// a &[str], since both implement that trait). +/// You can create a `CString` from a literal with `CString::from(c"Text")`. +/// +/// The [`CString::new`] method will actually check that the provided &[[u8]] +/// does not have 0 bytes in the middle, and return an error if it +/// finds one. +/// +/// # Extracting a raw pointer to the whole C string +/// +/// `CString` implements an [`as_ptr`][`CStr::as_ptr`] method through the [`Deref`] +/// trait. This method will give you a `*const c_char` which you can +/// feed directly to extern functions that expect a nul-terminated +/// string, like C's `strdup()`. Notice that [`as_ptr`][`CStr::as_ptr`] returns a +/// read-only pointer; if the C code writes to it, that causes +/// undefined behavior. +/// +/// # Extracting a slice of the whole C string +/// +/// Alternatively, you can obtain a &[[u8]] slice from a +/// `CString` with the [`CString::as_bytes`] method. Slices produced in this +/// way do *not* contain the trailing nul terminator. This is useful +/// when you will be calling an extern function that takes a `*const +/// u8` argument which is not necessarily nul-terminated, plus another +/// argument with the length of the string — like C's `strndup()`. +/// You can of course get the slice's length with its +/// [`len`][slice::len] method. +/// +/// If you need a &[[u8]] slice *with* the nul terminator, you +/// can use [`CString::as_bytes_with_nul`] instead. +/// +/// Once you have the kind of slice you need (with or without a nul +/// terminator), you can call the slice's own +/// [`as_ptr`][slice::as_ptr] method to get a read-only raw pointer to pass to +/// extern functions. See the documentation for that function for a +/// discussion on ensuring the lifetime of the raw pointer. +/// +/// [str]: prim@str "str" +/// [`Deref`]: ops::Deref +/// +/// # Examples +/// +/// ```ignore (extern-declaration) +/// # fn main() { +/// use std::ffi::CString; +/// use std::os::raw::c_char; +/// +/// extern "C" { +/// fn my_printer(s: *const c_char); +/// } +/// +/// // We are certain that our string doesn't have 0 bytes in the middle, +/// // so we can .expect() +/// let c_to_print = CString::new("Hello, world!").expect("CString::new failed"); +/// unsafe { +/// my_printer(c_to_print.as_ptr()); +/// } +/// # } +/// ``` +/// +/// # Safety +/// +/// `CString` is intended for working with traditional C-style strings +/// (a sequence of non-nul bytes terminated by a single nul byte); the +/// primary use case for these kinds of strings is interoperating with C-like +/// code. Often you will need to transfer ownership to/from that external +/// code. It is strongly recommended that you thoroughly read through the +/// documentation of `CString` before use, as improper ownership management +/// of `CString` instances can lead to invalid memory accesses, memory leaks, +/// and other memory errors. +#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)] +#[cfg_attr(not(test), rustc_diagnostic_item = "cstring_type")] +#[stable(feature = "alloc_c_string", since = "1.64.0")] +pub struct CString { + // Invariant 1: the slice ends with a zero byte and has a length of at least one. + // Invariant 2: the slice contains only one zero byte. + // Improper usage of unsafe function can break Invariant 2, but not Invariant 1. + inner: Box<[u8]>, +} + +/// An error indicating that an interior nul byte was found. +/// +/// While Rust strings may contain nul bytes in the middle, C strings +/// can't, as that byte would effectively truncate the string. +/// +/// This error is created by the [`new`][`CString::new`] method on +/// [`CString`]. See its documentation for more. +/// +/// # Examples +/// +/// ``` +/// use std::ffi::{CString, NulError}; +/// +/// let _: NulError = CString::new(b"f\0oo".to_vec()).unwrap_err(); +/// ``` +#[derive(Clone, PartialEq, Eq, Debug)] +#[stable(feature = "alloc_c_string", since = "1.64.0")] +pub struct NulError(usize, Vec); + +#[derive(Clone, PartialEq, Eq, Debug)] +enum FromBytesWithNulErrorKind { + InteriorNul(usize), + NotNulTerminated, +} + +/// An error indicating that a nul byte was not in the expected position. +/// +/// The vector used to create a [`CString`] must have one and only one nul byte, +/// positioned at the end. +/// +/// This error is created by the [`CString::from_vec_with_nul`] method. +/// See its documentation for more. +/// +/// # Examples +/// +/// ``` +/// use std::ffi::{CString, FromVecWithNulError}; +/// +/// let _: FromVecWithNulError = CString::from_vec_with_nul(b"f\0oo".to_vec()).unwrap_err(); +/// ``` +#[derive(Clone, PartialEq, Eq, Debug)] +#[stable(feature = "alloc_c_string", since = "1.64.0")] +pub struct FromVecWithNulError { + error_kind: FromBytesWithNulErrorKind, + bytes: Vec, +} + +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] +impl FromVecWithNulError { + /// Returns a slice of [`u8`]s bytes that were attempted to convert to a [`CString`]. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::ffi::CString; + /// + /// // Some invalid bytes in a vector + /// let bytes = b"f\0oo".to_vec(); + /// + /// let value = CString::from_vec_with_nul(bytes.clone()); + /// + /// assert_eq!(&bytes[..], value.unwrap_err().as_bytes()); + /// ``` + #[must_use] + #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] + pub fn as_bytes(&self) -> &[u8] { + &self.bytes[..] + } + + /// Returns the bytes that were attempted to convert to a [`CString`]. + /// + /// This method is carefully constructed to avoid allocation. It will + /// consume the error, moving out the bytes, so that a copy of the bytes + /// does not need to be made. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::ffi::CString; + /// + /// // Some invalid bytes in a vector + /// let bytes = b"f\0oo".to_vec(); + /// + /// let value = CString::from_vec_with_nul(bytes.clone()); + /// + /// assert_eq!(bytes, value.unwrap_err().into_bytes()); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] + pub fn into_bytes(self) -> Vec { + self.bytes + } +} + +/// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`]. +/// +/// `CString` is just a wrapper over a buffer of bytes with a nul terminator; +/// [`CString::into_string`] performs UTF-8 validation on those bytes and may +/// return this error. +/// +/// This `struct` is created by [`CString::into_string()`]. See +/// its documentation for more. +#[derive(Clone, PartialEq, Eq, Debug)] +#[stable(feature = "alloc_c_string", since = "1.64.0")] +pub struct IntoStringError { + inner: CString, + error: Utf8Error, +} + +impl CString { + /// Creates a new C-compatible string from a container of bytes. + /// + /// This function will consume the provided data and use the + /// underlying bytes to construct a new string, ensuring that + /// there is a trailing 0 byte. This trailing 0 byte will be + /// appended by this function; the provided data should *not* + /// contain any 0 bytes in it. + /// + /// # Examples + /// + /// ```ignore (extern-declaration) + /// use std::ffi::CString; + /// use std::os::raw::c_char; + /// + /// extern "C" { fn puts(s: *const c_char); } + /// + /// let to_print = CString::new("Hello!").expect("CString::new failed"); + /// unsafe { + /// puts(to_print.as_ptr()); + /// } + /// ``` + /// + /// # Errors + /// + /// This function will return an error if the supplied bytes contain an + /// internal 0 byte. The [`NulError`] returned will contain the bytes as well as + /// the position of the nul byte. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new>>(t: T) -> Result { + trait SpecNewImpl { + fn spec_new_impl(self) -> Result; + } + + impl>> SpecNewImpl for T { + default fn spec_new_impl(self) -> Result { + let bytes: Vec = self.into(); + match memchr::memchr(0, &bytes) { + Some(i) => Err(NulError(i, bytes)), + None => Ok(unsafe { CString::_from_vec_unchecked(bytes) }), + } + } + } + + // Specialization for avoiding reallocation + #[inline(always)] // Without that it is not inlined into specializations + fn spec_new_impl_bytes(bytes: &[u8]) -> Result { + // We cannot have such large slice that we would overflow here + // but using `checked_add` allows LLVM to assume that capacity never overflows + // and generate twice shorter code. + // `saturating_add` doesn't help for some reason. + let capacity = bytes.len().checked_add(1).unwrap(); + + // Allocate before validation to avoid duplication of allocation code. + // We still need to allocate and copy memory even if we get an error. + let mut buffer = Vec::with_capacity(capacity); + buffer.extend(bytes); + + // Check memory of self instead of new buffer. + // This allows better optimizations if lto enabled. + match memchr::memchr(0, bytes) { + Some(i) => Err(NulError(i, buffer)), + None => Ok(unsafe { CString::_from_vec_unchecked(buffer) }), + } + } + + impl SpecNewImpl for &'_ [u8] { + fn spec_new_impl(self) -> Result { + spec_new_impl_bytes(self) + } + } + + impl SpecNewImpl for &'_ str { + fn spec_new_impl(self) -> Result { + spec_new_impl_bytes(self.as_bytes()) + } + } + + impl SpecNewImpl for &'_ mut [u8] { + fn spec_new_impl(self) -> Result { + spec_new_impl_bytes(self) + } + } + + t.spec_new_impl() + } + + /// Creates a C-compatible string by consuming a byte vector, + /// without checking for interior 0 bytes. + /// + /// Trailing 0 byte will be appended by this function. + /// + /// This method is equivalent to [`CString::new`] except that no runtime + /// assertion is made that `v` contains no 0 bytes, and it requires an + /// actual byte vector, not anything that can be converted to one with Into. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let raw = b"foo".to_vec(); + /// unsafe { + /// let c_string = CString::from_vec_unchecked(raw); + /// } + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn from_vec_unchecked(v: Vec) -> Self { + debug_assert!(memchr::memchr(0, &v).is_none()); + unsafe { Self::_from_vec_unchecked(v) } + } + + unsafe fn _from_vec_unchecked(mut v: Vec) -> Self { + v.reserve_exact(1); + v.push(0); + Self { inner: v.into_boxed_slice() } + } + + /// Retakes ownership of a `CString` that was transferred to C via + /// [`CString::into_raw`]. + /// + /// Additionally, the length of the string will be recalculated from the pointer. + /// + /// # Safety + /// + /// This should only ever be called with a pointer that was earlier + /// obtained by calling [`CString::into_raw`]. Other usage (e.g., trying to take + /// ownership of a string that was allocated by foreign code) is likely to lead + /// to undefined behavior or allocator corruption. + /// + /// It should be noted that the length isn't just "recomputed," but that + /// the recomputed length must match the original length from the + /// [`CString::into_raw`] call. This means the [`CString::into_raw`]/`from_raw` + /// methods should not be used when passing the string to C functions that can + /// modify the string's length. + /// + /// > **Note:** If you need to borrow a string that was allocated by + /// > foreign code, use [`CStr`]. If you need to take ownership of + /// > a string that was allocated by foreign code, you will need to + /// > make your own provisions for freeing it appropriately, likely + /// > with the foreign code's API to do that. + /// + /// # Examples + /// + /// Creates a `CString`, pass ownership to an `extern` function (via raw pointer), then retake + /// ownership with `from_raw`: + /// + /// ```ignore (extern-declaration) + /// use std::ffi::CString; + /// use std::os::raw::c_char; + /// + /// extern "C" { + /// fn some_extern_function(s: *mut c_char); + /// } + /// + /// let c_string = CString::from(c"Hello!"); + /// let raw = c_string.into_raw(); + /// unsafe { + /// some_extern_function(raw); + /// let c_string = CString::from_raw(raw); + /// } + /// ``` + #[must_use = "call `drop(from_raw(ptr))` if you intend to drop the `CString`"] + #[stable(feature = "cstr_memory", since = "1.4.0")] + pub unsafe fn from_raw(ptr: *mut c_char) -> CString { + // SAFETY: This is called with a pointer that was obtained from a call + // to `CString::into_raw` and the length has not been modified. As such, + // we know there is a NUL byte (and only one) at the end and that the + // information about the size of the allocation is correct on Rust's + // side. + unsafe { + extern "C" { + /// Provided by libc or compiler_builtins. + fn strlen(s: *const c_char) -> usize; + } + let len = strlen(ptr) + 1; // Including the NUL byte + let slice = slice::from_raw_parts_mut(ptr, len); + CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) } + } + } + + /// Consumes the `CString` and transfers ownership of the string to a C caller. + /// + /// The pointer which this function returns must be returned to Rust and reconstituted using + /// [`CString::from_raw`] to be properly deallocated. Specifically, one + /// should *not* use the standard C `free()` function to deallocate + /// this string. + /// + /// Failure to call [`CString::from_raw`] will lead to a memory leak. + /// + /// The C side must **not** modify the length of the string (by writing a + /// nul byte somewhere inside the string or removing the final one) before + /// it makes it back into Rust using [`CString::from_raw`]. See the safety section + /// in [`CString::from_raw`]. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::from(c"foo"); + /// + /// let ptr = c_string.into_raw(); + /// + /// unsafe { + /// assert_eq!(b'f', *ptr as u8); + /// assert_eq!(b'o', *ptr.add(1) as u8); + /// assert_eq!(b'o', *ptr.add(2) as u8); + /// assert_eq!(b'\0', *ptr.add(3) as u8); + /// + /// // retake pointer to free memory + /// let _ = CString::from_raw(ptr); + /// } + /// ``` + #[inline] + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "cstr_memory", since = "1.4.0")] + pub fn into_raw(self) -> *mut c_char { + Box::into_raw(self.into_inner()) as *mut c_char + } + + /// Converts the `CString` into a [`String`] if it contains valid UTF-8 data. + /// + /// On failure, ownership of the original `CString` is returned. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let valid_utf8 = vec![b'f', b'o', b'o']; + /// let cstring = CString::new(valid_utf8).expect("CString::new failed"); + /// assert_eq!(cstring.into_string().expect("into_string() call failed"), "foo"); + /// + /// let invalid_utf8 = vec![b'f', 0xff, b'o', b'o']; + /// let cstring = CString::new(invalid_utf8).expect("CString::new failed"); + /// let err = cstring.into_string().err().expect("into_string().err() failed"); + /// assert_eq!(err.utf8_error().valid_up_to(), 1); + /// ``` + #[stable(feature = "cstring_into", since = "1.7.0")] + pub fn into_string(self) -> Result { + String::from_utf8(self.into_bytes()).map_err(|e| IntoStringError { + error: e.utf8_error(), + inner: unsafe { Self::_from_vec_unchecked(e.into_bytes()) }, + }) + } + + /// Consumes the `CString` and returns the underlying byte buffer. + /// + /// The returned buffer does **not** contain the trailing nul + /// terminator, and it is guaranteed to not have any interior nul + /// bytes. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::from(c"foo"); + /// let bytes = c_string.into_bytes(); + /// assert_eq!(bytes, vec![b'f', b'o', b'o']); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "cstring_into", since = "1.7.0")] + pub fn into_bytes(self) -> Vec { + let mut vec = into_vec(self.into_inner()); + let _nul = vec.pop(); + debug_assert_eq!(_nul, Some(0u8)); + vec + } + + /// Equivalent to [`CString::into_bytes()`] except that the + /// returned vector includes the trailing nul terminator. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::from(c"foo"); + /// let bytes = c_string.into_bytes_with_nul(); + /// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "cstring_into", since = "1.7.0")] + pub fn into_bytes_with_nul(self) -> Vec { + into_vec(self.into_inner()) + } + + /// Returns the contents of this `CString` as a slice of bytes. + /// + /// The returned slice does **not** contain the trailing nul + /// terminator, and it is guaranteed to not have any interior nul + /// bytes. If you need the nul terminator, use + /// [`CString::as_bytes_with_nul`] instead. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::from(c"foo"); + /// let bytes = c_string.as_bytes(); + /// assert_eq!(bytes, &[b'f', b'o', b'o']); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_bytes(&self) -> &[u8] { + // SAFETY: CString has a length at least 1 + unsafe { self.inner.get_unchecked(..self.inner.len() - 1) } + } + + /// Equivalent to [`CString::as_bytes()`] except that the + /// returned slice includes the trailing nul terminator. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::from(c"foo"); + /// let bytes = c_string.as_bytes_with_nul(); + /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_bytes_with_nul(&self) -> &[u8] { + &self.inner + } + + /// Extracts a [`CStr`] slice containing the entire string. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::{CString, CStr}; + /// + /// let c_string = CString::from(c"foo"); + /// let cstr = c_string.as_c_str(); + /// assert_eq!(cstr, + /// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed")); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "as_c_str", since = "1.20.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "cstring_as_c_str")] + pub fn as_c_str(&self) -> &CStr { + &*self + } + + /// Converts this `CString` into a boxed [`CStr`]. + /// + /// # Examples + /// + /// ``` + /// let c_string = c"foo".to_owned(); + /// let boxed = c_string.into_boxed_c_str(); + /// assert_eq!(boxed.to_bytes_with_nul(), b"foo\0"); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "into_boxed_c_str", since = "1.20.0")] + pub fn into_boxed_c_str(self) -> Box { + unsafe { Box::from_raw(Box::into_raw(self.into_inner()) as *mut CStr) } + } + + /// Bypass "move out of struct which implements [`Drop`] trait" restriction. + #[inline] + fn into_inner(self) -> Box<[u8]> { + // Rationale: `mem::forget(self)` invalidates the previous call to `ptr::read(&self.inner)` + // so we use `ManuallyDrop` to ensure `self` is not dropped. + // Then we can return the box directly without invalidating it. + // See https://github.com/rust-lang/rust/issues/62553. + let this = mem::ManuallyDrop::new(self); + unsafe { ptr::read(&this.inner) } + } + + /// Converts a [Vec]<[u8]> to a [`CString`] without checking the + /// invariants on the given [`Vec`]. + /// + /// # Safety + /// + /// The given [`Vec`] **must** have one nul byte as its last element. + /// This means it cannot be empty nor have any other nul byte anywhere else. + /// + /// # Example + /// + /// ``` + /// use std::ffi::CString; + /// assert_eq!( + /// unsafe { CString::from_vec_with_nul_unchecked(b"abc\0".to_vec()) }, + /// unsafe { CString::from_vec_unchecked(b"abc".to_vec()) } + /// ); + /// ``` + #[must_use] + #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] + pub unsafe fn from_vec_with_nul_unchecked(v: Vec) -> Self { + debug_assert!(memchr::memchr(0, &v).unwrap() + 1 == v.len()); + unsafe { Self::_from_vec_with_nul_unchecked(v) } + } + + unsafe fn _from_vec_with_nul_unchecked(v: Vec) -> Self { + Self { inner: v.into_boxed_slice() } + } + + /// Attempts to converts a [Vec]<[u8]> to a [`CString`]. + /// + /// Runtime checks are present to ensure there is only one nul byte in the + /// [`Vec`], its last element. + /// + /// # Errors + /// + /// If a nul byte is present and not the last element or no nul bytes + /// is present, an error will be returned. + /// + /// # Examples + /// + /// A successful conversion will produce the same result as [`CString::new`] + /// when called without the ending nul byte. + /// + /// ``` + /// use std::ffi::CString; + /// assert_eq!( + /// CString::from_vec_with_nul(b"abc\0".to_vec()) + /// .expect("CString::from_vec_with_nul failed"), + /// c"abc".to_owned() + /// ); + /// ``` + /// + /// An incorrectly formatted [`Vec`] will produce an error. + /// + /// ``` + /// use std::ffi::{CString, FromVecWithNulError}; + /// // Interior nul byte + /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err(); + /// // No nul byte + /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err(); + /// ``` + #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] + pub fn from_vec_with_nul(v: Vec) -> Result { + let nul_pos = memchr::memchr(0, &v); + match nul_pos { + Some(nul_pos) if nul_pos + 1 == v.len() => { + // SAFETY: We know there is only one nul byte, at the end + // of the vec. + Ok(unsafe { Self::_from_vec_with_nul_unchecked(v) }) + } + Some(nul_pos) => Err(FromVecWithNulError { + error_kind: FromBytesWithNulErrorKind::InteriorNul(nul_pos), + bytes: v, + }), + None => Err(FromVecWithNulError { + error_kind: FromBytesWithNulErrorKind::NotNulTerminated, + bytes: v, + }), + } + } +} + +// Turns this `CString` into an empty string to prevent +// memory-unsafe code from working by accident. Inline +// to prevent LLVM from optimizing it away in debug builds. +#[stable(feature = "cstring_drop", since = "1.13.0")] +#[rustc_insignificant_dtor] +impl Drop for CString { + #[inline] + fn drop(&mut self) { + unsafe { + *self.inner.get_unchecked_mut(0) = 0; + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Deref for CString { + type Target = CStr; + + #[inline] + fn deref(&self) -> &CStr { + unsafe { CStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for CString { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "cstring_into", since = "1.7.0")] +impl From for Vec { + /// Converts a [`CString`] into a [Vec]<[u8]>. + /// + /// The conversion consumes the [`CString`], and removes the terminating NUL byte. + #[inline] + fn from(s: CString) -> Vec { + s.into_bytes() + } +} + +#[stable(feature = "cstr_default", since = "1.10.0")] +impl Default for CString { + /// Creates an empty `CString`. + fn default() -> CString { + let a: &CStr = Default::default(); + a.to_owned() + } +} + +#[stable(feature = "cstr_borrow", since = "1.3.0")] +impl Borrow for CString { + #[inline] + fn borrow(&self) -> &CStr { + self + } +} + +#[stable(feature = "cstring_from_cow_cstr", since = "1.28.0")] +impl<'a> From> for CString { + /// Converts a `Cow<'a, CStr>` into a `CString`, by copying the contents if they are + /// borrowed. + #[inline] + fn from(s: Cow<'a, CStr>) -> Self { + s.into_owned() + } +} + +#[cfg(not(test))] +#[stable(feature = "box_from_c_str", since = "1.17.0")] +impl From<&CStr> for Box { + /// Converts a `&CStr` into a `Box`, + /// by copying the contents into a newly allocated [`Box`]. + fn from(s: &CStr) -> Box { + let boxed: Box<[u8]> = Box::from(s.to_bytes_with_nul()); + unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) } + } +} + +#[cfg(not(test))] +#[stable(feature = "box_from_mut_slice", since = "1.84.0")] +impl From<&mut CStr> for Box { + /// Converts a `&mut CStr` into a `Box`, + /// by copying the contents into a newly allocated [`Box`]. + fn from(s: &mut CStr) -> Box { + Self::from(&*s) + } +} + +#[stable(feature = "box_from_cow", since = "1.45.0")] +impl From> for Box { + /// Converts a `Cow<'a, CStr>` into a `Box`, + /// by copying the contents if they are borrowed. + #[inline] + fn from(cow: Cow<'_, CStr>) -> Box { + match cow { + Cow::Borrowed(s) => Box::from(s), + Cow::Owned(s) => Box::from(s), + } + } +} + +#[stable(feature = "c_string_from_box", since = "1.18.0")] +impl From> for CString { + /// Converts a [Box]<[CStr]> into a [`CString`] without copying or allocating. + #[inline] + fn from(s: Box) -> CString { + let raw = Box::into_raw(s) as *mut [u8]; + CString { inner: unsafe { Box::from_raw(raw) } } + } +} + +#[stable(feature = "cstring_from_vec_of_nonzerou8", since = "1.43.0")] +impl From>> for CString { + /// Converts a [Vec]<[NonZero]<[u8]>> into a [`CString`] without + /// copying nor checking for inner nul bytes. + #[inline] + fn from(v: Vec>) -> CString { + unsafe { + // Transmute `Vec>` to `Vec`. + let v: Vec = { + // SAFETY: + // - transmuting between `NonZero` and `u8` is sound; + // - `alloc::Layout> == alloc::Layout`. + let (ptr, len, cap): (*mut NonZero, _, _) = Vec::into_raw_parts(v); + Vec::from_raw_parts(ptr.cast::(), len, cap) + }; + // SAFETY: `v` cannot contain nul bytes, given the type-level + // invariant of `NonZero`. + Self::_from_vec_unchecked(v) + } + } +} + +impl FromStr for CString { + type Err = NulError; + + /// Converts a string `s` into a [`CString`]. + /// + /// This method is equivalent to [`CString::new`]. + #[inline] + fn from_str(s: &str) -> Result { + Self::new(s) + } +} + +impl TryFrom for String { + type Error = IntoStringError; + + /// Converts a [`CString`] into a [`String`] if it contains valid UTF-8 data. + /// + /// This method is equivalent to [`CString::into_string`]. + #[inline] + fn try_from(value: CString) -> Result { + value.into_string() + } +} + +#[cfg(not(test))] +#[stable(feature = "more_box_slice_clone", since = "1.29.0")] +impl Clone for Box { + #[inline] + fn clone(&self) -> Self { + (**self).into() + } +} + +#[stable(feature = "box_from_c_string", since = "1.20.0")] +impl From for Box { + /// Converts a [`CString`] into a [Box]<[CStr]> without copying or allocating. + #[inline] + fn from(s: CString) -> Box { + s.into_boxed_c_str() + } +} + +#[stable(feature = "cow_from_cstr", since = "1.28.0")] +impl<'a> From for Cow<'a, CStr> { + /// Converts a [`CString`] into an owned [`Cow`] without copying or allocating. + #[inline] + fn from(s: CString) -> Cow<'a, CStr> { + Cow::Owned(s) + } +} + +#[stable(feature = "cow_from_cstr", since = "1.28.0")] +impl<'a> From<&'a CStr> for Cow<'a, CStr> { + /// Converts a [`CStr`] into a borrowed [`Cow`] without copying or allocating. + #[inline] + fn from(s: &'a CStr) -> Cow<'a, CStr> { + Cow::Borrowed(s) + } +} + +#[stable(feature = "cow_from_cstr", since = "1.28.0")] +impl<'a> From<&'a CString> for Cow<'a, CStr> { + /// Converts a `&`[`CString`] into a borrowed [`Cow`] without copying or allocating. + #[inline] + fn from(s: &'a CString) -> Cow<'a, CStr> { + Cow::Borrowed(s.as_c_str()) + } +} + +#[cfg(target_has_atomic = "ptr")] +#[stable(feature = "shared_from_slice2", since = "1.24.0")] +impl From for Arc { + /// Converts a [`CString`] into an [Arc]<[CStr]> by moving the [`CString`] + /// data into a new [`Arc`] buffer. + #[inline] + fn from(s: CString) -> Arc { + let arc: Arc<[u8]> = Arc::from(s.into_inner()); + unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) } + } +} + +#[cfg(target_has_atomic = "ptr")] +#[stable(feature = "shared_from_slice2", since = "1.24.0")] +impl From<&CStr> for Arc { + /// Converts a `&CStr` into a `Arc`, + /// by copying the contents into a newly allocated [`Arc`]. + #[inline] + fn from(s: &CStr) -> Arc { + let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul()); + unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) } + } +} + +#[cfg(target_has_atomic = "ptr")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] +impl From<&mut CStr> for Arc { + /// Converts a `&mut CStr` into a `Arc`, + /// by copying the contents into a newly allocated [`Arc`]. + #[inline] + fn from(s: &mut CStr) -> Arc { + Arc::from(&*s) + } +} + +#[stable(feature = "shared_from_slice2", since = "1.24.0")] +impl From for Rc { + /// Converts a [`CString`] into an [Rc]<[CStr]> by moving the [`CString`] + /// data into a new [`Rc`] buffer. + #[inline] + fn from(s: CString) -> Rc { + let rc: Rc<[u8]> = Rc::from(s.into_inner()); + unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) } + } +} + +#[stable(feature = "shared_from_slice2", since = "1.24.0")] +impl From<&CStr> for Rc { + /// Converts a `&CStr` into a `Rc`, + /// by copying the contents into a newly allocated [`Rc`]. + #[inline] + fn from(s: &CStr) -> Rc { + let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul()); + unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) } + } +} + +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] +impl From<&mut CStr> for Rc { + /// Converts a `&mut CStr` into a `Rc`, + /// by copying the contents into a newly allocated [`Rc`]. + #[inline] + fn from(s: &mut CStr) -> Rc { + Rc::from(&*s) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "1.80.0")] +impl Default for Rc { + /// Creates an empty CStr inside an Rc + /// + /// This may or may not share an allocation with other Rcs on the same thread. + #[inline] + fn default() -> Self { + let c_str: &CStr = Default::default(); + Rc::from(c_str) + } +} + +#[cfg(not(test))] +#[stable(feature = "default_box_extra", since = "1.17.0")] +impl Default for Box { + fn default() -> Box { + let boxed: Box<[u8]> = Box::from([0]); + unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) } + } +} + +impl NulError { + /// Returns the position of the nul byte in the slice that caused + /// [`CString::new`] to fail. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let nul_error = CString::new("foo\0bar").unwrap_err(); + /// assert_eq!(nul_error.nul_position(), 3); + /// + /// let nul_error = CString::new("foo bar\0").unwrap_err(); + /// assert_eq!(nul_error.nul_position(), 7); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn nul_position(&self) -> usize { + self.0 + } + + /// Consumes this error, returning the underlying vector of bytes which + /// generated the error in the first place. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let nul_error = CString::new("foo\0bar").unwrap_err(); + /// assert_eq!(nul_error.into_vec(), b"foo\0bar"); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_vec(self) -> Vec { + self.1 + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for NulError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "nul byte found in provided data at position: {}", self.0) + } +} + +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] +impl fmt::Display for FromVecWithNulError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.error_kind { + FromBytesWithNulErrorKind::InteriorNul(pos) => { + write!(f, "data provided contains an interior nul byte at pos {pos}") + } + FromBytesWithNulErrorKind::NotNulTerminated => { + write!(f, "data provided is not nul terminated") + } + } + } +} + +impl IntoStringError { + /// Consumes this error, returning original [`CString`] which generated the + /// error. + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "cstring_into", since = "1.7.0")] + pub fn into_cstring(self) -> CString { + self.inner + } + + /// Access the underlying UTF-8 error that was the cause of this error. + #[must_use] + #[stable(feature = "cstring_into", since = "1.7.0")] + pub fn utf8_error(&self) -> Utf8Error { + self.error + } +} + +impl IntoStringError { + fn description(&self) -> &str { + "C string contained non-utf8 bytes" + } +} + +#[stable(feature = "cstring_into", since = "1.7.0")] +impl fmt::Display for IntoStringError { + #[allow(deprecated, deprecated_in_future)] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.description().fmt(f) + } +} + +#[stable(feature = "cstr_borrow", since = "1.3.0")] +impl ToOwned for CStr { + type Owned = CString; + + fn to_owned(&self) -> CString { + CString { inner: self.to_bytes_with_nul().into() } + } + + fn clone_into(&self, target: &mut CString) { + let mut b = into_vec(mem::take(&mut target.inner)); + self.to_bytes_with_nul().clone_into(&mut b); + target.inner = b.into_boxed_slice(); + } +} + +#[stable(feature = "cstring_asref", since = "1.7.0")] +impl From<&CStr> for CString { + /// Converts a &[CStr] into a [`CString`] + /// by copying the contents into a new allocation. + fn from(s: &CStr) -> CString { + s.to_owned() + } +} + +#[stable(feature = "cstring_asref", since = "1.7.0")] +impl ops::Index for CString { + type Output = CStr; + + #[inline] + fn index(&self, _index: ops::RangeFull) -> &CStr { + self + } +} + +#[stable(feature = "cstring_asref", since = "1.7.0")] +impl AsRef for CString { + #[inline] + fn as_ref(&self) -> &CStr { + self + } +} + +#[cfg(not(test))] +impl CStr { + /// Converts a `CStr` into a [Cow]<[str]>. + /// + /// If the contents of the `CStr` are valid UTF-8 data, this + /// function will return a [Cow]::[Borrowed]\(&[str]) + /// with the corresponding &[str] slice. Otherwise, it will + /// replace any invalid UTF-8 sequences with + /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a + /// [Cow]::[Owned]\(&[str]) with the result. + /// + /// [str]: prim@str "str" + /// [Borrowed]: Cow::Borrowed + /// [Owned]: Cow::Owned + /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER "std::char::REPLACEMENT_CHARACTER" + /// + /// # Examples + /// + /// Calling `to_string_lossy` on a `CStr` containing valid UTF-8. The leading + /// `c` on the string literal denotes a `CStr`. + /// + /// ``` + /// use std::borrow::Cow; + /// + /// assert_eq!(c"Hello World".to_string_lossy(), Cow::Borrowed("Hello World")); + /// ``` + /// + /// Calling `to_string_lossy` on a `CStr` containing invalid UTF-8: + /// + /// ``` + /// use std::borrow::Cow; + /// + /// assert_eq!( + /// c"Hello \xF0\x90\x80World".to_string_lossy(), + /// Cow::Owned(String::from("Hello �World")) as Cow<'_, str> + /// ); + /// ``` + #[rustc_allow_incoherent_impl] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[stable(feature = "cstr_to_str", since = "1.4.0")] + pub fn to_string_lossy(&self) -> Cow<'_, str> { + String::from_utf8_lossy(self.to_bytes()) + } + + /// Converts a [Box]<[CStr]> into a [`CString`] without copying or allocating. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::{CStr, CString}; + /// + /// let boxed: Box = Box::from(c"foo"); + /// let c_string: CString = c"foo".to_owned(); + /// + /// assert_eq!(boxed.into_c_string(), c_string); + /// ``` + #[rustc_allow_incoherent_impl] + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "into_boxed_c_str", since = "1.20.0")] + pub fn into_c_string(self: Box) -> CString { + CString::from(self) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl core::error::Error for NulError { + #[allow(deprecated)] + fn description(&self) -> &str { + "nul byte found in data" + } +} + +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] +impl core::error::Error for FromVecWithNulError {} + +#[stable(feature = "cstring_into", since = "1.7.0")] +impl core::error::Error for IntoStringError { + #[allow(deprecated)] + fn description(&self) -> &str { + "C string contained non-utf8 bytes" + } + + fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { + Some(&self.error) + } +} diff --git a/CoqOfRust/alloc/ffi/c_str/tests.rs b/CoqOfRust/alloc/ffi/c_str/tests.rs new file mode 100644 index 000000000..d6b797347 --- /dev/null +++ b/CoqOfRust/alloc/ffi/c_str/tests.rs @@ -0,0 +1,226 @@ +use core::assert_matches::assert_matches; +use core::ffi::FromBytesUntilNulError; +#[allow(deprecated)] +use core::hash::SipHasher13 as DefaultHasher; +use core::hash::{Hash, Hasher}; + +use super::*; + +#[test] +fn c_to_rust() { + let data = b"123\0"; + let ptr = data.as_ptr() as *const c_char; + unsafe { + assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123"); + assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0"); + } +} + +#[test] +fn simple() { + let s = CString::new("1234").unwrap(); + assert_eq!(s.as_bytes(), b"1234"); + assert_eq!(s.as_bytes_with_nul(), b"1234\0"); +} + +#[test] +fn build_with_zero1() { + assert!(CString::new(&b"\0"[..]).is_err()); +} +#[test] +fn build_with_zero2() { + assert!(CString::new(vec![0]).is_err()); +} + +#[test] +fn formatted() { + let s = CString::new(&b"abc\x01\x02\n\xE2\x80\xA6\xFF"[..]).unwrap(); + assert_eq!(format!("{s:?}"), r#""abc\x01\x02\n\xe2\x80\xa6\xff""#); +} + +#[test] +fn borrowed() { + unsafe { + let s = CStr::from_ptr(b"12\0".as_ptr() as *const _); + assert_eq!(s.to_bytes(), b"12"); + assert_eq!(s.to_bytes_with_nul(), b"12\0"); + } +} + +#[test] +fn to_owned() { + let data = b"123\0"; + let ptr = data.as_ptr() as *const c_char; + + let owned = unsafe { CStr::from_ptr(ptr).to_owned() }; + assert_eq!(owned.as_bytes_with_nul(), data); +} + +#[test] +fn equal_hash() { + let data = b"123\xE2\xFA\xA6\0"; + let ptr = data.as_ptr() as *const c_char; + let cstr: &'static CStr = unsafe { CStr::from_ptr(ptr) }; + + #[allow(deprecated)] + let mut s = DefaultHasher::new(); + cstr.hash(&mut s); + let cstr_hash = s.finish(); + #[allow(deprecated)] + let mut s = DefaultHasher::new(); + CString::new(&data[..data.len() - 1]).unwrap().hash(&mut s); + let cstring_hash = s.finish(); + + assert_eq!(cstr_hash, cstring_hash); +} + +#[test] +fn from_bytes_with_nul() { + let data = b"123\0"; + let cstr = CStr::from_bytes_with_nul(data); + assert_eq!(cstr.map(CStr::to_bytes), Ok(&b"123"[..])); + let cstr = CStr::from_bytes_with_nul(data); + assert_eq!(cstr.map(CStr::to_bytes_with_nul), Ok(&b"123\0"[..])); + + unsafe { + let cstr = CStr::from_bytes_with_nul(data); + let cstr_unchecked = CStr::from_bytes_with_nul_unchecked(data); + assert_eq!(cstr, Ok(cstr_unchecked)); + } +} + +#[test] +fn from_bytes_with_nul_unterminated() { + let data = b"123"; + let cstr = CStr::from_bytes_with_nul(data); + assert!(cstr.is_err()); +} + +#[test] +fn from_bytes_with_nul_interior() { + let data = b"1\023\0"; + let cstr = CStr::from_bytes_with_nul(data); + assert!(cstr.is_err()); +} + +#[test] +fn cstr_from_bytes_until_nul() { + // Test an empty slice. This should fail because it + // does not contain a nul byte. + let b = b""; + assert_matches!(CStr::from_bytes_until_nul(&b[..]), Err(FromBytesUntilNulError { .. })); + + // Test a non-empty slice, that does not contain a nul byte. + let b = b"hello"; + assert_matches!(CStr::from_bytes_until_nul(&b[..]), Err(FromBytesUntilNulError { .. })); + + // Test an empty nul-terminated string + let b = b"\0"; + let r = CStr::from_bytes_until_nul(&b[..]).unwrap(); + assert_eq!(r.to_bytes(), b""); + + // Test a slice with the nul byte in the middle + let b = b"hello\0world!"; + let r = CStr::from_bytes_until_nul(&b[..]).unwrap(); + assert_eq!(r.to_bytes(), b"hello"); + + // Test a slice with the nul byte at the end + let b = b"hello\0"; + let r = CStr::from_bytes_until_nul(&b[..]).unwrap(); + assert_eq!(r.to_bytes(), b"hello"); + + // Test a slice with two nul bytes at the end + let b = b"hello\0\0"; + let r = CStr::from_bytes_until_nul(&b[..]).unwrap(); + assert_eq!(r.to_bytes(), b"hello"); + + // Test a slice containing lots of nul bytes + let b = b"\0\0\0\0"; + let r = CStr::from_bytes_until_nul(&b[..]).unwrap(); + assert_eq!(r.to_bytes(), b""); +} + +#[test] +fn into_boxed() { + let orig: &[u8] = b"Hello, world!\0"; + let cstr = CStr::from_bytes_with_nul(orig).unwrap(); + let boxed: Box = Box::from(cstr); + let cstring = cstr.to_owned().into_boxed_c_str().into_c_string(); + assert_eq!(cstr, &*boxed); + assert_eq!(&*boxed, &*cstring); + assert_eq!(&*cstring, cstr); +} + +#[test] +fn boxed_default() { + let boxed = >::default(); + assert_eq!(boxed.to_bytes_with_nul(), &[0]); +} + +#[test] +fn test_c_str_clone_into() { + let mut c_string = c"lorem".to_owned(); + let c_ptr = c_string.as_ptr(); + let c_str = CStr::from_bytes_with_nul(b"ipsum\0").unwrap(); + c_str.clone_into(&mut c_string); + assert_eq!(c_str, c_string.as_c_str()); + // The exact same size shouldn't have needed to move its allocation + assert_eq!(c_ptr, c_string.as_ptr()); +} + +#[test] +fn into_rc() { + let orig: &[u8] = b"Hello, world!\0"; + let cstr = CStr::from_bytes_with_nul(orig).unwrap(); + let rc: Rc = Rc::from(cstr); + let arc: Arc = Arc::from(cstr); + + assert_eq!(&*rc, cstr); + assert_eq!(&*arc, cstr); + + let rc2: Rc = Rc::from(cstr.to_owned()); + let arc2: Arc = Arc::from(cstr.to_owned()); + + assert_eq!(&*rc2, cstr); + assert_eq!(&*arc2, cstr); +} + +#[test] +fn cstr_const_constructor() { + const CSTR: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"Hello, world!\0") }; + + assert_eq!(CSTR.to_str().unwrap(), "Hello, world!"); +} + +#[test] +fn cstr_index_from() { + let original = b"Hello, world!\0"; + let cstr = CStr::from_bytes_with_nul(original).unwrap(); + let result = CStr::from_bytes_with_nul(&original[7..]).unwrap(); + + assert_eq!(&cstr[7..], result); +} + +#[test] +#[should_panic] +fn cstr_index_from_empty() { + let original = b"Hello, world!\0"; + let cstr = CStr::from_bytes_with_nul(original).unwrap(); + let _ = &cstr[original.len()..]; +} + +#[test] +fn c_string_from_empty_string() { + let original = ""; + let cstring = CString::new(original).unwrap(); + assert_eq!(original.as_bytes(), cstring.as_bytes()); + assert_eq!([b'\0'], cstring.as_bytes_with_nul()); +} + +#[test] +fn c_str_from_empty_string() { + let original = b"\0"; + let cstr = CStr::from_bytes_with_nul(original).unwrap(); + assert_eq!([] as [u8; 0], cstr.to_bytes()); + assert_eq!([b'\0'], cstr.to_bytes_with_nul()); +} diff --git a/CoqOfRust/alloc/ffi/mod.rs b/CoqOfRust/alloc/ffi/mod.rs new file mode 100644 index 000000000..4f9dc40a3 --- /dev/null +++ b/CoqOfRust/alloc/ffi/mod.rs @@ -0,0 +1,91 @@ +//! Utilities related to FFI bindings. +//! +//! This module provides utilities to handle data across non-Rust +//! interfaces, like other programming languages and the underlying +//! operating system. It is mainly of use for FFI (Foreign Function +//! Interface) bindings and code that needs to exchange C-like strings +//! with other languages. +//! +//! # Overview +//! +//! Rust represents owned strings with the [`String`] type, and +//! borrowed slices of strings with the [`str`] primitive. Both are +//! always in UTF-8 encoding, and may contain nul bytes in the middle, +//! i.e., if you look at the bytes that make up the string, there may +//! be a `\0` among them. Both `String` and `str` store their length +//! explicitly; there are no nul terminators at the end of strings +//! like in C. +//! +//! C strings are different from Rust strings: +//! +//! * **Encodings** - Rust strings are UTF-8, but C strings may use +//! other encodings. If you are using a string from C, you should +//! check its encoding explicitly, rather than just assuming that it +//! is UTF-8 like you can do in Rust. +//! +//! * **Character size** - C strings may use `char` or `wchar_t`-sized +//! characters; please **note** that C's `char` is different from Rust's. +//! The C standard leaves the actual sizes of those types open to +//! interpretation, but defines different APIs for strings made up of +//! each character type. Rust strings are always UTF-8, so different +//! Unicode characters will be encoded in a variable number of bytes +//! each. The Rust type [`char`] represents a '[Unicode scalar +//! value]', which is similar to, but not the same as, a '[Unicode +//! code point]'. +//! +//! * **Nul terminators and implicit string lengths** - Often, C +//! strings are nul-terminated, i.e., they have a `\0` character at the +//! end. The length of a string buffer is not stored, but has to be +//! calculated; to compute the length of a string, C code must +//! manually call a function like `strlen()` for `char`-based strings, +//! or `wcslen()` for `wchar_t`-based ones. Those functions return +//! the number of characters in the string excluding the nul +//! terminator, so the buffer length is really `len+1` characters. +//! Rust strings don't have a nul terminator; their length is always +//! stored and does not need to be calculated. While in Rust +//! accessing a string's length is an *O*(1) operation (because the +//! length is stored); in C it is an *O*(*n*) operation because the +//! length needs to be computed by scanning the string for the nul +//! terminator. +//! +//! * **Internal nul characters** - When C strings have a nul +//! terminator character, this usually means that they cannot have nul +//! characters in the middle — a nul character would essentially +//! truncate the string. Rust strings *can* have nul characters in +//! the middle, because nul does not have to mark the end of the +//! string in Rust. +//! +//! # Representations of non-Rust strings +//! +//! [`CString`] and [`CStr`] are useful when you need to transfer +//! UTF-8 strings to and from languages with a C ABI, like Python. +//! +//! * **From Rust to C:** [`CString`] represents an owned, C-friendly +//! string: it is nul-terminated, and has no internal nul characters. +//! Rust code can create a [`CString`] out of a normal string (provided +//! that the string doesn't have nul characters in the middle), and +//! then use a variety of methods to obtain a raw \*mut [u8] that can +//! then be passed as an argument to functions which use the C +//! conventions for strings. +//! +//! * **From C to Rust:** [`CStr`] represents a borrowed C string; it +//! is what you would use to wrap a raw \*const [u8] that you got from +//! a C function. A [`CStr`] is guaranteed to be a nul-terminated array +//! of bytes. Once you have a [`CStr`], you can convert it to a Rust +//! &[str] if it's valid UTF-8, or lossily convert it by adding +//! replacement characters. +//! +//! [`String`]: crate::string::String +//! [`CStr`]: core::ffi::CStr + +#![stable(feature = "alloc_ffi", since = "1.64.0")] + +#[doc(inline)] +#[stable(feature = "alloc_c_string", since = "1.64.0")] +pub use self::c_str::CString; +#[doc(no_inline)] +#[stable(feature = "alloc_c_string", since = "1.64.0")] +pub use self::c_str::{FromVecWithNulError, IntoStringError, NulError}; + +#[unstable(feature = "c_str_module", issue = "112134")] +pub mod c_str; diff --git a/CoqOfRust/alloc/fmt.rs b/CoqOfRust/alloc/fmt.rs new file mode 100644 index 000000000..695dddb25 --- /dev/null +++ b/CoqOfRust/alloc/fmt.rs @@ -0,0 +1,653 @@ +//! Utilities for formatting and printing `String`s. +//! +//! This module contains the runtime support for the [`format!`] syntax extension. +//! This macro is implemented in the compiler to emit calls to this module in +//! order to format arguments at runtime into strings. +//! +//! # Usage +//! +//! The [`format!`] macro is intended to be familiar to those coming from C's +//! `printf`/`fprintf` functions or Python's `str.format` function. +//! +//! Some examples of the [`format!`] extension are: +//! +//! ``` +//! # #![allow(unused_must_use)] +//! format!("Hello"); // => "Hello" +//! format!("Hello, {}!", "world"); // => "Hello, world!" +//! format!("The number is {}", 1); // => "The number is 1" +//! format!("{:?}", (3, 4)); // => "(3, 4)" +//! format!("{value}", value=4); // => "4" +//! let people = "Rustaceans"; +//! format!("Hello {people}!"); // => "Hello Rustaceans!" +//! format!("{} {}", 1, 2); // => "1 2" +//! format!("{:04}", 42); // => "0042" with leading zeros +//! format!("{:#?}", (100, 200)); // => "( +//! // 100, +//! // 200, +//! // )" +//! ``` +//! +//! From these, you can see that the first argument is a format string. It is +//! required by the compiler for this to be a string literal; it cannot be a +//! variable passed in (in order to perform validity checking). The compiler +//! will then parse the format string and determine if the list of arguments +//! provided is suitable to pass to this format string. +//! +//! To convert a single value to a string, use the [`to_string`] method. This +//! will use the [`Display`] formatting trait. +//! +//! ## Positional parameters +//! +//! Each formatting argument is allowed to specify which value argument it's +//! referencing, and if omitted it is assumed to be "the next argument". For +//! example, the format string `{} {} {}` would take three parameters, and they +//! would be formatted in the same order as they're given. The format string +//! `{2} {1} {0}`, however, would format arguments in reverse order. +//! +//! Things can get a little tricky once you start intermingling the two types of +//! positional specifiers. The "next argument" specifier can be thought of as an +//! iterator over the argument. Each time a "next argument" specifier is seen, +//! the iterator advances. This leads to behavior like this: +//! +//! ``` +//! # #![allow(unused_must_use)] +//! format!("{1} {} {0} {}", 1, 2); // => "2 1 1 2" +//! ``` +//! +//! The internal iterator over the argument has not been advanced by the time +//! the first `{}` is seen, so it prints the first argument. Then upon reaching +//! the second `{}`, the iterator has advanced forward to the second argument. +//! Essentially, parameters that explicitly name their argument do not affect +//! parameters that do not name an argument in terms of positional specifiers. +//! +//! A format string is required to use all of its arguments, otherwise it is a +//! compile-time error. You may refer to the same argument more than once in the +//! format string. +//! +//! ## Named parameters +//! +//! Rust itself does not have a Python-like equivalent of named parameters to a +//! function, but the [`format!`] macro is a syntax extension that allows it to +//! leverage named parameters. Named parameters are listed at the end of the +//! argument list and have the syntax: +//! +//! ```text +//! identifier '=' expression +//! ``` +//! +//! For example, the following [`format!`] expressions all use named arguments: +//! +//! ``` +//! # #![allow(unused_must_use)] +//! format!("{argument}", argument = "test"); // => "test" +//! format!("{name} {}", 1, name = 2); // => "2 1" +//! format!("{a} {c} {b}", a="a", b='b', c=3); // => "a 3 b" +//! ``` +//! +//! If a named parameter does not appear in the argument list, `format!` will +//! reference a variable with that name in the current scope. +//! +//! ``` +//! # #![allow(unused_must_use)] +//! let argument = 2 + 2; +//! format!("{argument}"); // => "4" +//! +//! fn make_string(a: u32, b: &str) -> String { +//! format!("{b} {a}") +//! } +//! make_string(927, "label"); // => "label 927" +//! ``` +//! +//! It is not valid to put positional parameters (those without names) after +//! arguments that have names. Like with positional parameters, it is not +//! valid to provide named parameters that are unused by the format string. +//! +//! # Formatting Parameters +//! +//! Each argument being formatted can be transformed by a number of formatting +//! parameters (corresponding to `format_spec` in [the syntax](#syntax)). These +//! parameters affect the string representation of what's being formatted. +//! +//! The colon `:` in format syntax divides indentifier of the input data and +//! the formatting options, the colon itself does not change anything, only +//! introduces the options. +//! +//! ``` +//! let a = 5; +//! let b = &a; +//! println!("{a:e} {b:p}"); // => 5e0 0x7ffe37b7273c +//! ``` +//! +//! ## Width +//! +//! ``` +//! // All of these print "Hello x !" +//! println!("Hello {:5}!", "x"); +//! println!("Hello {:1$}!", "x", 5); +//! println!("Hello {1:0$}!", 5, "x"); +//! println!("Hello {:width$}!", "x", width = 5); +//! let width = 5; +//! println!("Hello {:width$}!", "x"); +//! ``` +//! +//! This is a parameter for the "minimum width" that the format should take up. +//! If the value's string does not fill up this many characters, then the +//! padding specified by fill/alignment will be used to take up the required +//! space (see below). +//! +//! The value for the width can also be provided as a [`usize`] in the list of +//! parameters by adding a postfix `$`, indicating that the second argument is +//! a [`usize`] specifying the width. +//! +//! Referring to an argument with the dollar syntax does not affect the "next +//! argument" counter, so it's usually a good idea to refer to arguments by +//! position, or use named arguments. +//! +//! ## Fill/Alignment +//! +//! ``` +//! assert_eq!(format!("Hello {:<5}!", "x"), "Hello x !"); +//! assert_eq!(format!("Hello {:-<5}!", "x"), "Hello x----!"); +//! assert_eq!(format!("Hello {:^5}!", "x"), "Hello x !"); +//! assert_eq!(format!("Hello {:>5}!", "x"), "Hello x!"); +//! ``` +//! +//! The optional fill character and alignment is provided normally in conjunction with the +//! [`width`](#width) parameter. It must be defined before `width`, right after the `:`. +//! This indicates that if the value being formatted is smaller than +//! `width` some extra characters will be printed around it. +//! Filling comes in the following variants for different alignments: +//! +//! * `[fill]<` - the argument is left-aligned in `width` columns +//! * `[fill]^` - the argument is center-aligned in `width` columns +//! * `[fill]>` - the argument is right-aligned in `width` columns +//! +//! The default [fill/alignment](#fillalignment) for non-numerics is a space and +//! left-aligned. The +//! default for numeric formatters is also a space character but with right-alignment. If +//! the `0` flag (see below) is specified for numerics, then the implicit fill character is +//! `0`. +//! +//! Note that alignment might not be implemented by some types. In particular, it +//! is not generally implemented for the `Debug` trait. A good way to ensure +//! padding is applied is to format your input, then pad this resulting string +//! to obtain your output: +//! +//! ``` +//! println!("Hello {:^15}!", format!("{:?}", Some("hi"))); // => "Hello Some("hi") !" +//! ``` +//! +//! ## Sign/`#`/`0` +//! +//! ``` +//! assert_eq!(format!("Hello {:+}!", 5), "Hello +5!"); +//! assert_eq!(format!("{:#x}!", 27), "0x1b!"); +//! assert_eq!(format!("Hello {:05}!", 5), "Hello 00005!"); +//! assert_eq!(format!("Hello {:05}!", -5), "Hello -0005!"); +//! assert_eq!(format!("{:#010x}!", 27), "0x0000001b!"); +//! ``` +//! +//! These are all flags altering the behavior of the formatter. +//! +//! * `+` - This is intended for numeric types and indicates that the sign +//! should always be printed. By default only the negative sign of signed values +//! is printed, and the sign of positive or unsigned values is omitted. +//! This flag indicates that the correct sign (`+` or `-`) should always be printed. +//! * `-` - Currently not used +//! * `#` - This flag indicates that the "alternate" form of printing should +//! be used. The alternate forms are: +//! * `#?` - pretty-print the [`Debug`] formatting (adds linebreaks and indentation) +//! * `#x` - precedes the argument with a `0x` +//! * `#X` - precedes the argument with a `0x` +//! * `#b` - precedes the argument with a `0b` +//! * `#o` - precedes the argument with a `0o` +//! +//! See [Formatting traits](#formatting-traits) for a description of what the `?`, `x`, `X`, +//! `b`, and `o` flags do. +//! +//! * `0` - This is used to indicate for integer formats that the padding to `width` should +//! both be done with a `0` character as well as be sign-aware. A format +//! like `{:08}` would yield `00000001` for the integer `1`, while the +//! same format would yield `-0000001` for the integer `-1`. Notice that +//! the negative version has one fewer zero than the positive version. +//! Note that padding zeros are always placed after the sign (if any) +//! and before the digits. When used together with the `#` flag, a similar +//! rule applies: padding zeros are inserted after the prefix but before +//! the digits. The prefix is included in the total width. +//! This flag overrides the [fill character and alignment flag](#fillalignment). +//! +//! ## Precision +//! +//! For non-numeric types, this can be considered a "maximum width". If the resulting string is +//! longer than this width, then it is truncated down to this many characters and that truncated +//! value is emitted with proper `fill`, `alignment` and `width` if those parameters are set. +//! +//! For integral types, this is ignored. +//! +//! For floating-point types, this indicates how many digits after the decimal point should be +//! printed. +//! +//! There are three possible ways to specify the desired `precision`: +//! +//! 1. An integer `.N`: +//! +//! the integer `N` itself is the precision. +//! +//! 2. An integer or name followed by dollar sign `.N$`: +//! +//! use format *argument* `N` (which must be a `usize`) as the precision. +//! +//! 3. An asterisk `.*`: +//! +//! `.*` means that this `{...}` is associated with *two* format inputs rather than one: +//! - If a format string in the fashion of `{:.*}` is used, then the first input holds +//! the `usize` precision, and the second holds the value to print. +//! - If a format string in the fashion of `{:.*}` is used, then the `` part +//! refers to the value to print, and the `precision` is taken like it was specified with an +//! omitted positional parameter (`{}` instead of `{:}`). +//! +//! For example, the following calls all print the same thing `Hello x is 0.01000`: +//! +//! ``` +//! // Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)} +//! println!("Hello {0} is {1:.5}", "x", 0.01); +//! +//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)} +//! println!("Hello {1} is {2:.0$}", 5, "x", 0.01); +//! +//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)} +//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01); +//! +//! // Hello {next arg -> arg 0 ("x")} is {second of next two args -> arg 2 (0.01) with precision +//! // specified in first of next two args -> arg 1 (5)} +//! println!("Hello {} is {:.*}", "x", 5, 0.01); +//! +//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision +//! // specified in next arg -> arg 0 (5)} +//! println!("Hello {1} is {2:.*}", 5, "x", 0.01); +//! +//! // Hello {next arg -> arg 0 ("x")} is {arg 2 (0.01) with precision +//! // specified in next arg -> arg 1 (5)} +//! println!("Hello {} is {2:.*}", "x", 5, 0.01); +//! +//! // Hello {next arg -> arg 0 ("x")} is {arg "number" (0.01) with precision specified +//! // in arg "prec" (5)} +//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01); +//! ``` +//! +//! While these: +//! +//! ``` +//! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56); +//! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56"); +//! println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56"); +//! ``` +//! +//! print three significantly different things: +//! +//! ```text +//! Hello, `1234.560` has 3 fractional digits +//! Hello, `123` has 3 characters +//! Hello, ` 123` has 3 right-aligned characters +//! ``` +//! +//! When truncating these values, Rust uses [round half-to-even](https://en.wikipedia.org/wiki/Rounding#Rounding_half_to_even), +//! which is the default rounding mode in IEEE 754. +//! For example, +//! +//! ``` +//! print!("{0:.1$e}", 12345, 3); +//! print!("{0:.1$e}", 12355, 3); +//! ``` +//! +//! Would return: +//! +//! ```text +//! 1.234e4 +//! 1.236e4 +//! ``` +//! +//! ## Localization +//! +//! In some programming languages, the behavior of string formatting functions +//! depends on the operating system's locale setting. The format functions +//! provided by Rust's standard library do not have any concept of locale and +//! will produce the same results on all systems regardless of user +//! configuration. +//! +//! For example, the following code will always print `1.5` even if the system +//! locale uses a decimal separator other than a dot. +//! +//! ``` +//! println!("The value is {}", 1.5); +//! ``` +//! +//! # Escaping +//! +//! The literal characters `{` and `}` may be included in a string by preceding +//! them with the same character. For example, the `{` character is escaped with +//! `{{` and the `}` character is escaped with `}}`. +//! +//! ``` +//! assert_eq!(format!("Hello {{}}"), "Hello {}"); +//! assert_eq!(format!("{{ Hello"), "{ Hello"); +//! ``` +//! +//! # Syntax +//! +//! To summarize, here you can find the full grammar of format strings. +//! The syntax for the formatting language used is drawn from other languages, +//! so it should not be too alien. Arguments are formatted with Python-like +//! syntax, meaning that arguments are surrounded by `{}` instead of the C-like +//! `%`. The actual grammar for the formatting syntax is: +//! +//! ```text +//! format_string := text [ maybe_format text ] * +//! maybe_format := '{' '{' | '}' '}' | format +//! format := '{' [ argument ] [ ':' format_spec ] [ ws ] * '}' +//! argument := integer | identifier +//! +//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision]type +//! fill := character +//! align := '<' | '^' | '>' +//! sign := '+' | '-' +//! width := count +//! precision := count | '*' +//! type := '' | '?' | 'x?' | 'X?' | identifier +//! count := parameter | integer +//! parameter := argument '$' +//! ``` +//! In the above grammar, +//! - `text` must not contain any `'{'` or `'}'` characters, +//! - `ws` is any character for which [`char::is_whitespace`] returns `true`, has no semantic +//! meaning and is completely optional, +//! - `integer` is a decimal integer that may contain leading zeroes and must fit into an `usize` and +//! - `identifier` is an `IDENTIFIER_OR_KEYWORD` (not an `IDENTIFIER`) as defined by the [Rust language reference](https://doc.rust-lang.org/reference/identifiers.html). +//! +//! # Formatting traits +//! +//! When requesting that an argument be formatted with a particular type, you +//! are actually requesting that an argument ascribes to a particular trait. +//! This allows multiple actual types to be formatted via `{:x}` (like [`i8`] as +//! well as [`isize`]). The current mapping of types to traits is: +//! +//! * *nothing* ⇒ [`Display`] +//! * `?` ⇒ [`Debug`] +//! * `x?` ⇒ [`Debug`] with lower-case hexadecimal integers +//! * `X?` ⇒ [`Debug`] with upper-case hexadecimal integers +//! * `o` ⇒ [`Octal`] +//! * `x` ⇒ [`LowerHex`] +//! * `X` ⇒ [`UpperHex`] +//! * `p` ⇒ [`Pointer`] +//! * `b` ⇒ [`Binary`] +//! * `e` ⇒ [`LowerExp`] +//! * `E` ⇒ [`UpperExp`] +//! +//! What this means is that any type of argument which implements the +//! [`fmt::Binary`][`Binary`] trait can then be formatted with `{:b}`. Implementations +//! are provided for these traits for a number of primitive types by the +//! standard library as well. If no format is specified (as in `{}` or `{:6}`), +//! then the format trait used is the [`Display`] trait. +//! +//! When implementing a format trait for your own type, you will have to +//! implement a method of the signature: +//! +//! ``` +//! # #![allow(dead_code)] +//! # use std::fmt; +//! # struct Foo; // our custom type +//! # impl fmt::Display for Foo { +//! fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +//! # write!(f, "testing, testing") +//! # } } +//! ``` +//! +//! Your type will be passed as `self` by-reference, and then the function +//! should emit output into the Formatter `f` which implements `fmt::Write`. It is up to each +//! format trait implementation to correctly adhere to the requested formatting parameters. +//! The values of these parameters can be accessed with methods of the +//! [`Formatter`] struct. In order to help with this, the [`Formatter`] struct also +//! provides some helper methods. +//! +//! Additionally, the return value of this function is [`fmt::Result`] which is a +//! type alias of [Result]<(), [std::fmt::Error]>. Formatting implementations +//! should ensure that they propagate errors from the [`Formatter`] (e.g., when +//! calling [`write!`]). However, they should never return errors spuriously. That +//! is, a formatting implementation must and may only return an error if the +//! passed-in [`Formatter`] returns an error. This is because, contrary to what +//! the function signature might suggest, string formatting is an infallible +//! operation. This function only returns a [`Result`] because writing to the +//! underlying stream might fail and it must provide a way to propagate the fact +//! that an error has occurred back up the stack. +//! +//! An example of implementing the formatting traits would look +//! like: +//! +//! ``` +//! use std::fmt; +//! +//! #[derive(Debug)] +//! struct Vector2D { +//! x: isize, +//! y: isize, +//! } +//! +//! impl fmt::Display for Vector2D { +//! fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +//! // The `f` value implements the `Write` trait, which is what the +//! // write! macro is expecting. Note that this formatting ignores the +//! // various flags provided to format strings. +//! write!(f, "({}, {})", self.x, self.y) +//! } +//! } +//! +//! // Different traits allow different forms of output of a type. The meaning +//! // of this format is to print the magnitude of a vector. +//! impl fmt::Binary for Vector2D { +//! fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +//! let magnitude = (self.x * self.x + self.y * self.y) as f64; +//! let magnitude = magnitude.sqrt(); +//! +//! // Respect the formatting flags by using the helper method +//! // `pad_integral` on the Formatter object. See the method +//! // documentation for details, and the function `pad` can be used +//! // to pad strings. +//! let decimals = f.precision().unwrap_or(3); +//! let string = format!("{magnitude:.decimals$}"); +//! f.pad_integral(true, "", &string) +//! } +//! } +//! +//! fn main() { +//! let myvector = Vector2D { x: 3, y: 4 }; +//! +//! println!("{myvector}"); // => "(3, 4)" +//! println!("{myvector:?}"); // => "Vector2D {x: 3, y:4}" +//! println!("{myvector:10.3b}"); // => " 5.000" +//! } +//! ``` +//! +//! ### `fmt::Display` vs `fmt::Debug` +//! +//! These two formatting traits have distinct purposes: +//! +//! - [`fmt::Display`][`Display`] implementations assert that the type can be faithfully +//! represented as a UTF-8 string at all times. It is **not** expected that +//! all types implement the [`Display`] trait. +//! - [`fmt::Debug`][`Debug`] implementations should be implemented for **all** public types. +//! Output will typically represent the internal state as faithfully as possible. +//! The purpose of the [`Debug`] trait is to facilitate debugging Rust code. In +//! most cases, using `#[derive(Debug)]` is sufficient and recommended. +//! +//! Some examples of the output from both traits: +//! +//! ``` +//! assert_eq!(format!("{} {:?}", 3, 4), "3 4"); +//! assert_eq!(format!("{} {:?}", 'a', 'b'), "a 'b'"); +//! assert_eq!(format!("{} {:?}", "foo\n", "bar\n"), "foo\n \"bar\\n\""); +//! ``` +//! +//! # Related macros +//! +//! There are a number of related macros in the [`format!`] family. The ones that +//! are currently implemented are: +//! +//! ```ignore (only-for-syntax-highlight) +//! format! // described above +//! write! // first argument is either a &mut io::Write or a &mut fmt::Write, the destination +//! writeln! // same as write but appends a newline +//! print! // the format string is printed to the standard output +//! println! // same as print but appends a newline +//! eprint! // the format string is printed to the standard error +//! eprintln! // same as eprint but appends a newline +//! format_args! // described below. +//! ``` +//! +//! ### `write!` +//! +//! [`write!`] and [`writeln!`] are two macros which are used to emit the format string +//! to a specified stream. This is used to prevent intermediate allocations of +//! format strings and instead directly write the output. Under the hood, this +//! function is actually invoking the [`write_fmt`] function defined on the +//! [`std::io::Write`] and the [`std::fmt::Write`] trait. Example usage is: +//! +//! ``` +//! # #![allow(unused_must_use)] +//! use std::io::Write; +//! let mut w = Vec::new(); +//! write!(&mut w, "Hello {}!", "world"); +//! ``` +//! +//! ### `print!` +//! +//! This and [`println!`] emit their output to stdout. Similarly to the [`write!`] +//! macro, the goal of these macros is to avoid intermediate allocations when +//! printing output. Example usage is: +//! +//! ``` +//! print!("Hello {}!", "world"); +//! println!("I have a newline {}", "character at the end"); +//! ``` +//! ### `eprint!` +//! +//! The [`eprint!`] and [`eprintln!`] macros are identical to +//! [`print!`] and [`println!`], respectively, except they emit their +//! output to stderr. +//! +//! ### `format_args!` +//! +//! [`format_args!`] is a curious macro used to safely pass around +//! an opaque object describing the format string. This object +//! does not require any heap allocations to create, and it only +//! references information on the stack. Under the hood, all of +//! the related macros are implemented in terms of this. First +//! off, some example usage is: +//! +//! ``` +//! # #![allow(unused_must_use)] +//! use std::fmt; +//! use std::io::{self, Write}; +//! +//! let mut some_writer = io::stdout(); +//! write!(&mut some_writer, "{}", format_args!("print with a {}", "macro")); +//! +//! fn my_fmt_fn(args: fmt::Arguments<'_>) { +//! write!(&mut io::stdout(), "{args}"); +//! } +//! my_fmt_fn(format_args!(", or a {} too", "function")); +//! ``` +//! +//! The result of the [`format_args!`] macro is a value of type [`fmt::Arguments`]. +//! This structure can then be passed to the [`write`] and [`format`] functions +//! inside this module in order to process the format string. +//! The goal of this macro is to even further prevent intermediate allocations +//! when dealing with formatting strings. +//! +//! For example, a logging library could use the standard formatting syntax, but +//! it would internally pass around this structure until it has been determined +//! where output should go to. +//! +//! [`fmt::Result`]: Result "fmt::Result" +//! [Result]: core::result::Result "std::result::Result" +//! [std::fmt::Error]: Error "fmt::Error" +//! [`write`]: write() "fmt::write" +//! [`to_string`]: crate::string::ToString::to_string "ToString::to_string" +//! [`write_fmt`]: ../../std/io/trait.Write.html#method.write_fmt +//! [`std::io::Write`]: ../../std/io/trait.Write.html +//! [`std::fmt::Write`]: ../../std/fmt/trait.Write.html +//! [`print!`]: ../../std/macro.print.html "print!" +//! [`println!`]: ../../std/macro.println.html "println!" +//! [`eprint!`]: ../../std/macro.eprint.html "eprint!" +//! [`eprintln!`]: ../../std/macro.eprintln.html "eprintln!" +//! [`format_args!`]: ../../std/macro.format_args.html "format_args!" +//! [`fmt::Arguments`]: Arguments "fmt::Arguments" +//! [`format`]: format() "fmt::format" + +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "fmt_flags_align", since = "1.28.0")] +pub use core::fmt::Alignment; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::Error; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{Arguments, write}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{Binary, Octal}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{Debug, Display}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{Formatter, Result, Write}; +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +pub use core::fmt::{FromFn, from_fn}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{LowerExp, UpperExp}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{LowerHex, Pointer, UpperHex}; + +#[cfg(not(no_global_oom_handling))] +use crate::string; + +/// Takes an [`Arguments`] struct and returns the resulting formatted string. +/// +/// The [`Arguments`] instance can be created with the [`format_args!`] macro. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::fmt; +/// +/// let s = fmt::format(format_args!("Hello, {}!", "world")); +/// assert_eq!(s, "Hello, world!"); +/// ``` +/// +/// Please note that using [`format!`] might be preferable. +/// Example: +/// +/// ``` +/// let s = format!("Hello, {}!", "world"); +/// assert_eq!(s, "Hello, world!"); +/// ``` +/// +/// [`format_args!`]: core::format_args +/// [`format!`]: crate::format +#[cfg(not(no_global_oom_handling))] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[inline] +pub fn format(args: Arguments<'_>) -> string::String { + fn format_inner(args: Arguments<'_>) -> string::String { + let capacity = args.estimated_capacity(); + let mut output = string::String::with_capacity(capacity); + output + .write_fmt(args) + .expect("a formatting trait implementation returned an error when the underlying stream did not"); + output + } + + args.as_str().map_or_else(|| format_inner(args), crate::borrow::ToOwned::to_owned) +} diff --git a/CoqOfRust/alloc/lib.miri.rs b/CoqOfRust/alloc/lib.miri.rs new file mode 100644 index 000000000..89d7f49f5 --- /dev/null +++ b/CoqOfRust/alloc/lib.miri.rs @@ -0,0 +1,4 @@ +//! Grep bootstrap for `MIRI_REPLACE_LIBRS_IF_NOT_TEST` to learn what this is about. +#![no_std] +extern crate alloc as realalloc; +pub use realalloc::*; diff --git a/CoqOfRust/alloc/lib.rs b/CoqOfRust/alloc/lib.rs new file mode 100644 index 000000000..84f4202c0 --- /dev/null +++ b/CoqOfRust/alloc/lib.rs @@ -0,0 +1,267 @@ +//! # The Rust core allocation and collections library +//! +//! This library provides smart pointers and collections for managing +//! heap-allocated values. +//! +//! This library, like core, normally doesn’t need to be used directly +//! since its contents are re-exported in the [`std` crate](../std/index.html). +//! Crates that use the `#![no_std]` attribute however will typically +//! not depend on `std`, so they’d use this crate instead. +//! +//! ## Boxed values +//! +//! The [`Box`] type is a smart pointer type. There can only be one owner of a +//! [`Box`], and the owner can decide to mutate the contents, which live on the +//! heap. +//! +//! This type can be sent among threads efficiently as the size of a `Box` value +//! is the same as that of a pointer. Tree-like data structures are often built +//! with boxes because each node often has only one owner, the parent. +//! +//! ## Reference counted pointers +//! +//! The [`Rc`] type is a non-threadsafe reference-counted pointer type intended +//! for sharing memory within a thread. An [`Rc`] pointer wraps a type, `T`, and +//! only allows access to `&T`, a shared reference. +//! +//! This type is useful when inherited mutability (such as using [`Box`]) is too +//! constraining for an application, and is often paired with the [`Cell`] or +//! [`RefCell`] types in order to allow mutation. +//! +//! ## Atomically reference counted pointers +//! +//! The [`Arc`] type is the threadsafe equivalent of the [`Rc`] type. It +//! provides all the same functionality of [`Rc`], except it requires that the +//! contained type `T` is shareable. Additionally, [`Arc`][`Arc`] is itself +//! sendable while [`Rc`][`Rc`] is not. +//! +//! This type allows for shared access to the contained data, and is often +//! paired with synchronization primitives such as mutexes to allow mutation of +//! shared resources. +//! +//! ## Collections +//! +//! Implementations of the most common general purpose data structures are +//! defined in this library. They are re-exported through the +//! [standard collections library](../std/collections/index.html). +//! +//! ## Heap interfaces +//! +//! The [`alloc`](alloc/index.html) module defines the low-level interface to the +//! default global allocator. It is not compatible with the libc allocator API. +//! +//! [`Arc`]: sync +//! [`Box`]: boxed +//! [`Cell`]: core::cell +//! [`Rc`]: rc +//! [`RefCell`]: core::cell + +#![allow(unused_attributes)] +#![stable(feature = "alloc", since = "1.36.0")] +#![doc( + html_playground_url = "https://play.rust-lang.org/", + issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", + test(no_crate_inject, attr(allow(unused_variables), deny(warnings))) +)] +#![doc(cfg_hide( + not(test), + not(any(test, bootstrap)), + no_global_oom_handling, + not(no_global_oom_handling), + not(no_rc), + not(no_sync), + target_has_atomic = "ptr" +))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] +#![no_std] +#![needs_allocator] +// Lints: +#![deny(unsafe_op_in_unsafe_fn)] +#![deny(fuzzy_provenance_casts)] +#![warn(deprecated_in_future)] +#![warn(missing_debug_implementations)] +#![warn(missing_docs)] +#![allow(explicit_outlives_requirements)] +#![warn(multiple_supertrait_upcastable)] +#![allow(internal_features)] +#![allow(rustdoc::redundant_explicit_links)] +#![warn(rustdoc::unescaped_backticks)] +#![deny(ffi_unwind_calls)] +// +// Library features: +// tidy-alphabetical-start +#![cfg_attr(test, feature(str_as_str))] +#![feature(alloc_layout_extra)] +#![feature(allocator_api)] +#![feature(array_chunks)] +#![feature(array_into_iter_constructors)] +#![feature(array_windows)] +#![feature(ascii_char)] +#![feature(assert_matches)] +#![feature(async_closure)] +#![feature(async_fn_traits)] +#![feature(async_iterator)] +#![feature(box_uninit_write)] +#![feature(clone_to_uninit)] +#![feature(coerce_unsized)] +#![feature(const_eval_select)] +#![feature(const_heap)] +#![feature(core_intrinsics)] +#![feature(deprecated_suggestion)] +#![feature(deref_pure_trait)] +#![feature(dispatch_from_dyn)] +#![feature(error_generic_member_access)] +#![feature(exact_size_is_empty)] +#![feature(extend_one)] +#![feature(extend_one_unchecked)] +#![feature(fmt_internals)] +#![feature(fn_traits)] +#![feature(hasher_prefixfree_extras)] +#![feature(inplace_iteration)] +#![feature(iter_advance_by)] +#![feature(iter_next_chunk)] +#![feature(layout_for_ptr)] +#![feature(legacy_receiver_trait)] +#![feature(local_waker)] +#![feature(maybe_uninit_slice)] +#![feature(maybe_uninit_uninit_array_transpose)] +#![feature(panic_internals)] +#![feature(pattern)] +#![feature(pin_coerce_unsized_trait)] +#![feature(pointer_like_trait)] +#![feature(ptr_internals)] +#![feature(ptr_metadata)] +#![feature(ptr_sub_ptr)] +#![feature(set_ptr_value)] +#![feature(sized_type_properties)] +#![feature(slice_from_ptr_range)] +#![feature(slice_index_methods)] +#![feature(slice_iter_mut_as_mut_slice)] +#![feature(slice_ptr_get)] +#![feature(slice_range)] +#![feature(std_internals)] +#![feature(str_internals)] +#![feature(trusted_fused)] +#![feature(trusted_len)] +#![feature(trusted_random_access)] +#![feature(try_trait_v2)] +#![feature(try_with_capacity)] +#![feature(tuple_trait)] +#![feature(unicode_internals)] +#![feature(unsize)] +#![feature(unwrap_infallible)] +#![feature(vec_pop_if)] +// tidy-alphabetical-end +// +// Language features: +// tidy-alphabetical-start +#![cfg_attr(not(test), feature(coroutine_trait))] +#![cfg_attr(test, feature(panic_update_hook))] +#![cfg_attr(test, feature(test))] +#![feature(allocator_internals)] +#![feature(allow_internal_unstable)] +#![feature(cfg_sanitize)] +#![feature(const_precise_live_drops)] +#![feature(decl_macro)] +#![feature(dropck_eyepatch)] +#![feature(fundamental)] +#![feature(hashmap_internals)] +#![feature(lang_items)] +#![feature(min_specialization)] +#![feature(multiple_supertrait_upcastable)] +#![feature(negative_impls)] +#![feature(never_type)] +#![feature(optimize_attribute)] +#![feature(rustc_allow_const_fn_unstable)] +#![feature(rustc_attrs)] +#![feature(slice_internals)] +#![feature(staged_api)] +#![feature(stmt_expr_attributes)] +#![feature(strict_provenance_lints)] +#![feature(unboxed_closures)] +#![feature(unsized_fn_params)] +#![feature(with_negative_coherence)] +#![rustc_preserve_ub_checks] +// tidy-alphabetical-end +// +// Rustdoc features: +#![feature(doc_cfg)] +#![feature(doc_cfg_hide)] +// Technically, this is a bug in rustdoc: rustdoc sees the documentation on `#[lang = slice_alloc]` +// blocks is for `&[T]`, which also has documentation using this feature in `core`, and gets mad +// that the feature-gate isn't enabled. Ideally, it wouldn't check for the feature gate for docs +// from other crates, but since this can only appear for lang items, it doesn't seem worth fixing. +#![feature(intra_doc_pointers)] + +// Allow testing this library +#[cfg(test)] +#[macro_use] +extern crate std; +#[cfg(test)] +extern crate test; +#[cfg(test)] +mod testing; + +// Module with internal macros used by other modules (needs to be included before other modules). +#[macro_use] +mod macros; + +mod raw_vec; + +// Heaps provided for low-level allocation strategies + +pub mod alloc; + +// Primitive types using the heaps above + +// Need to conditionally define the mod from `boxed.rs` to avoid +// duplicating the lang-items when building in test cfg; but also need +// to allow code to have `use boxed::Box;` declarations. +#[cfg(not(test))] +pub mod boxed; +#[cfg(test)] +mod boxed { + pub use std::boxed::Box; +} +pub mod borrow; +pub mod collections; +#[cfg(all(not(no_rc), not(no_sync), not(no_global_oom_handling)))] +pub mod ffi; +pub mod fmt; +#[cfg(not(no_rc))] +pub mod rc; +pub mod slice; +pub mod str; +pub mod string; +#[cfg(all(not(no_rc), not(no_sync), target_has_atomic = "ptr"))] +pub mod sync; +#[cfg(all(not(no_global_oom_handling), not(no_rc), not(no_sync)))] +pub mod task; +#[cfg(test)] +mod tests; +pub mod vec; + +#[doc(hidden)] +#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")] +pub mod __export { + pub use core::format_args; + pub use core::hint::must_use; +} + +#[cfg(test)] +#[allow(dead_code)] // Not used in all configurations +pub(crate) mod test_helpers { + /// Copied from `std::test_helpers::test_rng`, since these tests rely on the + /// seed not being the same for every RNG invocation too. + pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { + use std::hash::{BuildHasher, Hash, Hasher}; + let mut hasher = std::hash::RandomState::new().build_hasher(); + std::panic::Location::caller().hash(&mut hasher); + let hc64 = hasher.finish(); + let seed_vec = + hc64.to_le_bytes().into_iter().chain(0u8..8).collect::>(); + let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap(); + rand::SeedableRng::from_seed(seed) + } +} diff --git a/CoqOfRust/alloc/macros.rs b/CoqOfRust/alloc/macros.rs new file mode 100644 index 000000000..8c6a36786 --- /dev/null +++ b/CoqOfRust/alloc/macros.rs @@ -0,0 +1,132 @@ +/// Creates a [`Vec`] containing the arguments. +/// +/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions. +/// There are two forms of this macro: +/// +/// - Create a [`Vec`] containing a given list of elements: +/// +/// ``` +/// let v = vec![1, 2, 3]; +/// assert_eq!(v[0], 1); +/// assert_eq!(v[1], 2); +/// assert_eq!(v[2], 3); +/// ``` +/// +/// - Create a [`Vec`] from a given element and size: +/// +/// ``` +/// let v = vec![1; 3]; +/// assert_eq!(v, [1, 1, 1]); +/// ``` +/// +/// Note that unlike array expressions this syntax supports all elements +/// which implement [`Clone`] and the number of elements doesn't have to be +/// a constant. +/// +/// This will use `clone` to duplicate an expression, so one should be careful +/// using this with types having a nonstandard `Clone` implementation. For +/// example, `vec![Rc::new(1); 5]` will create a vector of five references +/// to the same boxed integer value, not five references pointing to independently +/// boxed integers. +/// +/// Also, note that `vec![expr; 0]` is allowed, and produces an empty vector. +/// This will still evaluate `expr`, however, and immediately drop the resulting value, so +/// be mindful of side effects. +/// +/// [`Vec`]: crate::vec::Vec +#[cfg(all(not(no_global_oom_handling), not(test)))] +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "vec_macro"] +#[allow_internal_unstable(rustc_attrs, liballoc_internals)] +macro_rules! vec { + () => ( + $crate::vec::Vec::new() + ); + ($elem:expr; $n:expr) => ( + $crate::vec::from_elem($elem, $n) + ); + ($($x:expr),+ $(,)?) => ( + <[_]>::into_vec( + // This rustc_box is not required, but it produces a dramatic improvement in compile + // time when constructing arrays with many elements. + #[rustc_box] + $crate::boxed::Box::new([$($x),+]) + ) + ); +} + +// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is +// required for this macro definition, is not available. Instead use the +// `slice::into_vec` function which is only available with cfg(test) +// NB see the slice::hack module in slice.rs for more information +#[cfg(all(not(no_global_oom_handling), test))] +#[allow(unused_macro_rules)] +macro_rules! vec { + () => ( + $crate::vec::Vec::new() + ); + ($elem:expr; $n:expr) => ( + $crate::vec::from_elem($elem, $n) + ); + ($($x:expr),*) => ( + $crate::slice::into_vec($crate::boxed::Box::new([$($x),*])) + ); + ($($x:expr,)*) => (vec![$($x),*]) +} + +/// Creates a `String` using interpolation of runtime expressions. +/// +/// The first argument `format!` receives is a format string. This must be a string +/// literal. The power of the formatting string is in the `{}`s contained. +/// Additional parameters passed to `format!` replace the `{}`s within the +/// formatting string in the order given unless named or positional parameters +/// are used. +/// +/// See [the formatting syntax documentation in `std::fmt`](../std/fmt/index.html) +/// for details. +/// +/// A common use for `format!` is concatenation and interpolation of strings. +/// The same convention is used with [`print!`] and [`write!`] macros, +/// depending on the intended destination of the string; all these macros internally use [`format_args!`]. +/// +/// To convert a single value to a string, use the [`to_string`] method. This +/// will use the [`Display`] formatting trait. +/// +/// To concatenate literals into a `&'static str`, use the [`concat!`] macro. +/// +/// [`print!`]: ../std/macro.print.html +/// [`write!`]: core::write +/// [`format_args!`]: core::format_args +/// [`to_string`]: crate::string::ToString +/// [`Display`]: core::fmt::Display +/// [`concat!`]: core::concat +/// +/// # Panics +/// +/// `format!` panics if a formatting trait implementation returns an error. +/// This indicates an incorrect implementation +/// since `fmt::Write for String` never returns an error itself. +/// +/// # Examples +/// +/// ``` +/// # #![allow(unused_must_use)] +/// format!("test"); // => "test" +/// format!("hello {}", "world!"); // => "hello world!" +/// format!("x = {}, y = {val}", 10, val = 30); // => "x = 10, y = 30" +/// let (x, y) = (1, 2); +/// format!("{x} + {y} = 3"); // => "1 + 2 = 3" +/// ``` +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[allow_internal_unstable(hint_must_use, liballoc_internals)] +#[cfg_attr(not(test), rustc_diagnostic_item = "format_macro")] +macro_rules! format { + ($($arg:tt)*) => { + $crate::__export::must_use({ + let res = $crate::fmt::format($crate::__export::format_args!($($arg)*)); + res + }) + } +} diff --git a/CoqOfRust/alloc/raw_vec.rs b/CoqOfRust/alloc/raw_vec.rs new file mode 100644 index 000000000..2c7cdcf0c --- /dev/null +++ b/CoqOfRust/alloc/raw_vec.rs @@ -0,0 +1,816 @@ +#![unstable(feature = "raw_vec_internals", reason = "unstable const warnings", issue = "none")] + +use core::marker::PhantomData; +use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties}; +use core::ptr::{self, NonNull, Unique}; +use core::{cmp, hint}; + +#[cfg(not(no_global_oom_handling))] +use crate::alloc::handle_alloc_error; +use crate::alloc::{Allocator, Global, Layout}; +use crate::boxed::Box; +use crate::collections::TryReserveError; +use crate::collections::TryReserveErrorKind::*; + +#[cfg(test)] +mod tests; + +// One central function responsible for reporting capacity overflows. This'll +// ensure that the code generation related to these panics is minimal as there's +// only one location which panics rather than a bunch throughout the module. +#[cfg(not(no_global_oom_handling))] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[track_caller] +fn capacity_overflow() -> ! { + panic!("capacity overflow"); +} + +enum AllocInit { + /// The contents of the new memory are uninitialized. + Uninitialized, + #[cfg(not(no_global_oom_handling))] + /// The new memory is guaranteed to be zeroed. + Zeroed, +} + +#[repr(transparent)] +#[cfg_attr(target_pointer_width = "16", rustc_layout_scalar_valid_range_end(0x7fff))] +#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0x7fff_ffff))] +#[cfg_attr(target_pointer_width = "64", rustc_layout_scalar_valid_range_end(0x7fff_ffff_ffff_ffff))] +struct Cap(usize); + +impl Cap { + const ZERO: Cap = unsafe { Cap(0) }; + + /// `Cap(cap)`, except if `T` is a ZST then `Cap::ZERO`. + /// + /// # Safety: cap must be <= `isize::MAX`. + unsafe fn new(cap: usize) -> Self { + if T::IS_ZST { Cap::ZERO } else { unsafe { Self(cap) } } + } +} + +/// A low-level utility for more ergonomically allocating, reallocating, and deallocating +/// a buffer of memory on the heap without having to worry about all the corner cases +/// involved. This type is excellent for building your own data structures like Vec and VecDeque. +/// In particular: +/// +/// * Produces `Unique::dangling()` on zero-sized types. +/// * Produces `Unique::dangling()` on zero-length allocations. +/// * Avoids freeing `Unique::dangling()`. +/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics). +/// * Guards against 32-bit systems allocating more than `isize::MAX` bytes. +/// * Guards against overflowing your length. +/// * Calls `handle_alloc_error` for fallible allocations. +/// * Contains a `ptr::Unique` and thus endows the user with all related benefits. +/// * Uses the excess returned from the allocator to use the largest available capacity. +/// +/// This type does not in anyway inspect the memory that it manages. When dropped it *will* +/// free its memory, but it *won't* try to drop its contents. It is up to the user of `RawVec` +/// to handle the actual things *stored* inside of a `RawVec`. +/// +/// Note that the excess of a zero-sized types is always infinite, so `capacity()` always returns +/// `usize::MAX`. This means that you need to be careful when round-tripping this type with a +/// `Box<[T]>`, since `capacity()` won't yield the length. +#[allow(missing_debug_implementations)] +pub(crate) struct RawVec { + inner: RawVecInner, + _marker: PhantomData, +} + +/// Like a `RawVec`, but only generic over the allocator, not the type. +/// +/// As such, all the methods need the layout passed-in as a parameter. +/// +/// Having this separation reduces the amount of code we need to monomorphize, +/// as most operations don't need the actual type, just its layout. +#[allow(missing_debug_implementations)] +struct RawVecInner { + ptr: Unique, + /// Never used for ZSTs; it's `capacity()`'s responsibility to return usize::MAX in that case. + /// + /// # Safety + /// + /// `cap` must be in the `0..=isize::MAX` range. + cap: Cap, + alloc: A, +} + +impl RawVec { + /// Creates the biggest possible `RawVec` (on the system heap) + /// without allocating. If `T` has positive size, then this makes a + /// `RawVec` with capacity `0`. If `T` is zero-sized, then it makes a + /// `RawVec` with capacity `usize::MAX`. Useful for implementing + /// delayed allocation. + #[must_use] + pub const fn new() -> Self { + Self::new_in(Global) + } + + /// Creates a `RawVec` (on the system heap) with exactly the + /// capacity and alignment requirements for a `[T; capacity]`. This is + /// equivalent to calling `RawVec::new` when `capacity` is `0` or `T` is + /// zero-sized. Note that if `T` is zero-sized this means you will + /// *not* get a `RawVec` with the requested capacity. + /// + /// Non-fallible version of `try_with_capacity` + /// + /// # Panics + /// + /// Panics if the requested capacity exceeds `isize::MAX` bytes. + /// + /// # Aborts + /// + /// Aborts on OOM. + #[cfg(not(any(no_global_oom_handling, test)))] + #[must_use] + #[inline] + #[track_caller] + pub fn with_capacity(capacity: usize) -> Self { + Self { inner: RawVecInner::with_capacity(capacity, T::LAYOUT), _marker: PhantomData } + } + + /// Like `with_capacity`, but guarantees the buffer is zeroed. + #[cfg(not(any(no_global_oom_handling, test)))] + #[must_use] + #[inline] + #[track_caller] + pub fn with_capacity_zeroed(capacity: usize) -> Self { + Self { + inner: RawVecInner::with_capacity_zeroed_in(capacity, Global, T::LAYOUT), + _marker: PhantomData, + } + } +} + +impl RawVecInner { + #[cfg(not(any(no_global_oom_handling, test)))] + #[must_use] + #[inline] + #[track_caller] + fn with_capacity(capacity: usize, elem_layout: Layout) -> Self { + match Self::try_allocate_in(capacity, AllocInit::Uninitialized, Global, elem_layout) { + Ok(res) => res, + Err(err) => handle_error(err), + } + } +} + +// Tiny Vecs are dumb. Skip to: +// - 8 if the element size is 1, because any heap allocators is likely +// to round up a request of less than 8 bytes to at least 8 bytes. +// - 4 if elements are moderate-sized (<= 1 KiB). +// - 1 otherwise, to avoid wasting too much space for very short Vecs. +const fn min_non_zero_cap(size: usize) -> usize { + if size == 1 { + 8 + } else if size <= 1024 { + 4 + } else { + 1 + } +} + +impl RawVec { + #[cfg(not(no_global_oom_handling))] + pub(crate) const MIN_NON_ZERO_CAP: usize = min_non_zero_cap(size_of::()); + + /// Like `new`, but parameterized over the choice of allocator for + /// the returned `RawVec`. + #[inline] + pub const fn new_in(alloc: A) -> Self { + Self { inner: RawVecInner::new_in(alloc, align_of::()), _marker: PhantomData } + } + + /// Like `with_capacity`, but parameterized over the choice of + /// allocator for the returned `RawVec`. + #[cfg(not(no_global_oom_handling))] + #[inline] + #[track_caller] + pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { + Self { + inner: RawVecInner::with_capacity_in(capacity, alloc, T::LAYOUT), + _marker: PhantomData, + } + } + + /// Like `try_with_capacity`, but parameterized over the choice of + /// allocator for the returned `RawVec`. + #[inline] + pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result { + match RawVecInner::try_with_capacity_in(capacity, alloc, T::LAYOUT) { + Ok(inner) => Ok(Self { inner, _marker: PhantomData }), + Err(e) => Err(e), + } + } + + /// Like `with_capacity_zeroed`, but parameterized over the choice + /// of allocator for the returned `RawVec`. + #[cfg(not(no_global_oom_handling))] + #[inline] + #[track_caller] + pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self { + Self { + inner: RawVecInner::with_capacity_zeroed_in(capacity, alloc, T::LAYOUT), + _marker: PhantomData, + } + } + + /// Converts the entire buffer into `Box<[MaybeUninit]>` with the specified `len`. + /// + /// Note that this will correctly reconstitute any `cap` changes + /// that may have been performed. (See description of type for details.) + /// + /// # Safety + /// + /// * `len` must be greater than or equal to the most recently requested capacity, and + /// * `len` must be less than or equal to `self.capacity()`. + /// + /// Note, that the requested capacity and `self.capacity()` could differ, as + /// an allocator could overallocate and return a greater memory block than requested. + pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit], A> { + // Sanity-check one half of the safety requirement (we cannot check the other half). + debug_assert!( + len <= self.capacity(), + "`len` must be smaller than or equal to `self.capacity()`" + ); + + let me = ManuallyDrop::new(self); + unsafe { + let slice = ptr::slice_from_raw_parts_mut(me.ptr() as *mut MaybeUninit, len); + Box::from_raw_in(slice, ptr::read(&me.inner.alloc)) + } + } + + /// Reconstitutes a `RawVec` from a pointer, capacity, and allocator. + /// + /// # Safety + /// + /// The `ptr` must be allocated (via the given allocator `alloc`), and with the given + /// `capacity`. + /// The `capacity` cannot exceed `isize::MAX` for sized types. (only a concern on 32-bit + /// systems). For ZSTs capacity is ignored. + /// If the `ptr` and `capacity` come from a `RawVec` created via `alloc`, then this is + /// guaranteed. + #[inline] + pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, alloc: A) -> Self { + // SAFETY: Precondition passed to the caller + unsafe { + let ptr = ptr.cast(); + let capacity = Cap::new::(capacity); + Self { + inner: RawVecInner::from_raw_parts_in(ptr, capacity, alloc), + _marker: PhantomData, + } + } + } + + /// A convenience method for hoisting the non-null precondition out of [`RawVec::from_raw_parts_in`]. + /// + /// # Safety + /// + /// See [`RawVec::from_raw_parts_in`]. + #[inline] + pub unsafe fn from_nonnull_in(ptr: NonNull, capacity: usize, alloc: A) -> Self { + // SAFETY: Precondition passed to the caller + unsafe { + let ptr = ptr.cast(); + let capacity = Cap::new::(capacity); + Self { inner: RawVecInner::from_nonnull_in(ptr, capacity, alloc), _marker: PhantomData } + } + } + + /// Gets a raw pointer to the start of the allocation. Note that this is + /// `Unique::dangling()` if `capacity == 0` or `T` is zero-sized. In the former case, you must + /// be careful. + #[inline] + pub const fn ptr(&self) -> *mut T { + self.inner.ptr() + } + + #[inline] + pub fn non_null(&self) -> NonNull { + self.inner.non_null() + } + + /// Gets the capacity of the allocation. + /// + /// This will always be `usize::MAX` if `T` is zero-sized. + #[inline] + pub const fn capacity(&self) -> usize { + self.inner.capacity(size_of::()) + } + + /// Returns a shared reference to the allocator backing this `RawVec`. + #[inline] + pub fn allocator(&self) -> &A { + self.inner.allocator() + } + + /// Ensures that the buffer contains at least enough space to hold `len + + /// additional` elements. If it doesn't already have enough capacity, will + /// reallocate enough space plus comfortable slack space to get amortized + /// *O*(1) behavior. Will limit this behavior if it would needlessly cause + /// itself to panic. + /// + /// If `len` exceeds `self.capacity()`, this may fail to actually allocate + /// the requested space. This is not really unsafe, but the unsafe + /// code *you* write that relies on the behavior of this function may break. + /// + /// This is ideal for implementing a bulk-push operation like `extend`. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. + /// + /// # Aborts + /// + /// Aborts on OOM. + #[cfg(not(no_global_oom_handling))] + #[inline] + #[track_caller] + pub fn reserve(&mut self, len: usize, additional: usize) { + self.inner.reserve(len, additional, T::LAYOUT) + } + + /// A specialized version of `self.reserve(len, 1)` which requires the + /// caller to ensure `len == self.capacity()`. + #[cfg(not(no_global_oom_handling))] + #[inline(never)] + #[track_caller] + pub fn grow_one(&mut self) { + self.inner.grow_one(T::LAYOUT) + } + + /// The same as `reserve`, but returns on errors instead of panicking or aborting. + pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve(len, additional, T::LAYOUT) + } + + /// Ensures that the buffer contains at least enough space to hold `len + + /// additional` elements. If it doesn't already, will reallocate the + /// minimum possible amount of memory necessary. Generally this will be + /// exactly the amount of memory necessary, but in principle the allocator + /// is free to give back more than we asked for. + /// + /// If `len` exceeds `self.capacity()`, this may fail to actually allocate + /// the requested space. This is not really unsafe, but the unsafe code + /// *you* write that relies on the behavior of this function may break. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. + /// + /// # Aborts + /// + /// Aborts on OOM. + #[cfg(not(no_global_oom_handling))] + #[track_caller] + pub fn reserve_exact(&mut self, len: usize, additional: usize) { + self.inner.reserve_exact(len, additional, T::LAYOUT) + } + + /// The same as `reserve_exact`, but returns on errors instead of panicking or aborting. + pub fn try_reserve_exact( + &mut self, + len: usize, + additional: usize, + ) -> Result<(), TryReserveError> { + self.inner.try_reserve_exact(len, additional, T::LAYOUT) + } + + /// Shrinks the buffer down to the specified capacity. If the given amount + /// is 0, actually completely deallocates. + /// + /// # Panics + /// + /// Panics if the given amount is *larger* than the current capacity. + /// + /// # Aborts + /// + /// Aborts on OOM. + #[cfg(not(no_global_oom_handling))] + #[track_caller] + #[inline] + pub fn shrink_to_fit(&mut self, cap: usize) { + self.inner.shrink_to_fit(cap, T::LAYOUT) + } +} + +unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { + /// Frees the memory owned by the `RawVec` *without* trying to drop its contents. + fn drop(&mut self) { + // SAFETY: We are in a Drop impl, self.inner will not be used again. + unsafe { self.inner.deallocate(T::LAYOUT) } + } +} + +impl RawVecInner { + #[inline] + const fn new_in(alloc: A, align: usize) -> Self { + let ptr = unsafe { core::mem::transmute(align) }; + // `cap: 0` means "unallocated". zero-sized types are ignored. + Self { ptr, cap: Cap::ZERO, alloc } + } + + #[cfg(not(no_global_oom_handling))] + #[inline] + #[track_caller] + fn with_capacity_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self { + match Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout) { + Ok(this) => { + unsafe { + // Make it more obvious that a subsquent Vec::reserve(capacity) will not allocate. + hint::assert_unchecked(!this.needs_to_grow(0, capacity, elem_layout)); + } + this + } + Err(err) => handle_error(err), + } + } + + #[inline] + fn try_with_capacity_in( + capacity: usize, + alloc: A, + elem_layout: Layout, + ) -> Result { + Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout) + } + + #[cfg(not(no_global_oom_handling))] + #[inline] + #[track_caller] + fn with_capacity_zeroed_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self { + match Self::try_allocate_in(capacity, AllocInit::Zeroed, alloc, elem_layout) { + Ok(res) => res, + Err(err) => handle_error(err), + } + } + + fn try_allocate_in( + capacity: usize, + init: AllocInit, + alloc: A, + elem_layout: Layout, + ) -> Result { + // We avoid `unwrap_or_else` here because it bloats the amount of + // LLVM IR generated. + let layout = match layout_array(capacity, elem_layout) { + Ok(layout) => layout, + Err(_) => return Err(CapacityOverflow.into()), + }; + + // Don't allocate here because `Drop` will not deallocate when `capacity` is 0. + if layout.size() == 0 { + return Ok(Self::new_in(alloc, elem_layout.align())); + } + + if let Err(err) = alloc_guard(layout.size()) { + return Err(err); + } + + let result = match init { + AllocInit::Uninitialized => alloc.allocate(layout), + #[cfg(not(no_global_oom_handling))] + AllocInit::Zeroed => alloc.allocate_zeroed(layout), + }; + let ptr = match result { + Ok(ptr) => ptr, + Err(_) => return Err(AllocError { layout, non_exhaustive: () }.into()), + }; + + // Allocators currently return a `NonNull<[u8]>` whose length + // matches the size requested. If that ever changes, the capacity + // here should change to `ptr.len() / mem::size_of::()`. + Ok(Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc }) + } + + #[inline] + unsafe fn from_raw_parts_in(ptr: *mut u8, cap: Cap, alloc: A) -> Self { + Self { ptr: unsafe { Unique::new_unchecked(ptr) }, cap, alloc } + } + + #[inline] + unsafe fn from_nonnull_in(ptr: NonNull, cap: Cap, alloc: A) -> Self { + Self { ptr: Unique::from(ptr), cap, alloc } + } + + #[inline] + const fn ptr(&self) -> *mut T { + self.non_null::().as_ptr() + } + + #[inline] + const fn non_null(&self) -> NonNull { + self.ptr.cast().as_non_null_ptr() + } + + #[inline] + const fn capacity(&self, elem_size: usize) -> usize { + if elem_size == 0 { usize::MAX } else { self.cap.0 } + } + + #[inline] + fn allocator(&self) -> &A { + &self.alloc + } + + #[inline] + fn current_memory(&self, elem_layout: Layout) -> Option<(NonNull, Layout)> { + if elem_layout.size() == 0 || self.cap.0 == 0 { + None + } else { + // We could use Layout::array here which ensures the absence of isize and usize overflows + // and could hypothetically handle differences between stride and size, but this memory + // has already been allocated so we know it can't overflow and currently Rust does not + // support such types. So we can do better by skipping some checks and avoid an unwrap. + unsafe { + let alloc_size = elem_layout.size().unchecked_mul(self.cap.0); + let layout = Layout::from_size_align_unchecked(alloc_size, elem_layout.align()); + Some((self.ptr.into(), layout)) + } + } + } + + #[cfg(not(no_global_oom_handling))] + #[inline] + #[track_caller] + fn reserve(&mut self, len: usize, additional: usize, elem_layout: Layout) { + // Callers expect this function to be very cheap when there is already sufficient capacity. + // Therefore, we move all the resizing and error-handling logic from grow_amortized and + // handle_reserve behind a call, while making sure that this function is likely to be + // inlined as just a comparison and a call if the comparison fails. + #[cold] + fn do_reserve_and_handle( + slf: &mut RawVecInner, + len: usize, + additional: usize, + elem_layout: Layout, + ) { + if let Err(err) = slf.grow_amortized(len, additional, elem_layout) { + handle_error(err); + } + } + + if self.needs_to_grow(len, additional, elem_layout) { + do_reserve_and_handle(self, len, additional, elem_layout); + } + } + + #[cfg(not(no_global_oom_handling))] + #[inline] + #[track_caller] + fn grow_one(&mut self, elem_layout: Layout) { + if let Err(err) = self.grow_amortized(self.cap.0, 1, elem_layout) { + handle_error(err); + } + } + + fn try_reserve( + &mut self, + len: usize, + additional: usize, + elem_layout: Layout, + ) -> Result<(), TryReserveError> { + if self.needs_to_grow(len, additional, elem_layout) { + self.grow_amortized(len, additional, elem_layout)?; + } + unsafe { + // Inform the optimizer that the reservation has succeeded or wasn't needed + hint::assert_unchecked(!self.needs_to_grow(len, additional, elem_layout)); + } + Ok(()) + } + + #[cfg(not(no_global_oom_handling))] + #[track_caller] + fn reserve_exact(&mut self, len: usize, additional: usize, elem_layout: Layout) { + if let Err(err) = self.try_reserve_exact(len, additional, elem_layout) { + handle_error(err); + } + } + + fn try_reserve_exact( + &mut self, + len: usize, + additional: usize, + elem_layout: Layout, + ) -> Result<(), TryReserveError> { + if self.needs_to_grow(len, additional, elem_layout) { + self.grow_exact(len, additional, elem_layout)?; + } + unsafe { + // Inform the optimizer that the reservation has succeeded or wasn't needed + hint::assert_unchecked(!self.needs_to_grow(len, additional, elem_layout)); + } + Ok(()) + } + + #[cfg(not(no_global_oom_handling))] + #[inline] + #[track_caller] + fn shrink_to_fit(&mut self, cap: usize, elem_layout: Layout) { + if let Err(err) = self.shrink(cap, elem_layout) { + handle_error(err); + } + } + + #[inline] + fn needs_to_grow(&self, len: usize, additional: usize, elem_layout: Layout) -> bool { + additional > self.capacity(elem_layout.size()).wrapping_sub(len) + } + + #[inline] + unsafe fn set_ptr_and_cap(&mut self, ptr: NonNull<[u8]>, cap: usize) { + // Allocators currently return a `NonNull<[u8]>` whose length matches + // the size requested. If that ever changes, the capacity here should + // change to `ptr.len() / mem::size_of::()`. + self.ptr = Unique::from(ptr.cast()); + self.cap = unsafe { Cap(cap) }; + } + + fn grow_amortized( + &mut self, + len: usize, + additional: usize, + elem_layout: Layout, + ) -> Result<(), TryReserveError> { + // This is ensured by the calling contexts. + debug_assert!(additional > 0); + + if elem_layout.size() == 0 { + // Since we return a capacity of `usize::MAX` when `elem_size` is + // 0, getting to here necessarily means the `RawVec` is overfull. + return Err(CapacityOverflow.into()); + } + + // Nothing we can really do about these checks, sadly. + let required_cap = len.checked_add(additional).ok_or(CapacityOverflow)?; + + // This guarantees exponential growth. The doubling cannot overflow + // because `cap <= isize::MAX` and the type of `cap` is `usize`. + let cap = cmp::max(self.cap.0 * 2, required_cap); + let cap = cmp::max(min_non_zero_cap(elem_layout.size()), cap); + + let new_layout = layout_array(cap, elem_layout)?; + + let ptr = finish_grow(new_layout, self.current_memory(elem_layout), &mut self.alloc)?; + // SAFETY: finish_grow would have resulted in a capacity overflow if we tried to allocate more than `isize::MAX` items + + unsafe { self.set_ptr_and_cap(ptr, cap) }; + Ok(()) + } + + fn grow_exact( + &mut self, + len: usize, + additional: usize, + elem_layout: Layout, + ) -> Result<(), TryReserveError> { + if elem_layout.size() == 0 { + // Since we return a capacity of `usize::MAX` when the type size is + // 0, getting to here necessarily means the `RawVec` is overfull. + return Err(CapacityOverflow.into()); + } + + let cap = len.checked_add(additional).ok_or(CapacityOverflow)?; + let new_layout = layout_array(cap, elem_layout)?; + + let ptr = finish_grow(new_layout, self.current_memory(elem_layout), &mut self.alloc)?; + // SAFETY: finish_grow would have resulted in a capacity overflow if we tried to allocate more than `isize::MAX` items + unsafe { + self.set_ptr_and_cap(ptr, cap); + } + Ok(()) + } + + #[cfg(not(no_global_oom_handling))] + #[inline] + fn shrink(&mut self, cap: usize, elem_layout: Layout) -> Result<(), TryReserveError> { + assert!(cap <= self.capacity(elem_layout.size()), "Tried to shrink to a larger capacity"); + // SAFETY: Just checked this isn't trying to grow + unsafe { self.shrink_unchecked(cap, elem_layout) } + } + + /// `shrink`, but without the capacity check. + /// + /// This is split out so that `shrink` can inline the check, since it + /// optimizes out in things like `shrink_to_fit`, without needing to + /// also inline all this code, as doing that ends up failing the + /// `vec-shrink-panic` codegen test when `shrink_to_fit` ends up being too + /// big for LLVM to be willing to inline. + /// + /// # Safety + /// `cap <= self.capacity()` + #[cfg(not(no_global_oom_handling))] + unsafe fn shrink_unchecked( + &mut self, + cap: usize, + elem_layout: Layout, + ) -> Result<(), TryReserveError> { + let (ptr, layout) = + if let Some(mem) = self.current_memory(elem_layout) { mem } else { return Ok(()) }; + + // If shrinking to 0, deallocate the buffer. We don't reach this point + // for the T::IS_ZST case since current_memory() will have returned + // None. + if cap == 0 { + unsafe { self.alloc.deallocate(ptr, layout) }; + self.ptr = + unsafe { Unique::new_unchecked(ptr::without_provenance_mut(elem_layout.align())) }; + self.cap = Cap::ZERO; + } else { + let ptr = unsafe { + // Layout cannot overflow here because it would have + // overflowed earlier when capacity was larger. + let new_size = elem_layout.size().unchecked_mul(cap); + let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); + self.alloc + .shrink(ptr, layout, new_layout) + .map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })? + }; + // SAFETY: if the allocation is valid, then the capacity is too + unsafe { + self.set_ptr_and_cap(ptr, cap); + } + } + Ok(()) + } + + /// # Safety + /// + /// This function deallocates the owned allocation, but does not update `ptr` or `cap` to + /// prevent double-free or use-after-free. Essentially, do not do anything with the caller + /// after this function returns. + /// Ideally this function would take `self` by move, but it cannot because it exists to be + /// called from a `Drop` impl. + unsafe fn deallocate(&mut self, elem_layout: Layout) { + if let Some((ptr, layout)) = self.current_memory(elem_layout) { + unsafe { + self.alloc.deallocate(ptr, layout); + } + } + } +} + +// not marked inline(never) since we want optimizers to be able to observe the specifics of this +// function, see tests/codegen/vec-reserve-extend.rs. +#[cold] +fn finish_grow( + new_layout: Layout, + current_memory: Option<(NonNull, Layout)>, + alloc: &mut A, +) -> Result, TryReserveError> +where + A: Allocator, +{ + alloc_guard(new_layout.size())?; + + let memory = if let Some((ptr, old_layout)) = current_memory { + debug_assert_eq!(old_layout.align(), new_layout.align()); + unsafe { + // The allocator checks for alignment equality + hint::assert_unchecked(old_layout.align() == new_layout.align()); + alloc.grow(ptr, old_layout, new_layout) + } + } else { + alloc.allocate(new_layout) + }; + + memory.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () }.into()) +} + +// Central function for reserve error handling. +#[cfg(not(no_global_oom_handling))] +#[cold] +#[optimize(size)] +#[track_caller] +fn handle_error(e: TryReserveError) -> ! { + match e.kind() { + CapacityOverflow => capacity_overflow(), + AllocError { layout, .. } => handle_alloc_error(layout), + } +} + +// We need to guarantee the following: +// * We don't ever allocate `> isize::MAX` byte-size objects. +// * We don't overflow `usize::MAX` and actually allocate too little. +// +// On 64-bit we just need to check for overflow since trying to allocate +// `> isize::MAX` bytes will surely fail. On 32-bit and 16-bit we need to add +// an extra guard for this in case we're running on a platform which can use +// all 4GB in user-space, e.g., PAE or x32. +#[inline] +fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { + if usize::BITS < 64 && alloc_size > isize::MAX as usize { + Err(CapacityOverflow.into()) + } else { + Ok(()) + } +} + +#[inline] +fn layout_array(cap: usize, elem_layout: Layout) -> Result { + elem_layout.repeat(cap).map(|(layout, _pad)| layout).map_err(|_| CapacityOverflow.into()) +} diff --git a/CoqOfRust/alloc/raw_vec/tests.rs b/CoqOfRust/alloc/raw_vec/tests.rs new file mode 100644 index 000000000..d78ded104 --- /dev/null +++ b/CoqOfRust/alloc/raw_vec/tests.rs @@ -0,0 +1,163 @@ +use core::mem::size_of; +use std::cell::Cell; + +use super::*; + +#[test] +fn allocator_param() { + use crate::alloc::AllocError; + + // Writing a test of integration between third-party + // allocators and `RawVec` is a little tricky because the `RawVec` + // API does not expose fallible allocation methods, so we + // cannot check what happens when allocator is exhausted + // (beyond detecting a panic). + // + // Instead, this just checks that the `RawVec` methods do at + // least go through the Allocator API when it reserves + // storage. + + // A dumb allocator that consumes a fixed amount of fuel + // before allocation attempts start failing. + struct BoundedAlloc { + fuel: Cell, + } + unsafe impl Allocator for BoundedAlloc { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + let size = layout.size(); + if size > self.fuel.get() { + return Err(AllocError); + } + match Global.allocate(layout) { + ok @ Ok(_) => { + self.fuel.set(self.fuel.get() - size); + ok + } + err @ Err(_) => err, + } + } + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + unsafe { Global.deallocate(ptr, layout) } + } + } + + let a = BoundedAlloc { fuel: Cell::new(500) }; + let mut v: RawVec = RawVec::with_capacity_in(50, a); + assert_eq!(v.inner.alloc.fuel.get(), 450); + v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel) + assert_eq!(v.inner.alloc.fuel.get(), 250); +} + +#[test] +fn reserve_does_not_overallocate() { + { + let mut v: RawVec = RawVec::new(); + // First, `reserve` allocates like `reserve_exact`. + v.reserve(0, 9); + assert_eq!(9, v.capacity()); + } + + { + let mut v: RawVec = RawVec::new(); + v.reserve(0, 7); + assert_eq!(7, v.capacity()); + // 97 is more than double of 7, so `reserve` should work + // like `reserve_exact`. + v.reserve(7, 90); + assert_eq!(97, v.capacity()); + } + + { + let mut v: RawVec = RawVec::new(); + v.reserve(0, 12); + assert_eq!(12, v.capacity()); + v.reserve(12, 3); + // 3 is less than half of 12, so `reserve` must grow + // exponentially. At the time of writing this test grow + // factor is 2, so new capacity is 24, however, grow factor + // of 1.5 is OK too. Hence `>= 18` in assert. + assert!(v.capacity() >= 12 + 12 / 2); + } +} + +struct ZST; + +// A `RawVec` holding zero-sized elements should always look like this. +fn zst_sanity(v: &RawVec) { + assert_eq!(v.capacity(), usize::MAX); + assert_eq!(v.ptr(), core::ptr::Unique::::dangling().as_ptr()); + assert_eq!(v.inner.current_memory(T::LAYOUT), None); +} + +#[test] +fn zst() { + let cap_err = Err(crate::collections::TryReserveErrorKind::CapacityOverflow.into()); + + assert_eq!(std::mem::size_of::(), 0); + + // All these different ways of creating the RawVec produce the same thing. + + let v: RawVec = RawVec::new(); + zst_sanity(&v); + + let v: RawVec = RawVec::with_capacity_in(100, Global); + zst_sanity(&v); + + let v: RawVec = RawVec::with_capacity_in(100, Global); + zst_sanity(&v); + + let mut v: RawVec = RawVec::with_capacity_in(usize::MAX, Global); + zst_sanity(&v); + + // Check all these operations work as expected with zero-sized elements. + + v.reserve(100, usize::MAX - 100); + //v.reserve(101, usize::MAX - 100); // panics, in `zst_reserve_panic` below + zst_sanity(&v); + + v.reserve_exact(100, usize::MAX - 100); + //v.reserve_exact(101, usize::MAX - 100); // panics, in `zst_reserve_exact_panic` below + zst_sanity(&v); + + assert_eq!(v.try_reserve(100, usize::MAX - 100), Ok(())); + assert_eq!(v.try_reserve(101, usize::MAX - 100), cap_err); + zst_sanity(&v); + + assert_eq!(v.try_reserve_exact(100, usize::MAX - 100), Ok(())); + assert_eq!(v.try_reserve_exact(101, usize::MAX - 100), cap_err); + zst_sanity(&v); + + assert_eq!(v.inner.grow_amortized(100, usize::MAX - 100, ZST::LAYOUT), cap_err); + assert_eq!(v.inner.grow_amortized(101, usize::MAX - 100, ZST::LAYOUT), cap_err); + zst_sanity(&v); + + assert_eq!(v.inner.grow_exact(100, usize::MAX - 100, ZST::LAYOUT), cap_err); + assert_eq!(v.inner.grow_exact(101, usize::MAX - 100, ZST::LAYOUT), cap_err); + zst_sanity(&v); +} + +#[test] +#[should_panic(expected = "capacity overflow")] +fn zst_reserve_panic() { + let mut v: RawVec = RawVec::new(); + zst_sanity(&v); + + v.reserve(101, usize::MAX - 100); +} + +#[test] +#[should_panic(expected = "capacity overflow")] +fn zst_reserve_exact_panic() { + let mut v: RawVec = RawVec::new(); + zst_sanity(&v); + + v.reserve_exact(101, usize::MAX - 100); +} + +#[test] +fn niches() { + let baseline = size_of::>(); + assert_eq!(size_of::>>(), baseline); + assert_eq!(size_of::>>>(), baseline); + assert_eq!(size_of::>>>>(), baseline); +} diff --git a/CoqOfRust/alloc/rc.rs b/CoqOfRust/alloc/rc.rs new file mode 100644 index 000000000..7aa1457b1 --- /dev/null +++ b/CoqOfRust/alloc/rc.rs @@ -0,0 +1,3887 @@ +//! Single-threaded reference-counting pointers. 'Rc' stands for 'Reference +//! Counted'. +//! +//! The type [`Rc`][`Rc`] provides shared ownership of a value of type `T`, +//! allocated in the heap. Invoking [`clone`][clone] on [`Rc`] produces a new +//! pointer to the same allocation in the heap. When the last [`Rc`] pointer to a +//! given allocation is destroyed, the value stored in that allocation (often +//! referred to as "inner value") is also dropped. +//! +//! Shared references in Rust disallow mutation by default, and [`Rc`] +//! is no exception: you cannot generally obtain a mutable reference to +//! something inside an [`Rc`]. If you need mutability, put a [`Cell`] +//! or [`RefCell`] inside the [`Rc`]; see [an example of mutability +//! inside an `Rc`][mutability]. +//! +//! [`Rc`] uses non-atomic reference counting. This means that overhead is very +//! low, but an [`Rc`] cannot be sent between threads, and consequently [`Rc`] +//! does not implement [`Send`]. As a result, the Rust compiler +//! will check *at compile time* that you are not sending [`Rc`]s between +//! threads. If you need multi-threaded, atomic reference counting, use +//! [`sync::Arc`][arc]. +//! +//! The [`downgrade`][downgrade] method can be used to create a non-owning +//! [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d +//! to an [`Rc`], but this will return [`None`] if the value stored in the allocation has +//! already been dropped. In other words, `Weak` pointers do not keep the value +//! inside the allocation alive; however, they *do* keep the allocation +//! (the backing store for the inner value) alive. +//! +//! A cycle between [`Rc`] pointers will never be deallocated. For this reason, +//! [`Weak`] is used to break cycles. For example, a tree could have strong +//! [`Rc`] pointers from parent nodes to children, and [`Weak`] pointers from +//! children back to their parents. +//! +//! `Rc` automatically dereferences to `T` (via the [`Deref`] trait), +//! so you can call `T`'s methods on a value of type [`Rc`][`Rc`]. To avoid name +//! clashes with `T`'s methods, the methods of [`Rc`][`Rc`] itself are associated +//! functions, called using [fully qualified syntax]: +//! +//! ``` +//! use std::rc::Rc; +//! +//! let my_rc = Rc::new(()); +//! let my_weak = Rc::downgrade(&my_rc); +//! ``` +//! +//! `Rc`'s implementations of traits like `Clone` may also be called using +//! fully qualified syntax. Some people prefer to use fully qualified syntax, +//! while others prefer using method-call syntax. +//! +//! ``` +//! use std::rc::Rc; +//! +//! let rc = Rc::new(()); +//! // Method-call syntax +//! let rc2 = rc.clone(); +//! // Fully qualified syntax +//! let rc3 = Rc::clone(&rc); +//! ``` +//! +//! [`Weak`][`Weak`] does not auto-dereference to `T`, because the inner value may have +//! already been dropped. +//! +//! # Cloning references +//! +//! Creating a new reference to the same allocation as an existing reference counted pointer +//! is done using the `Clone` trait implemented for [`Rc`][`Rc`] and [`Weak`][`Weak`]. +//! +//! ``` +//! use std::rc::Rc; +//! +//! let foo = Rc::new(vec![1.0, 2.0, 3.0]); +//! // The two syntaxes below are equivalent. +//! let a = foo.clone(); +//! let b = Rc::clone(&foo); +//! // a and b both point to the same memory location as foo. +//! ``` +//! +//! The `Rc::clone(&from)` syntax is the most idiomatic because it conveys more explicitly +//! the meaning of the code. In the example above, this syntax makes it easier to see that +//! this code is creating a new reference rather than copying the whole content of foo. +//! +//! # Examples +//! +//! Consider a scenario where a set of `Gadget`s are owned by a given `Owner`. +//! We want to have our `Gadget`s point to their `Owner`. We can't do this with +//! unique ownership, because more than one gadget may belong to the same +//! `Owner`. [`Rc`] allows us to share an `Owner` between multiple `Gadget`s, +//! and have the `Owner` remain allocated as long as any `Gadget` points at it. +//! +//! ``` +//! use std::rc::Rc; +//! +//! struct Owner { +//! name: String, +//! // ...other fields +//! } +//! +//! struct Gadget { +//! id: i32, +//! owner: Rc, +//! // ...other fields +//! } +//! +//! fn main() { +//! // Create a reference-counted `Owner`. +//! let gadget_owner: Rc = Rc::new( +//! Owner { +//! name: "Gadget Man".to_string(), +//! } +//! ); +//! +//! // Create `Gadget`s belonging to `gadget_owner`. Cloning the `Rc` +//! // gives us a new pointer to the same `Owner` allocation, incrementing +//! // the reference count in the process. +//! let gadget1 = Gadget { +//! id: 1, +//! owner: Rc::clone(&gadget_owner), +//! }; +//! let gadget2 = Gadget { +//! id: 2, +//! owner: Rc::clone(&gadget_owner), +//! }; +//! +//! // Dispose of our local variable `gadget_owner`. +//! drop(gadget_owner); +//! +//! // Despite dropping `gadget_owner`, we're still able to print out the name +//! // of the `Owner` of the `Gadget`s. This is because we've only dropped a +//! // single `Rc`, not the `Owner` it points to. As long as there are +//! // other `Rc` pointing at the same `Owner` allocation, it will remain +//! // live. The field projection `gadget1.owner.name` works because +//! // `Rc` automatically dereferences to `Owner`. +//! println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name); +//! println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name); +//! +//! // At the end of the function, `gadget1` and `gadget2` are destroyed, and +//! // with them the last counted references to our `Owner`. Gadget Man now +//! // gets destroyed as well. +//! } +//! ``` +//! +//! If our requirements change, and we also need to be able to traverse from +//! `Owner` to `Gadget`, we will run into problems. An [`Rc`] pointer from `Owner` +//! to `Gadget` introduces a cycle. This means that their +//! reference counts can never reach 0, and the allocation will never be destroyed: +//! a memory leak. In order to get around this, we can use [`Weak`] +//! pointers. +//! +//! Rust actually makes it somewhat difficult to produce this loop in the first +//! place. In order to end up with two values that point at each other, one of +//! them needs to be mutable. This is difficult because [`Rc`] enforces +//! memory safety by only giving out shared references to the value it wraps, +//! and these don't allow direct mutation. We need to wrap the part of the +//! value we wish to mutate in a [`RefCell`], which provides *interior +//! mutability*: a method to achieve mutability through a shared reference. +//! [`RefCell`] enforces Rust's borrowing rules at runtime. +//! +//! ``` +//! use std::rc::Rc; +//! use std::rc::Weak; +//! use std::cell::RefCell; +//! +//! struct Owner { +//! name: String, +//! gadgets: RefCell>>, +//! // ...other fields +//! } +//! +//! struct Gadget { +//! id: i32, +//! owner: Rc, +//! // ...other fields +//! } +//! +//! fn main() { +//! // Create a reference-counted `Owner`. Note that we've put the `Owner`'s +//! // vector of `Gadget`s inside a `RefCell` so that we can mutate it through +//! // a shared reference. +//! let gadget_owner: Rc = Rc::new( +//! Owner { +//! name: "Gadget Man".to_string(), +//! gadgets: RefCell::new(vec![]), +//! } +//! ); +//! +//! // Create `Gadget`s belonging to `gadget_owner`, as before. +//! let gadget1 = Rc::new( +//! Gadget { +//! id: 1, +//! owner: Rc::clone(&gadget_owner), +//! } +//! ); +//! let gadget2 = Rc::new( +//! Gadget { +//! id: 2, +//! owner: Rc::clone(&gadget_owner), +//! } +//! ); +//! +//! // Add the `Gadget`s to their `Owner`. +//! { +//! let mut gadgets = gadget_owner.gadgets.borrow_mut(); +//! gadgets.push(Rc::downgrade(&gadget1)); +//! gadgets.push(Rc::downgrade(&gadget2)); +//! +//! // `RefCell` dynamic borrow ends here. +//! } +//! +//! // Iterate over our `Gadget`s, printing their details out. +//! for gadget_weak in gadget_owner.gadgets.borrow().iter() { +//! +//! // `gadget_weak` is a `Weak`. Since `Weak` pointers can't +//! // guarantee the allocation still exists, we need to call +//! // `upgrade`, which returns an `Option>`. +//! // +//! // In this case we know the allocation still exists, so we simply +//! // `unwrap` the `Option`. In a more complicated program, you might +//! // need graceful error handling for a `None` result. +//! +//! let gadget = gadget_weak.upgrade().unwrap(); +//! println!("Gadget {} owned by {}", gadget.id, gadget.owner.name); +//! } +//! +//! // At the end of the function, `gadget_owner`, `gadget1`, and `gadget2` +//! // are destroyed. There are now no strong (`Rc`) pointers to the +//! // gadgets, so they are destroyed. This zeroes the reference count on +//! // Gadget Man, so he gets destroyed as well. +//! } +//! ``` +//! +//! [clone]: Clone::clone +//! [`Cell`]: core::cell::Cell +//! [`RefCell`]: core::cell::RefCell +//! [arc]: crate::sync::Arc +//! [`Deref`]: core::ops::Deref +//! [downgrade]: Rc::downgrade +//! [upgrade]: Weak::upgrade +//! [mutability]: core::cell#introducing-mutability-inside-of-something-immutable +//! [fully qualified syntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::any::Any; +use core::cell::Cell; +#[cfg(not(no_global_oom_handling))] +use core::clone::CloneToUninit; +use core::cmp::Ordering; +use core::hash::{Hash, Hasher}; +use core::intrinsics::abort; +#[cfg(not(no_global_oom_handling))] +use core::iter; +use core::marker::{PhantomData, Unsize}; +use core::mem::{self, ManuallyDrop, align_of_val_raw}; +use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver}; +use core::panic::{RefUnwindSafe, UnwindSafe}; +#[cfg(not(no_global_oom_handling))] +use core::pin::Pin; +use core::pin::PinCoerceUnsized; +use core::ptr::{self, NonNull, drop_in_place}; +#[cfg(not(no_global_oom_handling))] +use core::slice::from_raw_parts_mut; +use core::{borrow, fmt, hint}; +#[cfg(test)] +use std::boxed::Box; + +#[cfg(not(no_global_oom_handling))] +use crate::alloc::handle_alloc_error; +use crate::alloc::{AllocError, Allocator, Global, Layout}; +use crate::borrow::{Cow, ToOwned}; +#[cfg(not(test))] +use crate::boxed::Box; +#[cfg(not(no_global_oom_handling))] +use crate::string::String; +#[cfg(not(no_global_oom_handling))] +use crate::vec::Vec; + +#[cfg(test)] +mod tests; + +// This is repr(C) to future-proof against possible field-reordering, which +// would interfere with otherwise safe [into|from]_raw() of transmutable +// inner types. +#[repr(C)] +struct RcInner { + strong: Cell, + weak: Cell, + value: T, +} + +/// Calculate layout for `RcInner` using the inner value's layout +fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout { + // Calculate layout using the given value layout. + // Previously, layout was calculated on the expression + // `&*(ptr as *const RcInner)`, but this created a misaligned + // reference (see #54908). + Layout::new::>().extend(layout).unwrap().0.pad_to_align() +} + +/// A single-threaded reference-counting pointer. 'Rc' stands for 'Reference +/// Counted'. +/// +/// See the [module-level documentation](./index.html) for more details. +/// +/// The inherent methods of `Rc` are all associated functions, which means +/// that you have to call them as e.g., [`Rc::get_mut(&mut value)`][get_mut] instead of +/// `value.get_mut()`. This avoids conflicts with methods of the inner type `T`. +/// +/// [get_mut]: Rc::get_mut +#[doc(search_unbox)] +#[cfg_attr(not(test), rustc_diagnostic_item = "Rc")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_insignificant_dtor] +pub struct Rc< + T: ?Sized, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + ptr: NonNull>, + phantom: PhantomData>, + alloc: A, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl !Send for Rc {} + +// Note that this negative impl isn't strictly necessary for correctness, +// as `Rc` transitively contains a `Cell`, which is itself `!Sync`. +// However, given how important `Rc`'s `!Sync`-ness is, +// having an explicit negative impl is nice for documentation purposes +// and results in nicer error messages. +#[stable(feature = "rust1", since = "1.0.0")] +impl !Sync for Rc {} + +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for Rc {} +#[stable(feature = "rc_ref_unwind_safe", since = "1.58.0")] +impl RefUnwindSafe for Rc {} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U: ?Sized, A: Allocator> CoerceUnsized> for Rc {} + +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for Rc {} + +impl Rc { + #[inline] + unsafe fn from_inner(ptr: NonNull>) -> Self { + unsafe { Self::from_inner_in(ptr, Global) } + } + + #[inline] + unsafe fn from_ptr(ptr: *mut RcInner) -> Self { + unsafe { Self::from_inner(NonNull::new_unchecked(ptr)) } + } +} + +impl Rc { + #[inline(always)] + fn inner(&self) -> &RcInner { + // This unsafety is ok because while this Rc is alive we're guaranteed + // that the inner pointer is valid. + unsafe { self.ptr.as_ref() } + } + + #[inline] + fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { + let this = mem::ManuallyDrop::new(this); + (this.ptr, unsafe { ptr::read(&this.alloc) }) + } + + #[inline] + unsafe fn from_inner_in(ptr: NonNull>, alloc: A) -> Self { + Self { ptr, phantom: PhantomData, alloc } + } + + #[inline] + unsafe fn from_ptr_in(ptr: *mut RcInner, alloc: A) -> Self { + unsafe { Self::from_inner_in(NonNull::new_unchecked(ptr), alloc) } + } + + // Non-inlined part of `drop`. + #[inline(never)] + unsafe fn drop_slow(&mut self) { + // Reconstruct the "strong weak" pointer and drop it when this + // variable goes out of scope. This ensures that the memory is + // deallocated even if the destructor of `T` panics. + let _weak = Weak { ptr: self.ptr, alloc: &self.alloc }; + + // Destroy the contained object. + // We cannot use `get_mut_unchecked` here, because `self.alloc` is borrowed. + unsafe { + ptr::drop_in_place(&mut (*self.ptr.as_ptr()).value); + } + } +} + +impl Rc { + /// Constructs a new `Rc`. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(value: T) -> Rc { + // There is an implicit weak pointer owned by all the strong + // pointers, which ensures that the weak destructor never frees + // the allocation while the strong destructor is running, even + // if the weak pointer is stored inside the strong one. + unsafe { + Self::from_inner( + Box::leak(Box::new(RcInner { strong: Cell::new(1), weak: Cell::new(1), value })) + .into(), + ) + } + } + + /// Constructs a new `Rc` while giving you a `Weak` to the allocation, + /// to allow you to construct a `T` which holds a weak pointer to itself. + /// + /// Generally, a structure circularly referencing itself, either directly or + /// indirectly, should not hold a strong reference to itself to prevent a memory leak. + /// Using this function, you get access to the weak pointer during the + /// initialization of `T`, before the `Rc` is created, such that you can + /// clone and store it inside the `T`. + /// + /// `new_cyclic` first allocates the managed allocation for the `Rc`, + /// then calls your closure, giving it a `Weak` to this allocation, + /// and only afterwards completes the construction of the `Rc` by placing + /// the `T` returned from your closure into the allocation. + /// + /// Since the new `Rc` is not fully-constructed until `Rc::new_cyclic` + /// returns, calling [`upgrade`] on the weak reference inside your closure will + /// fail and result in a `None` value. + /// + /// # Panics + /// + /// If `data_fn` panics, the panic is propagated to the caller, and the + /// temporary [`Weak`] is dropped normally. + /// + /// # Examples + /// + /// ``` + /// # #![allow(dead_code)] + /// use std::rc::{Rc, Weak}; + /// + /// struct Gadget { + /// me: Weak, + /// } + /// + /// impl Gadget { + /// /// Constructs a reference counted Gadget. + /// fn new() -> Rc { + /// // `me` is a `Weak` pointing at the new allocation of the + /// // `Rc` we're constructing. + /// Rc::new_cyclic(|me| { + /// // Create the actual struct here. + /// Gadget { me: me.clone() } + /// }) + /// } + /// + /// /// Returns a reference counted pointer to Self. + /// fn me(&self) -> Rc { + /// self.me.upgrade().unwrap() + /// } + /// } + /// ``` + /// [`upgrade`]: Weak::upgrade + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "arc_new_cyclic", since = "1.60.0")] + pub fn new_cyclic(data_fn: F) -> Rc + where + F: FnOnce(&Weak) -> T, + { + Self::new_cyclic_in(data_fn, Global) + } + + /// Constructs a new `Rc` with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::::new_uninit(); + /// + /// // Deferred initialization: + /// Rc::get_mut(&mut five).unwrap().write(5); + /// + /// let five = unsafe { five.assume_init() }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "new_uninit", since = "1.82.0")] + #[must_use] + pub fn new_uninit() -> Rc> { + unsafe { + Rc::from_ptr(Rc::allocate_for_layout( + Layout::new::(), + |layout| Global.allocate(layout), + <*mut u8>::cast, + )) + } + } + + /// Constructs a new `Rc` with uninitialized contents, with the memory + /// being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_zeroed_alloc)] + /// + /// use std::rc::Rc; + /// + /// let zero = Rc::::new_zeroed(); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] + #[must_use] + pub fn new_zeroed() -> Rc> { + unsafe { + Rc::from_ptr(Rc::allocate_for_layout( + Layout::new::(), + |layout| Global.allocate_zeroed(layout), + <*mut u8>::cast, + )) + } + } + + /// Constructs a new `Rc`, returning an error if the allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::rc::Rc; + /// + /// let five = Rc::try_new(5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn try_new(value: T) -> Result, AllocError> { + // There is an implicit weak pointer owned by all the strong + // pointers, which ensures that the weak destructor never frees + // the allocation while the strong destructor is running, even + // if the weak pointer is stored inside the strong one. + unsafe { + Ok(Self::from_inner( + Box::leak(Box::try_new(RcInner { + strong: Cell::new(1), + weak: Cell::new(1), + value, + })?) + .into(), + )) + } + } + + /// Constructs a new `Rc` with uninitialized contents, returning an error if the allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::::try_new_uninit()?; + /// + /// // Deferred initialization: + /// Rc::get_mut(&mut five).unwrap().write(5); + /// + /// let five = unsafe { five.assume_init() }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_uninit() -> Result>, AllocError> { + unsafe { + Ok(Rc::from_ptr(Rc::try_allocate_for_layout( + Layout::new::(), + |layout| Global.allocate(layout), + <*mut u8>::cast, + )?)) + } + } + + /// Constructs a new `Rc` with uninitialized contents, with the memory + /// being filled with `0` bytes, returning an error if the allocation fails + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::rc::Rc; + /// + /// let zero = Rc::::try_new_zeroed()?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + //#[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_zeroed() -> Result>, AllocError> { + unsafe { + Ok(Rc::from_ptr(Rc::try_allocate_for_layout( + Layout::new::(), + |layout| Global.allocate_zeroed(layout), + <*mut u8>::cast, + )?)) + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `value` will be pinned in memory and unable to be moved. + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "pin", since = "1.33.0")] + #[must_use] + pub fn pin(value: T) -> Pin> { + unsafe { Pin::new_unchecked(Rc::new(value)) } + } +} + +impl Rc { + /// Constructs a new `Rc` in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let five = Rc::new_in(5, System); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn new_in(value: T, alloc: A) -> Rc { + // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. + // That would make code size bigger. + match Self::try_new_in(value, alloc) { + Ok(m) => m, + Err(_) => handle_alloc_error(Layout::new::>()), + } + } + + /// Constructs a new `Rc` with uninitialized contents in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// #![feature(allocator_api)] + /// + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let mut five = Rc::::new_uninit_in(System); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn new_uninit_in(alloc: A) -> Rc, A> { + unsafe { + Rc::from_ptr_in( + Rc::allocate_for_layout( + Layout::new::(), + |layout| alloc.allocate(layout), + <*mut u8>::cast, + ), + alloc, + ) + } + } + + /// Constructs a new `Rc` with uninitialized contents, with the memory + /// being filled with `0` bytes, in the provided allocator. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let zero = Rc::::new_zeroed_in(System); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn new_zeroed_in(alloc: A) -> Rc, A> { + unsafe { + Rc::from_ptr_in( + Rc::allocate_for_layout( + Layout::new::(), + |layout| alloc.allocate_zeroed(layout), + <*mut u8>::cast, + ), + alloc, + ) + } + } + + /// Constructs a new `Rc` in the given allocator while giving you a `Weak` to the allocation, + /// to allow you to construct a `T` which holds a weak pointer to itself. + /// + /// Generally, a structure circularly referencing itself, either directly or + /// indirectly, should not hold a strong reference to itself to prevent a memory leak. + /// Using this function, you get access to the weak pointer during the + /// initialization of `T`, before the `Rc` is created, such that you can + /// clone and store it inside the `T`. + /// + /// `new_cyclic_in` first allocates the managed allocation for the `Rc`, + /// then calls your closure, giving it a `Weak` to this allocation, + /// and only afterwards completes the construction of the `Rc` by placing + /// the `T` returned from your closure into the allocation. + /// + /// Since the new `Rc` is not fully-constructed until `Rc::new_cyclic_in` + /// returns, calling [`upgrade`] on the weak reference inside your closure will + /// fail and result in a `None` value. + /// + /// # Panics + /// + /// If `data_fn` panics, the panic is propagated to the caller, and the + /// temporary [`Weak`] is dropped normally. + /// + /// # Examples + /// + /// See [`new_cyclic`]. + /// + /// [`new_cyclic`]: Rc::new_cyclic + /// [`upgrade`]: Weak::upgrade + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn new_cyclic_in(data_fn: F, alloc: A) -> Rc + where + F: FnOnce(&Weak) -> T, + { + // Construct the inner in the "uninitialized" state with a single + // weak reference. + let (uninit_raw_ptr, alloc) = Box::into_raw_with_allocator(Box::new_in( + RcInner { + strong: Cell::new(0), + weak: Cell::new(1), + value: mem::MaybeUninit::::uninit(), + }, + alloc, + )); + let uninit_ptr: NonNull<_> = (unsafe { &mut *uninit_raw_ptr }).into(); + let init_ptr: NonNull> = uninit_ptr.cast(); + + let weak = Weak { ptr: init_ptr, alloc: alloc }; + + // It's important we don't give up ownership of the weak pointer, or + // else the memory might be freed by the time `data_fn` returns. If + // we really wanted to pass ownership, we could create an additional + // weak pointer for ourselves, but this would result in additional + // updates to the weak reference count which might not be necessary + // otherwise. + let data = data_fn(&weak); + + let strong = unsafe { + let inner = init_ptr.as_ptr(); + ptr::write(&raw mut (*inner).value, data); + + let prev_value = (*inner).strong.get(); + debug_assert_eq!(prev_value, 0, "No prior strong references should exist"); + (*inner).strong.set(1); + + // Strong references should collectively own a shared weak reference, + // so don't run the destructor for our old weak reference. + // Calling into_raw_with_allocator has the double effect of giving us back the allocator, + // and forgetting the weak reference. + let alloc = weak.into_raw_with_allocator().1; + + Rc::from_inner_in(init_ptr, alloc) + }; + + strong + } + + /// Constructs a new `Rc` in the provided allocator, returning an error if the allocation + /// fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let five = Rc::try_new_in(5, System); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new_in(value: T, alloc: A) -> Result { + // There is an implicit weak pointer owned by all the strong + // pointers, which ensures that the weak destructor never frees + // the allocation while the strong destructor is running, even + // if the weak pointer is stored inside the strong one. + let (ptr, alloc) = Box::into_unique(Box::try_new_in( + RcInner { strong: Cell::new(1), weak: Cell::new(1), value }, + alloc, + )?); + Ok(unsafe { Self::from_inner_in(ptr.into(), alloc) }) + } + + /// Constructs a new `Rc` with uninitialized contents, in the provided allocator, returning an + /// error if the allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let mut five = Rc::::try_new_uninit_in(System)?; + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> { + unsafe { + Ok(Rc::from_ptr_in( + Rc::try_allocate_for_layout( + Layout::new::(), + |layout| alloc.allocate(layout), + <*mut u8>::cast, + )?, + alloc, + )) + } + } + + /// Constructs a new `Rc` with uninitialized contents, with the memory + /// being filled with `0` bytes, in the provided allocator, returning an error if the allocation + /// fails + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let zero = Rc::::try_new_zeroed_in(System)?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + //#[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> { + unsafe { + Ok(Rc::from_ptr_in( + Rc::try_allocate_for_layout( + Layout::new::(), + |layout| alloc.allocate_zeroed(layout), + <*mut u8>::cast, + )?, + alloc, + )) + } + } + + /// Constructs a new `Pin>` in the provided allocator. If `T` does not implement `Unpin`, then + /// `value` will be pinned in memory and unable to be moved. + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn pin_in(value: T, alloc: A) -> Pin + where + A: 'static, + { + unsafe { Pin::new_unchecked(Rc::new_in(value, alloc)) } + } + + /// Returns the inner value, if the `Rc` has exactly one strong reference. + /// + /// Otherwise, an [`Err`] is returned with the same `Rc` that was + /// passed in. + /// + /// This will succeed even if there are outstanding weak references. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x = Rc::new(3); + /// assert_eq!(Rc::try_unwrap(x), Ok(3)); + /// + /// let x = Rc::new(4); + /// let _y = Rc::clone(&x); + /// assert_eq!(*Rc::try_unwrap(x).unwrap_err(), 4); + /// ``` + #[inline] + #[stable(feature = "rc_unique", since = "1.4.0")] + pub fn try_unwrap(this: Self) -> Result { + if Rc::strong_count(&this) == 1 { + let this = ManuallyDrop::new(this); + + let val: T = unsafe { ptr::read(&**this) }; // copy the contained object + let alloc: A = unsafe { ptr::read(&this.alloc) }; // copy the allocator + + // Indicate to Weaks that they can't be promoted by decrementing + // the strong count, and then remove the implicit "strong weak" + // pointer while also handling drop logic by just crafting a + // fake Weak. + this.inner().dec_strong(); + let _weak = Weak { ptr: this.ptr, alloc }; + Ok(val) + } else { + Err(this) + } + } + + /// Returns the inner value, if the `Rc` has exactly one strong reference. + /// + /// Otherwise, [`None`] is returned and the `Rc` is dropped. + /// + /// This will succeed even if there are outstanding weak references. + /// + /// If `Rc::into_inner` is called on every clone of this `Rc`, + /// it is guaranteed that exactly one of the calls returns the inner value. + /// This means in particular that the inner value is not dropped. + /// + /// [`Rc::try_unwrap`] is conceptually similar to `Rc::into_inner`. + /// And while they are meant for different use-cases, `Rc::into_inner(this)` + /// is in fact equivalent to [Rc::try_unwrap]\(this).[ok][Result::ok](). + /// (Note that the same kind of equivalence does **not** hold true for + /// [`Arc`](crate::sync::Arc), due to race conditions that do not apply to `Rc`!) + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x = Rc::new(3); + /// assert_eq!(Rc::into_inner(x), Some(3)); + /// + /// let x = Rc::new(4); + /// let y = Rc::clone(&x); + /// + /// assert_eq!(Rc::into_inner(y), None); + /// assert_eq!(Rc::into_inner(x), Some(4)); + /// ``` + #[inline] + #[stable(feature = "rc_into_inner", since = "1.70.0")] + pub fn into_inner(this: Self) -> Option { + Rc::try_unwrap(this).ok() + } +} + +impl Rc<[T]> { + /// Constructs a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::<[u32]>::new_uninit_slice(3); + /// + /// // Deferred initialization: + /// let data = Rc::get_mut(&mut values).unwrap(); + /// data[0].write(1); + /// data[1].write(2); + /// data[2].write(3); + /// + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "new_uninit", since = "1.82.0")] + #[must_use] + pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { + unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) } + } + + /// Constructs a new reference-counted slice with uninitialized contents, with the memory being + /// filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_zeroed_alloc)] + /// + /// use std::rc::Rc; + /// + /// let values = Rc::<[u32]>::new_zeroed_slice(3); + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] + #[must_use] + pub fn new_zeroed_slice(len: usize) -> Rc<[mem::MaybeUninit]> { + unsafe { + Rc::from_ptr(Rc::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| Global.allocate_zeroed(layout), + |mem| { + ptr::slice_from_raw_parts_mut(mem.cast::(), len) + as *mut RcInner<[mem::MaybeUninit]> + }, + )) + } + } +} + +impl Rc<[T], A> { + /// Constructs a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// #![feature(allocator_api)] + /// + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let mut values = Rc::<[u32], _>::new_uninit_slice_in(3, System); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn new_uninit_slice_in(len: usize, alloc: A) -> Rc<[mem::MaybeUninit], A> { + unsafe { Rc::from_ptr_in(Rc::allocate_for_slice_in(len, &alloc), alloc) } + } + + /// Constructs a new reference-counted slice with uninitialized contents, with the memory being + /// filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let values = Rc::<[u32], _>::new_zeroed_slice_in(3, System); + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Rc<[mem::MaybeUninit], A> { + unsafe { + Rc::from_ptr_in( + Rc::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| alloc.allocate_zeroed(layout), + |mem| { + ptr::slice_from_raw_parts_mut(mem.cast::(), len) + as *mut RcInner<[mem::MaybeUninit]> + }, + ), + alloc, + ) + } + } +} + +impl Rc, A> { + /// Converts to `Rc`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the inner value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::::new_uninit(); + /// + /// // Deferred initialization: + /// Rc::get_mut(&mut five).unwrap().write(5); + /// + /// let five = unsafe { five.assume_init() }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[stable(feature = "new_uninit", since = "1.82.0")] + #[inline] + pub unsafe fn assume_init(self) -> Rc { + let (ptr, alloc) = Rc::into_inner_with_allocator(self); + unsafe { Rc::from_inner_in(ptr.cast(), alloc) } + } +} + +impl Rc<[mem::MaybeUninit], A> { + /// Converts to `Rc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the inner value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::<[u32]>::new_uninit_slice(3); + /// + /// // Deferred initialization: + /// let data = Rc::get_mut(&mut values).unwrap(); + /// data[0].write(1); + /// data[1].write(2); + /// data[2].write(3); + /// + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[stable(feature = "new_uninit", since = "1.82.0")] + #[inline] + pub unsafe fn assume_init(self) -> Rc<[T], A> { + let (ptr, alloc) = Rc::into_inner_with_allocator(self); + unsafe { Rc::from_ptr_in(ptr.as_ptr() as _, alloc) } + } +} + +impl Rc { + /// Constructs an `Rc` from a raw pointer. + /// + /// The raw pointer must have been previously returned by a call to + /// [`Rc::into_raw`][into_raw] with the following requirements: + /// + /// * If `U` is sized, it must have the same size and alignment as `T`. This + /// is trivially true if `U` is `T`. + /// * If `U` is unsized, its data pointer must have the same size and + /// alignment as `T`. This is trivially true if `Rc` was constructed + /// through `Rc` and then converted to `Rc` through an [unsized + /// coercion]. + /// + /// Note that if `U` or `U`'s data pointer is not `T` but has the same size + /// and alignment, this is basically like transmuting references of + /// different types. See [`mem::transmute`][transmute] for more information + /// on what restrictions apply in this case. + /// + /// The raw pointer must point to a block of memory allocated by the global allocator + /// + /// The user of `from_raw` has to make sure a specific value of `T` is only + /// dropped once. + /// + /// This function is unsafe because improper use may lead to memory unsafety, + /// even if the returned `Rc` is never accessed. + /// + /// [into_raw]: Rc::into_raw + /// [transmute]: core::mem::transmute + /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x = Rc::new("hello".to_owned()); + /// let x_ptr = Rc::into_raw(x); + /// + /// unsafe { + /// // Convert back to an `Rc` to prevent leak. + /// let x = Rc::from_raw(x_ptr); + /// assert_eq!(&*x, "hello"); + /// + /// // Further calls to `Rc::from_raw(x_ptr)` would be memory-unsafe. + /// } + /// + /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! + /// ``` + /// + /// Convert a slice back into its original array: + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x: Rc<[u32]> = Rc::new([1, 2, 3]); + /// let x_ptr: *const [u32] = Rc::into_raw(x); + /// + /// unsafe { + /// let x: Rc<[u32; 3]> = Rc::from_raw(x_ptr.cast::<[u32; 3]>()); + /// assert_eq!(&*x, &[1, 2, 3]); + /// } + /// ``` + #[inline] + #[stable(feature = "rc_raw", since = "1.17.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + unsafe { Self::from_raw_in(ptr, Global) } + } + + /// Increments the strong reference count on the `Rc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Rc::into_raw`, the + /// associated `Rc` instance must be valid (i.e. the strong count must be at + /// least 1) for the duration of this method, and `ptr` must point to a block of memory + /// allocated by the global allocator. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// unsafe { + /// let ptr = Rc::into_raw(five); + /// Rc::increment_strong_count(ptr); + /// + /// let five = Rc::from_raw(ptr); + /// assert_eq!(2, Rc::strong_count(&five)); + /// # // Prevent leaks for Miri. + /// # Rc::decrement_strong_count(ptr); + /// } + /// ``` + #[inline] + #[stable(feature = "rc_mutate_strong_count", since = "1.53.0")] + pub unsafe fn increment_strong_count(ptr: *const T) { + unsafe { Self::increment_strong_count_in(ptr, Global) } + } + + /// Decrements the strong reference count on the `Rc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Rc::into_raw`, the + /// associated `Rc` instance must be valid (i.e. the strong count must be at + /// least 1) when invoking this method, and `ptr` must point to a block of memory + /// allocated by the global allocator. This method can be used to release the final `Rc` and + /// backing storage, but **should not** be called after the final `Rc` has been released. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// unsafe { + /// let ptr = Rc::into_raw(five); + /// Rc::increment_strong_count(ptr); + /// + /// let five = Rc::from_raw(ptr); + /// assert_eq!(2, Rc::strong_count(&five)); + /// Rc::decrement_strong_count(ptr); + /// assert_eq!(1, Rc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[stable(feature = "rc_mutate_strong_count", since = "1.53.0")] + pub unsafe fn decrement_strong_count(ptr: *const T) { + unsafe { Self::decrement_strong_count_in(ptr, Global) } + } +} + +impl Rc { + /// Returns a reference to the underlying allocator. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Rc::allocator(&r)` instead of `r.allocator()`. This + /// is so that there is no conflict with a method on the inner type. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(this: &Self) -> &A { + &this.alloc + } + + /// Consumes the `Rc`, returning the wrapped pointer. + /// + /// To avoid a memory leak the pointer must be converted back to an `Rc` using + /// [`Rc::from_raw`]. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x = Rc::new("hello".to_owned()); + /// let x_ptr = Rc::into_raw(x); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// # // Prevent leaks for Miri. + /// # drop(unsafe { Rc::from_raw(x_ptr) }); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[stable(feature = "rc_raw", since = "1.17.0")] + #[rustc_never_returns_null_ptr] + pub fn into_raw(this: Self) -> *const T { + let this = ManuallyDrop::new(this); + Self::as_ptr(&*this) + } + + /// Consumes the `Rc`, returning the wrapped pointer and allocator. + /// + /// To avoid a memory leak the pointer must be converted back to an `Rc` using + /// [`Rc::from_raw_in`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let x = Rc::new_in("hello".to_owned(), System); + /// let (ptr, alloc) = Rc::into_raw_with_allocator(x); + /// assert_eq!(unsafe { &*ptr }, "hello"); + /// let x = unsafe { Rc::from_raw_in(ptr, alloc) }; + /// assert_eq!(&*x, "hello"); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn into_raw_with_allocator(this: Self) -> (*const T, A) { + let this = mem::ManuallyDrop::new(this); + let ptr = Self::as_ptr(&this); + // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + let alloc = unsafe { ptr::read(&this.alloc) }; + (ptr, alloc) + } + + /// Provides a raw pointer to the data. + /// + /// The counts are not affected in any way and the `Rc` is not consumed. The pointer is valid + /// for as long there are strong counts in the `Rc`. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x = Rc::new("hello".to_owned()); + /// let y = Rc::clone(&x); + /// let x_ptr = Rc::as_ptr(&x); + /// assert_eq!(x_ptr, Rc::as_ptr(&y)); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// ``` + #[stable(feature = "weak_into_raw", since = "1.45.0")] + #[rustc_never_returns_null_ptr] + pub fn as_ptr(this: &Self) -> *const T { + let ptr: *mut RcInner = NonNull::as_ptr(this.ptr); + + // SAFETY: This cannot go through Deref::deref or Rc::inner because + // this is required to retain raw/mut provenance such that e.g. `get_mut` can + // write through the pointer after the Rc is recovered through `from_raw`. + unsafe { &raw mut (*ptr).value } + } + + /// Constructs an `Rc` from a raw pointer in the provided allocator. + /// + /// The raw pointer must have been previously returned by a call to [`Rc::into_raw`][into_raw] with the following requirements: + /// + /// * If `U` is sized, it must have the same size and alignment as `T`. This + /// is trivially true if `U` is `T`. + /// * If `U` is unsized, its data pointer must have the same size and + /// alignment as `T`. This is trivially true if `Rc` was constructed + /// through `Rc` and then converted to `Rc` through an [unsized + /// coercion]. + /// + /// Note that if `U` or `U`'s data pointer is not `T` but has the same size + /// and alignment, this is basically like transmuting references of + /// different types. See [`mem::transmute`][transmute] for more information + /// on what restrictions apply in this case. + /// + /// The raw pointer must point to a block of memory allocated by `alloc` + /// + /// The user of `from_raw` has to make sure a specific value of `T` is only + /// dropped once. + /// + /// This function is unsafe because improper use may lead to memory unsafety, + /// even if the returned `Rc` is never accessed. + /// + /// [into_raw]: Rc::into_raw + /// [transmute]: core::mem::transmute + /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let x = Rc::new_in("hello".to_owned(), System); + /// let x_ptr = Rc::into_raw(x); + /// + /// unsafe { + /// // Convert back to an `Rc` to prevent leak. + /// let x = Rc::from_raw_in(x_ptr, System); + /// assert_eq!(&*x, "hello"); + /// + /// // Further calls to `Rc::from_raw(x_ptr)` would be memory-unsafe. + /// } + /// + /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! + /// ``` + /// + /// Convert a slice back into its original array: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let x: Rc<[u32], _> = Rc::new_in([1, 2, 3], System); + /// let x_ptr: *const [u32] = Rc::into_raw(x); + /// + /// unsafe { + /// let x: Rc<[u32; 3], _> = Rc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); + /// assert_eq!(&*x, &[1, 2, 3]); + /// } + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { + let offset = unsafe { data_offset(ptr) }; + + // Reverse the offset to find the original RcInner. + let rc_ptr = unsafe { ptr.byte_sub(offset) as *mut RcInner }; + + unsafe { Self::from_ptr_in(rc_ptr, alloc) } + } + + /// Creates a new [`Weak`] pointer to this allocation. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// let weak_five = Rc::downgrade(&five); + /// ``` + #[must_use = "this returns a new `Weak` pointer, \ + without modifying the original `Rc`"] + #[stable(feature = "rc_weak", since = "1.4.0")] + pub fn downgrade(this: &Self) -> Weak + where + A: Clone, + { + this.inner().inc_weak(); + // Make sure we do not create a dangling Weak + debug_assert!(!is_dangling(this.ptr.as_ptr())); + Weak { ptr: this.ptr, alloc: this.alloc.clone() } + } + + /// Gets the number of [`Weak`] pointers to this allocation. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// let _weak_five = Rc::downgrade(&five); + /// + /// assert_eq!(1, Rc::weak_count(&five)); + /// ``` + #[inline] + #[stable(feature = "rc_counts", since = "1.15.0")] + pub fn weak_count(this: &Self) -> usize { + this.inner().weak() - 1 + } + + /// Gets the number of strong (`Rc`) pointers to this allocation. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// let _also_five = Rc::clone(&five); + /// + /// assert_eq!(2, Rc::strong_count(&five)); + /// ``` + #[inline] + #[stable(feature = "rc_counts", since = "1.15.0")] + pub fn strong_count(this: &Self) -> usize { + this.inner().strong() + } + + /// Increments the strong reference count on the `Rc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Rc::into_raw`, the + /// associated `Rc` instance must be valid (i.e. the strong count must be at + /// least 1) for the duration of this method, and `ptr` must point to a block of memory + /// allocated by `alloc` + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let five = Rc::new_in(5, System); + /// + /// unsafe { + /// let ptr = Rc::into_raw(five); + /// Rc::increment_strong_count_in(ptr, System); + /// + /// let five = Rc::from_raw_in(ptr, System); + /// assert_eq!(2, Rc::strong_count(&five)); + /// # // Prevent leaks for Miri. + /// # Rc::decrement_strong_count_in(ptr, System); + /// } + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub unsafe fn increment_strong_count_in(ptr: *const T, alloc: A) + where + A: Clone, + { + // Retain Rc, but don't touch refcount by wrapping in ManuallyDrop + let rc = unsafe { mem::ManuallyDrop::new(Rc::::from_raw_in(ptr, alloc)) }; + // Now increase refcount, but don't drop new refcount either + let _rc_clone: mem::ManuallyDrop<_> = rc.clone(); + } + + /// Decrements the strong reference count on the `Rc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Rc::into_raw`, the + /// associated `Rc` instance must be valid (i.e. the strong count must be at + /// least 1) when invoking this method, and `ptr` must point to a block of memory + /// allocated by `alloc`. This method can be used to release the final `Rc` and backing storage, + /// but **should not** be called after the final `Rc` has been released. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let five = Rc::new_in(5, System); + /// + /// unsafe { + /// let ptr = Rc::into_raw(five); + /// Rc::increment_strong_count_in(ptr, System); + /// + /// let five = Rc::from_raw_in(ptr, System); + /// assert_eq!(2, Rc::strong_count(&five)); + /// Rc::decrement_strong_count_in(ptr, System); + /// assert_eq!(1, Rc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub unsafe fn decrement_strong_count_in(ptr: *const T, alloc: A) { + unsafe { drop(Rc::from_raw_in(ptr, alloc)) }; + } + + /// Returns `true` if there are no other `Rc` or [`Weak`] pointers to + /// this allocation. + #[inline] + fn is_unique(this: &Self) -> bool { + Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1 + } + + /// Returns a mutable reference into the given `Rc`, if there are + /// no other `Rc` or [`Weak`] pointers to the same allocation. + /// + /// Returns [`None`] otherwise, because it is not safe to + /// mutate a shared value. + /// + /// See also [`make_mut`][make_mut], which will [`clone`][clone] + /// the inner value when there are other `Rc` pointers. + /// + /// [make_mut]: Rc::make_mut + /// [clone]: Clone::clone + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let mut x = Rc::new(3); + /// *Rc::get_mut(&mut x).unwrap() = 4; + /// assert_eq!(*x, 4); + /// + /// let _y = Rc::clone(&x); + /// assert!(Rc::get_mut(&mut x).is_none()); + /// ``` + #[inline] + #[stable(feature = "rc_unique", since = "1.4.0")] + pub fn get_mut(this: &mut Self) -> Option<&mut T> { + if Rc::is_unique(this) { unsafe { Some(Rc::get_mut_unchecked(this)) } } else { None } + } + + /// Returns a mutable reference into the given `Rc`, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: Rc::get_mut + /// + /// # Safety + /// + /// If any other `Rc` or [`Weak`] pointers to the same allocation exist, then + /// they must not be dereferenced or have active borrows for the duration + /// of the returned borrow, and their inner type must be exactly the same as the + /// inner type of this Rc (including lifetimes). This is trivially the case if no + /// such pointers exist, for example immediately after `Rc::new`. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut x = Rc::new(String::new()); + /// unsafe { + /// Rc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + /// Other `Rc` pointers to the same allocation must be to the same type. + /// ```no_run + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let x: Rc = Rc::from("Hello, world!"); + /// let mut y: Rc<[u8]> = x.clone().into(); + /// unsafe { + /// // this is Undefined Behavior, because x's inner type is str, not [u8] + /// Rc::get_mut_unchecked(&mut y).fill(0xff); // 0xff is invalid in UTF-8 + /// } + /// println!("{}", &*x); // Invalid UTF-8 in a str + /// ``` + /// Other `Rc` pointers to the same allocation must be to the exact same type, including lifetimes. + /// ```no_run + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let x: Rc<&str> = Rc::new("Hello, world!"); + /// { + /// let s = String::from("Oh, no!"); + /// let mut y: Rc<&str> = x.clone().into(); + /// unsafe { + /// // this is Undefined Behavior, because x's inner type + /// // is &'long str, not &'short str + /// *Rc::get_mut_unchecked(&mut y) = &s; + /// } + /// } + /// println!("{}", &*x); // Use-after-free + /// ``` + #[inline] + #[unstable(feature = "get_mut_unchecked", issue = "63292")] + pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { + // We are careful to *not* create a reference covering the "count" fields, as + // this would conflict with accesses to the reference counts (e.g. by `Weak`). + unsafe { &mut (*this.ptr.as_ptr()).value } + } + + #[inline] + #[stable(feature = "ptr_eq", since = "1.17.0")] + /// Returns `true` if the two `Rc`s point to the same allocation in a vein similar to + /// [`ptr::eq`]. This function ignores the metadata of `dyn Trait` pointers. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// let same_five = Rc::clone(&five); + /// let other_five = Rc::new(5); + /// + /// assert!(Rc::ptr_eq(&five, &same_five)); + /// assert!(!Rc::ptr_eq(&five, &other_five)); + /// ``` + pub fn ptr_eq(this: &Self, other: &Self) -> bool { + ptr::addr_eq(this.ptr.as_ptr(), other.ptr.as_ptr()) + } +} + +#[cfg(not(no_global_oom_handling))] +impl Rc { + /// Makes a mutable reference into the given `Rc`. + /// + /// If there are other `Rc` pointers to the same allocation, then `make_mut` will + /// [`clone`] the inner value to a new allocation to ensure unique ownership. This is also + /// referred to as clone-on-write. + /// + /// However, if there are no other `Rc` pointers to this allocation, but some [`Weak`] + /// pointers, then the [`Weak`] pointers will be disassociated and the inner value will not + /// be cloned. + /// + /// See also [`get_mut`], which will fail rather than cloning the inner value + /// or disassociating [`Weak`] pointers. + /// + /// [`clone`]: Clone::clone + /// [`get_mut`]: Rc::get_mut + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let mut data = Rc::new(5); + /// + /// *Rc::make_mut(&mut data) += 1; // Won't clone anything + /// let mut other_data = Rc::clone(&data); // Won't clone inner data + /// *Rc::make_mut(&mut data) += 1; // Clones inner data + /// *Rc::make_mut(&mut data) += 1; // Won't clone anything + /// *Rc::make_mut(&mut other_data) *= 2; // Won't clone anything + /// + /// // Now `data` and `other_data` point to different allocations. + /// assert_eq!(*data, 8); + /// assert_eq!(*other_data, 12); + /// ``` + /// + /// [`Weak`] pointers will be disassociated: + /// + /// ``` + /// use std::rc::Rc; + /// + /// let mut data = Rc::new(75); + /// let weak = Rc::downgrade(&data); + /// + /// assert!(75 == *data); + /// assert!(75 == *weak.upgrade().unwrap()); + /// + /// *Rc::make_mut(&mut data) += 1; + /// + /// assert!(76 == *data); + /// assert!(weak.upgrade().is_none()); + /// ``` + #[inline] + #[stable(feature = "rc_unique", since = "1.4.0")] + pub fn make_mut(this: &mut Self) -> &mut T { + let size_of_val = size_of_val::(&**this); + + if Rc::strong_count(this) != 1 { + // Gotta clone the data, there are other Rcs. + + let this_data_ref: &T = &**this; + // `in_progress` drops the allocation if we panic before finishing initializing it. + let mut in_progress: UniqueRcUninit = + UniqueRcUninit::new(this_data_ref, this.alloc.clone()); + + // Initialize with clone of this. + let initialized_clone = unsafe { + // Clone. If the clone panics, `in_progress` will be dropped and clean up. + this_data_ref.clone_to_uninit(in_progress.data_ptr().cast()); + // Cast type of pointer, now that it is initialized. + in_progress.into_rc() + }; + + // Replace `this` with newly constructed Rc. + *this = initialized_clone; + } else if Rc::weak_count(this) != 0 { + // Can just steal the data, all that's left is Weaks + + // We don't need panic-protection like the above branch does, but we might as well + // use the same mechanism. + let mut in_progress: UniqueRcUninit = + UniqueRcUninit::new(&**this, this.alloc.clone()); + unsafe { + // Initialize `in_progress` with move of **this. + // We have to express this in terms of bytes because `T: ?Sized`; there is no + // operation that just copies a value based on its `size_of_val()`. + ptr::copy_nonoverlapping( + ptr::from_ref(&**this).cast::(), + in_progress.data_ptr().cast::(), + size_of_val, + ); + + this.inner().dec_strong(); + // Remove implicit strong-weak ref (no need to craft a fake + // Weak here -- we know other Weaks can clean up for us) + this.inner().dec_weak(); + // Replace `this` with newly constructed Rc that has the moved data. + ptr::write(this, in_progress.into_rc()); + } + } + // This unsafety is ok because we're guaranteed that the pointer + // returned is the *only* pointer that will ever be returned to T. Our + // reference count is guaranteed to be 1 at this point, and we required + // the `Rc` itself to be `mut`, so we're returning the only possible + // reference to the allocation. + unsafe { &mut this.ptr.as_mut().value } + } +} + +impl Rc { + /// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the + /// clone. + /// + /// Assuming `rc_t` is of type `Rc`, this function is functionally equivalent to + /// `(*rc_t).clone()`, but will avoid cloning the inner value where possible. + /// + /// # Examples + /// + /// ``` + /// # use std::{ptr, rc::Rc}; + /// let inner = String::from("test"); + /// let ptr = inner.as_ptr(); + /// + /// let rc = Rc::new(inner); + /// let inner = Rc::unwrap_or_clone(rc); + /// // The inner value was not cloned + /// assert!(ptr::eq(ptr, inner.as_ptr())); + /// + /// let rc = Rc::new(inner); + /// let rc2 = rc.clone(); + /// let inner = Rc::unwrap_or_clone(rc); + /// // Because there were 2 references, we had to clone the inner value. + /// assert!(!ptr::eq(ptr, inner.as_ptr())); + /// // `rc2` is the last reference, so when we unwrap it we get back + /// // the original `String`. + /// let inner = Rc::unwrap_or_clone(rc2); + /// assert!(ptr::eq(ptr, inner.as_ptr())); + /// ``` + #[inline] + #[stable(feature = "arc_unwrap_or_clone", since = "1.76.0")] + pub fn unwrap_or_clone(this: Self) -> T { + Rc::try_unwrap(this).unwrap_or_else(|rc| (*rc).clone()) + } +} + +impl Rc { + /// Attempts to downcast the `Rc` to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// use std::rc::Rc; + /// + /// fn print_if_string(value: Rc) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Rc::new(my_string)); + /// print_if_string(Rc::new(0i8)); + /// ``` + #[inline] + #[stable(feature = "rc_downcast", since = "1.29.0")] + pub fn downcast(self) -> Result, Self> { + if (*self).is::() { + unsafe { + let (ptr, alloc) = Rc::into_inner_with_allocator(self); + Ok(Rc::from_inner_in(ptr.cast(), alloc)) + } + } else { + Err(self) + } + } + + /// Downcasts the `Rc` to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// use std::rc::Rc; + /// + /// let x: Rc = Rc::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + /// + /// + /// [`downcast`]: Self::downcast + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "90850")] + pub unsafe fn downcast_unchecked(self) -> Rc { + unsafe { + let (ptr, alloc) = Rc::into_inner_with_allocator(self); + Rc::from_inner_in(ptr.cast(), alloc) + } + } +} + +impl Rc { + /// Allocates an `RcInner` with sufficient space for + /// a possibly-unsized inner value where the value has the layout provided. + /// + /// The function `mem_to_rc_inner` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `RcInner`. + #[cfg(not(no_global_oom_handling))] + unsafe fn allocate_for_layout( + value_layout: Layout, + allocate: impl FnOnce(Layout) -> Result, AllocError>, + mem_to_rc_inner: impl FnOnce(*mut u8) -> *mut RcInner, + ) -> *mut RcInner { + let layout = rc_inner_layout_for_value_layout(value_layout); + unsafe { + Rc::try_allocate_for_layout(value_layout, allocate, mem_to_rc_inner) + .unwrap_or_else(|_| handle_alloc_error(layout)) + } + } + + /// Allocates an `RcInner` with sufficient space for + /// a possibly-unsized inner value where the value has the layout provided, + /// returning an error if allocation fails. + /// + /// The function `mem_to_rc_inner` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `RcInner`. + #[inline] + unsafe fn try_allocate_for_layout( + value_layout: Layout, + allocate: impl FnOnce(Layout) -> Result, AllocError>, + mem_to_rc_inner: impl FnOnce(*mut u8) -> *mut RcInner, + ) -> Result<*mut RcInner, AllocError> { + let layout = rc_inner_layout_for_value_layout(value_layout); + + // Allocate for the layout. + let ptr = allocate(layout)?; + + // Initialize the RcInner + let inner = mem_to_rc_inner(ptr.as_non_null_ptr().as_ptr()); + unsafe { + debug_assert_eq!(Layout::for_value_raw(inner), layout); + + (&raw mut (*inner).strong).write(Cell::new(1)); + (&raw mut (*inner).weak).write(Cell::new(1)); + } + + Ok(inner) + } +} + +impl Rc { + /// Allocates an `RcInner` with sufficient space for an unsized inner value + #[cfg(not(no_global_oom_handling))] + unsafe fn allocate_for_ptr_in(ptr: *const T, alloc: &A) -> *mut RcInner { + // Allocate for the `RcInner` using the given value. + unsafe { + Rc::::allocate_for_layout( + Layout::for_value_raw(ptr), + |layout| alloc.allocate(layout), + |mem| mem.with_metadata_of(ptr as *const RcInner), + ) + } + } + + #[cfg(not(no_global_oom_handling))] + fn from_box_in(src: Box) -> Rc { + unsafe { + let value_size = size_of_val(&*src); + let ptr = Self::allocate_for_ptr_in(&*src, Box::allocator(&src)); + + // Copy value as bytes + ptr::copy_nonoverlapping( + (&raw const *src) as *const u8, + (&raw mut (*ptr).value) as *mut u8, + value_size, + ); + + // Free the allocation without dropping its contents + let (bptr, alloc) = Box::into_raw_with_allocator(src); + let src = Box::from_raw_in(bptr as *mut mem::ManuallyDrop, alloc.by_ref()); + drop(src); + + Self::from_ptr_in(ptr, alloc) + } + } +} + +impl Rc<[T]> { + /// Allocates an `RcInner<[T]>` with the given length. + #[cfg(not(no_global_oom_handling))] + unsafe fn allocate_for_slice(len: usize) -> *mut RcInner<[T]> { + unsafe { + Self::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| Global.allocate(layout), + |mem| ptr::slice_from_raw_parts_mut(mem.cast::(), len) as *mut RcInner<[T]>, + ) + } + } + + /// Copy elements from slice into newly allocated `Rc<[T]>` + /// + /// Unsafe because the caller must either take ownership or bind `T: Copy` + #[cfg(not(no_global_oom_handling))] + unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> { + unsafe { + let ptr = Self::allocate_for_slice(v.len()); + ptr::copy_nonoverlapping(v.as_ptr(), (&raw mut (*ptr).value) as *mut T, v.len()); + Self::from_ptr(ptr) + } + } + + /// Constructs an `Rc<[T]>` from an iterator known to be of a certain size. + /// + /// Behavior is undefined should the size be wrong. + #[cfg(not(no_global_oom_handling))] + unsafe fn from_iter_exact(iter: impl Iterator, len: usize) -> Rc<[T]> { + // Panic guard while cloning T elements. + // In the event of a panic, elements that have been written + // into the new RcInner will be dropped, then the memory freed. + struct Guard { + mem: NonNull, + elems: *mut T, + layout: Layout, + n_elems: usize, + } + + impl Drop for Guard { + fn drop(&mut self) { + unsafe { + let slice = from_raw_parts_mut(self.elems, self.n_elems); + ptr::drop_in_place(slice); + + Global.deallocate(self.mem, self.layout); + } + } + } + + unsafe { + let ptr = Self::allocate_for_slice(len); + + let mem = ptr as *mut _ as *mut u8; + let layout = Layout::for_value_raw(ptr); + + // Pointer to first element + let elems = (&raw mut (*ptr).value) as *mut T; + + let mut guard = Guard { mem: NonNull::new_unchecked(mem), elems, layout, n_elems: 0 }; + + for (i, item) in iter.enumerate() { + ptr::write(elems.add(i), item); + guard.n_elems += 1; + } + + // All clear. Forget the guard so it doesn't free the new RcInner. + mem::forget(guard); + + Self::from_ptr(ptr) + } + } +} + +impl Rc<[T], A> { + /// Allocates an `RcInner<[T]>` with the given length. + #[inline] + #[cfg(not(no_global_oom_handling))] + unsafe fn allocate_for_slice_in(len: usize, alloc: &A) -> *mut RcInner<[T]> { + unsafe { + Rc::<[T]>::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| alloc.allocate(layout), + |mem| ptr::slice_from_raw_parts_mut(mem.cast::(), len) as *mut RcInner<[T]>, + ) + } + } +} + +#[cfg(not(no_global_oom_handling))] +/// Specialization trait used for `From<&[T]>`. +trait RcFromSlice { + fn from_slice(slice: &[T]) -> Self; +} + +#[cfg(not(no_global_oom_handling))] +impl RcFromSlice for Rc<[T]> { + #[inline] + default fn from_slice(v: &[T]) -> Self { + unsafe { Self::from_iter_exact(v.iter().cloned(), v.len()) } + } +} + +#[cfg(not(no_global_oom_handling))] +impl RcFromSlice for Rc<[T]> { + #[inline] + fn from_slice(v: &[T]) -> Self { + unsafe { Rc::copy_from_slice(v) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for Rc { + type Target = T; + + #[inline(always)] + fn deref(&self) -> &T { + &self.inner().value + } +} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Rc {} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Weak {} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for Rc {} + +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +impl LegacyReceiver for Rc {} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Rc { + /// Drops the `Rc`. + /// + /// This will decrement the strong reference count. If the strong reference + /// count reaches zero then the only other references (if any) are + /// [`Weak`], so we `drop` the inner value. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// struct Foo; + /// + /// impl Drop for Foo { + /// fn drop(&mut self) { + /// println!("dropped!"); + /// } + /// } + /// + /// let foo = Rc::new(Foo); + /// let foo2 = Rc::clone(&foo); + /// + /// drop(foo); // Doesn't print anything + /// drop(foo2); // Prints "dropped!" + /// ``` + #[inline] + fn drop(&mut self) { + unsafe { + self.inner().dec_strong(); + if self.inner().strong() == 0 { + self.drop_slow(); + } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Rc { + /// Makes a clone of the `Rc` pointer. + /// + /// This creates another pointer to the same allocation, increasing the + /// strong reference count. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// let _ = Rc::clone(&five); + /// ``` + #[inline] + fn clone(&self) -> Self { + unsafe { + self.inner().inc_strong(); + Self::from_inner_in(self.ptr, self.alloc.clone()) + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Rc { + /// Creates a new `Rc`, with the `Default` value for `T`. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x: Rc = Default::default(); + /// assert_eq!(*x, 0); + /// ``` + #[inline] + fn default() -> Rc { + unsafe { + Self::from_inner( + Box::leak(Box::write(Box::new_uninit(), RcInner { + strong: Cell::new(1), + weak: Cell::new(1), + value: T::default(), + })) + .into(), + ) + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "1.80.0")] +impl Default for Rc { + /// Creates an empty str inside an Rc + /// + /// This may or may not share an allocation with other Rcs on the same thread. + #[inline] + fn default() -> Self { + Rc::from("") + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "1.80.0")] +impl Default for Rc<[T]> { + /// Creates an empty `[T]` inside an Rc + /// + /// This may or may not share an allocation with other Rcs on the same thread. + #[inline] + fn default() -> Self { + let arr: [T; 0] = []; + Rc::from(arr) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +trait RcEqIdent { + fn eq(&self, other: &Rc) -> bool; + fn ne(&self, other: &Rc) -> bool; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl RcEqIdent for Rc { + #[inline] + default fn eq(&self, other: &Rc) -> bool { + **self == **other + } + + #[inline] + default fn ne(&self, other: &Rc) -> bool { + **self != **other + } +} + +// Hack to allow specializing on `Eq` even though `Eq` has a method. +#[rustc_unsafe_specialization_marker] +pub(crate) trait MarkerEq: PartialEq {} + +impl MarkerEq for T {} + +/// We're doing this specialization here, and not as a more general optimization on `&T`, because it +/// would otherwise add a cost to all equality checks on refs. We assume that `Rc`s are used to +/// store large values, that are slow to clone, but also heavy to check for equality, causing this +/// cost to pay off more easily. It's also more likely to have two `Rc` clones, that point to +/// the same value, than two `&T`s. +/// +/// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive. +#[stable(feature = "rust1", since = "1.0.0")] +impl RcEqIdent for Rc { + #[inline] + fn eq(&self, other: &Rc) -> bool { + Rc::ptr_eq(self, other) || **self == **other + } + + #[inline] + fn ne(&self, other: &Rc) -> bool { + !Rc::ptr_eq(self, other) && **self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for Rc { + /// Equality for two `Rc`s. + /// + /// Two `Rc`s are equal if their inner values are equal, even if they are + /// stored in different allocation. + /// + /// If `T` also implements `Eq` (implying reflexivity of equality), + /// two `Rc`s that point to the same allocation are + /// always equal. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// assert!(five == Rc::new(5)); + /// ``` + #[inline] + fn eq(&self, other: &Rc) -> bool { + RcEqIdent::eq(self, other) + } + + /// Inequality for two `Rc`s. + /// + /// Two `Rc`s are not equal if their inner values are not equal. + /// + /// If `T` also implements `Eq` (implying reflexivity of equality), + /// two `Rc`s that point to the same allocation are + /// always equal. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// assert!(five != Rc::new(6)); + /// ``` + #[inline] + fn ne(&self, other: &Rc) -> bool { + RcEqIdent::ne(self, other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Rc {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Rc { + /// Partial comparison for two `Rc`s. + /// + /// The two are compared by calling `partial_cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// use std::cmp::Ordering; + /// + /// let five = Rc::new(5); + /// + /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&Rc::new(6))); + /// ``` + #[inline(always)] + fn partial_cmp(&self, other: &Rc) -> Option { + (**self).partial_cmp(&**other) + } + + /// Less-than comparison for two `Rc`s. + /// + /// The two are compared by calling `<` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// assert!(five < Rc::new(6)); + /// ``` + #[inline(always)] + fn lt(&self, other: &Rc) -> bool { + **self < **other + } + + /// 'Less than or equal to' comparison for two `Rc`s. + /// + /// The two are compared by calling `<=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// assert!(five <= Rc::new(5)); + /// ``` + #[inline(always)] + fn le(&self, other: &Rc) -> bool { + **self <= **other + } + + /// Greater-than comparison for two `Rc`s. + /// + /// The two are compared by calling `>` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// assert!(five > Rc::new(4)); + /// ``` + #[inline(always)] + fn gt(&self, other: &Rc) -> bool { + **self > **other + } + + /// 'Greater than or equal to' comparison for two `Rc`s. + /// + /// The two are compared by calling `>=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// assert!(five >= Rc::new(5)); + /// ``` + #[inline(always)] + fn ge(&self, other: &Rc) -> bool { + **self >= **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Rc { + /// Comparison for two `Rc`s. + /// + /// The two are compared by calling `cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// use std::cmp::Ordering; + /// + /// let five = Rc::new(5); + /// + /// assert_eq!(Ordering::Less, five.cmp(&Rc::new(6))); + /// ``` + #[inline] + fn cmp(&self, other: &Rc) -> Ordering { + (**self).cmp(&**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Rc { + fn hash(&self, state: &mut H) { + (**self).hash(state); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Rc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Rc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Pointer for Rc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&(&raw const **self), f) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "from_for_ptrs", since = "1.6.0")] +impl From for Rc { + /// Converts a generic type `T` into an `Rc` + /// + /// The conversion allocates on the heap and moves `t` + /// from the stack into it. + /// + /// # Example + /// ```rust + /// # use std::rc::Rc; + /// let x = 5; + /// let rc = Rc::new(5); + /// + /// assert_eq!(Rc::from(x), rc); + /// ``` + fn from(t: T) -> Self { + Rc::new(t) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_array", since = "1.74.0")] +impl From<[T; N]> for Rc<[T]> { + /// Converts a [`[T; N]`](prim@array) into an `Rc<[T]>`. + /// + /// The conversion moves the array into a newly allocated `Rc`. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let original: [i32; 3] = [1, 2, 3]; + /// let shared: Rc<[i32]> = Rc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: [T; N]) -> Rc<[T]> { + Rc::<[T; N]>::from(v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From<&[T]> for Rc<[T]> { + /// Allocates a reference-counted slice and fills it by cloning `v`'s items. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let original: &[i32] = &[1, 2, 3]; + /// let shared: Rc<[i32]> = Rc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: &[T]) -> Rc<[T]> { + >::from_slice(v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] +impl From<&mut [T]> for Rc<[T]> { + /// Allocates a reference-counted slice and fills it by cloning `v`'s items. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let mut original = [1, 2, 3]; + /// let original: &mut [i32] = &mut original; + /// let shared: Rc<[i32]> = Rc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: &mut [T]) -> Rc<[T]> { + Rc::from(&*v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From<&str> for Rc { + /// Allocates a reference-counted string slice and copies `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let shared: Rc = Rc::from("statue"); + /// assert_eq!("statue", &shared[..]); + /// ``` + #[inline] + fn from(v: &str) -> Rc { + let rc = Rc::<[u8]>::from(v.as_bytes()); + unsafe { Rc::from_raw(Rc::into_raw(rc) as *const str) } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] +impl From<&mut str> for Rc { + /// Allocates a reference-counted string slice and copies `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let mut original = String::from("statue"); + /// let original: &mut str = &mut original; + /// let shared: Rc = Rc::from(original); + /// assert_eq!("statue", &shared[..]); + /// ``` + #[inline] + fn from(v: &mut str) -> Rc { + Rc::from(&*v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From for Rc { + /// Allocates a reference-counted string slice and copies `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let original: String = "statue".to_owned(); + /// let shared: Rc = Rc::from(original); + /// assert_eq!("statue", &shared[..]); + /// ``` + #[inline] + fn from(v: String) -> Rc { + Rc::from(&v[..]) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From> for Rc { + /// Move a boxed object to a new, reference counted, allocation. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let original: Box = Box::new(1); + /// let shared: Rc = Rc::from(original); + /// assert_eq!(1, *shared); + /// ``` + #[inline] + fn from(v: Box) -> Rc { + Rc::from_box_in(v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From> for Rc<[T], A> { + /// Allocates a reference-counted slice and moves `v`'s items into it. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let unique: Vec = vec![1, 2, 3]; + /// let shared: Rc<[i32]> = Rc::from(unique); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: Vec) -> Rc<[T], A> { + unsafe { + let (vec_ptr, len, cap, alloc) = v.into_raw_parts_with_alloc(); + + let rc_ptr = Self::allocate_for_slice_in(len, &alloc); + ptr::copy_nonoverlapping(vec_ptr, (&raw mut (*rc_ptr).value) as *mut T, len); + + // Create a `Vec` with length 0, to deallocate the buffer + // without dropping its contents or the allocator + let _ = Vec::from_raw_parts_in(vec_ptr, 0, cap, &alloc); + + Self::from_ptr_in(rc_ptr, alloc) + } + } +} + +#[stable(feature = "shared_from_cow", since = "1.45.0")] +impl<'a, B> From> for Rc +where + B: ToOwned + ?Sized, + Rc: From<&'a B> + From, +{ + /// Creates a reference-counted pointer from a clone-on-write pointer by + /// copying its content. + /// + /// # Example + /// + /// ```rust + /// # use std::rc::Rc; + /// # use std::borrow::Cow; + /// let cow: Cow<'_, str> = Cow::Borrowed("eggplant"); + /// let shared: Rc = Rc::from(cow); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(cow: Cow<'a, B>) -> Rc { + match cow { + Cow::Borrowed(s) => Rc::from(s), + Cow::Owned(s) => Rc::from(s), + } + } +} + +#[stable(feature = "shared_from_str", since = "1.62.0")] +impl From> for Rc<[u8]> { + /// Converts a reference-counted string slice into a byte slice. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let string: Rc = Rc::from("eggplant"); + /// let bytes: Rc<[u8]> = Rc::from(string); + /// assert_eq!("eggplant".as_bytes(), bytes.as_ref()); + /// ``` + #[inline] + fn from(rc: Rc) -> Self { + // SAFETY: `str` has the same layout as `[u8]`. + unsafe { Rc::from_raw(Rc::into_raw(rc) as *const [u8]) } + } +} + +#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] +impl TryFrom> for Rc<[T; N], A> { + type Error = Rc<[T], A>; + + fn try_from(boxed_slice: Rc<[T], A>) -> Result { + if boxed_slice.len() == N { + let (ptr, alloc) = Rc::into_inner_with_allocator(boxed_slice); + Ok(unsafe { Rc::from_inner_in(ptr.cast(), alloc) }) + } else { + Err(boxed_slice) + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_iter", since = "1.37.0")] +impl FromIterator for Rc<[T]> { + /// Takes each element in the `Iterator` and collects it into an `Rc<[T]>`. + /// + /// # Performance characteristics + /// + /// ## The general case + /// + /// In the general case, collecting into `Rc<[T]>` is done by first + /// collecting into a `Vec`. That is, when writing the following: + /// + /// ```rust + /// # use std::rc::Rc; + /// let evens: Rc<[u8]> = (0..10).filter(|&x| x % 2 == 0).collect(); + /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); + /// ``` + /// + /// this behaves as if we wrote: + /// + /// ```rust + /// # use std::rc::Rc; + /// let evens: Rc<[u8]> = (0..10).filter(|&x| x % 2 == 0) + /// .collect::>() // The first set of allocations happens here. + /// .into(); // A second allocation for `Rc<[T]>` happens here. + /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); + /// ``` + /// + /// This will allocate as many times as needed for constructing the `Vec` + /// and then it will allocate once for turning the `Vec` into the `Rc<[T]>`. + /// + /// ## Iterators of known length + /// + /// When your `Iterator` implements `TrustedLen` and is of an exact size, + /// a single allocation will be made for the `Rc<[T]>`. For example: + /// + /// ```rust + /// # use std::rc::Rc; + /// let evens: Rc<[u8]> = (0..10).collect(); // Just a single allocation happens here. + /// # assert_eq!(&*evens, &*(0..10).collect::>()); + /// ``` + fn from_iter>(iter: I) -> Self { + ToRcSlice::to_rc_slice(iter.into_iter()) + } +} + +/// Specialization trait used for collecting into `Rc<[T]>`. +#[cfg(not(no_global_oom_handling))] +trait ToRcSlice: Iterator + Sized { + fn to_rc_slice(self) -> Rc<[T]>; +} + +#[cfg(not(no_global_oom_handling))] +impl> ToRcSlice for I { + default fn to_rc_slice(self) -> Rc<[T]> { + self.collect::>().into() + } +} + +#[cfg(not(no_global_oom_handling))] +impl> ToRcSlice for I { + fn to_rc_slice(self) -> Rc<[T]> { + // This is the case for a `TrustedLen` iterator. + let (low, high) = self.size_hint(); + if let Some(high) = high { + debug_assert_eq!( + low, + high, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + + unsafe { + // SAFETY: We need to ensure that the iterator has an exact length and we have. + Rc::from_iter_exact(self, low) + } + } else { + // TrustedLen contract guarantees that `upper_bound == None` implies an iterator + // length exceeding `usize::MAX`. + // The default implementation would collect into a vec which would panic. + // Thus we panic here immediately without invoking `Vec` code. + panic!("capacity overflow"); + } + } +} + +/// `Weak` is a version of [`Rc`] that holds a non-owning reference to the +/// managed allocation. +/// +/// The allocation is accessed by calling [`upgrade`] on the `Weak` +/// pointer, which returns an [Option]<[Rc]\>. +/// +/// Since a `Weak` reference does not count towards ownership, it will not +/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no +/// guarantees about the value still being present. Thus it may return [`None`] +/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation +/// itself (the backing store) from being deallocated. +/// +/// A `Weak` pointer is useful for keeping a temporary reference to the allocation +/// managed by [`Rc`] without preventing its inner value from being dropped. It is also used to +/// prevent circular references between [`Rc`] pointers, since mutual owning references +/// would never allow either [`Rc`] to be dropped. For example, a tree could +/// have strong [`Rc`] pointers from parent nodes to children, and `Weak` +/// pointers from children back to their parents. +/// +/// The typical way to obtain a `Weak` pointer is to call [`Rc::downgrade`]. +/// +/// [`upgrade`]: Weak::upgrade +#[stable(feature = "rc_weak", since = "1.4.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "RcWeak")] +pub struct Weak< + T: ?Sized, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + // This is a `NonNull` to allow optimizing the size of this type in enums, + // but it is not necessarily a valid pointer. + // `Weak::new` sets this to `usize::MAX` so that it doesn’t need + // to allocate space on the heap. That's not a value a real pointer + // will ever have because RcInner has alignment at least 2. + // This is only possible when `T: Sized`; unsized `T` never dangle. + ptr: NonNull>, + alloc: A, +} + +#[stable(feature = "rc_weak", since = "1.4.0")] +impl !Send for Weak {} +#[stable(feature = "rc_weak", since = "1.4.0")] +impl !Sync for Weak {} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U: ?Sized, A: Allocator> CoerceUnsized> for Weak {} + +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for Weak {} + +impl Weak { + /// Constructs a new `Weak`, without allocating any memory. + /// Calling [`upgrade`] on the return value always gives [`None`]. + /// + /// [`upgrade`]: Weak::upgrade + /// + /// # Examples + /// + /// ``` + /// use std::rc::Weak; + /// + /// let empty: Weak = Weak::new(); + /// assert!(empty.upgrade().is_none()); + /// ``` + #[inline] + #[stable(feature = "downgraded_weak", since = "1.10.0")] + #[rustc_const_stable(feature = "const_weak_new", since = "1.73.0")] + #[must_use] + pub const fn new() -> Weak { + Weak { + ptr: unsafe { + NonNull::new_unchecked(ptr::without_provenance_mut::>(usize::MAX)) + }, + alloc: Global, + } + } +} + +impl Weak { + /// Constructs a new `Weak`, without allocating any memory, technically in the provided + /// allocator. + /// Calling [`upgrade`] on the return value always gives [`None`]. + /// + /// [`upgrade`]: Weak::upgrade + /// + /// # Examples + /// + /// ``` + /// use std::rc::Weak; + /// + /// let empty: Weak = Weak::new(); + /// assert!(empty.upgrade().is_none()); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn new_in(alloc: A) -> Weak { + Weak { + ptr: unsafe { + NonNull::new_unchecked(ptr::without_provenance_mut::>(usize::MAX)) + }, + alloc, + } + } +} + +pub(crate) fn is_dangling(ptr: *const T) -> bool { + (ptr.cast::<()>()).addr() == usize::MAX +} + +/// Helper type to allow accessing the reference counts without +/// making any assertions about the data field. +struct WeakInner<'a> { + weak: &'a Cell, + strong: &'a Cell, +} + +impl Weak { + /// Converts a raw pointer previously created by [`into_raw`] back into `Weak`. + /// + /// This can be used to safely get a strong reference (by calling [`upgrade`] + /// later) or to deallocate the weak count by dropping the `Weak`. + /// + /// It takes ownership of one weak reference (with the exception of pointers created by [`new`], + /// as these don't own anything; the method still works on them). + /// + /// # Safety + /// + /// The pointer must have originated from the [`into_raw`] and must still own its potential + /// weak reference, and `ptr` must point to a block of memory allocated by the global allocator. + /// + /// It is allowed for the strong count to be 0 at the time of calling this. Nevertheless, this + /// takes ownership of one weak reference currently represented as a raw pointer (the weak + /// count is not modified by this operation) and therefore it must be paired with a previous + /// call to [`into_raw`]. + /// + /// # Examples + /// + /// ``` + /// use std::rc::{Rc, Weak}; + /// + /// let strong = Rc::new("hello".to_owned()); + /// + /// let raw_1 = Rc::downgrade(&strong).into_raw(); + /// let raw_2 = Rc::downgrade(&strong).into_raw(); + /// + /// assert_eq!(2, Rc::weak_count(&strong)); + /// + /// assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap()); + /// assert_eq!(1, Rc::weak_count(&strong)); + /// + /// drop(strong); + /// + /// // Decrement the last weak count. + /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); + /// ``` + /// + /// [`into_raw`]: Weak::into_raw + /// [`upgrade`]: Weak::upgrade + /// [`new`]: Weak::new + #[inline] + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + unsafe { Self::from_raw_in(ptr, Global) } + } +} + +impl Weak { + /// Returns a reference to the underlying allocator. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(&self) -> &A { + &self.alloc + } + + /// Returns a raw pointer to the object `T` pointed to by this `Weak`. + /// + /// The pointer is valid only if there are some strong references. The pointer may be dangling, + /// unaligned or even [`null`] otherwise. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// use std::ptr; + /// + /// let strong = Rc::new("hello".to_owned()); + /// let weak = Rc::downgrade(&strong); + /// // Both point to the same object + /// assert!(ptr::eq(&*strong, weak.as_ptr())); + /// // The strong here keeps it alive, so we can still access the object. + /// assert_eq!("hello", unsafe { &*weak.as_ptr() }); + /// + /// drop(strong); + /// // But not any more. We can do weak.as_ptr(), but accessing the pointer would lead to + /// // undefined behavior. + /// // assert_eq!("hello", unsafe { &*weak.as_ptr() }); + /// ``` + /// + /// [`null`]: ptr::null + #[must_use] + #[stable(feature = "rc_as_ptr", since = "1.45.0")] + pub fn as_ptr(&self) -> *const T { + let ptr: *mut RcInner = NonNull::as_ptr(self.ptr); + + if is_dangling(ptr) { + // If the pointer is dangling, we return the sentinel directly. This cannot be + // a valid payload address, as the payload is at least as aligned as RcInner (usize). + ptr as *const T + } else { + // SAFETY: if is_dangling returns false, then the pointer is dereferenceable. + // The payload may be dropped at this point, and we have to maintain provenance, + // so use raw pointer manipulation. + unsafe { &raw mut (*ptr).value } + } + } + + /// Consumes the `Weak` and turns it into a raw pointer. + /// + /// This converts the weak pointer into a raw pointer, while still preserving the ownership of + /// one weak reference (the weak count is not modified by this operation). It can be turned + /// back into the `Weak` with [`from_raw`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_ptr`] apply. + /// + /// # Examples + /// + /// ``` + /// use std::rc::{Rc, Weak}; + /// + /// let strong = Rc::new("hello".to_owned()); + /// let weak = Rc::downgrade(&strong); + /// let raw = weak.into_raw(); + /// + /// assert_eq!(1, Rc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw(raw) }); + /// assert_eq!(0, Rc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw`]: Weak::from_raw + /// [`as_ptr`]: Weak::as_ptr + #[must_use = "losing the pointer will leak memory"] + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub fn into_raw(self) -> *const T { + mem::ManuallyDrop::new(self).as_ptr() + } + + /// Consumes the `Weak`, returning the wrapped pointer and allocator. + /// + /// This converts the weak pointer into a raw pointer, while still preserving the ownership of + /// one weak reference (the weak count is not modified by this operation). It can be turned + /// back into the `Weak` with [`from_raw_in`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_ptr`] apply. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::rc::{Rc, Weak}; + /// use std::alloc::System; + /// + /// let strong = Rc::new_in("hello".to_owned(), System); + /// let weak = Rc::downgrade(&strong); + /// let (raw, alloc) = weak.into_raw_with_allocator(); + /// + /// assert_eq!(1, Rc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw_in(raw, alloc) }); + /// assert_eq!(0, Rc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw_in`]: Weak::from_raw_in + /// [`as_ptr`]: Weak::as_ptr + #[must_use = "losing the pointer will leak memory"] + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn into_raw_with_allocator(self) -> (*const T, A) { + let this = mem::ManuallyDrop::new(self); + let result = this.as_ptr(); + // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + let alloc = unsafe { ptr::read(&this.alloc) }; + (result, alloc) + } + + /// Converts a raw pointer previously created by [`into_raw`] back into `Weak`. + /// + /// This can be used to safely get a strong reference (by calling [`upgrade`] + /// later) or to deallocate the weak count by dropping the `Weak`. + /// + /// It takes ownership of one weak reference (with the exception of pointers created by [`new`], + /// as these don't own anything; the method still works on them). + /// + /// # Safety + /// + /// The pointer must have originated from the [`into_raw`] and must still own its potential + /// weak reference, and `ptr` must point to a block of memory allocated by `alloc`. + /// + /// It is allowed for the strong count to be 0 at the time of calling this. Nevertheless, this + /// takes ownership of one weak reference currently represented as a raw pointer (the weak + /// count is not modified by this operation) and therefore it must be paired with a previous + /// call to [`into_raw`]. + /// + /// # Examples + /// + /// ``` + /// use std::rc::{Rc, Weak}; + /// + /// let strong = Rc::new("hello".to_owned()); + /// + /// let raw_1 = Rc::downgrade(&strong).into_raw(); + /// let raw_2 = Rc::downgrade(&strong).into_raw(); + /// + /// assert_eq!(2, Rc::weak_count(&strong)); + /// + /// assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap()); + /// assert_eq!(1, Rc::weak_count(&strong)); + /// + /// drop(strong); + /// + /// // Decrement the last weak count. + /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); + /// ``` + /// + /// [`into_raw`]: Weak::into_raw + /// [`upgrade`]: Weak::upgrade + /// [`new`]: Weak::new + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { + // See Weak::as_ptr for context on how the input pointer is derived. + + let ptr = if is_dangling(ptr) { + // This is a dangling Weak. + ptr as *mut RcInner + } else { + // Otherwise, we're guaranteed the pointer came from a nondangling Weak. + // SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T. + let offset = unsafe { data_offset(ptr) }; + // Thus, we reverse the offset to get the whole RcInner. + // SAFETY: the pointer originated from a Weak, so this offset is safe. + unsafe { ptr.byte_sub(offset) as *mut RcInner } + }; + + // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. + Weak { ptr: unsafe { NonNull::new_unchecked(ptr) }, alloc } + } + + /// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying + /// dropping of the inner value if successful. + /// + /// Returns [`None`] if the inner value has since been dropped. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// let weak_five = Rc::downgrade(&five); + /// + /// let strong_five: Option> = weak_five.upgrade(); + /// assert!(strong_five.is_some()); + /// + /// // Destroy all strong pointers. + /// drop(strong_five); + /// drop(five); + /// + /// assert!(weak_five.upgrade().is_none()); + /// ``` + #[must_use = "this returns a new `Rc`, \ + without modifying the original weak pointer"] + #[stable(feature = "rc_weak", since = "1.4.0")] + pub fn upgrade(&self) -> Option> + where + A: Clone, + { + let inner = self.inner()?; + + if inner.strong() == 0 { + None + } else { + unsafe { + inner.inc_strong(); + Some(Rc::from_inner_in(self.ptr, self.alloc.clone())) + } + } + } + + /// Gets the number of strong (`Rc`) pointers pointing to this allocation. + /// + /// If `self` was created using [`Weak::new`], this will return 0. + #[must_use] + #[stable(feature = "weak_counts", since = "1.41.0")] + pub fn strong_count(&self) -> usize { + if let Some(inner) = self.inner() { inner.strong() } else { 0 } + } + + /// Gets the number of `Weak` pointers pointing to this allocation. + /// + /// If no strong pointers remain, this will return zero. + #[must_use] + #[stable(feature = "weak_counts", since = "1.41.0")] + pub fn weak_count(&self) -> usize { + if let Some(inner) = self.inner() { + if inner.strong() > 0 { + inner.weak() - 1 // subtract the implicit weak ptr + } else { + 0 + } + } else { + 0 + } + } + + /// Returns `None` when the pointer is dangling and there is no allocated `RcInner`, + /// (i.e., when this `Weak` was created by `Weak::new`). + #[inline] + fn inner(&self) -> Option> { + if is_dangling(self.ptr.as_ptr()) { + None + } else { + // We are careful to *not* create a reference covering the "data" field, as + // the field may be mutated concurrently (for example, if the last `Rc` + // is dropped, the data field will be dropped in-place). + Some(unsafe { + let ptr = self.ptr.as_ptr(); + WeakInner { strong: &(*ptr).strong, weak: &(*ptr).weak } + }) + } + } + + /// Returns `true` if the two `Weak`s point to the same allocation similar to [`ptr::eq`], or if + /// both don't point to any allocation (because they were created with `Weak::new()`). However, + /// this function ignores the metadata of `dyn Trait` pointers. + /// + /// # Notes + /// + /// Since this compares pointers it means that `Weak::new()` will equal each + /// other, even though they don't point to any allocation. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let first_rc = Rc::new(5); + /// let first = Rc::downgrade(&first_rc); + /// let second = Rc::downgrade(&first_rc); + /// + /// assert!(first.ptr_eq(&second)); + /// + /// let third_rc = Rc::new(5); + /// let third = Rc::downgrade(&third_rc); + /// + /// assert!(!first.ptr_eq(&third)); + /// ``` + /// + /// Comparing `Weak::new`. + /// + /// ``` + /// use std::rc::{Rc, Weak}; + /// + /// let first = Weak::new(); + /// let second = Weak::new(); + /// assert!(first.ptr_eq(&second)); + /// + /// let third_rc = Rc::new(()); + /// let third = Rc::downgrade(&third_rc); + /// assert!(!first.ptr_eq(&third)); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "weak_ptr_eq", since = "1.39.0")] + pub fn ptr_eq(&self, other: &Self) -> bool { + ptr::addr_eq(self.ptr.as_ptr(), other.ptr.as_ptr()) + } +} + +#[stable(feature = "rc_weak", since = "1.4.0")] +unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Weak { + /// Drops the `Weak` pointer. + /// + /// # Examples + /// + /// ``` + /// use std::rc::{Rc, Weak}; + /// + /// struct Foo; + /// + /// impl Drop for Foo { + /// fn drop(&mut self) { + /// println!("dropped!"); + /// } + /// } + /// + /// let foo = Rc::new(Foo); + /// let weak_foo = Rc::downgrade(&foo); + /// let other_weak_foo = Weak::clone(&weak_foo); + /// + /// drop(weak_foo); // Doesn't print anything + /// drop(foo); // Prints "dropped!" + /// + /// assert!(other_weak_foo.upgrade().is_none()); + /// ``` + fn drop(&mut self) { + let inner = if let Some(inner) = self.inner() { inner } else { return }; + + inner.dec_weak(); + // the weak count starts at 1, and will only go to zero if all + // the strong pointers have disappeared. + if inner.weak() == 0 { + unsafe { + self.alloc.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr())); + } + } + } +} + +#[stable(feature = "rc_weak", since = "1.4.0")] +impl Clone for Weak { + /// Makes a clone of the `Weak` pointer that points to the same allocation. + /// + /// # Examples + /// + /// ``` + /// use std::rc::{Rc, Weak}; + /// + /// let weak_five = Rc::downgrade(&Rc::new(5)); + /// + /// let _ = Weak::clone(&weak_five); + /// ``` + #[inline] + fn clone(&self) -> Weak { + if let Some(inner) = self.inner() { + inner.inc_weak() + } + Weak { ptr: self.ptr, alloc: self.alloc.clone() } + } +} + +#[stable(feature = "rc_weak", since = "1.4.0")] +impl fmt::Debug for Weak { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(Weak)") + } +} + +#[stable(feature = "downgraded_weak", since = "1.10.0")] +impl Default for Weak { + /// Constructs a new `Weak`, without allocating any memory. + /// Calling [`upgrade`] on the return value always gives [`None`]. + /// + /// [`upgrade`]: Weak::upgrade + /// + /// # Examples + /// + /// ``` + /// use std::rc::Weak; + /// + /// let empty: Weak = Default::default(); + /// assert!(empty.upgrade().is_none()); + /// ``` + fn default() -> Weak { + Weak::new() + } +} + +// NOTE: We checked_add here to deal with mem::forget safely. In particular +// if you mem::forget Rcs (or Weaks), the ref-count can overflow, and then +// you can free the allocation while outstanding Rcs (or Weaks) exist. +// We abort because this is such a degenerate scenario that we don't care about +// what happens -- no real program should ever experience this. +// +// This should have negligible overhead since you don't actually need to +// clone these much in Rust thanks to ownership and move-semantics. + +#[doc(hidden)] +trait RcInnerPtr { + fn weak_ref(&self) -> &Cell; + fn strong_ref(&self) -> &Cell; + + #[inline] + fn strong(&self) -> usize { + self.strong_ref().get() + } + + #[inline] + fn inc_strong(&self) { + let strong = self.strong(); + + // We insert an `assume` here to hint LLVM at an otherwise + // missed optimization. + // SAFETY: The reference count will never be zero when this is + // called. + unsafe { + hint::assert_unchecked(strong != 0); + } + + let strong = strong.wrapping_add(1); + self.strong_ref().set(strong); + + // We want to abort on overflow instead of dropping the value. + // Checking for overflow after the store instead of before + // allows for slightly better code generation. + if core::intrinsics::unlikely(strong == 0) { + abort(); + } + } + + #[inline] + fn dec_strong(&self) { + self.strong_ref().set(self.strong() - 1); + } + + #[inline] + fn weak(&self) -> usize { + self.weak_ref().get() + } + + #[inline] + fn inc_weak(&self) { + let weak = self.weak(); + + // We insert an `assume` here to hint LLVM at an otherwise + // missed optimization. + // SAFETY: The reference count will never be zero when this is + // called. + unsafe { + hint::assert_unchecked(weak != 0); + } + + let weak = weak.wrapping_add(1); + self.weak_ref().set(weak); + + // We want to abort on overflow instead of dropping the value. + // Checking for overflow after the store instead of before + // allows for slightly better code generation. + if core::intrinsics::unlikely(weak == 0) { + abort(); + } + } + + #[inline] + fn dec_weak(&self) { + self.weak_ref().set(self.weak() - 1); + } +} + +impl RcInnerPtr for RcInner { + #[inline(always)] + fn weak_ref(&self) -> &Cell { + &self.weak + } + + #[inline(always)] + fn strong_ref(&self) -> &Cell { + &self.strong + } +} + +impl<'a> RcInnerPtr for WeakInner<'a> { + #[inline(always)] + fn weak_ref(&self) -> &Cell { + self.weak + } + + #[inline(always)] + fn strong_ref(&self) -> &Cell { + self.strong + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl borrow::Borrow for Rc { + fn borrow(&self) -> &T { + &**self + } +} + +#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] +impl AsRef for Rc { + fn as_ref(&self) -> &T { + &**self + } +} + +#[stable(feature = "pin", since = "1.33.0")] +impl Unpin for Rc {} + +/// Gets the offset within an `RcInner` for the payload behind a pointer. +/// +/// # Safety +/// +/// The pointer must point to (and have valid metadata for) a previously +/// valid instance of T, but the T is allowed to be dropped. +unsafe fn data_offset(ptr: *const T) -> usize { + // Align the unsized value to the end of the RcInner. + // Because RcInner is repr(C), it will always be the last field in memory. + // SAFETY: since the only unsized types possible are slices, trait objects, + // and extern types, the input safety requirement is currently enough to + // satisfy the requirements of align_of_val_raw; this is an implementation + // detail of the language that must not be relied upon outside of std. + unsafe { data_offset_align(align_of_val_raw(ptr)) } +} + +#[inline] +fn data_offset_align(align: usize) -> usize { + let layout = Layout::new::>(); + layout.size() + layout.padding_needed_for(align) +} + +/// A uniquely owned [`Rc`]. +/// +/// This represents an `Rc` that is known to be uniquely owned -- that is, have exactly one strong +/// reference. Multiple weak pointers can be created, but attempts to upgrade those to strong +/// references will fail unless the `UniqueRc` they point to has been converted into a regular `Rc`. +/// +/// Because they are uniquely owned, the contents of a `UniqueRc` can be freely mutated. A common +/// use case is to have an object be mutable during its initialization phase but then have it become +/// immutable and converted to a normal `Rc`. +/// +/// This can be used as a flexible way to create cyclic data structures, as in the example below. +/// +/// ``` +/// #![feature(unique_rc_arc)] +/// use std::rc::{Rc, Weak, UniqueRc}; +/// +/// struct Gadget { +/// #[allow(dead_code)] +/// me: Weak, +/// } +/// +/// fn create_gadget() -> Option> { +/// let mut rc = UniqueRc::new(Gadget { +/// me: Weak::new(), +/// }); +/// rc.me = UniqueRc::downgrade(&rc); +/// Some(UniqueRc::into_rc(rc)) +/// } +/// +/// create_gadget().unwrap(); +/// ``` +/// +/// An advantage of using `UniqueRc` over [`Rc::new_cyclic`] to build cyclic data structures is that +/// [`Rc::new_cyclic`]'s `data_fn` parameter cannot be async or return a [`Result`]. As shown in the +/// previous example, `UniqueRc` allows for more flexibility in the construction of cyclic data, +/// including fallible or async constructors. +#[unstable(feature = "unique_rc_arc", issue = "112566")] +#[derive(Debug)] +pub struct UniqueRc< + T: ?Sized, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + ptr: NonNull>, + phantom: PhantomData>, + alloc: A, +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl, U: ?Sized, A: Allocator> CoerceUnsized> + for UniqueRc +{ +} + +// Depends on A = Global +impl UniqueRc { + /// Creates a new `UniqueRc`. + /// + /// Weak references to this `UniqueRc` can be created with [`UniqueRc::downgrade`]. Upgrading + /// these weak references will fail before the `UniqueRc` has been converted into an [`Rc`]. + /// After converting the `UniqueRc` into an [`Rc`], any weak references created beforehand will + /// point to the new [`Rc`]. + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "unique_rc_arc", issue = "112566")] + pub fn new(value: T) -> Self { + Self::new_in(value, Global) + } +} + +impl UniqueRc { + /// Creates a new `UniqueRc` in the provided allocator. + /// + /// Weak references to this `UniqueRc` can be created with [`UniqueRc::downgrade`]. Upgrading + /// these weak references will fail before the `UniqueRc` has been converted into an [`Rc`]. + /// After converting the `UniqueRc` into an [`Rc`], any weak references created beforehand will + /// point to the new [`Rc`]. + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "unique_rc_arc", issue = "112566")] + pub fn new_in(value: T, alloc: A) -> Self { + let (ptr, alloc) = Box::into_unique(Box::new_in( + RcInner { + strong: Cell::new(0), + // keep one weak reference so if all the weak pointers that are created are dropped + // the UniqueRc still stays valid. + weak: Cell::new(1), + value, + }, + alloc, + )); + Self { ptr: ptr.into(), phantom: PhantomData, alloc } + } +} + +impl UniqueRc { + /// Converts the `UniqueRc` into a regular [`Rc`]. + /// + /// This consumes the `UniqueRc` and returns a regular [`Rc`] that contains the `value` that + /// is passed to `into_rc`. + /// + /// Any weak references created before this method is called can now be upgraded to strong + /// references. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + pub fn into_rc(this: Self) -> Rc { + let mut this = ManuallyDrop::new(this); + + // Move the allocator out. + // SAFETY: `this.alloc` will not be accessed again, nor dropped because it is in + // a `ManuallyDrop`. + let alloc: A = unsafe { ptr::read(&this.alloc) }; + + // SAFETY: This pointer was allocated at creation time so we know it is valid. + unsafe { + // Convert our weak reference into a strong reference + this.ptr.as_mut().strong.set(1); + Rc::from_inner_in(this.ptr, alloc) + } + } +} + +impl UniqueRc { + /// Creates a new weak reference to the `UniqueRc`. + /// + /// Attempting to upgrade this weak reference will fail before the `UniqueRc` has been converted + /// to a [`Rc`] using [`UniqueRc::into_rc`]. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + pub fn downgrade(this: &Self) -> Weak { + // SAFETY: This pointer was allocated at creation time and we guarantee that we only have + // one strong reference before converting to a regular Rc. + unsafe { + this.ptr.as_ref().inc_weak(); + } + Weak { ptr: this.ptr, alloc: this.alloc.clone() } + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl Deref for UniqueRc { + type Target = T; + + fn deref(&self) -> &T { + // SAFETY: This pointer was allocated at creation time so we know it is valid. + unsafe { &self.ptr.as_ref().value } + } +} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for UniqueRc {} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl DerefMut for UniqueRc { + fn deref_mut(&mut self) -> &mut T { + // SAFETY: This pointer was allocated at creation time so we know it is valid. We know we + // have unique ownership and therefore it's safe to make a mutable reference because + // `UniqueRc` owns the only strong reference to itself. + unsafe { &mut (*self.ptr.as_ptr()).value } + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueRc { + fn drop(&mut self) { + unsafe { + // destroy the contained object + drop_in_place(DerefMut::deref_mut(self)); + + // remove the implicit "strong weak" pointer now that we've destroyed the contents. + self.ptr.as_ref().dec_weak(); + + if self.ptr.as_ref().weak() == 0 { + self.alloc.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr())); + } + } + } +} + +/// A unique owning pointer to a [`RcInner`] **that does not imply the contents are initialized,** +/// but will deallocate it (without dropping the value) when dropped. +/// +/// This is a helper for [`Rc::make_mut()`] to ensure correct cleanup on panic. +/// It is nearly a duplicate of `UniqueRc, A>` except that it allows `T: !Sized`, +/// which `MaybeUninit` does not. +#[cfg(not(no_global_oom_handling))] +struct UniqueRcUninit { + ptr: NonNull>, + layout_for_value: Layout, + alloc: Option, +} + +#[cfg(not(no_global_oom_handling))] +impl UniqueRcUninit { + /// Allocates a RcInner with layout suitable to contain `for_value` or a clone of it. + fn new(for_value: &T, alloc: A) -> UniqueRcUninit { + let layout = Layout::for_value(for_value); + let ptr = unsafe { + Rc::allocate_for_layout( + layout, + |layout_for_rc_inner| alloc.allocate(layout_for_rc_inner), + |mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const RcInner), + ) + }; + Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) } + } + + /// Returns the pointer to be written into to initialize the [`Rc`]. + fn data_ptr(&mut self) -> *mut T { + let offset = data_offset_align(self.layout_for_value.align()); + unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T } + } + + /// Upgrade this into a normal [`Rc`]. + /// + /// # Safety + /// + /// The data must have been initialized (by writing to [`Self::data_ptr()`]). + unsafe fn into_rc(self) -> Rc { + let mut this = ManuallyDrop::new(self); + let ptr = this.ptr; + let alloc = this.alloc.take().unwrap(); + + // SAFETY: The pointer is valid as per `UniqueRcUninit::new`, and the caller is responsible + // for having initialized the data. + unsafe { Rc::from_ptr_in(ptr.as_ptr(), alloc) } + } +} + +#[cfg(not(no_global_oom_handling))] +impl Drop for UniqueRcUninit { + fn drop(&mut self) { + // SAFETY: + // * new() produced a pointer safe to deallocate. + // * We own the pointer unless into_rc() was called, which forgets us. + unsafe { + self.alloc.take().unwrap().deallocate( + self.ptr.cast(), + rc_inner_layout_for_value_layout(self.layout_for_value), + ); + } + } +} diff --git a/CoqOfRust/alloc/rc/tests.rs b/CoqOfRust/alloc/rc/tests.rs new file mode 100644 index 000000000..2210a7c24 --- /dev/null +++ b/CoqOfRust/alloc/rc/tests.rs @@ -0,0 +1,664 @@ +use std::cell::RefCell; +use std::clone::Clone; + +use super::*; + +#[test] +fn test_clone() { + let x = Rc::new(RefCell::new(5)); + let y = x.clone(); + *x.borrow_mut() = 20; + assert_eq!(*y.borrow(), 20); +} + +#[test] +fn test_simple() { + let x = Rc::new(5); + assert_eq!(*x, 5); +} + +#[test] +fn test_simple_clone() { + let x = Rc::new(5); + let y = x.clone(); + assert_eq!(*x, 5); + assert_eq!(*y, 5); +} + +#[test] +fn test_destructor() { + let x: Rc> = Rc::new(Box::new(5)); + assert_eq!(**x, 5); +} + +#[test] +fn test_live() { + let x = Rc::new(5); + let y = Rc::downgrade(&x); + assert!(y.upgrade().is_some()); +} + +#[test] +fn test_dead() { + let x = Rc::new(5); + let y = Rc::downgrade(&x); + drop(x); + assert!(y.upgrade().is_none()); +} + +#[test] +fn weak_self_cyclic() { + struct Cycle { + x: RefCell>>, + } + + let a = Rc::new(Cycle { x: RefCell::new(None) }); + let b = Rc::downgrade(&a.clone()); + *a.x.borrow_mut() = Some(b); + + // hopefully we don't double-free (or leak)... +} + +#[test] +fn is_unique() { + let x = Rc::new(3); + assert!(Rc::is_unique(&x)); + let y = x.clone(); + assert!(!Rc::is_unique(&x)); + drop(y); + assert!(Rc::is_unique(&x)); + let w = Rc::downgrade(&x); + assert!(!Rc::is_unique(&x)); + drop(w); + assert!(Rc::is_unique(&x)); +} + +#[test] +fn test_strong_count() { + let a = Rc::new(0); + assert!(Rc::strong_count(&a) == 1); + let w = Rc::downgrade(&a); + assert!(Rc::strong_count(&a) == 1); + let b = w.upgrade().expect("upgrade of live rc failed"); + assert!(Rc::strong_count(&b) == 2); + assert!(Rc::strong_count(&a) == 2); + drop(w); + drop(a); + assert!(Rc::strong_count(&b) == 1); + let c = b.clone(); + assert!(Rc::strong_count(&b) == 2); + assert!(Rc::strong_count(&c) == 2); +} + +#[test] +fn test_weak_count() { + let a = Rc::new(0); + assert!(Rc::strong_count(&a) == 1); + assert!(Rc::weak_count(&a) == 0); + let w = Rc::downgrade(&a); + assert!(Rc::strong_count(&a) == 1); + assert!(Rc::weak_count(&a) == 1); + drop(w); + assert!(Rc::strong_count(&a) == 1); + assert!(Rc::weak_count(&a) == 0); + let c = a.clone(); + assert!(Rc::strong_count(&a) == 2); + assert!(Rc::weak_count(&a) == 0); + drop(c); +} + +#[test] +fn weak_counts() { + assert_eq!(Weak::weak_count(&Weak::::new()), 0); + assert_eq!(Weak::strong_count(&Weak::::new()), 0); + + let a = Rc::new(0); + let w = Rc::downgrade(&a); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), 1); + let w2 = w.clone(); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), 2); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), 2); + drop(w); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), 1); + let a2 = a.clone(); + assert_eq!(Weak::strong_count(&w2), 2); + assert_eq!(Weak::weak_count(&w2), 1); + drop(a2); + drop(a); + assert_eq!(Weak::strong_count(&w2), 0); + assert_eq!(Weak::weak_count(&w2), 0); + drop(w2); +} + +#[test] +fn try_unwrap() { + let x = Rc::new(3); + assert_eq!(Rc::try_unwrap(x), Ok(3)); + let x = Rc::new(4); + let _y = x.clone(); + assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4))); + let x = Rc::new(5); + let _w = Rc::downgrade(&x); + assert_eq!(Rc::try_unwrap(x), Ok(5)); +} + +#[test] +fn into_inner() { + let x = Rc::new(3); + assert_eq!(Rc::into_inner(x), Some(3)); + + let x = Rc::new(4); + let y = Rc::clone(&x); + assert_eq!(Rc::into_inner(x), None); + assert_eq!(Rc::into_inner(y), Some(4)); + + let x = Rc::new(5); + let _w = Rc::downgrade(&x); + assert_eq!(Rc::into_inner(x), Some(5)); +} + +#[test] +fn into_from_raw() { + let x = Rc::new(Box::new("hello")); + let y = x.clone(); + + let x_ptr = Rc::into_raw(x); + drop(y); + unsafe { + assert_eq!(**x_ptr, "hello"); + + let x = Rc::from_raw(x_ptr); + assert_eq!(**x, "hello"); + + assert_eq!(Rc::try_unwrap(x).map(|x| *x), Ok("hello")); + } +} + +#[test] +fn test_into_from_raw_unsized() { + use std::fmt::Display; + use std::string::ToString; + + let rc: Rc = Rc::from("foo"); + + let ptr = Rc::into_raw(rc.clone()); + let rc2 = unsafe { Rc::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }, "foo"); + assert_eq!(rc, rc2); + + let rc: Rc = Rc::new(123); + + let ptr = Rc::into_raw(rc.clone()); + let rc2 = unsafe { Rc::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }.to_string(), "123"); + assert_eq!(rc2.to_string(), "123"); +} + +#[test] +fn into_from_weak_raw() { + let x = Rc::new(Box::new("hello")); + let y = Rc::downgrade(&x); + + let y_ptr = Weak::into_raw(y); + unsafe { + assert_eq!(**y_ptr, "hello"); + + let y = Weak::from_raw(y_ptr); + let y_up = Weak::upgrade(&y).unwrap(); + assert_eq!(**y_up, "hello"); + drop(y_up); + + assert_eq!(Rc::try_unwrap(x).map(|x| *x), Ok("hello")); + } +} + +#[test] +fn test_into_from_weak_raw_unsized() { + use std::fmt::Display; + use std::string::ToString; + + let arc: Rc = Rc::from("foo"); + let weak: Weak = Rc::downgrade(&arc); + + let ptr = Weak::into_raw(weak.clone()); + let weak2 = unsafe { Weak::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }, "foo"); + assert!(weak.ptr_eq(&weak2)); + + let arc: Rc = Rc::new(123); + let weak: Weak = Rc::downgrade(&arc); + + let ptr = Weak::into_raw(weak.clone()); + let weak2 = unsafe { Weak::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }.to_string(), "123"); + assert!(weak.ptr_eq(&weak2)); +} + +#[test] +fn get_mut() { + let mut x = Rc::new(3); + *Rc::get_mut(&mut x).unwrap() = 4; + assert_eq!(*x, 4); + let y = x.clone(); + assert!(Rc::get_mut(&mut x).is_none()); + drop(y); + assert!(Rc::get_mut(&mut x).is_some()); + let _w = Rc::downgrade(&x); + assert!(Rc::get_mut(&mut x).is_none()); +} + +#[test] +fn test_cowrc_clone_make_unique() { + let mut cow0 = Rc::new(75); + let mut cow1 = cow0.clone(); + let mut cow2 = cow1.clone(); + + assert!(75 == *Rc::make_mut(&mut cow0)); + assert!(75 == *Rc::make_mut(&mut cow1)); + assert!(75 == *Rc::make_mut(&mut cow2)); + + *Rc::make_mut(&mut cow0) += 1; + *Rc::make_mut(&mut cow1) += 2; + *Rc::make_mut(&mut cow2) += 3; + + assert!(76 == *cow0); + assert!(77 == *cow1); + assert!(78 == *cow2); + + // none should point to the same backing memory + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 != *cow2); +} + +#[test] +fn test_cowrc_clone_unique2() { + let mut cow0 = Rc::new(75); + let cow1 = cow0.clone(); + let cow2 = cow1.clone(); + + assert!(75 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + *Rc::make_mut(&mut cow0) += 1; + + assert!(76 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + // cow1 and cow2 should share the same contents + // cow0 should have a unique reference + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 == *cow2); +} + +#[test] +fn test_cowrc_clone_weak() { + let mut cow0 = Rc::new(75); + let cow1_weak = Rc::downgrade(&cow0); + + assert!(75 == *cow0); + assert!(75 == *cow1_weak.upgrade().unwrap()); + + *Rc::make_mut(&mut cow0) += 1; + + assert!(76 == *cow0); + assert!(cow1_weak.upgrade().is_none()); +} + +/// This is similar to the doc-test for `Rc::make_mut()`, but on an unsized type (slice). +#[test] +fn test_cowrc_unsized() { + use std::rc::Rc; + + let mut data: Rc<[i32]> = Rc::new([10, 20, 30]); + + Rc::make_mut(&mut data)[0] += 1; // Won't clone anything + let mut other_data = Rc::clone(&data); // Won't clone inner data + Rc::make_mut(&mut data)[1] += 1; // Clones inner data + Rc::make_mut(&mut data)[2] += 1; // Won't clone anything + Rc::make_mut(&mut other_data)[0] *= 10; // Won't clone anything + + // Now `data` and `other_data` point to different allocations. + assert_eq!(*data, [11, 21, 31]); + assert_eq!(*other_data, [110, 20, 30]); +} + +#[test] +fn test_show() { + let foo = Rc::new(75); + assert_eq!(format!("{foo:?}"), "75"); +} + +#[test] +fn test_unsized() { + let foo: Rc<[i32]> = Rc::new([1, 2, 3]); + assert_eq!(foo, foo.clone()); +} + +#[test] +fn test_maybe_thin_unsized() { + // If/when custom thin DSTs exist, this test should be updated to use one + use std::ffi::CStr; + + let x: Rc = Rc::from(c"swordfish"); + assert_eq!(format!("{x:?}"), "\"swordfish\""); + let y: Weak = Rc::downgrade(&x); + drop(x); + + // At this point, the weak points to a dropped DST + assert!(y.upgrade().is_none()); + // But we still need to be able to get the alloc layout to drop. + // CStr has no drop glue, but custom DSTs might, and need to work. + drop(y); +} + +#[test] +fn test_from_owned() { + let foo = 123; + let foo_rc = Rc::from(foo); + assert!(123 == *foo_rc); +} + +#[test] +fn test_new_weak() { + let foo: Weak = Weak::new(); + assert!(foo.upgrade().is_none()); +} + +#[test] +fn test_ptr_eq() { + let five = Rc::new(5); + let same_five = five.clone(); + let other_five = Rc::new(5); + + assert!(Rc::ptr_eq(&five, &same_five)); + assert!(!Rc::ptr_eq(&five, &other_five)); +} + +#[test] +fn test_from_str() { + let r: Rc = Rc::from("foo"); + + assert_eq!(&r[..], "foo"); +} + +#[test] +fn test_copy_from_slice() { + let s: &[u32] = &[1, 2, 3]; + let r: Rc<[u32]> = Rc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_clone_from_slice() { + #[derive(Clone, Debug, Eq, PartialEq)] + struct X(u32); + + let s: &[X] = &[X(1), X(2), X(3)]; + let r: Rc<[X]> = Rc::from(s); + + assert_eq!(&r[..], s); +} + +#[test] +#[should_panic] +fn test_clone_from_slice_panic() { + use std::string::{String, ToString}; + + struct Fail(u32, String); + + impl Clone for Fail { + fn clone(&self) -> Fail { + if self.0 == 2 { + panic!(); + } + Fail(self.0, self.1.clone()) + } + } + + let s: &[Fail] = + &[Fail(0, "foo".to_string()), Fail(1, "bar".to_string()), Fail(2, "baz".to_string())]; + + // Should panic, but not cause memory corruption + let _r: Rc<[Fail]> = Rc::from(s); +} + +#[test] +fn test_from_box() { + let b: Box = Box::new(123); + let r: Rc = Rc::from(b); + + assert_eq!(*r, 123); +} + +#[test] +fn test_from_box_str() { + use std::string::String; + + let s = String::from("foo").into_boxed_str(); + assert_eq!((&&&s).as_str(), "foo"); + + let r: Rc = Rc::from(s); + assert_eq!((&r).as_str(), "foo"); + assert_eq!(r.as_str(), "foo"); + + assert_eq!(&r[..], "foo"); +} + +#[test] +fn test_from_box_slice() { + let s = vec![1, 2, 3].into_boxed_slice(); + let r: Rc<[u32]> = Rc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_from_box_trait() { + use std::fmt::Display; + use std::string::ToString; + + let b: Box = Box::new(123); + let r: Rc = Rc::from(b); + + assert_eq!(r.to_string(), "123"); +} + +#[test] +fn test_from_box_trait_zero_sized() { + use std::fmt::Debug; + + let b: Box = Box::new(()); + let r: Rc = Rc::from(b); + + assert_eq!(format!("{r:?}"), "()"); +} + +#[test] +fn test_from_vec() { + let v = vec![1, 2, 3]; + let r: Rc<[u32]> = Rc::from(v); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_downcast() { + use std::any::Any; + + let r1: Rc = Rc::new(i32::MAX); + let r2: Rc = Rc::new("abc"); + + assert!(r1.clone().downcast::().is_err()); + + let r1i32 = r1.downcast::(); + assert!(r1i32.is_ok()); + assert_eq!(r1i32.unwrap(), Rc::new(i32::MAX)); + + assert!(r2.clone().downcast::().is_err()); + + let r2str = r2.downcast::<&'static str>(); + assert!(r2str.is_ok()); + assert_eq!(r2str.unwrap(), Rc::new("abc")); +} + +#[test] +fn test_array_from_slice() { + let v = vec![1, 2, 3]; + let r: Rc<[u32]> = Rc::from(v); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_ok()); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_err()); +} + +#[test] +fn test_rc_cyclic_with_zero_refs() { + struct ZeroRefs { + inner: Weak, + } + + let zero_refs = Rc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + ZeroRefs { inner: Weak::new() } + }); + + assert_eq!(Rc::strong_count(&zero_refs), 1); + assert_eq!(Rc::weak_count(&zero_refs), 0); + assert_eq!(zero_refs.inner.strong_count(), 0); + assert_eq!(zero_refs.inner.weak_count(), 0); +} + +#[test] +fn test_rc_cyclic_with_one_ref() { + struct OneRef { + inner: Weak, + } + + let one_ref = Rc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + OneRef { inner: inner.clone() } + }); + + assert_eq!(Rc::strong_count(&one_ref), 1); + assert_eq!(Rc::weak_count(&one_ref), 1); + + let one_ref2 = Weak::upgrade(&one_ref.inner).unwrap(); + assert!(Rc::ptr_eq(&one_ref, &one_ref2)); + + assert_eq!(one_ref.inner.strong_count(), 2); + assert_eq!(one_ref.inner.weak_count(), 1); +} + +#[test] +fn test_rc_cyclic_with_two_ref() { + struct TwoRefs { + inner: Weak, + inner1: Weak, + } + + let two_refs = Rc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + TwoRefs { inner: inner.clone(), inner1: inner.clone() } + }); + + assert_eq!(Rc::strong_count(&two_refs), 1); + assert_eq!(Rc::weak_count(&two_refs), 2); + + let two_ref3 = Weak::upgrade(&two_refs.inner).unwrap(); + assert!(Rc::ptr_eq(&two_refs, &two_ref3)); + + let two_ref2 = Weak::upgrade(&two_refs.inner1).unwrap(); + assert!(Rc::ptr_eq(&two_refs, &two_ref2)); + + assert_eq!(Rc::strong_count(&two_refs), 3); + assert_eq!(Rc::weak_count(&two_refs), 2); +} + +#[test] +fn test_unique_rc_weak() { + let rc = UniqueRc::new(42); + let weak = UniqueRc::downgrade(&rc); + assert!(weak.upgrade().is_none()); + + let _rc = UniqueRc::into_rc(rc); + assert_eq!(*weak.upgrade().unwrap(), 42); +} + +#[test] +fn test_unique_rc_drop_weak() { + let rc = UniqueRc::new(42); + let weak = UniqueRc::downgrade(&rc); + mem::drop(weak); + + let rc = UniqueRc::into_rc(rc); + assert_eq!(*rc, 42); +} + +#[test] +fn test_unique_rc_drops_contents() { + let mut dropped = false; + struct DropMe<'a>(&'a mut bool); + impl Drop for DropMe<'_> { + fn drop(&mut self) { + *self.0 = true; + } + } + { + let rc = UniqueRc::new(DropMe(&mut dropped)); + drop(rc); + } + assert!(dropped); +} + +/// Exercise the non-default allocator usage. +#[test] +fn test_unique_rc_with_alloc_drops_contents() { + let mut dropped = false; + struct DropMe<'a>(&'a mut bool); + impl Drop for DropMe<'_> { + fn drop(&mut self) { + *self.0 = true; + } + } + { + let rc = UniqueRc::new_in(DropMe(&mut dropped), std::alloc::System); + drop(rc); + } + assert!(dropped); +} + +#[test] +fn test_unique_rc_weak_clone_holding_ref() { + let mut v = UniqueRc::new(0u8); + let w = UniqueRc::downgrade(&v); + let r = &mut *v; + let _ = w.clone(); // touch weak count + *r = 123; +} + +#[test] +fn test_unique_rc_unsizing_coercion() { + let mut rc: UniqueRc<[u8]> = UniqueRc::new([0u8; 3]); + assert_eq!(rc.len(), 3); + rc[0] = 123; + let rc: Rc<[u8]> = UniqueRc::into_rc(rc); + assert_eq!(*rc, [123, 0, 0]); +} diff --git a/CoqOfRust/alloc/slice.rs b/CoqOfRust/alloc/slice.rs new file mode 100644 index 000000000..e3c7835f1 --- /dev/null +++ b/CoqOfRust/alloc/slice.rs @@ -0,0 +1,921 @@ +//! Utilities for the slice primitive type. +//! +//! *[See also the slice primitive type](slice).* +//! +//! Most of the structs in this module are iterator types which can only be created +//! using a certain function. For example, `slice.iter()` yields an [`Iter`]. +//! +//! A few functions are provided to create a slice from a value reference +//! or from a raw pointer. +#![stable(feature = "rust1", since = "1.0.0")] +// Many of the usings in this module are only used in the test configuration. +// It's cleaner to just turn off the unused_imports warning than to fix them. +#![cfg_attr(test, allow(unused_imports, dead_code))] + +use core::borrow::{Borrow, BorrowMut}; +#[cfg(not(no_global_oom_handling))] +use core::cmp::Ordering::{self, Less}; +#[cfg(not(no_global_oom_handling))] +use core::mem::{self, MaybeUninit}; +#[cfg(not(no_global_oom_handling))] +use core::ptr; +#[unstable(feature = "array_chunks", issue = "74985")] +pub use core::slice::ArrayChunks; +#[unstable(feature = "array_chunks", issue = "74985")] +pub use core::slice::ArrayChunksMut; +#[unstable(feature = "array_windows", issue = "75027")] +pub use core::slice::ArrayWindows; +#[stable(feature = "inherent_ascii_escape", since = "1.60.0")] +pub use core::slice::EscapeAscii; +#[stable(feature = "slice_get_slice", since = "1.28.0")] +pub use core::slice::SliceIndex; +#[cfg(not(no_global_oom_handling))] +use core::slice::sort; +#[stable(feature = "slice_group_by", since = "1.77.0")] +pub use core::slice::{ChunkBy, ChunkByMut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::slice::{Chunks, Windows}; +#[stable(feature = "chunks_exact", since = "1.31.0")] +pub use core::slice::{ChunksExact, ChunksExactMut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::slice::{ChunksMut, Split, SplitMut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::slice::{Iter, IterMut}; +#[stable(feature = "rchunks", since = "1.31.0")] +pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut}; +#[stable(feature = "slice_rsplit", since = "1.27.0")] +pub use core::slice::{RSplit, RSplitMut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut}; +#[stable(feature = "split_inclusive", since = "1.51.0")] +pub use core::slice::{SplitInclusive, SplitInclusiveMut}; +#[stable(feature = "from_ref", since = "1.28.0")] +pub use core::slice::{from_mut, from_ref}; +#[unstable(feature = "slice_from_ptr_range", issue = "89792")] +pub use core::slice::{from_mut_ptr_range, from_ptr_range}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::slice::{from_raw_parts, from_raw_parts_mut}; +#[unstable(feature = "slice_range", issue = "76393")] +pub use core::slice::{range, try_range}; + +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// + +// HACK(japaric) needed for the implementation of `vec!` macro during testing +// N.B., see the `hack` module in this file for more details. +#[cfg(test)] +pub use hack::into_vec; +// HACK(japaric) needed for the implementation of `Vec::clone` during testing +// N.B., see the `hack` module in this file for more details. +#[cfg(test)] +pub use hack::to_vec; + +use crate::alloc::Allocator; +#[cfg(not(no_global_oom_handling))] +use crate::alloc::Global; +#[cfg(not(no_global_oom_handling))] +use crate::borrow::ToOwned; +use crate::boxed::Box; +use crate::vec::Vec; + +// HACK(japaric): With cfg(test) `impl [T]` is not available, these three +// functions are actually methods that are in `impl [T]` but not in +// `core::slice::SliceExt` - we need to supply these functions for the +// `test_permutations` test +pub(crate) mod hack { + use core::alloc::Allocator; + + use crate::boxed::Box; + use crate::vec::Vec; + + // We shouldn't add inline attribute to this since this is used in + // `vec!` macro mostly and causes perf regression. See #71204 for + // discussion and perf results. + #[allow(missing_docs)] + pub fn into_vec(b: Box<[T], A>) -> Vec { + unsafe { + let len = b.len(); + let (b, alloc) = Box::into_raw_with_allocator(b); + Vec::from_raw_parts_in(b as *mut T, len, len, alloc) + } + } + + #[cfg(not(no_global_oom_handling))] + #[allow(missing_docs)] + #[inline] + pub fn to_vec(s: &[T], alloc: A) -> Vec { + T::to_vec(s, alloc) + } + + #[cfg(not(no_global_oom_handling))] + pub trait ConvertVec { + fn to_vec(s: &[Self], alloc: A) -> Vec + where + Self: Sized; + } + + #[cfg(not(no_global_oom_handling))] + impl ConvertVec for T { + #[inline] + default fn to_vec(s: &[Self], alloc: A) -> Vec { + struct DropGuard<'a, T, A: Allocator> { + vec: &'a mut Vec, + num_init: usize, + } + impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> { + #[inline] + fn drop(&mut self) { + // SAFETY: + // items were marked initialized in the loop below + unsafe { + self.vec.set_len(self.num_init); + } + } + } + let mut vec = Vec::with_capacity_in(s.len(), alloc); + let mut guard = DropGuard { vec: &mut vec, num_init: 0 }; + let slots = guard.vec.spare_capacity_mut(); + // .take(slots.len()) is necessary for LLVM to remove bounds checks + // and has better codegen than zip. + for (i, b) in s.iter().enumerate().take(slots.len()) { + guard.num_init = i; + slots[i].write(b.clone()); + } + core::mem::forget(guard); + // SAFETY: + // the vec was allocated and initialized above to at least this length. + unsafe { + vec.set_len(s.len()); + } + vec + } + } + + #[cfg(not(no_global_oom_handling))] + impl ConvertVec for T { + #[inline] + fn to_vec(s: &[Self], alloc: A) -> Vec { + let mut v = Vec::with_capacity_in(s.len(), alloc); + // SAFETY: + // allocated above with the capacity of `s`, and initialize to `s.len()` in + // ptr::copy_to_non_overlapping below. + unsafe { + s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), s.len()); + v.set_len(s.len()); + } + v + } + } +} + +#[cfg(not(test))] +impl [T] { + /// Sorts the slice, preserving initial order of equal elements. + /// + /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*)) + /// worst-case. + /// + /// If the implementation of [`Ord`] for `T` does not implement a [total order], the function + /// may panic; even if the function exits normally, the resulting order of elements in the slice + /// is unspecified. See also the note on panicking below. + /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. See + /// [`sort_unstable`](slice::sort_unstable). The exception are partially sorted slices, which + /// may be better served with `slice::sort`. + /// + /// Sorting types that only implement [`PartialOrd`] such as [`f32`] and [`f64`] require + /// additional precautions. For example, `f32::NAN != f32::NAN`, which doesn't fulfill the + /// reflexivity requirement of [`Ord`]. By using an alternative comparison function with + /// `slice::sort_by` such as [`f32::total_cmp`] or [`f64::total_cmp`] that defines a [total + /// order] users can sort slices containing floating-point values. Alternatively, if all values + /// in the slice are guaranteed to be in a subset for which [`PartialOrd::partial_cmp`] forms a + /// [total order], it's possible to sort the slice with `sort_by(|a, b| + /// a.partial_cmp(b).unwrap())`. + /// + /// # Current implementation + /// + /// The current implementation is based on [driftsort] by Orson Peters and Lukas Bergdoll, which + /// combines the fast average case of quicksort with the fast worst case and partial run + /// detection of mergesort, achieving linear time on fully sorted and reversed inputs. On inputs + /// with k distinct elements, the expected time to sort the data is *O*(*n* \* log(*k*)). + /// + /// The auxiliary memory allocation behavior depends on the input length. Short slices are + /// handled without allocation, medium sized slices allocate `self.len()` and beyond that it + /// clamps at `self.len() / 2`. + /// + /// # Panics + /// + /// May panic if the implementation of [`Ord`] for `T` does not implement a [total order], or if + /// the [`Ord`] implementation itself panics. + /// + /// All safe functions on slices preserve the invariant that even if the function panics, all + /// original elements will remain in the slice and any possible modifications via interior + /// mutability are observed in the input. This ensures that recovery code (for instance inside + /// of a `Drop` or following a `catch_unwind`) will still have access to all the original + /// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able + /// to dispose of all contained elements. + /// + /// # Examples + /// + /// ``` + /// let mut v = [4, -5, 1, -3, 2]; + /// + /// v.sort(); + /// assert_eq!(v, [-5, -3, 1, 2, 4]); + /// ``` + /// + /// [driftsort]: https://github.com/Voultapher/driftsort + /// [total order]: https://en.wikipedia.org/wiki/Total_order + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sort(&mut self) + where + T: Ord, + { + stable_sort(self, T::lt); + } + + /// Sorts the slice with a comparison function, preserving initial order of equal elements. + /// + /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*)) + /// worst-case. + /// + /// If the comparison function `compare` does not implement a [total order], the function may + /// panic; even if the function exits normally, the resulting order of elements in the slice is + /// unspecified. See also the note on panicking below. + /// + /// For example `|a, b| (a - b).cmp(a)` is a comparison function that is neither transitive nor + /// reflexive nor total, `a < b < c < a` with `a = 1, b = 2, c = 3`. For more information and + /// examples see the [`Ord`] documentation. + /// + /// # Current implementation + /// + /// The current implementation is based on [driftsort] by Orson Peters and Lukas Bergdoll, which + /// combines the fast average case of quicksort with the fast worst case and partial run + /// detection of mergesort, achieving linear time on fully sorted and reversed inputs. On inputs + /// with k distinct elements, the expected time to sort the data is *O*(*n* \* log(*k*)). + /// + /// The auxiliary memory allocation behavior depends on the input length. Short slices are + /// handled without allocation, medium sized slices allocate `self.len()` and beyond that it + /// clamps at `self.len() / 2`. + /// + /// # Panics + /// + /// May panic if `compare` does not implement a [total order], or if `compare` itself panics. + /// + /// All safe functions on slices preserve the invariant that even if the function panics, all + /// original elements will remain in the slice and any possible modifications via interior + /// mutability are observed in the input. This ensures that recovery code (for instance inside + /// of a `Drop` or following a `catch_unwind`) will still have access to all the original + /// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able + /// to dispose of all contained elements. + /// + /// # Examples + /// + /// ``` + /// let mut v = [4, -5, 1, -3, 2]; + /// v.sort_by(|a, b| a.cmp(b)); + /// assert_eq!(v, [-5, -3, 1, 2, 4]); + /// + /// // reverse sorting + /// v.sort_by(|a, b| b.cmp(a)); + /// assert_eq!(v, [4, 2, 1, -3, -5]); + /// ``` + /// + /// [driftsort]: https://github.com/Voultapher/driftsort + /// [total order]: https://en.wikipedia.org/wiki/Total_order + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sort_by(&mut self, mut compare: F) + where + F: FnMut(&T, &T) -> Ordering, + { + stable_sort(self, |a, b| compare(a, b) == Less); + } + + /// Sorts the slice with a key extraction function, preserving initial order of equal elements. + /// + /// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* \* log(*n*)) + /// worst-case, where the key function is *O*(*m*). + /// + /// If the implementation of [`Ord`] for `K` does not implement a [total order], the function + /// may panic; even if the function exits normally, the resulting order of elements in the slice + /// is unspecified. See also the note on panicking below. + /// + /// # Current implementation + /// + /// The current implementation is based on [driftsort] by Orson Peters and Lukas Bergdoll, which + /// combines the fast average case of quicksort with the fast worst case and partial run + /// detection of mergesort, achieving linear time on fully sorted and reversed inputs. On inputs + /// with k distinct elements, the expected time to sort the data is *O*(*n* \* log(*k*)). + /// + /// The auxiliary memory allocation behavior depends on the input length. Short slices are + /// handled without allocation, medium sized slices allocate `self.len()` and beyond that it + /// clamps at `self.len() / 2`. + /// + /// # Panics + /// + /// May panic if the implementation of [`Ord`] for `K` does not implement a [total order], or if + /// the [`Ord`] implementation or the key-function `f` panics. + /// + /// All safe functions on slices preserve the invariant that even if the function panics, all + /// original elements will remain in the slice and any possible modifications via interior + /// mutability are observed in the input. This ensures that recovery code (for instance inside + /// of a `Drop` or following a `catch_unwind`) will still have access to all the original + /// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able + /// to dispose of all contained elements. + /// + /// # Examples + /// + /// ``` + /// let mut v = [4i32, -5, 1, -3, 2]; + /// + /// v.sort_by_key(|k| k.abs()); + /// assert_eq!(v, [1, 2, -3, 4, -5]); + /// ``` + /// + /// [driftsort]: https://github.com/Voultapher/driftsort + /// [total order]: https://en.wikipedia.org/wiki/Total_order + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[stable(feature = "slice_sort_by_key", since = "1.7.0")] + #[inline] + pub fn sort_by_key(&mut self, mut f: F) + where + F: FnMut(&T) -> K, + K: Ord, + { + stable_sort(self, |a, b| f(a).lt(&f(b))); + } + + /// Sorts the slice with a key extraction function, preserving initial order of equal elements. + /// + /// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* + *n* \* + /// log(*n*)) worst-case, where the key function is *O*(*m*). + /// + /// During sorting, the key function is called at most once per element, by using temporary + /// storage to remember the results of key evaluation. The order of calls to the key function is + /// unspecified and may change in future versions of the standard library. + /// + /// If the implementation of [`Ord`] for `K` does not implement a [total order], the function + /// may panic; even if the function exits normally, the resulting order of elements in the slice + /// is unspecified. See also the note on panicking below. + /// + /// For simple key functions (e.g., functions that are property accesses or basic operations), + /// [`sort_by_key`](slice::sort_by_key) is likely to be faster. + /// + /// # Current implementation + /// + /// The current implementation is based on [instruction-parallel-network sort][ipnsort] by Lukas + /// Bergdoll, which combines the fast average case of randomized quicksort with the fast worst + /// case of heapsort, while achieving linear time on fully sorted and reversed inputs. And + /// *O*(*k* \* log(*n*)) where *k* is the number of distinct elements in the input. It leverages + /// superscalar out-of-order execution capabilities commonly found in CPUs, to efficiently + /// perform the operation. + /// + /// In the worst case, the algorithm allocates temporary storage in a `Vec<(K, usize)>` the + /// length of the slice. + /// + /// # Panics + /// + /// May panic if the implementation of [`Ord`] for `K` does not implement a [total order], or if + /// the [`Ord`] implementation panics. + /// + /// All safe functions on slices preserve the invariant that even if the function panics, all + /// original elements will remain in the slice and any possible modifications via interior + /// mutability are observed in the input. This ensures that recovery code (for instance inside + /// of a `Drop` or following a `catch_unwind`) will still have access to all the original + /// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able + /// to dispose of all contained elements. + /// + /// # Examples + /// + /// ``` + /// let mut v = [4i32, -5, 1, -3, 2, 10]; + /// + /// // Strings are sorted by lexicographical order. + /// v.sort_by_cached_key(|k| k.to_string()); + /// assert_eq!(v, [-3, -5, 1, 10, 2, 4]); + /// ``` + /// + /// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort + /// [total order]: https://en.wikipedia.org/wiki/Total_order + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[stable(feature = "slice_sort_by_cached_key", since = "1.34.0")] + #[inline] + pub fn sort_by_cached_key(&mut self, f: F) + where + F: FnMut(&T) -> K, + K: Ord, + { + // Helper macro for indexing our vector by the smallest possible type, to reduce allocation. + macro_rules! sort_by_key { + ($t:ty, $slice:ident, $f:ident) => {{ + let mut indices: Vec<_> = + $slice.iter().map($f).enumerate().map(|(i, k)| (k, i as $t)).collect(); + // The elements of `indices` are unique, as they are indexed, so any sort will be + // stable with respect to the original slice. We use `sort_unstable` here because + // it requires no memory allocation. + indices.sort_unstable(); + for i in 0..$slice.len() { + let mut index = indices[i].1; + while (index as usize) < i { + index = indices[index as usize].1; + } + indices[i].1 = index; + $slice.swap(i, index as usize); + } + }}; + } + + let len = self.len(); + if len < 2 { + return; + } + + // Avoids binary-size usage in cases where the alignment doesn't work out to make this + // beneficial or on 32-bit platforms. + let is_using_u32_as_idx_type_helpful = + const { mem::size_of::<(K, u32)>() < mem::size_of::<(K, usize)>() }; + + // It's possible to instantiate this for u8 and u16 but, doing so is very wasteful in terms + // of compile-times and binary-size, the peak saved heap memory for u16 is (u8 + u16) -> 4 + // bytes * u16::MAX vs (u8 + u32) -> 8 bytes * u16::MAX, the saved heap memory is at peak + // ~262KB. + if is_using_u32_as_idx_type_helpful && len <= (u32::MAX as usize) { + return sort_by_key!(u32, self, f); + } + + sort_by_key!(usize, self, f) + } + + /// Copies `self` into a new `Vec`. + /// + /// # Examples + /// + /// ``` + /// let s = [10, 40, 30]; + /// let x = s.to_vec(); + /// // Here, `s` and `x` can be modified independently. + /// ``` + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[rustc_conversion_suggestion] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_vec(&self) -> Vec + where + T: Clone, + { + self.to_vec_in(Global) + } + + /// Copies `self` into a new `Vec` with an allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let s = [10, 40, 30]; + /// let x = s.to_vec_in(System); + /// // Here, `s` and `x` can be modified independently. + /// ``` + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn to_vec_in(&self, alloc: A) -> Vec + where + T: Clone, + { + // N.B., see the `hack` module in this file for more details. + hack::to_vec(self, alloc) + } + + /// Converts `self` into a vector without clones or allocation. + /// + /// The resulting vector can be converted back into a box via + /// `Vec`'s `into_boxed_slice` method. + /// + /// # Examples + /// + /// ``` + /// let s: Box<[i32]> = Box::new([10, 40, 30]); + /// let x = s.into_vec(); + /// // `s` cannot be used anymore because it has been converted into `x`. + /// + /// assert_eq!(x, vec![10, 40, 30]); + /// ``` + #[rustc_allow_incoherent_impl] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg_attr(not(test), rustc_diagnostic_item = "slice_into_vec")] + pub fn into_vec(self: Box) -> Vec { + // N.B., see the `hack` module in this file for more details. + hack::into_vec(self) + } + + /// Creates a vector by copying a slice `n` times. + /// + /// # Panics + /// + /// This function will panic if the capacity would overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]); + /// ``` + /// + /// A panic upon overflow: + /// + /// ```should_panic + /// // this will panic at runtime + /// b"0123456789abcdef".repeat(usize::MAX); + /// ``` + #[rustc_allow_incoherent_impl] + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "repeat_generic_slice", since = "1.40.0")] + pub fn repeat(&self, n: usize) -> Vec + where + T: Copy, + { + if n == 0 { + return Vec::new(); + } + + // If `n` is larger than zero, it can be split as + // `n = 2^expn + rem (2^expn > rem, expn >= 0, rem >= 0)`. + // `2^expn` is the number represented by the leftmost '1' bit of `n`, + // and `rem` is the remaining part of `n`. + + // Using `Vec` to access `set_len()`. + let capacity = self.len().checked_mul(n).expect("capacity overflow"); + let mut buf = Vec::with_capacity(capacity); + + // `2^expn` repetition is done by doubling `buf` `expn`-times. + buf.extend(self); + { + let mut m = n >> 1; + // If `m > 0`, there are remaining bits up to the leftmost '1'. + while m > 0 { + // `buf.extend(buf)`: + unsafe { + ptr::copy_nonoverlapping::( + buf.as_ptr(), + (buf.as_mut_ptr()).add(buf.len()), + buf.len(), + ); + // `buf` has capacity of `self.len() * n`. + let buf_len = buf.len(); + buf.set_len(buf_len * 2); + } + + m >>= 1; + } + } + + // `rem` (`= n - 2^expn`) repetition is done by copying + // first `rem` repetitions from `buf` itself. + let rem_len = capacity - buf.len(); // `self.len() * rem` + if rem_len > 0 { + // `buf.extend(buf[0 .. rem_len])`: + unsafe { + // This is non-overlapping since `2^expn > rem`. + ptr::copy_nonoverlapping::( + buf.as_ptr(), + (buf.as_mut_ptr()).add(buf.len()), + rem_len, + ); + // `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`). + buf.set_len(capacity); + } + } + buf + } + + /// Flattens a slice of `T` into a single value `Self::Output`. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(["hello", "world"].concat(), "helloworld"); + /// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]); + /// ``` + #[rustc_allow_incoherent_impl] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn concat(&self) -> >::Output + where + Self: Concat, + { + Concat::concat(self) + } + + /// Flattens a slice of `T` into a single value `Self::Output`, placing a + /// given separator between each. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(["hello", "world"].join(" "), "hello world"); + /// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]); + /// assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 0, 3, 4]); + /// ``` + #[rustc_allow_incoherent_impl] + #[stable(feature = "rename_connect_to_join", since = "1.3.0")] + pub fn join(&self, sep: Separator) -> >::Output + where + Self: Join, + { + Join::join(self, sep) + } + + /// Flattens a slice of `T` into a single value `Self::Output`, placing a + /// given separator between each. + /// + /// # Examples + /// + /// ``` + /// # #![allow(deprecated)] + /// assert_eq!(["hello", "world"].connect(" "), "hello world"); + /// assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]); + /// ``` + #[rustc_allow_incoherent_impl] + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.3.0", note = "renamed to join", suggestion = "join")] + pub fn connect(&self, sep: Separator) -> >::Output + where + Self: Join, + { + Join::join(self, sep) + } +} + +#[cfg(not(test))] +impl [u8] { + /// Returns a vector containing a copy of this slice where each byte + /// is mapped to its ASCII upper case equivalent. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To uppercase the value in-place, use [`make_ascii_uppercase`]. + /// + /// [`make_ascii_uppercase`]: slice::make_ascii_uppercase + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[must_use = "this returns the uppercase bytes as a new Vec, \ + without modifying the original"] + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[inline] + pub fn to_ascii_uppercase(&self) -> Vec { + let mut me = self.to_vec(); + me.make_ascii_uppercase(); + me + } + + /// Returns a vector containing a copy of this slice where each byte + /// is mapped to its ASCII lower case equivalent. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To lowercase the value in-place, use [`make_ascii_lowercase`]. + /// + /// [`make_ascii_lowercase`]: slice::make_ascii_lowercase + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[must_use = "this returns the lowercase bytes as a new Vec, \ + without modifying the original"] + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[inline] + pub fn to_ascii_lowercase(&self) -> Vec { + let mut me = self.to_vec(); + me.make_ascii_lowercase(); + me + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Extension traits for slices over specific kinds of data +//////////////////////////////////////////////////////////////////////////////// + +/// Helper trait for [`[T]::concat`](slice::concat). +/// +/// Note: the `Item` type parameter is not used in this trait, +/// but it allows impls to be more generic. +/// Without it, we get this error: +/// +/// ```error +/// error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predica +/// --> library/alloc/src/slice.rs:608:6 +/// | +/// 608 | impl> Concat for [V] { +/// | ^ unconstrained type parameter +/// ``` +/// +/// This is because there could exist `V` types with multiple `Borrow<[_]>` impls, +/// such that multiple `T` types would apply: +/// +/// ``` +/// # #[allow(dead_code)] +/// pub struct Foo(Vec, Vec); +/// +/// impl std::borrow::Borrow<[u32]> for Foo { +/// fn borrow(&self) -> &[u32] { &self.0 } +/// } +/// +/// impl std::borrow::Borrow<[String]> for Foo { +/// fn borrow(&self) -> &[String] { &self.1 } +/// } +/// ``` +#[unstable(feature = "slice_concat_trait", issue = "27747")] +pub trait Concat { + #[unstable(feature = "slice_concat_trait", issue = "27747")] + /// The resulting type after concatenation + type Output; + + /// Implementation of [`[T]::concat`](slice::concat) + #[unstable(feature = "slice_concat_trait", issue = "27747")] + fn concat(slice: &Self) -> Self::Output; +} + +/// Helper trait for [`[T]::join`](slice::join) +#[unstable(feature = "slice_concat_trait", issue = "27747")] +pub trait Join { + #[unstable(feature = "slice_concat_trait", issue = "27747")] + /// The resulting type after concatenation + type Output; + + /// Implementation of [`[T]::join`](slice::join) + #[unstable(feature = "slice_concat_trait", issue = "27747")] + fn join(slice: &Self, sep: Separator) -> Self::Output; +} + +#[cfg(not(no_global_oom_handling))] +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl> Concat for [V] { + type Output = Vec; + + fn concat(slice: &Self) -> Vec { + let size = slice.iter().map(|slice| slice.borrow().len()).sum(); + let mut result = Vec::with_capacity(size); + for v in slice { + result.extend_from_slice(v.borrow()) + } + result + } +} + +#[cfg(not(no_global_oom_handling))] +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl> Join<&T> for [V] { + type Output = Vec; + + fn join(slice: &Self, sep: &T) -> Vec { + let mut iter = slice.iter(); + let first = match iter.next() { + Some(first) => first, + None => return vec![], + }; + let size = slice.iter().map(|v| v.borrow().len()).sum::() + slice.len() - 1; + let mut result = Vec::with_capacity(size); + result.extend_from_slice(first.borrow()); + + for v in iter { + result.push(sep.clone()); + result.extend_from_slice(v.borrow()) + } + result + } +} + +#[cfg(not(no_global_oom_handling))] +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl> Join<&[T]> for [V] { + type Output = Vec; + + fn join(slice: &Self, sep: &[T]) -> Vec { + let mut iter = slice.iter(); + let first = match iter.next() { + Some(first) => first, + None => return vec![], + }; + let size = + slice.iter().map(|v| v.borrow().len()).sum::() + sep.len() * (slice.len() - 1); + let mut result = Vec::with_capacity(size); + result.extend_from_slice(first.borrow()); + + for v in iter { + result.extend_from_slice(sep); + result.extend_from_slice(v.borrow()) + } + result + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Standard trait implementations for slices +//////////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow<[T]> for Vec { + fn borrow(&self) -> &[T] { + &self[..] + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl BorrowMut<[T]> for Vec { + fn borrow_mut(&mut self) -> &mut [T] { + &mut self[..] + } +} + +// Specializable trait for implementing ToOwned::clone_into. This is +// public in the crate and has the Allocator parameter so that +// vec::clone_from use it too. +#[cfg(not(no_global_oom_handling))] +pub(crate) trait SpecCloneIntoVec { + fn clone_into(&self, target: &mut Vec); +} + +#[cfg(not(no_global_oom_handling))] +impl SpecCloneIntoVec for [T] { + default fn clone_into(&self, target: &mut Vec) { + // drop anything in target that will not be overwritten + target.truncate(self.len()); + + // target.len <= self.len due to the truncate above, so the + // slices here are always in-bounds. + let (init, tail) = self.split_at(target.len()); + + // reuse the contained values' allocations/resources. + target.clone_from_slice(init); + target.extend_from_slice(tail); + } +} + +#[cfg(not(no_global_oom_handling))] +impl SpecCloneIntoVec for [T] { + fn clone_into(&self, target: &mut Vec) { + target.clear(); + target.extend_from_slice(self); + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for [T] { + type Owned = Vec; + #[cfg(not(test))] + fn to_owned(&self) -> Vec { + self.to_vec() + } + + #[cfg(test)] + fn to_owned(&self) -> Vec { + hack::to_vec(self, Global) + } + + fn clone_into(&self, target: &mut Vec) { + SpecCloneIntoVec::clone_into(self, target); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Sorting +//////////////////////////////////////////////////////////////////////////////// + +#[inline] +#[cfg(not(no_global_oom_handling))] +fn stable_sort(v: &mut [T], mut is_less: F) +where + F: FnMut(&T, &T) -> bool, +{ + sort::stable::sort::>(v, &mut is_less); +} + +#[cfg(not(no_global_oom_handling))] +#[unstable(issue = "none", feature = "std_internals")] +impl sort::stable::BufGuard for Vec { + fn with_capacity(capacity: usize) -> Self { + Vec::with_capacity(capacity) + } + + fn as_uninit_slice_mut(&mut self) -> &mut [MaybeUninit] { + self.spare_capacity_mut() + } +} diff --git a/CoqOfRust/alloc/str.rs b/CoqOfRust/alloc/str.rs new file mode 100644 index 000000000..6fee8d3fe --- /dev/null +++ b/CoqOfRust/alloc/str.rs @@ -0,0 +1,716 @@ +//! Utilities for the `str` primitive type. +//! +//! *[See also the `str` primitive type](str).* + +#![stable(feature = "rust1", since = "1.0.0")] +// Many of the usings in this module are only used in the test configuration. +// It's cleaner to just turn off the unused_imports warning than to fix them. +#![allow(unused_imports)] + +use core::borrow::{Borrow, BorrowMut}; +use core::iter::FusedIterator; +use core::mem::MaybeUninit; +#[stable(feature = "encode_utf16", since = "1.8.0")] +pub use core::str::EncodeUtf16; +#[stable(feature = "split_ascii_whitespace", since = "1.34.0")] +pub use core::str::SplitAsciiWhitespace; +#[stable(feature = "split_inclusive", since = "1.51.0")] +pub use core::str::SplitInclusive; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::SplitWhitespace; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::pattern; +use core::str::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher, Utf8Pattern}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{Bytes, CharIndices, Chars, from_utf8, from_utf8_mut}; +#[stable(feature = "str_escape", since = "1.34.0")] +pub use core::str::{EscapeDebug, EscapeDefault, EscapeUnicode}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{FromStr, Utf8Error}; +#[allow(deprecated)] +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{Lines, LinesAny}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{MatchIndices, RMatchIndices}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{Matches, RMatches}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{ParseBoolError, from_utf8_unchecked, from_utf8_unchecked_mut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{RSplit, Split}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{RSplitN, SplitN}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{RSplitTerminator, SplitTerminator}; +#[stable(feature = "utf8_chunks", since = "1.79.0")] +pub use core::str::{Utf8Chunk, Utf8Chunks}; +#[unstable(feature = "str_from_raw_parts", issue = "119206")] +pub use core::str::{from_raw_parts, from_raw_parts_mut}; +use core::unicode::conversions; +use core::{mem, ptr}; + +use crate::borrow::ToOwned; +use crate::boxed::Box; +use crate::slice::{Concat, Join, SliceIndex}; +use crate::string::String; +use crate::vec::Vec; + +/// Note: `str` in `Concat` is not meaningful here. +/// This type parameter of the trait only exists to enable another impl. +#[cfg(not(no_global_oom_handling))] +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl> Concat for [S] { + type Output = String; + + fn concat(slice: &Self) -> String { + Join::join(slice, "") + } +} + +#[cfg(not(no_global_oom_handling))] +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl> Join<&str> for [S] { + type Output = String; + + fn join(slice: &Self, sep: &str) -> String { + unsafe { String::from_utf8_unchecked(join_generic_copy(slice, sep.as_bytes())) } + } +} + +#[cfg(not(no_global_oom_handling))] +macro_rules! specialize_for_lengths { + ($separator:expr, $target:expr, $iter:expr; $($num:expr),*) => {{ + let mut target = $target; + let iter = $iter; + let sep_bytes = $separator; + match $separator.len() { + $( + // loops with hardcoded sizes run much faster + // specialize the cases with small separator lengths + $num => { + for s in iter { + copy_slice_and_advance!(target, sep_bytes); + let content_bytes = s.borrow().as_ref(); + copy_slice_and_advance!(target, content_bytes); + } + }, + )* + _ => { + // arbitrary non-zero size fallback + for s in iter { + copy_slice_and_advance!(target, sep_bytes); + let content_bytes = s.borrow().as_ref(); + copy_slice_and_advance!(target, content_bytes); + } + } + } + target + }} +} + +#[cfg(not(no_global_oom_handling))] +macro_rules! copy_slice_and_advance { + ($target:expr, $bytes:expr) => { + let len = $bytes.len(); + let (head, tail) = { $target }.split_at_mut(len); + head.copy_from_slice($bytes); + $target = tail; + }; +} + +// Optimized join implementation that works for both Vec (T: Copy) and String's inner vec +// Currently (2018-05-13) there is a bug with type inference and specialization (see issue #36262) +// For this reason SliceConcat is not specialized for T: Copy and SliceConcat is the +// only user of this function. It is left in place for the time when that is fixed. +// +// the bounds for String-join are S: Borrow and for Vec-join Borrow<[T]> +// [T] and str both impl AsRef<[T]> for some T +// => s.borrow().as_ref() and we always have slices +#[cfg(not(no_global_oom_handling))] +fn join_generic_copy(slice: &[S], sep: &[T]) -> Vec +where + T: Copy, + B: AsRef<[T]> + ?Sized, + S: Borrow, +{ + let sep_len = sep.len(); + let mut iter = slice.iter(); + + // the first slice is the only one without a separator preceding it + let first = match iter.next() { + Some(first) => first, + None => return vec![], + }; + + // compute the exact total length of the joined Vec + // if the `len` calculation overflows, we'll panic + // we would have run out of memory anyway and the rest of the function requires + // the entire Vec pre-allocated for safety + let reserved_len = sep_len + .checked_mul(iter.len()) + .and_then(|n| { + slice.iter().map(|s| s.borrow().as_ref().len()).try_fold(n, usize::checked_add) + }) + .expect("attempt to join into collection with len > usize::MAX"); + + // prepare an uninitialized buffer + let mut result = Vec::with_capacity(reserved_len); + debug_assert!(result.capacity() >= reserved_len); + + result.extend_from_slice(first.borrow().as_ref()); + + unsafe { + let pos = result.len(); + let target = result.spare_capacity_mut().get_unchecked_mut(..reserved_len - pos); + + // Convert the separator and slices to slices of MaybeUninit + // to simplify implementation in specialize_for_lengths + let sep_uninit = core::slice::from_raw_parts(sep.as_ptr().cast(), sep.len()); + let iter_uninit = iter.map(|it| { + let it = it.borrow().as_ref(); + core::slice::from_raw_parts(it.as_ptr().cast(), it.len()) + }); + + // copy separator and slices over without bounds checks + // generate loops with hardcoded offsets for small separators + // massive improvements possible (~ x2) + let remain = specialize_for_lengths!(sep_uninit, target, iter_uninit; 0, 1, 2, 3, 4); + + // A weird borrow implementation may return different + // slices for the length calculation and the actual copy. + // Make sure we don't expose uninitialized bytes to the caller. + let result_len = reserved_len - remain.len(); + result.set_len(result_len); + } + result +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow for String { + #[inline] + fn borrow(&self) -> &str { + &self[..] + } +} + +#[stable(feature = "string_borrow_mut", since = "1.36.0")] +impl BorrowMut for String { + #[inline] + fn borrow_mut(&mut self) -> &mut str { + &mut self[..] + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for str { + type Owned = String; + + #[inline] + fn to_owned(&self) -> String { + unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) } + } + + #[inline] + fn clone_into(&self, target: &mut String) { + target.clear(); + target.push_str(self); + } +} + +/// Methods for string slices. +#[cfg(not(test))] +impl str { + /// Converts a `Box` into a `Box<[u8]>` without copying or allocating. + /// + /// # Examples + /// + /// ``` + /// let s = "this is a string"; + /// let boxed_str = s.to_owned().into_boxed_str(); + /// let boxed_bytes = boxed_str.into_boxed_bytes(); + /// assert_eq!(*boxed_bytes, *s.as_bytes()); + /// ``` + #[rustc_allow_incoherent_impl] + #[stable(feature = "str_box_extras", since = "1.20.0")] + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub fn into_boxed_bytes(self: Box) -> Box<[u8]> { + self.into() + } + + /// Replaces all matches of a pattern with another string. + /// + /// `replace` creates a new [`String`], and copies the data from this string slice into it. + /// While doing so, it attempts to find matches of a pattern. If it finds any, it + /// replaces them with the replacement string slice. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "this is old"; + /// + /// assert_eq!("this is new", s.replace("old", "new")); + /// assert_eq!("than an old", s.replace("is", "an")); + /// ``` + /// + /// When the pattern doesn't match, it returns this string slice as [`String`]: + /// + /// ``` + /// let s = "this is old"; + /// assert_eq!(s, s.replace("cookie monster", "little lamb")); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[must_use = "this returns the replaced string as a new allocation, \ + without modifying the original"] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn replace(&self, from: P, to: &str) -> String { + // Fast path for replacing a single ASCII character with another. + if let Some(from_byte) = match from.as_utf8_pattern() { + Some(Utf8Pattern::StringPattern([from_byte])) => Some(*from_byte), + Some(Utf8Pattern::CharPattern(c)) => c.as_ascii().map(|ascii_char| ascii_char.to_u8()), + _ => None, + } { + if let [to_byte] = to.as_bytes() { + return unsafe { replace_ascii(self.as_bytes(), from_byte, *to_byte) }; + } + } + // Set result capacity to self.len() when from.len() <= to.len() + let default_capacity = match from.as_utf8_pattern() { + Some(Utf8Pattern::StringPattern(s)) if s.len() <= to.len() => self.len(), + Some(Utf8Pattern::CharPattern(c)) if c.len_utf8() <= to.len() => self.len(), + _ => 0, + }; + let mut result = String::with_capacity(default_capacity); + let mut last_end = 0; + for (start, part) in self.match_indices(from) { + result.push_str(unsafe { self.get_unchecked(last_end..start) }); + result.push_str(to); + last_end = start + part.len(); + } + result.push_str(unsafe { self.get_unchecked(last_end..self.len()) }); + result + } + + /// Replaces first N matches of a pattern with another string. + /// + /// `replacen` creates a new [`String`], and copies the data from this string slice into it. + /// While doing so, it attempts to find matches of a pattern. If it finds any, it + /// replaces them with the replacement string slice at most `count` times. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "foo foo 123 foo"; + /// assert_eq!("new new 123 foo", s.replacen("foo", "new", 2)); + /// assert_eq!("faa fao 123 foo", s.replacen('o', "a", 3)); + /// assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1)); + /// ``` + /// + /// When the pattern doesn't match, it returns this string slice as [`String`]: + /// + /// ``` + /// let s = "this is old"; + /// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10)); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[must_use = "this returns the replaced string as a new allocation, \ + without modifying the original"] + #[stable(feature = "str_replacen", since = "1.16.0")] + pub fn replacen(&self, pat: P, to: &str, count: usize) -> String { + // Hope to reduce the times of re-allocation + let mut result = String::with_capacity(32); + let mut last_end = 0; + for (start, part) in self.match_indices(pat).take(count) { + result.push_str(unsafe { self.get_unchecked(last_end..start) }); + result.push_str(to); + last_end = start + part.len(); + } + result.push_str(unsafe { self.get_unchecked(last_end..self.len()) }); + result + } + + /// Returns the lowercase equivalent of this string slice, as a new [`String`]. + /// + /// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property + /// `Lowercase`. + /// + /// Since some characters can expand into multiple characters when changing + /// the case, this function returns a [`String`] instead of modifying the + /// parameter in-place. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "HELLO"; + /// + /// assert_eq!("hello", s.to_lowercase()); + /// ``` + /// + /// A tricky example, with sigma: + /// + /// ``` + /// let sigma = "Σ"; + /// + /// assert_eq!("σ", sigma.to_lowercase()); + /// + /// // but at the end of a word, it's ς, not σ: + /// let odysseus = "ὈΔΥΣΣΕΎΣ"; + /// + /// assert_eq!("ὀδυσσεύς", odysseus.to_lowercase()); + /// ``` + /// + /// Languages without case are not changed: + /// + /// ``` + /// let new_year = "农历新年"; + /// + /// assert_eq!(new_year, new_year.to_lowercase()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[must_use = "this returns the lowercase string as a new String, \ + without modifying the original"] + #[stable(feature = "unicode_case_mapping", since = "1.2.0")] + pub fn to_lowercase(&self) -> String { + let (mut s, rest) = convert_while_ascii(self, u8::to_ascii_lowercase); + + let prefix_len = s.len(); + + for (i, c) in rest.char_indices() { + if c == 'Σ' { + // Σ maps to σ, except at the end of a word where it maps to ς. + // This is the only conditional (contextual) but language-independent mapping + // in `SpecialCasing.txt`, + // so hard-code it rather than have a generic "condition" mechanism. + // See https://github.com/rust-lang/rust/issues/26035 + let sigma_lowercase = map_uppercase_sigma(self, prefix_len + i); + s.push(sigma_lowercase); + } else { + match conversions::to_lower(c) { + [a, '\0', _] => s.push(a), + [a, b, '\0'] => { + s.push(a); + s.push(b); + } + [a, b, c] => { + s.push(a); + s.push(b); + s.push(c); + } + } + } + } + return s; + + fn map_uppercase_sigma(from: &str, i: usize) -> char { + // See https://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 + // for the definition of `Final_Sigma`. + debug_assert!('Σ'.len_utf8() == 2); + let is_word_final = case_ignorable_then_cased(from[..i].chars().rev()) + && !case_ignorable_then_cased(from[i + 2..].chars()); + if is_word_final { 'ς' } else { 'σ' } + } + + fn case_ignorable_then_cased>(iter: I) -> bool { + use core::unicode::{Case_Ignorable, Cased}; + match iter.skip_while(|&c| Case_Ignorable(c)).next() { + Some(c) => Cased(c), + None => false, + } + } + } + + /// Returns the uppercase equivalent of this string slice, as a new [`String`]. + /// + /// 'Uppercase' is defined according to the terms of the Unicode Derived Core Property + /// `Uppercase`. + /// + /// Since some characters can expand into multiple characters when changing + /// the case, this function returns a [`String`] instead of modifying the + /// parameter in-place. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "hello"; + /// + /// assert_eq!("HELLO", s.to_uppercase()); + /// ``` + /// + /// Scripts without case are not changed: + /// + /// ``` + /// let new_year = "农历新年"; + /// + /// assert_eq!(new_year, new_year.to_uppercase()); + /// ``` + /// + /// One character can become multiple: + /// ``` + /// let s = "tschüß"; + /// + /// assert_eq!("TSCHÜSS", s.to_uppercase()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[must_use = "this returns the uppercase string as a new String, \ + without modifying the original"] + #[stable(feature = "unicode_case_mapping", since = "1.2.0")] + pub fn to_uppercase(&self) -> String { + let (mut s, rest) = convert_while_ascii(self, u8::to_ascii_uppercase); + + for c in rest.chars() { + match conversions::to_upper(c) { + [a, '\0', _] => s.push(a), + [a, b, '\0'] => { + s.push(a); + s.push(b); + } + [a, b, c] => { + s.push(a); + s.push(b); + s.push(c); + } + } + } + s + } + + /// Converts a [`Box`] into a [`String`] without copying or allocating. + /// + /// # Examples + /// + /// ``` + /// let string = String::from("birthday gift"); + /// let boxed_str = string.clone().into_boxed_str(); + /// + /// assert_eq!(boxed_str.into_string(), string); + /// ``` + #[stable(feature = "box_str", since = "1.4.0")] + #[rustc_allow_incoherent_impl] + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub fn into_string(self: Box) -> String { + let slice = Box::<[u8]>::from(self); + unsafe { String::from_utf8_unchecked(slice.into_vec()) } + } + + /// Creates a new [`String`] by repeating a string `n` times. + /// + /// # Panics + /// + /// This function will panic if the capacity would overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!("abc".repeat(4), String::from("abcabcabcabc")); + /// ``` + /// + /// A panic upon overflow: + /// + /// ```should_panic + /// // this will panic at runtime + /// let huge = "0123456789abcdef".repeat(usize::MAX); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[must_use] + #[stable(feature = "repeat_str", since = "1.16.0")] + #[inline] + pub fn repeat(&self, n: usize) -> String { + unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) } + } + + /// Returns a copy of this string where each character is mapped to its + /// ASCII upper case equivalent. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To uppercase the value in-place, use [`make_ascii_uppercase`]. + /// + /// To uppercase ASCII characters in addition to non-ASCII characters, use + /// [`to_uppercase`]. + /// + /// # Examples + /// + /// ``` + /// let s = "Grüße, Jürgen ❤"; + /// + /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase()); + /// ``` + /// + /// [`make_ascii_uppercase`]: str::make_ascii_uppercase + /// [`to_uppercase`]: #method.to_uppercase + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"] + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[inline] + pub fn to_ascii_uppercase(&self) -> String { + let mut s = self.to_owned(); + s.make_ascii_uppercase(); + s + } + + /// Returns a copy of this string where each character is mapped to its + /// ASCII lower case equivalent. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To lowercase the value in-place, use [`make_ascii_lowercase`]. + /// + /// To lowercase ASCII characters in addition to non-ASCII characters, use + /// [`to_lowercase`]. + /// + /// # Examples + /// + /// ``` + /// let s = "Grüße, Jürgen ❤"; + /// + /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase()); + /// ``` + /// + /// [`make_ascii_lowercase`]: str::make_ascii_lowercase + /// [`to_lowercase`]: #method.to_lowercase + #[cfg(not(no_global_oom_handling))] + #[rustc_allow_incoherent_impl] + #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"] + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[inline] + pub fn to_ascii_lowercase(&self) -> String { + let mut s = self.to_owned(); + s.make_ascii_lowercase(); + s + } +} + +/// Converts a boxed slice of bytes to a boxed string slice without checking +/// that the string contains valid UTF-8. +/// +/// # Examples +/// +/// ``` +/// let smile_utf8 = Box::new([226, 152, 186]); +/// let smile = unsafe { std::str::from_boxed_utf8_unchecked(smile_utf8) }; +/// +/// assert_eq!("☺", &*smile); +/// ``` +#[stable(feature = "str_box_extras", since = "1.20.0")] +#[must_use] +#[inline] +pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box { + unsafe { Box::from_raw(Box::into_raw(v) as *mut str) } +} + +/// Converts leading ascii bytes in `s` by calling the `convert` function. +/// +/// For better average performance, this happens in chunks of `2*size_of::()`. +/// +/// Returns a tuple of the converted prefix and the remainder starting from +/// the first non-ascii character. +/// +/// This function is only public so that it can be verified in a codegen test, +/// see `issue-123712-str-to-lower-autovectorization.rs`. +#[unstable(feature = "str_internals", issue = "none")] +#[doc(hidden)] +#[inline] +#[cfg(not(test))] +#[cfg(not(no_global_oom_handling))] +pub fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, &str) { + // Process the input in chunks of 16 bytes to enable auto-vectorization. + // Previously the chunk size depended on the size of `usize`, + // but on 32-bit platforms with sse or neon is also the better choice. + // The only downside on other platforms would be a bit more loop-unrolling. + const N: usize = 16; + + let mut slice = s.as_bytes(); + let mut out = Vec::with_capacity(slice.len()); + let mut out_slice = out.spare_capacity_mut(); + + let mut ascii_prefix_len = 0_usize; + let mut is_ascii = [false; N]; + + while slice.len() >= N { + // SAFETY: checked in loop condition + let chunk = unsafe { slice.get_unchecked(..N) }; + // SAFETY: out_slice has at least same length as input slice and gets sliced with the same offsets + let out_chunk = unsafe { out_slice.get_unchecked_mut(..N) }; + + for j in 0..N { + is_ascii[j] = chunk[j] <= 127; + } + + // Auto-vectorization for this check is a bit fragile, sum and comparing against the chunk + // size gives the best result, specifically a pmovmsk instruction on x86. + // See https://github.com/llvm/llvm-project/issues/96395 for why llvm currently does not + // currently recognize other similar idioms. + if is_ascii.iter().map(|x| *x as u8).sum::() as usize != N { + break; + } + + for j in 0..N { + out_chunk[j] = MaybeUninit::new(convert(&chunk[j])); + } + + ascii_prefix_len += N; + slice = unsafe { slice.get_unchecked(N..) }; + out_slice = unsafe { out_slice.get_unchecked_mut(N..) }; + } + + // handle the remainder as individual bytes + while slice.len() > 0 { + let byte = slice[0]; + if byte > 127 { + break; + } + // SAFETY: out_slice has at least same length as input slice + unsafe { + *out_slice.get_unchecked_mut(0) = MaybeUninit::new(convert(&byte)); + } + ascii_prefix_len += 1; + slice = unsafe { slice.get_unchecked(1..) }; + out_slice = unsafe { out_slice.get_unchecked_mut(1..) }; + } + + unsafe { + // SAFETY: ascii_prefix_len bytes have been initialized above + out.set_len(ascii_prefix_len); + + // SAFETY: We have written only valid ascii to the output vec + let ascii_string = String::from_utf8_unchecked(out); + + // SAFETY: we know this is a valid char boundary + // since we only skipped over leading ascii bytes + let rest = core::str::from_utf8_unchecked(slice); + + (ascii_string, rest) + } +} +#[inline] +#[cfg(not(test))] +#[cfg(not(no_global_oom_handling))] +#[allow(dead_code)] +/// Faster implementation of string replacement for ASCII to ASCII cases. +/// Should produce fast vectorized code. +unsafe fn replace_ascii(utf8_bytes: &[u8], from: u8, to: u8) -> String { + let result: Vec = utf8_bytes.iter().map(|b| if *b == from { to } else { *b }).collect(); + // SAFETY: We replaced ascii with ascii on valid utf8 strings. + unsafe { String::from_utf8_unchecked(result) } +} diff --git a/CoqOfRust/alloc/string.rs b/CoqOfRust/alloc/string.rs new file mode 100644 index 000000000..e0576c255 --- /dev/null +++ b/CoqOfRust/alloc/string.rs @@ -0,0 +1,3219 @@ +//! A UTF-8–encoded, growable string. +//! +//! This module contains the [`String`] type, the [`ToString`] trait for +//! converting to strings, and several error types that may result from +//! working with [`String`]s. +//! +//! # Examples +//! +//! There are multiple ways to create a new [`String`] from a string literal: +//! +//! ``` +//! let s = "Hello".to_string(); +//! +//! let s = String::from("world"); +//! let s: String = "also this".into(); +//! ``` +//! +//! You can create a new [`String`] from an existing one by concatenating with +//! `+`: +//! +//! ``` +//! let s = "Hello".to_string(); +//! +//! let message = s + " world!"; +//! ``` +//! +//! If you have a vector of valid UTF-8 bytes, you can make a [`String`] out of +//! it. You can do the reverse too. +//! +//! ``` +//! let sparkle_heart = vec![240, 159, 146, 150]; +//! +//! // We know these bytes are valid, so we'll use `unwrap()`. +//! let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); +//! +//! assert_eq!("💖", sparkle_heart); +//! +//! let bytes = sparkle_heart.into_bytes(); +//! +//! assert_eq!(bytes, [240, 159, 146, 150]); +//! ``` + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::error::Error; +use core::iter::FusedIterator; +#[cfg(not(no_global_oom_handling))] +use core::iter::from_fn; +#[cfg(not(no_global_oom_handling))] +use core::ops::Add; +#[cfg(not(no_global_oom_handling))] +use core::ops::AddAssign; +#[cfg(not(no_global_oom_handling))] +use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{self, Range, RangeBounds}; +use core::str::pattern::{Pattern, Utf8Pattern}; +use core::{fmt, hash, ptr, slice}; + +#[cfg(not(no_global_oom_handling))] +use crate::alloc::Allocator; +#[cfg(not(no_global_oom_handling))] +use crate::borrow::{Cow, ToOwned}; +use crate::boxed::Box; +use crate::collections::TryReserveError; +use crate::str::{self, Chars, Utf8Error, from_utf8_unchecked_mut}; +#[cfg(not(no_global_oom_handling))] +use crate::str::{FromStr, from_boxed_utf8_unchecked}; +use crate::vec::Vec; + +/// A UTF-8–encoded, growable string. +/// +/// `String` is the most common string type. It has ownership over the contents +/// of the string, stored in a heap-allocated buffer (see [Representation](#representation)). +/// It is closely related to its borrowed counterpart, the primitive [`str`]. +/// +/// # Examples +/// +/// You can create a `String` from [a literal string][`&str`] with [`String::from`]: +/// +/// [`String::from`]: From::from +/// +/// ``` +/// let hello = String::from("Hello, world!"); +/// ``` +/// +/// You can append a [`char`] to a `String` with the [`push`] method, and +/// append a [`&str`] with the [`push_str`] method: +/// +/// ``` +/// let mut hello = String::from("Hello, "); +/// +/// hello.push('w'); +/// hello.push_str("orld!"); +/// ``` +/// +/// [`push`]: String::push +/// [`push_str`]: String::push_str +/// +/// If you have a vector of UTF-8 bytes, you can create a `String` from it with +/// the [`from_utf8`] method: +/// +/// ``` +/// // some bytes, in a vector +/// let sparkle_heart = vec![240, 159, 146, 150]; +/// +/// // We know these bytes are valid, so we'll use `unwrap()`. +/// let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); +/// +/// assert_eq!("💖", sparkle_heart); +/// ``` +/// +/// [`from_utf8`]: String::from_utf8 +/// +/// # UTF-8 +/// +/// `String`s are always valid UTF-8. If you need a non-UTF-8 string, consider +/// [`OsString`]. It is similar, but without the UTF-8 constraint. Because UTF-8 +/// is a variable width encoding, `String`s are typically smaller than an array of +/// the same `char`s: +/// +/// ``` +/// use std::mem; +/// +/// // `s` is ASCII which represents each `char` as one byte +/// let s = "hello"; +/// assert_eq!(s.len(), 5); +/// +/// // A `char` array with the same contents would be longer because +/// // every `char` is four bytes +/// let s = ['h', 'e', 'l', 'l', 'o']; +/// let size: usize = s.into_iter().map(|c| mem::size_of_val(&c)).sum(); +/// assert_eq!(size, 20); +/// +/// // However, for non-ASCII strings, the difference will be smaller +/// // and sometimes they are the same +/// let s = "💖💖💖💖💖"; +/// assert_eq!(s.len(), 20); +/// +/// let s = ['💖', '💖', '💖', '💖', '💖']; +/// let size: usize = s.into_iter().map(|c| mem::size_of_val(&c)).sum(); +/// assert_eq!(size, 20); +/// ``` +/// +/// This raises interesting questions as to how `s[i]` should work. +/// What should `i` be here? Several options include byte indices and +/// `char` indices but, because of UTF-8 encoding, only byte indices +/// would provide constant time indexing. Getting the `i`th `char`, for +/// example, is available using [`chars`]: +/// +/// ``` +/// let s = "hello"; +/// let third_character = s.chars().nth(2); +/// assert_eq!(third_character, Some('l')); +/// +/// let s = "💖💖💖💖💖"; +/// let third_character = s.chars().nth(2); +/// assert_eq!(third_character, Some('💖')); +/// ``` +/// +/// Next, what should `s[i]` return? Because indexing returns a reference +/// to underlying data it could be `&u8`, `&[u8]`, or something else similar. +/// Since we're only providing one index, `&u8` makes the most sense but that +/// might not be what the user expects and can be explicitly achieved with +/// [`as_bytes()`]: +/// +/// ``` +/// // The first byte is 104 - the byte value of `'h'` +/// let s = "hello"; +/// assert_eq!(s.as_bytes()[0], 104); +/// // or +/// assert_eq!(s.as_bytes()[0], b'h'); +/// +/// // The first byte is 240 which isn't obviously useful +/// let s = "💖💖💖💖💖"; +/// assert_eq!(s.as_bytes()[0], 240); +/// ``` +/// +/// Due to these ambiguities/restrictions, indexing with a `usize` is simply +/// forbidden: +/// +/// ```compile_fail,E0277 +/// let s = "hello"; +/// +/// // The following will not compile! +/// println!("The first letter of s is {}", s[0]); +/// ``` +/// +/// It is more clear, however, how `&s[i..j]` should work (that is, +/// indexing with a range). It should accept byte indices (to be constant-time) +/// and return a `&str` which is UTF-8 encoded. This is also called "string slicing". +/// Note this will panic if the byte indices provided are not character +/// boundaries - see [`is_char_boundary`] for more details. See the implementations +/// for [`SliceIndex`] for more details on string slicing. For a non-panicking +/// version of string slicing, see [`get`]. +/// +/// [`OsString`]: ../../std/ffi/struct.OsString.html "ffi::OsString" +/// [`SliceIndex`]: core::slice::SliceIndex +/// [`as_bytes()`]: str::as_bytes +/// [`get`]: str::get +/// [`is_char_boundary`]: str::is_char_boundary +/// +/// The [`bytes`] and [`chars`] methods return iterators over the bytes and +/// codepoints of the string, respectively. To iterate over codepoints along +/// with byte indices, use [`char_indices`]. +/// +/// [`bytes`]: str::bytes +/// [`chars`]: str::chars +/// [`char_indices`]: str::char_indices +/// +/// # Deref +/// +/// `String` implements [Deref], and so inherits all of [`str`]'s +/// methods. In addition, this means that you can pass a `String` to a +/// function which takes a [`&str`] by using an ampersand (`&`): +/// +/// ``` +/// fn takes_str(s: &str) { } +/// +/// let s = String::from("Hello"); +/// +/// takes_str(&s); +/// ``` +/// +/// This will create a [`&str`] from the `String` and pass it in. This +/// conversion is very inexpensive, and so generally, functions will accept +/// [`&str`]s as arguments unless they need a `String` for some specific +/// reason. +/// +/// In certain cases Rust doesn't have enough information to make this +/// conversion, known as [`Deref`] coercion. In the following example a string +/// slice [`&'a str`][`&str`] implements the trait `TraitExample`, and the function +/// `example_func` takes anything that implements the trait. In this case Rust +/// would need to make two implicit conversions, which Rust doesn't have the +/// means to do. For that reason, the following example will not compile. +/// +/// ```compile_fail,E0277 +/// trait TraitExample {} +/// +/// impl<'a> TraitExample for &'a str {} +/// +/// fn example_func(example_arg: A) {} +/// +/// let example_string = String::from("example_string"); +/// example_func(&example_string); +/// ``` +/// +/// There are two options that would work instead. The first would be to +/// change the line `example_func(&example_string);` to +/// `example_func(example_string.as_str());`, using the method [`as_str()`] +/// to explicitly extract the string slice containing the string. The second +/// way changes `example_func(&example_string);` to +/// `example_func(&*example_string);`. In this case we are dereferencing a +/// `String` to a [`str`], then referencing the [`str`] back to +/// [`&str`]. The second way is more idiomatic, however both work to do the +/// conversion explicitly rather than relying on the implicit conversion. +/// +/// # Representation +/// +/// A `String` is made up of three components: a pointer to some bytes, a +/// length, and a capacity. The pointer points to the internal buffer which `String` +/// uses to store its data. The length is the number of bytes currently stored +/// in the buffer, and the capacity is the size of the buffer in bytes. As such, +/// the length will always be less than or equal to the capacity. +/// +/// This buffer is always stored on the heap. +/// +/// You can look at these with the [`as_ptr`], [`len`], and [`capacity`] +/// methods: +/// +/// ``` +/// use std::mem; +/// +/// let story = String::from("Once upon a time..."); +/// +// FIXME Update this when vec_into_raw_parts is stabilized +/// // Prevent automatically dropping the String's data +/// let mut story = mem::ManuallyDrop::new(story); +/// +/// let ptr = story.as_mut_ptr(); +/// let len = story.len(); +/// let capacity = story.capacity(); +/// +/// // story has nineteen bytes +/// assert_eq!(19, len); +/// +/// // We can re-build a String out of ptr, len, and capacity. This is all +/// // unsafe because we are responsible for making sure the components are +/// // valid: +/// let s = unsafe { String::from_raw_parts(ptr, len, capacity) } ; +/// +/// assert_eq!(String::from("Once upon a time..."), s); +/// ``` +/// +/// [`as_ptr`]: str::as_ptr +/// [`len`]: String::len +/// [`capacity`]: String::capacity +/// +/// If a `String` has enough capacity, adding elements to it will not +/// re-allocate. For example, consider this program: +/// +/// ``` +/// let mut s = String::new(); +/// +/// println!("{}", s.capacity()); +/// +/// for _ in 0..5 { +/// s.push_str("hello"); +/// println!("{}", s.capacity()); +/// } +/// ``` +/// +/// This will output the following: +/// +/// ```text +/// 0 +/// 8 +/// 16 +/// 16 +/// 32 +/// 32 +/// ``` +/// +/// At first, we have no memory allocated at all, but as we append to the +/// string, it increases its capacity appropriately. If we instead use the +/// [`with_capacity`] method to allocate the correct capacity initially: +/// +/// ``` +/// let mut s = String::with_capacity(25); +/// +/// println!("{}", s.capacity()); +/// +/// for _ in 0..5 { +/// s.push_str("hello"); +/// println!("{}", s.capacity()); +/// } +/// ``` +/// +/// [`with_capacity`]: String::with_capacity +/// +/// We end up with a different output: +/// +/// ```text +/// 25 +/// 25 +/// 25 +/// 25 +/// 25 +/// 25 +/// ``` +/// +/// Here, there's no need to allocate more memory inside the loop. +/// +/// [str]: prim@str "str" +/// [`str`]: prim@str "str" +/// [`&str`]: prim@str "&str" +/// [Deref]: core::ops::Deref "ops::Deref" +/// [`Deref`]: core::ops::Deref "ops::Deref" +/// [`as_str()`]: String::as_str +#[derive(PartialEq, PartialOrd, Eq, Ord)] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), lang = "String")] +pub struct String { + vec: Vec, +} + +/// A possible error value when converting a `String` from a UTF-8 byte vector. +/// +/// This type is the error type for the [`from_utf8`] method on [`String`]. It +/// is designed in such a way to carefully avoid reallocations: the +/// [`into_bytes`] method will give back the byte vector that was used in the +/// conversion attempt. +/// +/// [`from_utf8`]: String::from_utf8 +/// [`into_bytes`]: FromUtf8Error::into_bytes +/// +/// The [`Utf8Error`] type provided by [`std::str`] represents an error that may +/// occur when converting a slice of [`u8`]s to a [`&str`]. In this sense, it's +/// an analogue to `FromUtf8Error`, and you can get one from a `FromUtf8Error` +/// through the [`utf8_error`] method. +/// +/// [`Utf8Error`]: str::Utf8Error "std::str::Utf8Error" +/// [`std::str`]: core::str "std::str" +/// [`&str`]: prim@str "&str" +/// [`utf8_error`]: FromUtf8Error::utf8_error +/// +/// # Examples +/// +/// ``` +/// // some invalid bytes, in a vector +/// let bytes = vec![0, 159]; +/// +/// let value = String::from_utf8(bytes); +/// +/// assert!(value.is_err()); +/// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(no_global_oom_handling), derive(Clone))] +#[derive(Debug, PartialEq, Eq)] +pub struct FromUtf8Error { + bytes: Vec, + error: Utf8Error, +} + +/// A possible error value when converting a `String` from a UTF-16 byte slice. +/// +/// This type is the error type for the [`from_utf16`] method on [`String`]. +/// +/// [`from_utf16`]: String::from_utf16 +/// +/// # Examples +/// +/// ``` +/// // 𝄞muic +/// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, +/// 0xD800, 0x0069, 0x0063]; +/// +/// assert!(String::from_utf16(v).is_err()); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct FromUtf16Error(()); + +impl String { + /// Creates a new empty `String`. + /// + /// Given that the `String` is empty, this will not allocate any initial + /// buffer. While that means that this initial operation is very + /// inexpensive, it may cause excessive allocation later when you add + /// data. If you have an idea of how much data the `String` will hold, + /// consider the [`with_capacity`] method to prevent excessive + /// re-allocation. + /// + /// [`with_capacity`]: String::with_capacity + /// + /// # Examples + /// + /// ``` + /// let s = String::new(); + /// ``` + #[inline] + #[rustc_const_stable(feature = "const_string_new", since = "1.39.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "string_new")] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub const fn new() -> String { + String { vec: Vec::new() } + } + + /// Creates a new empty `String` with at least the specified capacity. + /// + /// `String`s have an internal buffer to hold their data. The capacity is + /// the length of that buffer, and can be queried with the [`capacity`] + /// method. This method creates an empty `String`, but one with an initial + /// buffer that can hold at least `capacity` bytes. This is useful when you + /// may be appending a bunch of data to the `String`, reducing the number of + /// reallocations it needs to do. + /// + /// [`capacity`]: String::capacity + /// + /// If the given capacity is `0`, no allocation will occur, and this method + /// is identical to the [`new`] method. + /// + /// [`new`]: String::new + /// + /// # Examples + /// + /// ``` + /// let mut s = String::with_capacity(10); + /// + /// // The String contains no chars, even though it has capacity for more + /// assert_eq!(s.len(), 0); + /// + /// // These are all done without reallocating... + /// let cap = s.capacity(); + /// for _ in 0..10 { + /// s.push('a'); + /// } + /// + /// assert_eq!(s.capacity(), cap); + /// + /// // ...but this may make the string reallocate + /// s.push('a'); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub fn with_capacity(capacity: usize) -> String { + String { vec: Vec::with_capacity(capacity) } + } + + /// Creates a new empty `String` with at least the specified capacity. + /// + /// # Errors + /// + /// Returns [`Err`] if the capacity exceeds `isize::MAX` bytes, + /// or if the memory allocator reports failure. + /// + #[inline] + #[unstable(feature = "try_with_capacity", issue = "91913")] + pub fn try_with_capacity(capacity: usize) -> Result { + Ok(String { vec: Vec::try_with_capacity(capacity)? }) + } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is + // required for this method definition, is not available. Since we don't + // require this method for testing purposes, I'll just stub it + // NB see the slice::hack module in slice.rs for more information + #[inline] + #[cfg(test)] + #[allow(missing_docs)] + pub fn from_str(_: &str) -> String { + panic!("not available with cfg(test)"); + } + + /// Converts a vector of bytes to a `String`. + /// + /// A string ([`String`]) is made of bytes ([`u8`]), and a vector of bytes + /// ([`Vec`]) is made of bytes, so this function converts between the + /// two. Not all byte slices are valid `String`s, however: `String` + /// requires that it is valid UTF-8. `from_utf8()` checks to ensure that + /// the bytes are valid UTF-8, and then does the conversion. + /// + /// If you are sure that the byte slice is valid UTF-8, and you don't want + /// to incur the overhead of the validity check, there is an unsafe version + /// of this function, [`from_utf8_unchecked`], which has the same behavior + /// but skips the check. + /// + /// This method will take care to not copy the vector, for efficiency's + /// sake. + /// + /// If you need a [`&str`] instead of a `String`, consider + /// [`str::from_utf8`]. + /// + /// The inverse of this method is [`into_bytes`]. + /// + /// # Errors + /// + /// Returns [`Err`] if the slice is not UTF-8 with a description as to why the + /// provided bytes are not UTF-8. The vector you moved in is also included. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// // We know these bytes are valid, so we'll use `unwrap()`. + /// let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + /// + /// Incorrect bytes: + /// + /// ``` + /// // some invalid bytes, in a vector + /// let sparkle_heart = vec![0, 159, 146, 150]; + /// + /// assert!(String::from_utf8(sparkle_heart).is_err()); + /// ``` + /// + /// See the docs for [`FromUtf8Error`] for more details on what you can do + /// with this error. + /// + /// [`from_utf8_unchecked`]: String::from_utf8_unchecked + /// [`Vec`]: crate::vec::Vec "Vec" + /// [`&str`]: prim@str "&str" + /// [`into_bytes`]: String::into_bytes + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "string_from_utf8")] + pub fn from_utf8(vec: Vec) -> Result { + match str::from_utf8(&vec) { + Ok(..) => Ok(String { vec }), + Err(e) => Err(FromUtf8Error { bytes: vec, error: e }), + } + } + + /// Converts a slice of bytes to a string, including invalid characters. + /// + /// Strings are made of bytes ([`u8`]), and a slice of bytes + /// ([`&[u8]`][byteslice]) is made of bytes, so this function converts + /// between the two. Not all byte slices are valid strings, however: strings + /// are required to be valid UTF-8. During this conversion, + /// `from_utf8_lossy()` will replace any invalid UTF-8 sequences with + /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], which looks like this: � + /// + /// [byteslice]: prim@slice + /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER + /// + /// If you are sure that the byte slice is valid UTF-8, and you don't want + /// to incur the overhead of the conversion, there is an unsafe version + /// of this function, [`from_utf8_unchecked`], which has the same behavior + /// but skips the checks. + /// + /// [`from_utf8_unchecked`]: String::from_utf8_unchecked + /// + /// This function returns a [`Cow<'a, str>`]. If our byte slice is invalid + /// UTF-8, then we need to insert the replacement characters, which will + /// change the size of the string, and hence, require a `String`. But if + /// it's already valid UTF-8, we don't need a new allocation. This return + /// type allows us to handle both cases. + /// + /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// let sparkle_heart = String::from_utf8_lossy(&sparkle_heart); + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + /// + /// Incorrect bytes: + /// + /// ``` + /// // some invalid bytes + /// let input = b"Hello \xF0\x90\x80World"; + /// let output = String::from_utf8_lossy(input); + /// + /// assert_eq!("Hello �World", output); + /// ``` + #[must_use] + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> { + let mut iter = v.utf8_chunks(); + + let first_valid = if let Some(chunk) = iter.next() { + let valid = chunk.valid(); + if chunk.invalid().is_empty() { + debug_assert_eq!(valid.len(), v.len()); + return Cow::Borrowed(valid); + } + valid + } else { + return Cow::Borrowed(""); + }; + + const REPLACEMENT: &str = "\u{FFFD}"; + + let mut res = String::with_capacity(v.len()); + res.push_str(first_valid); + res.push_str(REPLACEMENT); + + for chunk in iter { + res.push_str(chunk.valid()); + if !chunk.invalid().is_empty() { + res.push_str(REPLACEMENT); + } + } + + Cow::Owned(res) + } + + /// Converts a [`Vec`] to a `String`, substituting invalid UTF-8 + /// sequences with replacement characters. + /// + /// See [`from_utf8_lossy`] for more details. + /// + /// [`from_utf8_lossy`]: String::from_utf8_lossy + /// + /// Note that this function does not guarantee reuse of the original `Vec` + /// allocation. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(string_from_utf8_lossy_owned)] + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// let sparkle_heart = String::from_utf8_lossy_owned(sparkle_heart); + /// + /// assert_eq!(String::from("💖"), sparkle_heart); + /// ``` + /// + /// Incorrect bytes: + /// + /// ``` + /// #![feature(string_from_utf8_lossy_owned)] + /// // some invalid bytes + /// let input: Vec = b"Hello \xF0\x90\x80World".into(); + /// let output = String::from_utf8_lossy_owned(input); + /// + /// assert_eq!(String::from("Hello �World"), output); + /// ``` + #[must_use] + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")] + pub fn from_utf8_lossy_owned(v: Vec) -> String { + if let Cow::Owned(string) = String::from_utf8_lossy(&v) { + string + } else { + // SAFETY: `String::from_utf8_lossy`'s contract ensures that if + // it returns a `Cow::Borrowed`, it is a valid UTF-8 string. + // Otherwise, it returns a new allocation of an owned `String`, with + // replacement characters for invalid sequences, which is returned + // above. + unsafe { String::from_utf8_unchecked(v) } + } + } + + /// Decode a UTF-16–encoded vector `v` into a `String`, returning [`Err`] + /// if `v` contains any invalid data. + /// + /// # Examples + /// + /// ``` + /// // 𝄞music + /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, + /// 0x0073, 0x0069, 0x0063]; + /// assert_eq!(String::from("𝄞music"), + /// String::from_utf16(v).unwrap()); + /// + /// // 𝄞muic + /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, + /// 0xD800, 0x0069, 0x0063]; + /// assert!(String::from_utf16(v).is_err()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_utf16(v: &[u16]) -> Result { + // This isn't done via collect::>() for performance reasons. + // FIXME: the function can be simplified again when #48994 is closed. + let mut ret = String::with_capacity(v.len()); + for c in char::decode_utf16(v.iter().cloned()) { + if let Ok(c) = c { + ret.push(c); + } else { + return Err(FromUtf16Error(())); + } + } + Ok(ret) + } + + /// Decode a UTF-16–encoded slice `v` into a `String`, replacing + /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. + /// + /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], + /// `from_utf16_lossy` returns a `String` since the UTF-16 to UTF-8 + /// conversion requires a memory allocation. + /// + /// [`from_utf8_lossy`]: String::from_utf8_lossy + /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" + /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER + /// + /// # Examples + /// + /// ``` + /// // 𝄞music + /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, + /// 0x0073, 0xDD1E, 0x0069, 0x0063, + /// 0xD834]; + /// + /// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), + /// String::from_utf16_lossy(v)); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[must_use] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_utf16_lossy(v: &[u16]) -> String { + char::decode_utf16(v.iter().cloned()) + .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)) + .collect() + } + + /// Decode a UTF-16LE–encoded vector `v` into a `String`, returning [`Err`] + /// if `v` contains any invalid data. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(str_from_utf16_endian)] + /// // 𝄞music + /// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, + /// 0x73, 0x00, 0x69, 0x00, 0x63, 0x00]; + /// assert_eq!(String::from("𝄞music"), + /// String::from_utf16le(v).unwrap()); + /// + /// // 𝄞muic + /// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, + /// 0x00, 0xD8, 0x69, 0x00, 0x63, 0x00]; + /// assert!(String::from_utf16le(v).is_err()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "str_from_utf16_endian", issue = "116258")] + pub fn from_utf16le(v: &[u8]) -> Result { + if v.len() % 2 != 0 { + return Err(FromUtf16Error(())); + } + match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { + (true, ([], v, [])) => Self::from_utf16(v), + _ => char::decode_utf16(v.array_chunks::<2>().copied().map(u16::from_le_bytes)) + .collect::>() + .map_err(|_| FromUtf16Error(())), + } + } + + /// Decode a UTF-16LE–encoded slice `v` into a `String`, replacing + /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. + /// + /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], + /// `from_utf16le_lossy` returns a `String` since the UTF-16 to UTF-8 + /// conversion requires a memory allocation. + /// + /// [`from_utf8_lossy`]: String::from_utf8_lossy + /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" + /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(str_from_utf16_endian)] + /// // 𝄞music + /// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, + /// 0x73, 0x00, 0x1E, 0xDD, 0x69, 0x00, 0x63, 0x00, + /// 0x34, 0xD8]; + /// + /// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), + /// String::from_utf16le_lossy(v)); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "str_from_utf16_endian", issue = "116258")] + pub fn from_utf16le_lossy(v: &[u8]) -> String { + match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { + (true, ([], v, [])) => Self::from_utf16_lossy(v), + (true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", + _ => { + let mut iter = v.array_chunks::<2>(); + let string = char::decode_utf16(iter.by_ref().copied().map(u16::from_le_bytes)) + .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)) + .collect(); + if iter.remainder().is_empty() { string } else { string + "\u{FFFD}" } + } + } + } + + /// Decode a UTF-16BE–encoded vector `v` into a `String`, returning [`Err`] + /// if `v` contains any invalid data. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(str_from_utf16_endian)] + /// // 𝄞music + /// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, + /// 0x00, 0x73, 0x00, 0x69, 0x00, 0x63]; + /// assert_eq!(String::from("𝄞music"), + /// String::from_utf16be(v).unwrap()); + /// + /// // 𝄞muic + /// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, + /// 0xD8, 0x00, 0x00, 0x69, 0x00, 0x63]; + /// assert!(String::from_utf16be(v).is_err()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "str_from_utf16_endian", issue = "116258")] + pub fn from_utf16be(v: &[u8]) -> Result { + if v.len() % 2 != 0 { + return Err(FromUtf16Error(())); + } + match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { + (true, ([], v, [])) => Self::from_utf16(v), + _ => char::decode_utf16(v.array_chunks::<2>().copied().map(u16::from_be_bytes)) + .collect::>() + .map_err(|_| FromUtf16Error(())), + } + } + + /// Decode a UTF-16BE–encoded slice `v` into a `String`, replacing + /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. + /// + /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], + /// `from_utf16le_lossy` returns a `String` since the UTF-16 to UTF-8 + /// conversion requires a memory allocation. + /// + /// [`from_utf8_lossy`]: String::from_utf8_lossy + /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" + /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(str_from_utf16_endian)] + /// // 𝄞music + /// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, + /// 0x00, 0x73, 0xDD, 0x1E, 0x00, 0x69, 0x00, 0x63, + /// 0xD8, 0x34]; + /// + /// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), + /// String::from_utf16be_lossy(v)); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "str_from_utf16_endian", issue = "116258")] + pub fn from_utf16be_lossy(v: &[u8]) -> String { + match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { + (true, ([], v, [])) => Self::from_utf16_lossy(v), + (true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", + _ => { + let mut iter = v.array_chunks::<2>(); + let string = char::decode_utf16(iter.by_ref().copied().map(u16::from_be_bytes)) + .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)) + .collect(); + if iter.remainder().is_empty() { string } else { string + "\u{FFFD}" } + } + } + } + + /// Decomposes a `String` into its raw components: `(pointer, length, capacity)`. + /// + /// Returns the raw pointer to the underlying data, the length of + /// the string (in bytes), and the allocated capacity of the data + /// (in bytes). These are the same arguments in the same order as + /// the arguments to [`from_raw_parts`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `String`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `String` with the [`from_raw_parts`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts`]: String::from_raw_parts + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts)] + /// let s = String::from("hello"); + /// + /// let (ptr, len, cap) = s.into_raw_parts(); + /// + /// let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) }; + /// assert_eq!(rebuilt, "hello"); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts(self) -> (*mut u8, usize, usize) { + self.vec.into_raw_parts() + } + + /// Creates a new `String` from a pointer, a length and a capacity. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * The memory at `buf` needs to have been previously allocated by the + /// same allocator the standard library uses, with a required alignment of exactly 1. + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the correct value. + /// * The first `length` bytes at `buf` need to be valid UTF-8. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example, it is normally **not** safe to + /// build a `String` from a pointer to a C `char` array containing UTF-8 + /// _unless_ you are certain that array was originally allocated by the + /// Rust standard library's allocator. + /// + /// The ownership of `buf` is effectively transferred to the + /// `String` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// # Examples + /// + /// ``` + /// use std::mem; + /// + /// unsafe { + /// let s = String::from("hello"); + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent automatically dropping the String's data + /// let mut s = mem::ManuallyDrop::new(s); + /// + /// let ptr = s.as_mut_ptr(); + /// let len = s.len(); + /// let capacity = s.capacity(); + /// + /// let s = String::from_raw_parts(ptr, len, capacity); + /// + /// assert_eq!(String::from("hello"), s); + /// } + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String { + unsafe { String { vec: Vec::from_raw_parts(buf, length, capacity) } } + } + + /// Converts a vector of bytes to a `String` without checking that the + /// string contains valid UTF-8. + /// + /// See the safe version, [`from_utf8`], for more details. + /// + /// [`from_utf8`]: String::from_utf8 + /// + /// # Safety + /// + /// This function is unsafe because it does not check that the bytes passed + /// to it are valid UTF-8. If this constraint is violated, it may cause + /// memory unsafety issues with future users of the `String`, as the rest of + /// the standard library assumes that `String`s are valid UTF-8. + /// + /// # Examples + /// + /// ``` + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// let sparkle_heart = unsafe { + /// String::from_utf8_unchecked(sparkle_heart) + /// }; + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn from_utf8_unchecked(bytes: Vec) -> String { + String { vec: bytes } + } + + /// Converts a `String` into a byte vector. + /// + /// This consumes the `String`, so we do not need to copy its contents. + /// + /// # Examples + /// + /// ``` + /// let s = String::from("hello"); + /// let bytes = s.into_bytes(); + /// + /// assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]); + /// ``` + #[inline] + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn into_bytes(self) -> Vec { + self.vec + } + + /// Extracts a string slice containing the entire `String`. + /// + /// # Examples + /// + /// ``` + /// let s = String::from("foo"); + /// + /// assert_eq!("foo", s.as_str()); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "string_as_str", since = "1.7.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_str")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn as_str(&self) -> &str { + // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error + // at construction. + unsafe { str::from_utf8_unchecked(self.vec.as_slice()) } + } + + /// Converts a `String` into a mutable string slice. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("foobar"); + /// let s_mut_str = s.as_mut_str(); + /// + /// s_mut_str.make_ascii_uppercase(); + /// + /// assert_eq!("FOOBAR", s_mut_str); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "string_as_str", since = "1.7.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_mut_str")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn as_mut_str(&mut self) -> &mut str { + // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error + // at construction. + unsafe { str::from_utf8_unchecked_mut(self.vec.as_mut_slice()) } + } + + /// Appends a given string slice onto the end of this `String`. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("foo"); + /// + /// s.push_str("bar"); + /// + /// assert_eq!("foobar", s); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("append", "push")] + #[cfg_attr(not(test), rustc_diagnostic_item = "string_push_str")] + pub fn push_str(&mut self, string: &str) { + self.vec.extend_from_slice(string.as_bytes()) + } + + /// Copies elements from `src` range to the end of the string. + /// + /// # Panics + /// + /// Panics if the starting point or end point do not lie on a [`char`] + /// boundary, or if they're out of bounds. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_extend_from_within)] + /// let mut string = String::from("abcde"); + /// + /// string.extend_from_within(2..); + /// assert_eq!(string, "abcdecde"); + /// + /// string.extend_from_within(..2); + /// assert_eq!(string, "abcdecdeab"); + /// + /// string.extend_from_within(4..8); + /// assert_eq!(string, "abcdecdeabecde"); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "string_extend_from_within", issue = "103806")] + pub fn extend_from_within(&mut self, src: R) + where + R: RangeBounds, + { + let src @ Range { start, end } = slice::range(src, ..self.len()); + + assert!(self.is_char_boundary(start)); + assert!(self.is_char_boundary(end)); + + self.vec.extend_from_within(src); + } + + /// Returns this `String`'s capacity, in bytes. + /// + /// # Examples + /// + /// ``` + /// let s = String::with_capacity(10); + /// + /// assert!(s.capacity() >= 10); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn capacity(&self) -> usize { + self.vec.capacity() + } + + /// Reserves capacity for at least `additional` bytes more than the + /// current length. The allocator may reserve more space to speculatively + /// avoid frequent allocations. After calling `reserve`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if capacity is already sufficient. + /// + /// # Panics + /// + /// Panics if the new capacity overflows [`usize`]. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::new(); + /// + /// s.reserve(10); + /// + /// assert!(s.capacity() >= 10); + /// ``` + /// + /// This might not actually increase the capacity: + /// + /// ``` + /// let mut s = String::with_capacity(10); + /// s.push('a'); + /// s.push('b'); + /// + /// // s now has a length of 2 and a capacity of at least 10 + /// let capacity = s.capacity(); + /// assert_eq!(2, s.len()); + /// assert!(capacity >= 10); + /// + /// // Since we already have at least an extra 8 capacity, calling this... + /// s.reserve(8); + /// + /// // ... doesn't actually increase. + /// assert_eq!(capacity, s.capacity()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve(&mut self, additional: usize) { + self.vec.reserve(additional) + } + + /// Reserves the minimum capacity for at least `additional` bytes more than + /// the current length. Unlike [`reserve`], this will not + /// deliberately over-allocate to speculatively avoid frequent allocations. + /// After calling `reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional`. Does nothing if the capacity is already + /// sufficient. + /// + /// [`reserve`]: String::reserve + /// + /// # Panics + /// + /// Panics if the new capacity overflows [`usize`]. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::new(); + /// + /// s.reserve_exact(10); + /// + /// assert!(s.capacity() >= 10); + /// ``` + /// + /// This might not actually increase the capacity: + /// + /// ``` + /// let mut s = String::with_capacity(10); + /// s.push('a'); + /// s.push('b'); + /// + /// // s now has a length of 2 and a capacity of at least 10 + /// let capacity = s.capacity(); + /// assert_eq!(2, s.len()); + /// assert!(capacity >= 10); + /// + /// // Since we already have at least an extra 8 capacity, calling this... + /// s.reserve_exact(8); + /// + /// // ... doesn't actually increase. + /// assert_eq!(capacity, s.capacity()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve_exact(&mut self, additional: usize) { + self.vec.reserve_exact(additional) + } + + /// Tries to reserve capacity for at least `additional` bytes more than the + /// current length. The allocator may reserve more space to speculatively + /// avoid frequent allocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional` if it returns + /// `Ok(())`. Does nothing if capacity is already sufficient. This method + /// preserves the contents even if an error occurs. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &str) -> Result { + /// let mut output = String::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.push_str(data); + /// + /// Ok(output) + /// } + /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); + /// ``` + #[stable(feature = "try_reserve", since = "1.57.0")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.vec.try_reserve(additional) + } + + /// Tries to reserve the minimum capacity for at least `additional` bytes + /// more than the current length. Unlike [`try_reserve`], this will not + /// deliberately over-allocate to speculatively avoid frequent allocations. + /// After calling `try_reserve_exact`, capacity will be greater than or + /// equal to `self.len() + additional` if it returns `Ok(())`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer [`try_reserve`] if future insertions are expected. + /// + /// [`try_reserve`]: String::try_reserve + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &str) -> Result { + /// let mut output = String::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve_exact(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.push_str(data); + /// + /// Ok(output) + /// } + /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); + /// ``` + #[stable(feature = "try_reserve", since = "1.57.0")] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.vec.try_reserve_exact(additional) + } + + /// Shrinks the capacity of this `String` to match its length. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to_fit(); + /// assert_eq!(3, s.capacity()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn shrink_to_fit(&mut self) { + self.vec.shrink_to_fit() + } + + /// Shrinks the capacity of this `String` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// If the current capacity is less than the lower limit, this is a no-op. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to(10); + /// assert!(s.capacity() >= 10); + /// s.shrink_to(0); + /// assert!(s.capacity() >= 3); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "shrink_to", since = "1.56.0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.vec.shrink_to(min_capacity) + } + + /// Appends the given [`char`] to the end of this `String`. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("abc"); + /// + /// s.push('1'); + /// s.push('2'); + /// s.push('3'); + /// + /// assert_eq!("abc123", s); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push(&mut self, ch: char) { + match ch.len_utf8() { + 1 => self.vec.push(ch as u8), + _ => self.vec.extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()), + } + } + + /// Returns a byte slice of this `String`'s contents. + /// + /// The inverse of this method is [`from_utf8`]. + /// + /// [`from_utf8`]: String::from_utf8 + /// + /// # Examples + /// + /// ``` + /// let s = String::from("hello"); + /// + /// assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes()); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn as_bytes(&self) -> &[u8] { + self.vec.as_slice() + } + + /// Shortens this `String` to the specified length. + /// + /// If `new_len` is greater than or equal to the string's current length, this has no + /// effect. + /// + /// Note that this method has no effect on the allocated capacity + /// of the string + /// + /// # Panics + /// + /// Panics if `new_len` does not lie on a [`char`] boundary. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("hello"); + /// + /// s.truncate(2); + /// + /// assert_eq!("he", s); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn truncate(&mut self, new_len: usize) { + if new_len <= self.len() { + assert!(self.is_char_boundary(new_len)); + self.vec.truncate(new_len) + } + } + + /// Removes the last character from the string buffer and returns it. + /// + /// Returns [`None`] if this `String` is empty. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("abč"); + /// + /// assert_eq!(s.pop(), Some('č')); + /// assert_eq!(s.pop(), Some('b')); + /// assert_eq!(s.pop(), Some('a')); + /// + /// assert_eq!(s.pop(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop(&mut self) -> Option { + let ch = self.chars().rev().next()?; + let newlen = self.len() - ch.len_utf8(); + unsafe { + self.vec.set_len(newlen); + } + Some(ch) + } + + /// Removes a [`char`] from this `String` at a byte position and returns it. + /// + /// This is an *O*(*n*) operation, as it requires copying every element in the + /// buffer. + /// + /// # Panics + /// + /// Panics if `idx` is larger than or equal to the `String`'s length, + /// or if it does not lie on a [`char`] boundary. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("abç"); + /// + /// assert_eq!(s.remove(0), 'a'); + /// assert_eq!(s.remove(1), 'ç'); + /// assert_eq!(s.remove(0), 'b'); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("delete", "take")] + pub fn remove(&mut self, idx: usize) -> char { + let ch = match self[idx..].chars().next() { + Some(ch) => ch, + None => panic!("cannot remove a char from the end of a string"), + }; + + let next = idx + ch.len_utf8(); + let len = self.len(); + unsafe { + ptr::copy(self.vec.as_ptr().add(next), self.vec.as_mut_ptr().add(idx), len - next); + self.vec.set_len(len - (next - idx)); + } + ch + } + + /// Remove all matches of pattern `pat` in the `String`. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_remove_matches)] + /// let mut s = String::from("Trees are not green, the sky is not blue."); + /// s.remove_matches("not "); + /// assert_eq!("Trees are green, the sky is blue.", s); + /// ``` + /// + /// Matches will be detected and removed iteratively, so in cases where + /// patterns overlap, only the first pattern will be removed: + /// + /// ``` + /// #![feature(string_remove_matches)] + /// let mut s = String::from("banana"); + /// s.remove_matches("ana"); + /// assert_eq!("bna", s); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "string_remove_matches", reason = "new API", issue = "72826")] + pub fn remove_matches(&mut self, pat: P) { + use core::str::pattern::Searcher; + + let rejections = { + let mut searcher = pat.into_searcher(self); + // Per Searcher::next: + // + // A Match result needs to contain the whole matched pattern, + // however Reject results may be split up into arbitrary many + // adjacent fragments. Both ranges may have zero length. + // + // In practice the implementation of Searcher::next_match tends to + // be more efficient, so we use it here and do some work to invert + // matches into rejections since that's what we want to copy below. + let mut front = 0; + let rejections: Vec<_> = from_fn(|| { + let (start, end) = searcher.next_match()?; + let prev_front = front; + front = end; + Some((prev_front, start)) + }) + .collect(); + rejections.into_iter().chain(core::iter::once((front, self.len()))) + }; + + let mut len = 0; + let ptr = self.vec.as_mut_ptr(); + + for (start, end) in rejections { + let count = end - start; + if start != len { + // SAFETY: per Searcher::next: + // + // The stream of Match and Reject values up to a Done will + // contain index ranges that are adjacent, non-overlapping, + // covering the whole haystack, and laying on utf8 + // boundaries. + unsafe { + ptr::copy(ptr.add(start), ptr.add(len), count); + } + } + len += count; + } + + unsafe { + self.vec.set_len(len); + } + } + + /// Retains only the characters specified by the predicate. + /// + /// In other words, remove all characters `c` such that `f(c)` returns `false`. + /// This method operates in place, visiting each character exactly once in the + /// original order, and preserves the order of the retained characters. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("f_o_ob_ar"); + /// + /// s.retain(|c| c != '_'); + /// + /// assert_eq!(s, "foobar"); + /// ``` + /// + /// Because the elements are visited exactly once in the original order, + /// external state may be used to decide which elements to keep. + /// + /// ``` + /// let mut s = String::from("abcde"); + /// let keep = [false, true, true, false, true]; + /// let mut iter = keep.iter(); + /// s.retain(|_| *iter.next().unwrap()); + /// assert_eq!(s, "bce"); + /// ``` + #[inline] + #[stable(feature = "string_retain", since = "1.26.0")] + pub fn retain(&mut self, mut f: F) + where + F: FnMut(char) -> bool, + { + struct SetLenOnDrop<'a> { + s: &'a mut String, + idx: usize, + del_bytes: usize, + } + + impl<'a> Drop for SetLenOnDrop<'a> { + fn drop(&mut self) { + let new_len = self.idx - self.del_bytes; + debug_assert!(new_len <= self.s.len()); + unsafe { self.s.vec.set_len(new_len) }; + } + } + + let len = self.len(); + let mut guard = SetLenOnDrop { s: self, idx: 0, del_bytes: 0 }; + + while guard.idx < len { + let ch = + // SAFETY: `guard.idx` is positive-or-zero and less that len so the `get_unchecked` + // is in bound. `self` is valid UTF-8 like string and the returned slice starts at + // a unicode code point so the `Chars` always return one character. + unsafe { guard.s.get_unchecked(guard.idx..len).chars().next().unwrap_unchecked() }; + let ch_len = ch.len_utf8(); + + if !f(ch) { + guard.del_bytes += ch_len; + } else if guard.del_bytes > 0 { + // SAFETY: `guard.idx` is in bound and `guard.del_bytes` represent the number of + // bytes that are erased from the string so the resulting `guard.idx - + // guard.del_bytes` always represent a valid unicode code point. + // + // `guard.del_bytes` >= `ch.len_utf8()`, so taking a slice with `ch.len_utf8()` len + // is safe. + ch.encode_utf8(unsafe { + crate::slice::from_raw_parts_mut( + guard.s.as_mut_ptr().add(guard.idx - guard.del_bytes), + ch.len_utf8(), + ) + }); + } + + // Point idx to the next char + guard.idx += ch_len; + } + + drop(guard); + } + + /// Inserts a character into this `String` at a byte position. + /// + /// This is an *O*(*n*) operation as it requires copying every element in the + /// buffer. + /// + /// # Panics + /// + /// Panics if `idx` is larger than the `String`'s length, or if it does not + /// lie on a [`char`] boundary. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::with_capacity(3); + /// + /// s.insert(0, 'f'); + /// s.insert(1, 'o'); + /// s.insert(2, 'o'); + /// + /// assert_eq!("foo", s); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("set")] + pub fn insert(&mut self, idx: usize, ch: char) { + assert!(self.is_char_boundary(idx)); + let mut bits = [0; 4]; + let bits = ch.encode_utf8(&mut bits).as_bytes(); + + unsafe { + self.insert_bytes(idx, bits); + } + } + + #[cfg(not(no_global_oom_handling))] + unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) { + let len = self.len(); + let amt = bytes.len(); + self.vec.reserve(amt); + + unsafe { + ptr::copy(self.vec.as_ptr().add(idx), self.vec.as_mut_ptr().add(idx + amt), len - idx); + ptr::copy_nonoverlapping(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt); + self.vec.set_len(len + amt); + } + } + + /// Inserts a string slice into this `String` at a byte position. + /// + /// This is an *O*(*n*) operation as it requires copying every element in the + /// buffer. + /// + /// # Panics + /// + /// Panics if `idx` is larger than the `String`'s length, or if it does not + /// lie on a [`char`] boundary. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("bar"); + /// + /// s.insert_str(0, "foo"); + /// + /// assert_eq!("foobar", s); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "insert_str", since = "1.16.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "string_insert_str")] + pub fn insert_str(&mut self, idx: usize, string: &str) { + assert!(self.is_char_boundary(idx)); + + unsafe { + self.insert_bytes(idx, string.as_bytes()); + } + } + + /// Returns a mutable reference to the contents of this `String`. + /// + /// # Safety + /// + /// This function is unsafe because the returned `&mut Vec` allows writing + /// bytes which are not valid UTF-8. If this constraint is violated, using + /// the original `String` after dropping the `&mut Vec` may violate memory + /// safety, as the rest of the standard library assumes that `String`s are + /// valid UTF-8. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("hello"); + /// + /// unsafe { + /// let vec = s.as_mut_vec(); + /// assert_eq!(&[104, 101, 108, 108, 111][..], &vec[..]); + /// + /// vec.reverse(); + /// } + /// assert_eq!(s, "olleh"); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const unsafe fn as_mut_vec(&mut self) -> &mut Vec { + &mut self.vec + } + + /// Returns the length of this `String`, in bytes, not [`char`]s or + /// graphemes. In other words, it might not be what a human considers the + /// length of the string. + /// + /// # Examples + /// + /// ``` + /// let a = String::from("foo"); + /// assert_eq!(a.len(), 3); + /// + /// let fancy_f = String::from("ƒoo"); + /// assert_eq!(fancy_f.len(), 4); + /// assert_eq!(fancy_f.chars().count(), 3); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + #[rustc_confusables("length", "size")] + pub const fn len(&self) -> usize { + self.vec.len() + } + + /// Returns `true` if this `String` has a length of zero, and `false` otherwise. + /// + /// # Examples + /// + /// ``` + /// let mut v = String::new(); + /// assert!(v.is_empty()); + /// + /// v.push('a'); + /// assert!(!v.is_empty()); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Splits the string into two at the given byte index. + /// + /// Returns a newly allocated `String`. `self` contains bytes `[0, at)`, and + /// the returned `String` contains bytes `[at, len)`. `at` must be on the + /// boundary of a UTF-8 code point. + /// + /// Note that the capacity of `self` does not change. + /// + /// # Panics + /// + /// Panics if `at` is not on a `UTF-8` code point boundary, or if it is beyond the last + /// code point of the string. + /// + /// # Examples + /// + /// ``` + /// # fn main() { + /// let mut hello = String::from("Hello, World!"); + /// let world = hello.split_off(7); + /// assert_eq!(hello, "Hello, "); + /// assert_eq!(world, "World!"); + /// # } + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "string_split_off", since = "1.16.0")] + #[must_use = "use `.truncate()` if you don't need the other half"] + pub fn split_off(&mut self, at: usize) -> String { + assert!(self.is_char_boundary(at)); + let other = self.vec.split_off(at); + unsafe { String::from_utf8_unchecked(other) } + } + + /// Truncates this `String`, removing all contents. + /// + /// While this means the `String` will have a length of zero, it does not + /// touch its capacity. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("foo"); + /// + /// s.clear(); + /// + /// assert!(s.is_empty()); + /// assert_eq!(0, s.len()); + /// assert_eq!(3, s.capacity()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + self.vec.clear() + } + + /// Removes the specified range from the string in bulk, returning all + /// removed characters as an iterator. + /// + /// The returned iterator keeps a mutable borrow on the string to optimize + /// its implementation. + /// + /// # Panics + /// + /// Panics if the starting point or end point do not lie on a [`char`] + /// boundary, or if they're out of bounds. + /// + /// # Leaking + /// + /// If the returned iterator goes out of scope without being dropped (due to + /// [`core::mem::forget`], for example), the string may still contain a copy + /// of any drained characters, or may have lost characters arbitrarily, + /// including characters outside the range. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("α is alpha, β is beta"); + /// let beta_offset = s.find('β').unwrap_or(s.len()); + /// + /// // Remove the range up until the β from the string + /// let t: String = s.drain(..beta_offset).collect(); + /// assert_eq!(t, "α is alpha, "); + /// assert_eq!(s, "β is beta"); + /// + /// // A full range clears the string, like `clear()` does + /// s.drain(..); + /// assert_eq!(s, ""); + /// ``` + #[stable(feature = "drain", since = "1.6.0")] + pub fn drain(&mut self, range: R) -> Drain<'_> + where + R: RangeBounds, + { + // Memory safety + // + // The String version of Drain does not have the memory safety issues + // of the vector version. The data is just plain bytes. + // Because the range removal happens in Drop, if the Drain iterator is leaked, + // the removal will not happen. + let Range { start, end } = slice::range(range, ..self.len()); + assert!(self.is_char_boundary(start)); + assert!(self.is_char_boundary(end)); + + // Take out two simultaneous borrows. The &mut String won't be accessed + // until iteration is over, in Drop. + let self_ptr = self as *mut _; + // SAFETY: `slice::range` and `is_char_boundary` do the appropriate bounds checks. + let chars_iter = unsafe { self.get_unchecked(start..end) }.chars(); + + Drain { start, end, iter: chars_iter, string: self_ptr } + } + + /// Removes the specified range in the string, + /// and replaces it with the given string. + /// The given string doesn't need to be the same length as the range. + /// + /// # Panics + /// + /// Panics if the starting point or end point do not lie on a [`char`] + /// boundary, or if they're out of bounds. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("α is alpha, β is beta"); + /// let beta_offset = s.find('β').unwrap_or(s.len()); + /// + /// // Replace the range up until the β from the string + /// s.replace_range(..beta_offset, "Α is capital alpha; "); + /// assert_eq!(s, "Α is capital alpha; β is beta"); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "splice", since = "1.27.0")] + pub fn replace_range(&mut self, range: R, replace_with: &str) + where + R: RangeBounds, + { + // Memory safety + // + // Replace_range does not have the memory safety issues of a vector Splice. + // of the vector version. The data is just plain bytes. + + // WARNING: Inlining this variable would be unsound (#81138) + let start = range.start_bound(); + match start { + Included(&n) => assert!(self.is_char_boundary(n)), + Excluded(&n) => assert!(self.is_char_boundary(n + 1)), + Unbounded => {} + }; + // WARNING: Inlining this variable would be unsound (#81138) + let end = range.end_bound(); + match end { + Included(&n) => assert!(self.is_char_boundary(n + 1)), + Excluded(&n) => assert!(self.is_char_boundary(n)), + Unbounded => {} + }; + + // Using `range` again would be unsound (#81138) + // We assume the bounds reported by `range` remain the same, but + // an adversarial implementation could change between calls + unsafe { self.as_mut_vec() }.splice((start, end), replace_with.bytes()); + } + + /// Converts this `String` into a [Box]<[str]>. + /// + /// Before doing the conversion, this method discards excess capacity like [`shrink_to_fit`]. + /// Note that this call may reallocate and copy the bytes of the string. + /// + /// [`shrink_to_fit`]: String::shrink_to_fit + /// [str]: prim@str "str" + /// + /// # Examples + /// + /// ``` + /// let s = String::from("hello"); + /// + /// let b = s.into_boxed_str(); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "box_str", since = "1.4.0")] + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub fn into_boxed_str(self) -> Box { + let slice = self.vec.into_boxed_slice(); + unsafe { from_boxed_utf8_unchecked(slice) } + } + + /// Consumes and leaks the `String`, returning a mutable reference to the contents, + /// `&'a mut str`. + /// + /// The caller has free choice over the returned lifetime, including `'static`. Indeed, + /// this function is ideally used for data that lives for the remainder of the program's life, + /// as dropping the returned reference will cause a memory leak. + /// + /// It does not reallocate or shrink the `String`, so the leaked allocation may include unused + /// capacity that is not part of the returned slice. If you want to discard excess capacity, + /// call [`into_boxed_str`], and then [`Box::leak`] instead. However, keep in mind that + /// trimming the capacity may result in a reallocation and copy. + /// + /// [`into_boxed_str`]: Self::into_boxed_str + /// + /// # Examples + /// + /// ``` + /// let x = String::from("bucket"); + /// let static_ref: &'static mut str = x.leak(); + /// assert_eq!(static_ref, "bucket"); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # drop(unsafe { Box::from_raw(static_ref) }); + /// ``` + #[stable(feature = "string_leak", since = "1.72.0")] + #[inline] + pub fn leak<'a>(self) -> &'a mut str { + let slice = self.vec.leak(); + unsafe { from_utf8_unchecked_mut(slice) } + } +} + +impl FromUtf8Error { + /// Returns a slice of [`u8`]s bytes that were attempted to convert to a `String`. + /// + /// # Examples + /// + /// ``` + /// // some invalid bytes, in a vector + /// let bytes = vec![0, 159]; + /// + /// let value = String::from_utf8(bytes); + /// + /// assert_eq!(&[0, 159], value.unwrap_err().as_bytes()); + /// ``` + #[must_use] + #[stable(feature = "from_utf8_error_as_bytes", since = "1.26.0")] + pub fn as_bytes(&self) -> &[u8] { + &self.bytes[..] + } + + /// Converts the bytes into a `String` lossily, substituting invalid UTF-8 + /// sequences with replacement characters. + /// + /// See [`String::from_utf8_lossy`] for more details on replacement of + /// invalid sequences, and [`String::from_utf8_lossy_owned`] for the + /// `String` function which corresponds to this function. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_from_utf8_lossy_owned)] + /// // some invalid bytes + /// let input: Vec = b"Hello \xF0\x90\x80World".into(); + /// let output = String::from_utf8(input).unwrap_or_else(|e| e.into_utf8_lossy()); + /// + /// assert_eq!(String::from("Hello �World"), output); + /// ``` + #[must_use] + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")] + pub fn into_utf8_lossy(self) -> String { + const REPLACEMENT: &str = "\u{FFFD}"; + + let mut res = { + let mut v = Vec::with_capacity(self.bytes.len()); + + // `Utf8Error::valid_up_to` returns the maximum index of validated + // UTF-8 bytes. Copy the valid bytes into the output buffer. + v.extend_from_slice(&self.bytes[..self.error.valid_up_to()]); + + // SAFETY: This is safe because the only bytes present in the buffer + // were validated as UTF-8 by the call to `String::from_utf8` which + // produced this `FromUtf8Error`. + unsafe { String::from_utf8_unchecked(v) } + }; + + let iter = self.bytes[self.error.valid_up_to()..].utf8_chunks(); + + for chunk in iter { + res.push_str(chunk.valid()); + if !chunk.invalid().is_empty() { + res.push_str(REPLACEMENT); + } + } + + res + } + + /// Returns the bytes that were attempted to convert to a `String`. + /// + /// This method is carefully constructed to avoid allocation. It will + /// consume the error, moving out the bytes, so that a copy of the bytes + /// does not need to be made. + /// + /// # Examples + /// + /// ``` + /// // some invalid bytes, in a vector + /// let bytes = vec![0, 159]; + /// + /// let value = String::from_utf8(bytes); + /// + /// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_bytes(self) -> Vec { + self.bytes + } + + /// Fetch a `Utf8Error` to get more details about the conversion failure. + /// + /// The [`Utf8Error`] type provided by [`std::str`] represents an error that may + /// occur when converting a slice of [`u8`]s to a [`&str`]. In this sense, it's + /// an analogue to `FromUtf8Error`. See its documentation for more details + /// on using it. + /// + /// [`std::str`]: core::str "std::str" + /// [`&str`]: prim@str "&str" + /// + /// # Examples + /// + /// ``` + /// // some invalid bytes, in a vector + /// let bytes = vec![0, 159]; + /// + /// let error = String::from_utf8(bytes).unwrap_err().utf8_error(); + /// + /// // the first byte is invalid here + /// assert_eq!(1, error.valid_up_to()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn utf8_error(&self) -> Utf8Error { + self.error + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for FromUtf8Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.error, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for FromUtf16Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt("invalid utf-16: lone surrogate found", f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for FromUtf8Error { + #[allow(deprecated)] + fn description(&self) -> &str { + "invalid utf-8" + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for FromUtf16Error { + #[allow(deprecated)] + fn description(&self) -> &str { + "invalid utf-16" + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for String { + fn clone(&self) -> Self { + String { vec: self.vec.clone() } + } + + /// Clones the contents of `source` into `self`. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids reallocation if possible. + fn clone_from(&mut self, source: &Self) { + self.vec.clone_from(&source.vec); + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for String { + fn from_iter>(iter: I) -> String { + let mut buf = String::new(); + buf.extend(iter); + buf + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "string_from_iter_by_ref", since = "1.17.0")] +impl<'a> FromIterator<&'a char> for String { + fn from_iter>(iter: I) -> String { + let mut buf = String::new(); + buf.extend(iter); + buf + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> FromIterator<&'a str> for String { + fn from_iter>(iter: I) -> String { + let mut buf = String::new(); + buf.extend(iter); + buf + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "extend_string", since = "1.4.0")] +impl FromIterator for String { + fn from_iter>(iter: I) -> String { + let mut iterator = iter.into_iter(); + + // Because we're iterating over `String`s, we can avoid at least + // one allocation by getting the first string from the iterator + // and appending to it all the subsequent strings. + match iterator.next() { + None => String::new(), + Some(mut buf) => { + buf.extend(iterator); + buf + } + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_str2", since = "1.45.0")] +impl FromIterator> for String { + fn from_iter>>(iter: I) -> String { + let mut buf = String::new(); + buf.extend(iter); + buf + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "herd_cows", since = "1.19.0")] +impl<'a> FromIterator> for String { + fn from_iter>>(iter: I) -> String { + let mut iterator = iter.into_iter(); + + // Because we're iterating over CoWs, we can (potentially) avoid at least + // one allocation by getting the first item and appending to it all the + // subsequent items. + match iterator.next() { + None => String::new(), + Some(cow) => { + let mut buf = cow.into_owned(); + buf.extend(iterator); + buf + } + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for String { + fn extend>(&mut self, iter: I) { + let iterator = iter.into_iter(); + let (lower_bound, _) = iterator.size_hint(); + self.reserve(lower_bound); + iterator.for_each(move |c| self.push(c)); + } + + #[inline] + fn extend_one(&mut self, c: char) { + self.push(c); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a> Extend<&'a char> for String { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()); + } + + #[inline] + fn extend_one(&mut self, &c: &'a char) { + self.push(c); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> Extend<&'a str> for String { + fn extend>(&mut self, iter: I) { + iter.into_iter().for_each(move |s| self.push_str(s)); + } + + #[inline] + fn extend_one(&mut self, s: &'a str) { + self.push_str(s); + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_str2", since = "1.45.0")] +impl Extend> for String { + fn extend>>(&mut self, iter: I) { + iter.into_iter().for_each(move |s| self.push_str(&s)); + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "extend_string", since = "1.4.0")] +impl Extend for String { + fn extend>(&mut self, iter: I) { + iter.into_iter().for_each(move |s| self.push_str(&s)); + } + + #[inline] + fn extend_one(&mut self, s: String) { + self.push_str(&s); + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "herd_cows", since = "1.19.0")] +impl<'a> Extend> for String { + fn extend>>(&mut self, iter: I) { + iter.into_iter().for_each(move |s| self.push_str(&s)); + } + + #[inline] + fn extend_one(&mut self, s: Cow<'a, str>) { + self.push_str(&s); + } +} + +/// A convenience impl that delegates to the impl for `&str`. +/// +/// # Examples +/// +/// ``` +/// assert_eq!(String::from("Hello world").find("world"), Some(6)); +/// ``` +#[unstable( + feature = "pattern", + reason = "API not fully fleshed out and ready to be stabilized", + issue = "27721" +)] +impl<'b> Pattern for &'b String { + type Searcher<'a> = <&'b str as Pattern>::Searcher<'a>; + + fn into_searcher(self, haystack: &str) -> <&'b str as Pattern>::Searcher<'_> { + self[..].into_searcher(haystack) + } + + #[inline] + fn is_contained_in(self, haystack: &str) -> bool { + self[..].is_contained_in(haystack) + } + + #[inline] + fn is_prefix_of(self, haystack: &str) -> bool { + self[..].is_prefix_of(haystack) + } + + #[inline] + fn strip_prefix_of(self, haystack: &str) -> Option<&str> { + self[..].strip_prefix_of(haystack) + } + + #[inline] + fn is_suffix_of<'a>(self, haystack: &'a str) -> bool + where + Self::Searcher<'a>: core::str::pattern::ReverseSearcher<'a>, + { + self[..].is_suffix_of(haystack) + } + + #[inline] + fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str> + where + Self::Searcher<'a>: core::str::pattern::ReverseSearcher<'a>, + { + self[..].strip_suffix_of(haystack) + } + + #[inline] + fn as_utf8_pattern(&self) -> Option> { + Some(Utf8Pattern::StringPattern(self.as_bytes())) + } +} + +macro_rules! impl_eq { + ($lhs:ty, $rhs: ty) => { + #[stable(feature = "rust1", since = "1.0.0")] + #[allow(unused_lifetimes)] + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + PartialEq::eq(&self[..], &other[..]) + } + #[inline] + fn ne(&self, other: &$rhs) -> bool { + PartialEq::ne(&self[..], &other[..]) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[allow(unused_lifetimes)] + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + PartialEq::eq(&self[..], &other[..]) + } + #[inline] + fn ne(&self, other: &$lhs) -> bool { + PartialEq::ne(&self[..], &other[..]) + } + } + }; +} + +impl_eq! { String, str } +impl_eq! { String, &'a str } +#[cfg(not(no_global_oom_handling))] +impl_eq! { Cow<'a, str>, str } +#[cfg(not(no_global_oom_handling))] +impl_eq! { Cow<'a, str>, &'b str } +#[cfg(not(no_global_oom_handling))] +impl_eq! { Cow<'a, str>, String } + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for String { + /// Creates an empty `String`. + #[inline] + fn default() -> String { + String::new() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for String { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for String { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl hash::Hash for String { + #[inline] + fn hash(&self, hasher: &mut H) { + (**self).hash(hasher) + } +} + +/// Implements the `+` operator for concatenating two strings. +/// +/// This consumes the `String` on the left-hand side and re-uses its buffer (growing it if +/// necessary). This is done to avoid allocating a new `String` and copying the entire contents on +/// every operation, which would lead to *O*(*n*^2) running time when building an *n*-byte string by +/// repeated concatenation. +/// +/// The string on the right-hand side is only borrowed; its contents are copied into the returned +/// `String`. +/// +/// # Examples +/// +/// Concatenating two `String`s takes the first by value and borrows the second: +/// +/// ``` +/// let a = String::from("hello"); +/// let b = String::from(" world"); +/// let c = a + &b; +/// // `a` is moved and can no longer be used here. +/// ``` +/// +/// If you want to keep using the first `String`, you can clone it and append to the clone instead: +/// +/// ``` +/// let a = String::from("hello"); +/// let b = String::from(" world"); +/// let c = a.clone() + &b; +/// // `a` is still valid here. +/// ``` +/// +/// Concatenating `&str` slices can be done by converting the first to a `String`: +/// +/// ``` +/// let a = "hello"; +/// let b = " world"; +/// let c = a.to_string() + b; +/// ``` +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Add<&str> for String { + type Output = String; + + #[inline] + fn add(mut self, other: &str) -> String { + self.push_str(other); + self + } +} + +/// Implements the `+=` operator for appending to a `String`. +/// +/// This has the same behavior as the [`push_str`][String::push_str] method. +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "stringaddassign", since = "1.12.0")] +impl AddAssign<&str> for String { + #[inline] + fn add_assign(&mut self, other: &str) { + self.push_str(other); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Index for String +where + I: slice::SliceIndex, +{ + type Output = I::Output; + + #[inline] + fn index(&self, index: I) -> &I::Output { + index.index(self.as_str()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::IndexMut for String +where + I: slice::SliceIndex, +{ + #[inline] + fn index_mut(&mut self, index: I) -> &mut I::Output { + index.index_mut(self.as_mut_str()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Deref for String { + type Target = str; + + #[inline] + fn deref(&self) -> &str { + self.as_str() + } +} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl ops::DerefPure for String {} + +#[stable(feature = "derefmut_for_string", since = "1.3.0")] +impl ops::DerefMut for String { + #[inline] + fn deref_mut(&mut self) -> &mut str { + self.as_mut_str() + } +} + +/// A type alias for [`Infallible`]. +/// +/// This alias exists for backwards compatibility, and may be eventually deprecated. +/// +/// [`Infallible`]: core::convert::Infallible "convert::Infallible" +#[stable(feature = "str_parse_error", since = "1.5.0")] +pub type ParseError = core::convert::Infallible; + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl FromStr for String { + type Err = core::convert::Infallible; + #[inline] + fn from_str(s: &str) -> Result { + Ok(String::from(s)) + } +} + +/// A trait for converting a value to a `String`. +/// +/// This trait is automatically implemented for any type which implements the +/// [`Display`] trait. As such, `ToString` shouldn't be implemented directly: +/// [`Display`] should be implemented instead, and you get the `ToString` +/// implementation for free. +/// +/// [`Display`]: fmt::Display +#[cfg_attr(not(test), rustc_diagnostic_item = "ToString")] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait ToString { + /// Converts the given value to a `String`. + /// + /// # Examples + /// + /// ``` + /// let i = 5; + /// let five = String::from("5"); + /// + /// assert_eq!(five, i.to_string()); + /// ``` + #[rustc_conversion_suggestion] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "to_string_method")] + fn to_string(&self) -> String; +} + +/// # Panics +/// +/// In this implementation, the `to_string` method panics +/// if the `Display` implementation returns an error. +/// This indicates an incorrect `Display` implementation +/// since `fmt::Write for String` never returns an error itself. +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl ToString for T { + // A common guideline is to not inline generic functions. However, + // removing `#[inline]` from this method causes non-negligible regressions. + // See , the last attempt + // to try to remove it. + #[inline] + default fn to_string(&self) -> String { + let mut buf = String::new(); + let mut formatter = core::fmt::Formatter::new(&mut buf); + // Bypass format_args!() to avoid write_str with zero-length strs + fmt::Display::fmt(self, &mut formatter) + .expect("a Display implementation returned an error unexpectedly"); + buf + } +} + +#[doc(hidden)] +#[cfg(not(no_global_oom_handling))] +#[unstable(feature = "ascii_char", issue = "110998")] +impl ToString for core::ascii::Char { + #[inline] + fn to_string(&self) -> String { + self.as_str().to_owned() + } +} + +#[doc(hidden)] +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "char_to_string_specialization", since = "1.46.0")] +impl ToString for char { + #[inline] + fn to_string(&self) -> String { + String::from(self.encode_utf8(&mut [0; 4])) + } +} + +#[doc(hidden)] +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "bool_to_string_specialization", since = "1.68.0")] +impl ToString for bool { + #[inline] + fn to_string(&self) -> String { + String::from(if *self { "true" } else { "false" }) + } +} + +#[doc(hidden)] +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "u8_to_string_specialization", since = "1.54.0")] +impl ToString for u8 { + #[inline] + fn to_string(&self) -> String { + let mut buf = String::with_capacity(3); + let mut n = *self; + if n >= 10 { + if n >= 100 { + buf.push((b'0' + n / 100) as char); + n %= 100; + } + buf.push((b'0' + n / 10) as char); + n %= 10; + } + buf.push((b'0' + n) as char); + buf + } +} + +#[doc(hidden)] +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "i8_to_string_specialization", since = "1.54.0")] +impl ToString for i8 { + #[inline] + fn to_string(&self) -> String { + let mut buf = String::with_capacity(4); + if self.is_negative() { + buf.push('-'); + } + let mut n = self.unsigned_abs(); + if n >= 10 { + if n >= 100 { + buf.push('1'); + n -= 100; + } + buf.push((b'0' + n / 10) as char); + n %= 10; + } + buf.push((b'0' + n) as char); + buf + } +} + +// Generic/generated code can sometimes have multiple, nested references +// for strings, including `&&&str`s that would never be written +// by hand. This macro generates twelve layers of nested `&`-impl +// for primitive strings. +#[cfg(not(no_global_oom_handling))] +macro_rules! to_string_str_wrap_in_ref { + {x $($x:ident)*} => { + &to_string_str_wrap_in_ref! { $($x)* } + }; + {} => { str }; +} +#[cfg(not(no_global_oom_handling))] +macro_rules! to_string_expr_wrap_in_deref { + {$self:expr ; x $($x:ident)*} => { + *(to_string_expr_wrap_in_deref! { $self ; $($x)* }) + }; + {$self:expr ;} => { $self }; +} +#[cfg(not(no_global_oom_handling))] +macro_rules! to_string_str { + {$($($x:ident)*),+} => { + $( + #[doc(hidden)] + #[stable(feature = "str_to_string_specialization", since = "1.9.0")] + impl ToString for to_string_str_wrap_in_ref!($($x)*) { + #[inline] + fn to_string(&self) -> String { + String::from(to_string_expr_wrap_in_deref!(self ; $($x)*)) + } + } + )+ + }; +} + +#[cfg(not(no_global_oom_handling))] +to_string_str! { + x x x x x x x x x x x x, + x x x x x x x x x x x, + x x x x x x x x x x, + x x x x x x x x x, + x x x x x x x x, + x x x x x x x, + x x x x x x, + x x x x x, + x x x x, + x x x, + x x, + x, +} + +#[doc(hidden)] +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_str_to_string_specialization", since = "1.17.0")] +impl ToString for Cow<'_, str> { + #[inline] + fn to_string(&self) -> String { + self[..].to_owned() + } +} + +#[doc(hidden)] +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "string_to_string_specialization", since = "1.17.0")] +impl ToString for String { + #[inline] + fn to_string(&self) -> String { + self.to_owned() + } +} + +#[doc(hidden)] +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "fmt_arguments_to_string_specialization", since = "1.71.0")] +impl ToString for fmt::Arguments<'_> { + #[inline] + fn to_string(&self) -> String { + crate::fmt::format(*self) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for String { + #[inline] + fn as_ref(&self) -> &str { + self + } +} + +#[stable(feature = "string_as_mut", since = "1.43.0")] +impl AsMut for String { + #[inline] + fn as_mut(&mut self) -> &mut str { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef<[u8]> for String { + #[inline] + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl From<&str> for String { + /// Converts a `&str` into a [`String`]. + /// + /// The result is allocated on the heap. + #[inline] + fn from(s: &str) -> String { + s.to_owned() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "from_mut_str_for_string", since = "1.44.0")] +impl From<&mut str> for String { + /// Converts a `&mut str` into a [`String`]. + /// + /// The result is allocated on the heap. + #[inline] + fn from(s: &mut str) -> String { + s.to_owned() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "from_ref_string", since = "1.35.0")] +impl From<&String> for String { + /// Converts a `&String` into a [`String`]. + /// + /// This clones `s` and returns the clone. + #[inline] + fn from(s: &String) -> String { + s.clone() + } +} + +// note: test pulls in std, which causes errors here +#[cfg(not(test))] +#[stable(feature = "string_from_box", since = "1.18.0")] +impl From> for String { + /// Converts the given boxed `str` slice to a [`String`]. + /// It is notable that the `str` slice is owned. + /// + /// # Examples + /// + /// ``` + /// let s1: String = String::from("hello world"); + /// let s2: Box = s1.into_boxed_str(); + /// let s3: String = String::from(s2); + /// + /// assert_eq!("hello world", s3) + /// ``` + fn from(s: Box) -> String { + s.into_string() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_str", since = "1.20.0")] +impl From for Box { + /// Converts the given [`String`] to a boxed `str` slice that is owned. + /// + /// # Examples + /// + /// ``` + /// let s1: String = String::from("hello world"); + /// let s2: Box = Box::from(s1); + /// let s3: String = String::from(s2); + /// + /// assert_eq!("hello world", s3) + /// ``` + fn from(s: String) -> Box { + s.into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "string_from_cow_str", since = "1.14.0")] +impl<'a> From> for String { + /// Converts a clone-on-write string to an owned + /// instance of [`String`]. + /// + /// This extracts the owned string, + /// clones the string if it is not already owned. + /// + /// # Example + /// + /// ``` + /// # use std::borrow::Cow; + /// // If the string is not owned... + /// let cow: Cow<'_, str> = Cow::Borrowed("eggplant"); + /// // It will allocate on the heap and copy the string. + /// let owned: String = String::from(cow); + /// assert_eq!(&owned[..], "eggplant"); + /// ``` + fn from(s: Cow<'a, str>) -> String { + s.into_owned() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> From<&'a str> for Cow<'a, str> { + /// Converts a string slice into a [`Borrowed`] variant. + /// No heap allocation is performed, and the string + /// is not copied. + /// + /// # Example + /// + /// ``` + /// # use std::borrow::Cow; + /// assert_eq!(Cow::from("eggplant"), Cow::Borrowed("eggplant")); + /// ``` + /// + /// [`Borrowed`]: crate::borrow::Cow::Borrowed "borrow::Cow::Borrowed" + #[inline] + fn from(s: &'a str) -> Cow<'a, str> { + Cow::Borrowed(s) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> From for Cow<'a, str> { + /// Converts a [`String`] into an [`Owned`] variant. + /// No heap allocation is performed, and the string + /// is not copied. + /// + /// # Example + /// + /// ``` + /// # use std::borrow::Cow; + /// let s = "eggplant".to_string(); + /// let s2 = "eggplant".to_string(); + /// assert_eq!(Cow::from(s), Cow::<'static, str>::Owned(s2)); + /// ``` + /// + /// [`Owned`]: crate::borrow::Cow::Owned "borrow::Cow::Owned" + #[inline] + fn from(s: String) -> Cow<'a, str> { + Cow::Owned(s) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_from_string_ref", since = "1.28.0")] +impl<'a> From<&'a String> for Cow<'a, str> { + /// Converts a [`String`] reference into a [`Borrowed`] variant. + /// No heap allocation is performed, and the string + /// is not copied. + /// + /// # Example + /// + /// ``` + /// # use std::borrow::Cow; + /// let s = "eggplant".to_string(); + /// assert_eq!(Cow::from(&s), Cow::Borrowed("eggplant")); + /// ``` + /// + /// [`Borrowed`]: crate::borrow::Cow::Borrowed "borrow::Cow::Borrowed" + #[inline] + fn from(s: &'a String) -> Cow<'a, str> { + Cow::Borrowed(s.as_str()) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_str_from_iter", since = "1.12.0")] +impl<'a> FromIterator for Cow<'a, str> { + fn from_iter>(it: I) -> Cow<'a, str> { + Cow::Owned(FromIterator::from_iter(it)) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_str_from_iter", since = "1.12.0")] +impl<'a, 'b> FromIterator<&'b str> for Cow<'a, str> { + fn from_iter>(it: I) -> Cow<'a, str> { + Cow::Owned(FromIterator::from_iter(it)) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_str_from_iter", since = "1.12.0")] +impl<'a> FromIterator for Cow<'a, str> { + fn from_iter>(it: I) -> Cow<'a, str> { + Cow::Owned(FromIterator::from_iter(it)) + } +} + +#[stable(feature = "from_string_for_vec_u8", since = "1.14.0")] +impl From for Vec { + /// Converts the given [`String`] to a vector [`Vec`] that holds values of type [`u8`]. + /// + /// # Examples + /// + /// ``` + /// let s1 = String::from("hello world"); + /// let v1 = Vec::from(s1); + /// + /// for b in v1 { + /// println!("{b}"); + /// } + /// ``` + fn from(string: String) -> Vec { + string.into_bytes() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Write for String { + #[inline] + fn write_str(&mut self, s: &str) -> fmt::Result { + self.push_str(s); + Ok(()) + } + + #[inline] + fn write_char(&mut self, c: char) -> fmt::Result { + self.push(c); + Ok(()) + } +} + +/// A draining iterator for `String`. +/// +/// This struct is created by the [`drain`] method on [`String`]. See its +/// documentation for more. +/// +/// [`drain`]: String::drain +#[stable(feature = "drain", since = "1.6.0")] +pub struct Drain<'a> { + /// Will be used as &'a mut String in the destructor + string: *mut String, + /// Start of part to remove + start: usize, + /// End of part to remove + end: usize, + /// Current remaining range to remove + iter: Chars<'a>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Drain<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Drain").field(&self.as_str()).finish() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Sync for Drain<'_> {} +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Send for Drain<'_> {} + +#[stable(feature = "drain", since = "1.6.0")] +impl Drop for Drain<'_> { + fn drop(&mut self) { + unsafe { + // Use Vec::drain. "Reaffirm" the bounds checks to avoid + // panic code being inserted again. + let self_vec = (*self.string).as_mut_vec(); + if self.start <= self.end && self.end <= self_vec.len() { + self_vec.drain(self.start..self.end); + } + } + } +} + +impl<'a> Drain<'a> { + /// Returns the remaining (sub)string of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("abc"); + /// let mut drain = s.drain(..); + /// assert_eq!(drain.as_str(), "abc"); + /// let _ = drain.next().unwrap(); + /// assert_eq!(drain.as_str(), "bc"); + /// ``` + #[must_use] + #[stable(feature = "string_drain_as_str", since = "1.55.0")] + pub fn as_str(&self) -> &str { + self.iter.as_str() + } +} + +#[stable(feature = "string_drain_as_str", since = "1.55.0")] +impl<'a> AsRef for Drain<'a> { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +#[stable(feature = "string_drain_as_str", since = "1.55.0")] +impl<'a> AsRef<[u8]> for Drain<'a> { + fn as_ref(&self) -> &[u8] { + self.as_str().as_bytes() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl Iterator for Drain<'_> { + type Item = char; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl DoubleEndedIterator for Drain<'_> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Drain<'_> {} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "from_char_for_string", since = "1.46.0")] +impl From for String { + /// Allocates an owned [`String`] from a single character. + /// + /// # Example + /// ```rust + /// let c: char = 'a'; + /// let s: String = String::from(c); + /// assert_eq!("a", &s[..]); + /// ``` + #[inline] + fn from(c: char) -> Self { + c.to_string() + } +} diff --git a/CoqOfRust/alloc/sync.rs b/CoqOfRust/alloc/sync.rs new file mode 100644 index 000000000..b8bdd298c --- /dev/null +++ b/CoqOfRust/alloc/sync.rs @@ -0,0 +1,4014 @@ +#![stable(feature = "rust1", since = "1.0.0")] + +//! Thread-safe reference-counting pointers. +//! +//! See the [`Arc`][Arc] documentation for more details. +//! +//! **Note**: This module is only available on platforms that support atomic +//! loads and stores of pointers. This may be detected at compile time using +//! `#[cfg(target_has_atomic = "ptr")]`. + +use core::any::Any; +#[cfg(not(no_global_oom_handling))] +use core::clone::CloneToUninit; +use core::cmp::Ordering; +use core::hash::{Hash, Hasher}; +use core::intrinsics::abort; +#[cfg(not(no_global_oom_handling))] +use core::iter; +use core::marker::{PhantomData, Unsize}; +use core::mem::{self, ManuallyDrop, align_of_val_raw}; +use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, LegacyReceiver}; +use core::panic::{RefUnwindSafe, UnwindSafe}; +use core::pin::{Pin, PinCoerceUnsized}; +use core::ptr::{self, NonNull}; +#[cfg(not(no_global_oom_handling))] +use core::slice::from_raw_parts_mut; +use core::sync::atomic; +use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; +use core::{borrow, fmt, hint}; + +#[cfg(not(no_global_oom_handling))] +use crate::alloc::handle_alloc_error; +use crate::alloc::{AllocError, Allocator, Global, Layout}; +use crate::borrow::{Cow, ToOwned}; +use crate::boxed::Box; +use crate::rc::is_dangling; +#[cfg(not(no_global_oom_handling))] +use crate::string::String; +#[cfg(not(no_global_oom_handling))] +use crate::vec::Vec; + +#[cfg(test)] +mod tests; + +/// A soft limit on the amount of references that may be made to an `Arc`. +/// +/// Going above this limit will abort your program (although not +/// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. +/// Trying to go above it might call a `panic` (if not actually going above it). +/// +/// This is a global invariant, and also applies when using a compare-exchange loop. +/// +/// See comment in `Arc::clone`. +const MAX_REFCOUNT: usize = (isize::MAX) as usize; + +/// The error in case either counter reaches above `MAX_REFCOUNT`, and we can `panic` safely. +const INTERNAL_OVERFLOW_ERROR: &str = "Arc counter overflow"; + +#[cfg(not(sanitize = "thread"))] +macro_rules! acquire { + ($x:expr) => { + atomic::fence(Acquire) + }; +} + +// ThreadSanitizer does not support memory fences. To avoid false positive +// reports in Arc / Weak implementation use atomic loads for synchronization +// instead. +#[cfg(sanitize = "thread")] +macro_rules! acquire { + ($x:expr) => { + $x.load(Acquire) + }; +} + +/// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically +/// Reference Counted'. +/// +/// The type `Arc` provides shared ownership of a value of type `T`, +/// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces +/// a new `Arc` instance, which points to the same allocation on the heap as the +/// source `Arc`, while increasing a reference count. When the last `Arc` +/// pointer to a given allocation is destroyed, the value stored in that allocation (often +/// referred to as "inner value") is also dropped. +/// +/// Shared references in Rust disallow mutation by default, and `Arc` is no +/// exception: you cannot generally obtain a mutable reference to something +/// inside an `Arc`. If you need to mutate through an `Arc`, use +/// [`Mutex`][mutex], [`RwLock`][rwlock], or one of the [`Atomic`][atomic] +/// types. +/// +/// **Note**: This type is only available on platforms that support atomic +/// loads and stores of pointers, which includes all platforms that support +/// the `std` crate but not all those which only support [`alloc`](crate). +/// This may be detected at compile time using `#[cfg(target_has_atomic = "ptr")]`. +/// +/// ## Thread Safety +/// +/// Unlike [`Rc`], `Arc` uses atomic operations for its reference +/// counting. This means that it is thread-safe. The disadvantage is that +/// atomic operations are more expensive than ordinary memory accesses. If you +/// are not sharing reference-counted allocations between threads, consider using +/// [`Rc`] for lower overhead. [`Rc`] is a safe default, because the +/// compiler will catch any attempt to send an [`Rc`] between threads. +/// However, a library might choose `Arc` in order to give library consumers +/// more flexibility. +/// +/// `Arc` will implement [`Send`] and [`Sync`] as long as the `T` implements +/// [`Send`] and [`Sync`]. Why can't you put a non-thread-safe type `T` in an +/// `Arc` to make it thread-safe? This may be a bit counter-intuitive at +/// first: after all, isn't the point of `Arc` thread safety? The key is +/// this: `Arc` makes it thread safe to have multiple ownership of the same +/// data, but it doesn't add thread safety to its data. Consider +/// Arc<[RefCell\]>. [`RefCell`] isn't [`Sync`], and if `Arc` was always +/// [`Send`], Arc<[RefCell\]> would be as well. But then we'd have a problem: +/// [`RefCell`] is not thread safe; it keeps track of the borrowing count using +/// non-atomic operations. +/// +/// In the end, this means that you may need to pair `Arc` with some sort of +/// [`std::sync`] type, usually [`Mutex`][mutex]. +/// +/// ## Breaking cycles with `Weak` +/// +/// The [`downgrade`][downgrade] method can be used to create a non-owning +/// [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d +/// to an `Arc`, but this will return [`None`] if the value stored in the allocation has +/// already been dropped. In other words, `Weak` pointers do not keep the value +/// inside the allocation alive; however, they *do* keep the allocation +/// (the backing store for the value) alive. +/// +/// A cycle between `Arc` pointers will never be deallocated. For this reason, +/// [`Weak`] is used to break cycles. For example, a tree could have +/// strong `Arc` pointers from parent nodes to children, and [`Weak`] +/// pointers from children back to their parents. +/// +/// # Cloning references +/// +/// Creating a new reference from an existing reference-counted pointer is done using the +/// `Clone` trait implemented for [`Arc`][Arc] and [`Weak`][Weak]. +/// +/// ``` +/// use std::sync::Arc; +/// let foo = Arc::new(vec![1.0, 2.0, 3.0]); +/// // The two syntaxes below are equivalent. +/// let a = foo.clone(); +/// let b = Arc::clone(&foo); +/// // a, b, and foo are all Arcs that point to the same memory location +/// ``` +/// +/// ## `Deref` behavior +/// +/// `Arc` automatically dereferences to `T` (via the [`Deref`] trait), +/// so you can call `T`'s methods on a value of type `Arc`. To avoid name +/// clashes with `T`'s methods, the methods of `Arc` itself are associated +/// functions, called using [fully qualified syntax]: +/// +/// ``` +/// use std::sync::Arc; +/// +/// let my_arc = Arc::new(()); +/// let my_weak = Arc::downgrade(&my_arc); +/// ``` +/// +/// `Arc`'s implementations of traits like `Clone` may also be called using +/// fully qualified syntax. Some people prefer to use fully qualified syntax, +/// while others prefer using method-call syntax. +/// +/// ``` +/// use std::sync::Arc; +/// +/// let arc = Arc::new(()); +/// // Method-call syntax +/// let arc2 = arc.clone(); +/// // Fully qualified syntax +/// let arc3 = Arc::clone(&arc); +/// ``` +/// +/// [`Weak`][Weak] does not auto-dereference to `T`, because the inner value may have +/// already been dropped. +/// +/// [`Rc`]: crate::rc::Rc +/// [clone]: Clone::clone +/// [mutex]: ../../std/sync/struct.Mutex.html +/// [rwlock]: ../../std/sync/struct.RwLock.html +/// [atomic]: core::sync::atomic +/// [downgrade]: Arc::downgrade +/// [upgrade]: Weak::upgrade +/// [RefCell\]: core::cell::RefCell +/// [`RefCell`]: core::cell::RefCell +/// [`std::sync`]: ../../std/sync/index.html +/// [`Arc::clone(&from)`]: Arc::clone +/// [fully qualified syntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name +/// +/// # Examples +/// +/// Sharing some immutable data between threads: +/// +/// ``` +/// use std::sync::Arc; +/// use std::thread; +/// +/// let five = Arc::new(5); +/// +/// for _ in 0..10 { +/// let five = Arc::clone(&five); +/// +/// thread::spawn(move || { +/// println!("{five:?}"); +/// }); +/// } +/// ``` +/// +/// Sharing a mutable [`AtomicUsize`]: +/// +/// [`AtomicUsize`]: core::sync::atomic::AtomicUsize "sync::atomic::AtomicUsize" +/// +/// ``` +/// use std::sync::Arc; +/// use std::sync::atomic::{AtomicUsize, Ordering}; +/// use std::thread; +/// +/// let val = Arc::new(AtomicUsize::new(5)); +/// +/// for _ in 0..10 { +/// let val = Arc::clone(&val); +/// +/// thread::spawn(move || { +/// let v = val.fetch_add(1, Ordering::Relaxed); +/// println!("{v:?}"); +/// }); +/// } +/// ``` +/// +/// See the [`rc` documentation][rc_examples] for more examples of reference +/// counting in general. +/// +/// [rc_examples]: crate::rc#examples +#[doc(search_unbox)] +#[cfg_attr(not(test), rustc_diagnostic_item = "Arc")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_insignificant_dtor] +pub struct Arc< + T: ?Sized, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + ptr: NonNull>, + phantom: PhantomData>, + alloc: A, +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for Arc {} +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for Arc {} + +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for Arc {} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U: ?Sized, A: Allocator> CoerceUnsized> for Arc {} + +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for Arc {} + +impl Arc { + unsafe fn from_inner(ptr: NonNull>) -> Self { + unsafe { Self::from_inner_in(ptr, Global) } + } + + unsafe fn from_ptr(ptr: *mut ArcInner) -> Self { + unsafe { Self::from_ptr_in(ptr, Global) } + } +} + +impl Arc { + #[inline] + fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { + let this = mem::ManuallyDrop::new(this); + (this.ptr, unsafe { ptr::read(&this.alloc) }) + } + + #[inline] + unsafe fn from_inner_in(ptr: NonNull>, alloc: A) -> Self { + Self { ptr, phantom: PhantomData, alloc } + } + + #[inline] + unsafe fn from_ptr_in(ptr: *mut ArcInner, alloc: A) -> Self { + unsafe { Self::from_inner_in(NonNull::new_unchecked(ptr), alloc) } + } +} + +/// `Weak` is a version of [`Arc`] that holds a non-owning reference to the +/// managed allocation. +/// +/// The allocation is accessed by calling [`upgrade`] on the `Weak` +/// pointer, which returns an [Option]<[Arc]\>. +/// +/// Since a `Weak` reference does not count towards ownership, it will not +/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no +/// guarantees about the value still being present. Thus it may return [`None`] +/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation +/// itself (the backing store) from being deallocated. +/// +/// A `Weak` pointer is useful for keeping a temporary reference to the allocation +/// managed by [`Arc`] without preventing its inner value from being dropped. It is also used to +/// prevent circular references between [`Arc`] pointers, since mutual owning references +/// would never allow either [`Arc`] to be dropped. For example, a tree could +/// have strong [`Arc`] pointers from parent nodes to children, and `Weak` +/// pointers from children back to their parents. +/// +/// The typical way to obtain a `Weak` pointer is to call [`Arc::downgrade`]. +/// +/// [`upgrade`]: Weak::upgrade +#[stable(feature = "arc_weak", since = "1.4.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "ArcWeak")] +pub struct Weak< + T: ?Sized, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + // This is a `NonNull` to allow optimizing the size of this type in enums, + // but it is not necessarily a valid pointer. + // `Weak::new` sets this to `usize::MAX` so that it doesn’t need + // to allocate space on the heap. That's not a value a real pointer + // will ever have because RcInner has alignment at least 2. + // This is only possible when `T: Sized`; unsized `T` never dangle. + ptr: NonNull>, + alloc: A, +} + +#[stable(feature = "arc_weak", since = "1.4.0")] +unsafe impl Send for Weak {} +#[stable(feature = "arc_weak", since = "1.4.0")] +unsafe impl Sync for Weak {} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U: ?Sized, A: Allocator> CoerceUnsized> for Weak {} +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for Weak {} + +#[stable(feature = "arc_weak", since = "1.4.0")] +impl fmt::Debug for Weak { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(Weak)") + } +} + +// This is repr(C) to future-proof against possible field-reordering, which +// would interfere with otherwise safe [into|from]_raw() of transmutable +// inner types. +#[repr(C)] +struct ArcInner { + strong: atomic::AtomicUsize, + + // the value usize::MAX acts as a sentinel for temporarily "locking" the + // ability to upgrade weak pointers or downgrade strong ones; this is used + // to avoid races in `make_mut` and `get_mut`. + weak: atomic::AtomicUsize, + + data: T, +} + +/// Calculate layout for `ArcInner` using the inner value's layout +fn arcinner_layout_for_value_layout(layout: Layout) -> Layout { + // Calculate layout using the given value layout. + // Previously, layout was calculated on the expression + // `&*(ptr as *const ArcInner)`, but this created a misaligned + // reference (see #54908). + Layout::new::>().extend(layout).unwrap().0.pad_to_align() +} + +unsafe impl Send for ArcInner {} +unsafe impl Sync for ArcInner {} + +impl Arc { + /// Constructs a new `Arc`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(data: T) -> Arc { + // Start the weak pointer count as 1 which is the weak pointer that's + // held by all the strong pointers (kinda), see std/rc.rs for more info + let x: Box<_> = Box::new(ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data, + }); + unsafe { Self::from_inner(Box::leak(x).into()) } + } + + /// Constructs a new `Arc` while giving you a `Weak` to the allocation, + /// to allow you to construct a `T` which holds a weak pointer to itself. + /// + /// Generally, a structure circularly referencing itself, either directly or + /// indirectly, should not hold a strong reference to itself to prevent a memory leak. + /// Using this function, you get access to the weak pointer during the + /// initialization of `T`, before the `Arc` is created, such that you can + /// clone and store it inside the `T`. + /// + /// `new_cyclic` first allocates the managed allocation for the `Arc`, + /// then calls your closure, giving it a `Weak` to this allocation, + /// and only afterwards completes the construction of the `Arc` by placing + /// the `T` returned from your closure into the allocation. + /// + /// Since the new `Arc` is not fully-constructed until `Arc::new_cyclic` + /// returns, calling [`upgrade`] on the weak reference inside your closure will + /// fail and result in a `None` value. + /// + /// # Panics + /// + /// If `data_fn` panics, the panic is propagated to the caller, and the + /// temporary [`Weak`] is dropped normally. + /// + /// # Example + /// + /// ``` + /// # #![allow(dead_code)] + /// use std::sync::{Arc, Weak}; + /// + /// struct Gadget { + /// me: Weak, + /// } + /// + /// impl Gadget { + /// /// Constructs a reference counted Gadget. + /// fn new() -> Arc { + /// // `me` is a `Weak` pointing at the new allocation of the + /// // `Arc` we're constructing. + /// Arc::new_cyclic(|me| { + /// // Create the actual struct here. + /// Gadget { me: me.clone() } + /// }) + /// } + /// + /// /// Returns a reference counted pointer to Self. + /// fn me(&self) -> Arc { + /// self.me.upgrade().unwrap() + /// } + /// } + /// ``` + /// [`upgrade`]: Weak::upgrade + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "arc_new_cyclic", since = "1.60.0")] + pub fn new_cyclic(data_fn: F) -> Arc + where + F: FnOnce(&Weak) -> T, + { + Self::new_cyclic_in(data_fn, Global) + } + + /// Constructs a new `Arc` with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::::new_uninit(); + /// + /// // Deferred initialization: + /// Arc::get_mut(&mut five).unwrap().write(5); + /// + /// let five = unsafe { five.assume_init() }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "new_uninit", since = "1.82.0")] + #[must_use] + pub fn new_uninit() -> Arc> { + unsafe { + Arc::from_ptr(Arc::allocate_for_layout( + Layout::new::(), + |layout| Global.allocate(layout), + <*mut u8>::cast, + )) + } + } + + /// Constructs a new `Arc` with uninitialized contents, with the memory + /// being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_zeroed_alloc)] + /// + /// use std::sync::Arc; + /// + /// let zero = Arc::::new_zeroed(); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[inline] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] + #[must_use] + pub fn new_zeroed() -> Arc> { + unsafe { + Arc::from_ptr(Arc::allocate_for_layout( + Layout::new::(), + |layout| Global.allocate_zeroed(layout), + <*mut u8>::cast, + )) + } + } + + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `data` will be pinned in memory and unable to be moved. + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "pin", since = "1.33.0")] + #[must_use] + pub fn pin(data: T) -> Pin> { + unsafe { Pin::new_unchecked(Arc::new(data)) } + } + + /// Constructs a new `Pin>`, return an error if allocation fails. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_pin(data: T) -> Result>, AllocError> { + unsafe { Ok(Pin::new_unchecked(Arc::try_new(data)?)) } + } + + /// Constructs a new `Arc`, returning an error if allocation fails. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::sync::Arc; + /// + /// let five = Arc::try_new(5)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new(data: T) -> Result, AllocError> { + // Start the weak pointer count as 1 which is the weak pointer that's + // held by all the strong pointers (kinda), see std/rc.rs for more info + let x: Box<_> = Box::try_new(ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data, + })?; + unsafe { Ok(Self::from_inner(Box::leak(x).into())) } + } + + /// Constructs a new `Arc` with uninitialized contents, returning an error + /// if allocation fails. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::::try_new_uninit()?; + /// + /// // Deferred initialization: + /// Arc::get_mut(&mut five).unwrap().write(5); + /// + /// let five = unsafe { five.assume_init() }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_uninit() -> Result>, AllocError> { + unsafe { + Ok(Arc::from_ptr(Arc::try_allocate_for_layout( + Layout::new::(), + |layout| Global.allocate(layout), + <*mut u8>::cast, + )?)) + } + } + + /// Constructs a new `Arc` with uninitialized contents, with the memory + /// being filled with `0` bytes, returning an error if allocation fails. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature( allocator_api)] + /// + /// use std::sync::Arc; + /// + /// let zero = Arc::::try_new_zeroed()?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_zeroed() -> Result>, AllocError> { + unsafe { + Ok(Arc::from_ptr(Arc::try_allocate_for_layout( + Layout::new::(), + |layout| Global.allocate_zeroed(layout), + <*mut u8>::cast, + )?)) + } + } +} + +impl Arc { + /// Constructs a new `Arc` in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let five = Arc::new_in(5, System); + /// ``` + #[inline] + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn new_in(data: T, alloc: A) -> Arc { + // Start the weak pointer count as 1 which is the weak pointer that's + // held by all the strong pointers (kinda), see std/rc.rs for more info + let x = Box::new_in( + ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data, + }, + alloc, + ); + let (ptr, alloc) = Box::into_unique(x); + unsafe { Self::from_inner_in(ptr.into(), alloc) } + } + + /// Constructs a new `Arc` with uninitialized contents in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// #![feature(allocator_api)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let mut five = Arc::::new_uninit_in(System); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn new_uninit_in(alloc: A) -> Arc, A> { + unsafe { + Arc::from_ptr_in( + Arc::allocate_for_layout( + Layout::new::(), + |layout| alloc.allocate(layout), + <*mut u8>::cast, + ), + alloc, + ) + } + } + + /// Constructs a new `Arc` with uninitialized contents, with the memory + /// being filled with `0` bytes, in the provided allocator. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let zero = Arc::::new_zeroed_in(System); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn new_zeroed_in(alloc: A) -> Arc, A> { + unsafe { + Arc::from_ptr_in( + Arc::allocate_for_layout( + Layout::new::(), + |layout| alloc.allocate_zeroed(layout), + <*mut u8>::cast, + ), + alloc, + ) + } + } + + /// Constructs a new `Arc` in the given allocator while giving you a `Weak` to the allocation, + /// to allow you to construct a `T` which holds a weak pointer to itself. + /// + /// Generally, a structure circularly referencing itself, either directly or + /// indirectly, should not hold a strong reference to itself to prevent a memory leak. + /// Using this function, you get access to the weak pointer during the + /// initialization of `T`, before the `Arc` is created, such that you can + /// clone and store it inside the `T`. + /// + /// `new_cyclic_in` first allocates the managed allocation for the `Arc`, + /// then calls your closure, giving it a `Weak` to this allocation, + /// and only afterwards completes the construction of the `Arc` by placing + /// the `T` returned from your closure into the allocation. + /// + /// Since the new `Arc` is not fully-constructed until `Arc::new_cyclic_in` + /// returns, calling [`upgrade`] on the weak reference inside your closure will + /// fail and result in a `None` value. + /// + /// # Panics + /// + /// If `data_fn` panics, the panic is propagated to the caller, and the + /// temporary [`Weak`] is dropped normally. + /// + /// # Example + /// + /// See [`new_cyclic`] + /// + /// [`new_cyclic`]: Arc::new_cyclic + /// [`upgrade`]: Weak::upgrade + #[cfg(not(no_global_oom_handling))] + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn new_cyclic_in(data_fn: F, alloc: A) -> Arc + where + F: FnOnce(&Weak) -> T, + { + // Construct the inner in the "uninitialized" state with a single + // weak reference. + let (uninit_raw_ptr, alloc) = Box::into_raw_with_allocator(Box::new_in( + ArcInner { + strong: atomic::AtomicUsize::new(0), + weak: atomic::AtomicUsize::new(1), + data: mem::MaybeUninit::::uninit(), + }, + alloc, + )); + let uninit_ptr: NonNull<_> = (unsafe { &mut *uninit_raw_ptr }).into(); + let init_ptr: NonNull> = uninit_ptr.cast(); + + let weak = Weak { ptr: init_ptr, alloc: alloc }; + + // It's important we don't give up ownership of the weak pointer, or + // else the memory might be freed by the time `data_fn` returns. If + // we really wanted to pass ownership, we could create an additional + // weak pointer for ourselves, but this would result in additional + // updates to the weak reference count which might not be necessary + // otherwise. + let data = data_fn(&weak); + + // Now we can properly initialize the inner value and turn our weak + // reference into a strong reference. + let strong = unsafe { + let inner = init_ptr.as_ptr(); + ptr::write(&raw mut (*inner).data, data); + + // The above write to the data field must be visible to any threads which + // observe a non-zero strong count. Therefore we need at least "Release" ordering + // in order to synchronize with the `compare_exchange_weak` in `Weak::upgrade`. + // + // "Acquire" ordering is not required. When considering the possible behaviors + // of `data_fn` we only need to look at what it could do with a reference to a + // non-upgradeable `Weak`: + // - It can *clone* the `Weak`, increasing the weak reference count. + // - It can drop those clones, decreasing the weak reference count (but never to zero). + // + // These side effects do not impact us in any way, and no other side effects are + // possible with safe code alone. + let prev_value = (*inner).strong.fetch_add(1, Release); + debug_assert_eq!(prev_value, 0, "No prior strong references should exist"); + + // Strong references should collectively own a shared weak reference, + // so don't run the destructor for our old weak reference. + // Calling into_raw_with_allocator has the double effect of giving us back the allocator, + // and forgetting the weak reference. + let alloc = weak.into_raw_with_allocator().1; + + Arc::from_inner_in(init_ptr, alloc) + }; + + strong + } + + /// Constructs a new `Pin>` in the provided allocator. If `T` does not implement `Unpin`, + /// then `data` will be pinned in memory and unable to be moved. + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn pin_in(data: T, alloc: A) -> Pin> + where + A: 'static, + { + unsafe { Pin::new_unchecked(Arc::new_in(data, alloc)) } + } + + /// Constructs a new `Pin>` in the provided allocator, return an error if allocation + /// fails. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn try_pin_in(data: T, alloc: A) -> Result>, AllocError> + where + A: 'static, + { + unsafe { Ok(Pin::new_unchecked(Arc::try_new_in(data, alloc)?)) } + } + + /// Constructs a new `Arc` in the provided allocator, returning an error if allocation fails. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let five = Arc::try_new_in(5, System)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new_in(data: T, alloc: A) -> Result, AllocError> { + // Start the weak pointer count as 1 which is the weak pointer that's + // held by all the strong pointers (kinda), see std/rc.rs for more info + let x = Box::try_new_in( + ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data, + }, + alloc, + )?; + let (ptr, alloc) = Box::into_unique(x); + Ok(unsafe { Self::from_inner_in(ptr.into(), alloc) }) + } + + /// Constructs a new `Arc` with uninitialized contents, in the provided allocator, returning an + /// error if allocation fails. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let mut five = Arc::::try_new_uninit_in(System)?; + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> { + unsafe { + Ok(Arc::from_ptr_in( + Arc::try_allocate_for_layout( + Layout::new::(), + |layout| alloc.allocate(layout), + <*mut u8>::cast, + )?, + alloc, + )) + } + } + + /// Constructs a new `Arc` with uninitialized contents, with the memory + /// being filled with `0` bytes, in the provided allocator, returning an error if allocation + /// fails. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let zero = Arc::::try_new_zeroed_in(System)?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> { + unsafe { + Ok(Arc::from_ptr_in( + Arc::try_allocate_for_layout( + Layout::new::(), + |layout| alloc.allocate_zeroed(layout), + <*mut u8>::cast, + )?, + alloc, + )) + } + } + /// Returns the inner value, if the `Arc` has exactly one strong reference. + /// + /// Otherwise, an [`Err`] is returned with the same `Arc` that was + /// passed in. + /// + /// This will succeed even if there are outstanding weak references. + /// + /// It is strongly recommended to use [`Arc::into_inner`] instead if you don't + /// keep the `Arc` in the [`Err`] case. + /// Immediately dropping the [`Err`]-value, as the expression + /// `Arc::try_unwrap(this).ok()` does, can cause the strong count to + /// drop to zero and the inner value of the `Arc` to be dropped. + /// For instance, if two threads execute such an expression in parallel, + /// there is a race condition without the possibility of unsafety: + /// The threads could first both check whether they own the last instance + /// in `Arc::try_unwrap`, determine that they both do not, and then both + /// discard and drop their instance in the call to [`ok`][`Result::ok`]. + /// In this scenario, the value inside the `Arc` is safely destroyed + /// by exactly one of the threads, but neither thread will ever be able + /// to use the value. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new(3); + /// assert_eq!(Arc::try_unwrap(x), Ok(3)); + /// + /// let x = Arc::new(4); + /// let _y = Arc::clone(&x); + /// assert_eq!(*Arc::try_unwrap(x).unwrap_err(), 4); + /// ``` + #[inline] + #[stable(feature = "arc_unique", since = "1.4.0")] + pub fn try_unwrap(this: Self) -> Result { + if this.inner().strong.compare_exchange(1, 0, Relaxed, Relaxed).is_err() { + return Err(this); + } + + acquire!(this.inner().strong); + + let this = ManuallyDrop::new(this); + let elem: T = unsafe { ptr::read(&this.ptr.as_ref().data) }; + let alloc: A = unsafe { ptr::read(&this.alloc) }; // copy the allocator + + // Make a weak pointer to clean up the implicit strong-weak reference + let _weak = Weak { ptr: this.ptr, alloc }; + + Ok(elem) + } + + /// Returns the inner value, if the `Arc` has exactly one strong reference. + /// + /// Otherwise, [`None`] is returned and the `Arc` is dropped. + /// + /// This will succeed even if there are outstanding weak references. + /// + /// If `Arc::into_inner` is called on every clone of this `Arc`, + /// it is guaranteed that exactly one of the calls returns the inner value. + /// This means in particular that the inner value is not dropped. + /// + /// [`Arc::try_unwrap`] is conceptually similar to `Arc::into_inner`, but it + /// is meant for different use-cases. If used as a direct replacement + /// for `Arc::into_inner` anyway, such as with the expression + /// [Arc::try_unwrap]\(this).[ok][Result::ok](), then it does + /// **not** give the same guarantee as described in the previous paragraph. + /// For more information, see the examples below and read the documentation + /// of [`Arc::try_unwrap`]. + /// + /// # Examples + /// + /// Minimal example demonstrating the guarantee that `Arc::into_inner` gives. + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new(3); + /// let y = Arc::clone(&x); + /// + /// // Two threads calling `Arc::into_inner` on both clones of an `Arc`: + /// let x_thread = std::thread::spawn(|| Arc::into_inner(x)); + /// let y_thread = std::thread::spawn(|| Arc::into_inner(y)); + /// + /// let x_inner_value = x_thread.join().unwrap(); + /// let y_inner_value = y_thread.join().unwrap(); + /// + /// // One of the threads is guaranteed to receive the inner value: + /// assert!(matches!( + /// (x_inner_value, y_inner_value), + /// (None, Some(3)) | (Some(3), None) + /// )); + /// // The result could also be `(None, None)` if the threads called + /// // `Arc::try_unwrap(x).ok()` and `Arc::try_unwrap(y).ok()` instead. + /// ``` + /// + /// A more practical example demonstrating the need for `Arc::into_inner`: + /// ``` + /// use std::sync::Arc; + /// + /// // Definition of a simple singly linked list using `Arc`: + /// #[derive(Clone)] + /// struct LinkedList(Option>>); + /// struct Node(T, Option>>); + /// + /// // Dropping a long `LinkedList` relying on the destructor of `Arc` + /// // can cause a stack overflow. To prevent this, we can provide a + /// // manual `Drop` implementation that does the destruction in a loop: + /// impl Drop for LinkedList { + /// fn drop(&mut self) { + /// let mut link = self.0.take(); + /// while let Some(arc_node) = link.take() { + /// if let Some(Node(_value, next)) = Arc::into_inner(arc_node) { + /// link = next; + /// } + /// } + /// } + /// } + /// + /// // Implementation of `new` and `push` omitted + /// impl LinkedList { + /// /* ... */ + /// # fn new() -> Self { + /// # LinkedList(None) + /// # } + /// # fn push(&mut self, x: T) { + /// # self.0 = Some(Arc::new(Node(x, self.0.take()))); + /// # } + /// } + /// + /// // The following code could have still caused a stack overflow + /// // despite the manual `Drop` impl if that `Drop` impl had used + /// // `Arc::try_unwrap(arc).ok()` instead of `Arc::into_inner(arc)`. + /// + /// // Create a long list and clone it + /// let mut x = LinkedList::new(); + /// let size = 100000; + /// # let size = if cfg!(miri) { 100 } else { size }; + /// for i in 0..size { + /// x.push(i); // Adds i to the front of x + /// } + /// let y = x.clone(); + /// + /// // Drop the clones in parallel + /// let x_thread = std::thread::spawn(|| drop(x)); + /// let y_thread = std::thread::spawn(|| drop(y)); + /// x_thread.join().unwrap(); + /// y_thread.join().unwrap(); + /// ``` + #[inline] + #[stable(feature = "arc_into_inner", since = "1.70.0")] + pub fn into_inner(this: Self) -> Option { + // Make sure that the ordinary `Drop` implementation isn’t called as well + let mut this = mem::ManuallyDrop::new(this); + + // Following the implementation of `drop` and `drop_slow` + if this.inner().strong.fetch_sub(1, Release) != 1 { + return None; + } + + acquire!(this.inner().strong); + + // SAFETY: This mirrors the line + // + // unsafe { ptr::drop_in_place(Self::get_mut_unchecked(self)) }; + // + // in `drop_slow`. Instead of dropping the value behind the pointer, + // it is read and eventually returned; `ptr::read` has the same + // safety conditions as `ptr::drop_in_place`. + + let inner = unsafe { ptr::read(Self::get_mut_unchecked(&mut this)) }; + let alloc = unsafe { ptr::read(&this.alloc) }; + + drop(Weak { ptr: this.ptr, alloc }); + + Some(inner) + } +} + +impl Arc<[T]> { + /// Constructs a new atomically reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); + /// + /// // Deferred initialization: + /// let data = Arc::get_mut(&mut values).unwrap(); + /// data[0].write(1); + /// data[1].write(2); + /// data[2].write(3); + /// + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "new_uninit", since = "1.82.0")] + #[must_use] + pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { + unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) } + } + + /// Constructs a new atomically reference-counted slice with uninitialized contents, with the memory being + /// filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_zeroed_alloc)] + /// + /// use std::sync::Arc; + /// + /// let values = Arc::<[u32]>::new_zeroed_slice(3); + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[inline] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] + #[must_use] + pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit]> { + unsafe { + Arc::from_ptr(Arc::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| Global.allocate_zeroed(layout), + |mem| { + ptr::slice_from_raw_parts_mut(mem as *mut T, len) + as *mut ArcInner<[mem::MaybeUninit]> + }, + )) + } + } +} + +impl Arc<[T], A> { + /// Constructs a new atomically reference-counted slice with uninitialized contents in the + /// provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// #![feature(allocator_api)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let mut values = Arc::<[u32], _>::new_uninit_slice_in(3, System); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn new_uninit_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit], A> { + unsafe { Arc::from_ptr_in(Arc::allocate_for_slice_in(len, &alloc), alloc) } + } + + /// Constructs a new atomically reference-counted slice with uninitialized contents, with the memory being + /// filled with `0` bytes, in the provided allocator. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let values = Arc::<[u32], _>::new_zeroed_slice_in(3, System); + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit], A> { + unsafe { + Arc::from_ptr_in( + Arc::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| alloc.allocate_zeroed(layout), + |mem| { + ptr::slice_from_raw_parts_mut(mem.cast::(), len) + as *mut ArcInner<[mem::MaybeUninit]> + }, + ), + alloc, + ) + } + } +} + +impl Arc, A> { + /// Converts to `Arc`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the inner value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::::new_uninit(); + /// + /// // Deferred initialization: + /// Arc::get_mut(&mut five).unwrap().write(5); + /// + /// let five = unsafe { five.assume_init() }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[stable(feature = "new_uninit", since = "1.82.0")] + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub unsafe fn assume_init(self) -> Arc { + let (ptr, alloc) = Arc::into_inner_with_allocator(self); + unsafe { Arc::from_inner_in(ptr.cast(), alloc) } + } +} + +impl Arc<[mem::MaybeUninit], A> { + /// Converts to `Arc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the inner value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); + /// + /// // Deferred initialization: + /// let data = Arc::get_mut(&mut values).unwrap(); + /// data[0].write(1); + /// data[1].write(2); + /// data[2].write(3); + /// + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[stable(feature = "new_uninit", since = "1.82.0")] + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub unsafe fn assume_init(self) -> Arc<[T], A> { + let (ptr, alloc) = Arc::into_inner_with_allocator(self); + unsafe { Arc::from_ptr_in(ptr.as_ptr() as _, alloc) } + } +} + +impl Arc { + /// Constructs an `Arc` from a raw pointer. + /// + /// The raw pointer must have been previously returned by a call to + /// [`Arc::into_raw`][into_raw] with the following requirements: + /// + /// * If `U` is sized, it must have the same size and alignment as `T`. This + /// is trivially true if `U` is `T`. + /// * If `U` is unsized, its data pointer must have the same size and + /// alignment as `T`. This is trivially true if `Arc` was constructed + /// through `Arc` and then converted to `Arc` through an [unsized + /// coercion]. + /// + /// Note that if `U` or `U`'s data pointer is not `T` but has the same size + /// and alignment, this is basically like transmuting references of + /// different types. See [`mem::transmute`][transmute] for more information + /// on what restrictions apply in this case. + /// + /// The user of `from_raw` has to make sure a specific value of `T` is only + /// dropped once. + /// + /// This function is unsafe because improper use may lead to memory unsafety, + /// even if the returned `Arc` is never accessed. + /// + /// [into_raw]: Arc::into_raw + /// [transmute]: core::mem::transmute + /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new("hello".to_owned()); + /// let x_ptr = Arc::into_raw(x); + /// + /// unsafe { + /// // Convert back to an `Arc` to prevent leak. + /// let x = Arc::from_raw(x_ptr); + /// assert_eq!(&*x, "hello"); + /// + /// // Further calls to `Arc::from_raw(x_ptr)` would be memory-unsafe. + /// } + /// + /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! + /// ``` + /// + /// Convert a slice back into its original array: + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x: Arc<[u32]> = Arc::new([1, 2, 3]); + /// let x_ptr: *const [u32] = Arc::into_raw(x); + /// + /// unsafe { + /// let x: Arc<[u32; 3]> = Arc::from_raw(x_ptr.cast::<[u32; 3]>()); + /// assert_eq!(&*x, &[1, 2, 3]); + /// } + /// ``` + #[inline] + #[stable(feature = "rc_raw", since = "1.17.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + unsafe { Arc::from_raw_in(ptr, Global) } + } + + /// Increments the strong reference count on the `Arc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Arc::into_raw`, and the + /// associated `Arc` instance must be valid (i.e. the strong count must be at + /// least 1) for the duration of this method. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// unsafe { + /// let ptr = Arc::into_raw(five); + /// Arc::increment_strong_count(ptr); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` between threads. + /// let five = Arc::from_raw(ptr); + /// assert_eq!(2, Arc::strong_count(&five)); + /// # // Prevent leaks for Miri. + /// # Arc::decrement_strong_count(ptr); + /// } + /// ``` + #[inline] + #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")] + pub unsafe fn increment_strong_count(ptr: *const T) { + unsafe { Arc::increment_strong_count_in(ptr, Global) } + } + + /// Decrements the strong reference count on the `Arc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Arc::into_raw`, and the + /// associated `Arc` instance must be valid (i.e. the strong count must be at + /// least 1) when invoking this method. This method can be used to release the final + /// `Arc` and backing storage, but **should not** be called after the final `Arc` has been + /// released. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// unsafe { + /// let ptr = Arc::into_raw(five); + /// Arc::increment_strong_count(ptr); + /// + /// // Those assertions are deterministic because we haven't shared + /// // the `Arc` between threads. + /// let five = Arc::from_raw(ptr); + /// assert_eq!(2, Arc::strong_count(&five)); + /// Arc::decrement_strong_count(ptr); + /// assert_eq!(1, Arc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")] + pub unsafe fn decrement_strong_count(ptr: *const T) { + unsafe { Arc::decrement_strong_count_in(ptr, Global) } + } +} + +impl Arc { + /// Returns a reference to the underlying allocator. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Arc::allocator(&a)` instead of `a.allocator()`. This + /// is so that there is no conflict with a method on the inner type. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(this: &Self) -> &A { + &this.alloc + } + + /// Consumes the `Arc`, returning the wrapped pointer. + /// + /// To avoid a memory leak the pointer must be converted back to an `Arc` using + /// [`Arc::from_raw`]. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new("hello".to_owned()); + /// let x_ptr = Arc::into_raw(x); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// # // Prevent leaks for Miri. + /// # drop(unsafe { Arc::from_raw(x_ptr) }); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[stable(feature = "rc_raw", since = "1.17.0")] + #[rustc_never_returns_null_ptr] + pub fn into_raw(this: Self) -> *const T { + let this = ManuallyDrop::new(this); + Self::as_ptr(&*this) + } + + /// Consumes the `Arc`, returning the wrapped pointer and allocator. + /// + /// To avoid a memory leak the pointer must be converted back to an `Arc` using + /// [`Arc::from_raw_in`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let x = Arc::new_in("hello".to_owned(), System); + /// let (ptr, alloc) = Arc::into_raw_with_allocator(x); + /// assert_eq!(unsafe { &*ptr }, "hello"); + /// let x = unsafe { Arc::from_raw_in(ptr, alloc) }; + /// assert_eq!(&*x, "hello"); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn into_raw_with_allocator(this: Self) -> (*const T, A) { + let this = mem::ManuallyDrop::new(this); + let ptr = Self::as_ptr(&this); + // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + let alloc = unsafe { ptr::read(&this.alloc) }; + (ptr, alloc) + } + + /// Provides a raw pointer to the data. + /// + /// The counts are not affected in any way and the `Arc` is not consumed. The pointer is valid for + /// as long as there are strong counts in the `Arc`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new("hello".to_owned()); + /// let y = Arc::clone(&x); + /// let x_ptr = Arc::as_ptr(&x); + /// assert_eq!(x_ptr, Arc::as_ptr(&y)); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// ``` + #[must_use] + #[stable(feature = "rc_as_ptr", since = "1.45.0")] + #[rustc_never_returns_null_ptr] + pub fn as_ptr(this: &Self) -> *const T { + let ptr: *mut ArcInner = NonNull::as_ptr(this.ptr); + + // SAFETY: This cannot go through Deref::deref or RcInnerPtr::inner because + // this is required to retain raw/mut provenance such that e.g. `get_mut` can + // write through the pointer after the Rc is recovered through `from_raw`. + unsafe { &raw mut (*ptr).data } + } + + /// Constructs an `Arc` from a raw pointer. + /// + /// The raw pointer must have been previously returned by a call to [`Arc::into_raw`][into_raw] with the following requirements: + /// + /// * If `U` is sized, it must have the same size and alignment as `T`. This + /// is trivially true if `U` is `T`. + /// * If `U` is unsized, its data pointer must have the same size and + /// alignment as `T`. This is trivially true if `Arc` was constructed + /// through `Arc` and then converted to `Arc` through an [unsized + /// coercion]. + /// + /// Note that if `U` or `U`'s data pointer is not `T` but has the same size + /// and alignment, this is basically like transmuting references of + /// different types. See [`mem::transmute`][transmute] for more information + /// on what restrictions apply in this case. + /// + /// The raw pointer must point to a block of memory allocated by `alloc` + /// + /// The user of `from_raw` has to make sure a specific value of `T` is only + /// dropped once. + /// + /// This function is unsafe because improper use may lead to memory unsafety, + /// even if the returned `Arc` is never accessed. + /// + /// [into_raw]: Arc::into_raw + /// [transmute]: core::mem::transmute + /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let x = Arc::new_in("hello".to_owned(), System); + /// let x_ptr = Arc::into_raw(x); + /// + /// unsafe { + /// // Convert back to an `Arc` to prevent leak. + /// let x = Arc::from_raw_in(x_ptr, System); + /// assert_eq!(&*x, "hello"); + /// + /// // Further calls to `Arc::from_raw(x_ptr)` would be memory-unsafe. + /// } + /// + /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! + /// ``` + /// + /// Convert a slice back into its original array: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let x: Arc<[u32], _> = Arc::new_in([1, 2, 3], System); + /// let x_ptr: *const [u32] = Arc::into_raw(x); + /// + /// unsafe { + /// let x: Arc<[u32; 3], _> = Arc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); + /// assert_eq!(&*x, &[1, 2, 3]); + /// } + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { + unsafe { + let offset = data_offset(ptr); + + // Reverse the offset to find the original ArcInner. + let arc_ptr = ptr.byte_sub(offset) as *mut ArcInner; + + Self::from_ptr_in(arc_ptr, alloc) + } + } + + /// Creates a new [`Weak`] pointer to this allocation. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// let weak_five = Arc::downgrade(&five); + /// ``` + #[must_use = "this returns a new `Weak` pointer, \ + without modifying the original `Arc`"] + #[stable(feature = "arc_weak", since = "1.4.0")] + pub fn downgrade(this: &Self) -> Weak + where + A: Clone, + { + // This Relaxed is OK because we're checking the value in the CAS + // below. + let mut cur = this.inner().weak.load(Relaxed); + + loop { + // check if the weak counter is currently "locked"; if so, spin. + if cur == usize::MAX { + hint::spin_loop(); + cur = this.inner().weak.load(Relaxed); + continue; + } + + // We can't allow the refcount to increase much past `MAX_REFCOUNT`. + assert!(cur <= MAX_REFCOUNT, "{}", INTERNAL_OVERFLOW_ERROR); + + // NOTE: this code currently ignores the possibility of overflow + // into usize::MAX; in general both Rc and Arc need to be adjusted + // to deal with overflow. + + // Unlike with Clone(), we need this to be an Acquire read to + // synchronize with the write coming from `is_unique`, so that the + // events prior to that write happen before this read. + match this.inner().weak.compare_exchange_weak(cur, cur + 1, Acquire, Relaxed) { + Ok(_) => { + // Make sure we do not create a dangling Weak + debug_assert!(!is_dangling(this.ptr.as_ptr())); + return Weak { ptr: this.ptr, alloc: this.alloc.clone() }; + } + Err(old) => cur = old, + } + } + } + + /// Gets the number of [`Weak`] pointers to this allocation. + /// + /// # Safety + /// + /// This method by itself is safe, but using it correctly requires extra care. + /// Another thread can change the weak count at any time, + /// including potentially between calling this method and acting on the result. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// let _weak_five = Arc::downgrade(&five); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` or `Weak` between threads. + /// assert_eq!(1, Arc::weak_count(&five)); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "arc_counts", since = "1.15.0")] + pub fn weak_count(this: &Self) -> usize { + let cnt = this.inner().weak.load(Relaxed); + // If the weak count is currently locked, the value of the + // count was 0 just before taking the lock. + if cnt == usize::MAX { 0 } else { cnt - 1 } + } + + /// Gets the number of strong (`Arc`) pointers to this allocation. + /// + /// # Safety + /// + /// This method by itself is safe, but using it correctly requires extra care. + /// Another thread can change the strong count at any time, + /// including potentially between calling this method and acting on the result. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// let _also_five = Arc::clone(&five); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` between threads. + /// assert_eq!(2, Arc::strong_count(&five)); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "arc_counts", since = "1.15.0")] + pub fn strong_count(this: &Self) -> usize { + this.inner().strong.load(Relaxed) + } + + /// Increments the strong reference count on the `Arc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Arc::into_raw`, and the + /// associated `Arc` instance must be valid (i.e. the strong count must be at + /// least 1) for the duration of this method,, and `ptr` must point to a block of memory + /// allocated by `alloc`. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let five = Arc::new_in(5, System); + /// + /// unsafe { + /// let ptr = Arc::into_raw(five); + /// Arc::increment_strong_count_in(ptr, System); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` between threads. + /// let five = Arc::from_raw_in(ptr, System); + /// assert_eq!(2, Arc::strong_count(&five)); + /// # // Prevent leaks for Miri. + /// # Arc::decrement_strong_count_in(ptr, System); + /// } + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub unsafe fn increment_strong_count_in(ptr: *const T, alloc: A) + where + A: Clone, + { + // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop + let arc = unsafe { mem::ManuallyDrop::new(Arc::from_raw_in(ptr, alloc)) }; + // Now increase refcount, but don't drop new refcount either + let _arc_clone: mem::ManuallyDrop<_> = arc.clone(); + } + + /// Decrements the strong reference count on the `Arc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Arc::into_raw`, the + /// associated `Arc` instance must be valid (i.e. the strong count must be at + /// least 1) when invoking this method, and `ptr` must point to a block of memory + /// allocated by `alloc`. This method can be used to release the final + /// `Arc` and backing storage, but **should not** be called after the final `Arc` has been + /// released. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let five = Arc::new_in(5, System); + /// + /// unsafe { + /// let ptr = Arc::into_raw(five); + /// Arc::increment_strong_count_in(ptr, System); + /// + /// // Those assertions are deterministic because we haven't shared + /// // the `Arc` between threads. + /// let five = Arc::from_raw_in(ptr, System); + /// assert_eq!(2, Arc::strong_count(&five)); + /// Arc::decrement_strong_count_in(ptr, System); + /// assert_eq!(1, Arc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub unsafe fn decrement_strong_count_in(ptr: *const T, alloc: A) { + unsafe { drop(Arc::from_raw_in(ptr, alloc)) }; + } + + #[inline] + fn inner(&self) -> &ArcInner { + // This unsafety is ok because while this arc is alive we're guaranteed + // that the inner pointer is valid. Furthermore, we know that the + // `ArcInner` structure itself is `Sync` because the inner data is + // `Sync` as well, so we're ok loaning out an immutable pointer to these + // contents. + unsafe { self.ptr.as_ref() } + } + + // Non-inlined part of `drop`. + #[inline(never)] + unsafe fn drop_slow(&mut self) { + // Drop the weak ref collectively held by all strong references when this + // variable goes out of scope. This ensures that the memory is deallocated + // even if the destructor of `T` panics. + // Take a reference to `self.alloc` instead of cloning because 1. it'll last long + // enough, and 2. you should be able to drop `Arc`s with unclonable allocators + let _weak = Weak { ptr: self.ptr, alloc: &self.alloc }; + + // Destroy the data at this time, even though we must not free the box + // allocation itself (there might still be weak pointers lying around). + // We cannot use `get_mut_unchecked` here, because `self.alloc` is borrowed. + unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) }; + } + + /// Returns `true` if the two `Arc`s point to the same allocation in a vein similar to + /// [`ptr::eq`]. This function ignores the metadata of `dyn Trait` pointers. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// let same_five = Arc::clone(&five); + /// let other_five = Arc::new(5); + /// + /// assert!(Arc::ptr_eq(&five, &same_five)); + /// assert!(!Arc::ptr_eq(&five, &other_five)); + /// ``` + /// + /// [`ptr::eq`]: core::ptr::eq "ptr::eq" + #[inline] + #[must_use] + #[stable(feature = "ptr_eq", since = "1.17.0")] + pub fn ptr_eq(this: &Self, other: &Self) -> bool { + ptr::addr_eq(this.ptr.as_ptr(), other.ptr.as_ptr()) + } +} + +impl Arc { + /// Allocates an `ArcInner` with sufficient space for + /// a possibly-unsized inner value where the value has the layout provided. + /// + /// The function `mem_to_arcinner` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `ArcInner`. + #[cfg(not(no_global_oom_handling))] + unsafe fn allocate_for_layout( + value_layout: Layout, + allocate: impl FnOnce(Layout) -> Result, AllocError>, + mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, + ) -> *mut ArcInner { + let layout = arcinner_layout_for_value_layout(value_layout); + + let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout)); + + unsafe { Self::initialize_arcinner(ptr, layout, mem_to_arcinner) } + } + + /// Allocates an `ArcInner` with sufficient space for + /// a possibly-unsized inner value where the value has the layout provided, + /// returning an error if allocation fails. + /// + /// The function `mem_to_arcinner` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `ArcInner`. + unsafe fn try_allocate_for_layout( + value_layout: Layout, + allocate: impl FnOnce(Layout) -> Result, AllocError>, + mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, + ) -> Result<*mut ArcInner, AllocError> { + let layout = arcinner_layout_for_value_layout(value_layout); + + let ptr = allocate(layout)?; + + let inner = unsafe { Self::initialize_arcinner(ptr, layout, mem_to_arcinner) }; + + Ok(inner) + } + + unsafe fn initialize_arcinner( + ptr: NonNull<[u8]>, + layout: Layout, + mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, + ) -> *mut ArcInner { + let inner = mem_to_arcinner(ptr.as_non_null_ptr().as_ptr()); + debug_assert_eq!(unsafe { Layout::for_value_raw(inner) }, layout); + + unsafe { + (&raw mut (*inner).strong).write(atomic::AtomicUsize::new(1)); + (&raw mut (*inner).weak).write(atomic::AtomicUsize::new(1)); + } + + inner + } +} + +impl Arc { + /// Allocates an `ArcInner` with sufficient space for an unsized inner value. + #[inline] + #[cfg(not(no_global_oom_handling))] + unsafe fn allocate_for_ptr_in(ptr: *const T, alloc: &A) -> *mut ArcInner { + // Allocate for the `ArcInner` using the given value. + unsafe { + Arc::allocate_for_layout( + Layout::for_value_raw(ptr), + |layout| alloc.allocate(layout), + |mem| mem.with_metadata_of(ptr as *const ArcInner), + ) + } + } + + #[cfg(not(no_global_oom_handling))] + fn from_box_in(src: Box) -> Arc { + unsafe { + let value_size = size_of_val(&*src); + let ptr = Self::allocate_for_ptr_in(&*src, Box::allocator(&src)); + + // Copy value as bytes + ptr::copy_nonoverlapping( + (&raw const *src) as *const u8, + (&raw mut (*ptr).data) as *mut u8, + value_size, + ); + + // Free the allocation without dropping its contents + let (bptr, alloc) = Box::into_raw_with_allocator(src); + let src = Box::from_raw_in(bptr as *mut mem::ManuallyDrop, alloc.by_ref()); + drop(src); + + Self::from_ptr_in(ptr, alloc) + } + } +} + +impl Arc<[T]> { + /// Allocates an `ArcInner<[T]>` with the given length. + #[cfg(not(no_global_oom_handling))] + unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> { + unsafe { + Self::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| Global.allocate(layout), + |mem| ptr::slice_from_raw_parts_mut(mem.cast::(), len) as *mut ArcInner<[T]>, + ) + } + } + + /// Copy elements from slice into newly allocated `Arc<[T]>` + /// + /// Unsafe because the caller must either take ownership or bind `T: Copy`. + #[cfg(not(no_global_oom_handling))] + unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> { + unsafe { + let ptr = Self::allocate_for_slice(v.len()); + + ptr::copy_nonoverlapping(v.as_ptr(), (&raw mut (*ptr).data) as *mut T, v.len()); + + Self::from_ptr(ptr) + } + } + + /// Constructs an `Arc<[T]>` from an iterator known to be of a certain size. + /// + /// Behavior is undefined should the size be wrong. + #[cfg(not(no_global_oom_handling))] + unsafe fn from_iter_exact(iter: impl Iterator, len: usize) -> Arc<[T]> { + // Panic guard while cloning T elements. + // In the event of a panic, elements that have been written + // into the new ArcInner will be dropped, then the memory freed. + struct Guard { + mem: NonNull, + elems: *mut T, + layout: Layout, + n_elems: usize, + } + + impl Drop for Guard { + fn drop(&mut self) { + unsafe { + let slice = from_raw_parts_mut(self.elems, self.n_elems); + ptr::drop_in_place(slice); + + Global.deallocate(self.mem, self.layout); + } + } + } + + unsafe { + let ptr = Self::allocate_for_slice(len); + + let mem = ptr as *mut _ as *mut u8; + let layout = Layout::for_value_raw(ptr); + + // Pointer to first element + let elems = (&raw mut (*ptr).data) as *mut T; + + let mut guard = Guard { mem: NonNull::new_unchecked(mem), elems, layout, n_elems: 0 }; + + for (i, item) in iter.enumerate() { + ptr::write(elems.add(i), item); + guard.n_elems += 1; + } + + // All clear. Forget the guard so it doesn't free the new ArcInner. + mem::forget(guard); + + Self::from_ptr(ptr) + } + } +} + +impl Arc<[T], A> { + /// Allocates an `ArcInner<[T]>` with the given length. + #[inline] + #[cfg(not(no_global_oom_handling))] + unsafe fn allocate_for_slice_in(len: usize, alloc: &A) -> *mut ArcInner<[T]> { + unsafe { + Arc::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| alloc.allocate(layout), + |mem| ptr::slice_from_raw_parts_mut(mem.cast::(), len) as *mut ArcInner<[T]>, + ) + } + } +} + +/// Specialization trait used for `From<&[T]>`. +#[cfg(not(no_global_oom_handling))] +trait ArcFromSlice { + fn from_slice(slice: &[T]) -> Self; +} + +#[cfg(not(no_global_oom_handling))] +impl ArcFromSlice for Arc<[T]> { + #[inline] + default fn from_slice(v: &[T]) -> Self { + unsafe { Self::from_iter_exact(v.iter().cloned(), v.len()) } + } +} + +#[cfg(not(no_global_oom_handling))] +impl ArcFromSlice for Arc<[T]> { + #[inline] + fn from_slice(v: &[T]) -> Self { + unsafe { Arc::copy_from_slice(v) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Arc { + /// Makes a clone of the `Arc` pointer. + /// + /// This creates another pointer to the same allocation, increasing the + /// strong reference count. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// let _ = Arc::clone(&five); + /// ``` + #[inline] + fn clone(&self) -> Arc { + // Using a relaxed ordering is alright here, as knowledge of the + // original reference prevents other threads from erroneously deleting + // the object. + // + // As explained in the [Boost documentation][1], Increasing the + // reference counter can always be done with memory_order_relaxed: New + // references to an object can only be formed from an existing + // reference, and passing an existing reference from one thread to + // another must already provide any required synchronization. + // + // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) + let old_size = self.inner().strong.fetch_add(1, Relaxed); + + // However we need to guard against massive refcounts in case someone is `mem::forget`ing + // Arcs. If we don't do this the count can overflow and users will use-after free. This + // branch will never be taken in any realistic program. We abort because such a program is + // incredibly degenerate, and we don't care to support it. + // + // This check is not 100% water-proof: we error when the refcount grows beyond `isize::MAX`. + // But we do that check *after* having done the increment, so there is a chance here that + // the worst already happened and we actually do overflow the `usize` counter. However, that + // requires the counter to grow from `isize::MAX` to `usize::MAX` between the increment + // above and the `abort` below, which seems exceedingly unlikely. + // + // This is a global invariant, and also applies when using a compare-exchange loop to increment + // counters in other methods. + // Otherwise, the counter could be brought to an almost-overflow using a compare-exchange loop, + // and then overflow using a few `fetch_add`s. + if old_size > MAX_REFCOUNT { + abort(); + } + + unsafe { Self::from_inner_in(self.ptr, self.alloc.clone()) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for Arc { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + &self.inner().data + } +} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Arc {} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Weak {} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for Arc {} + +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +impl LegacyReceiver for Arc {} + +#[cfg(not(no_global_oom_handling))] +impl Arc { + /// Makes a mutable reference into the given `Arc`. + /// + /// If there are other `Arc` pointers to the same allocation, then `make_mut` will + /// [`clone`] the inner value to a new allocation to ensure unique ownership. This is also + /// referred to as clone-on-write. + /// + /// However, if there are no other `Arc` pointers to this allocation, but some [`Weak`] + /// pointers, then the [`Weak`] pointers will be dissociated and the inner value will not + /// be cloned. + /// + /// See also [`get_mut`], which will fail rather than cloning the inner value + /// or dissociating [`Weak`] pointers. + /// + /// [`clone`]: Clone::clone + /// [`get_mut`]: Arc::get_mut + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut data = Arc::new(5); + /// + /// *Arc::make_mut(&mut data) += 1; // Won't clone anything + /// let mut other_data = Arc::clone(&data); // Won't clone inner data + /// *Arc::make_mut(&mut data) += 1; // Clones inner data + /// *Arc::make_mut(&mut data) += 1; // Won't clone anything + /// *Arc::make_mut(&mut other_data) *= 2; // Won't clone anything + /// + /// // Now `data` and `other_data` point to different allocations. + /// assert_eq!(*data, 8); + /// assert_eq!(*other_data, 12); + /// ``` + /// + /// [`Weak`] pointers will be dissociated: + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut data = Arc::new(75); + /// let weak = Arc::downgrade(&data); + /// + /// assert!(75 == *data); + /// assert!(75 == *weak.upgrade().unwrap()); + /// + /// *Arc::make_mut(&mut data) += 1; + /// + /// assert!(76 == *data); + /// assert!(weak.upgrade().is_none()); + /// ``` + #[inline] + #[stable(feature = "arc_unique", since = "1.4.0")] + pub fn make_mut(this: &mut Self) -> &mut T { + let size_of_val = mem::size_of_val::(&**this); + + // Note that we hold both a strong reference and a weak reference. + // Thus, releasing our strong reference only will not, by itself, cause + // the memory to be deallocated. + // + // Use Acquire to ensure that we see any writes to `weak` that happen + // before release writes (i.e., decrements) to `strong`. Since we hold a + // weak count, there's no chance the ArcInner itself could be + // deallocated. + if this.inner().strong.compare_exchange(1, 0, Acquire, Relaxed).is_err() { + // Another strong pointer exists, so we must clone. + + let this_data_ref: &T = &**this; + // `in_progress` drops the allocation if we panic before finishing initializing it. + let mut in_progress: UniqueArcUninit = + UniqueArcUninit::new(this_data_ref, this.alloc.clone()); + + let initialized_clone = unsafe { + // Clone. If the clone panics, `in_progress` will be dropped and clean up. + this_data_ref.clone_to_uninit(in_progress.data_ptr().cast()); + // Cast type of pointer, now that it is initialized. + in_progress.into_arc() + }; + *this = initialized_clone; + } else if this.inner().weak.load(Relaxed) != 1 { + // Relaxed suffices in the above because this is fundamentally an + // optimization: we are always racing with weak pointers being + // dropped. Worst case, we end up allocated a new Arc unnecessarily. + + // We removed the last strong ref, but there are additional weak + // refs remaining. We'll move the contents to a new Arc, and + // invalidate the other weak refs. + + // Note that it is not possible for the read of `weak` to yield + // usize::MAX (i.e., locked), since the weak count can only be + // locked by a thread with a strong reference. + + // Materialize our own implicit weak pointer, so that it can clean + // up the ArcInner as needed. + let _weak = Weak { ptr: this.ptr, alloc: this.alloc.clone() }; + + // Can just steal the data, all that's left is Weaks + // + // We don't need panic-protection like the above branch does, but we might as well + // use the same mechanism. + let mut in_progress: UniqueArcUninit = + UniqueArcUninit::new(&**this, this.alloc.clone()); + unsafe { + // Initialize `in_progress` with move of **this. + // We have to express this in terms of bytes because `T: ?Sized`; there is no + // operation that just copies a value based on its `size_of_val()`. + ptr::copy_nonoverlapping( + ptr::from_ref(&**this).cast::(), + in_progress.data_ptr().cast::(), + size_of_val, + ); + + ptr::write(this, in_progress.into_arc()); + } + } else { + // We were the sole reference of either kind; bump back up the + // strong ref count. + this.inner().strong.store(1, Release); + } + + // As with `get_mut()`, the unsafety is ok because our reference was + // either unique to begin with, or became one upon cloning the contents. + unsafe { Self::get_mut_unchecked(this) } + } +} + +impl Arc { + /// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the + /// clone. + /// + /// Assuming `arc_t` is of type `Arc`, this function is functionally equivalent to + /// `(*arc_t).clone()`, but will avoid cloning the inner value where possible. + /// + /// # Examples + /// + /// ``` + /// # use std::{ptr, sync::Arc}; + /// let inner = String::from("test"); + /// let ptr = inner.as_ptr(); + /// + /// let arc = Arc::new(inner); + /// let inner = Arc::unwrap_or_clone(arc); + /// // The inner value was not cloned + /// assert!(ptr::eq(ptr, inner.as_ptr())); + /// + /// let arc = Arc::new(inner); + /// let arc2 = arc.clone(); + /// let inner = Arc::unwrap_or_clone(arc); + /// // Because there were 2 references, we had to clone the inner value. + /// assert!(!ptr::eq(ptr, inner.as_ptr())); + /// // `arc2` is the last reference, so when we unwrap it we get back + /// // the original `String`. + /// let inner = Arc::unwrap_or_clone(arc2); + /// assert!(ptr::eq(ptr, inner.as_ptr())); + /// ``` + #[inline] + #[stable(feature = "arc_unwrap_or_clone", since = "1.76.0")] + pub fn unwrap_or_clone(this: Self) -> T { + Arc::try_unwrap(this).unwrap_or_else(|arc| (*arc).clone()) + } +} + +impl Arc { + /// Returns a mutable reference into the given `Arc`, if there are + /// no other `Arc` or [`Weak`] pointers to the same allocation. + /// + /// Returns [`None`] otherwise, because it is not safe to + /// mutate a shared value. + /// + /// See also [`make_mut`][make_mut], which will [`clone`][clone] + /// the inner value when there are other `Arc` pointers. + /// + /// [make_mut]: Arc::make_mut + /// [clone]: Clone::clone + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut x = Arc::new(3); + /// *Arc::get_mut(&mut x).unwrap() = 4; + /// assert_eq!(*x, 4); + /// + /// let _y = Arc::clone(&x); + /// assert!(Arc::get_mut(&mut x).is_none()); + /// ``` + #[inline] + #[stable(feature = "arc_unique", since = "1.4.0")] + pub fn get_mut(this: &mut Self) -> Option<&mut T> { + if this.is_unique() { + // This unsafety is ok because we're guaranteed that the pointer + // returned is the *only* pointer that will ever be returned to T. Our + // reference count is guaranteed to be 1 at this point, and we required + // the Arc itself to be `mut`, so we're returning the only possible + // reference to the inner data. + unsafe { Some(Arc::get_mut_unchecked(this)) } + } else { + None + } + } + + /// Returns a mutable reference into the given `Arc`, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: Arc::get_mut + /// + /// # Safety + /// + /// If any other `Arc` or [`Weak`] pointers to the same allocation exist, then + /// they must not be dereferenced or have active borrows for the duration + /// of the returned borrow, and their inner type must be exactly the same as the + /// inner type of this Rc (including lifetimes). This is trivially the case if no + /// such pointers exist, for example immediately after `Arc::new`. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut x = Arc::new(String::new()); + /// unsafe { + /// Arc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + /// Other `Arc` pointers to the same allocation must be to the same type. + /// ```no_run + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let x: Arc = Arc::from("Hello, world!"); + /// let mut y: Arc<[u8]> = x.clone().into(); + /// unsafe { + /// // this is Undefined Behavior, because x's inner type is str, not [u8] + /// Arc::get_mut_unchecked(&mut y).fill(0xff); // 0xff is invalid in UTF-8 + /// } + /// println!("{}", &*x); // Invalid UTF-8 in a str + /// ``` + /// Other `Arc` pointers to the same allocation must be to the exact same type, including lifetimes. + /// ```no_run + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let x: Arc<&str> = Arc::new("Hello, world!"); + /// { + /// let s = String::from("Oh, no!"); + /// let mut y: Arc<&str> = x.clone().into(); + /// unsafe { + /// // this is Undefined Behavior, because x's inner type + /// // is &'long str, not &'short str + /// *Arc::get_mut_unchecked(&mut y) = &s; + /// } + /// } + /// println!("{}", &*x); // Use-after-free + /// ``` + #[inline] + #[unstable(feature = "get_mut_unchecked", issue = "63292")] + pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { + // We are careful to *not* create a reference covering the "count" fields, as + // this would alias with concurrent access to the reference counts (e.g. by `Weak`). + unsafe { &mut (*this.ptr.as_ptr()).data } + } + + /// Determine whether this is the unique reference (including weak refs) to + /// the underlying data. + /// + /// Note that this requires locking the weak ref count. + fn is_unique(&mut self) -> bool { + // lock the weak pointer count if we appear to be the sole weak pointer + // holder. + // + // The acquire label here ensures a happens-before relationship with any + // writes to `strong` (in particular in `Weak::upgrade`) prior to decrements + // of the `weak` count (via `Weak::drop`, which uses release). If the upgraded + // weak ref was never dropped, the CAS here will fail so we do not care to synchronize. + if self.inner().weak.compare_exchange(1, usize::MAX, Acquire, Relaxed).is_ok() { + // This needs to be an `Acquire` to synchronize with the decrement of the `strong` + // counter in `drop` -- the only access that happens when any but the last reference + // is being dropped. + let unique = self.inner().strong.load(Acquire) == 1; + + // The release write here synchronizes with a read in `downgrade`, + // effectively preventing the above read of `strong` from happening + // after the write. + self.inner().weak.store(1, Release); // release the lock + unique + } else { + false + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Arc { + /// Drops the `Arc`. + /// + /// This will decrement the strong reference count. If the strong reference + /// count reaches zero then the only other references (if any) are + /// [`Weak`], so we `drop` the inner value. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// struct Foo; + /// + /// impl Drop for Foo { + /// fn drop(&mut self) { + /// println!("dropped!"); + /// } + /// } + /// + /// let foo = Arc::new(Foo); + /// let foo2 = Arc::clone(&foo); + /// + /// drop(foo); // Doesn't print anything + /// drop(foo2); // Prints "dropped!" + /// ``` + #[inline] + fn drop(&mut self) { + // Because `fetch_sub` is already atomic, we do not need to synchronize + // with other threads unless we are going to delete the object. This + // same logic applies to the below `fetch_sub` to the `weak` count. + if self.inner().strong.fetch_sub(1, Release) != 1 { + return; + } + + // This fence is needed to prevent reordering of use of the data and + // deletion of the data. Because it is marked `Release`, the decreasing + // of the reference count synchronizes with this `Acquire` fence. This + // means that use of the data happens before decreasing the reference + // count, which happens before this fence, which happens before the + // deletion of the data. + // + // As explained in the [Boost documentation][1], + // + // > It is important to enforce any possible access to the object in one + // > thread (through an existing reference) to *happen before* deleting + // > the object in a different thread. This is achieved by a "release" + // > operation after dropping a reference (any access to the object + // > through this reference must obviously happened before), and an + // > "acquire" operation before deleting the object. + // + // In particular, while the contents of an Arc are usually immutable, it's + // possible to have interior writes to something like a Mutex. Since a + // Mutex is not acquired when it is deleted, we can't rely on its + // synchronization logic to make writes in thread A visible to a destructor + // running in thread B. + // + // Also note that the Acquire fence here could probably be replaced with an + // Acquire load, which could improve performance in highly-contended + // situations. See [2]. + // + // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) + // [2]: (https://github.com/rust-lang/rust/pull/41714) + acquire!(self.inner().strong); + + // Make sure we aren't trying to "drop" the shared static for empty slices + // used by Default::default. + debug_assert!( + !ptr::addr_eq(self.ptr.as_ptr(), &STATIC_INNER_SLICE.inner), + "Arcs backed by a static should never reach a strong count of 0. \ + Likely decrement_strong_count or from_raw were called too many times.", + ); + + unsafe { + self.drop_slow(); + } + } +} + +impl Arc { + /// Attempts to downcast the `Arc` to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// use std::sync::Arc; + /// + /// fn print_if_string(value: Arc) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Arc::new(my_string)); + /// print_if_string(Arc::new(0i8)); + /// ``` + #[inline] + #[stable(feature = "rc_downcast", since = "1.29.0")] + pub fn downcast(self) -> Result, Self> + where + T: Any + Send + Sync, + { + if (*self).is::() { + unsafe { + let (ptr, alloc) = Arc::into_inner_with_allocator(self); + Ok(Arc::from_inner_in(ptr.cast(), alloc)) + } + } else { + Err(self) + } + } + + /// Downcasts the `Arc` to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// use std::sync::Arc; + /// + /// let x: Arc = Arc::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + /// + /// + /// [`downcast`]: Self::downcast + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "90850")] + pub unsafe fn downcast_unchecked(self) -> Arc + where + T: Any + Send + Sync, + { + unsafe { + let (ptr, alloc) = Arc::into_inner_with_allocator(self); + Arc::from_inner_in(ptr.cast(), alloc) + } + } +} + +impl Weak { + /// Constructs a new `Weak`, without allocating any memory. + /// Calling [`upgrade`] on the return value always gives [`None`]. + /// + /// [`upgrade`]: Weak::upgrade + /// + /// # Examples + /// + /// ``` + /// use std::sync::Weak; + /// + /// let empty: Weak = Weak::new(); + /// assert!(empty.upgrade().is_none()); + /// ``` + #[inline] + #[stable(feature = "downgraded_weak", since = "1.10.0")] + #[rustc_const_stable(feature = "const_weak_new", since = "1.73.0")] + #[must_use] + pub const fn new() -> Weak { + Weak { + ptr: unsafe { + NonNull::new_unchecked(ptr::without_provenance_mut::>(usize::MAX)) + }, + alloc: Global, + } + } +} + +impl Weak { + /// Constructs a new `Weak`, without allocating any memory, technically in the provided + /// allocator. + /// Calling [`upgrade`] on the return value always gives [`None`]. + /// + /// [`upgrade`]: Weak::upgrade + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::sync::Weak; + /// use std::alloc::System; + /// + /// let empty: Weak = Weak::new_in(System); + /// assert!(empty.upgrade().is_none()); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn new_in(alloc: A) -> Weak { + Weak { + ptr: unsafe { + NonNull::new_unchecked(ptr::without_provenance_mut::>(usize::MAX)) + }, + alloc, + } + } +} + +/// Helper type to allow accessing the reference counts without +/// making any assertions about the data field. +struct WeakInner<'a> { + weak: &'a atomic::AtomicUsize, + strong: &'a atomic::AtomicUsize, +} + +impl Weak { + /// Converts a raw pointer previously created by [`into_raw`] back into `Weak`. + /// + /// This can be used to safely get a strong reference (by calling [`upgrade`] + /// later) or to deallocate the weak count by dropping the `Weak`. + /// + /// It takes ownership of one weak reference (with the exception of pointers created by [`new`], + /// as these don't own anything; the method still works on them). + /// + /// # Safety + /// + /// The pointer must have originated from the [`into_raw`] and must still own its potential + /// weak reference. + /// + /// It is allowed for the strong count to be 0 at the time of calling this. Nevertheless, this + /// takes ownership of one weak reference currently represented as a raw pointer (the weak + /// count is not modified by this operation) and therefore it must be paired with a previous + /// call to [`into_raw`]. + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new("hello".to_owned()); + /// + /// let raw_1 = Arc::downgrade(&strong).into_raw(); + /// let raw_2 = Arc::downgrade(&strong).into_raw(); + /// + /// assert_eq!(2, Arc::weak_count(&strong)); + /// + /// assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap()); + /// assert_eq!(1, Arc::weak_count(&strong)); + /// + /// drop(strong); + /// + /// // Decrement the last weak count. + /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); + /// ``` + /// + /// [`new`]: Weak::new + /// [`into_raw`]: Weak::into_raw + /// [`upgrade`]: Weak::upgrade + #[inline] + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + unsafe { Weak::from_raw_in(ptr, Global) } + } +} + +impl Weak { + /// Returns a reference to the underlying allocator. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(&self) -> &A { + &self.alloc + } + + /// Returns a raw pointer to the object `T` pointed to by this `Weak`. + /// + /// The pointer is valid only if there are some strong references. The pointer may be dangling, + /// unaligned or even [`null`] otherwise. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// use std::ptr; + /// + /// let strong = Arc::new("hello".to_owned()); + /// let weak = Arc::downgrade(&strong); + /// // Both point to the same object + /// assert!(ptr::eq(&*strong, weak.as_ptr())); + /// // The strong here keeps it alive, so we can still access the object. + /// assert_eq!("hello", unsafe { &*weak.as_ptr() }); + /// + /// drop(strong); + /// // But not any more. We can do weak.as_ptr(), but accessing the pointer would lead to + /// // undefined behavior. + /// // assert_eq!("hello", unsafe { &*weak.as_ptr() }); + /// ``` + /// + /// [`null`]: core::ptr::null "ptr::null" + #[must_use] + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub fn as_ptr(&self) -> *const T { + let ptr: *mut ArcInner = NonNull::as_ptr(self.ptr); + + if is_dangling(ptr) { + // If the pointer is dangling, we return the sentinel directly. This cannot be + // a valid payload address, as the payload is at least as aligned as ArcInner (usize). + ptr as *const T + } else { + // SAFETY: if is_dangling returns false, then the pointer is dereferenceable. + // The payload may be dropped at this point, and we have to maintain provenance, + // so use raw pointer manipulation. + unsafe { &raw mut (*ptr).data } + } + } + + /// Consumes the `Weak` and turns it into a raw pointer. + /// + /// This converts the weak pointer into a raw pointer, while still preserving the ownership of + /// one weak reference (the weak count is not modified by this operation). It can be turned + /// back into the `Weak` with [`from_raw`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_ptr`] apply. + /// + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new("hello".to_owned()); + /// let weak = Arc::downgrade(&strong); + /// let raw = weak.into_raw(); + /// + /// assert_eq!(1, Arc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw(raw) }); + /// assert_eq!(0, Arc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw`]: Weak::from_raw + /// [`as_ptr`]: Weak::as_ptr + #[must_use = "losing the pointer will leak memory"] + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub fn into_raw(self) -> *const T { + ManuallyDrop::new(self).as_ptr() + } + + /// Consumes the `Weak`, returning the wrapped pointer and allocator. + /// + /// This converts the weak pointer into a raw pointer, while still preserving the ownership of + /// one weak reference (the weak count is not modified by this operation). It can be turned + /// back into the `Weak` with [`from_raw_in`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_ptr`] apply. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::sync::{Arc, Weak}; + /// use std::alloc::System; + /// + /// let strong = Arc::new_in("hello".to_owned(), System); + /// let weak = Arc::downgrade(&strong); + /// let (raw, alloc) = weak.into_raw_with_allocator(); + /// + /// assert_eq!(1, Arc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw_in(raw, alloc) }); + /// assert_eq!(0, Arc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw_in`]: Weak::from_raw_in + /// [`as_ptr`]: Weak::as_ptr + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn into_raw_with_allocator(self) -> (*const T, A) { + let this = mem::ManuallyDrop::new(self); + let result = this.as_ptr(); + // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + let alloc = unsafe { ptr::read(&this.alloc) }; + (result, alloc) + } + + /// Converts a raw pointer previously created by [`into_raw`] back into `Weak` in the provided + /// allocator. + /// + /// This can be used to safely get a strong reference (by calling [`upgrade`] + /// later) or to deallocate the weak count by dropping the `Weak`. + /// + /// It takes ownership of one weak reference (with the exception of pointers created by [`new`], + /// as these don't own anything; the method still works on them). + /// + /// # Safety + /// + /// The pointer must have originated from the [`into_raw`] and must still own its potential + /// weak reference, and must point to a block of memory allocated by `alloc`. + /// + /// It is allowed for the strong count to be 0 at the time of calling this. Nevertheless, this + /// takes ownership of one weak reference currently represented as a raw pointer (the weak + /// count is not modified by this operation) and therefore it must be paired with a previous + /// call to [`into_raw`]. + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new("hello".to_owned()); + /// + /// let raw_1 = Arc::downgrade(&strong).into_raw(); + /// let raw_2 = Arc::downgrade(&strong).into_raw(); + /// + /// assert_eq!(2, Arc::weak_count(&strong)); + /// + /// assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap()); + /// assert_eq!(1, Arc::weak_count(&strong)); + /// + /// drop(strong); + /// + /// // Decrement the last weak count. + /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); + /// ``` + /// + /// [`new`]: Weak::new + /// [`into_raw`]: Weak::into_raw + /// [`upgrade`]: Weak::upgrade + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { + // See Weak::as_ptr for context on how the input pointer is derived. + + let ptr = if is_dangling(ptr) { + // This is a dangling Weak. + ptr as *mut ArcInner + } else { + // Otherwise, we're guaranteed the pointer came from a nondangling Weak. + // SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T. + let offset = unsafe { data_offset(ptr) }; + // Thus, we reverse the offset to get the whole RcInner. + // SAFETY: the pointer originated from a Weak, so this offset is safe. + unsafe { ptr.byte_sub(offset) as *mut ArcInner } + }; + + // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. + Weak { ptr: unsafe { NonNull::new_unchecked(ptr) }, alloc } + } +} + +impl Weak { + /// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying + /// dropping of the inner value if successful. + /// + /// Returns [`None`] if the inner value has since been dropped. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// let weak_five = Arc::downgrade(&five); + /// + /// let strong_five: Option> = weak_five.upgrade(); + /// assert!(strong_five.is_some()); + /// + /// // Destroy all strong pointers. + /// drop(strong_five); + /// drop(five); + /// + /// assert!(weak_five.upgrade().is_none()); + /// ``` + #[must_use = "this returns a new `Arc`, \ + without modifying the original weak pointer"] + #[stable(feature = "arc_weak", since = "1.4.0")] + pub fn upgrade(&self) -> Option> + where + A: Clone, + { + #[inline] + fn checked_increment(n: usize) -> Option { + // Any write of 0 we can observe leaves the field in permanently zero state. + if n == 0 { + return None; + } + // See comments in `Arc::clone` for why we do this (for `mem::forget`). + assert!(n <= MAX_REFCOUNT, "{}", INTERNAL_OVERFLOW_ERROR); + Some(n + 1) + } + + // We use a CAS loop to increment the strong count instead of a + // fetch_add as this function should never take the reference count + // from zero to one. + // + // Relaxed is fine for the failure case because we don't have any expectations about the new state. + // Acquire is necessary for the success case to synchronise with `Arc::new_cyclic`, when the inner + // value can be initialized after `Weak` references have already been created. In that case, we + // expect to observe the fully initialized value. + if self.inner()?.strong.fetch_update(Acquire, Relaxed, checked_increment).is_ok() { + // SAFETY: pointer is not null, verified in checked_increment + unsafe { Some(Arc::from_inner_in(self.ptr, self.alloc.clone())) } + } else { + None + } + } + + /// Gets the number of strong (`Arc`) pointers pointing to this allocation. + /// + /// If `self` was created using [`Weak::new`], this will return 0. + #[must_use] + #[stable(feature = "weak_counts", since = "1.41.0")] + pub fn strong_count(&self) -> usize { + if let Some(inner) = self.inner() { inner.strong.load(Relaxed) } else { 0 } + } + + /// Gets an approximation of the number of `Weak` pointers pointing to this + /// allocation. + /// + /// If `self` was created using [`Weak::new`], or if there are no remaining + /// strong pointers, this will return 0. + /// + /// # Accuracy + /// + /// Due to implementation details, the returned value can be off by 1 in + /// either direction when other threads are manipulating any `Arc`s or + /// `Weak`s pointing to the same allocation. + #[must_use] + #[stable(feature = "weak_counts", since = "1.41.0")] + pub fn weak_count(&self) -> usize { + if let Some(inner) = self.inner() { + let weak = inner.weak.load(Acquire); + let strong = inner.strong.load(Relaxed); + if strong == 0 { + 0 + } else { + // Since we observed that there was at least one strong pointer + // after reading the weak count, we know that the implicit weak + // reference (present whenever any strong references are alive) + // was still around when we observed the weak count, and can + // therefore safely subtract it. + weak - 1 + } + } else { + 0 + } + } + + /// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`, + /// (i.e., when this `Weak` was created by `Weak::new`). + #[inline] + fn inner(&self) -> Option> { + let ptr = self.ptr.as_ptr(); + if is_dangling(ptr) { + None + } else { + // We are careful to *not* create a reference covering the "data" field, as + // the field may be mutated concurrently (for example, if the last `Arc` + // is dropped, the data field will be dropped in-place). + Some(unsafe { WeakInner { strong: &(*ptr).strong, weak: &(*ptr).weak } }) + } + } + + /// Returns `true` if the two `Weak`s point to the same allocation similar to [`ptr::eq`], or if + /// both don't point to any allocation (because they were created with `Weak::new()`). However, + /// this function ignores the metadata of `dyn Trait` pointers. + /// + /// # Notes + /// + /// Since this compares pointers it means that `Weak::new()` will equal each + /// other, even though they don't point to any allocation. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let first_rc = Arc::new(5); + /// let first = Arc::downgrade(&first_rc); + /// let second = Arc::downgrade(&first_rc); + /// + /// assert!(first.ptr_eq(&second)); + /// + /// let third_rc = Arc::new(5); + /// let third = Arc::downgrade(&third_rc); + /// + /// assert!(!first.ptr_eq(&third)); + /// ``` + /// + /// Comparing `Weak::new`. + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let first = Weak::new(); + /// let second = Weak::new(); + /// assert!(first.ptr_eq(&second)); + /// + /// let third_rc = Arc::new(()); + /// let third = Arc::downgrade(&third_rc); + /// assert!(!first.ptr_eq(&third)); + /// ``` + /// + /// [`ptr::eq`]: core::ptr::eq "ptr::eq" + #[inline] + #[must_use] + #[stable(feature = "weak_ptr_eq", since = "1.39.0")] + pub fn ptr_eq(&self, other: &Self) -> bool { + ptr::addr_eq(self.ptr.as_ptr(), other.ptr.as_ptr()) + } +} + +#[stable(feature = "arc_weak", since = "1.4.0")] +impl Clone for Weak { + /// Makes a clone of the `Weak` pointer that points to the same allocation. + /// + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let weak_five = Arc::downgrade(&Arc::new(5)); + /// + /// let _ = Weak::clone(&weak_five); + /// ``` + #[inline] + fn clone(&self) -> Weak { + if let Some(inner) = self.inner() { + // See comments in Arc::clone() for why this is relaxed. This can use a + // fetch_add (ignoring the lock) because the weak count is only locked + // where are *no other* weak pointers in existence. (So we can't be + // running this code in that case). + let old_size = inner.weak.fetch_add(1, Relaxed); + + // See comments in Arc::clone() for why we do this (for mem::forget). + if old_size > MAX_REFCOUNT { + abort(); + } + } + + Weak { ptr: self.ptr, alloc: self.alloc.clone() } + } +} + +#[stable(feature = "downgraded_weak", since = "1.10.0")] +impl Default for Weak { + /// Constructs a new `Weak`, without allocating memory. + /// Calling [`upgrade`] on the return value always + /// gives [`None`]. + /// + /// [`upgrade`]: Weak::upgrade + /// + /// # Examples + /// + /// ``` + /// use std::sync::Weak; + /// + /// let empty: Weak = Default::default(); + /// assert!(empty.upgrade().is_none()); + /// ``` + fn default() -> Weak { + Weak::new() + } +} + +#[stable(feature = "arc_weak", since = "1.4.0")] +unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Weak { + /// Drops the `Weak` pointer. + /// + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// struct Foo; + /// + /// impl Drop for Foo { + /// fn drop(&mut self) { + /// println!("dropped!"); + /// } + /// } + /// + /// let foo = Arc::new(Foo); + /// let weak_foo = Arc::downgrade(&foo); + /// let other_weak_foo = Weak::clone(&weak_foo); + /// + /// drop(weak_foo); // Doesn't print anything + /// drop(foo); // Prints "dropped!" + /// + /// assert!(other_weak_foo.upgrade().is_none()); + /// ``` + fn drop(&mut self) { + // If we find out that we were the last weak pointer, then its time to + // deallocate the data entirely. See the discussion in Arc::drop() about + // the memory orderings + // + // It's not necessary to check for the locked state here, because the + // weak count can only be locked if there was precisely one weak ref, + // meaning that drop could only subsequently run ON that remaining weak + // ref, which can only happen after the lock is released. + let inner = if let Some(inner) = self.inner() { inner } else { return }; + + if inner.weak.fetch_sub(1, Release) == 1 { + acquire!(inner.weak); + + // Make sure we aren't trying to "deallocate" the shared static for empty slices + // used by Default::default. + debug_assert!( + !ptr::addr_eq(self.ptr.as_ptr(), &STATIC_INNER_SLICE.inner), + "Arc/Weaks backed by a static should never be deallocated. \ + Likely decrement_strong_count or from_raw were called too many times.", + ); + + unsafe { + self.alloc.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr())) + } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +trait ArcEqIdent { + fn eq(&self, other: &Arc) -> bool; + fn ne(&self, other: &Arc) -> bool; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ArcEqIdent for Arc { + #[inline] + default fn eq(&self, other: &Arc) -> bool { + **self == **other + } + #[inline] + default fn ne(&self, other: &Arc) -> bool { + **self != **other + } +} + +/// We're doing this specialization here, and not as a more general optimization on `&T`, because it +/// would otherwise add a cost to all equality checks on refs. We assume that `Arc`s are used to +/// store large values, that are slow to clone, but also heavy to check for equality, causing this +/// cost to pay off more easily. It's also more likely to have two `Arc` clones, that point to +/// the same value, than two `&T`s. +/// +/// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive. +#[stable(feature = "rust1", since = "1.0.0")] +impl ArcEqIdent for Arc { + #[inline] + fn eq(&self, other: &Arc) -> bool { + Arc::ptr_eq(self, other) || **self == **other + } + + #[inline] + fn ne(&self, other: &Arc) -> bool { + !Arc::ptr_eq(self, other) && **self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for Arc { + /// Equality for two `Arc`s. + /// + /// Two `Arc`s are equal if their inner values are equal, even if they are + /// stored in different allocation. + /// + /// If `T` also implements `Eq` (implying reflexivity of equality), + /// two `Arc`s that point to the same allocation are always equal. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five == Arc::new(5)); + /// ``` + #[inline] + fn eq(&self, other: &Arc) -> bool { + ArcEqIdent::eq(self, other) + } + + /// Inequality for two `Arc`s. + /// + /// Two `Arc`s are not equal if their inner values are not equal. + /// + /// If `T` also implements `Eq` (implying reflexivity of equality), + /// two `Arc`s that point to the same value are always equal. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five != Arc::new(6)); + /// ``` + #[inline] + fn ne(&self, other: &Arc) -> bool { + ArcEqIdent::ne(self, other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Arc { + /// Partial comparison for two `Arc`s. + /// + /// The two are compared by calling `partial_cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// use std::cmp::Ordering; + /// + /// let five = Arc::new(5); + /// + /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&Arc::new(6))); + /// ``` + fn partial_cmp(&self, other: &Arc) -> Option { + (**self).partial_cmp(&**other) + } + + /// Less-than comparison for two `Arc`s. + /// + /// The two are compared by calling `<` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five < Arc::new(6)); + /// ``` + fn lt(&self, other: &Arc) -> bool { + *(*self) < *(*other) + } + + /// 'Less than or equal to' comparison for two `Arc`s. + /// + /// The two are compared by calling `<=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five <= Arc::new(5)); + /// ``` + fn le(&self, other: &Arc) -> bool { + *(*self) <= *(*other) + } + + /// Greater-than comparison for two `Arc`s. + /// + /// The two are compared by calling `>` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five > Arc::new(4)); + /// ``` + fn gt(&self, other: &Arc) -> bool { + *(*self) > *(*other) + } + + /// 'Greater than or equal to' comparison for two `Arc`s. + /// + /// The two are compared by calling `>=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five >= Arc::new(5)); + /// ``` + fn ge(&self, other: &Arc) -> bool { + *(*self) >= *(*other) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Arc { + /// Comparison for two `Arc`s. + /// + /// The two are compared by calling `cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// use std::cmp::Ordering; + /// + /// let five = Arc::new(5); + /// + /// assert_eq!(Ordering::Less, five.cmp(&Arc::new(6))); + /// ``` + fn cmp(&self, other: &Arc) -> Ordering { + (**self).cmp(&**other) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Arc {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Arc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Arc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Pointer for Arc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&(&raw const **self), f) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Arc { + /// Creates a new `Arc`, with the `Default` value for `T`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x: Arc = Default::default(); + /// assert_eq!(*x, 0); + /// ``` + fn default() -> Arc { + unsafe { + Self::from_inner( + Box::leak(Box::write(Box::new_uninit(), ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data: T::default(), + })) + .into(), + ) + } + } +} + +/// Struct to hold the static `ArcInner` used for empty `Arc` as +/// returned by `Default::default`. +/// +/// Layout notes: +/// * `repr(align(16))` so we can use it for `[T]` with `align_of::() <= 16`. +/// * `repr(C)` so `inner` is at offset 0 (and thus guaranteed to actually be aligned to 16). +/// * `[u8; 1]` (to be initialized with 0) so it can be used for `Arc`. +#[repr(C, align(16))] +struct SliceArcInnerForStatic { + inner: ArcInner<[u8; 1]>, +} +#[cfg(not(no_global_oom_handling))] +const MAX_STATIC_INNER_SLICE_ALIGNMENT: usize = 16; + +static STATIC_INNER_SLICE: SliceArcInnerForStatic = SliceArcInnerForStatic { + inner: ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data: [0], + }, +}; + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "1.80.0")] +impl Default for Arc { + /// Creates an empty str inside an Arc + /// + /// This may or may not share an allocation with other Arcs. + #[inline] + fn default() -> Self { + let arc: Arc<[u8]> = Default::default(); + debug_assert!(core::str::from_utf8(&*arc).is_ok()); + let (ptr, alloc) = Arc::into_inner_with_allocator(arc); + unsafe { Arc::from_ptr_in(ptr.as_ptr() as *mut ArcInner, alloc) } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "1.80.0")] +impl Default for Arc { + /// Creates an empty CStr inside an Arc + /// + /// This may or may not share an allocation with other Arcs. + #[inline] + fn default() -> Self { + use core::ffi::CStr; + let inner: NonNull> = NonNull::from(&STATIC_INNER_SLICE.inner); + let inner: NonNull> = + NonNull::new(inner.as_ptr() as *mut ArcInner).unwrap(); + // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. + let this: mem::ManuallyDrop> = + unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; + (*this).clone() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "more_rc_default_impls", since = "1.80.0")] +impl Default for Arc<[T]> { + /// Creates an empty `[T]` inside an Arc + /// + /// This may or may not share an allocation with other Arcs. + #[inline] + fn default() -> Self { + if mem::align_of::() <= MAX_STATIC_INNER_SLICE_ALIGNMENT { + // We take a reference to the whole struct instead of the ArcInner<[u8; 1]> inside it so + // we don't shrink the range of bytes the ptr is allowed to access under Stacked Borrows. + // (Miri complains on 32-bit targets with Arc<[Align16]> otherwise.) + // (Note that NonNull::from(&STATIC_INNER_SLICE.inner) is fine under Tree Borrows.) + let inner: NonNull = NonNull::from(&STATIC_INNER_SLICE); + let inner: NonNull> = inner.cast(); + // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. + let this: mem::ManuallyDrop> = + unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; + return (*this).clone(); + } + + // If T's alignment is too large for the static, make a new unique allocation. + let arr: [T; 0] = []; + Arc::from(arr) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Arc { + fn hash(&self, state: &mut H) { + (**self).hash(state) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "from_for_ptrs", since = "1.6.0")] +impl From for Arc { + /// Converts a `T` into an `Arc` + /// + /// The conversion moves the value into a + /// newly allocated `Arc`. It is equivalent to + /// calling `Arc::new(t)`. + /// + /// # Example + /// ```rust + /// # use std::sync::Arc; + /// let x = 5; + /// let arc = Arc::new(5); + /// + /// assert_eq!(Arc::from(x), arc); + /// ``` + fn from(t: T) -> Self { + Arc::new(t) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_array", since = "1.74.0")] +impl From<[T; N]> for Arc<[T]> { + /// Converts a [`[T; N]`](prim@array) into an `Arc<[T]>`. + /// + /// The conversion moves the array into a newly allocated `Arc`. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let original: [i32; 3] = [1, 2, 3]; + /// let shared: Arc<[i32]> = Arc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: [T; N]) -> Arc<[T]> { + Arc::<[T; N]>::from(v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From<&[T]> for Arc<[T]> { + /// Allocates a reference-counted slice and fills it by cloning `v`'s items. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let original: &[i32] = &[1, 2, 3]; + /// let shared: Arc<[i32]> = Arc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: &[T]) -> Arc<[T]> { + >::from_slice(v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] +impl From<&mut [T]> for Arc<[T]> { + /// Allocates a reference-counted slice and fills it by cloning `v`'s items. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let mut original = [1, 2, 3]; + /// let original: &mut [i32] = &mut original; + /// let shared: Arc<[i32]> = Arc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: &mut [T]) -> Arc<[T]> { + Arc::from(&*v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From<&str> for Arc { + /// Allocates a reference-counted `str` and copies `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let shared: Arc = Arc::from("eggplant"); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(v: &str) -> Arc { + let arc = Arc::<[u8]>::from(v.as_bytes()); + unsafe { Arc::from_raw(Arc::into_raw(arc) as *const str) } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] +impl From<&mut str> for Arc { + /// Allocates a reference-counted `str` and copies `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let mut original = String::from("eggplant"); + /// let original: &mut str = &mut original; + /// let shared: Arc = Arc::from(original); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(v: &mut str) -> Arc { + Arc::from(&*v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From for Arc { + /// Allocates a reference-counted `str` and copies `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let unique: String = "eggplant".to_owned(); + /// let shared: Arc = Arc::from(unique); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(v: String) -> Arc { + Arc::from(&v[..]) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From> for Arc { + /// Move a boxed object to a new, reference-counted allocation. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let unique: Box = Box::from("eggplant"); + /// let shared: Arc = Arc::from(unique); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(v: Box) -> Arc { + Arc::from_box_in(v) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From> for Arc<[T], A> { + /// Allocates a reference-counted slice and moves `v`'s items into it. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let unique: Vec = vec![1, 2, 3]; + /// let shared: Arc<[i32]> = Arc::from(unique); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: Vec) -> Arc<[T], A> { + unsafe { + let (vec_ptr, len, cap, alloc) = v.into_raw_parts_with_alloc(); + + let rc_ptr = Self::allocate_for_slice_in(len, &alloc); + ptr::copy_nonoverlapping(vec_ptr, (&raw mut (*rc_ptr).data) as *mut T, len); + + // Create a `Vec` with length 0, to deallocate the buffer + // without dropping its contents or the allocator + let _ = Vec::from_raw_parts_in(vec_ptr, 0, cap, &alloc); + + Self::from_ptr_in(rc_ptr, alloc) + } + } +} + +#[stable(feature = "shared_from_cow", since = "1.45.0")] +impl<'a, B> From> for Arc +where + B: ToOwned + ?Sized, + Arc: From<&'a B> + From, +{ + /// Creates an atomically reference-counted pointer from a clone-on-write + /// pointer by copying its content. + /// + /// # Example + /// + /// ```rust + /// # use std::sync::Arc; + /// # use std::borrow::Cow; + /// let cow: Cow<'_, str> = Cow::Borrowed("eggplant"); + /// let shared: Arc = Arc::from(cow); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(cow: Cow<'a, B>) -> Arc { + match cow { + Cow::Borrowed(s) => Arc::from(s), + Cow::Owned(s) => Arc::from(s), + } + } +} + +#[stable(feature = "shared_from_str", since = "1.62.0")] +impl From> for Arc<[u8]> { + /// Converts an atomically reference-counted string slice into a byte slice. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let string: Arc = Arc::from("eggplant"); + /// let bytes: Arc<[u8]> = Arc::from(string); + /// assert_eq!("eggplant".as_bytes(), bytes.as_ref()); + /// ``` + #[inline] + fn from(rc: Arc) -> Self { + // SAFETY: `str` has the same layout as `[u8]`. + unsafe { Arc::from_raw(Arc::into_raw(rc) as *const [u8]) } + } +} + +#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] +impl TryFrom> for Arc<[T; N], A> { + type Error = Arc<[T], A>; + + fn try_from(boxed_slice: Arc<[T], A>) -> Result { + if boxed_slice.len() == N { + let (ptr, alloc) = Arc::into_inner_with_allocator(boxed_slice); + Ok(unsafe { Arc::from_inner_in(ptr.cast(), alloc) }) + } else { + Err(boxed_slice) + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_iter", since = "1.37.0")] +impl FromIterator for Arc<[T]> { + /// Takes each element in the `Iterator` and collects it into an `Arc<[T]>`. + /// + /// # Performance characteristics + /// + /// ## The general case + /// + /// In the general case, collecting into `Arc<[T]>` is done by first + /// collecting into a `Vec`. That is, when writing the following: + /// + /// ```rust + /// # use std::sync::Arc; + /// let evens: Arc<[u8]> = (0..10).filter(|&x| x % 2 == 0).collect(); + /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); + /// ``` + /// + /// this behaves as if we wrote: + /// + /// ```rust + /// # use std::sync::Arc; + /// let evens: Arc<[u8]> = (0..10).filter(|&x| x % 2 == 0) + /// .collect::>() // The first set of allocations happens here. + /// .into(); // A second allocation for `Arc<[T]>` happens here. + /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); + /// ``` + /// + /// This will allocate as many times as needed for constructing the `Vec` + /// and then it will allocate once for turning the `Vec` into the `Arc<[T]>`. + /// + /// ## Iterators of known length + /// + /// When your `Iterator` implements `TrustedLen` and is of an exact size, + /// a single allocation will be made for the `Arc<[T]>`. For example: + /// + /// ```rust + /// # use std::sync::Arc; + /// let evens: Arc<[u8]> = (0..10).collect(); // Just a single allocation happens here. + /// # assert_eq!(&*evens, &*(0..10).collect::>()); + /// ``` + fn from_iter>(iter: I) -> Self { + ToArcSlice::to_arc_slice(iter.into_iter()) + } +} + +#[cfg(not(no_global_oom_handling))] +/// Specialization trait used for collecting into `Arc<[T]>`. +trait ToArcSlice: Iterator + Sized { + fn to_arc_slice(self) -> Arc<[T]>; +} + +#[cfg(not(no_global_oom_handling))] +impl> ToArcSlice for I { + default fn to_arc_slice(self) -> Arc<[T]> { + self.collect::>().into() + } +} + +#[cfg(not(no_global_oom_handling))] +impl> ToArcSlice for I { + fn to_arc_slice(self) -> Arc<[T]> { + // This is the case for a `TrustedLen` iterator. + let (low, high) = self.size_hint(); + if let Some(high) = high { + debug_assert_eq!( + low, + high, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + + unsafe { + // SAFETY: We need to ensure that the iterator has an exact length and we have. + Arc::from_iter_exact(self, low) + } + } else { + // TrustedLen contract guarantees that `upper_bound == None` implies an iterator + // length exceeding `usize::MAX`. + // The default implementation would collect into a vec which would panic. + // Thus we panic here immediately without invoking `Vec` code. + panic!("capacity overflow"); + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl borrow::Borrow for Arc { + fn borrow(&self) -> &T { + &**self + } +} + +#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] +impl AsRef for Arc { + fn as_ref(&self) -> &T { + &**self + } +} + +#[stable(feature = "pin", since = "1.33.0")] +impl Unpin for Arc {} + +/// Gets the offset within an `ArcInner` for the payload behind a pointer. +/// +/// # Safety +/// +/// The pointer must point to (and have valid metadata for) a previously +/// valid instance of T, but the T is allowed to be dropped. +unsafe fn data_offset(ptr: *const T) -> usize { + // Align the unsized value to the end of the ArcInner. + // Because RcInner is repr(C), it will always be the last field in memory. + // SAFETY: since the only unsized types possible are slices, trait objects, + // and extern types, the input safety requirement is currently enough to + // satisfy the requirements of align_of_val_raw; this is an implementation + // detail of the language that must not be relied upon outside of std. + unsafe { data_offset_align(align_of_val_raw(ptr)) } +} + +#[inline] +fn data_offset_align(align: usize) -> usize { + let layout = Layout::new::>(); + layout.size() + layout.padding_needed_for(align) +} + +/// A unique owning pointer to an [`ArcInner`] **that does not imply the contents are initialized,** +/// but will deallocate it (without dropping the value) when dropped. +/// +/// This is a helper for [`Arc::make_mut()`] to ensure correct cleanup on panic. +#[cfg(not(no_global_oom_handling))] +struct UniqueArcUninit { + ptr: NonNull>, + layout_for_value: Layout, + alloc: Option, +} + +#[cfg(not(no_global_oom_handling))] +impl UniqueArcUninit { + /// Allocates an ArcInner with layout suitable to contain `for_value` or a clone of it. + fn new(for_value: &T, alloc: A) -> UniqueArcUninit { + let layout = Layout::for_value(for_value); + let ptr = unsafe { + Arc::allocate_for_layout( + layout, + |layout_for_arcinner| alloc.allocate(layout_for_arcinner), + |mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const ArcInner), + ) + }; + Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) } + } + + /// Returns the pointer to be written into to initialize the [`Arc`]. + fn data_ptr(&mut self) -> *mut T { + let offset = data_offset_align(self.layout_for_value.align()); + unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T } + } + + /// Upgrade this into a normal [`Arc`]. + /// + /// # Safety + /// + /// The data must have been initialized (by writing to [`Self::data_ptr()`]). + unsafe fn into_arc(self) -> Arc { + let mut this = ManuallyDrop::new(self); + let ptr = this.ptr.as_ptr(); + let alloc = this.alloc.take().unwrap(); + + // SAFETY: The pointer is valid as per `UniqueArcUninit::new`, and the caller is responsible + // for having initialized the data. + unsafe { Arc::from_ptr_in(ptr, alloc) } + } +} + +#[cfg(not(no_global_oom_handling))] +impl Drop for UniqueArcUninit { + fn drop(&mut self) { + // SAFETY: + // * new() produced a pointer safe to deallocate. + // * We own the pointer unless into_arc() was called, which forgets us. + unsafe { + self.alloc.take().unwrap().deallocate( + self.ptr.cast(), + arcinner_layout_for_value_layout(self.layout_for_value), + ); + } + } +} + +#[stable(feature = "arc_error", since = "1.52.0")] +impl core::error::Error for Arc { + #[allow(deprecated, deprecated_in_future)] + fn description(&self) -> &str { + core::error::Error::description(&**self) + } + + #[allow(deprecated)] + fn cause(&self) -> Option<&dyn core::error::Error> { + core::error::Error::cause(&**self) + } + + fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { + core::error::Error::source(&**self) + } + + fn provide<'a>(&'a self, req: &mut core::error::Request<'a>) { + core::error::Error::provide(&**self, req); + } +} diff --git a/CoqOfRust/alloc/sync/tests.rs b/CoqOfRust/alloc/sync/tests.rs new file mode 100644 index 000000000..de5816fda --- /dev/null +++ b/CoqOfRust/alloc/sync/tests.rs @@ -0,0 +1,717 @@ +use std::clone::Clone; +use std::mem::MaybeUninit; +use std::option::Option::None; +use std::sync::Mutex; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering::SeqCst; +use std::sync::mpsc::channel; +use std::thread; + +use super::*; + +struct Canary(*mut AtomicUsize); + +impl Drop for Canary { + fn drop(&mut self) { + unsafe { + match *self { + Canary(c) => { + (*c).fetch_add(1, SeqCst); + } + } + } + } +} + +struct AllocCanary<'a>(&'a AtomicUsize); + +impl<'a> AllocCanary<'a> { + fn new(counter: &'a AtomicUsize) -> Self { + counter.fetch_add(1, SeqCst); + Self(counter) + } +} + +unsafe impl Allocator for AllocCanary<'_> { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + std::alloc::Global.allocate(layout) + } + + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + unsafe { std::alloc::Global.deallocate(ptr, layout) } + } +} + +impl Clone for AllocCanary<'_> { + fn clone(&self) -> Self { + Self::new(self.0) + } +} + +impl Drop for AllocCanary<'_> { + fn drop(&mut self) { + self.0.fetch_sub(1, SeqCst); + } +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn manually_share_arc() { + let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let arc_v = Arc::new(v); + + let (tx, rx) = channel(); + + let _t = thread::spawn(move || { + let arc_v: Arc> = rx.recv().unwrap(); + assert_eq!((*arc_v)[3], 4); + }); + + tx.send(arc_v.clone()).unwrap(); + + assert_eq!((*arc_v)[2], 3); + assert_eq!((*arc_v)[4], 5); +} + +#[test] +fn test_arc_get_mut() { + let mut x = Arc::new(3); + *Arc::get_mut(&mut x).unwrap() = 4; + assert_eq!(*x, 4); + let y = x.clone(); + assert!(Arc::get_mut(&mut x).is_none()); + drop(y); + assert!(Arc::get_mut(&mut x).is_some()); + let _w = Arc::downgrade(&x); + assert!(Arc::get_mut(&mut x).is_none()); +} + +#[test] +fn weak_counts() { + assert_eq!(Weak::weak_count(&Weak::::new()), 0); + assert_eq!(Weak::strong_count(&Weak::::new()), 0); + + let a = Arc::new(0); + let w = Arc::downgrade(&a); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), 1); + let w2 = w.clone(); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), 2); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), 2); + drop(w); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), 1); + let a2 = a.clone(); + assert_eq!(Weak::strong_count(&w2), 2); + assert_eq!(Weak::weak_count(&w2), 1); + drop(a2); + drop(a); + assert_eq!(Weak::strong_count(&w2), 0); + assert_eq!(Weak::weak_count(&w2), 0); + drop(w2); +} + +#[test] +fn try_unwrap() { + let x = Arc::new(3); + assert_eq!(Arc::try_unwrap(x), Ok(3)); + let x = Arc::new(4); + let _y = x.clone(); + assert_eq!(Arc::try_unwrap(x), Err(Arc::new(4))); + let x = Arc::new(5); + let _w = Arc::downgrade(&x); + assert_eq!(Arc::try_unwrap(x), Ok(5)); +} + +#[test] +fn into_inner() { + for _ in 0..100 + // ^ Increase chances of hitting potential race conditions + { + let x = Arc::new(3); + let y = Arc::clone(&x); + let r_thread = std::thread::spawn(|| Arc::into_inner(x)); + let s_thread = std::thread::spawn(|| Arc::into_inner(y)); + let r = r_thread.join().expect("r_thread panicked"); + let s = s_thread.join().expect("s_thread panicked"); + assert!( + matches!((r, s), (None, Some(3)) | (Some(3), None)), + "assertion failed: unexpected result `{:?}`\ + \n expected `(None, Some(3))` or `(Some(3), None)`", + (r, s), + ); + } + + let x = Arc::new(3); + assert_eq!(Arc::into_inner(x), Some(3)); + + let x = Arc::new(4); + let y = Arc::clone(&x); + assert_eq!(Arc::into_inner(x), None); + assert_eq!(Arc::into_inner(y), Some(4)); + + let x = Arc::new(5); + let _w = Arc::downgrade(&x); + assert_eq!(Arc::into_inner(x), Some(5)); +} + +#[test] +fn into_from_raw() { + let x = Arc::new(Box::new("hello")); + let y = x.clone(); + + let x_ptr = Arc::into_raw(x); + drop(y); + unsafe { + assert_eq!(**x_ptr, "hello"); + + let x = Arc::from_raw(x_ptr); + assert_eq!(**x, "hello"); + + assert_eq!(Arc::try_unwrap(x).map(|x| *x), Ok("hello")); + } +} + +#[test] +fn test_into_from_raw_unsized() { + use std::fmt::Display; + use std::string::ToString; + + let arc: Arc = Arc::from("foo"); + + let ptr = Arc::into_raw(arc.clone()); + let arc2 = unsafe { Arc::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }, "foo"); + assert_eq!(arc, arc2); + + let arc: Arc = Arc::new(123); + + let ptr = Arc::into_raw(arc.clone()); + let arc2 = unsafe { Arc::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }.to_string(), "123"); + assert_eq!(arc2.to_string(), "123"); +} + +#[test] +fn into_from_weak_raw() { + let x = Arc::new(Box::new("hello")); + let y = Arc::downgrade(&x); + + let y_ptr = Weak::into_raw(y); + unsafe { + assert_eq!(**y_ptr, "hello"); + + let y = Weak::from_raw(y_ptr); + let y_up = Weak::upgrade(&y).unwrap(); + assert_eq!(**y_up, "hello"); + drop(y_up); + + assert_eq!(Arc::try_unwrap(x).map(|x| *x), Ok("hello")); + } +} + +#[test] +fn test_into_from_weak_raw_unsized() { + use std::fmt::Display; + use std::string::ToString; + + let arc: Arc = Arc::from("foo"); + let weak: Weak = Arc::downgrade(&arc); + + let ptr = Weak::into_raw(weak.clone()); + let weak2 = unsafe { Weak::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }, "foo"); + assert!(weak.ptr_eq(&weak2)); + + let arc: Arc = Arc::new(123); + let weak: Weak = Arc::downgrade(&arc); + + let ptr = Weak::into_raw(weak.clone()); + let weak2 = unsafe { Weak::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }.to_string(), "123"); + assert!(weak.ptr_eq(&weak2)); +} + +#[test] +fn test_cowarc_clone_make_mut() { + let mut cow0 = Arc::new(75); + let mut cow1 = cow0.clone(); + let mut cow2 = cow1.clone(); + + assert!(75 == *Arc::make_mut(&mut cow0)); + assert!(75 == *Arc::make_mut(&mut cow1)); + assert!(75 == *Arc::make_mut(&mut cow2)); + + *Arc::make_mut(&mut cow0) += 1; + *Arc::make_mut(&mut cow1) += 2; + *Arc::make_mut(&mut cow2) += 3; + + assert!(76 == *cow0); + assert!(77 == *cow1); + assert!(78 == *cow2); + + // none should point to the same backing memory + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 != *cow2); +} + +#[test] +fn test_cowarc_clone_unique2() { + let mut cow0 = Arc::new(75); + let cow1 = cow0.clone(); + let cow2 = cow1.clone(); + + assert!(75 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + *Arc::make_mut(&mut cow0) += 1; + assert!(76 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + // cow1 and cow2 should share the same contents + // cow0 should have a unique reference + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 == *cow2); +} + +#[test] +fn test_cowarc_clone_weak() { + let mut cow0 = Arc::new(75); + let cow1_weak = Arc::downgrade(&cow0); + + assert!(75 == *cow0); + assert!(75 == *cow1_weak.upgrade().unwrap()); + + *Arc::make_mut(&mut cow0) += 1; + + assert!(76 == *cow0); + assert!(cow1_weak.upgrade().is_none()); +} + +#[test] +fn test_live() { + let x = Arc::new(5); + let y = Arc::downgrade(&x); + assert!(y.upgrade().is_some()); +} + +#[test] +fn test_dead() { + let x = Arc::new(5); + let y = Arc::downgrade(&x); + drop(x); + assert!(y.upgrade().is_none()); +} + +#[test] +fn weak_self_cyclic() { + struct Cycle { + x: Mutex>>, + } + + let a = Arc::new(Cycle { x: Mutex::new(None) }); + let b = Arc::downgrade(&a.clone()); + *a.x.lock().unwrap() = Some(b); + + // hopefully we don't double-free (or leak)... +} + +#[test] +fn drop_arc() { + let mut canary = AtomicUsize::new(0); + let x = Arc::new(Canary(&mut canary as *mut AtomicUsize)); + drop(x); + assert!(canary.load(Acquire) == 1); +} + +#[test] +fn drop_arc_weak() { + let mut canary = AtomicUsize::new(0); + let arc = Arc::new(Canary(&mut canary as *mut AtomicUsize)); + let arc_weak = Arc::downgrade(&arc); + assert!(canary.load(Acquire) == 0); + drop(arc); + assert!(canary.load(Acquire) == 1); + drop(arc_weak); +} + +#[test] +fn test_strong_count() { + let a = Arc::new(0); + assert!(Arc::strong_count(&a) == 1); + let w = Arc::downgrade(&a); + assert!(Arc::strong_count(&a) == 1); + let b = w.upgrade().expect(""); + assert!(Arc::strong_count(&b) == 2); + assert!(Arc::strong_count(&a) == 2); + drop(w); + drop(a); + assert!(Arc::strong_count(&b) == 1); + let c = b.clone(); + assert!(Arc::strong_count(&b) == 2); + assert!(Arc::strong_count(&c) == 2); +} + +#[test] +fn test_weak_count() { + let a = Arc::new(0); + assert!(Arc::strong_count(&a) == 1); + assert!(Arc::weak_count(&a) == 0); + let w = Arc::downgrade(&a); + assert!(Arc::strong_count(&a) == 1); + assert!(Arc::weak_count(&a) == 1); + let x = w.clone(); + assert!(Arc::weak_count(&a) == 2); + drop(w); + drop(x); + assert!(Arc::strong_count(&a) == 1); + assert!(Arc::weak_count(&a) == 0); + let c = a.clone(); + assert!(Arc::strong_count(&a) == 2); + assert!(Arc::weak_count(&a) == 0); + let d = Arc::downgrade(&c); + assert!(Arc::weak_count(&c) == 1); + assert!(Arc::strong_count(&c) == 2); + + drop(a); + drop(c); + drop(d); +} + +#[test] +fn show_arc() { + let a = Arc::new(5); + assert_eq!(format!("{a:?}"), "5"); +} + +// Make sure deriving works with Arc +#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)] +struct _Foo { + inner: Arc, +} + +#[test] +fn test_unsized() { + let x: Arc<[i32]> = Arc::new([1, 2, 3]); + assert_eq!(format!("{x:?}"), "[1, 2, 3]"); + let y = Arc::downgrade(&x.clone()); + drop(x); + assert!(y.upgrade().is_none()); +} + +#[test] +fn test_maybe_thin_unsized() { + // If/when custom thin DSTs exist, this test should be updated to use one + use std::ffi::CStr; + + let x: Arc = Arc::from(c"swordfish"); + assert_eq!(format!("{x:?}"), "\"swordfish\""); + let y: Weak = Arc::downgrade(&x); + drop(x); + + // At this point, the weak points to a dropped DST + assert!(y.upgrade().is_none()); + // But we still need to be able to get the alloc layout to drop. + // CStr has no drop glue, but custom DSTs might, and need to work. + drop(y); +} + +#[test] +fn test_from_owned() { + let foo = 123; + let foo_arc = Arc::from(foo); + assert!(123 == *foo_arc); +} + +#[test] +fn test_new_weak() { + let foo: Weak = Weak::new(); + assert!(foo.upgrade().is_none()); +} + +#[test] +fn test_ptr_eq() { + let five = Arc::new(5); + let same_five = five.clone(); + let other_five = Arc::new(5); + + assert!(Arc::ptr_eq(&five, &same_five)); + assert!(!Arc::ptr_eq(&five, &other_five)); +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_weak_count_locked() { + let mut a = Arc::new(atomic::AtomicBool::new(false)); + let a2 = a.clone(); + let t = thread::spawn(move || { + // Miri is too slow + let count = if cfg!(miri) { 1000 } else { 1000000 }; + for _i in 0..count { + Arc::get_mut(&mut a); + } + a.store(true, SeqCst); + }); + + while !a2.load(SeqCst) { + let n = Arc::weak_count(&a2); + assert!(n < 2, "bad weak count: {}", n); + #[cfg(miri)] // Miri's scheduler does not guarantee liveness, and thus needs this hint. + std::hint::spin_loop(); + } + t.join().unwrap(); +} + +#[test] +fn test_from_str() { + let r: Arc = Arc::from("foo"); + + assert_eq!(&r[..], "foo"); +} + +#[test] +fn test_copy_from_slice() { + let s: &[u32] = &[1, 2, 3]; + let r: Arc<[u32]> = Arc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_clone_from_slice() { + #[derive(Clone, Debug, Eq, PartialEq)] + struct X(u32); + + let s: &[X] = &[X(1), X(2), X(3)]; + let r: Arc<[X]> = Arc::from(s); + + assert_eq!(&r[..], s); +} + +#[test] +#[should_panic] +fn test_clone_from_slice_panic() { + use std::string::{String, ToString}; + + struct Fail(u32, String); + + impl Clone for Fail { + fn clone(&self) -> Fail { + if self.0 == 2 { + panic!(); + } + Fail(self.0, self.1.clone()) + } + } + + let s: &[Fail] = + &[Fail(0, "foo".to_string()), Fail(1, "bar".to_string()), Fail(2, "baz".to_string())]; + + // Should panic, but not cause memory corruption + let _r: Arc<[Fail]> = Arc::from(s); +} + +#[test] +fn test_from_box() { + let b: Box = Box::new(123); + let r: Arc = Arc::from(b); + + assert_eq!(*r, 123); +} + +#[test] +fn test_from_box_str() { + use std::string::String; + + let s = String::from("foo").into_boxed_str(); + let r: Arc = Arc::from(s); + + assert_eq!(&r[..], "foo"); +} + +#[test] +fn test_from_box_slice() { + let s = vec![1, 2, 3].into_boxed_slice(); + let r: Arc<[u32]> = Arc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_from_box_trait() { + use std::fmt::Display; + use std::string::ToString; + + let b: Box = Box::new(123); + let r: Arc = Arc::from(b); + + assert_eq!(r.to_string(), "123"); +} + +#[test] +fn test_from_box_trait_zero_sized() { + use std::fmt::Debug; + + let b: Box = Box::new(()); + let r: Arc = Arc::from(b); + + assert_eq!(format!("{r:?}"), "()"); +} + +#[test] +fn test_from_vec() { + let v = vec![1, 2, 3]; + let r: Arc<[u32]> = Arc::from(v); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_downcast() { + use std::any::Any; + + let r1: Arc = Arc::new(i32::MAX); + let r2: Arc = Arc::new("abc"); + + assert!(r1.clone().downcast::().is_err()); + + let r1i32 = r1.downcast::(); + assert!(r1i32.is_ok()); + assert_eq!(r1i32.unwrap(), Arc::new(i32::MAX)); + + assert!(r2.clone().downcast::().is_err()); + + let r2str = r2.downcast::<&'static str>(); + assert!(r2str.is_ok()); + assert_eq!(r2str.unwrap(), Arc::new("abc")); +} + +#[test] +fn test_array_from_slice() { + let v = vec![1, 2, 3]; + let r: Arc<[u32]> = Arc::from(v); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_ok()); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_err()); +} + +#[test] +fn test_arc_cyclic_with_zero_refs() { + struct ZeroRefs { + inner: Weak, + } + let zero_refs = Arc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + ZeroRefs { inner: Weak::new() } + }); + + assert_eq!(Arc::strong_count(&zero_refs), 1); + assert_eq!(Arc::weak_count(&zero_refs), 0); + assert_eq!(zero_refs.inner.strong_count(), 0); + assert_eq!(zero_refs.inner.weak_count(), 0); +} + +#[test] +fn test_arc_new_cyclic_one_ref() { + struct OneRef { + inner: Weak, + } + let one_ref = Arc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + OneRef { inner: inner.clone() } + }); + + assert_eq!(Arc::strong_count(&one_ref), 1); + assert_eq!(Arc::weak_count(&one_ref), 1); + + let one_ref2 = Weak::upgrade(&one_ref.inner).unwrap(); + assert!(Arc::ptr_eq(&one_ref, &one_ref2)); + + assert_eq!(Arc::strong_count(&one_ref), 2); + assert_eq!(Arc::weak_count(&one_ref), 1); +} + +#[test] +fn test_arc_cyclic_two_refs() { + struct TwoRefs { + inner1: Weak, + inner2: Weak, + } + let two_refs = Arc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + + let inner1 = inner.clone(); + let inner2 = inner1.clone(); + + TwoRefs { inner1, inner2 } + }); + + assert_eq!(Arc::strong_count(&two_refs), 1); + assert_eq!(Arc::weak_count(&two_refs), 2); + + let two_refs1 = Weak::upgrade(&two_refs.inner1).unwrap(); + assert!(Arc::ptr_eq(&two_refs, &two_refs1)); + + let two_refs2 = Weak::upgrade(&two_refs.inner2).unwrap(); + assert!(Arc::ptr_eq(&two_refs, &two_refs2)); + + assert_eq!(Arc::strong_count(&two_refs), 3); + assert_eq!(Arc::weak_count(&two_refs), 2); +} + +/// Test for Arc::drop bug (https://github.com/rust-lang/rust/issues/55005) +#[test] +#[cfg(miri)] // relies on Stacked Borrows in Miri +fn arc_drop_dereferenceable_race() { + // The bug seems to take up to 700 iterations to reproduce with most seeds (tested 0-9). + for _ in 0..750 { + let arc_1 = Arc::new(()); + let arc_2 = arc_1.clone(); + let thread = thread::spawn(|| drop(arc_2)); + // Spin a bit; makes the race more likely to appear + let mut i = 0; + while i < 256 { + i += 1; + } + drop(arc_1); + thread.join().unwrap(); + } +} + +#[test] +fn arc_doesnt_leak_allocator() { + let counter = AtomicUsize::new(0); + + { + let arc: Arc = Arc::new_in(5usize, AllocCanary::new(&counter)); + drop(arc.downcast::().unwrap()); + + let arc: Arc = Arc::new_in(5usize, AllocCanary::new(&counter)); + drop(unsafe { arc.downcast_unchecked::() }); + + let arc = Arc::new_in(MaybeUninit::::new(5usize), AllocCanary::new(&counter)); + drop(unsafe { arc.assume_init() }); + + let arc: Arc<[MaybeUninit], _> = + Arc::new_zeroed_slice_in(5, AllocCanary::new(&counter)); + drop(unsafe { arc.assume_init() }); + } + + assert_eq!(counter.load(SeqCst), 0); +} diff --git a/CoqOfRust/alloc/task.rs b/CoqOfRust/alloc/task.rs new file mode 100644 index 000000000..b4116f498 --- /dev/null +++ b/CoqOfRust/alloc/task.rs @@ -0,0 +1,350 @@ +#![stable(feature = "wake_trait", since = "1.51.0")] + +//! Types and Traits for working with asynchronous tasks. +//! +//! **Note**: Some of the types in this module are only available +//! on platforms that support atomic loads and stores of pointers. +//! This may be detected at compile time using +//! `#[cfg(target_has_atomic = "ptr")]`. + +use core::mem::ManuallyDrop; +#[cfg(target_has_atomic = "ptr")] +use core::task::Waker; +use core::task::{LocalWaker, RawWaker, RawWakerVTable}; + +use crate::rc::Rc; +#[cfg(target_has_atomic = "ptr")] +use crate::sync::Arc; + +/// The implementation of waking a task on an executor. +/// +/// This trait can be used to create a [`Waker`]. An executor can define an +/// implementation of this trait, and use that to construct a [`Waker`] to pass +/// to the tasks that are executed on that executor. +/// +/// This trait is a memory-safe and ergonomic alternative to constructing a +/// [`RawWaker`]. It supports the common executor design in which the data used +/// to wake up a task is stored in an [`Arc`]. Some executors (especially +/// those for embedded systems) cannot use this API, which is why [`RawWaker`] +/// exists as an alternative for those systems. +/// +/// To construct a [`Waker`] from some type `W` implementing this trait, +/// wrap it in an [`Arc`](Arc) and call `Waker::from()` on that. +/// It is also possible to convert to [`RawWaker`] in the same way. +/// +/// +/// +/// # Examples +/// +/// A basic `block_on` function that takes a future and runs it to completion on +/// the current thread. +/// +/// **Note:** This example trades correctness for simplicity. In order to prevent +/// deadlocks, production-grade implementations will also need to handle +/// intermediate calls to `thread::unpark` as well as nested invocations. +/// +/// ```rust +/// use std::future::Future; +/// use std::sync::Arc; +/// use std::task::{Context, Poll, Wake}; +/// use std::thread::{self, Thread}; +/// use core::pin::pin; +/// +/// /// A waker that wakes up the current thread when called. +/// struct ThreadWaker(Thread); +/// +/// impl Wake for ThreadWaker { +/// fn wake(self: Arc) { +/// self.0.unpark(); +/// } +/// } +/// +/// /// Run a future to completion on the current thread. +/// fn block_on(fut: impl Future) -> T { +/// // Pin the future so it can be polled. +/// let mut fut = pin!(fut); +/// +/// // Create a new context to be passed to the future. +/// let t = thread::current(); +/// let waker = Arc::new(ThreadWaker(t)).into(); +/// let mut cx = Context::from_waker(&waker); +/// +/// // Run the future to completion. +/// loop { +/// match fut.as_mut().poll(&mut cx) { +/// Poll::Ready(res) => return res, +/// Poll::Pending => thread::park(), +/// } +/// } +/// } +/// +/// block_on(async { +/// println!("Hi from inside a future!"); +/// }); +/// ``` +#[cfg(target_has_atomic = "ptr")] +#[stable(feature = "wake_trait", since = "1.51.0")] +pub trait Wake { + /// Wake this task. + #[stable(feature = "wake_trait", since = "1.51.0")] + fn wake(self: Arc); + + /// Wake this task without consuming the waker. + /// + /// If an executor supports a cheaper way to wake without consuming the + /// waker, it should override this method. By default, it clones the + /// [`Arc`] and calls [`wake`] on the clone. + /// + /// [`wake`]: Wake::wake + #[stable(feature = "wake_trait", since = "1.51.0")] + fn wake_by_ref(self: &Arc) { + self.clone().wake(); + } +} +#[cfg(target_has_atomic = "ptr")] +#[stable(feature = "wake_trait", since = "1.51.0")] +impl From> for Waker { + /// Use a [`Wake`]-able type as a `Waker`. + /// + /// No heap allocations or atomic operations are used for this conversion. + fn from(waker: Arc) -> Waker { + // SAFETY: This is safe because raw_waker safely constructs + // a RawWaker from Arc. + unsafe { Waker::from_raw(raw_waker(waker)) } + } +} +#[cfg(target_has_atomic = "ptr")] +#[stable(feature = "wake_trait", since = "1.51.0")] +impl From> for RawWaker { + /// Use a `Wake`-able type as a `RawWaker`. + /// + /// No heap allocations or atomic operations are used for this conversion. + fn from(waker: Arc) -> RawWaker { + raw_waker(waker) + } +} + +// NB: This private function for constructing a RawWaker is used, rather than +// inlining this into the `From> for RawWaker` impl, to ensure that +// the safety of `From> for Waker` does not depend on the correct +// trait dispatch - instead both impls call this function directly and +// explicitly. +#[cfg(target_has_atomic = "ptr")] +#[inline(always)] +fn raw_waker(waker: Arc) -> RawWaker { + // Increment the reference count of the arc to clone it. + // + // The #[inline(always)] is to ensure that raw_waker and clone_waker are + // always generated in the same code generation unit as one another, and + // therefore that the structurally identical const-promoted RawWakerVTable + // within both functions is deduplicated at LLVM IR code generation time. + // This allows optimizing Waker::will_wake to a single pointer comparison of + // the vtable pointers, rather than comparing all four function pointers + // within the vtables. + #[inline(always)] + unsafe fn clone_waker(waker: *const ()) -> RawWaker { + unsafe { Arc::increment_strong_count(waker as *const W) }; + RawWaker::new( + waker, + &RawWakerVTable::new(clone_waker::, wake::, wake_by_ref::, drop_waker::), + ) + } + + // Wake by value, moving the Arc into the Wake::wake function + unsafe fn wake(waker: *const ()) { + let waker = unsafe { Arc::from_raw(waker as *const W) }; + ::wake(waker); + } + + // Wake by reference, wrap the waker in ManuallyDrop to avoid dropping it + unsafe fn wake_by_ref(waker: *const ()) { + let waker = unsafe { ManuallyDrop::new(Arc::from_raw(waker as *const W)) }; + ::wake_by_ref(&waker); + } + + // Decrement the reference count of the Arc on drop + unsafe fn drop_waker(waker: *const ()) { + unsafe { Arc::decrement_strong_count(waker as *const W) }; + } + + RawWaker::new( + Arc::into_raw(waker) as *const (), + &RawWakerVTable::new(clone_waker::, wake::, wake_by_ref::, drop_waker::), + ) +} + +/// An analogous trait to `Wake` but used to construct a `LocalWaker`. +/// +/// This API works in exactly the same way as `Wake`, +/// except that it uses an `Rc` instead of an `Arc`, +/// and the result is a `LocalWaker` instead of a `Waker`. +/// +/// The benefits of using `LocalWaker` over `Waker` are that it allows the local waker +/// to hold data that does not implement `Send` and `Sync`. Additionally, it saves calls +/// to `Arc::clone`, which requires atomic synchronization. +/// +/// +/// # Examples +/// +/// This is a simplified example of a `spawn` and a `block_on` function. The `spawn` function +/// is used to push new tasks onto the run queue, while the block on function will remove them +/// and poll them. When a task is woken, it will put itself back on the run queue to be polled +/// by the executor. +/// +/// **Note:** This example trades correctness for simplicity. A real world example would interleave +/// poll calls with calls to an io reactor to wait for events instead of spinning on a loop. +/// +/// ```rust +/// #![feature(local_waker)] +/// use std::task::{LocalWake, ContextBuilder, LocalWaker, Waker}; +/// use std::future::Future; +/// use std::pin::Pin; +/// use std::rc::Rc; +/// use std::cell::RefCell; +/// use std::collections::VecDeque; +/// +/// +/// thread_local! { +/// // A queue containing all tasks ready to do progress +/// static RUN_QUEUE: RefCell>> = RefCell::default(); +/// } +/// +/// type BoxedFuture = Pin>>; +/// +/// struct Task(RefCell); +/// +/// impl LocalWake for Task { +/// fn wake(self: Rc) { +/// RUN_QUEUE.with_borrow_mut(|queue| { +/// queue.push_back(self) +/// }) +/// } +/// } +/// +/// fn spawn(future: F) +/// where +/// F: Future + 'static + Send + Sync +/// { +/// let task = RefCell::new(Box::pin(future)); +/// RUN_QUEUE.with_borrow_mut(|queue| { +/// queue.push_back(Rc::new(Task(task))); +/// }); +/// } +/// +/// fn block_on(future: F) +/// where +/// F: Future + 'static + Sync + Send +/// { +/// spawn(future); +/// loop { +/// let Some(task) = RUN_QUEUE.with_borrow_mut(|queue| queue.pop_front()) else { +/// // we exit, since there are no more tasks remaining on the queue +/// return; +/// }; +/// +/// // cast the Rc into a `LocalWaker` +/// let local_waker: LocalWaker = task.clone().into(); +/// // Build the context using `ContextBuilder` +/// let mut cx = ContextBuilder::from_waker(Waker::noop()) +/// .local_waker(&local_waker) +/// .build(); +/// +/// // Poll the task +/// let _ = task.0 +/// .borrow_mut() +/// .as_mut() +/// .poll(&mut cx); +/// } +/// } +/// +/// block_on(async { +/// println!("hello world"); +/// }); +/// ``` +/// +#[unstable(feature = "local_waker", issue = "118959")] +pub trait LocalWake { + /// Wake this task. + #[unstable(feature = "local_waker", issue = "118959")] + fn wake(self: Rc); + + /// Wake this task without consuming the local waker. + /// + /// If an executor supports a cheaper way to wake without consuming the + /// waker, it should override this method. By default, it clones the + /// [`Rc`] and calls [`wake`] on the clone. + /// + /// [`wake`]: LocalWaker::wake + #[unstable(feature = "local_waker", issue = "118959")] + fn wake_by_ref(self: &Rc) { + self.clone().wake(); + } +} + +#[unstable(feature = "local_waker", issue = "118959")] +impl From> for LocalWaker { + /// Use a `Wake`-able type as a `LocalWaker`. + /// + /// No heap allocations or atomic operations are used for this conversion. + fn from(waker: Rc) -> LocalWaker { + // SAFETY: This is safe because raw_waker safely constructs + // a RawWaker from Rc. + unsafe { LocalWaker::from_raw(local_raw_waker(waker)) } + } +} +#[allow(ineffective_unstable_trait_impl)] +#[unstable(feature = "local_waker", issue = "118959")] +impl From> for RawWaker { + /// Use a `Wake`-able type as a `RawWaker`. + /// + /// No heap allocations or atomic operations are used for this conversion. + fn from(waker: Rc) -> RawWaker { + local_raw_waker(waker) + } +} + +// NB: This private function for constructing a RawWaker is used, rather than +// inlining this into the `From> for RawWaker` impl, to ensure that +// the safety of `From> for Waker` does not depend on the correct +// trait dispatch - instead both impls call this function directly and +// explicitly. +#[inline(always)] +fn local_raw_waker(waker: Rc) -> RawWaker { + // Increment the reference count of the Rc to clone it. + // + // Refer to the comment on raw_waker's clone_waker regarding why this is + // always inline. + #[inline(always)] + unsafe fn clone_waker(waker: *const ()) -> RawWaker { + unsafe { Rc::increment_strong_count(waker as *const W) }; + RawWaker::new( + waker, + &RawWakerVTable::new(clone_waker::, wake::, wake_by_ref::, drop_waker::), + ) + } + + // Wake by value, moving the Rc into the LocalWake::wake function + unsafe fn wake(waker: *const ()) { + let waker = unsafe { Rc::from_raw(waker as *const W) }; + ::wake(waker); + } + + // Wake by reference, wrap the waker in ManuallyDrop to avoid dropping it + unsafe fn wake_by_ref(waker: *const ()) { + let waker = unsafe { ManuallyDrop::new(Rc::from_raw(waker as *const W)) }; + ::wake_by_ref(&waker); + } + + // Decrement the reference count of the Rc on drop + unsafe fn drop_waker(waker: *const ()) { + unsafe { Rc::decrement_strong_count(waker as *const W) }; + } + + RawWaker::new( + Rc::into_raw(waker) as *const (), + &RawWakerVTable::new(clone_waker::, wake::, wake_by_ref::, drop_waker::), + ) +} diff --git a/CoqOfRust/alloc/testing/crash_test.rs b/CoqOfRust/alloc/testing/crash_test.rs new file mode 100644 index 000000000..684bac60d --- /dev/null +++ b/CoqOfRust/alloc/testing/crash_test.rs @@ -0,0 +1,120 @@ +use std::cmp::Ordering; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering::SeqCst; + +use crate::fmt::Debug; // the `Debug` trait is the only thing we use from `crate::fmt` + +/// A blueprint for crash test dummy instances that monitor particular events. +/// Some instances may be configured to panic at some point. +/// Events are `clone`, `drop` or some anonymous `query`. +/// +/// Crash test dummies are identified and ordered by an id, so they can be used +/// as keys in a BTreeMap. +#[derive(Debug)] +pub struct CrashTestDummy { + pub id: usize, + cloned: AtomicUsize, + dropped: AtomicUsize, + queried: AtomicUsize, +} + +impl CrashTestDummy { + /// Creates a crash test dummy design. The `id` determines order and equality of instances. + pub fn new(id: usize) -> CrashTestDummy { + CrashTestDummy { + id, + cloned: AtomicUsize::new(0), + dropped: AtomicUsize::new(0), + queried: AtomicUsize::new(0), + } + } + + /// Creates an instance of a crash test dummy that records what events it experiences + /// and optionally panics. + pub fn spawn(&self, panic: Panic) -> Instance<'_> { + Instance { origin: self, panic } + } + + /// Returns how many times instances of the dummy have been cloned. + pub fn cloned(&self) -> usize { + self.cloned.load(SeqCst) + } + + /// Returns how many times instances of the dummy have been dropped. + pub fn dropped(&self) -> usize { + self.dropped.load(SeqCst) + } + + /// Returns how many times instances of the dummy have had their `query` member invoked. + pub fn queried(&self) -> usize { + self.queried.load(SeqCst) + } +} + +#[derive(Debug)] +pub struct Instance<'a> { + origin: &'a CrashTestDummy, + panic: Panic, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Panic { + Never, + InClone, + InDrop, + InQuery, +} + +impl Instance<'_> { + pub fn id(&self) -> usize { + self.origin.id + } + + /// Some anonymous query, the result of which is already given. + pub fn query(&self, result: R) -> R { + self.origin.queried.fetch_add(1, SeqCst); + if self.panic == Panic::InQuery { + panic!("panic in `query`"); + } + result + } +} + +impl Clone for Instance<'_> { + fn clone(&self) -> Self { + self.origin.cloned.fetch_add(1, SeqCst); + if self.panic == Panic::InClone { + panic!("panic in `clone`"); + } + Self { origin: self.origin, panic: Panic::Never } + } +} + +impl Drop for Instance<'_> { + fn drop(&mut self) { + self.origin.dropped.fetch_add(1, SeqCst); + if self.panic == Panic::InDrop { + panic!("panic in `drop`"); + } + } +} + +impl PartialOrd for Instance<'_> { + fn partial_cmp(&self, other: &Self) -> Option { + self.id().partial_cmp(&other.id()) + } +} + +impl Ord for Instance<'_> { + fn cmp(&self, other: &Self) -> Ordering { + self.id().cmp(&other.id()) + } +} + +impl PartialEq for Instance<'_> { + fn eq(&self, other: &Self) -> bool { + self.id().eq(&other.id()) + } +} + +impl Eq for Instance<'_> {} diff --git a/CoqOfRust/alloc/testing/mod.rs b/CoqOfRust/alloc/testing/mod.rs new file mode 100644 index 000000000..7a094f8a5 --- /dev/null +++ b/CoqOfRust/alloc/testing/mod.rs @@ -0,0 +1,3 @@ +pub mod crash_test; +pub mod ord_chaos; +pub mod rng; diff --git a/CoqOfRust/alloc/testing/ord_chaos.rs b/CoqOfRust/alloc/testing/ord_chaos.rs new file mode 100644 index 000000000..96ce7c157 --- /dev/null +++ b/CoqOfRust/alloc/testing/ord_chaos.rs @@ -0,0 +1,81 @@ +use std::cell::Cell; +use std::cmp::Ordering::{self, *}; +use std::ptr; + +// Minimal type with an `Ord` implementation violating transitivity. +#[derive(Debug)] +pub enum Cyclic3 { + A, + B, + C, +} +use Cyclic3::*; + +impl PartialOrd for Cyclic3 { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Cyclic3 { + fn cmp(&self, other: &Self) -> Ordering { + match (self, other) { + (A, A) | (B, B) | (C, C) => Equal, + (A, B) | (B, C) | (C, A) => Less, + (A, C) | (B, A) | (C, B) => Greater, + } + } +} + +impl PartialEq for Cyclic3 { + fn eq(&self, other: &Self) -> bool { + self.cmp(&other) == Equal + } +} + +impl Eq for Cyclic3 {} + +// Controls the ordering of values wrapped by `Governed`. +#[derive(Debug)] +pub struct Governor { + flipped: Cell, +} + +impl Governor { + pub fn new() -> Self { + Governor { flipped: Cell::new(false) } + } + + pub fn flip(&self) { + self.flipped.set(!self.flipped.get()); + } +} + +// Type with an `Ord` implementation that forms a total order at any moment +// (assuming that `T` respects total order), but can suddenly be made to invert +// that total order. +#[derive(Debug)] +pub struct Governed<'a, T>(pub T, pub &'a Governor); + +impl PartialOrd for Governed<'_, T> { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Governed<'_, T> { + fn cmp(&self, other: &Self) -> Ordering { + assert!(ptr::eq(self.1, other.1)); + let ord = self.0.cmp(&other.0); + if self.1.flipped.get() { ord.reverse() } else { ord } + } +} + +impl PartialEq for Governed<'_, T> { + fn eq(&self, other: &Self) -> bool { + assert!(ptr::eq(self.1, other.1)); + self.0.eq(&other.0) + } +} + +impl Eq for Governed<'_, T> {} diff --git a/CoqOfRust/alloc/testing/rng.rs b/CoqOfRust/alloc/testing/rng.rs new file mode 100644 index 000000000..ecf543bee --- /dev/null +++ b/CoqOfRust/alloc/testing/rng.rs @@ -0,0 +1,28 @@ +/// XorShiftRng +pub struct DeterministicRng { + count: usize, + x: u32, + y: u32, + z: u32, + w: u32, +} + +impl DeterministicRng { + pub fn new() -> Self { + DeterministicRng { count: 0, x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb } + } + + /// Guarantees that each returned number is unique. + pub fn next(&mut self) -> u32 { + self.count += 1; + assert!(self.count <= 70029); + let x = self.x; + let t = x ^ (x << 11); + self.x = self.y; + self.y = self.z; + self.z = self.w; + let w_ = self.w; + self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8)); + self.w + } +} diff --git a/CoqOfRust/alloc/tests.rs b/CoqOfRust/alloc/tests.rs new file mode 100644 index 000000000..b95d11cb0 --- /dev/null +++ b/CoqOfRust/alloc/tests.rs @@ -0,0 +1,140 @@ +//! Test for `boxed` mod. + +use core::any::Any; +use core::ops::Deref; +use std::boxed::Box; + +#[test] +fn test_owned_clone() { + let a = Box::new(5); + let b: Box = a.clone(); + assert!(a == b); +} + +#[derive(Debug, PartialEq, Eq)] +struct Test; + +#[test] +fn any_move() { + let a = Box::new(8) as Box; + let b = Box::new(Test) as Box; + + let a: Box = a.downcast::().unwrap(); + assert_eq!(*a, 8); + + let b: Box = b.downcast::().unwrap(); + assert_eq!(*b, Test); + + let a = Box::new(8) as Box; + let b = Box::new(Test) as Box; + + assert!(a.downcast::>().is_err()); + assert!(b.downcast::>().is_err()); +} + +#[test] +fn test_show() { + let a = Box::new(8) as Box; + let b = Box::new(Test) as Box; + let a_str = format!("{a:?}"); + let b_str = format!("{b:?}"); + assert_eq!(a_str, "Any { .. }"); + assert_eq!(b_str, "Any { .. }"); + + static EIGHT: usize = 8; + static TEST: Test = Test; + let a = &EIGHT as &dyn Any; + let b = &TEST as &dyn Any; + let s = format!("{a:?}"); + assert_eq!(s, "Any { .. }"); + let s = format!("{b:?}"); + assert_eq!(s, "Any { .. }"); +} + +#[test] +fn deref() { + fn homura>(_: T) {} + homura(Box::new(765)); +} + +#[test] +fn raw_sized() { + let x = Box::new(17); + let p = Box::into_raw(x); + unsafe { + assert_eq!(17, *p); + *p = 19; + let y = Box::from_raw(p); + assert_eq!(19, *y); + } +} + +#[test] +fn raw_trait() { + trait Foo { + fn get(&self) -> u32; + fn set(&mut self, value: u32); + } + + struct Bar(u32); + + impl Foo for Bar { + fn get(&self) -> u32 { + self.0 + } + + fn set(&mut self, value: u32) { + self.0 = value; + } + } + + let x: Box = Box::new(Bar(17)); + let p = Box::into_raw(x); + unsafe { + assert_eq!(17, (*p).get()); + (*p).set(19); + let y: Box = Box::from_raw(p); + assert_eq!(19, y.get()); + } +} + +#[test] +fn f64_slice() { + let slice: &[f64] = &[-1.0, 0.0, 1.0, f64::INFINITY]; + let boxed: Box<[f64]> = Box::from(slice); + assert_eq!(&*boxed, slice) +} + +#[test] +fn i64_slice() { + let slice: &[i64] = &[i64::MIN, -2, -1, 0, 1, 2, i64::MAX]; + let boxed: Box<[i64]> = Box::from(slice); + assert_eq!(&*boxed, slice) +} + +#[test] +fn str_slice() { + let s = "Hello, world!"; + let boxed: Box = Box::from(s); + assert_eq!(&*boxed, s) +} + +#[test] +fn boxed_slice_from_iter() { + let iter = 0..100; + let boxed: Box<[u32]> = iter.collect(); + assert_eq!(boxed.len(), 100); + assert_eq!(boxed[7], 7); +} + +#[test] +fn test_array_from_slice() { + let v = vec![1, 2, 3]; + let r: Box<[u32]> = v.into_boxed_slice(); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_ok()); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_err()); +} diff --git a/CoqOfRust/alloc/vec/cow.rs b/CoqOfRust/alloc/vec/cow.rs new file mode 100644 index 000000000..4deb35eff --- /dev/null +++ b/CoqOfRust/alloc/vec/cow.rs @@ -0,0 +1,65 @@ +use super::Vec; +use crate::borrow::Cow; + +#[stable(feature = "cow_from_vec", since = "1.8.0")] +impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { + /// Creates a [`Borrowed`] variant of [`Cow`] + /// from a slice. + /// + /// This conversion does not allocate or clone the data. + /// + /// [`Borrowed`]: crate::borrow::Cow::Borrowed + fn from(s: &'a [T]) -> Cow<'a, [T]> { + Cow::Borrowed(s) + } +} + +#[stable(feature = "cow_from_array_ref", since = "1.77.0")] +impl<'a, T: Clone, const N: usize> From<&'a [T; N]> for Cow<'a, [T]> { + /// Creates a [`Borrowed`] variant of [`Cow`] + /// from a reference to an array. + /// + /// This conversion does not allocate or clone the data. + /// + /// [`Borrowed`]: crate::borrow::Cow::Borrowed + fn from(s: &'a [T; N]) -> Cow<'a, [T]> { + Cow::Borrowed(s as &[_]) + } +} + +#[stable(feature = "cow_from_vec", since = "1.8.0")] +impl<'a, T: Clone> From> for Cow<'a, [T]> { + /// Creates an [`Owned`] variant of [`Cow`] + /// from an owned instance of [`Vec`]. + /// + /// This conversion does not allocate or clone the data. + /// + /// [`Owned`]: crate::borrow::Cow::Owned + fn from(v: Vec) -> Cow<'a, [T]> { + Cow::Owned(v) + } +} + +#[stable(feature = "cow_from_vec_ref", since = "1.28.0")] +impl<'a, T: Clone> From<&'a Vec> for Cow<'a, [T]> { + /// Creates a [`Borrowed`] variant of [`Cow`] + /// from a reference to [`Vec`]. + /// + /// This conversion does not allocate or clone the data. + /// + /// [`Borrowed`]: crate::borrow::Cow::Borrowed + fn from(v: &'a Vec) -> Cow<'a, [T]> { + Cow::Borrowed(v.as_slice()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> FromIterator for Cow<'a, [T]> +where + T: Clone, +{ + #[track_caller] + fn from_iter>(it: I) -> Cow<'a, [T]> { + Cow::Owned(FromIterator::from_iter(it)) + } +} diff --git a/CoqOfRust/alloc/vec/drain.rs b/CoqOfRust/alloc/vec/drain.rs new file mode 100644 index 000000000..9362cef2a --- /dev/null +++ b/CoqOfRust/alloc/vec/drain.rs @@ -0,0 +1,253 @@ +use core::fmt; +use core::iter::{FusedIterator, TrustedLen}; +use core::mem::{self, ManuallyDrop, SizedTypeProperties}; +use core::ptr::{self, NonNull}; +use core::slice::{self}; + +use super::Vec; +use crate::alloc::{Allocator, Global}; + +/// A draining iterator for `Vec`. +/// +/// This `struct` is created by [`Vec::drain`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// let mut v = vec![0, 1, 2]; +/// let iter: std::vec::Drain<'_, _> = v.drain(..); +/// ``` +#[stable(feature = "drain", since = "1.6.0")] +pub struct Drain< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, +> { + /// Index of tail to preserve + pub(super) tail_start: usize, + /// Length of tail + pub(super) tail_len: usize, + /// Current remaining range to remove + pub(super) iter: slice::Iter<'a, T>, + pub(super) vec: NonNull>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Drain<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Drain").field(&self.iter.as_slice()).finish() + } +} + +impl<'a, T, A: Allocator> Drain<'a, T, A> { + /// Returns the remaining items of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec!['a', 'b', 'c']; + /// let mut drain = vec.drain(..); + /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']); + /// let _ = drain.next().unwrap(); + /// assert_eq!(drain.as_slice(), &['b', 'c']); + /// ``` + #[must_use] + #[stable(feature = "vec_drain_as_slice", since = "1.46.0")] + pub fn as_slice(&self) -> &[T] { + self.iter.as_slice() + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] + #[inline] + pub fn allocator(&self) -> &A { + unsafe { self.vec.as_ref().allocator() } + } + + /// Keep unyielded elements in the source `Vec`. + /// + /// # Examples + /// + /// ``` + /// #![feature(drain_keep_rest)] + /// + /// let mut vec = vec!['a', 'b', 'c']; + /// let mut drain = vec.drain(..); + /// + /// assert_eq!(drain.next().unwrap(), 'a'); + /// + /// // This call keeps 'b' and 'c' in the vec. + /// drain.keep_rest(); + /// + /// // If we wouldn't call `keep_rest()`, + /// // `vec` would be empty. + /// assert_eq!(vec, ['b', 'c']); + /// ``` + #[unstable(feature = "drain_keep_rest", issue = "101122")] + pub fn keep_rest(self) { + // At this moment layout looks like this: + // + // [head] [yielded by next] [unyielded] [yielded by next_back] [tail] + // ^-- start \_________/-- unyielded_len \____/-- self.tail_len + // ^-- unyielded_ptr ^-- tail + // + // Normally `Drop` impl would drop [unyielded] and then move [tail] to the `start`. + // Here we want to + // 1. Move [unyielded] to `start` + // 2. Move [tail] to a new start at `start + len(unyielded)` + // 3. Update length of the original vec to `len(head) + len(unyielded) + len(tail)` + // a. In case of ZST, this is the only thing we want to do + // 4. Do *not* drop self, as everything is put in a consistent state already, there is nothing to do + let mut this = ManuallyDrop::new(self); + + unsafe { + let source_vec = this.vec.as_mut(); + + let start = source_vec.len(); + let tail = this.tail_start; + + let unyielded_len = this.iter.len(); + let unyielded_ptr = this.iter.as_slice().as_ptr(); + + // ZSTs have no identity, so we don't need to move them around. + if !T::IS_ZST { + let start_ptr = source_vec.as_mut_ptr().add(start); + + // memmove back unyielded elements + if unyielded_ptr != start_ptr { + let src = unyielded_ptr; + let dst = start_ptr; + + ptr::copy(src, dst, unyielded_len); + } + + // memmove back untouched tail + if tail != (start + unyielded_len) { + let src = source_vec.as_ptr().add(tail); + let dst = start_ptr.add(unyielded_len); + ptr::copy(src, dst, this.tail_len); + } + } + + source_vec.set_len(start + unyielded_len + this.tail_len); + } + } +} + +#[stable(feature = "vec_drain_as_slice", since = "1.46.0")] +impl<'a, T, A: Allocator> AsRef<[T]> for Drain<'a, T, A> { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Sync for Drain<'_, T, A> {} +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Send for Drain<'_, T, A> {} + +#[stable(feature = "drain", since = "1.6.0")] +impl Iterator for Drain<'_, T, A> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) }) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl DoubleEndedIterator for Drain<'_, T, A> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) }) + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl Drop for Drain<'_, T, A> { + fn drop(&mut self) { + /// Moves back the un-`Drain`ed elements to restore the original `Vec`. + struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); + + impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { + fn drop(&mut self) { + if self.0.tail_len > 0 { + unsafe { + let source_vec = self.0.vec.as_mut(); + // memmove back untouched tail, update to new length + let start = source_vec.len(); + let tail = self.0.tail_start; + if tail != start { + let src = source_vec.as_ptr().add(tail); + let dst = source_vec.as_mut_ptr().add(start); + ptr::copy(src, dst, self.0.tail_len); + } + source_vec.set_len(start + self.0.tail_len); + } + } + } + } + + let iter = mem::take(&mut self.iter); + let drop_len = iter.len(); + + let mut vec = self.vec; + + if T::IS_ZST { + // ZSTs have no identity, so we don't need to move them around, we only need to drop the correct amount. + // this can be achieved by manipulating the Vec length instead of moving values out from `iter`. + unsafe { + let vec = vec.as_mut(); + let old_len = vec.len(); + vec.set_len(old_len + drop_len + self.tail_len); + vec.truncate(old_len + self.tail_len); + } + + return; + } + + // ensure elements are moved back into their appropriate places, even when drop_in_place panics + let _guard = DropGuard(self); + + if drop_len == 0 { + return; + } + + // as_slice() must only be called when iter.len() is > 0 because + // it also gets touched by vec::Splice which may turn it into a dangling pointer + // which would make it and the vec pointer point to different allocations which would + // lead to invalid pointer arithmetic below. + let drop_ptr = iter.as_slice().as_ptr(); + + unsafe { + // drop_ptr comes from a slice::Iter which only gives us a &[T] but for drop_in_place + // a pointer with mutable provenance is necessary. Therefore we must reconstruct + // it from the original vec but also avoid creating a &mut to the front since that could + // invalidate raw pointers to it which some unsafe code might rely on. + let vec_ptr = vec.as_mut().as_mut_ptr(); + let drop_offset = drop_ptr.sub_ptr(vec_ptr); + let to_drop = ptr::slice_from_raw_parts_mut(vec_ptr.add(drop_offset), drop_len); + ptr::drop_in_place(to_drop); + } + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl ExactSizeIterator for Drain<'_, T, A> { + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Drain<'_, T, A> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Drain<'_, T, A> {} diff --git a/CoqOfRust/alloc/vec/extract_if.rs b/CoqOfRust/alloc/vec/extract_if.rs new file mode 100644 index 000000000..72d51e890 --- /dev/null +++ b/CoqOfRust/alloc/vec/extract_if.rs @@ -0,0 +1,112 @@ +use core::{ptr, slice}; + +use super::Vec; +use crate::alloc::{Allocator, Global}; + +/// An iterator which uses a closure to determine if an element should be removed. +/// +/// This struct is created by [`Vec::extract_if`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// #![feature(extract_if)] +/// +/// let mut v = vec![0, 1, 2]; +/// let iter: std::vec::ExtractIf<'_, _, _> = v.extract_if(|x| *x % 2 == 0); +/// ``` +#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] +#[derive(Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct ExtractIf< + 'a, + T, + F, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> where + F: FnMut(&mut T) -> bool, +{ + pub(super) vec: &'a mut Vec, + /// The index of the item that will be inspected by the next call to `next`. + pub(super) idx: usize, + /// The number of items that have been drained (removed) thus far. + pub(super) del: usize, + /// The original length of `vec` prior to draining. + pub(super) old_len: usize, + /// The filter test predicate. + pub(super) pred: F, +} + +impl ExtractIf<'_, T, F, A> +where + F: FnMut(&mut T) -> bool, +{ + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + self.vec.allocator() + } +} + +#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] +impl Iterator for ExtractIf<'_, T, F, A> +where + F: FnMut(&mut T) -> bool, +{ + type Item = T; + + fn next(&mut self) -> Option { + unsafe { + while self.idx < self.old_len { + let i = self.idx; + let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); + let drained = (self.pred)(&mut v[i]); + // Update the index *after* the predicate is called. If the index + // is updated prior and the predicate panics, the element at this + // index would be leaked. + self.idx += 1; + if drained { + self.del += 1; + return Some(ptr::read(&v[i])); + } else if self.del > 0 { + let del = self.del; + let src: *const T = &v[i]; + let dst: *mut T = &mut v[i - del]; + ptr::copy_nonoverlapping(src, dst, 1); + } + } + None + } + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.old_len - self.idx)) + } +} + +#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] +impl Drop for ExtractIf<'_, T, F, A> +where + F: FnMut(&mut T) -> bool, +{ + fn drop(&mut self) { + unsafe { + if self.idx < self.old_len && self.del > 0 { + // This is a pretty messed up state, and there isn't really an + // obviously right thing to do. We don't want to keep trying + // to execute `pred`, so we just backshift all the unprocessed + // elements and tell the vec that they still exist. The backshift + // is required to prevent a double-drop of the last successfully + // drained item prior to a panic in the predicate. + let ptr = self.vec.as_mut_ptr(); + let src = ptr.add(self.idx); + let dst = src.sub(self.del); + let tail_len = self.old_len - self.idx; + src.copy_to(dst, tail_len); + } + self.vec.set_len(self.old_len - self.del); + } + } +} diff --git a/CoqOfRust/alloc/vec/in_place_collect.rs b/CoqOfRust/alloc/vec/in_place_collect.rs new file mode 100644 index 000000000..a7dba1694 --- /dev/null +++ b/CoqOfRust/alloc/vec/in_place_collect.rs @@ -0,0 +1,431 @@ +//! Inplace iterate-and-collect specialization for `Vec` +//! +//! Note: This documents Vec internals, some of the following sections explain implementation +//! details and are best read together with the source of this module. +//! +//! The specialization in this module applies to iterators in the shape of +//! `source.adapter().adapter().adapter().collect::>()` +//! where `source` is an owning iterator obtained from [`Vec`], [`Box<[T]>`][box] (by conversion to `Vec`) +//! or [`BinaryHeap`], the adapters guarantee to consume enough items per step to make room +//! for the results (represented by [`InPlaceIterable`]), provide transitive access to `source` +//! (via [`SourceIter`]) and thus the underlying allocation. +//! And finally there are alignment and size constraints to consider, this is currently ensured via +//! const eval instead of trait bounds in the specialized [`SpecFromIter`] implementation. +//! +//! [`BinaryHeap`]: crate::collections::BinaryHeap +//! [box]: crate::boxed::Box +//! +//! By extension some other collections which use `collect::>()` internally in their +//! `FromIterator` implementation benefit from this too. +//! +//! Access to the underlying source goes through a further layer of indirection via the private +//! trait [`AsVecIntoIter`] to hide the implementation detail that other collections may use +//! `vec::IntoIter` internally. +//! +//! In-place iteration depends on the interaction of several unsafe traits, implementation +//! details of multiple parts in the iterator pipeline and often requires holistic reasoning +//! across multiple structs since iterators are executed cooperatively rather than having +//! a central evaluator/visitor struct executing all iterator components. +//! +//! # Reading from and writing to the same allocation +//! +//! By its nature collecting in place means that the reader and writer side of the iterator +//! use the same allocation. Since `try_fold()` (used in [`SpecInPlaceCollect`]) takes a +//! reference to the iterator for the duration of the iteration that means we can't interleave +//! the step of reading a value and getting a reference to write to. Instead raw pointers must be +//! used on the reader and writer side. +//! +//! That writes never clobber a yet-to-be-read items is ensured by the [`InPlaceIterable`] requirements. +//! +//! # Layout constraints +//! +//! When recycling an allocation between different types we must uphold the [`Allocator`] contract +//! which means that the input and output Layouts have to "fit". +//! +//! To complicate things further `InPlaceIterable` supports splitting or merging items into smaller/ +//! larger ones to enable (de)aggregation of arrays. +//! +//! Ultimately each step of the iterator must free up enough *bytes* in the source to make room +//! for the next output item. +//! If `T` and `U` have the same size no fixup is needed. +//! If `T`'s size is a multiple of `U`'s we can compensate by multiplying the capacity accordingly. +//! Otherwise the input capacity (and thus layout) in bytes may not be representable by the output +//! `Vec`. In that case `alloc.shrink()` is used to update the allocation's layout. +//! +//! Alignments of `T` must be the same or larger than `U`. Since alignments are always a power +//! of two _larger_ implies _is a multiple of_. +//! +//! See `in_place_collectible()` for the current conditions. +//! +//! Additionally this specialization doesn't make sense for ZSTs as there is no reallocation to +//! avoid and it would make pointer arithmetic more difficult. +//! +//! [`Allocator`]: core::alloc::Allocator +//! +//! # Drop- and panic-safety +//! +//! Iteration can panic, requiring dropping the already written parts but also the remainder of +//! the source. Iteration can also leave some source items unconsumed which must be dropped. +//! All those drops in turn can panic which then must either leak the allocation or abort to avoid +//! double-drops. +//! +//! This is handled by the [`InPlaceDrop`] guard for sink items (`U`) and by +//! [`vec::IntoIter::forget_allocation_drop_remaining()`] for remaining source items (`T`). +//! +//! If dropping any remaining source item (`T`) panics then [`InPlaceDstDataSrcBufDrop`] will handle dropping +//! the already collected sink items (`U`) and freeing the allocation. +//! +//! [`vec::IntoIter::forget_allocation_drop_remaining()`]: super::IntoIter::forget_allocation_drop_remaining() +//! +//! # O(1) collect +//! +//! The main iteration itself is further specialized when the iterator implements +//! [`TrustedRandomAccessNoCoerce`] to let the optimizer see that it is a counted loop with a single +//! [induction variable]. This can turn some iterators into a noop, i.e. it reduces them from O(n) to +//! O(1). This particular optimization is quite fickle and doesn't always work, see [#79308] +//! +//! [#79308]: https://github.com/rust-lang/rust/issues/79308 +//! [induction variable]: https://en.wikipedia.org/wiki/Induction_variable +//! +//! Since unchecked accesses through that trait do not advance the read pointer of `IntoIter` +//! this would interact unsoundly with the requirements about dropping the tail described above. +//! But since the normal `Drop` implementation of `IntoIter` would suffer from the same problem it +//! is only correct for `TrustedRandomAccessNoCoerce` to be implemented when the items don't +//! have a destructor. Thus that implicit requirement also makes the specialization safe to use for +//! in-place collection. +//! Note that this safety concern is about the correctness of `impl Drop for IntoIter`, +//! not the guarantees of `InPlaceIterable`. +//! +//! # Adapter implementations +//! +//! The invariants for adapters are documented in [`SourceIter`] and [`InPlaceIterable`], but +//! getting them right can be rather subtle for multiple, sometimes non-local reasons. +//! For example `InPlaceIterable` would be valid to implement for [`Peekable`], except +//! that it is stateful, cloneable and `IntoIter`'s clone implementation shortens the underlying +//! allocation which means if the iterator has been peeked and then gets cloned there no longer is +//! enough room, thus breaking an invariant ([#85322]). +//! +//! [#85322]: https://github.com/rust-lang/rust/issues/85322 +//! [`Peekable`]: core::iter::Peekable +//! +//! +//! # Examples +//! +//! Some cases that are optimized by this specialization, more can be found in the `Vec` +//! benchmarks: +//! +//! ```rust +//! # #[allow(dead_code)] +//! /// Converts a usize vec into an isize one. +//! pub fn cast(vec: Vec) -> Vec { +//! // Does not allocate, free or panic. On optlevel>=2 it does not loop. +//! // Of course this particular case could and should be written with `into_raw_parts` and +//! // `from_raw_parts` instead. +//! vec.into_iter().map(|u| u as isize).collect() +//! } +//! ``` +//! +//! ```rust +//! # #[allow(dead_code)] +//! /// Drops remaining items in `src` and if the layouts of `T` and `U` match it +//! /// returns an empty Vec backed by the original allocation. Otherwise it returns a new +//! /// empty vec. +//! pub fn recycle_allocation(src: Vec) -> Vec { +//! src.into_iter().filter_map(|_| None).collect() +//! } +//! ``` +//! +//! ```rust +//! let vec = vec![13usize; 1024]; +//! let _ = vec.into_iter() +//! .enumerate() +//! .filter_map(|(idx, val)| if idx % 2 == 0 { Some(val+idx) } else {None}) +//! .collect::>(); +//! +//! // is equivalent to the following, but doesn't require bounds checks +//! +//! let mut vec = vec![13usize; 1024]; +//! let mut write_idx = 0; +//! for idx in 0..vec.len() { +//! if idx % 2 == 0 { +//! vec[write_idx] = vec[idx] + idx; +//! write_idx += 1; +//! } +//! } +//! vec.truncate(write_idx); +//! ``` + +use core::alloc::{Allocator, Layout}; +use core::iter::{InPlaceIterable, SourceIter, TrustedRandomAccessNoCoerce}; +use core::marker::PhantomData; +use core::mem::{self, ManuallyDrop, SizedTypeProperties}; +use core::num::NonZero; +use core::ptr; + +use super::{InPlaceDrop, InPlaceDstDataSrcBufDrop, SpecFromIter, SpecFromIterNested, Vec}; +use crate::alloc::{Global, handle_alloc_error}; + +const fn in_place_collectible( + step_merge: Option>, + step_expand: Option>, +) -> bool { + // Require matching alignments because an alignment-changing realloc is inefficient on many + // system allocators and better implementations would require the unstable Allocator trait. + if const { SRC::IS_ZST || DEST::IS_ZST || mem::align_of::() != mem::align_of::() } { + return false; + } + + match (step_merge, step_expand) { + (Some(step_merge), Some(step_expand)) => { + // At least N merged source items -> at most M expanded destination items + // e.g. + // - 1 x [u8; 4] -> 4x u8, via flatten + // - 4 x u8 -> 1x [u8; 4], via array_chunks + mem::size_of::() * step_merge.get() >= mem::size_of::() * step_expand.get() + } + // Fall back to other from_iter impls if an overflow occurred in the step merge/expansion + // tracking. + _ => false, + } +} + +const fn needs_realloc(src_cap: usize, dst_cap: usize) -> bool { + if const { mem::align_of::() != mem::align_of::() } { + // FIXME(const-hack): use unreachable! once that works in const + panic!("in_place_collectible() prevents this"); + } + + // If src type size is an integer multiple of the destination type size then + // the caller will have calculated a `dst_cap` that is an integer multiple of + // `src_cap` without remainder. + if const { + let src_sz = mem::size_of::(); + let dest_sz = mem::size_of::(); + dest_sz != 0 && src_sz % dest_sz == 0 + } { + return false; + } + + // type layouts don't guarantee a fit, so do a runtime check to see if + // the allocations happen to match + src_cap > 0 && src_cap * mem::size_of::() != dst_cap * mem::size_of::() +} + +/// This provides a shorthand for the source type since local type aliases aren't a thing. +#[rustc_specialization_trait] +trait InPlaceCollect: SourceIter + InPlaceIterable { + type Src; +} + +impl InPlaceCollect for T +where + T: SourceIter + InPlaceIterable, +{ + type Src = <::Source as AsVecIntoIter>::Item; +} + +impl SpecFromIter for Vec +where + I: Iterator + InPlaceCollect, + ::Source: AsVecIntoIter, +{ + #[track_caller] + default fn from_iter(iterator: I) -> Self { + // Select the implementation in const eval to avoid codegen of the dead branch to improve compile times. + let fun: fn(I) -> Vec = const { + // See "Layout constraints" section in the module documentation. We use const conditions here + // since these conditions currently cannot be expressed as trait bounds + if in_place_collectible::(I::MERGE_BY, I::EXPAND_BY) { + from_iter_in_place + } else { + // fallback + SpecFromIterNested::::from_iter + } + }; + + fun(iterator) + } +} + +#[track_caller] +fn from_iter_in_place(mut iterator: I) -> Vec +where + I: Iterator + InPlaceCollect, + ::Source: AsVecIntoIter, +{ + let (src_buf, src_ptr, src_cap, mut dst_buf, dst_end, dst_cap) = unsafe { + let inner = iterator.as_inner().as_into_iter(); + ( + inner.buf, + inner.ptr, + inner.cap, + inner.buf.cast::(), + inner.end as *const T, + // SAFETY: the multiplication can not overflow, since `inner.cap * size_of::()` is the size of the allocation. + inner.cap.unchecked_mul(mem::size_of::()) / mem::size_of::(), + ) + }; + + // SAFETY: `dst_buf` and `dst_end` are the start and end of the buffer. + let len = unsafe { + SpecInPlaceCollect::collect_in_place(&mut iterator, dst_buf.as_ptr() as *mut T, dst_end) + }; + + let src = unsafe { iterator.as_inner().as_into_iter() }; + // check if SourceIter contract was upheld + // caveat: if they weren't we might not even make it to this point + debug_assert_eq!(src_buf, src.buf); + // check InPlaceIterable contract. This is only possible if the iterator advanced the + // source pointer at all. If it uses unchecked access via TrustedRandomAccess + // then the source pointer will stay in its initial position and we can't use it as reference + if src.ptr != src_ptr { + debug_assert!( + unsafe { dst_buf.add(len).cast() } <= src.ptr, + "InPlaceIterable contract violation, write pointer advanced beyond read pointer" + ); + } + + // The ownership of the source allocation and the new `T` values is temporarily moved into `dst_guard`. + // This is safe because + // * `forget_allocation_drop_remaining` immediately forgets the allocation + // before any panic can occur in order to avoid any double free, and then proceeds to drop + // any remaining values at the tail of the source. + // * the shrink either panics without invalidating the allocation, aborts or + // succeeds. In the last case we disarm the guard. + // + // Note: This access to the source wouldn't be allowed by the TrustedRandomIteratorNoCoerce + // contract (used by SpecInPlaceCollect below). But see the "O(1) collect" section in the + // module documentation why this is ok anyway. + let dst_guard = + InPlaceDstDataSrcBufDrop { ptr: dst_buf, len, src_cap, src: PhantomData:: }; + src.forget_allocation_drop_remaining(); + + // Adjust the allocation if the source had a capacity in bytes that wasn't a multiple + // of the destination type size. + // Since the discrepancy should generally be small this should only result in some + // bookkeeping updates and no memmove. + if needs_realloc::(src_cap, dst_cap) { + let alloc = Global; + debug_assert_ne!(src_cap, 0); + debug_assert_ne!(dst_cap, 0); + unsafe { + // The old allocation exists, therefore it must have a valid layout. + let src_align = mem::align_of::(); + let src_size = mem::size_of::().unchecked_mul(src_cap); + let old_layout = Layout::from_size_align_unchecked(src_size, src_align); + + // The allocation must be equal or smaller for in-place iteration to be possible + // therefore the new layout must be ≤ the old one and therefore valid. + let dst_align = mem::align_of::(); + let dst_size = mem::size_of::().unchecked_mul(dst_cap); + let new_layout = Layout::from_size_align_unchecked(dst_size, dst_align); + + let result = alloc.shrink(dst_buf.cast(), old_layout, new_layout); + let Ok(reallocated) = result else { handle_alloc_error(new_layout) }; + dst_buf = reallocated.cast::(); + } + } else { + debug_assert_eq!(src_cap * mem::size_of::(), dst_cap * mem::size_of::()); + } + + mem::forget(dst_guard); + + let vec = unsafe { Vec::from_parts(dst_buf, len, dst_cap) }; + + vec +} + +fn write_in_place_with_drop( + src_end: *const T, +) -> impl FnMut(InPlaceDrop, T) -> Result, !> { + move |mut sink, item| { + unsafe { + // the InPlaceIterable contract cannot be verified precisely here since + // try_fold has an exclusive reference to the source pointer + // all we can do is check if it's still in range + debug_assert!(sink.dst as *const _ <= src_end, "InPlaceIterable contract violation"); + ptr::write(sink.dst, item); + // Since this executes user code which can panic we have to bump the pointer + // after each step. + sink.dst = sink.dst.add(1); + } + Ok(sink) + } +} + +/// Helper trait to hold specialized implementations of the in-place iterate-collect loop +trait SpecInPlaceCollect: Iterator { + /// Collects an iterator (`self`) into the destination buffer (`dst`) and returns the number of items + /// collected. `end` is the last writable element of the allocation and used for bounds checks. + /// + /// This method is specialized and one of its implementations makes use of + /// `Iterator::__iterator_get_unchecked` calls with a `TrustedRandomAccessNoCoerce` bound + /// on `I` which means the caller of this method must take the safety conditions + /// of that trait into consideration. + unsafe fn collect_in_place(&mut self, dst: *mut T, end: *const T) -> usize; +} + +impl SpecInPlaceCollect for I +where + I: Iterator, +{ + #[inline] + default unsafe fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize { + // use try-fold since + // - it vectorizes better for some iterator adapters + // - unlike most internal iteration methods, it only takes a &mut self + // - it lets us thread the write pointer through its innards and get it back in the end + let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf }; + let sink = + self.try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(end)).into_ok(); + // iteration succeeded, don't drop head + unsafe { ManuallyDrop::new(sink).dst.sub_ptr(dst_buf) } + } +} + +impl SpecInPlaceCollect for I +where + I: Iterator + TrustedRandomAccessNoCoerce, +{ + #[inline] + unsafe fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize { + let len = self.size(); + let mut drop_guard = InPlaceDrop { inner: dst_buf, dst: dst_buf }; + for i in 0..len { + // Safety: InplaceIterable contract guarantees that for every element we read + // one slot in the underlying storage will have been freed up and we can immediately + // write back the result. + unsafe { + let dst = dst_buf.add(i); + debug_assert!(dst as *const _ <= end, "InPlaceIterable contract violation"); + ptr::write(dst, self.__iterator_get_unchecked(i)); + // Since this executes user code which can panic we have to bump the pointer + // after each step. + drop_guard.dst = dst.add(1); + } + } + mem::forget(drop_guard); + len + } +} + +/// Internal helper trait for in-place iteration specialization. +/// +/// Currently this is only implemented by [`vec::IntoIter`] - returning a reference to itself - and +/// [`binary_heap::IntoIter`] which returns a reference to its inner representation. +/// +/// Since this is an internal trait it hides the implementation detail `binary_heap::IntoIter` +/// uses `vec::IntoIter` internally. +/// +/// [`vec::IntoIter`]: super::IntoIter +/// [`binary_heap::IntoIter`]: crate::collections::binary_heap::IntoIter +/// +/// # Safety +/// +/// In-place iteration relies on implementation details of `vec::IntoIter`, most importantly that +/// it does not create references to the whole allocation during iteration, only raw pointers +#[rustc_specialization_trait] +pub(crate) unsafe trait AsVecIntoIter { + type Item; + fn as_into_iter(&mut self) -> &mut super::IntoIter; +} diff --git a/CoqOfRust/alloc/vec/in_place_drop.rs b/CoqOfRust/alloc/vec/in_place_drop.rs new file mode 100644 index 000000000..4d5b4e47d --- /dev/null +++ b/CoqOfRust/alloc/vec/in_place_drop.rs @@ -0,0 +1,49 @@ +use core::marker::PhantomData; +use core::ptr::{self, NonNull, drop_in_place}; +use core::slice::{self}; + +use crate::alloc::Global; +use crate::raw_vec::RawVec; + +// A helper struct for in-place iteration that drops the destination slice of iteration, +// i.e. the head. The source slice (the tail) is dropped by IntoIter. +pub(super) struct InPlaceDrop { + pub(super) inner: *mut T, + pub(super) dst: *mut T, +} + +impl InPlaceDrop { + fn len(&self) -> usize { + unsafe { self.dst.sub_ptr(self.inner) } + } +} + +impl Drop for InPlaceDrop { + #[inline] + fn drop(&mut self) { + unsafe { + ptr::drop_in_place(slice::from_raw_parts_mut(self.inner, self.len())); + } + } +} + +// A helper struct for in-place collection that drops the destination items together with +// the source allocation - i.e. before the reallocation happened - to avoid leaking them +// if some other destructor panics. +pub(super) struct InPlaceDstDataSrcBufDrop { + pub(super) ptr: NonNull, + pub(super) len: usize, + pub(super) src_cap: usize, + pub(super) src: PhantomData, +} + +impl Drop for InPlaceDstDataSrcBufDrop { + #[inline] + fn drop(&mut self) { + unsafe { + let _drop_allocation = + RawVec::::from_nonnull_in(self.ptr.cast::(), self.src_cap, Global); + drop_in_place(core::ptr::slice_from_raw_parts_mut::(self.ptr.as_ptr(), self.len)); + }; + } +} diff --git a/CoqOfRust/alloc/vec/into_iter.rs b/CoqOfRust/alloc/vec/into_iter.rs new file mode 100644 index 000000000..9a6745fdb --- /dev/null +++ b/CoqOfRust/alloc/vec/into_iter.rs @@ -0,0 +1,537 @@ +use core::iter::{ + FusedIterator, InPlaceIterable, SourceIter, TrustedFused, TrustedLen, + TrustedRandomAccessNoCoerce, +}; +use core::marker::PhantomData; +use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties}; +use core::num::NonZero; +#[cfg(not(no_global_oom_handling))] +use core::ops::Deref; +use core::ptr::{self, NonNull}; +use core::slice::{self}; +use core::{array, fmt}; + +#[cfg(not(no_global_oom_handling))] +use super::AsVecIntoIter; +use crate::alloc::{Allocator, Global}; +#[cfg(not(no_global_oom_handling))] +use crate::collections::VecDeque; +use crate::raw_vec::RawVec; + +macro non_null { + (mut $place:expr, $t:ident) => {{ + #![allow(unused_unsafe)] // we're sometimes used within an unsafe block + unsafe { &mut *((&raw mut $place) as *mut NonNull<$t>) } + }}, + ($place:expr, $t:ident) => {{ + #![allow(unused_unsafe)] // we're sometimes used within an unsafe block + unsafe { *((&raw const $place) as *const NonNull<$t>) } + }}, +} + +/// An iterator that moves out of a vector. +/// +/// This `struct` is created by the `into_iter` method on [`Vec`](super::Vec) +/// (provided by the [`IntoIterator`] trait). +/// +/// # Example +/// +/// ``` +/// let v = vec![0, 1, 2]; +/// let iter: std::vec::IntoIter<_> = v.into_iter(); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_insignificant_dtor] +pub struct IntoIter< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + pub(super) buf: NonNull, + pub(super) phantom: PhantomData, + pub(super) cap: usize, + // the drop impl reconstructs a RawVec from buf, cap and alloc + // to avoid dropping the allocator twice we need to wrap it into ManuallyDrop + pub(super) alloc: ManuallyDrop, + pub(super) ptr: NonNull, + /// If T is a ZST, this is actually ptr+len. This encoding is picked so that + /// ptr == end is a quick test for the Iterator being empty, that works + /// for both ZST and non-ZST. + /// For non-ZSTs the pointer is treated as `NonNull` + pub(super) end: *const T, +} + +#[stable(feature = "vec_intoiter_debug", since = "1.13.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoIter").field(&self.as_slice()).finish() + } +} + +impl IntoIter { + /// Returns the remaining items of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// let vec = vec!['a', 'b', 'c']; + /// let mut into_iter = vec.into_iter(); + /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); + /// let _ = into_iter.next().unwrap(); + /// assert_eq!(into_iter.as_slice(), &['b', 'c']); + /// ``` + #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] + pub fn as_slice(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len()) } + } + + /// Returns the remaining items of this iterator as a mutable slice. + /// + /// # Examples + /// + /// ``` + /// let vec = vec!['a', 'b', 'c']; + /// let mut into_iter = vec.into_iter(); + /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); + /// into_iter.as_mut_slice()[2] = 'z'; + /// assert_eq!(into_iter.next().unwrap(), 'a'); + /// assert_eq!(into_iter.next().unwrap(), 'b'); + /// assert_eq!(into_iter.next().unwrap(), 'z'); + /// ``` + #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { &mut *self.as_raw_mut_slice() } + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + &self.alloc + } + + fn as_raw_mut_slice(&mut self) -> *mut [T] { + ptr::slice_from_raw_parts_mut(self.ptr.as_ptr(), self.len()) + } + + /// Drops remaining elements and relinquishes the backing allocation. + /// + /// This method guarantees it won't panic before relinquishing the backing + /// allocation. + /// + /// This is roughly equivalent to the following, but more efficient + /// + /// ``` + /// # let mut vec = Vec::::with_capacity(10); + /// # let ptr = vec.as_mut_ptr(); + /// # let mut into_iter = vec.into_iter(); + /// let mut into_iter = std::mem::replace(&mut into_iter, Vec::new().into_iter()); + /// (&mut into_iter).for_each(drop); + /// std::mem::forget(into_iter); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # drop(unsafe { Vec::::from_raw_parts(ptr, 0, 10) }); + /// ``` + /// + /// This method is used by in-place iteration, refer to the vec::in_place_collect + /// documentation for an overview. + #[cfg(not(no_global_oom_handling))] + pub(super) fn forget_allocation_drop_remaining(&mut self) { + let remaining = self.as_raw_mut_slice(); + + // overwrite the individual fields instead of creating a new + // struct and then overwriting &mut self. + // this creates less assembly + self.cap = 0; + self.buf = RawVec::new().non_null(); + self.ptr = self.buf; + self.end = self.buf.as_ptr(); + + // Dropping the remaining elements can panic, so this needs to be + // done only after updating the other fields. + unsafe { + ptr::drop_in_place(remaining); + } + } + + /// Forgets to Drop the remaining elements while still allowing the backing allocation to be freed. + pub(crate) fn forget_remaining_elements(&mut self) { + // For the ZST case, it is crucial that we mutate `end` here, not `ptr`. + // `ptr` must stay aligned, while `end` may be unaligned. + self.end = self.ptr.as_ptr(); + } + + #[cfg(not(no_global_oom_handling))] + #[inline] + pub(crate) fn into_vecdeque(self) -> VecDeque { + // Keep our `Drop` impl from dropping the elements and the allocator + let mut this = ManuallyDrop::new(self); + + // SAFETY: This allocation originally came from a `Vec`, so it passes + // all those checks. We have `this.buf` ≤ `this.ptr` ≤ `this.end`, + // so the `sub_ptr`s below cannot wrap, and will produce a well-formed + // range. `end` ≤ `buf + cap`, so the range will be in-bounds. + // Taking `alloc` is ok because nothing else is going to look at it, + // since our `Drop` impl isn't going to run so there's no more code. + unsafe { + let buf = this.buf.as_ptr(); + let initialized = if T::IS_ZST { + // All the pointers are the same for ZSTs, so it's fine to + // say that they're all at the beginning of the "allocation". + 0..this.len() + } else { + this.ptr.sub_ptr(this.buf)..this.end.sub_ptr(buf) + }; + let cap = this.cap; + let alloc = ManuallyDrop::take(&mut this.alloc); + VecDeque::from_contiguous_raw_parts_in(buf, initialized, cap, alloc) + } + } +} + +#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")] +impl AsRef<[T]> for IntoIter { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for IntoIter {} +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for IntoIter {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + let ptr = if T::IS_ZST { + if self.ptr.as_ptr() == self.end as *mut T { + return None; + } + // `ptr` has to stay where it is to remain aligned, so we reduce the length by 1 by + // reducing the `end`. + self.end = self.end.wrapping_byte_sub(1); + self.ptr + } else { + if self.ptr == non_null!(self.end, T) { + return None; + } + let old = self.ptr; + self.ptr = unsafe { old.add(1) }; + old + }; + Some(unsafe { ptr.read() }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let exact = if T::IS_ZST { + self.end.addr().wrapping_sub(self.ptr.as_ptr().addr()) + } else { + unsafe { non_null!(self.end, T).sub_ptr(self.ptr) } + }; + (exact, Some(exact)) + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + let step_size = self.len().min(n); + let to_drop = ptr::slice_from_raw_parts_mut(self.ptr.as_ptr(), step_size); + if T::IS_ZST { + // See `next` for why we sub `end` here. + self.end = self.end.wrapping_byte_sub(step_size); + } else { + // SAFETY: the min() above ensures that step_size is in bounds + self.ptr = unsafe { self.ptr.add(step_size) }; + } + // SAFETY: the min() above ensures that step_size is in bounds + unsafe { + ptr::drop_in_place(to_drop); + } + NonZero::new(n - step_size).map_or(Ok(()), Err) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + #[inline] + fn next_chunk(&mut self) -> Result<[T; N], core::array::IntoIter> { + let mut raw_ary = [const { MaybeUninit::uninit() }; N]; + + let len = self.len(); + + if T::IS_ZST { + if len < N { + self.forget_remaining_elements(); + // Safety: ZSTs can be conjured ex nihilo, only the amount has to be correct + return Err(unsafe { array::IntoIter::new_unchecked(raw_ary, 0..len) }); + } + + self.end = self.end.wrapping_byte_sub(N); + // Safety: ditto + return Ok(unsafe { raw_ary.transpose().assume_init() }); + } + + if len < N { + // Safety: `len` indicates that this many elements are available and we just checked that + // it fits into the array. + unsafe { + ptr::copy_nonoverlapping(self.ptr.as_ptr(), raw_ary.as_mut_ptr() as *mut T, len); + self.forget_remaining_elements(); + return Err(array::IntoIter::new_unchecked(raw_ary, 0..len)); + } + } + + // Safety: `len` is larger than the array size. Copy a fixed amount here to fully initialize + // the array. + unsafe { + ptr::copy_nonoverlapping(self.ptr.as_ptr(), raw_ary.as_mut_ptr() as *mut T, N); + self.ptr = self.ptr.add(N); + Ok(raw_ary.transpose().assume_init()) + } + } + + fn fold(mut self, mut accum: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + if T::IS_ZST { + while self.ptr.as_ptr() != self.end.cast_mut() { + // SAFETY: we just checked that `self.ptr` is in bounds. + let tmp = unsafe { self.ptr.read() }; + // See `next` for why we subtract from `end` here. + self.end = self.end.wrapping_byte_sub(1); + accum = f(accum, tmp); + } + } else { + // SAFETY: `self.end` can only be null if `T` is a ZST. + while self.ptr != non_null!(self.end, T) { + // SAFETY: we just checked that `self.ptr` is in bounds. + let tmp = unsafe { self.ptr.read() }; + // SAFETY: the maximum this can be is `self.end`. + // Increment `self.ptr` first to avoid double dropping in the event of a panic. + self.ptr = unsafe { self.ptr.add(1) }; + accum = f(accum, tmp); + } + } + accum + } + + fn try_fold(&mut self, mut accum: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: core::ops::Try, + { + if T::IS_ZST { + while self.ptr.as_ptr() != self.end.cast_mut() { + // SAFETY: we just checked that `self.ptr` is in bounds. + let tmp = unsafe { self.ptr.read() }; + // See `next` for why we subtract from `end` here. + self.end = self.end.wrapping_byte_sub(1); + accum = f(accum, tmp)?; + } + } else { + // SAFETY: `self.end` can only be null if `T` is a ZST. + while self.ptr != non_null!(self.end, T) { + // SAFETY: we just checked that `self.ptr` is in bounds. + let tmp = unsafe { self.ptr.read() }; + // SAFETY: the maximum this can be is `self.end`. + // Increment `self.ptr` first to avoid double dropping in the event of a panic. + self.ptr = unsafe { self.ptr.add(1) }; + accum = f(accum, tmp)?; + } + } + R::from_output(accum) + } + + unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item + where + Self: TrustedRandomAccessNoCoerce, + { + // SAFETY: the caller must guarantee that `i` is in bounds of the + // `Vec`, so `i` cannot overflow an `isize`, and the `self.ptr.add(i)` + // is guaranteed to pointer to an element of the `Vec` and + // thus guaranteed to be valid to dereference. + // + // Also note the implementation of `Self: TrustedRandomAccess` requires + // that `T: Copy` so reading elements from the buffer doesn't invalidate + // them for `Drop`. + unsafe { self.ptr.add(i).read() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + if T::IS_ZST { + if self.ptr.as_ptr() == self.end as *mut _ { + return None; + } + // See above for why 'ptr.offset' isn't used + self.end = self.end.wrapping_byte_sub(1); + // Note that even though this is next_back() we're reading from `self.ptr`, not + // `self.end`. We track our length using the byte offset from `self.ptr` to `self.end`, + // so the end pointer may not be suitably aligned for T. + Some(unsafe { ptr::read(self.ptr.as_ptr()) }) + } else { + if self.ptr == non_null!(self.end, T) { + return None; + } + unsafe { + self.end = self.end.sub(1); + Some(ptr::read(self.end)) + } + } + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + let step_size = self.len().min(n); + if T::IS_ZST { + // SAFETY: same as for advance_by() + self.end = self.end.wrapping_byte_sub(step_size); + } else { + // SAFETY: same as for advance_by() + self.end = unsafe { self.end.sub(step_size) }; + } + let to_drop = ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size); + // SAFETY: same as for advance_by() + unsafe { + ptr::drop_in_place(to_drop); + } + NonZero::new(n - step_size).map_or(Ok(()), Err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + fn is_empty(&self) -> bool { + if T::IS_ZST { + self.ptr.as_ptr() == self.end as *mut _ + } else { + self.ptr == non_null!(self.end, T) + } + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for IntoIter {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIter {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl Default for IntoIter +where + A: Allocator + Default, +{ + /// Creates an empty `vec::IntoIter`. + /// + /// ``` + /// # use std::vec; + /// let iter: vec::IntoIter = Default::default(); + /// assert_eq!(iter.len(), 0); + /// assert_eq!(iter.as_slice(), &[]); + /// ``` + fn default() -> Self { + super::Vec::new_in(Default::default()).into_iter() + } +} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "std_internals")] +#[rustc_unsafe_specialization_marker] +pub trait NonDrop {} + +// T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr +// and thus we can't implement drop-handling +#[unstable(issue = "none", feature = "std_internals")] +impl NonDrop for T {} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "std_internals")] +// TrustedRandomAccess (without NoCoerce) must not be implemented because +// subtypes/supertypes of `T` might not be `NonDrop` +unsafe impl TrustedRandomAccessNoCoerce for IntoIter +where + T: NonDrop, +{ + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "vec_into_iter_clone", since = "1.8.0")] +impl Clone for IntoIter { + #[cfg(not(test))] + fn clone(&self) -> Self { + self.as_slice().to_vec_in(self.alloc.deref().clone()).into_iter() + } + #[cfg(test)] + fn clone(&self) -> Self { + crate::slice::to_vec(self.as_slice(), self.alloc.deref().clone()).into_iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { + fn drop(&mut self) { + struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter); + + impl Drop for DropGuard<'_, T, A> { + fn drop(&mut self) { + unsafe { + // `IntoIter::alloc` is not used anymore after this and will be dropped by RawVec + let alloc = ManuallyDrop::take(&mut self.0.alloc); + // RawVec handles deallocation + let _ = RawVec::from_nonnull_in(self.0.buf, self.0.cap, alloc); + } + } + } + + let guard = DropGuard(self); + // destroy the remaining elements + unsafe { + ptr::drop_in_place(guard.0.as_raw_mut_slice()); + } + // now `guard` will be dropped and do the rest + } +} + +// In addition to the SAFETY invariants of the following three unsafe traits +// also refer to the vec::in_place_collect module documentation to get an overview +#[unstable(issue = "none", feature = "inplace_iteration")] +#[doc(hidden)] +unsafe impl InPlaceIterable for IntoIter { + const EXPAND_BY: Option> = NonZero::new(1); + const MERGE_BY: Option> = NonZero::new(1); +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +#[doc(hidden)] +unsafe impl SourceIter for IntoIter { + type Source = Self; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut Self::Source { + self + } +} + +#[cfg(not(no_global_oom_handling))] +unsafe impl AsVecIntoIter for IntoIter { + type Item = T; + + fn as_into_iter(&mut self) -> &mut IntoIter { + self + } +} diff --git a/CoqOfRust/alloc/vec/is_zero.rs b/CoqOfRust/alloc/vec/is_zero.rs new file mode 100644 index 000000000..ba57d940d --- /dev/null +++ b/CoqOfRust/alloc/vec/is_zero.rs @@ -0,0 +1,189 @@ +use core::num::{NonZero, Saturating, Wrapping}; + +use crate::boxed::Box; + +#[rustc_specialization_trait] +pub(super) unsafe trait IsZero { + /// Whether this value's representation is all zeros, + /// or can be represented with all zeroes. + fn is_zero(&self) -> bool; +} + +macro_rules! impl_is_zero { + ($t:ty, $is_zero:expr) => { + unsafe impl IsZero for $t { + #[inline] + fn is_zero(&self) -> bool { + $is_zero(*self) + } + } + }; +} + +impl_is_zero!(i8, |x| x == 0); // It is needed to impl for arrays and tuples of i8. +impl_is_zero!(i16, |x| x == 0); +impl_is_zero!(i32, |x| x == 0); +impl_is_zero!(i64, |x| x == 0); +impl_is_zero!(i128, |x| x == 0); +impl_is_zero!(isize, |x| x == 0); + +impl_is_zero!(u8, |x| x == 0); // It is needed to impl for arrays and tuples of u8. +impl_is_zero!(u16, |x| x == 0); +impl_is_zero!(u32, |x| x == 0); +impl_is_zero!(u64, |x| x == 0); +impl_is_zero!(u128, |x| x == 0); +impl_is_zero!(usize, |x| x == 0); + +impl_is_zero!(bool, |x| x == false); +impl_is_zero!(char, |x| x == '\0'); + +impl_is_zero!(f32, |x: f32| x.to_bits() == 0); +impl_is_zero!(f64, |x: f64| x.to_bits() == 0); + +unsafe impl IsZero for *const T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} + +unsafe impl IsZero for *mut T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} + +unsafe impl IsZero for [T; N] { + #[inline] + fn is_zero(&self) -> bool { + // Because this is generated as a runtime check, it's not obvious that + // it's worth doing if the array is really long. The threshold here + // is largely arbitrary, but was picked because as of 2022-07-01 LLVM + // fails to const-fold the check in `vec![[1; 32]; n]` + // See https://github.com/rust-lang/rust/pull/97581#issuecomment-1166628022 + // Feel free to tweak if you have better evidence. + + N <= 16 && self.iter().all(IsZero::is_zero) + } +} + +// This is recursive macro. +macro_rules! impl_is_zero_tuples { + // Stopper + () => { + // No use for implementing for empty tuple because it is ZST. + }; + ($first_arg:ident $(,$rest:ident)*) => { + unsafe impl <$first_arg: IsZero, $($rest: IsZero,)*> IsZero for ($first_arg, $($rest,)*){ + #[inline] + fn is_zero(&self) -> bool{ + // Destructure tuple to N references + // Rust allows to hide generic params by local variable names. + #[allow(non_snake_case)] + let ($first_arg, $($rest,)*) = self; + + $first_arg.is_zero() + $( && $rest.is_zero() )* + } + } + + impl_is_zero_tuples!($($rest),*); + } +} + +impl_is_zero_tuples!(A, B, C, D, E, F, G, H); + +// `Option<&T>` and `Option>` are guaranteed to represent `None` as null. +// For fat pointers, the bytes that would be the pointer metadata in the `Some` +// variant are padding in the `None` variant, so ignoring them and +// zero-initializing instead is ok. +// `Option<&mut T>` never implements `Clone`, so there's no need for an impl of +// `SpecFromElem`. + +unsafe impl IsZero for Option<&T> { + #[inline] + fn is_zero(&self) -> bool { + self.is_none() + } +} + +unsafe impl IsZero for Option> { + #[inline] + fn is_zero(&self) -> bool { + self.is_none() + } +} + +// `Option>` and similar have a representation guarantee that +// they're the same size as the corresponding `u32` type, as well as a guarantee +// that transmuting between `NonZero` and `Option>` works. +// While the documentation officially makes it UB to transmute from `None`, +// we're the standard library so we can make extra inferences, and we know that +// the only niche available to represent `None` is the one that's all zeros. +macro_rules! impl_is_zero_option_of_nonzero_int { + ($($t:ty),+ $(,)?) => {$( + unsafe impl IsZero for Option> { + #[inline] + fn is_zero(&self) -> bool { + self.is_none() + } + } + )+}; +} + +impl_is_zero_option_of_nonzero_int!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); + +macro_rules! impl_is_zero_option_of_int { + ($($t:ty),+ $(,)?) => {$( + unsafe impl IsZero for Option<$t> { + #[inline] + fn is_zero(&self) -> bool { + const { + let none: Self = unsafe { core::mem::MaybeUninit::zeroed().assume_init() }; + assert!(none.is_none()); + } + self.is_none() + } + } + )+}; +} + +impl_is_zero_option_of_int!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize); + +unsafe impl IsZero for Wrapping { + #[inline] + fn is_zero(&self) -> bool { + self.0.is_zero() + } +} + +unsafe impl IsZero for Saturating { + #[inline] + fn is_zero(&self) -> bool { + self.0.is_zero() + } +} + +macro_rules! impl_is_zero_option_of_bool { + ($($t:ty),+ $(,)?) => {$( + unsafe impl IsZero for $t { + #[inline] + fn is_zero(&self) -> bool { + // SAFETY: This is *not* a stable layout guarantee, but + // inside `core` we're allowed to rely on the current rustc + // behavior that options of bools will be one byte with + // no padding, so long as they're nested less than 254 deep. + let raw: u8 = unsafe { core::mem::transmute(*self) }; + raw == 0 + } + } + )+}; +} + +impl_is_zero_option_of_bool! { + Option, + Option>, + Option>>, + // Could go further, but not worth the metadata overhead. +} diff --git a/CoqOfRust/alloc/vec/mod.rs b/CoqOfRust/alloc/vec/mod.rs new file mode 100644 index 000000000..457be3ae7 --- /dev/null +++ b/CoqOfRust/alloc/vec/mod.rs @@ -0,0 +1,4037 @@ +//! A contiguous growable array type with heap-allocated contents, written +//! `Vec`. +//! +//! Vectors have *O*(1) indexing, amortized *O*(1) push (to the end) and +//! *O*(1) pop (from the end). +//! +//! Vectors ensure they never allocate more than `isize::MAX` bytes. +//! +//! # Examples +//! +//! You can explicitly create a [`Vec`] with [`Vec::new`]: +//! +//! ``` +//! let v: Vec = Vec::new(); +//! ``` +//! +//! ...or by using the [`vec!`] macro: +//! +//! ``` +//! let v: Vec = vec![]; +//! +//! let v = vec![1, 2, 3, 4, 5]; +//! +//! let v = vec![0; 10]; // ten zeroes +//! ``` +//! +//! You can [`push`] values onto the end of a vector (which will grow the vector +//! as needed): +//! +//! ``` +//! let mut v = vec![1, 2]; +//! +//! v.push(3); +//! ``` +//! +//! Popping values works in much the same way: +//! +//! ``` +//! let mut v = vec![1, 2]; +//! +//! let two = v.pop(); +//! ``` +//! +//! Vectors also support indexing (through the [`Index`] and [`IndexMut`] traits): +//! +//! ``` +//! let mut v = vec![1, 2, 3]; +//! let three = v[2]; +//! v[1] = v[1] + 5; +//! ``` +//! +//! [`push`]: Vec::push + +#![stable(feature = "rust1", since = "1.0.0")] + +#[cfg(not(no_global_oom_handling))] +use core::cmp; +use core::cmp::Ordering; +use core::fmt; +use core::hash::{Hash, Hasher}; +#[cfg(not(no_global_oom_handling))] +use core::iter; +use core::marker::PhantomData; +use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; +use core::ops::{self, Index, IndexMut, Range, RangeBounds}; +use core::ptr::{self, NonNull}; +use core::slice::{self, SliceIndex}; + +#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] +pub use self::extract_if::ExtractIf; +use crate::alloc::{Allocator, Global}; +use crate::borrow::{Cow, ToOwned}; +use crate::boxed::Box; +use crate::collections::TryReserveError; +use crate::raw_vec::RawVec; + +mod extract_if; + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "vec_splice", since = "1.21.0")] +pub use self::splice::Splice; + +#[cfg(not(no_global_oom_handling))] +mod splice; + +#[stable(feature = "drain", since = "1.6.0")] +pub use self::drain::Drain; + +mod drain; + +#[cfg(not(no_global_oom_handling))] +mod cow; + +#[cfg(not(no_global_oom_handling))] +pub(crate) use self::in_place_collect::AsVecIntoIter; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::into_iter::IntoIter; + +mod into_iter; + +#[cfg(not(no_global_oom_handling))] +use self::is_zero::IsZero; + +#[cfg(not(no_global_oom_handling))] +mod is_zero; + +#[cfg(not(no_global_oom_handling))] +mod in_place_collect; + +mod partial_eq; + +#[cfg(not(no_global_oom_handling))] +use self::spec_from_elem::SpecFromElem; + +#[cfg(not(no_global_oom_handling))] +mod spec_from_elem; + +#[cfg(not(no_global_oom_handling))] +use self::set_len_on_drop::SetLenOnDrop; + +#[cfg(not(no_global_oom_handling))] +mod set_len_on_drop; + +#[cfg(not(no_global_oom_handling))] +use self::in_place_drop::{InPlaceDrop, InPlaceDstDataSrcBufDrop}; + +#[cfg(not(no_global_oom_handling))] +mod in_place_drop; + +#[cfg(not(no_global_oom_handling))] +use self::spec_from_iter_nested::SpecFromIterNested; + +#[cfg(not(no_global_oom_handling))] +mod spec_from_iter_nested; + +#[cfg(not(no_global_oom_handling))] +use self::spec_from_iter::SpecFromIter; + +#[cfg(not(no_global_oom_handling))] +mod spec_from_iter; + +#[cfg(not(no_global_oom_handling))] +use self::spec_extend::SpecExtend; + +#[cfg(not(no_global_oom_handling))] +mod spec_extend; + +/// A contiguous growable array type, written as `Vec`, short for 'vector'. +/// +/// # Examples +/// +/// ``` +/// let mut vec = Vec::new(); +/// vec.push(1); +/// vec.push(2); +/// +/// assert_eq!(vec.len(), 2); +/// assert_eq!(vec[0], 1); +/// +/// assert_eq!(vec.pop(), Some(2)); +/// assert_eq!(vec.len(), 1); +/// +/// vec[0] = 7; +/// assert_eq!(vec[0], 7); +/// +/// vec.extend([1, 2, 3]); +/// +/// for x in &vec { +/// println!("{x}"); +/// } +/// assert_eq!(vec, [7, 1, 2, 3]); +/// ``` +/// +/// The [`vec!`] macro is provided for convenient initialization: +/// +/// ``` +/// let mut vec1 = vec![1, 2, 3]; +/// vec1.push(4); +/// let vec2 = Vec::from([1, 2, 3, 4]); +/// assert_eq!(vec1, vec2); +/// ``` +/// +/// It can also initialize each element of a `Vec` with a given value. +/// This may be more efficient than performing allocation and initialization +/// in separate steps, especially when initializing a vector of zeros: +/// +/// ``` +/// let vec = vec![0; 5]; +/// assert_eq!(vec, [0, 0, 0, 0, 0]); +/// +/// // The following is equivalent, but potentially slower: +/// let mut vec = Vec::with_capacity(5); +/// vec.resize(5, 0); +/// assert_eq!(vec, [0, 0, 0, 0, 0]); +/// ``` +/// +/// For more information, see +/// [Capacity and Reallocation](#capacity-and-reallocation). +/// +/// Use a `Vec` as an efficient stack: +/// +/// ``` +/// let mut stack = Vec::new(); +/// +/// stack.push(1); +/// stack.push(2); +/// stack.push(3); +/// +/// while let Some(top) = stack.pop() { +/// // Prints 3, 2, 1 +/// println!("{top}"); +/// } +/// ``` +/// +/// # Indexing +/// +/// The `Vec` type allows access to values by index, because it implements the +/// [`Index`] trait. An example will be more explicit: +/// +/// ``` +/// let v = vec![0, 2, 4, 6]; +/// println!("{}", v[1]); // it will display '2' +/// ``` +/// +/// However be careful: if you try to access an index which isn't in the `Vec`, +/// your software will panic! You cannot do this: +/// +/// ```should_panic +/// let v = vec![0, 2, 4, 6]; +/// println!("{}", v[6]); // it will panic! +/// ``` +/// +/// Use [`get`] and [`get_mut`] if you want to check whether the index is in +/// the `Vec`. +/// +/// # Slicing +/// +/// A `Vec` can be mutable. On the other hand, slices are read-only objects. +/// To get a [slice][prim@slice], use [`&`]. Example: +/// +/// ``` +/// fn read_slice(slice: &[usize]) { +/// // ... +/// } +/// +/// let v = vec![0, 1]; +/// read_slice(&v); +/// +/// // ... and that's all! +/// // you can also do it like this: +/// let u: &[usize] = &v; +/// // or like this: +/// let u: &[_] = &v; +/// ``` +/// +/// In Rust, it's more common to pass slices as arguments rather than vectors +/// when you just want to provide read access. The same goes for [`String`] and +/// [`&str`]. +/// +/// # Capacity and reallocation +/// +/// The capacity of a vector is the amount of space allocated for any future +/// elements that will be added onto the vector. This is not to be confused with +/// the *length* of a vector, which specifies the number of actual elements +/// within the vector. If a vector's length exceeds its capacity, its capacity +/// will automatically be increased, but its elements will have to be +/// reallocated. +/// +/// For example, a vector with capacity 10 and length 0 would be an empty vector +/// with space for 10 more elements. Pushing 10 or fewer elements onto the +/// vector will not change its capacity or cause reallocation to occur. However, +/// if the vector's length is increased to 11, it will have to reallocate, which +/// can be slow. For this reason, it is recommended to use [`Vec::with_capacity`] +/// whenever possible to specify how big the vector is expected to get. +/// +/// # Guarantees +/// +/// Due to its incredibly fundamental nature, `Vec` makes a lot of guarantees +/// about its design. This ensures that it's as low-overhead as possible in +/// the general case, and can be correctly manipulated in primitive ways +/// by unsafe code. Note that these guarantees refer to an unqualified `Vec`. +/// If additional type parameters are added (e.g., to support custom allocators), +/// overriding their defaults may change the behavior. +/// +/// Most fundamentally, `Vec` is and always will be a (pointer, capacity, length) +/// triplet. No more, no less. The order of these fields is completely +/// unspecified, and you should use the appropriate methods to modify these. +/// The pointer will never be null, so this type is null-pointer-optimized. +/// +/// However, the pointer might not actually point to allocated memory. In particular, +/// if you construct a `Vec` with capacity 0 via [`Vec::new`], [`vec![]`][`vec!`], +/// [`Vec::with_capacity(0)`][`Vec::with_capacity`], or by calling [`shrink_to_fit`] +/// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized +/// types inside a `Vec`, it will not allocate space for them. *Note that in this case +/// the `Vec` might not report a [`capacity`] of 0*. `Vec` will allocate if and only +/// if [mem::size_of::\]\() * [capacity]\() > 0. In general, `Vec`'s allocation +/// details are very subtle --- if you intend to allocate memory using a `Vec` +/// and use it for something else (either to pass to unsafe code, or to build your +/// own memory-backed collection), be sure to deallocate this memory by using +/// `from_raw_parts` to recover the `Vec` and then dropping it. +/// +/// If a `Vec` *has* allocated memory, then the memory it points to is on the heap +/// (as defined by the allocator Rust is configured to use by default), and its +/// pointer points to [`len`] initialized, contiguous elements in order (what +/// you would see if you coerced it to a slice), followed by [capacity] - [len] +/// logically uninitialized, contiguous elements. +/// +/// A vector containing the elements `'a'` and `'b'` with capacity 4 can be +/// visualized as below. The top part is the `Vec` struct, it contains a +/// pointer to the head of the allocation in the heap, length and capacity. +/// The bottom part is the allocation on the heap, a contiguous memory block. +/// +/// ```text +/// ptr len capacity +/// +--------+--------+--------+ +/// | 0x0123 | 2 | 4 | +/// +--------+--------+--------+ +/// | +/// v +/// Heap +--------+--------+--------+--------+ +/// | 'a' | 'b' | uninit | uninit | +/// +--------+--------+--------+--------+ +/// ``` +/// +/// - **uninit** represents memory that is not initialized, see [`MaybeUninit`]. +/// - Note: the ABI is not stable and `Vec` makes no guarantees about its memory +/// layout (including the order of fields). +/// +/// `Vec` will never perform a "small optimization" where elements are actually +/// stored on the stack for two reasons: +/// +/// * It would make it more difficult for unsafe code to correctly manipulate +/// a `Vec`. The contents of a `Vec` wouldn't have a stable address if it were +/// only moved, and it would be more difficult to determine if a `Vec` had +/// actually allocated memory. +/// +/// * It would penalize the general case, incurring an additional branch +/// on every access. +/// +/// `Vec` will never automatically shrink itself, even if completely empty. This +/// ensures no unnecessary allocations or deallocations occur. Emptying a `Vec` +/// and then filling it back up to the same [`len`] should incur no calls to +/// the allocator. If you wish to free up unused memory, use +/// [`shrink_to_fit`] or [`shrink_to`]. +/// +/// [`push`] and [`insert`] will never (re)allocate if the reported capacity is +/// sufficient. [`push`] and [`insert`] *will* (re)allocate if +/// [len] == [capacity]. That is, the reported capacity is completely +/// accurate, and can be relied on. It can even be used to manually free the memory +/// allocated by a `Vec` if desired. Bulk insertion methods *may* reallocate, even +/// when not necessary. +/// +/// `Vec` does not guarantee any particular growth strategy when reallocating +/// when full, nor when [`reserve`] is called. The current strategy is basic +/// and it may prove desirable to use a non-constant growth factor. Whatever +/// strategy is used will of course guarantee *O*(1) amortized [`push`]. +/// +/// `vec![x; n]`, `vec![a, b, c, d]`, and +/// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec` +/// with at least the requested capacity. If [len] == [capacity], +/// (as is the case for the [`vec!`] macro), then a `Vec` can be converted to +/// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements. +/// +/// `Vec` will not specifically overwrite any data that is removed from it, +/// but also won't specifically preserve it. Its uninitialized memory is +/// scratch space that it may use however it wants. It will generally just do +/// whatever is most efficient or otherwise easy to implement. Do not rely on +/// removed data to be erased for security purposes. Even if you drop a `Vec`, its +/// buffer may simply be reused by another allocation. Even if you zero a `Vec`'s memory +/// first, that might not actually happen because the optimizer does not consider +/// this a side-effect that must be preserved. There is one case which we will +/// not break, however: using `unsafe` code to write to the excess capacity, +/// and then increasing the length to match, is always valid. +/// +/// Currently, `Vec` does not guarantee the order in which elements are dropped. +/// The order has changed in the past and may change again. +/// +/// [`get`]: slice::get +/// [`get_mut`]: slice::get_mut +/// [`String`]: crate::string::String +/// [`&str`]: type@str +/// [`shrink_to_fit`]: Vec::shrink_to_fit +/// [`shrink_to`]: Vec::shrink_to +/// [capacity]: Vec::capacity +/// [`capacity`]: Vec::capacity +/// [mem::size_of::\]: core::mem::size_of +/// [len]: Vec::len +/// [`len`]: Vec::len +/// [`push`]: Vec::push +/// [`insert`]: Vec::insert +/// [`reserve`]: Vec::reserve +/// [`MaybeUninit`]: core::mem::MaybeUninit +/// [owned slice]: Box +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Vec")] +#[rustc_insignificant_dtor] +pub struct Vec { + buf: RawVec, + len: usize, +} + +//////////////////////////////////////////////////////////////////////////////// +// Inherent methods +//////////////////////////////////////////////////////////////////////////////// + +impl Vec { + /// Constructs a new, empty `Vec`. + /// + /// The vector will not allocate until elements are pushed onto it. + /// + /// # Examples + /// + /// ``` + /// # #![allow(unused_mut)] + /// let mut vec: Vec = Vec::new(); + /// ``` + #[inline] + #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "vec_new")] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + pub const fn new() -> Self { + Vec { buf: RawVec::new(), len: 0 } + } + + /// Constructs a new, empty `Vec` with at least the specified capacity. + /// + /// The vector will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is zero, the vector will not allocate. + /// + /// It is important to note that although the returned vector has the + /// minimum *capacity* specified, the vector will have a zero *length*. For + /// an explanation of the difference between length and capacity, see + /// *[Capacity and reallocation]*. + /// + /// If it is important to know the exact allocated capacity of a `Vec`, + /// always use the [`capacity`] method after construction. + /// + /// For `Vec` where `T` is a zero-sized type, there will be no allocation + /// and the capacity will always be `usize::MAX`. + /// + /// [Capacity and reallocation]: #capacity-and-reallocation + /// [`capacity`]: Vec::capacity + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. + /// + /// # Examples + /// + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// + /// // The vector contains no items, even though it has capacity for more + /// assert_eq!(vec.len(), 0); + /// assert!(vec.capacity() >= 10); + /// + /// // These are all done without reallocating... + /// for i in 0..10 { + /// vec.push(i); + /// } + /// assert_eq!(vec.len(), 10); + /// assert!(vec.capacity() >= 10); + /// + /// // ...but this may make the vector reallocate + /// vec.push(11); + /// assert_eq!(vec.len(), 11); + /// assert!(vec.capacity() >= 11); + /// + /// // A vector of a zero-sized type will always over-allocate, since no + /// // allocation is necessary + /// let vec_units = Vec::<()>::with_capacity(10); + /// assert_eq!(vec_units.capacity(), usize::MAX); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + #[cfg_attr(not(test), rustc_diagnostic_item = "vec_with_capacity")] + #[track_caller] + pub fn with_capacity(capacity: usize) -> Self { + Self::with_capacity_in(capacity, Global) + } + + /// Constructs a new, empty `Vec` with at least the specified capacity. + /// + /// The vector will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is zero, the vector will not allocate. + /// + /// # Errors + /// + /// Returns an error if the capacity exceeds `isize::MAX` _bytes_, + /// or if the allocator reports allocation failure. + #[inline] + #[unstable(feature = "try_with_capacity", issue = "91913")] + pub fn try_with_capacity(capacity: usize) -> Result { + Self::try_with_capacity_in(capacity, Global) + } + + /// Creates a `Vec` directly from a pointer, a length, and a capacity. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * `ptr` must have been allocated using the global allocator, such as via + /// the [`alloc::alloc`] function. + /// * `T` needs to have the same alignment as what `ptr` was allocated with. + /// (`T` having a less strict alignment is not sufficient, the alignment really + /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be + /// allocated and deallocated with the same layout.) + /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs + /// to be the same size as the pointer was allocated with. (Because similar to + /// alignment, [`dealloc`] must be called with the same layout `size`.) + /// * `length` needs to be less than or equal to `capacity`. + /// * The first `length` values must be properly initialized values of type `T`. + /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// * The allocated size in bytes must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// These requirements are always upheld by any `ptr` that has been allocated + /// via `Vec`. Other allocation sources are allowed if the invariants are + /// upheld. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example it is normally **not** safe + /// to build a `Vec` from a pointer to a C `char` array with length + /// `size_t`, doing so is only safe if the array was initially allocated by + /// a `Vec` or `String`. + /// It's also not safe to build one from a `Vec` and its length, because + /// the allocator cares about the alignment, and these two types have different + /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after + /// turning it into a `Vec` it'll be deallocated with alignment 1. To avoid + /// these issues, it is often preferable to do casting/transmuting using + /// [`slice::from_raw_parts`] instead. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `Vec` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// [`String`]: crate::string::String + /// [`alloc::alloc`]: crate::alloc::alloc + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// + /// # Examples + /// + /// ``` + /// use std::ptr; + /// use std::mem; + /// + /// let v = vec![1, 2, 3]; + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent running `v`'s destructor so we are in complete control + /// // of the allocation. + /// let mut v = mem::ManuallyDrop::new(v); + /// + /// // Pull out the various important pieces of information about `v` + /// let p = v.as_mut_ptr(); + /// let len = v.len(); + /// let cap = v.capacity(); + /// + /// unsafe { + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len { + /// ptr::write(p.add(i), 4 + i); + /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_raw_parts(p, len, cap); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } + /// ``` + /// + /// Using memory that was allocated elsewhere: + /// + /// ```rust + /// use std::alloc::{alloc, Layout}; + /// + /// fn main() { + /// let layout = Layout::array::(16).expect("overflow cannot happen"); + /// + /// let vec = unsafe { + /// let mem = alloc(layout).cast::(); + /// if mem.is_null() { + /// return; + /// } + /// + /// mem.write(1_000_000); + /// + /// Vec::from_raw_parts(mem, 1, 16) + /// }; + /// + /// assert_eq!(vec, &[1_000_000]); + /// assert_eq!(vec.capacity(), 16); + /// } + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self { + unsafe { Self::from_raw_parts_in(ptr, length, capacity, Global) } + } + + #[doc(alias = "from_non_null_parts")] + /// Creates a `Vec` directly from a `NonNull` pointer, a length, and a capacity. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * `ptr` must have been allocated using the global allocator, such as via + /// the [`alloc::alloc`] function. + /// * `T` needs to have the same alignment as what `ptr` was allocated with. + /// (`T` having a less strict alignment is not sufficient, the alignment really + /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be + /// allocated and deallocated with the same layout.) + /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs + /// to be the same size as the pointer was allocated with. (Because similar to + /// alignment, [`dealloc`] must be called with the same layout `size`.) + /// * `length` needs to be less than or equal to `capacity`. + /// * The first `length` values must be properly initialized values of type `T`. + /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// * The allocated size in bytes must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// These requirements are always upheld by any `ptr` that has been allocated + /// via `Vec`. Other allocation sources are allowed if the invariants are + /// upheld. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example it is normally **not** safe + /// to build a `Vec` from a pointer to a C `char` array with length + /// `size_t`, doing so is only safe if the array was initially allocated by + /// a `Vec` or `String`. + /// It's also not safe to build one from a `Vec` and its length, because + /// the allocator cares about the alignment, and these two types have different + /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after + /// turning it into a `Vec` it'll be deallocated with alignment 1. To avoid + /// these issues, it is often preferable to do casting/transmuting using + /// [`NonNull::slice_from_raw_parts`] instead. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `Vec` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// [`String`]: crate::string::String + /// [`alloc::alloc`]: crate::alloc::alloc + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// + /// # Examples + /// + /// ``` + /// #![feature(box_vec_non_null)] + /// + /// use std::ptr::NonNull; + /// use std::mem; + /// + /// let v = vec![1, 2, 3]; + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent running `v`'s destructor so we are in complete control + /// // of the allocation. + /// let mut v = mem::ManuallyDrop::new(v); + /// + /// // Pull out the various important pieces of information about `v` + /// let p = unsafe { NonNull::new_unchecked(v.as_mut_ptr()) }; + /// let len = v.len(); + /// let cap = v.capacity(); + /// + /// unsafe { + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len { + /// p.add(i).write(4 + i); + /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_parts(p, len, cap); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } + /// ``` + /// + /// Using memory that was allocated elsewhere: + /// + /// ```rust + /// #![feature(box_vec_non_null)] + /// + /// use std::alloc::{alloc, Layout}; + /// use std::ptr::NonNull; + /// + /// fn main() { + /// let layout = Layout::array::(16).expect("overflow cannot happen"); + /// + /// let vec = unsafe { + /// let Some(mem) = NonNull::new(alloc(layout).cast::()) else { + /// return; + /// }; + /// + /// mem.write(1_000_000); + /// + /// Vec::from_parts(mem, 1, 16) + /// }; + /// + /// assert_eq!(vec, &[1_000_000]); + /// assert_eq!(vec.capacity(), 16); + /// } + /// ``` + #[inline] + #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + pub unsafe fn from_parts(ptr: NonNull, length: usize, capacity: usize) -> Self { + unsafe { Self::from_parts_in(ptr, length, capacity, Global) } + } +} + +impl Vec { + /// Constructs a new, empty `Vec`. + /// + /// The vector will not allocate until elements are pushed onto it. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// # #[allow(unused_mut)] + /// let mut vec: Vec = Vec::new_in(System); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub const fn new_in(alloc: A) -> Self { + Vec { buf: RawVec::new_in(alloc), len: 0 } + } + + /// Constructs a new, empty `Vec` with at least the specified capacity + /// with the provided allocator. + /// + /// The vector will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is zero, the vector will not allocate. + /// + /// It is important to note that although the returned vector has the + /// minimum *capacity* specified, the vector will have a zero *length*. For + /// an explanation of the difference between length and capacity, see + /// *[Capacity and reallocation]*. + /// + /// If it is important to know the exact allocated capacity of a `Vec`, + /// always use the [`capacity`] method after construction. + /// + /// For `Vec` where `T` is a zero-sized type, there will be no allocation + /// and the capacity will always be `usize::MAX`. + /// + /// [Capacity and reallocation]: #capacity-and-reallocation + /// [`capacity`]: Vec::capacity + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let mut vec = Vec::with_capacity_in(10, System); + /// + /// // The vector contains no items, even though it has capacity for more + /// assert_eq!(vec.len(), 0); + /// assert!(vec.capacity() >= 10); + /// + /// // These are all done without reallocating... + /// for i in 0..10 { + /// vec.push(i); + /// } + /// assert_eq!(vec.len(), 10); + /// assert!(vec.capacity() >= 10); + /// + /// // ...but this may make the vector reallocate + /// vec.push(11); + /// assert_eq!(vec.len(), 11); + /// assert!(vec.capacity() >= 11); + /// + /// // A vector of a zero-sized type will always over-allocate, since no + /// // allocation is necessary + /// let vec_units = Vec::<(), System>::with_capacity_in(10, System); + /// assert_eq!(vec_units.capacity(), usize::MAX); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + #[track_caller] + pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { + Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 } + } + + /// Constructs a new, empty `Vec` with at least the specified capacity + /// with the provided allocator. + /// + /// The vector will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is zero, the vector will not allocate. + /// + /// # Errors + /// + /// Returns an error if the capacity exceeds `isize::MAX` _bytes_, + /// or if the allocator reports allocation failure. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "try_with_capacity", issue = "91913")] + pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result { + Ok(Vec { buf: RawVec::try_with_capacity_in(capacity, alloc)?, len: 0 }) + } + + /// Creates a `Vec` directly from a pointer, a length, a capacity, + /// and an allocator. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * `ptr` must be [*currently allocated*] via the given allocator `alloc`. + /// * `T` needs to have the same alignment as what `ptr` was allocated with. + /// (`T` having a less strict alignment is not sufficient, the alignment really + /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be + /// allocated and deallocated with the same layout.) + /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs + /// to be the same size as the pointer was allocated with. (Because similar to + /// alignment, [`dealloc`] must be called with the same layout `size`.) + /// * `length` needs to be less than or equal to `capacity`. + /// * The first `length` values must be properly initialized values of type `T`. + /// * `capacity` needs to [*fit*] the layout size that the pointer was allocated with. + /// * The allocated size in bytes must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// These requirements are always upheld by any `ptr` that has been allocated + /// via `Vec`. Other allocation sources are allowed if the invariants are + /// upheld. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example it is **not** safe + /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. + /// It's also not safe to build one from a `Vec` and its length, because + /// the allocator cares about the alignment, and these two types have different + /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after + /// turning it into a `Vec` it'll be deallocated with alignment 1. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `Vec` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// [`String`]: crate::string::String + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// [*currently allocated*]: crate::alloc::Allocator#currently-allocated-memory + /// [*fit*]: crate::alloc::Allocator#memory-fitting + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// use std::ptr; + /// use std::mem; + /// + /// let mut v = Vec::with_capacity_in(3, System); + /// v.push(1); + /// v.push(2); + /// v.push(3); + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent running `v`'s destructor so we are in complete control + /// // of the allocation. + /// let mut v = mem::ManuallyDrop::new(v); + /// + /// // Pull out the various important pieces of information about `v` + /// let p = v.as_mut_ptr(); + /// let len = v.len(); + /// let cap = v.capacity(); + /// let alloc = v.allocator(); + /// + /// unsafe { + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len { + /// ptr::write(p.add(i), 4 + i); + /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_raw_parts_in(p, len, cap, alloc.clone()); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } + /// ``` + /// + /// Using memory that was allocated elsewhere: + /// + /// ```rust + /// #![feature(allocator_api)] + /// + /// use std::alloc::{AllocError, Allocator, Global, Layout}; + /// + /// fn main() { + /// let layout = Layout::array::(16).expect("overflow cannot happen"); + /// + /// let vec = unsafe { + /// let mem = match Global.allocate(layout) { + /// Ok(mem) => mem.cast::().as_ptr(), + /// Err(AllocError) => return, + /// }; + /// + /// mem.write(1_000_000); + /// + /// Vec::from_raw_parts_in(mem, 1, 16, Global) + /// }; + /// + /// assert_eq!(vec, &[1_000_000]); + /// assert_eq!(vec.capacity(), 16); + /// } + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self { + unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } } + } + + #[doc(alias = "from_non_null_parts_in")] + /// Creates a `Vec` directly from a `NonNull` pointer, a length, a capacity, + /// and an allocator. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * `ptr` must be [*currently allocated*] via the given allocator `alloc`. + /// * `T` needs to have the same alignment as what `ptr` was allocated with. + /// (`T` having a less strict alignment is not sufficient, the alignment really + /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be + /// allocated and deallocated with the same layout.) + /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs + /// to be the same size as the pointer was allocated with. (Because similar to + /// alignment, [`dealloc`] must be called with the same layout `size`.) + /// * `length` needs to be less than or equal to `capacity`. + /// * The first `length` values must be properly initialized values of type `T`. + /// * `capacity` needs to [*fit*] the layout size that the pointer was allocated with. + /// * The allocated size in bytes must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// These requirements are always upheld by any `ptr` that has been allocated + /// via `Vec`. Other allocation sources are allowed if the invariants are + /// upheld. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example it is **not** safe + /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. + /// It's also not safe to build one from a `Vec` and its length, because + /// the allocator cares about the alignment, and these two types have different + /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after + /// turning it into a `Vec` it'll be deallocated with alignment 1. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `Vec` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// [`String`]: crate::string::String + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// [*currently allocated*]: crate::alloc::Allocator#currently-allocated-memory + /// [*fit*]: crate::alloc::Allocator#memory-fitting + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, box_vec_non_null)] + /// + /// use std::alloc::System; + /// + /// use std::ptr::NonNull; + /// use std::mem; + /// + /// let mut v = Vec::with_capacity_in(3, System); + /// v.push(1); + /// v.push(2); + /// v.push(3); + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent running `v`'s destructor so we are in complete control + /// // of the allocation. + /// let mut v = mem::ManuallyDrop::new(v); + /// + /// // Pull out the various important pieces of information about `v` + /// let p = unsafe { NonNull::new_unchecked(v.as_mut_ptr()) }; + /// let len = v.len(); + /// let cap = v.capacity(); + /// let alloc = v.allocator(); + /// + /// unsafe { + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len { + /// p.add(i).write(4 + i); + /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_parts_in(p, len, cap, alloc.clone()); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } + /// ``` + /// + /// Using memory that was allocated elsewhere: + /// + /// ```rust + /// #![feature(allocator_api, box_vec_non_null)] + /// + /// use std::alloc::{AllocError, Allocator, Global, Layout}; + /// + /// fn main() { + /// let layout = Layout::array::(16).expect("overflow cannot happen"); + /// + /// let vec = unsafe { + /// let mem = match Global.allocate(layout) { + /// Ok(mem) => mem.cast::(), + /// Err(AllocError) => return, + /// }; + /// + /// mem.write(1_000_000); + /// + /// Vec::from_parts_in(mem, 1, 16, Global) + /// }; + /// + /// assert_eq!(vec, &[1_000_000]); + /// assert_eq!(vec.capacity(), 16); + /// } + /// ``` + #[inline] + #[unstable(feature = "allocator_api", reason = "new API", issue = "32838")] + // #[unstable(feature = "box_vec_non_null", issue = "130364")] + pub unsafe fn from_parts_in(ptr: NonNull, length: usize, capacity: usize, alloc: A) -> Self { + unsafe { Vec { buf: RawVec::from_nonnull_in(ptr, capacity, alloc), len: length } } + } + + /// Decomposes a `Vec` into its raw components: `(pointer, length, capacity)`. + /// + /// Returns the raw pointer to the underlying data, the length of + /// the vector (in elements), and the allocated capacity of the + /// data (in elements). These are the same arguments in the same + /// order as the arguments to [`from_raw_parts`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `Vec` with the [`from_raw_parts`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts`]: Vec::from_raw_parts + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts)] + /// let v: Vec = vec![-1, 0, 1]; + /// + /// let (ptr, len, cap) = v.into_raw_parts(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr as *mut u32; + /// + /// Vec::from_raw_parts(ptr, len, cap) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts(self) -> (*mut T, usize, usize) { + let mut me = ManuallyDrop::new(self); + (me.as_mut_ptr(), me.len(), me.capacity()) + } + + #[doc(alias = "into_non_null_parts")] + /// Decomposes a `Vec` into its raw components: `(NonNull pointer, length, capacity)`. + /// + /// Returns the `NonNull` pointer to the underlying data, the length of + /// the vector (in elements), and the allocated capacity of the + /// data (in elements). These are the same arguments in the same + /// order as the arguments to [`from_parts`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the `NonNull` pointer, length, and capacity back + /// into a `Vec` with the [`from_parts`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_parts`]: Vec::from_parts + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts, box_vec_non_null)] + /// + /// let v: Vec = vec![-1, 0, 1]; + /// + /// let (ptr, len, cap) = v.into_parts(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr.cast::(); + /// + /// Vec::from_parts(ptr, len, cap) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_parts(self) -> (NonNull, usize, usize) { + let (ptr, len, capacity) = self.into_raw_parts(); + // SAFETY: A `Vec` always has a non-null pointer. + (unsafe { NonNull::new_unchecked(ptr) }, len, capacity) + } + + /// Decomposes a `Vec` into its raw components: `(pointer, length, capacity, allocator)`. + /// + /// Returns the raw pointer to the underlying data, the length of the vector (in elements), + /// the allocated capacity of the data (in elements), and the allocator. These are the same + /// arguments in the same order as the arguments to [`from_raw_parts_in`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `Vec` with the [`from_raw_parts_in`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts_in`]: Vec::from_raw_parts_in + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, vec_into_raw_parts)] + /// + /// use std::alloc::System; + /// + /// let mut v: Vec = Vec::new_in(System); + /// v.push(-1); + /// v.push(0); + /// v.push(1); + /// + /// let (ptr, len, cap, alloc) = v.into_raw_parts_with_alloc(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr as *mut u32; + /// + /// Vec::from_raw_parts_in(ptr, len, cap, alloc) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) { + let mut me = ManuallyDrop::new(self); + let len = me.len(); + let capacity = me.capacity(); + let ptr = me.as_mut_ptr(); + let alloc = unsafe { ptr::read(me.allocator()) }; + (ptr, len, capacity, alloc) + } + + #[doc(alias = "into_non_null_parts_with_alloc")] + /// Decomposes a `Vec` into its raw components: `(NonNull pointer, length, capacity, allocator)`. + /// + /// Returns the `NonNull` pointer to the underlying data, the length of the vector (in elements), + /// the allocated capacity of the data (in elements), and the allocator. These are the same + /// arguments in the same order as the arguments to [`from_parts_in`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the `NonNull` pointer, length, and capacity back + /// into a `Vec` with the [`from_parts_in`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_parts_in`]: Vec::from_parts_in + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, vec_into_raw_parts, box_vec_non_null)] + /// + /// use std::alloc::System; + /// + /// let mut v: Vec = Vec::new_in(System); + /// v.push(-1); + /// v.push(0); + /// v.push(1); + /// + /// let (ptr, len, cap, alloc) = v.into_parts_with_alloc(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr.cast::(); + /// + /// Vec::from_parts_in(ptr, len, cap, alloc) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_parts_with_alloc(self) -> (NonNull, usize, usize, A) { + let (ptr, len, capacity, alloc) = self.into_raw_parts_with_alloc(); + // SAFETY: A `Vec` always has a non-null pointer. + (unsafe { NonNull::new_unchecked(ptr) }, len, capacity, alloc) + } + + /// Returns the total number of elements the vector can hold without + /// reallocating. + /// + /// # Examples + /// + /// ``` + /// let mut vec: Vec = Vec::with_capacity(10); + /// vec.push(42); + /// assert!(vec.capacity() >= 10); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn capacity(&self) -> usize { + self.buf.capacity() + } + + /// Reserves capacity for at least `additional` more elements to be inserted + /// in the given `Vec`. The collection may reserve more space to + /// speculatively avoid frequent reallocations. After calling `reserve`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if capacity is already sufficient. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1]; + /// vec.reserve(10); + /// assert!(vec.capacity() >= 11); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] + pub fn reserve(&mut self, additional: usize) { + self.buf.reserve(self.len, additional); + } + + /// Reserves the minimum capacity for at least `additional` more elements to + /// be inserted in the given `Vec`. Unlike [`reserve`], this will not + /// deliberately over-allocate to speculatively avoid frequent allocations. + /// After calling `reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional`. Does nothing if the capacity is already + /// sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer [`reserve`] if future insertions are expected. + /// + /// [`reserve`]: Vec::reserve + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1]; + /// vec.reserve_exact(10); + /// assert!(vec.capacity() >= 11); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] + pub fn reserve_exact(&mut self, additional: usize) { + self.buf.reserve_exact(self.len, additional); + } + + /// Tries to reserve capacity for at least `additional` more elements to be inserted + /// in the given `Vec`. The collection may reserve more space to speculatively avoid + /// frequent reallocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional` if it returns + /// `Ok(())`. Does nothing if capacity is already sufficient. This method + /// preserves the contents even if an error occurs. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { + /// let mut output = Vec::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[stable(feature = "try_reserve", since = "1.57.0")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.buf.try_reserve(self.len, additional) + } + + /// Tries to reserve the minimum capacity for at least `additional` + /// elements to be inserted in the given `Vec`. Unlike [`try_reserve`], + /// this will not deliberately over-allocate to speculatively avoid frequent + /// allocations. After calling `try_reserve_exact`, capacity will be greater + /// than or equal to `self.len() + additional` if it returns `Ok(())`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer [`try_reserve`] if future insertions are expected. + /// + /// [`try_reserve`]: Vec::try_reserve + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { + /// let mut output = Vec::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve_exact(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[stable(feature = "try_reserve", since = "1.57.0")] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.buf.try_reserve_exact(self.len, additional) + } + + /// Shrinks the capacity of the vector as much as possible. + /// + /// The behavior of this method depends on the allocator, which may either shrink the vector + /// in-place or reallocate. The resulting vector might still have some excess capacity, just as + /// is the case for [`with_capacity`]. See [`Allocator::shrink`] for more details. + /// + /// [`with_capacity`]: Vec::with_capacity + /// + /// # Examples + /// + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3]); + /// assert!(vec.capacity() >= 10); + /// vec.shrink_to_fit(); + /// assert!(vec.capacity() >= 3); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] + #[inline] + pub fn shrink_to_fit(&mut self) { + // The capacity is never less than the length, and there's nothing to do when + // they are equal, so we can avoid the panic case in `RawVec::shrink_to_fit` + // by only calling it with a greater capacity. + if self.capacity() > self.len { + self.buf.shrink_to_fit(self.len); + } + } + + /// Shrinks the capacity of the vector with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// If the current capacity is less than the lower limit, this is a no-op. + /// + /// # Examples + /// + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3]); + /// assert!(vec.capacity() >= 10); + /// vec.shrink_to(4); + /// assert!(vec.capacity() >= 4); + /// vec.shrink_to(0); + /// assert!(vec.capacity() >= 3); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "shrink_to", since = "1.56.0")] + #[track_caller] + pub fn shrink_to(&mut self, min_capacity: usize) { + if self.capacity() > min_capacity { + self.buf.shrink_to_fit(cmp::max(self.len, min_capacity)); + } + } + + /// Converts the vector into [`Box<[T]>`][owned slice]. + /// + /// Before doing the conversion, this method discards excess capacity like [`shrink_to_fit`]. + /// + /// [owned slice]: Box + /// [`shrink_to_fit`]: Vec::shrink_to_fit + /// + /// # Examples + /// + /// ``` + /// let v = vec![1, 2, 3]; + /// + /// let slice = v.into_boxed_slice(); + /// ``` + /// + /// Any excess capacity is removed: + /// + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3]); + /// + /// assert!(vec.capacity() >= 10); + /// let slice = vec.into_boxed_slice(); + /// assert_eq!(slice.into_vec().capacity(), 3); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] + pub fn into_boxed_slice(mut self) -> Box<[T], A> { + unsafe { + self.shrink_to_fit(); + let me = ManuallyDrop::new(self); + let buf = ptr::read(&me.buf); + let len = me.len(); + buf.into_box(len).assume_init() + } + } + + /// Shortens the vector, keeping the first `len` elements and dropping + /// the rest. + /// + /// If `len` is greater or equal to the vector's current length, this has + /// no effect. + /// + /// The [`drain`] method can emulate `truncate`, but causes the excess + /// elements to be returned instead of dropped. + /// + /// Note that this method has no effect on the allocated capacity + /// of the vector. + /// + /// # Examples + /// + /// Truncating a five element vector to two elements: + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4, 5]; + /// vec.truncate(2); + /// assert_eq!(vec, [1, 2]); + /// ``` + /// + /// No truncation occurs when `len` is greater than the vector's current + /// length: + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.truncate(8); + /// assert_eq!(vec, [1, 2, 3]); + /// ``` + /// + /// Truncating when `len == 0` is equivalent to calling the [`clear`] + /// method. + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.truncate(0); + /// assert_eq!(vec, []); + /// ``` + /// + /// [`clear`]: Vec::clear + /// [`drain`]: Vec::drain + #[stable(feature = "rust1", since = "1.0.0")] + pub fn truncate(&mut self, len: usize) { + // This is safe because: + // + // * the slice passed to `drop_in_place` is valid; the `len > self.len` + // case avoids creating an invalid slice, and + // * the `len` of the vector is shrunk before calling `drop_in_place`, + // such that no value will be dropped twice in case `drop_in_place` + // were to panic once (if it panics twice, the program aborts). + unsafe { + // Note: It's intentional that this is `>` and not `>=`. + // Changing it to `>=` has negative performance + // implications in some cases. See #78884 for more. + if len > self.len { + return; + } + let remaining_len = self.len - len; + let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len); + self.len = len; + ptr::drop_in_place(s); + } + } + + /// Extracts a slice containing the entire vector. + /// + /// Equivalent to `&s[..]`. + /// + /// # Examples + /// + /// ``` + /// use std::io::{self, Write}; + /// let buffer = vec![1, 2, 3, 5, 8]; + /// io::sink().write(buffer.as_slice()).unwrap(); + /// ``` + #[inline] + #[stable(feature = "vec_as_slice", since = "1.7.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_slice")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn as_slice(&self) -> &[T] { + // SAFETY: `slice::from_raw_parts` requires pointee is a contiguous, aligned buffer of size + // `len` containing properly-initialized `T`s. Data must not be mutated for the returned + // lifetime. Further, `len * mem::size_of::` <= `ISIZE::MAX`, and allocation does not + // "wrap" through overflowing memory addresses. + // + // * Vec API guarantees that self.buf: + // * contains only properly-initialized items within 0..len + // * is aligned, contiguous, and valid for `len` reads + // * obeys size and address-wrapping constraints + // + // * We only construct `&mut` references to `self.buf` through `&mut self` methods; borrow- + // check ensures that it is not possible to mutably alias `self.buf` within the + // returned lifetime. + unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } + } + + /// Extracts a mutable slice of the entire vector. + /// + /// Equivalent to `&mut s[..]`. + /// + /// # Examples + /// + /// ``` + /// use std::io::{self, Read}; + /// let mut buffer = vec![0; 3]; + /// io::repeat(0b101).read_exact(buffer.as_mut_slice()).unwrap(); + /// ``` + #[inline] + #[stable(feature = "vec_as_slice", since = "1.7.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_mut_slice")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: `slice::from_raw_parts_mut` requires pointee is a contiguous, aligned buffer of + // size `len` containing properly-initialized `T`s. Data must not be accessed through any + // other pointer for the returned lifetime. Further, `len * mem::size_of::` <= + // `ISIZE::MAX` and allocation does not "wrap" through overflowing memory addresses. + // + // * Vec API guarantees that self.buf: + // * contains only properly-initialized items within 0..len + // * is aligned, contiguous, and valid for `len` reads + // * obeys size and address-wrapping constraints + // + // * We only construct references to `self.buf` through `&self` and `&mut self` methods; + // borrow-check ensures that it is not possible to construct a reference to `self.buf` + // within the returned lifetime. + unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } + } + + /// Returns a raw pointer to the vector's buffer, or a dangling raw pointer + /// valid for zero sized reads if the vector didn't allocate. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up dangling. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// The caller must also ensure that the memory the pointer (non-transitively) points to + /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer + /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. + /// + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying slice, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`], [`as_mut_ptr`], + /// and [`as_non_null`]. + /// Note that calling other methods that materialize mutable references to the slice, + /// or mutable references to specific elements you are planning on accessing through this pointer, + /// as well as writing to those elements, may still invalidate this pointer. + /// See the second example below for how this guarantee can be used. + /// + /// + /// # Examples + /// + /// ``` + /// let x = vec![1, 2, 4]; + /// let x_ptr = x.as_ptr(); + /// + /// unsafe { + /// for i in 0..x.len() { + /// assert_eq!(*x_ptr.add(i), 1 << i); + /// } + /// } + /// ``` + /// + /// Due to the aliasing guarantee, the following code is legal: + /// + /// ```rust + /// unsafe { + /// let mut v = vec![0, 1, 2]; + /// let ptr1 = v.as_ptr(); + /// let _ = ptr1.read(); + /// let ptr2 = v.as_mut_ptr().offset(2); + /// ptr2.write(2); + /// // Notably, the write to `ptr2` did *not* invalidate `ptr1` + /// // because it mutated a different element: + /// let _ = ptr1.read(); + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Vec::as_mut_ptr + /// [`as_ptr`]: Vec::as_ptr + /// [`as_non_null`]: Vec::as_non_null + #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + #[rustc_never_returns_null_ptr] + #[rustc_as_ptr] + #[inline] + pub const fn as_ptr(&self) -> *const T { + // We shadow the slice method of the same name to avoid going through + // `deref`, which creates an intermediate reference. + self.buf.ptr() + } + + /// Returns a raw mutable pointer to the vector's buffer, or a dangling + /// raw pointer valid for zero sized reads if the vector didn't allocate. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up dangling. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying slice, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`], [`as_mut_ptr`], + /// and [`as_non_null`]. + /// Note that calling other methods that materialize references to the slice, + /// or references to specific elements you are planning on accessing through this pointer, + /// may still invalidate this pointer. + /// See the second example below for how this guarantee can be used. + /// + /// # Examples + /// + /// ``` + /// // Allocate vector big enough for 4 elements. + /// let size = 4; + /// let mut x: Vec = Vec::with_capacity(size); + /// let x_ptr = x.as_mut_ptr(); + /// + /// // Initialize elements via raw pointer writes, then set length. + /// unsafe { + /// for i in 0..size { + /// *x_ptr.add(i) = i as i32; + /// } + /// x.set_len(size); + /// } + /// assert_eq!(&*x, &[0, 1, 2, 3]); + /// ``` + /// + /// Due to the aliasing guarantee, the following code is legal: + /// + /// ```rust + /// unsafe { + /// let mut v = vec![0]; + /// let ptr1 = v.as_mut_ptr(); + /// ptr1.write(1); + /// let ptr2 = v.as_mut_ptr(); + /// ptr2.write(2); + /// // Notably, the write to `ptr2` did *not* invalidate `ptr1`: + /// ptr1.write(3); + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Vec::as_mut_ptr + /// [`as_ptr`]: Vec::as_ptr + /// [`as_non_null`]: Vec::as_non_null + #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + #[rustc_never_returns_null_ptr] + #[rustc_as_ptr] + #[inline] + pub const fn as_mut_ptr(&mut self) -> *mut T { + // We shadow the slice method of the same name to avoid going through + // `deref_mut`, which creates an intermediate reference. + self.buf.ptr() + } + + /// Returns a `NonNull` pointer to the vector's buffer, or a dangling + /// `NonNull` pointer valid for zero sized reads if the vector didn't allocate. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up dangling. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying slice, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`], [`as_mut_ptr`], + /// and [`as_non_null`]. + /// Note that calling other methods that materialize references to the slice, + /// or references to specific elements you are planning on accessing through this pointer, + /// may still invalidate this pointer. + /// See the second example below for how this guarantee can be used. + /// + /// # Examples + /// + /// ``` + /// #![feature(box_vec_non_null)] + /// + /// // Allocate vector big enough for 4 elements. + /// let size = 4; + /// let mut x: Vec = Vec::with_capacity(size); + /// let x_ptr = x.as_non_null(); + /// + /// // Initialize elements via raw pointer writes, then set length. + /// unsafe { + /// for i in 0..size { + /// x_ptr.add(i).write(i as i32); + /// } + /// x.set_len(size); + /// } + /// assert_eq!(&*x, &[0, 1, 2, 3]); + /// ``` + /// + /// Due to the aliasing guarantee, the following code is legal: + /// + /// ```rust + /// #![feature(box_vec_non_null)] + /// + /// unsafe { + /// let mut v = vec![0]; + /// let ptr1 = v.as_non_null(); + /// ptr1.write(1); + /// let ptr2 = v.as_non_null(); + /// ptr2.write(2); + /// // Notably, the write to `ptr2` did *not* invalidate `ptr1`: + /// ptr1.write(3); + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Vec::as_mut_ptr + /// [`as_ptr`]: Vec::as_ptr + /// [`as_non_null`]: Vec::as_non_null + #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] + #[inline] + pub fn as_non_null(&mut self) -> NonNull { + // SAFETY: A `Vec` always has a non-null pointer. + unsafe { NonNull::new_unchecked(self.as_mut_ptr()) } + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + self.buf.allocator() + } + + /// Forces the length of the vector to `new_len`. + /// + /// This is a low-level operation that maintains none of the normal + /// invariants of the type. Normally changing the length of a vector + /// is done using one of the safe operations instead, such as + /// [`truncate`], [`resize`], [`extend`], or [`clear`]. + /// + /// [`truncate`]: Vec::truncate + /// [`resize`]: Vec::resize + /// [`extend`]: Extend::extend + /// [`clear`]: Vec::clear + /// + /// # Safety + /// + /// - `new_len` must be less than or equal to [`capacity()`]. + /// - The elements at `old_len..new_len` must be initialized. + /// + /// [`capacity()`]: Vec::capacity + /// + /// # Examples + /// + /// This method can be useful for situations in which the vector + /// is serving as a buffer for other code, particularly over FFI: + /// + /// ```no_run + /// # #![allow(dead_code)] + /// # // This is just a minimal skeleton for the doc example; + /// # // don't use this as a starting point for a real library. + /// # pub struct StreamWrapper { strm: *mut std::ffi::c_void } + /// # const Z_OK: i32 = 0; + /// # extern "C" { + /// # fn deflateGetDictionary( + /// # strm: *mut std::ffi::c_void, + /// # dictionary: *mut u8, + /// # dictLength: *mut usize, + /// # ) -> i32; + /// # } + /// # impl StreamWrapper { + /// pub fn get_dictionary(&self) -> Option> { + /// // Per the FFI method's docs, "32768 bytes is always enough". + /// let mut dict = Vec::with_capacity(32_768); + /// let mut dict_length = 0; + /// // SAFETY: When `deflateGetDictionary` returns `Z_OK`, it holds that: + /// // 1. `dict_length` elements were initialized. + /// // 2. `dict_length` <= the capacity (32_768) + /// // which makes `set_len` safe to call. + /// unsafe { + /// // Make the FFI call... + /// let r = deflateGetDictionary(self.strm, dict.as_mut_ptr(), &mut dict_length); + /// if r == Z_OK { + /// // ...and update the length to what was initialized. + /// dict.set_len(dict_length); + /// Some(dict) + /// } else { + /// None + /// } + /// } + /// } + /// # } + /// ``` + /// + /// While the following example is sound, there is a memory leak since + /// the inner vectors were not freed prior to the `set_len` call: + /// + /// ``` + /// let mut vec = vec![vec![1, 0, 0], + /// vec![0, 1, 0], + /// vec![0, 0, 1]]; + /// // SAFETY: + /// // 1. `old_len..0` is empty so no elements need to be initialized. + /// // 2. `0 <= capacity` always holds whatever `capacity` is. + /// unsafe { + /// vec.set_len(0); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # vec.set_len(3); + /// } + /// ``` + /// + /// Normally, here, one would use [`clear`] instead to correctly drop + /// the contents and thus not leak memory. + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn set_len(&mut self, new_len: usize) { + debug_assert!(new_len <= self.capacity()); + + self.len = new_len; + } + + /// Removes an element from the vector and returns it. + /// + /// The removed element is replaced by the last element of the vector. + /// + /// This does not preserve ordering of the remaining elements, but is *O*(1). + /// If you need to preserve the element order, use [`remove`] instead. + /// + /// [`remove`]: Vec::remove + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec!["foo", "bar", "baz", "qux"]; + /// + /// assert_eq!(v.swap_remove(1), "bar"); + /// assert_eq!(v, ["foo", "qux", "baz"]); + /// + /// assert_eq!(v.swap_remove(0), "foo"); + /// assert_eq!(v, ["baz", "qux"]); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn swap_remove(&mut self, index: usize) -> T { + #[cold] + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] + #[track_caller] + #[optimize(size)] + fn assert_failed(index: usize, len: usize) -> ! { + panic!("swap_remove index (is {index}) should be < len (is {len})"); + } + + let len = self.len(); + if index >= len { + assert_failed(index, len); + } + unsafe { + // We replace self[index] with the last element. Note that if the + // bounds check above succeeds there must be a last element (which + // can be self[index] itself). + let value = ptr::read(self.as_ptr().add(index)); + let base_ptr = self.as_mut_ptr(); + ptr::copy(base_ptr.add(len - 1), base_ptr.add(index), 1); + self.set_len(len - 1); + value + } + } + + /// Inserts an element at position `index` within the vector, shifting all + /// elements after it to the right. + /// + /// # Panics + /// + /// Panics if `index > len`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.insert(1, 4); + /// assert_eq!(vec, [1, 4, 2, 3]); + /// vec.insert(4, 5); + /// assert_eq!(vec, [1, 4, 2, 3, 5]); + /// ``` + /// + /// # Time complexity + /// + /// Takes *O*([`Vec::len`]) time. All items after the insertion index must be + /// shifted to the right. In the worst case, all elements are shifted when + /// the insertion index is 0. + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] + pub fn insert(&mut self, index: usize, element: T) { + #[cold] + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] + #[track_caller] + #[optimize(size)] + fn assert_failed(index: usize, len: usize) -> ! { + panic!("insertion index (is {index}) should be <= len (is {len})"); + } + + let len = self.len(); + if index > len { + assert_failed(index, len); + } + + // space for the new element + if len == self.buf.capacity() { + self.buf.grow_one(); + } + + unsafe { + // infallible + // The spot to put the new value + { + let p = self.as_mut_ptr().add(index); + if index < len { + // Shift everything over to make space. (Duplicating the + // `index`th element into two consecutive places.) + ptr::copy(p, p.add(1), len - index); + } + // Write it in, overwriting the first copy of the `index`th + // element. + ptr::write(p, element); + } + self.set_len(len + 1); + } + } + + /// Removes and returns the element at position `index` within the vector, + /// shifting all elements after it to the left. + /// + /// Note: Because this shifts over the remaining elements, it has a + /// worst-case performance of *O*(*n*). If you don't need the order of elements + /// to be preserved, use [`swap_remove`] instead. If you'd like to remove + /// elements from the beginning of the `Vec`, consider using + /// [`VecDeque::pop_front`] instead. + /// + /// [`swap_remove`]: Vec::swap_remove + /// [`VecDeque::pop_front`]: crate::collections::VecDeque::pop_front + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// assert_eq!(v.remove(1), 2); + /// assert_eq!(v, [1, 3]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] + #[rustc_confusables("delete", "take")] + pub fn remove(&mut self, index: usize) -> T { + #[cold] + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] + #[track_caller] + #[optimize(size)] + fn assert_failed(index: usize, len: usize) -> ! { + panic!("removal index (is {index}) should be < len (is {len})"); + } + + let len = self.len(); + if index >= len { + assert_failed(index, len); + } + unsafe { + // infallible + let ret; + { + // the place we are taking from. + let ptr = self.as_mut_ptr().add(index); + // copy it out, unsafely having a copy of the value on + // the stack and in the vector at the same time. + ret = ptr::read(ptr); + + // Shift everything down to fill in that spot. + ptr::copy(ptr.add(1), ptr, len - index - 1); + } + self.set_len(len - 1); + ret + } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` for which `f(&e)` returns `false`. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4]; + /// vec.retain(|&x| x % 2 == 0); + /// assert_eq!(vec, [2, 4]); + /// ``` + /// + /// Because the elements are visited exactly once in the original order, + /// external state may be used to decide which elements to keep. + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4, 5]; + /// let keep = [false, true, true, false, true]; + /// let mut iter = keep.iter(); + /// vec.retain(|_| *iter.next().unwrap()); + /// assert_eq!(vec, [2, 3, 5]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn retain(&mut self, mut f: F) + where + F: FnMut(&T) -> bool, + { + self.retain_mut(|elem| f(elem)); + } + + /// Retains only the elements specified by the predicate, passing a mutable reference to it. + /// + /// In other words, remove all elements `e` such that `f(&mut e)` returns `false`. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4]; + /// vec.retain_mut(|x| if *x <= 3 { + /// *x += 1; + /// true + /// } else { + /// false + /// }); + /// assert_eq!(vec, [2, 3, 4]); + /// ``` + #[stable(feature = "vec_retain_mut", since = "1.61.0")] + pub fn retain_mut(&mut self, mut f: F) + where + F: FnMut(&mut T) -> bool, + { + let original_len = self.len(); + + if original_len == 0 { + // Empty case: explicit return allows better optimization, vs letting compiler infer it + return; + } + + // Avoid double drop if the drop guard is not executed, + // since we may make some holes during the process. + unsafe { self.set_len(0) }; + + // Vec: [Kept, Kept, Hole, Hole, Hole, Hole, Unchecked, Unchecked] + // |<- processed len ->| ^- next to check + // |<- deleted cnt ->| + // |<- original_len ->| + // Kept: Elements which predicate returns true on. + // Hole: Moved or dropped element slot. + // Unchecked: Unchecked valid elements. + // + // This drop guard will be invoked when predicate or `drop` of element panicked. + // It shifts unchecked elements to cover holes and `set_len` to the correct length. + // In cases when predicate and `drop` never panick, it will be optimized out. + struct BackshiftOnDrop<'a, T, A: Allocator> { + v: &'a mut Vec, + processed_len: usize, + deleted_cnt: usize, + original_len: usize, + } + + impl Drop for BackshiftOnDrop<'_, T, A> { + fn drop(&mut self) { + if self.deleted_cnt > 0 { + // SAFETY: Trailing unchecked items must be valid since we never touch them. + unsafe { + ptr::copy( + self.v.as_ptr().add(self.processed_len), + self.v.as_mut_ptr().add(self.processed_len - self.deleted_cnt), + self.original_len - self.processed_len, + ); + } + } + // SAFETY: After filling holes, all items are in contiguous memory. + unsafe { + self.v.set_len(self.original_len - self.deleted_cnt); + } + } + } + + let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len }; + + fn process_loop( + original_len: usize, + f: &mut F, + g: &mut BackshiftOnDrop<'_, T, A>, + ) where + F: FnMut(&mut T) -> bool, + { + while g.processed_len != original_len { + // SAFETY: Unchecked element must be valid. + let cur = unsafe { &mut *g.v.as_mut_ptr().add(g.processed_len) }; + if !f(cur) { + // Advance early to avoid double drop if `drop_in_place` panicked. + g.processed_len += 1; + g.deleted_cnt += 1; + // SAFETY: We never touch this element again after dropped. + unsafe { ptr::drop_in_place(cur) }; + // We already advanced the counter. + if DELETED { + continue; + } else { + break; + } + } + if DELETED { + // SAFETY: `deleted_cnt` > 0, so the hole slot must not overlap with current element. + // We use copy for move, and never touch this element again. + unsafe { + let hole_slot = g.v.as_mut_ptr().add(g.processed_len - g.deleted_cnt); + ptr::copy_nonoverlapping(cur, hole_slot, 1); + } + } + g.processed_len += 1; + } + } + + // Stage 1: Nothing was deleted. + process_loop::(original_len, &mut f, &mut g); + + // Stage 2: Some elements were deleted. + process_loop::(original_len, &mut f, &mut g); + + // All item are processed. This can be optimized to `set_len` by LLVM. + drop(g); + } + + /// Removes all but the first of consecutive elements in the vector that resolve to the same + /// key. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![10, 20, 21, 30, 20]; + /// + /// vec.dedup_by_key(|i| *i / 10); + /// + /// assert_eq!(vec, [10, 20, 30, 20]); + /// ``` + #[stable(feature = "dedup_by", since = "1.16.0")] + #[inline] + pub fn dedup_by_key(&mut self, mut key: F) + where + F: FnMut(&mut T) -> K, + K: PartialEq, + { + self.dedup_by(|a, b| key(a) == key(b)) + } + + /// Removes all but the first of consecutive elements in the vector satisfying a given equality + /// relation. + /// + /// The `same_bucket` function is passed references to two elements from the vector and + /// must determine if the elements compare equal. The elements are passed in opposite order + /// from their order in the slice, so if `same_bucket(a, b)` returns `true`, `a` is removed. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"]; + /// + /// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); + /// + /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]); + /// ``` + #[stable(feature = "dedup_by", since = "1.16.0")] + pub fn dedup_by(&mut self, mut same_bucket: F) + where + F: FnMut(&mut T, &mut T) -> bool, + { + let len = self.len(); + if len <= 1 { + return; + } + + // Check if we ever want to remove anything. + // This allows to use copy_non_overlapping in next cycle. + // And avoids any memory writes if we don't need to remove anything. + let mut first_duplicate_idx: usize = 1; + let start = self.as_mut_ptr(); + while first_duplicate_idx != len { + let found_duplicate = unsafe { + // SAFETY: first_duplicate always in range [1..len) + // Note that we start iteration from 1 so we never overflow. + let prev = start.add(first_duplicate_idx.wrapping_sub(1)); + let current = start.add(first_duplicate_idx); + // We explicitly say in docs that references are reversed. + same_bucket(&mut *current, &mut *prev) + }; + if found_duplicate { + break; + } + first_duplicate_idx += 1; + } + // Don't need to remove anything. + // We cannot get bigger than len. + if first_duplicate_idx == len { + return; + } + + /* INVARIANT: vec.len() > read > write > write-1 >= 0 */ + struct FillGapOnDrop<'a, T, A: core::alloc::Allocator> { + /* Offset of the element we want to check if it is duplicate */ + read: usize, + + /* Offset of the place where we want to place the non-duplicate + * when we find it. */ + write: usize, + + /* The Vec that would need correction if `same_bucket` panicked */ + vec: &'a mut Vec, + } + + impl<'a, T, A: core::alloc::Allocator> Drop for FillGapOnDrop<'a, T, A> { + fn drop(&mut self) { + /* This code gets executed when `same_bucket` panics */ + + /* SAFETY: invariant guarantees that `read - write` + * and `len - read` never overflow and that the copy is always + * in-bounds. */ + unsafe { + let ptr = self.vec.as_mut_ptr(); + let len = self.vec.len(); + + /* How many items were left when `same_bucket` panicked. + * Basically vec[read..].len() */ + let items_left = len.wrapping_sub(self.read); + + /* Pointer to first item in vec[write..write+items_left] slice */ + let dropped_ptr = ptr.add(self.write); + /* Pointer to first item in vec[read..] slice */ + let valid_ptr = ptr.add(self.read); + + /* Copy `vec[read..]` to `vec[write..write+items_left]`. + * The slices can overlap, so `copy_nonoverlapping` cannot be used */ + ptr::copy(valid_ptr, dropped_ptr, items_left); + + /* How many items have been already dropped + * Basically vec[read..write].len() */ + let dropped = self.read.wrapping_sub(self.write); + + self.vec.set_len(len - dropped); + } + } + } + + /* Drop items while going through Vec, it should be more efficient than + * doing slice partition_dedup + truncate */ + + // Construct gap first and then drop item to avoid memory corruption if `T::drop` panics. + let mut gap = + FillGapOnDrop { read: first_duplicate_idx + 1, write: first_duplicate_idx, vec: self }; + unsafe { + // SAFETY: we checked that first_duplicate_idx in bounds before. + // If drop panics, `gap` would remove this item without drop. + ptr::drop_in_place(start.add(first_duplicate_idx)); + } + + /* SAFETY: Because of the invariant, read_ptr, prev_ptr and write_ptr + * are always in-bounds and read_ptr never aliases prev_ptr */ + unsafe { + while gap.read < len { + let read_ptr = start.add(gap.read); + let prev_ptr = start.add(gap.write.wrapping_sub(1)); + + // We explicitly say in docs that references are reversed. + let found_duplicate = same_bucket(&mut *read_ptr, &mut *prev_ptr); + if found_duplicate { + // Increase `gap.read` now since the drop may panic. + gap.read += 1; + /* We have found duplicate, drop it in-place */ + ptr::drop_in_place(read_ptr); + } else { + let write_ptr = start.add(gap.write); + + /* read_ptr cannot be equal to write_ptr because at this point + * we guaranteed to skip at least one element (before loop starts). + */ + ptr::copy_nonoverlapping(read_ptr, write_ptr, 1); + + /* We have filled that place, so go further */ + gap.write += 1; + gap.read += 1; + } + } + + /* Technically we could let `gap` clean up with its Drop, but + * when `same_bucket` is guaranteed to not panic, this bloats a little + * the codegen, so we just do it manually */ + gap.vec.set_len(gap.write); + mem::forget(gap); + } + } + + /// Appends an element to the back of a collection. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2]; + /// vec.push(3); + /// assert_eq!(vec, [1, 2, 3]); + /// ``` + /// + /// # Time complexity + /// + /// Takes amortized *O*(1) time. If the vector's length would exceed its + /// capacity after the push, *O*(*capacity*) time is taken to copy the + /// vector's elements to a larger allocation. This expensive operation is + /// offset by the *capacity* *O*(1) insertions it allows. + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_confusables("push_back", "put", "append")] + #[track_caller] + pub fn push(&mut self, value: T) { + // Inform codegen that the length does not change across grow_one(). + let len = self.len; + // This will panic or abort if we would allocate > isize::MAX bytes + // or if the length increment would overflow for zero-sized types. + if len == self.buf.capacity() { + self.buf.grow_one(); + } + unsafe { + let end = self.as_mut_ptr().add(len); + ptr::write(end, value); + self.len = len + 1; + } + } + + /// Appends an element if there is sufficient spare capacity, otherwise an error is returned + /// with the element. + /// + /// Unlike [`push`] this method will not reallocate when there's insufficient capacity. + /// The caller should use [`reserve`] or [`try_reserve`] to ensure that there is enough capacity. + /// + /// [`push`]: Vec::push + /// [`reserve`]: Vec::reserve + /// [`try_reserve`]: Vec::try_reserve + /// + /// # Examples + /// + /// A manual, panic-free alternative to [`FromIterator`]: + /// + /// ``` + /// #![feature(vec_push_within_capacity)] + /// + /// use std::collections::TryReserveError; + /// fn from_iter_fallible(iter: impl Iterator) -> Result, TryReserveError> { + /// let mut vec = Vec::new(); + /// for value in iter { + /// if let Err(value) = vec.push_within_capacity(value) { + /// vec.try_reserve(1)?; + /// // this cannot fail, the previous line either returned or added at least 1 free slot + /// let _ = vec.push_within_capacity(value); + /// } + /// } + /// Ok(vec) + /// } + /// assert_eq!(from_iter_fallible(0..100), Ok(Vec::from_iter(0..100))); + /// ``` + /// + /// # Time complexity + /// + /// Takes *O*(1) time. + #[inline] + #[unstable(feature = "vec_push_within_capacity", issue = "100486")] + pub fn push_within_capacity(&mut self, value: T) -> Result<(), T> { + if self.len == self.buf.capacity() { + return Err(value); + } + unsafe { + let end = self.as_mut_ptr().add(self.len); + ptr::write(end, value); + self.len += 1; + } + Ok(()) + } + + /// Removes the last element from a vector and returns it, or [`None`] if it + /// is empty. + /// + /// If you'd like to pop the first element, consider using + /// [`VecDeque::pop_front`] instead. + /// + /// [`VecDeque::pop_front`]: crate::collections::VecDeque::pop_front + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// assert_eq!(vec.pop(), Some(3)); + /// assert_eq!(vec, [1, 2]); + /// ``` + /// + /// # Time complexity + /// + /// Takes *O*(1) time. + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "vec_pop")] + pub fn pop(&mut self) -> Option { + if self.len == 0 { + None + } else { + unsafe { + self.len -= 1; + core::hint::assert_unchecked(self.len < self.capacity()); + Some(ptr::read(self.as_ptr().add(self.len()))) + } + } + } + + /// Removes and returns the last element in a vector if the predicate + /// returns `true`, or [`None`] if the predicate returns false or the vector + /// is empty. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_pop_if)] + /// + /// let mut vec = vec![1, 2, 3, 4]; + /// let pred = |x: &mut i32| *x % 2 == 0; + /// + /// assert_eq!(vec.pop_if(pred), Some(4)); + /// assert_eq!(vec, [1, 2, 3]); + /// assert_eq!(vec.pop_if(pred), None); + /// ``` + #[unstable(feature = "vec_pop_if", issue = "122741")] + pub fn pop_if(&mut self, f: F) -> Option + where + F: FnOnce(&mut T) -> bool, + { + let last = self.last_mut()?; + if f(last) { self.pop() } else { None } + } + + /// Moves all the elements of `other` into `self`, leaving `other` empty. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// let mut vec2 = vec![4, 5, 6]; + /// vec.append(&mut vec2); + /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]); + /// assert_eq!(vec2, []); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "append", since = "1.4.0")] + #[track_caller] + pub fn append(&mut self, other: &mut Self) { + unsafe { + self.append_elements(other.as_slice() as _); + other.set_len(0); + } + } + + /// Appends elements to `self` from other buffer. + #[cfg(not(no_global_oom_handling))] + #[inline] + #[track_caller] + unsafe fn append_elements(&mut self, other: *const [T]) { + let count = unsafe { (*other).len() }; + self.reserve(count); + let len = self.len(); + unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count) }; + self.len += count; + } + + /// Removes the specified range from the vector in bulk, returning all + /// removed elements as an iterator. If the iterator is dropped before + /// being fully consumed, it drops the remaining removed elements. + /// + /// The returned iterator keeps a mutable borrow on the vector to optimize + /// its implementation. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// # Leaking + /// + /// If the returned iterator goes out of scope without being dropped (due to + /// [`mem::forget`], for example), the vector may have lost and leaked + /// elements arbitrarily, including elements outside the range. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// let u: Vec<_> = v.drain(1..).collect(); + /// assert_eq!(v, &[1]); + /// assert_eq!(u, &[2, 3]); + /// + /// // A full range clears the vector, like `clear()` does + /// v.drain(..); + /// assert_eq!(v, &[]); + /// ``` + #[stable(feature = "drain", since = "1.6.0")] + pub fn drain(&mut self, range: R) -> Drain<'_, T, A> + where + R: RangeBounds, + { + // Memory safety + // + // When the Drain is first created, it shortens the length of + // the source vector to make sure no uninitialized or moved-from elements + // are accessible at all if the Drain's destructor never gets to run. + // + // Drain will ptr::read out the values to remove. + // When finished, remaining tail of the vec is copied back to cover + // the hole, and the vector length is restored to the new length. + // + let len = self.len(); + let Range { start, end } = slice::range(range, ..len); + + unsafe { + // set self.vec length's to start, to be safe in case Drain is leaked + self.set_len(start); + let range_slice = slice::from_raw_parts(self.as_ptr().add(start), end - start); + Drain { + tail_start: end, + tail_len: len - end, + iter: range_slice.iter(), + vec: NonNull::from(self), + } + } + } + + /// Clears the vector, removing all values. + /// + /// Note that this method has no effect on the allocated capacity + /// of the vector. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// + /// v.clear(); + /// + /// assert!(v.is_empty()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + let elems: *mut [T] = self.as_mut_slice(); + + // SAFETY: + // - `elems` comes directly from `as_mut_slice` and is therefore valid. + // - Setting `self.len` before calling `drop_in_place` means that, + // if an element's `Drop` impl panics, the vector's `Drop` impl will + // do nothing (leaking the rest of the elements) instead of dropping + // some twice. + unsafe { + self.len = 0; + ptr::drop_in_place(elems); + } + } + + /// Returns the number of elements in the vector, also referred to + /// as its 'length'. + /// + /// # Examples + /// + /// ``` + /// let a = vec![1, 2, 3]; + /// assert_eq!(a.len(), 3); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + #[rustc_confusables("length", "size")] + pub const fn len(&self) -> usize { + self.len + } + + /// Returns `true` if the vector contains no elements. + /// + /// # Examples + /// + /// ``` + /// let mut v = Vec::new(); + /// assert!(v.is_empty()); + /// + /// v.push(1); + /// assert!(!v.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "vec_is_empty")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Splits the collection into two at the given index. + /// + /// Returns a newly allocated vector containing the elements in the range + /// `[at, len)`. After the call, the original vector will be left containing + /// the elements `[0, at)` with its previous capacity unchanged. + /// + /// - If you want to take ownership of the entire contents and capacity of + /// the vector, see [`mem::take`] or [`mem::replace`]. + /// - If you don't need the returned vector at all, see [`Vec::truncate`]. + /// - If you want to take ownership of an arbitrary subslice, or you don't + /// necessarily want to store the removed items in a vector, see [`Vec::drain`]. + /// + /// # Panics + /// + /// Panics if `at > len`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// let vec2 = vec.split_off(1); + /// assert_eq!(vec, [1]); + /// assert_eq!(vec2, [2, 3]); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[must_use = "use `.truncate()` if you don't need the other half"] + #[stable(feature = "split_off", since = "1.4.0")] + #[track_caller] + pub fn split_off(&mut self, at: usize) -> Self + where + A: Clone, + { + #[cold] + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] + #[track_caller] + #[optimize(size)] + fn assert_failed(at: usize, len: usize) -> ! { + panic!("`at` split index (is {at}) should be <= len (is {len})"); + } + + if at > self.len() { + assert_failed(at, self.len()); + } + + let other_len = self.len - at; + let mut other = Vec::with_capacity_in(other_len, self.allocator().clone()); + + // Unsafely `set_len` and copy items to `other`. + unsafe { + self.set_len(at); + other.set_len(other_len); + + ptr::copy_nonoverlapping(self.as_ptr().add(at), other.as_mut_ptr(), other.len()); + } + other + } + + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. + /// + /// If `new_len` is greater than `len`, the `Vec` is extended by the + /// difference, with each additional slot filled with the result of + /// calling the closure `f`. The return values from `f` will end up + /// in the `Vec` in the order they have been generated. + /// + /// If `new_len` is less than `len`, the `Vec` is simply truncated. + /// + /// This method uses a closure to create new values on every push. If + /// you'd rather [`Clone`] a given value, use [`Vec::resize`]. If you + /// want to use the [`Default`] trait to generate values, you can + /// pass [`Default::default`] as the second argument. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.resize_with(5, Default::default); + /// assert_eq!(vec, [1, 2, 3, 0, 0]); + /// + /// let mut vec = vec![]; + /// let mut p = 1; + /// vec.resize_with(4, || { p *= 2; p }); + /// assert_eq!(vec, [2, 4, 8, 16]); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "vec_resize_with", since = "1.33.0")] + #[track_caller] + pub fn resize_with(&mut self, new_len: usize, f: F) + where + F: FnMut() -> T, + { + let len = self.len(); + if new_len > len { + self.extend_trusted(iter::repeat_with(f).take(new_len - len)); + } else { + self.truncate(new_len); + } + } + + /// Consumes and leaks the `Vec`, returning a mutable reference to the contents, + /// `&'a mut [T]`. + /// + /// Note that the type `T` must outlive the chosen lifetime `'a`. If the type + /// has only static references, or none at all, then this may be chosen to be + /// `'static`. + /// + /// As of Rust 1.57, this method does not reallocate or shrink the `Vec`, + /// so the leaked allocation may include unused capacity that is not part + /// of the returned slice. + /// + /// This function is mainly useful for data that lives for the remainder of + /// the program's life. Dropping the returned reference will cause a memory + /// leak. + /// + /// # Examples + /// + /// Simple usage: + /// + /// ``` + /// let x = vec![1, 2, 3]; + /// let static_ref: &'static mut [usize] = x.leak(); + /// static_ref[0] += 1; + /// assert_eq!(static_ref, &[2, 2, 3]); + /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): + /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. + /// # drop(unsafe { Box::from_raw(static_ref) }); + /// ``` + #[stable(feature = "vec_leak", since = "1.47.0")] + #[inline] + pub fn leak<'a>(self) -> &'a mut [T] + where + A: 'a, + { + let mut me = ManuallyDrop::new(self); + unsafe { slice::from_raw_parts_mut(me.as_mut_ptr(), me.len) } + } + + /// Returns the remaining spare capacity of the vector as a slice of + /// `MaybeUninit`. + /// + /// The returned slice can be used to fill the vector with data (e.g. by + /// reading from a file) before marking the data as initialized using the + /// [`set_len`] method. + /// + /// [`set_len`]: Vec::set_len + /// + /// # Examples + /// + /// ``` + /// // Allocate vector big enough for 10 elements. + /// let mut v = Vec::with_capacity(10); + /// + /// // Fill in the first 3 elements. + /// let uninit = v.spare_capacity_mut(); + /// uninit[0].write(0); + /// uninit[1].write(1); + /// uninit[2].write(2); + /// + /// // Mark the first 3 elements of the vector as being initialized. + /// unsafe { + /// v.set_len(3); + /// } + /// + /// assert_eq!(&v, &[0, 1, 2]); + /// ``` + #[stable(feature = "vec_spare_capacity", since = "1.60.0")] + #[inline] + pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit] { + // Note: + // This method is not implemented in terms of `split_at_spare_mut`, + // to prevent invalidation of pointers to the buffer. + unsafe { + slice::from_raw_parts_mut( + self.as_mut_ptr().add(self.len) as *mut MaybeUninit, + self.buf.capacity() - self.len, + ) + } + } + + /// Returns vector content as a slice of `T`, along with the remaining spare + /// capacity of the vector as a slice of `MaybeUninit`. + /// + /// The returned spare capacity slice can be used to fill the vector with data + /// (e.g. by reading from a file) before marking the data as initialized using + /// the [`set_len`] method. + /// + /// [`set_len`]: Vec::set_len + /// + /// Note that this is a low-level API, which should be used with care for + /// optimization purposes. If you need to append data to a `Vec` + /// you can use [`push`], [`extend`], [`extend_from_slice`], + /// [`extend_from_within`], [`insert`], [`append`], [`resize`] or + /// [`resize_with`], depending on your exact needs. + /// + /// [`push`]: Vec::push + /// [`extend`]: Vec::extend + /// [`extend_from_slice`]: Vec::extend_from_slice + /// [`extend_from_within`]: Vec::extend_from_within + /// [`insert`]: Vec::insert + /// [`append`]: Vec::append + /// [`resize`]: Vec::resize + /// [`resize_with`]: Vec::resize_with + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_split_at_spare)] + /// + /// let mut v = vec![1, 1, 2]; + /// + /// // Reserve additional space big enough for 10 elements. + /// v.reserve(10); + /// + /// let (init, uninit) = v.split_at_spare_mut(); + /// let sum = init.iter().copied().sum::(); + /// + /// // Fill in the next 4 elements. + /// uninit[0].write(sum); + /// uninit[1].write(sum * 2); + /// uninit[2].write(sum * 3); + /// uninit[3].write(sum * 4); + /// + /// // Mark the 4 elements of the vector as being initialized. + /// unsafe { + /// let len = v.len(); + /// v.set_len(len + 4); + /// } + /// + /// assert_eq!(&v, &[1, 1, 2, 4, 8, 12, 16]); + /// ``` + #[unstable(feature = "vec_split_at_spare", issue = "81944")] + #[inline] + pub fn split_at_spare_mut(&mut self) -> (&mut [T], &mut [MaybeUninit]) { + // SAFETY: + // - len is ignored and so never changed + let (init, spare, _) = unsafe { self.split_at_spare_mut_with_len() }; + (init, spare) + } + + /// Safety: changing returned .2 (&mut usize) is considered the same as calling `.set_len(_)`. + /// + /// This method provides unique access to all vec parts at once in `extend_from_within`. + unsafe fn split_at_spare_mut_with_len( + &mut self, + ) -> (&mut [T], &mut [MaybeUninit], &mut usize) { + let ptr = self.as_mut_ptr(); + // SAFETY: + // - `ptr` is guaranteed to be valid for `self.len` elements + // - but the allocation extends out to `self.buf.capacity()` elements, possibly + // uninitialized + let spare_ptr = unsafe { ptr.add(self.len) }; + let spare_ptr = spare_ptr.cast::>(); + let spare_len = self.buf.capacity() - self.len; + + // SAFETY: + // - `ptr` is guaranteed to be valid for `self.len` elements + // - `spare_ptr` is pointing one element past the buffer, so it doesn't overlap with `initialized` + unsafe { + let initialized = slice::from_raw_parts_mut(ptr, self.len); + let spare = slice::from_raw_parts_mut(spare_ptr, spare_len); + + (initialized, spare, &mut self.len) + } + } +} + +impl Vec { + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. + /// + /// If `new_len` is greater than `len`, the `Vec` is extended by the + /// difference, with each additional slot filled with `value`. + /// If `new_len` is less than `len`, the `Vec` is simply truncated. + /// + /// This method requires `T` to implement [`Clone`], + /// in order to be able to clone the passed value. + /// If you need more flexibility (or want to rely on [`Default`] instead of + /// [`Clone`]), use [`Vec::resize_with`]. + /// If you only need to resize to a smaller size, use [`Vec::truncate`]. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec!["hello"]; + /// vec.resize(3, "world"); + /// assert_eq!(vec, ["hello", "world", "world"]); + /// + /// let mut vec = vec![1, 2, 3, 4]; + /// vec.resize(2, 0); + /// assert_eq!(vec, [1, 2]); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "vec_resize", since = "1.5.0")] + #[track_caller] + pub fn resize(&mut self, new_len: usize, value: T) { + let len = self.len(); + + if new_len > len { + self.extend_with(new_len - len, value) + } else { + self.truncate(new_len); + } + } + + /// Clones and appends all elements in a slice to the `Vec`. + /// + /// Iterates over the slice `other`, clones each element, and then appends + /// it to this `Vec`. The `other` slice is traversed in-order. + /// + /// Note that this function is same as [`extend`] except that it is + /// specialized to work with slices instead. If and when Rust gets + /// specialization this function will likely be deprecated (but still + /// available). + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1]; + /// vec.extend_from_slice(&[2, 3, 4]); + /// assert_eq!(vec, [1, 2, 3, 4]); + /// ``` + /// + /// [`extend`]: Vec::extend + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "vec_extend_from_slice", since = "1.6.0")] + #[track_caller] + pub fn extend_from_slice(&mut self, other: &[T]) { + self.spec_extend(other.iter()) + } + + /// Given a range `src`, clones a slice of elements in that range and appends it to the end. + /// + /// `src` must be a range that can form a valid subslice of the `Vec`. + /// + /// # Panics + /// + /// Panics if starting index is greater than the end index + /// or if the index is greater than the length of the vector. + /// + /// # Examples + /// + /// ``` + /// let mut characters = vec!['a', 'b', 'c', 'd', 'e']; + /// characters.extend_from_within(2..); + /// assert_eq!(characters, ['a', 'b', 'c', 'd', 'e', 'c', 'd', 'e']); + /// + /// let mut numbers = vec![0, 1, 2, 3, 4]; + /// numbers.extend_from_within(..2); + /// assert_eq!(numbers, [0, 1, 2, 3, 4, 0, 1]); + /// + /// let mut strings = vec![String::from("hello"), String::from("world"), String::from("!")]; + /// strings.extend_from_within(1..=2); + /// assert_eq!(strings, ["hello", "world", "!", "world", "!"]); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "vec_extend_from_within", since = "1.53.0")] + #[track_caller] + pub fn extend_from_within(&mut self, src: R) + where + R: RangeBounds, + { + let range = slice::range(src, ..self.len()); + self.reserve(range.len()); + + // SAFETY: + // - `slice::range` guarantees that the given range is valid for indexing self + unsafe { + self.spec_extend_from_within(range); + } + } +} + +impl Vec<[T; N], A> { + /// Takes a `Vec<[T; N]>` and flattens it into a `Vec`. + /// + /// # Panics + /// + /// Panics if the length of the resulting vector would overflow a `usize`. + /// + /// This is only possible when flattening a vector of arrays of zero-sized + /// types, and thus tends to be irrelevant in practice. If + /// `size_of::() > 0`, this will never panic. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![[1, 2, 3], [4, 5, 6], [7, 8, 9]]; + /// assert_eq!(vec.pop(), Some([7, 8, 9])); + /// + /// let mut flattened = vec.into_flattened(); + /// assert_eq!(flattened.pop(), Some(6)); + /// ``` + #[stable(feature = "slice_flatten", since = "1.80.0")] + pub fn into_flattened(self) -> Vec { + let (ptr, len, cap, alloc) = self.into_raw_parts_with_alloc(); + let (new_len, new_cap) = if T::IS_ZST { + (len.checked_mul(N).expect("vec len overflow"), usize::MAX) + } else { + // SAFETY: + // - `cap * N` cannot overflow because the allocation is already in + // the address space. + // - Each `[T; N]` has `N` valid elements, so there are `len * N` + // valid elements in the allocation. + unsafe { (len.unchecked_mul(N), cap.unchecked_mul(N)) } + }; + // SAFETY: + // - `ptr` was allocated by `self` + // - `ptr` is well-aligned because `[T; N]` has the same alignment as `T`. + // - `new_cap` refers to the same sized allocation as `cap` because + // `new_cap * size_of::()` == `cap * size_of::<[T; N]>()` + // - `len` <= `cap`, so `len * N` <= `cap * N`. + unsafe { Vec::::from_raw_parts_in(ptr.cast(), new_len, new_cap, alloc) } + } +} + +impl Vec { + #[cfg(not(no_global_oom_handling))] + #[track_caller] + /// Extend the vector by `n` clones of value. + fn extend_with(&mut self, n: usize, value: T) { + self.reserve(n); + + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len()); + // Use SetLenOnDrop to work around bug where compiler + // might not realize the store through `ptr` through self.set_len() + // don't alias. + let mut local_len = SetLenOnDrop::new(&mut self.len); + + // Write all elements except the last one + for _ in 1..n { + ptr::write(ptr, value.clone()); + ptr = ptr.add(1); + // Increment the length in every step in case clone() panics + local_len.increment_len(1); + } + + if n > 0 { + // We can write the last element directly without cloning needlessly + ptr::write(ptr, value); + local_len.increment_len(1); + } + + // len set by scope guard + } + } +} + +impl Vec { + /// Removes consecutive repeated elements in the vector according to the + /// [`PartialEq`] trait implementation. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 2, 3, 2]; + /// + /// vec.dedup(); + /// + /// assert_eq!(vec, [1, 2, 3, 2]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn dedup(&mut self) { + self.dedup_by(|a, b| a == b) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Internal methods and functions +//////////////////////////////////////////////////////////////////////////////// + +#[doc(hidden)] +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "vec_from_elem")] +#[track_caller] +pub fn from_elem(elem: T, n: usize) -> Vec { + ::from_elem(elem, n, Global) +} + +#[doc(hidden)] +#[cfg(not(no_global_oom_handling))] +#[unstable(feature = "allocator_api", issue = "32838")] +#[track_caller] +pub fn from_elem_in(elem: T, n: usize, alloc: A) -> Vec { + ::from_elem(elem, n, alloc) +} + +#[cfg(not(no_global_oom_handling))] +trait ExtendFromWithinSpec { + /// # Safety + /// + /// - `src` needs to be valid index + /// - `self.capacity() - self.len()` must be `>= src.len()` + unsafe fn spec_extend_from_within(&mut self, src: Range); +} + +#[cfg(not(no_global_oom_handling))] +impl ExtendFromWithinSpec for Vec { + default unsafe fn spec_extend_from_within(&mut self, src: Range) { + // SAFETY: + // - len is increased only after initializing elements + let (this, spare, len) = unsafe { self.split_at_spare_mut_with_len() }; + + // SAFETY: + // - caller guarantees that src is a valid index + let to_clone = unsafe { this.get_unchecked(src) }; + + iter::zip(to_clone, spare) + .map(|(src, dst)| dst.write(src.clone())) + // Note: + // - Element was just initialized with `MaybeUninit::write`, so it's ok to increase len + // - len is increased after each element to prevent leaks (see issue #82533) + .for_each(|_| *len += 1); + } +} + +#[cfg(not(no_global_oom_handling))] +impl ExtendFromWithinSpec for Vec { + unsafe fn spec_extend_from_within(&mut self, src: Range) { + let count = src.len(); + { + let (init, spare) = self.split_at_spare_mut(); + + // SAFETY: + // - caller guarantees that `src` is a valid index + let source = unsafe { init.get_unchecked(src) }; + + // SAFETY: + // - Both pointers are created from unique slice references (`&mut [_]`) + // so they are valid and do not overlap. + // - Elements are :Copy so it's OK to copy them, without doing + // anything with the original values + // - `count` is equal to the len of `source`, so source is valid for + // `count` reads + // - `.reserve(count)` guarantees that `spare.len() >= count` so spare + // is valid for `count` writes + unsafe { ptr::copy_nonoverlapping(source.as_ptr(), spare.as_mut_ptr() as _, count) }; + } + + // SAFETY: + // - The elements were just initialized by `copy_nonoverlapping` + self.len += count; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Common trait implementations for Vec +//////////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Deref for Vec { + type Target = [T]; + + #[inline] + fn deref(&self) -> &[T] { + self.as_slice() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::DerefMut for Vec { + #[inline] + fn deref_mut(&mut self) -> &mut [T] { + self.as_mut_slice() + } +} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl ops::DerefPure for Vec {} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Vec { + #[cfg(not(test))] + #[track_caller] + fn clone(&self) -> Self { + let alloc = self.allocator().clone(); + <[T]>::to_vec_in(&**self, alloc) + } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is + // required for this method definition, is not available. Instead use the + // `slice::to_vec` function which is only available with cfg(test) + // NB see the slice::hack module in slice.rs for more information + #[cfg(test)] + fn clone(&self) -> Self { + let alloc = self.allocator().clone(); + crate::slice::to_vec(&**self, alloc) + } + + /// Overwrites the contents of `self` with a clone of the contents of `source`. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids reallocation if possible. Additionally, if the element type + /// `T` overrides `clone_from()`, this will reuse the resources of `self`'s + /// elements as well. + /// + /// # Examples + /// + /// ``` + /// let x = vec![5, 6, 7]; + /// let mut y = vec![8, 9, 10]; + /// let yp: *const i32 = y.as_ptr(); + /// + /// y.clone_from(&x); + /// + /// // The value is the same + /// assert_eq!(x, y); + /// + /// // And no reallocation occurred + /// assert_eq!(yp, y.as_ptr()); + /// ``` + #[track_caller] + fn clone_from(&mut self, source: &Self) { + crate::slice::SpecCloneIntoVec::clone_into(source.as_slice(), self); + } +} + +/// The hash of a vector is the same as that of the corresponding slice, +/// as required by the `core::borrow::Borrow` implementation. +/// +/// ``` +/// use std::hash::BuildHasher; +/// +/// let b = std::hash::RandomState::new(); +/// let v: Vec = vec![0xa8, 0x3c, 0x09]; +/// let s: &[u8] = &[0xa8, 0x3c, 0x09]; +/// assert_eq!(b.hash_one(v), b.hash_one(s)); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Vec { + #[inline] + fn hash(&self, state: &mut H) { + Hash::hash(&**self, state) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "vector indices are of type `usize` or ranges of `usize`", + label = "vector indices are of type `usize` or ranges of `usize`" +)] +impl, A: Allocator> Index for Vec { + type Output = I::Output; + + #[inline] + fn index(&self, index: I) -> &Self::Output { + Index::index(&**self, index) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "vector indices are of type `usize` or ranges of `usize`", + label = "vector indices are of type `usize` or ranges of `usize`" +)] +impl, A: Allocator> IndexMut for Vec { + #[inline] + fn index_mut(&mut self, index: I) -> &mut Self::Output { + IndexMut::index_mut(&mut **self, index) + } +} + +/// Collects an iterator into a Vec, commonly called via [`Iterator::collect()`] +/// +/// # Allocation behavior +/// +/// In general `Vec` does not guarantee any particular growth or allocation strategy. +/// That also applies to this trait impl. +/// +/// **Note:** This section covers implementation details and is therefore exempt from +/// stability guarantees. +/// +/// Vec may use any or none of the following strategies, +/// depending on the supplied iterator: +/// +/// * preallocate based on [`Iterator::size_hint()`] +/// * and panic if the number of items is outside the provided lower/upper bounds +/// * use an amortized growth strategy similar to `pushing` one item at a time +/// * perform the iteration in-place on the original allocation backing the iterator +/// +/// The last case warrants some attention. It is an optimization that in many cases reduces peak memory +/// consumption and improves cache locality. But when big, short-lived allocations are created, +/// only a small fraction of their items get collected, no further use is made of the spare capacity +/// and the resulting `Vec` is moved into a longer-lived structure, then this can lead to the large +/// allocations having their lifetimes unnecessarily extended which can result in increased memory +/// footprint. +/// +/// In cases where this is an issue, the excess capacity can be discarded with [`Vec::shrink_to()`], +/// [`Vec::shrink_to_fit()`] or by collecting into [`Box<[T]>`][owned slice] instead, which additionally reduces +/// the size of the long-lived struct. +/// +/// [owned slice]: Box +/// +/// ```rust +/// # use std::sync::Mutex; +/// static LONG_LIVED: Mutex>> = Mutex::new(Vec::new()); +/// +/// for i in 0..10 { +/// let big_temporary: Vec = (0..1024).collect(); +/// // discard most items +/// let mut result: Vec<_> = big_temporary.into_iter().filter(|i| i % 100 == 0).collect(); +/// // without this a lot of unused capacity might be moved into the global +/// result.shrink_to_fit(); +/// LONG_LIVED.lock().unwrap().push(result); +/// } +/// ``` +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for Vec { + #[inline] + #[track_caller] + fn from_iter>(iter: I) -> Vec { + >::from_iter(iter.into_iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for Vec { + type Item = T; + type IntoIter = IntoIter; + + /// Creates a consuming iterator, that is, one that moves each value out of + /// the vector (from start to end). The vector cannot be used after calling + /// this. + /// + /// # Examples + /// + /// ``` + /// let v = vec!["a".to_string(), "b".to_string()]; + /// let mut v_iter = v.into_iter(); + /// + /// let first_element: Option = v_iter.next(); + /// + /// assert_eq!(first_element, Some("a".to_string())); + /// assert_eq!(v_iter.next(), Some("b".to_string())); + /// assert_eq!(v_iter.next(), None); + /// ``` + #[inline] + fn into_iter(self) -> Self::IntoIter { + unsafe { + let me = ManuallyDrop::new(self); + let alloc = ManuallyDrop::new(ptr::read(me.allocator())); + let buf = me.buf.non_null(); + let begin = buf.as_ptr(); + let end = if T::IS_ZST { + begin.wrapping_byte_add(me.len()) + } else { + begin.add(me.len()) as *const T + }; + let cap = me.buf.capacity(); + IntoIter { buf, phantom: PhantomData, cap, alloc, ptr: buf, end } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, A: Allocator> IntoIterator for &'a Vec { + type Item = &'a T; + type IntoIter = slice::Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec { + type Item = &'a mut T; + type IntoIter = slice::IterMut<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for Vec { + #[inline] + #[track_caller] + fn extend>(&mut self, iter: I) { + >::spec_extend(self, iter.into_iter()) + } + + #[inline] + #[track_caller] + fn extend_one(&mut self, item: T) { + self.push(item); + } + + #[inline] + #[track_caller] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } + + #[inline] + unsafe fn extend_one_unchecked(&mut self, item: T) { + // SAFETY: Our preconditions ensure the space has been reserved, and `extend_reserve` is implemented correctly. + unsafe { + let len = self.len(); + ptr::write(self.as_mut_ptr().add(len), item); + self.set_len(len + 1); + } + } +} + +impl Vec { + // leaf method to which various SpecFrom/SpecExtend implementations delegate when + // they have no further optimizations to apply + #[cfg(not(no_global_oom_handling))] + #[track_caller] + fn extend_desugared>(&mut self, mut iterator: I) { + // This is the case for a general iterator. + // + // This function should be the moral equivalent of: + // + // for item in iterator { + // self.push(item); + // } + while let Some(element) = iterator.next() { + let len = self.len(); + if len == self.capacity() { + let (lower, _) = iterator.size_hint(); + self.reserve(lower.saturating_add(1)); + } + unsafe { + ptr::write(self.as_mut_ptr().add(len), element); + // Since next() executes user code which can panic we have to bump the length + // after each step. + // NB can't overflow since we would have had to alloc the address space + self.set_len(len + 1); + } + } + } + + // specific extend for `TrustedLen` iterators, called both by the specializations + // and internal places where resolving specialization makes compilation slower + #[cfg(not(no_global_oom_handling))] + #[track_caller] + fn extend_trusted(&mut self, iterator: impl iter::TrustedLen) { + let (low, high) = iterator.size_hint(); + if let Some(additional) = high { + debug_assert_eq!( + low, + additional, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + self.reserve(additional); + unsafe { + let ptr = self.as_mut_ptr(); + let mut local_len = SetLenOnDrop::new(&mut self.len); + iterator.for_each(move |element| { + ptr::write(ptr.add(local_len.current_len()), element); + // Since the loop executes user code which can panic we have to update + // the length every step to correctly drop what we've written. + // NB can't overflow since we would have had to alloc the address space + local_len.increment_len(1); + }); + } + } else { + // Per TrustedLen contract a `None` upper bound means that the iterator length + // truly exceeds usize::MAX, which would eventually lead to a capacity overflow anyway. + // Since the other branch already panics eagerly (via `reserve()`) we do the same here. + // This avoids additional codegen for a fallback code path which would eventually + // panic anyway. + panic!("capacity overflow"); + } + } + + /// Creates a splicing iterator that replaces the specified range in the vector + /// with the given `replace_with` iterator and yields the removed items. + /// `replace_with` does not need to be the same length as `range`. + /// + /// `range` is removed even if the iterator is not consumed until the end. + /// + /// It is unspecified how many elements are removed from the vector + /// if the `Splice` value is leaked. + /// + /// The input iterator `replace_with` is only consumed when the `Splice` value is dropped. + /// + /// This is optimal if: + /// + /// * The tail (elements in the vector after `range`) is empty, + /// * or `replace_with` yields fewer or equal elements than `range`’s length + /// * or the lower bound of its `size_hint()` is exact. + /// + /// Otherwise, a temporary vector is allocated and the tail is moved twice. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3, 4]; + /// let new = [7, 8, 9]; + /// let u: Vec<_> = v.splice(1..3, new).collect(); + /// assert_eq!(v, &[1, 7, 8, 9, 4]); + /// assert_eq!(u, &[2, 3]); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "vec_splice", since = "1.21.0")] + pub fn splice(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A> + where + R: RangeBounds, + I: IntoIterator, + { + Splice { drain: self.drain(range), replace_with: replace_with.into_iter() } + } + + /// Creates an iterator which uses a closure to determine if an element should be removed. + /// + /// If the closure returns true, then the element is removed and yielded. + /// If the closure returns false, the element will remain in the vector and will not be yielded + /// by the iterator. + /// + /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating + /// or the iteration short-circuits, then the remaining elements will be retained. + /// Use [`retain`] with a negated predicate if you do not need the returned iterator. + /// + /// [`retain`]: Vec::retain + /// + /// Using this method is equivalent to the following code: + /// + /// ``` + /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 }; + /// # let mut vec = vec![1, 2, 3, 4, 5, 6]; + /// let mut i = 0; + /// while i < vec.len() { + /// if some_predicate(&mut vec[i]) { + /// let val = vec.remove(i); + /// // your code here + /// } else { + /// i += 1; + /// } + /// } + /// + /// # assert_eq!(vec, vec![1, 4, 5]); + /// ``` + /// + /// But `extract_if` is easier to use. `extract_if` is also more efficient, + /// because it can backshift the elements of the array in bulk. + /// + /// Note that `extract_if` also lets you mutate every element in the filter closure, + /// regardless of whether you choose to keep or remove it. + /// + /// # Examples + /// + /// Splitting an array into evens and odds, reusing the original allocation: + /// + /// ``` + /// #![feature(extract_if)] + /// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; + /// + /// let evens = numbers.extract_if(|x| *x % 2 == 0).collect::>(); + /// let odds = numbers; + /// + /// assert_eq!(evens, vec![2, 4, 6, 8, 14]); + /// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]); + /// ``` + #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] + pub fn extract_if(&mut self, filter: F) -> ExtractIf<'_, T, F, A> + where + F: FnMut(&mut T) -> bool, + { + let old_len = self.len(); + + // Guard against us getting leaked (leak amplification) + unsafe { + self.set_len(0); + } + + ExtractIf { vec: self, idx: 0, del: 0, old_len, pred: filter } + } +} + +/// Extend implementation that copies elements out of references before pushing them onto the Vec. +/// +/// This implementation is specialized for slice iterators, where it uses [`copy_from_slice`] to +/// append the entire slice at once. +/// +/// [`copy_from_slice`]: slice::copy_from_slice +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, T: Copy + 'a, A: Allocator> Extend<&'a T> for Vec { + #[track_caller] + fn extend>(&mut self, iter: I) { + self.spec_extend(iter.into_iter()) + } + + #[inline] + #[track_caller] + fn extend_one(&mut self, &item: &'a T) { + self.push(item); + } + + #[inline] + #[track_caller] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } + + #[inline] + unsafe fn extend_one_unchecked(&mut self, &item: &'a T) { + // SAFETY: Our preconditions ensure the space has been reserved, and `extend_reserve` is implemented correctly. + unsafe { + let len = self.len(); + ptr::write(self.as_mut_ptr().add(len), item); + self.set_len(len + 1); + } + } +} + +/// Implements comparison of vectors, [lexicographically](Ord#lexicographical-comparison). +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd> for Vec +where + T: PartialOrd, + A1: Allocator, + A2: Allocator, +{ + #[inline] + fn partial_cmp(&self, other: &Vec) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Vec {} + +/// Implements ordering of vectors, [lexicographically](Ord#lexicographical-comparison). +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Vec { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec { + fn drop(&mut self) { + unsafe { + // use drop for [T] + // use a raw slice to refer to the elements of the vector as weakest necessary type; + // could avoid questions of validity in certain cases + ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.len)) + } + // RawVec handles deallocation + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Vec { + /// Creates an empty `Vec`. + /// + /// The vector will not allocate until elements are pushed onto it. + fn default() -> Vec { + Vec::new() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Vec { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef> for Vec { + fn as_ref(&self) -> &Vec { + self + } +} + +#[stable(feature = "vec_as_mut", since = "1.5.0")] +impl AsMut> for Vec { + fn as_mut(&mut self) -> &mut Vec { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef<[T]> for Vec { + fn as_ref(&self) -> &[T] { + self + } +} + +#[stable(feature = "vec_as_mut", since = "1.5.0")] +impl AsMut<[T]> for Vec { + fn as_mut(&mut self) -> &mut [T] { + self + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl From<&[T]> for Vec { + /// Allocates a `Vec` and fills it by cloning `s`'s items. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from(&[1, 2, 3][..]), vec![1, 2, 3]); + /// ``` + #[cfg(not(test))] + #[track_caller] + fn from(s: &[T]) -> Vec { + s.to_vec() + } + #[cfg(test)] + fn from(s: &[T]) -> Vec { + crate::slice::to_vec(s, Global) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "vec_from_mut", since = "1.19.0")] +impl From<&mut [T]> for Vec { + /// Allocates a `Vec` and fills it by cloning `s`'s items. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from(&mut [1, 2, 3][..]), vec![1, 2, 3]); + /// ``` + #[cfg(not(test))] + #[track_caller] + fn from(s: &mut [T]) -> Vec { + s.to_vec() + } + #[cfg(test)] + fn from(s: &mut [T]) -> Vec { + crate::slice::to_vec(s, Global) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "vec_from_array_ref", since = "1.74.0")] +impl From<&[T; N]> for Vec { + /// Allocates a `Vec` and fills it by cloning `s`'s items. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from(&[1, 2, 3]), vec![1, 2, 3]); + /// ``` + #[track_caller] + fn from(s: &[T; N]) -> Vec { + Self::from(s.as_slice()) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "vec_from_array_ref", since = "1.74.0")] +impl From<&mut [T; N]> for Vec { + /// Allocates a `Vec` and fills it by cloning `s`'s items. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]); + /// ``` + #[track_caller] + fn from(s: &mut [T; N]) -> Vec { + Self::from(s.as_mut_slice()) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "vec_from_array", since = "1.44.0")] +impl From<[T; N]> for Vec { + /// Allocates a `Vec` and moves `s`'s items into it. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from([1, 2, 3]), vec![1, 2, 3]); + /// ``` + #[cfg(not(test))] + #[track_caller] + fn from(s: [T; N]) -> Vec { + <[T]>::into_vec(Box::new(s)) + } + + #[cfg(test)] + fn from(s: [T; N]) -> Vec { + crate::slice::into_vec(Box::new(s)) + } +} + +#[stable(feature = "vec_from_cow_slice", since = "1.14.0")] +impl<'a, T> From> for Vec +where + [T]: ToOwned>, +{ + /// Converts a clone-on-write slice into a vector. + /// + /// If `s` already owns a `Vec`, it will be returned directly. + /// If `s` is borrowing a slice, a new `Vec` will be allocated and + /// filled by cloning `s`'s items into it. + /// + /// # Examples + /// + /// ``` + /// # use std::borrow::Cow; + /// let o: Cow<'_, [i32]> = Cow::Owned(vec![1, 2, 3]); + /// let b: Cow<'_, [i32]> = Cow::Borrowed(&[1, 2, 3]); + /// assert_eq!(Vec::from(o), Vec::from(b)); + /// ``` + #[track_caller] + fn from(s: Cow<'a, [T]>) -> Vec { + s.into_owned() + } +} + +// note: test pulls in std, which causes errors here +#[cfg(not(test))] +#[stable(feature = "vec_from_box", since = "1.18.0")] +impl From> for Vec { + /// Converts a boxed slice into a vector by transferring ownership of + /// the existing heap allocation. + /// + /// # Examples + /// + /// ``` + /// let b: Box<[i32]> = vec![1, 2, 3].into_boxed_slice(); + /// assert_eq!(Vec::from(b), vec![1, 2, 3]); + /// ``` + fn from(s: Box<[T], A>) -> Self { + s.into_vec() + } +} + +// note: test pulls in std, which causes errors here +#[cfg(not(no_global_oom_handling))] +#[cfg(not(test))] +#[stable(feature = "box_from_vec", since = "1.20.0")] +impl From> for Box<[T], A> { + /// Converts a vector into a boxed slice. + /// + /// Before doing the conversion, this method discards excess capacity like [`Vec::shrink_to_fit`]. + /// + /// [owned slice]: Box + /// [`Vec::shrink_to_fit`]: Vec::shrink_to_fit + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Box::from(vec![1, 2, 3]), vec![1, 2, 3].into_boxed_slice()); + /// ``` + /// + /// Any excess capacity is removed: + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3]); + /// + /// assert_eq!(Box::from(vec), vec![1, 2, 3].into_boxed_slice()); + /// ``` + #[track_caller] + fn from(v: Vec) -> Self { + v.into_boxed_slice() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl From<&str> for Vec { + /// Allocates a `Vec` and fills it with a UTF-8 string. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from("123"), vec![b'1', b'2', b'3']); + /// ``` + #[track_caller] + fn from(s: &str) -> Vec { + From::from(s.as_bytes()) + } +} + +#[stable(feature = "array_try_from_vec", since = "1.48.0")] +impl TryFrom> for [T; N] { + type Error = Vec; + + /// Gets the entire contents of the `Vec` as an array, + /// if its size exactly matches that of the requested array. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(vec![1, 2, 3].try_into(), Ok([1, 2, 3])); + /// assert_eq!(>::new().try_into(), Ok([])); + /// ``` + /// + /// If the length doesn't match, the input comes back in `Err`: + /// ``` + /// let r: Result<[i32; 4], _> = (0..10).collect::>().try_into(); + /// assert_eq!(r, Err(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); + /// ``` + /// + /// If you're fine with just getting a prefix of the `Vec`, + /// you can call [`.truncate(N)`](Vec::truncate) first. + /// ``` + /// let mut v = String::from("hello world").into_bytes(); + /// v.sort(); + /// v.truncate(2); + /// let [a, b]: [_; 2] = v.try_into().unwrap(); + /// assert_eq!(a, b' '); + /// assert_eq!(b, b'd'); + /// ``` + fn try_from(mut vec: Vec) -> Result<[T; N], Vec> { + if vec.len() != N { + return Err(vec); + } + + // SAFETY: `.set_len(0)` is always sound. + unsafe { vec.set_len(0) }; + + // SAFETY: A `Vec`'s pointer is always aligned properly, and + // the alignment the array needs is the same as the items. + // We checked earlier that we have sufficient items. + // The items will not double-drop as the `set_len` + // tells the `Vec` not to also drop them. + let array = unsafe { ptr::read(vec.as_ptr() as *const [T; N]) }; + Ok(array) + } +} diff --git a/CoqOfRust/alloc/vec/partial_eq.rs b/CoqOfRust/alloc/vec/partial_eq.rs new file mode 100644 index 000000000..5e620c4b2 --- /dev/null +++ b/CoqOfRust/alloc/vec/partial_eq.rs @@ -0,0 +1,46 @@ +use super::Vec; +use crate::alloc::Allocator; +#[cfg(not(no_global_oom_handling))] +use crate::borrow::Cow; + +macro_rules! __impl_slice_eq1 { + ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => { + #[$stability] + impl PartialEq<$rhs> for $lhs + where + T: PartialEq, + $($ty: $bound)? + { + #[inline] + fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] } + } + } +} + +__impl_slice_eq1! { [A1: Allocator, A2: Allocator] Vec, Vec, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, &[U], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, &mut [U], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] &[T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [A: Allocator] &mut [T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, [U], #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } +__impl_slice_eq1! { [A: Allocator] [T], Vec, #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } +#[cfg(not(no_global_oom_handling))] +__impl_slice_eq1! { [A: Allocator] Cow<'_, [T]>, Vec where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +#[cfg(not(no_global_oom_handling))] +__impl_slice_eq1! { [] Cow<'_, [T]>, &[U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +#[cfg(not(no_global_oom_handling))] +__impl_slice_eq1! { [] Cow<'_, [T]>, &mut [U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, [U; N], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, &[U; N], #[stable(feature = "rust1", since = "1.0.0")] } + +// NOTE: some less important impls are omitted to reduce code bloat +// FIXME(Centril): Reconsider this? +//__impl_slice_eq1! { [const N: usize] Vec, &mut [B; N], } +//__impl_slice_eq1! { [const N: usize] [A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] &[A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] &mut [A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], } diff --git a/CoqOfRust/alloc/vec/set_len_on_drop.rs b/CoqOfRust/alloc/vec/set_len_on_drop.rs new file mode 100644 index 000000000..6ce5a3a9f --- /dev/null +++ b/CoqOfRust/alloc/vec/set_len_on_drop.rs @@ -0,0 +1,33 @@ +// Set the length of the vec when the `SetLenOnDrop` value goes out of scope. +// +// The idea is: The length field in SetLenOnDrop is a local variable +// that the optimizer will see does not alias with any stores through the Vec's data +// pointer. This is a workaround for alias analysis issue #32155 +pub(super) struct SetLenOnDrop<'a> { + len: &'a mut usize, + local_len: usize, +} + +impl<'a> SetLenOnDrop<'a> { + #[inline] + pub(super) fn new(len: &'a mut usize) -> Self { + SetLenOnDrop { local_len: *len, len } + } + + #[inline] + pub(super) fn increment_len(&mut self, increment: usize) { + self.local_len += increment; + } + + #[inline] + pub(super) fn current_len(&self) -> usize { + self.local_len + } +} + +impl Drop for SetLenOnDrop<'_> { + #[inline] + fn drop(&mut self) { + *self.len = self.local_len; + } +} diff --git a/CoqOfRust/alloc/vec/spec_extend.rs b/CoqOfRust/alloc/vec/spec_extend.rs new file mode 100644 index 000000000..b98db6690 --- /dev/null +++ b/CoqOfRust/alloc/vec/spec_extend.rs @@ -0,0 +1,63 @@ +use core::iter::TrustedLen; +use core::slice::{self}; + +use super::{IntoIter, Vec}; +use crate::alloc::Allocator; + +// Specialization trait used for Vec::extend +pub(super) trait SpecExtend { + #[track_caller] + fn spec_extend(&mut self, iter: I); +} + +impl SpecExtend for Vec +where + I: Iterator, +{ + #[track_caller] + default fn spec_extend(&mut self, iter: I) { + self.extend_desugared(iter) + } +} + +impl SpecExtend for Vec +where + I: TrustedLen, +{ + #[track_caller] + default fn spec_extend(&mut self, iterator: I) { + self.extend_trusted(iterator) + } +} + +impl SpecExtend> for Vec { + #[track_caller] + fn spec_extend(&mut self, mut iterator: IntoIter) { + unsafe { + self.append_elements(iterator.as_slice() as _); + } + iterator.forget_remaining_elements(); + } +} + +impl<'a, T: 'a, I, A: Allocator> SpecExtend<&'a T, I> for Vec +where + I: Iterator, + T: Clone, +{ + #[track_caller] + default fn spec_extend(&mut self, iterator: I) { + self.spec_extend(iterator.cloned()) + } +} + +impl<'a, T: 'a, A: Allocator> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec +where + T: Copy, +{ + #[track_caller] + fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { + let slice = iterator.as_slice(); + unsafe { self.append_elements(slice) }; + } +} diff --git a/CoqOfRust/alloc/vec/spec_from_elem.rs b/CoqOfRust/alloc/vec/spec_from_elem.rs new file mode 100644 index 000000000..6c7b4d89f --- /dev/null +++ b/CoqOfRust/alloc/vec/spec_from_elem.rs @@ -0,0 +1,79 @@ +use core::ptr; + +use super::{IsZero, Vec}; +use crate::alloc::Allocator; +use crate::raw_vec::RawVec; + +// Specialization trait used for Vec::from_elem +pub(super) trait SpecFromElem: Sized { + fn from_elem(elem: Self, n: usize, alloc: A) -> Vec; +} + +impl SpecFromElem for T { + #[track_caller] + default fn from_elem(elem: Self, n: usize, alloc: A) -> Vec { + let mut v = Vec::with_capacity_in(n, alloc); + v.extend_with(n, elem); + v + } +} + +impl SpecFromElem for T { + #[inline] + #[track_caller] + default fn from_elem(elem: T, n: usize, alloc: A) -> Vec { + if elem.is_zero() { + return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; + } + let mut v = Vec::with_capacity_in(n, alloc); + v.extend_with(n, elem); + v + } +} + +impl SpecFromElem for i8 { + #[inline] + #[track_caller] + fn from_elem(elem: i8, n: usize, alloc: A) -> Vec { + if elem == 0 { + return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; + } + let mut v = Vec::with_capacity_in(n, alloc); + unsafe { + ptr::write_bytes(v.as_mut_ptr(), elem as u8, n); + v.set_len(n); + } + v + } +} + +impl SpecFromElem for u8 { + #[inline] + #[track_caller] + fn from_elem(elem: u8, n: usize, alloc: A) -> Vec { + if elem == 0 { + return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; + } + let mut v = Vec::with_capacity_in(n, alloc); + unsafe { + ptr::write_bytes(v.as_mut_ptr(), elem, n); + v.set_len(n); + } + v + } +} + +// A better way would be to implement this for all ZSTs which are `Copy` and have trivial `Clone` +// but the latter cannot be detected currently +impl SpecFromElem for () { + #[inline] + fn from_elem(_elem: (), n: usize, alloc: A) -> Vec<(), A> { + let mut v = Vec::with_capacity_in(n, alloc); + // SAFETY: the capacity has just been set to `n` + // and `()` is a ZST with trivial `Clone` implementation + unsafe { + v.set_len(n); + } + v + } +} diff --git a/CoqOfRust/alloc/vec/spec_from_iter.rs b/CoqOfRust/alloc/vec/spec_from_iter.rs new file mode 100644 index 000000000..ad7688e1c --- /dev/null +++ b/CoqOfRust/alloc/vec/spec_from_iter.rs @@ -0,0 +1,66 @@ +use core::mem::ManuallyDrop; +use core::ptr::{self}; + +use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec}; + +/// Specialization trait used for Vec::from_iter +/// +/// ## The delegation graph: +/// +/// ```text +/// +-------------+ +/// |FromIterator | +/// +-+-----------+ +/// | +/// v +/// +-+---------------------------------+ +---------------------+ +/// |SpecFromIter +---->+SpecFromIterNested | +/// |where I: | | |where I: | +/// | Iterator (default)------------+ | | Iterator (default) | +/// | vec::IntoIter | | | TrustedLen | +/// | InPlaceCollect--(fallback to)-+ | +---------------------+ +/// +-----------------------------------+ +/// ``` +pub(super) trait SpecFromIter { + fn from_iter(iter: I) -> Self; +} + +impl SpecFromIter for Vec +where + I: Iterator, +{ + #[track_caller] + default fn from_iter(iterator: I) -> Self { + SpecFromIterNested::from_iter(iterator) + } +} + +impl SpecFromIter> for Vec { + #[track_caller] + fn from_iter(iterator: IntoIter) -> Self { + // A common case is passing a vector into a function which immediately + // re-collects into a vector. We can short circuit this if the IntoIter + // has not been advanced at all. + // When it has been advanced We can also reuse the memory and move the data to the front. + // But we only do so when the resulting Vec wouldn't have more unused capacity + // than creating it through the generic FromIterator implementation would. That limitation + // is not strictly necessary as Vec's allocation behavior is intentionally unspecified. + // But it is a conservative choice. + let has_advanced = iterator.buf != iterator.ptr; + if !has_advanced || iterator.len() >= iterator.cap / 2 { + unsafe { + let it = ManuallyDrop::new(iterator); + if has_advanced { + ptr::copy(it.ptr.as_ptr(), it.buf.as_ptr(), it.len()); + } + return Vec::from_parts(it.buf, it.len(), it.cap); + } + } + + let mut vec = Vec::new(); + // must delegate to spec_extend() since extend() itself delegates + // to spec_from for empty Vecs + vec.spec_extend(iterator); + vec + } +} diff --git a/CoqOfRust/alloc/vec/spec_from_iter_nested.rs b/CoqOfRust/alloc/vec/spec_from_iter_nested.rs new file mode 100644 index 000000000..22eed2387 --- /dev/null +++ b/CoqOfRust/alloc/vec/spec_from_iter_nested.rs @@ -0,0 +1,65 @@ +use core::iter::TrustedLen; +use core::{cmp, ptr}; + +use super::{SpecExtend, Vec}; +use crate::raw_vec::RawVec; + +/// Another specialization trait for Vec::from_iter +/// necessary to manually prioritize overlapping specializations +/// see [`SpecFromIter`](super::SpecFromIter) for details. +pub(super) trait SpecFromIterNested { + fn from_iter(iter: I) -> Self; +} + +impl SpecFromIterNested for Vec +where + I: Iterator, +{ + #[track_caller] + default fn from_iter(mut iterator: I) -> Self { + // Unroll the first iteration, as the vector is going to be + // expanded on this iteration in every case when the iterable is not + // empty, but the loop in extend_desugared() is not going to see the + // vector being full in the few subsequent loop iterations. + // So we get better branch prediction. + let mut vector = match iterator.next() { + None => return Vec::new(), + Some(element) => { + let (lower, _) = iterator.size_hint(); + let initial_capacity = + cmp::max(RawVec::::MIN_NON_ZERO_CAP, lower.saturating_add(1)); + let mut vector = Vec::with_capacity(initial_capacity); + unsafe { + // SAFETY: We requested capacity at least 1 + ptr::write(vector.as_mut_ptr(), element); + vector.set_len(1); + } + vector + } + }; + // must delegate to spec_extend() since extend() itself delegates + // to spec_from for empty Vecs + as SpecExtend>::spec_extend(&mut vector, iterator); + vector + } +} + +impl SpecFromIterNested for Vec +where + I: TrustedLen, +{ + #[track_caller] + fn from_iter(iterator: I) -> Self { + let mut vector = match iterator.size_hint() { + (_, Some(upper)) => Vec::with_capacity(upper), + // TrustedLen contract guarantees that `size_hint() == (_, None)` means that there + // are more than `usize::MAX` elements. + // Since the previous branch would eagerly panic if the capacity is too large + // (via `with_capacity`) we do the same here. + _ => panic!("capacity overflow"), + }; + // reuse extend specialization for TrustedLen + vector.spec_extend(iterator); + vector + } +} diff --git a/CoqOfRust/alloc/vec/splice.rs b/CoqOfRust/alloc/vec/splice.rs new file mode 100644 index 000000000..ca5cb17f8 --- /dev/null +++ b/CoqOfRust/alloc/vec/splice.rs @@ -0,0 +1,141 @@ +use core::ptr::{self}; +use core::slice::{self}; + +use super::{Drain, Vec}; +use crate::alloc::{Allocator, Global}; + +/// A splicing iterator for `Vec`. +/// +/// This struct is created by [`Vec::splice()`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// let mut v = vec![0, 1, 2]; +/// let new = [7, 8]; +/// let iter: std::vec::Splice<'_, _> = v.splice(1.., new); +/// ``` +#[derive(Debug)] +#[stable(feature = "vec_splice", since = "1.21.0")] +pub struct Splice< + 'a, + I: Iterator + 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, +> { + pub(super) drain: Drain<'a, I::Item, A>, + pub(super) replace_with: I, +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl Iterator for Splice<'_, I, A> { + type Item = I::Item; + + fn next(&mut self) -> Option { + self.drain.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.drain.size_hint() + } +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl DoubleEndedIterator for Splice<'_, I, A> { + fn next_back(&mut self) -> Option { + self.drain.next_back() + } +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl ExactSizeIterator for Splice<'_, I, A> {} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl Drop for Splice<'_, I, A> { + #[track_caller] + fn drop(&mut self) { + self.drain.by_ref().for_each(drop); + // At this point draining is done and the only remaining tasks are splicing + // and moving things into the final place. + // Which means we can replace the slice::Iter with pointers that won't point to deallocated + // memory, so that Drain::drop is still allowed to call iter.len(), otherwise it would break + // the ptr.sub_ptr contract. + self.drain.iter = (&[]).iter(); + + unsafe { + if self.drain.tail_len == 0 { + self.drain.vec.as_mut().extend(self.replace_with.by_ref()); + return; + } + + // First fill the range left by drain(). + if !self.drain.fill(&mut self.replace_with) { + return; + } + + // There may be more elements. Use the lower bound as an estimate. + // FIXME: Is the upper bound a better guess? Or something else? + let (lower_bound, _upper_bound) = self.replace_with.size_hint(); + if lower_bound > 0 { + self.drain.move_tail(lower_bound); + if !self.drain.fill(&mut self.replace_with) { + return; + } + } + + // Collect any remaining elements. + // This is a zero-length vector which does not allocate if `lower_bound` was exact. + let mut collected = self.replace_with.by_ref().collect::>().into_iter(); + // Now we have an exact count. + if collected.len() > 0 { + self.drain.move_tail(collected.len()); + let filled = self.drain.fill(&mut collected); + debug_assert!(filled); + debug_assert_eq!(collected.len(), 0); + } + } + // Let `Drain::drop` move the tail back if necessary and restore `vec.len`. + } +} + +/// Private helper methods for `Splice::drop` +impl Drain<'_, T, A> { + /// The range from `self.vec.len` to `self.tail_start` contains elements + /// that have been moved out. + /// Fill that range as much as possible with new elements from the `replace_with` iterator. + /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.) + unsafe fn fill>(&mut self, replace_with: &mut I) -> bool { + let vec = unsafe { self.vec.as_mut() }; + let range_start = vec.len; + let range_end = self.tail_start; + let range_slice = unsafe { + slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start) + }; + + for place in range_slice { + if let Some(new_item) = replace_with.next() { + unsafe { ptr::write(place, new_item) }; + vec.len += 1; + } else { + return false; + } + } + true + } + + /// Makes room for inserting more elements before the tail. + #[track_caller] + unsafe fn move_tail(&mut self, additional: usize) { + let vec = unsafe { self.vec.as_mut() }; + let len = self.tail_start + self.tail_len; + vec.buf.reserve(len, additional); + + let new_tail_start = self.tail_start + additional; + unsafe { + let src = vec.as_ptr().add(self.tail_start); + let dst = vec.as_mut_ptr().add(new_tail_start); + ptr::copy(src, dst, self.tail_len); + } + self.tail_start = new_tail_start; + } +} diff --git a/CoqOfRust/core/alloc/global.rs b/CoqOfRust/core/alloc/global.rs new file mode 100644 index 000000000..8f48af245 --- /dev/null +++ b/CoqOfRust/core/alloc/global.rs @@ -0,0 +1,277 @@ +use crate::alloc::Layout; +use crate::{cmp, ptr}; + +/// A memory allocator that can be registered as the standard library’s default +/// through the `#[global_allocator]` attribute. +/// +/// Some of the methods require that a memory block be *currently +/// allocated* via an allocator. This means that: +/// +/// * the starting address for that memory block was previously +/// returned by a previous call to an allocation method +/// such as `alloc`, and +/// +/// * the memory block has not been subsequently deallocated, where +/// blocks are deallocated either by being passed to a deallocation +/// method such as `dealloc` or by being +/// passed to a reallocation method that returns a non-null pointer. +/// +/// +/// # Example +/// +/// ``` +/// use std::alloc::{GlobalAlloc, Layout}; +/// use std::cell::UnsafeCell; +/// use std::ptr::null_mut; +/// use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; +/// +/// const ARENA_SIZE: usize = 128 * 1024; +/// const MAX_SUPPORTED_ALIGN: usize = 4096; +/// #[repr(C, align(4096))] // 4096 == MAX_SUPPORTED_ALIGN +/// struct SimpleAllocator { +/// arena: UnsafeCell<[u8; ARENA_SIZE]>, +/// remaining: AtomicUsize, // we allocate from the top, counting down +/// } +/// +/// #[global_allocator] +/// static ALLOCATOR: SimpleAllocator = SimpleAllocator { +/// arena: UnsafeCell::new([0x55; ARENA_SIZE]), +/// remaining: AtomicUsize::new(ARENA_SIZE), +/// }; +/// +/// unsafe impl Sync for SimpleAllocator {} +/// +/// unsafe impl GlobalAlloc for SimpleAllocator { +/// unsafe fn alloc(&self, layout: Layout) -> *mut u8 { +/// let size = layout.size(); +/// let align = layout.align(); +/// +/// // `Layout` contract forbids making a `Layout` with align=0, or align not power of 2. +/// // So we can safely use a mask to ensure alignment without worrying about UB. +/// let align_mask_to_round_down = !(align - 1); +/// +/// if align > MAX_SUPPORTED_ALIGN { +/// return null_mut(); +/// } +/// +/// let mut allocated = 0; +/// if self +/// .remaining +/// .fetch_update(Relaxed, Relaxed, |mut remaining| { +/// if size > remaining { +/// return None; +/// } +/// remaining -= size; +/// remaining &= align_mask_to_round_down; +/// allocated = remaining; +/// Some(remaining) +/// }) +/// .is_err() +/// { +/// return null_mut(); +/// }; +/// self.arena.get().cast::().add(allocated) +/// } +/// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} +/// } +/// +/// fn main() { +/// let _s = format!("allocating a string!"); +/// let currently = ALLOCATOR.remaining.load(Relaxed); +/// println!("allocated so far: {}", ARENA_SIZE - currently); +/// } +/// ``` +/// +/// # Safety +/// +/// The `GlobalAlloc` trait is an `unsafe` trait for a number of reasons, and +/// implementors must ensure that they adhere to these contracts: +/// +/// * It's undefined behavior if global allocators unwind. This restriction may +/// be lifted in the future, but currently a panic from any of these +/// functions may lead to memory unsafety. +/// +/// * `Layout` queries and calculations in general must be correct. Callers of +/// this trait are allowed to rely on the contracts defined on each method, +/// and implementors must ensure such contracts remain true. +/// +/// * You must not rely on allocations actually happening, even if there are explicit +/// heap allocations in the source. The optimizer may detect unused allocations that it can either +/// eliminate entirely or move to the stack and thus never invoke the allocator. The +/// optimizer may further assume that allocation is infallible, so code that used to fail due +/// to allocator failures may now suddenly work because the optimizer worked around the +/// need for an allocation. More concretely, the following code example is unsound, irrespective +/// of whether your custom allocator allows counting how many allocations have happened. +/// +/// ```rust,ignore (unsound and has placeholders) +/// drop(Box::new(42)); +/// let number_of_heap_allocs = /* call private allocator API */; +/// unsafe { std::hint::assert_unchecked(number_of_heap_allocs > 0); } +/// ``` +/// +/// Note that the optimizations mentioned above are not the only +/// optimization that can be applied. You may generally not rely on heap allocations +/// happening if they can be removed without changing program behavior. +/// Whether allocations happen or not is not part of the program behavior, even if it +/// could be detected via an allocator that tracks allocations by printing or otherwise +/// having side effects. +#[stable(feature = "global_alloc", since = "1.28.0")] +pub unsafe trait GlobalAlloc { + /// Allocates memory as described by the given `layout`. + /// + /// Returns a pointer to newly-allocated memory, + /// or null to indicate allocation failure. + /// + /// # Safety + /// + /// `layout` must have non-zero size. Attempting to allocate for a zero-sized `layout` may + /// result in undefined behavior. + /// + /// (Extension subtraits might provide more specific bounds on + /// behavior, e.g., guarantee a sentinel address or a null pointer + /// in response to a zero-size allocation request.) + /// + /// The allocated block of memory may or may not be initialized. + /// + /// # Errors + /// + /// Returning a null pointer indicates that either memory is exhausted + /// or `layout` does not meet this allocator's size or alignment constraints. + /// + /// Implementations are encouraged to return null on memory + /// exhaustion rather than aborting, but this is not + /// a strict requirement. (Specifically: it is *legal* to + /// implement this trait atop an underlying native allocation + /// library that aborts on memory exhaustion.) + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + #[stable(feature = "global_alloc", since = "1.28.0")] + unsafe fn alloc(&self, layout: Layout) -> *mut u8; + + /// Deallocates the block of memory at the given `ptr` pointer with the given `layout`. + /// + /// # Safety + /// + /// The caller must ensure: + /// + /// * `ptr` is a block of memory currently allocated via this allocator and, + /// + /// * `layout` is the same layout that was used to allocate that block of + /// memory. + /// + /// Otherwise undefined behavior can result. + #[stable(feature = "global_alloc", since = "1.28.0")] + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout); + + /// Behaves like `alloc`, but also ensures that the contents + /// are set to zero before being returned. + /// + /// # Safety + /// + /// The caller has to ensure that `layout` has non-zero size. Like `alloc` + /// zero sized `layout` can result in undefined behavior. + /// However the allocated block of memory is guaranteed to be initialized. + /// + /// # Errors + /// + /// Returning a null pointer indicates that either memory is exhausted + /// or `layout` does not meet allocator's size or alignment constraints, + /// just as in `alloc`. + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + #[stable(feature = "global_alloc", since = "1.28.0")] + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + let size = layout.size(); + // SAFETY: the safety contract for `alloc` must be upheld by the caller. + let ptr = unsafe { self.alloc(layout) }; + if !ptr.is_null() { + // SAFETY: as allocation succeeded, the region from `ptr` + // of size `size` is guaranteed to be valid for writes. + unsafe { ptr::write_bytes(ptr, 0, size) }; + } + ptr + } + + /// Shrinks or grows a block of memory to the given `new_size` in bytes. + /// The block is described by the given `ptr` pointer and `layout`. + /// + /// If this returns a non-null pointer, then ownership of the memory block + /// referenced by `ptr` has been transferred to this allocator. + /// Any access to the old `ptr` is Undefined Behavior, even if the + /// allocation remained in-place. The newly returned pointer is the only valid pointer + /// for accessing this memory now. + /// + /// The new memory block is allocated with `layout`, + /// but with the `size` updated to `new_size` in bytes. + /// This new layout must be used when deallocating the new memory block with `dealloc`. + /// The range `0..min(layout.size(), new_size)` of the new memory block is + /// guaranteed to have the same values as the original block. + /// + /// If this method returns null, then ownership of the memory + /// block has not been transferred to this allocator, and the + /// contents of the memory block are unaltered. + /// + /// # Safety + /// + /// The caller must ensure that: + /// + /// * `ptr` is allocated via this allocator, + /// + /// * `layout` is the same layout that was used + /// to allocate that block of memory, + /// + /// * `new_size` is greater than zero. + /// + /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, + /// does not overflow `isize` (i.e., the rounded value must be less than or + /// equal to `isize::MAX`). + /// + /// If these are not followed, undefined behavior can result. + /// + /// (Extension subtraits might provide more specific bounds on + /// behavior, e.g., guarantee a sentinel address or a null pointer + /// in response to a zero-size allocation request.) + /// + /// # Errors + /// + /// Returns null if the new layout does not meet the size + /// and alignment constraints of the allocator, or if reallocation + /// otherwise fails. + /// + /// Implementations are encouraged to return null on memory + /// exhaustion rather than panicking or aborting, but this is not + /// a strict requirement. (Specifically: it is *legal* to + /// implement this trait atop an underlying native allocation + /// library that aborts on memory exhaustion.) + /// + /// Clients wishing to abort computation in response to a + /// reallocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + #[stable(feature = "global_alloc", since = "1.28.0")] + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + // SAFETY: the caller must ensure that the `new_size` does not overflow. + // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid. + let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; + // SAFETY: the caller must ensure that `new_layout` is greater than zero. + let new_ptr = unsafe { self.alloc(new_layout) }; + if !new_ptr.is_null() { + // SAFETY: the previously allocated block cannot overlap the newly allocated block. + // The safety contract for `dealloc` must be upheld by the caller. + unsafe { + ptr::copy_nonoverlapping(ptr, new_ptr, cmp::min(layout.size(), new_size)); + self.dealloc(ptr, layout); + } + } + new_ptr + } +} diff --git a/CoqOfRust/core/alloc/layout.rs b/CoqOfRust/core/alloc/layout.rs new file mode 100644 index 000000000..d884fa69e --- /dev/null +++ b/CoqOfRust/core/alloc/layout.rs @@ -0,0 +1,557 @@ +// Seemingly inconsequential code changes to this file can lead to measurable +// performance impact on compilation times, due at least in part to the fact +// that the layout code gets called from many instantiations of the various +// collections, resulting in having to optimize down excess IR multiple times. +// Your performance intuition is useless. Run perf. + +use crate::error::Error; +use crate::intrinsics::{unchecked_add, unchecked_mul, unchecked_sub}; +use crate::mem::SizedTypeProperties; +use crate::ptr::{Alignment, NonNull}; +use crate::{assert_unsafe_precondition, fmt, mem}; + +// While this function is used in one place and its implementation +// could be inlined, the previous attempts to do so made rustc +// slower: +// +// * https://github.com/rust-lang/rust/pull/72189 +// * https://github.com/rust-lang/rust/pull/79827 +const fn size_align() -> (usize, usize) { + (mem::size_of::(), mem::align_of::()) +} + +/// Layout of a block of memory. +/// +/// An instance of `Layout` describes a particular layout of memory. +/// You build a `Layout` up as an input to give to an allocator. +/// +/// All layouts have an associated size and a power-of-two alignment. The size, when rounded up to +/// the nearest multiple of `align`, does not overflow `isize` (i.e., the rounded value will always be +/// less than or equal to `isize::MAX`). +/// +/// (Note that layouts are *not* required to have non-zero size, +/// even though `GlobalAlloc` requires that all memory requests +/// be non-zero in size. A caller must either ensure that conditions +/// like this are met, use specific allocators with looser +/// requirements, or use the more lenient `Allocator` interface.) +#[stable(feature = "alloc_layout", since = "1.28.0")] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[lang = "alloc_layout"] +pub struct Layout { + // size of the requested block of memory, measured in bytes. + size: usize, + + // alignment of the requested block of memory, measured in bytes. + // we ensure that this is always a power-of-two, because API's + // like `posix_memalign` require it and it is a reasonable + // constraint to impose on Layout constructors. + // + // (However, we do not analogously require `align >= sizeof(void*)`, + // even though that is *also* a requirement of `posix_memalign`.) + align: Alignment, +} + +impl Layout { + /// Constructs a `Layout` from a given `size` and `align`, + /// or returns `LayoutError` if any of the following conditions + /// are not met: + /// + /// * `align` must not be zero, + /// + /// * `align` must be a power of two, + /// + /// * `size`, when rounded up to the nearest multiple of `align`, + /// must not overflow `isize` (i.e., the rounded value must be + /// less than or equal to `isize::MAX`). + #[stable(feature = "alloc_layout", since = "1.28.0")] + #[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")] + #[inline] + pub const fn from_size_align(size: usize, align: usize) -> Result { + if Layout::is_size_align_valid(size, align) { + // SAFETY: Layout::is_size_align_valid checks the preconditions for this call. + unsafe { Ok(Layout { size, align: mem::transmute(align) }) } + } else { + Err(LayoutError) + } + } + + const fn is_size_align_valid(size: usize, align: usize) -> bool { + let Some(align) = Alignment::new(align) else { return false }; + if size > Self::max_size_for_align(align) { + return false; + } + true + } + + #[inline(always)] + const fn max_size_for_align(align: Alignment) -> usize { + // (power-of-two implies align != 0.) + + // Rounded up size is: + // size_rounded_up = (size + align - 1) & !(align - 1); + // + // We know from above that align != 0. If adding (align - 1) + // does not overflow, then rounding up will be fine. + // + // Conversely, &-masking with !(align - 1) will subtract off + // only low-order-bits. Thus if overflow occurs with the sum, + // the &-mask cannot subtract enough to undo that overflow. + // + // Above implies that checking for summation overflow is both + // necessary and sufficient. + + // SAFETY: the maximum possible alignment is `isize::MAX + 1`, + // so the subtraction cannot overflow. + unsafe { unchecked_sub(isize::MAX as usize + 1, align.as_usize()) } + } + + /// Internal helper constructor to skip revalidating alignment validity. + #[inline] + const fn from_size_alignment(size: usize, align: Alignment) -> Result { + if size > Self::max_size_for_align(align) { + return Err(LayoutError); + } + + // SAFETY: Layout::size invariants checked above. + Ok(Layout { size, align }) + } + + /// Creates a layout, bypassing all checks. + /// + /// # Safety + /// + /// This function is unsafe as it does not verify the preconditions from + /// [`Layout::from_size_align`]. + #[stable(feature = "alloc_layout", since = "1.28.0")] + #[rustc_const_stable(feature = "const_alloc_layout_unchecked", since = "1.36.0")] + #[must_use] + #[inline] + pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { + assert_unsafe_precondition!( + check_library_ub, + "Layout::from_size_align_unchecked requires that align is a power of 2 \ + and the rounded-up allocation size does not exceed isize::MAX", + ( + size: usize = size, + align: usize = align, + ) => Layout::is_size_align_valid(size, align) + ); + // SAFETY: the caller is required to uphold the preconditions. + unsafe { Layout { size, align: mem::transmute(align) } } + } + + /// The minimum size in bytes for a memory block of this layout. + #[stable(feature = "alloc_layout", since = "1.28.0")] + #[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")] + #[must_use] + #[inline] + pub const fn size(&self) -> usize { + self.size + } + + /// The minimum byte alignment for a memory block of this layout. + /// + /// The returned alignment is guaranteed to be a power of two. + #[stable(feature = "alloc_layout", since = "1.28.0")] + #[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")] + #[must_use = "this returns the minimum alignment, \ + without modifying the layout"] + #[inline] + pub const fn align(&self) -> usize { + self.align.as_usize() + } + + /// Constructs a `Layout` suitable for holding a value of type `T`. + #[stable(feature = "alloc_layout", since = "1.28.0")] + #[rustc_const_stable(feature = "alloc_layout_const_new", since = "1.42.0")] + #[must_use] + #[inline] + pub const fn new() -> Self { + let (size, align) = size_align::(); + // SAFETY: if the type is instantiated, rustc already ensures that its + // layout is valid. Use the unchecked constructor to avoid inserting a + // panicking codepath that needs to be optimized out. + unsafe { Layout::from_size_align_unchecked(size, align) } + } + + /// Produces layout describing a record that could be used to + /// allocate backing structure for `T` (which could be a trait + /// or other unsized type like a slice). + #[stable(feature = "alloc_layout", since = "1.28.0")] + #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] + #[rustc_const_stable_indirect] + #[must_use] + #[inline] + pub const fn for_value(t: &T) -> Self { + let (size, align) = (mem::size_of_val(t), mem::align_of_val(t)); + // SAFETY: see rationale in `new` for why this is using the unsafe variant + unsafe { Layout::from_size_align_unchecked(size, align) } + } + + /// Produces layout describing a record that could be used to + /// allocate backing structure for `T` (which could be a trait + /// or other unsized type like a slice). + /// + /// # Safety + /// + /// This function is only safe to call if the following conditions hold: + /// + /// - If `T` is `Sized`, this function is always safe to call. + /// - If the unsized tail of `T` is: + /// - a [slice], then the length of the slice tail must be an initialized + /// integer, and the size of the *entire value* + /// (dynamic tail length + statically sized prefix) must fit in `isize`. + /// For the special case where the dynamic tail length is 0, this function + /// is safe to call. + /// - a [trait object], then the vtable part of the pointer must point + /// to a valid vtable for the type `T` acquired by an unsizing coercion, + /// and the size of the *entire value* + /// (dynamic tail length + statically sized prefix) must fit in `isize`. + /// - an (unstable) [extern type], then this function is always safe to + /// call, but may panic or otherwise return the wrong value, as the + /// extern type's layout is not known. This is the same behavior as + /// [`Layout::for_value`] on a reference to an extern type tail. + /// - otherwise, it is conservatively not allowed to call this function. + /// + /// [trait object]: ../../book/ch17-02-trait-objects.html + /// [extern type]: ../../unstable-book/language-features/extern-types.html + #[unstable(feature = "layout_for_ptr", issue = "69835")] + #[must_use] + pub const unsafe fn for_value_raw(t: *const T) -> Self { + // SAFETY: we pass along the prerequisites of these functions to the caller + let (size, align) = unsafe { (mem::size_of_val_raw(t), mem::align_of_val_raw(t)) }; + // SAFETY: see rationale in `new` for why this is using the unsafe variant + unsafe { Layout::from_size_align_unchecked(size, align) } + } + + /// Creates a `NonNull` that is dangling, but well-aligned for this Layout. + /// + /// Note that the pointer value may potentially represent a valid pointer, + /// which means this must not be used as a "not yet initialized" + /// sentinel value. Types that lazily allocate must track initialization by + /// some other means. + #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[must_use] + #[inline] + pub const fn dangling(&self) -> NonNull { + // SAFETY: align is guaranteed to be non-zero + unsafe { NonNull::new_unchecked(crate::ptr::without_provenance_mut::(self.align())) } + } + + /// Creates a layout describing the record that can hold a value + /// of the same layout as `self`, but that also is aligned to + /// alignment `align` (measured in bytes). + /// + /// If `self` already meets the prescribed alignment, then returns + /// `self`. + /// + /// Note that this method does not add any padding to the overall + /// size, regardless of whether the returned layout has a different + /// alignment. In other words, if `K` has size 16, `K.align_to(32)` + /// will *still* have size 16. + /// + /// Returns an error if the combination of `self.size()` and the given + /// `align` violates the conditions listed in [`Layout::from_size_align`]. + #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] + #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] + #[rustc_const_stable_indirect] + #[inline] + pub const fn align_to(&self, align: usize) -> Result { + if let Some(align) = Alignment::new(align) { + Layout::from_size_alignment(self.size, Alignment::max(self.align, align)) + } else { + Err(LayoutError) + } + } + + /// Returns the amount of padding we must insert after `self` + /// to ensure that the following address will satisfy `align` + /// (measured in bytes). + /// + /// e.g., if `self.size()` is 9, then `self.padding_needed_for(4)` + /// returns 3, because that is the minimum number of bytes of + /// padding required to get a 4-aligned address (assuming that the + /// corresponding memory block starts at a 4-aligned address). + /// + /// The return value of this function has no meaning if `align` is + /// not a power-of-two. + /// + /// Note that the utility of the returned value requires `align` + /// to be less than or equal to the alignment of the starting + /// address for the whole allocated block of memory. One way to + /// satisfy this constraint is to ensure `align <= self.align()`. + #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[must_use = "this returns the padding needed, \ + without modifying the `Layout`"] + #[inline] + pub const fn padding_needed_for(&self, align: usize) -> usize { + // FIXME: Can we just change the type on this to `Alignment`? + let Some(align) = Alignment::new(align) else { return usize::MAX }; + let len_rounded_up = self.size_rounded_up_to_custom_align(align); + // SAFETY: Cannot overflow because the rounded-up value is never less + unsafe { unchecked_sub(len_rounded_up, self.size) } + } + + /// Returns the smallest multiple of `align` greater than or equal to `self.size()`. + /// + /// This can return at most `Alignment::MAX` (aka `isize::MAX + 1`) + /// because the original size is at most `isize::MAX`. + #[inline] + const fn size_rounded_up_to_custom_align(&self, align: Alignment) -> usize { + // SAFETY: + // Rounded up value is: + // size_rounded_up = (size + align - 1) & !(align - 1); + // + // The arithmetic we do here can never overflow: + // + // 1. align is guaranteed to be > 0, so align - 1 is always + // valid. + // + // 2. size is at most `isize::MAX`, so adding `align - 1` (which is at + // most `isize::MAX`) can never overflow a `usize`. + // + // 3. masking by the alignment can remove at most `align - 1`, + // which is what we just added, thus the value we return is never + // less than the original `size`. + // + // (Size 0 Align MAX is already aligned, so stays the same, but things like + // Size 1 Align MAX or Size isize::MAX Align 2 round up to `isize::MAX + 1`.) + unsafe { + let align_m1 = unchecked_sub(align.as_usize(), 1); + let size_rounded_up = unchecked_add(self.size, align_m1) & !align_m1; + size_rounded_up + } + } + + /// Creates a layout by rounding the size of this layout up to a multiple + /// of the layout's alignment. + /// + /// This is equivalent to adding the result of `padding_needed_for` + /// to the layout's current size. + #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] + #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] + #[rustc_const_stable_indirect] + #[must_use = "this returns a new `Layout`, \ + without modifying the original"] + #[inline] + pub const fn pad_to_align(&self) -> Layout { + // This cannot overflow. Quoting from the invariant of Layout: + // > `size`, when rounded up to the nearest multiple of `align`, + // > must not overflow isize (i.e., the rounded value must be + // > less than or equal to `isize::MAX`) + let new_size = self.size_rounded_up_to_custom_align(self.align); + + // SAFETY: padded size is guaranteed to not exceed `isize::MAX`. + unsafe { Layout::from_size_align_unchecked(new_size, self.align()) } + } + + /// Creates a layout describing the record for `n` instances of + /// `self`, with a suitable amount of padding between each to + /// ensure that each instance is given its requested size and + /// alignment. On success, returns `(k, offs)` where `k` is the + /// layout of the array and `offs` is the distance between the start + /// of each element in the array. + /// + /// (That distance between elements is sometimes known as "stride".) + /// + /// On arithmetic overflow, returns `LayoutError`. + /// + /// # Examples + /// + /// ``` + /// #![feature(alloc_layout_extra)] + /// use std::alloc::Layout; + /// + /// // All rust types have a size that's a multiple of their alignment. + /// let normal = Layout::from_size_align(12, 4).unwrap(); + /// let repeated = normal.repeat(3).unwrap(); + /// assert_eq!(repeated, (Layout::from_size_align(36, 4).unwrap(), 12)); + /// + /// // But you can manually make layouts which don't meet that rule. + /// let padding_needed = Layout::from_size_align(6, 4).unwrap(); + /// let repeated = padding_needed.repeat(3).unwrap(); + /// assert_eq!(repeated, (Layout::from_size_align(24, 4).unwrap(), 8)); + /// ``` + #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[inline] + pub const fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> { + let padded = self.pad_to_align(); + if let Ok(repeated) = padded.repeat_packed(n) { + Ok((repeated, padded.size())) + } else { + Err(LayoutError) + } + } + + /// Creates a layout describing the record for `self` followed by + /// `next`, including any necessary padding to ensure that `next` + /// will be properly aligned, but *no trailing padding*. + /// + /// In order to match C representation layout `repr(C)`, you should + /// call `pad_to_align` after extending the layout with all fields. + /// (There is no way to match the default Rust representation + /// layout `repr(Rust)`, as it is unspecified.) + /// + /// Note that the alignment of the resulting layout will be the maximum of + /// those of `self` and `next`, in order to ensure alignment of both parts. + /// + /// Returns `Ok((k, offset))`, where `k` is layout of the concatenated + /// record and `offset` is the relative location, in bytes, of the + /// start of the `next` embedded within the concatenated record + /// (assuming that the record itself starts at offset 0). + /// + /// On arithmetic overflow, returns `LayoutError`. + /// + /// # Examples + /// + /// To calculate the layout of a `#[repr(C)]` structure and the offsets of + /// the fields from its fields' layouts: + /// + /// ```rust + /// # use std::alloc::{Layout, LayoutError}; + /// pub fn repr_c(fields: &[Layout]) -> Result<(Layout, Vec), LayoutError> { + /// let mut offsets = Vec::new(); + /// let mut layout = Layout::from_size_align(0, 1)?; + /// for &field in fields { + /// let (new_layout, offset) = layout.extend(field)?; + /// layout = new_layout; + /// offsets.push(offset); + /// } + /// // Remember to finalize with `pad_to_align`! + /// Ok((layout.pad_to_align(), offsets)) + /// } + /// # // test that it works + /// # #[repr(C)] struct S { a: u64, b: u32, c: u16, d: u32 } + /// # let s = Layout::new::(); + /// # let u16 = Layout::new::(); + /// # let u32 = Layout::new::(); + /// # let u64 = Layout::new::(); + /// # assert_eq!(repr_c(&[u64, u32, u16, u32]), Ok((s, vec![0, 8, 12, 16]))); + /// ``` + #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] + #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] + #[rustc_const_stable_indirect] + #[inline] + pub const fn extend(&self, next: Self) -> Result<(Self, usize), LayoutError> { + let new_align = Alignment::max(self.align, next.align); + let offset = self.size_rounded_up_to_custom_align(next.align); + + // SAFETY: `offset` is at most `isize::MAX + 1` (such as from aligning + // to `Alignment::MAX`) and `next.size` is at most `isize::MAX` (from the + // `Layout` type invariant). Thus the largest possible `new_size` is + // `isize::MAX + 1 + isize::MAX`, which is `usize::MAX`, and cannot overflow. + let new_size = unsafe { unchecked_add(offset, next.size) }; + + if let Ok(layout) = Layout::from_size_alignment(new_size, new_align) { + Ok((layout, offset)) + } else { + Err(LayoutError) + } + } + + /// Creates a layout describing the record for `n` instances of + /// `self`, with no padding between each instance. + /// + /// Note that, unlike `repeat`, `repeat_packed` does not guarantee + /// that the repeated instances of `self` will be properly + /// aligned, even if a given instance of `self` is properly + /// aligned. In other words, if the layout returned by + /// `repeat_packed` is used to allocate an array, it is not + /// guaranteed that all elements in the array will be properly + /// aligned. + /// + /// On arithmetic overflow, returns `LayoutError`. + #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[inline] + pub const fn repeat_packed(&self, n: usize) -> Result { + if let Some(size) = self.size.checked_mul(n) { + // The safe constructor is called here to enforce the isize size limit. + Layout::from_size_alignment(size, self.align) + } else { + Err(LayoutError) + } + } + + /// Creates a layout describing the record for `self` followed by + /// `next` with no additional padding between the two. Since no + /// padding is inserted, the alignment of `next` is irrelevant, + /// and is not incorporated *at all* into the resulting layout. + /// + /// On arithmetic overflow, returns `LayoutError`. + #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[inline] + pub const fn extend_packed(&self, next: Self) -> Result { + // SAFETY: each `size` is at most `isize::MAX == usize::MAX/2`, so the + // sum is at most `usize::MAX/2*2 == usize::MAX - 1`, and cannot overflow. + let new_size = unsafe { unchecked_add(self.size, next.size) }; + // The safe constructor enforces that the new size isn't too big for the alignment + Layout::from_size_alignment(new_size, self.align) + } + + /// Creates a layout describing the record for a `[T; n]`. + /// + /// On arithmetic overflow or when the total size would exceed + /// `isize::MAX`, returns `LayoutError`. + #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] + #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] + #[rustc_const_stable_indirect] + #[inline] + pub const fn array(n: usize) -> Result { + // Reduce the amount of code we need to monomorphize per `T`. + return inner(T::LAYOUT, n); + + #[inline] + const fn inner(element_layout: Layout, n: usize) -> Result { + let Layout { size: element_size, align } = element_layout; + + // We need to check two things about the size: + // - That the total size won't overflow a `usize`, and + // - That the total size still fits in an `isize`. + // By using division we can check them both with a single threshold. + // That'd usually be a bad idea, but thankfully here the element size + // and alignment are constants, so the compiler will fold all of it. + if element_size != 0 && n > Layout::max_size_for_align(align) / element_size { + return Err(LayoutError); + } + + // SAFETY: We just checked that we won't overflow `usize` when we multiply. + // This is a useless hint inside this function, but after inlining this helps + // deduplicate checks for whether the overall capacity is zero (e.g., in RawVec's + // allocation path) before/after this multiplication. + let array_size = unsafe { unchecked_mul(element_size, n) }; + + // SAFETY: We just checked above that the `array_size` will not + // exceed `isize::MAX` even when rounded up to the alignment. + // And `Alignment` guarantees it's a power of two. + unsafe { Ok(Layout::from_size_align_unchecked(array_size, align.as_usize())) } + } + } +} + +#[stable(feature = "alloc_layout", since = "1.28.0")] +#[deprecated( + since = "1.52.0", + note = "Name does not follow std convention, use LayoutError", + suggestion = "LayoutError" +)] +pub type LayoutErr = LayoutError; + +/// The `LayoutError` is returned when the parameters given +/// to `Layout::from_size_align` +/// or some other `Layout` constructor +/// do not satisfy its documented constraints. +#[stable(feature = "alloc_layout_error", since = "1.50.0")] +#[non_exhaustive] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct LayoutError; + +#[stable(feature = "alloc_layout", since = "1.28.0")] +impl Error for LayoutError {} + +// (we need this for downstream impl of trait Error) +#[stable(feature = "alloc_layout", since = "1.28.0")] +impl fmt::Display for LayoutError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("invalid parameters to Layout::from_size_align") + } +} diff --git a/CoqOfRust/core/alloc/mod.rs b/CoqOfRust/core/alloc/mod.rs new file mode 100644 index 000000000..aa841db04 --- /dev/null +++ b/CoqOfRust/core/alloc/mod.rs @@ -0,0 +1,425 @@ +//! Memory allocation APIs + +#![stable(feature = "alloc_module", since = "1.28.0")] + +mod global; +mod layout; + +#[stable(feature = "global_alloc", since = "1.28.0")] +pub use self::global::GlobalAlloc; +#[stable(feature = "alloc_layout", since = "1.28.0")] +pub use self::layout::Layout; +#[stable(feature = "alloc_layout", since = "1.28.0")] +#[deprecated( + since = "1.52.0", + note = "Name does not follow std convention, use LayoutError", + suggestion = "LayoutError" +)] +#[allow(deprecated, deprecated_in_future)] +pub use self::layout::LayoutErr; +#[stable(feature = "alloc_layout_error", since = "1.50.0")] +pub use self::layout::LayoutError; +use crate::error::Error; +use crate::fmt; +use crate::ptr::{self, NonNull}; + +/// The `AllocError` error indicates an allocation failure +/// that may be due to resource exhaustion or to +/// something wrong when combining the given input arguments with this +/// allocator. +#[unstable(feature = "allocator_api", issue = "32838")] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct AllocError; + +#[unstable( + feature = "allocator_api", + reason = "the precise API and guarantees it provides may be tweaked.", + issue = "32838" +)] +impl Error for AllocError {} + +// (we need this for downstream impl of trait Error) +#[unstable(feature = "allocator_api", issue = "32838")] +impl fmt::Display for AllocError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("memory allocation failed") + } +} + +/// An implementation of `Allocator` can allocate, grow, shrink, and deallocate arbitrary blocks of +/// data described via [`Layout`][]. +/// +/// `Allocator` is designed to be implemented on ZSTs, references, or smart pointers because having +/// an allocator like `MyAlloc([u8; N])` cannot be moved, without updating the pointers to the +/// allocated memory. +/// +/// Unlike [`GlobalAlloc`][], zero-sized allocations are allowed in `Allocator`. If an underlying +/// allocator does not support this (like jemalloc) or return a null pointer (such as +/// `libc::malloc`), this must be caught by the implementation. +/// +/// ### Currently allocated memory +/// +/// Some of the methods require that a memory block be *currently allocated* via an allocator. This +/// means that: +/// +/// * the starting address for that memory block was previously returned by [`allocate`], [`grow`], or +/// [`shrink`], and +/// +/// * the memory block has not been subsequently deallocated, where blocks are either deallocated +/// directly by being passed to [`deallocate`] or were changed by being passed to [`grow`] or +/// [`shrink`] that returns `Ok`. If `grow` or `shrink` have returned `Err`, the passed pointer +/// remains valid. +/// +/// [`allocate`]: Allocator::allocate +/// [`grow`]: Allocator::grow +/// [`shrink`]: Allocator::shrink +/// [`deallocate`]: Allocator::deallocate +/// +/// ### Memory fitting +/// +/// Some of the methods require that a layout *fit* a memory block. What it means for a layout to +/// "fit" a memory block means (or equivalently, for a memory block to "fit" a layout) is that the +/// following conditions must hold: +/// +/// * The block must be allocated with the same alignment as [`layout.align()`], and +/// +/// * The provided [`layout.size()`] must fall in the range `min ..= max`, where: +/// - `min` is the size of the layout most recently used to allocate the block, and +/// - `max` is the latest actual size returned from [`allocate`], [`grow`], or [`shrink`]. +/// +/// [`layout.align()`]: Layout::align +/// [`layout.size()`]: Layout::size +/// +/// # Safety +/// +/// * Memory blocks returned from an allocator that are [*currently allocated*] must point to +/// valid memory and retain their validity while they are [*currently allocated*] and the shorter +/// of: +/// - the borrow-checker lifetime of the allocator type itself. +/// - as long as at least one of the instance and all of its clones has not been dropped. +/// +/// * copying, cloning, or moving the allocator must not invalidate memory blocks returned from this +/// allocator. A copied or cloned allocator must behave like the same allocator, and +/// +/// * any pointer to a memory block which is [*currently allocated*] may be passed to any other +/// method of the allocator. +/// +/// [*currently allocated*]: #currently-allocated-memory +#[unstable(feature = "allocator_api", issue = "32838")] +pub unsafe trait Allocator { + /// Attempts to allocate a block of memory. + /// + /// On success, returns a [`NonNull<[u8]>`][NonNull] meeting the size and alignment guarantees of `layout`. + /// + /// The returned block may have a larger size than specified by `layout.size()`, and may or may + /// not have its contents initialized. + /// + /// The returned block of memory remains valid as long as it is [*currently allocated*] and the shorter of: + /// - the borrow-checker lifetime of the allocator type itself. + /// - as long as at the allocator and all its clones has not been dropped. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or `layout` does not meet + /// allocator's size or alignment constraints. + /// + /// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or + /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement + /// this trait atop an underlying native allocation library that aborts on memory exhaustion.) + /// + /// Clients wishing to abort computation in response to an allocation error are encouraged to + /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + fn allocate(&self, layout: Layout) -> Result, AllocError>; + + /// Behaves like `allocate`, but also ensures that the returned memory is zero-initialized. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or `layout` does not meet + /// allocator's size or alignment constraints. + /// + /// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or + /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement + /// this trait atop an underlying native allocation library that aborts on memory exhaustion.) + /// + /// Clients wishing to abort computation in response to an allocation error are encouraged to + /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + fn allocate_zeroed(&self, layout: Layout) -> Result, AllocError> { + let ptr = self.allocate(layout)?; + // SAFETY: `alloc` returns a valid memory block + unsafe { ptr.as_non_null_ptr().as_ptr().write_bytes(0, ptr.len()) } + Ok(ptr) + } + + /// Deallocates the memory referenced by `ptr`. + /// + /// # Safety + /// + /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator, and + /// * `layout` must [*fit*] that block of memory. + /// + /// [*currently allocated*]: #currently-allocated-memory + /// [*fit*]: #memory-fitting + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout); + + /// Attempts to extend the memory block. + /// + /// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated + /// memory. The pointer is suitable for holding data described by `new_layout`. To accomplish + /// this, the allocator may extend the allocation referenced by `ptr` to fit the new layout. + /// + /// If this returns `Ok`, then ownership of the memory block referenced by `ptr` has been + /// transferred to this allocator. Any access to the old `ptr` is Undefined Behavior, even if the + /// allocation was grown in-place. The newly returned pointer is the only valid pointer + /// for accessing this memory now. + /// + /// If this method returns `Err`, then ownership of the memory block has not been transferred to + /// this allocator, and the contents of the memory block are unaltered. + /// + /// # Safety + /// + /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator. + /// * `old_layout` must [*fit*] that block of memory (The `new_layout` argument need not fit it.). + /// * `new_layout.size()` must be greater than or equal to `old_layout.size()`. + /// + /// Note that `new_layout.align()` need not be the same as `old_layout.align()`. + /// + /// [*currently allocated*]: #currently-allocated-memory + /// [*fit*]: #memory-fitting + /// + /// # Errors + /// + /// Returns `Err` if the new layout does not meet the allocator's size and alignment + /// constraints of the allocator, or if growing otherwise fails. + /// + /// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or + /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement + /// this trait atop an underlying native allocation library that aborts on memory exhaustion.) + /// + /// Clients wishing to abort computation in response to an allocation error are encouraged to + /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + unsafe fn grow( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + debug_assert!( + new_layout.size() >= old_layout.size(), + "`new_layout.size()` must be greater than or equal to `old_layout.size()`" + ); + + let new_ptr = self.allocate(new_layout)?; + + // SAFETY: because `new_layout.size()` must be greater than or equal to + // `old_layout.size()`, both the old and new memory allocation are valid for reads and + // writes for `old_layout.size()` bytes. Also, because the old allocation wasn't yet + // deallocated, it cannot overlap `new_ptr`. Thus, the call to `copy_nonoverlapping` is + // safe. The safety contract for `dealloc` must be upheld by the caller. + unsafe { + ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_layout.size()); + self.deallocate(ptr, old_layout); + } + + Ok(new_ptr) + } + + /// Behaves like `grow`, but also ensures that the new contents are set to zero before being + /// returned. + /// + /// The memory block will contain the following contents after a successful call to + /// `grow_zeroed`: + /// * Bytes `0..old_layout.size()` are preserved from the original allocation. + /// * Bytes `old_layout.size()..old_size` will either be preserved or zeroed, depending on + /// the allocator implementation. `old_size` refers to the size of the memory block prior + /// to the `grow_zeroed` call, which may be larger than the size that was originally + /// requested when it was allocated. + /// * Bytes `old_size..new_size` are zeroed. `new_size` refers to the size of the memory + /// block returned by the `grow_zeroed` call. + /// + /// # Safety + /// + /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator. + /// * `old_layout` must [*fit*] that block of memory (The `new_layout` argument need not fit it.). + /// * `new_layout.size()` must be greater than or equal to `old_layout.size()`. + /// + /// Note that `new_layout.align()` need not be the same as `old_layout.align()`. + /// + /// [*currently allocated*]: #currently-allocated-memory + /// [*fit*]: #memory-fitting + /// + /// # Errors + /// + /// Returns `Err` if the new layout does not meet the allocator's size and alignment + /// constraints of the allocator, or if growing otherwise fails. + /// + /// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or + /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement + /// this trait atop an underlying native allocation library that aborts on memory exhaustion.) + /// + /// Clients wishing to abort computation in response to an allocation error are encouraged to + /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + unsafe fn grow_zeroed( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + debug_assert!( + new_layout.size() >= old_layout.size(), + "`new_layout.size()` must be greater than or equal to `old_layout.size()`" + ); + + let new_ptr = self.allocate_zeroed(new_layout)?; + + // SAFETY: because `new_layout.size()` must be greater than or equal to + // `old_layout.size()`, both the old and new memory allocation are valid for reads and + // writes for `old_layout.size()` bytes. Also, because the old allocation wasn't yet + // deallocated, it cannot overlap `new_ptr`. Thus, the call to `copy_nonoverlapping` is + // safe. The safety contract for `dealloc` must be upheld by the caller. + unsafe { + ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_layout.size()); + self.deallocate(ptr, old_layout); + } + + Ok(new_ptr) + } + + /// Attempts to shrink the memory block. + /// + /// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated + /// memory. The pointer is suitable for holding data described by `new_layout`. To accomplish + /// this, the allocator may shrink the allocation referenced by `ptr` to fit the new layout. + /// + /// If this returns `Ok`, then ownership of the memory block referenced by `ptr` has been + /// transferred to this allocator. Any access to the old `ptr` is Undefined Behavior, even if the + /// allocation was shrunk in-place. The newly returned pointer is the only valid pointer + /// for accessing this memory now. + /// + /// If this method returns `Err`, then ownership of the memory block has not been transferred to + /// this allocator, and the contents of the memory block are unaltered. + /// + /// # Safety + /// + /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator. + /// * `old_layout` must [*fit*] that block of memory (The `new_layout` argument need not fit it.). + /// * `new_layout.size()` must be smaller than or equal to `old_layout.size()`. + /// + /// Note that `new_layout.align()` need not be the same as `old_layout.align()`. + /// + /// [*currently allocated*]: #currently-allocated-memory + /// [*fit*]: #memory-fitting + /// + /// # Errors + /// + /// Returns `Err` if the new layout does not meet the allocator's size and alignment + /// constraints of the allocator, or if shrinking otherwise fails. + /// + /// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or + /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement + /// this trait atop an underlying native allocation library that aborts on memory exhaustion.) + /// + /// Clients wishing to abort computation in response to an allocation error are encouraged to + /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + unsafe fn shrink( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + debug_assert!( + new_layout.size() <= old_layout.size(), + "`new_layout.size()` must be smaller than or equal to `old_layout.size()`" + ); + + let new_ptr = self.allocate(new_layout)?; + + // SAFETY: because `new_layout.size()` must be lower than or equal to + // `old_layout.size()`, both the old and new memory allocation are valid for reads and + // writes for `new_layout.size()` bytes. Also, because the old allocation wasn't yet + // deallocated, it cannot overlap `new_ptr`. Thus, the call to `copy_nonoverlapping` is + // safe. The safety contract for `dealloc` must be upheld by the caller. + unsafe { + ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), new_layout.size()); + self.deallocate(ptr, old_layout); + } + + Ok(new_ptr) + } + + /// Creates a "by reference" adapter for this instance of `Allocator`. + /// + /// The returned adapter also implements `Allocator` and will simply borrow this. + #[inline(always)] + fn by_ref(&self) -> &Self + where + Self: Sized, + { + self + } +} + +#[unstable(feature = "allocator_api", issue = "32838")] +unsafe impl Allocator for &A +where + A: Allocator + ?Sized, +{ + #[inline] + fn allocate(&self, layout: Layout) -> Result, AllocError> { + (**self).allocate(layout) + } + + #[inline] + fn allocate_zeroed(&self, layout: Layout) -> Result, AllocError> { + (**self).allocate_zeroed(layout) + } + + #[inline] + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).deallocate(ptr, layout) } + } + + #[inline] + unsafe fn grow( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).grow(ptr, old_layout, new_layout) } + } + + #[inline] + unsafe fn grow_zeroed( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).grow_zeroed(ptr, old_layout, new_layout) } + } + + #[inline] + unsafe fn shrink( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).shrink(ptr, old_layout, new_layout) } + } +} diff --git a/CoqOfRust/core/any.rs b/CoqOfRust/core/any.rs new file mode 100644 index 000000000..58107b1e7 --- /dev/null +++ b/CoqOfRust/core/any.rs @@ -0,0 +1,750 @@ +//! Utilities for dynamic typing or type reflection. +//! +//! # `Any` and `TypeId` +//! +//! `Any` itself can be used to get a `TypeId`, and has more features when used +//! as a trait object. As `&dyn Any` (a borrowed trait object), it has the `is` +//! and `downcast_ref` methods, to test if the contained value is of a given type, +//! and to get a reference to the inner value as a type. As `&mut dyn Any`, there +//! is also the `downcast_mut` method, for getting a mutable reference to the +//! inner value. `Box` adds the `downcast` method, which attempts to +//! convert to a `Box`. See the [`Box`] documentation for the full details. +//! +//! Note that `&dyn Any` is limited to testing whether a value is of a specified +//! concrete type, and cannot be used to test whether a type implements a trait. +//! +//! [`Box`]: ../../std/boxed/struct.Box.html +//! +//! # Smart pointers and `dyn Any` +//! +//! One piece of behavior to keep in mind when using `Any` as a trait object, +//! especially with types like `Box` or `Arc`, is that simply +//! calling `.type_id()` on the value will produce the `TypeId` of the +//! *container*, not the underlying trait object. This can be avoided by +//! converting the smart pointer into a `&dyn Any` instead, which will return +//! the object's `TypeId`. For example: +//! +//! ``` +//! use std::any::{Any, TypeId}; +//! +//! let boxed: Box = Box::new(3_i32); +//! +//! // You're more likely to want this: +//! let actual_id = (&*boxed).type_id(); +//! // ... than this: +//! let boxed_id = boxed.type_id(); +//! +//! assert_eq!(actual_id, TypeId::of::()); +//! assert_eq!(boxed_id, TypeId::of::>()); +//! ``` +//! +//! ## Examples +//! +//! Consider a situation where we want to log a value passed to a function. +//! We know the value we're working on implements `Debug`, but we don't know its +//! concrete type. We want to give special treatment to certain types: in this +//! case printing out the length of `String` values prior to their value. +//! We don't know the concrete type of our value at compile time, so we need to +//! use runtime reflection instead. +//! +//! ```rust +//! use std::fmt::Debug; +//! use std::any::Any; +//! +//! // Logger function for any type that implements `Debug`. +//! fn log(value: &T) { +//! let value_any = value as &dyn Any; +//! +//! // Try to convert our value to a `String`. If successful, we want to +//! // output the `String`'s length as well as its value. If not, it's a +//! // different type: just print it out unadorned. +//! match value_any.downcast_ref::() { +//! Some(as_string) => { +//! println!("String ({}): {}", as_string.len(), as_string); +//! } +//! None => { +//! println!("{value:?}"); +//! } +//! } +//! } +//! +//! // This function wants to log its parameter out prior to doing work with it. +//! fn do_work(value: &T) { +//! log(value); +//! // ...do some other work +//! } +//! +//! fn main() { +//! let my_string = "Hello World".to_string(); +//! do_work(&my_string); +//! +//! let my_i8: i8 = 100; +//! do_work(&my_i8); +//! } +//! ``` +//! + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::{fmt, hash, intrinsics}; + +/////////////////////////////////////////////////////////////////////////////// +// Any trait +/////////////////////////////////////////////////////////////////////////////// + +/// A trait to emulate dynamic typing. +/// +/// Most types implement `Any`. However, any type which contains a non-`'static` reference does not. +/// See the [module-level documentation][mod] for more details. +/// +/// [mod]: crate::any +// This trait is not unsafe, though we rely on the specifics of it's sole impl's +// `type_id` function in unsafe code (e.g., `downcast`). Normally, that would be +// a problem, but because the only impl of `Any` is a blanket implementation, no +// other code can implement `Any`. +// +// We could plausibly make this trait unsafe -- it would not cause breakage, +// since we control all the implementations -- but we choose not to as that's +// both not really necessary and may confuse users about the distinction of +// unsafe traits and unsafe methods (i.e., `type_id` would still be safe to call, +// but we would likely want to indicate as such in documentation). +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Any")] +pub trait Any: 'static { + /// Gets the `TypeId` of `self`. + /// + /// If called on a `dyn Any` trait object + /// (or a trait object of a subtrait of `Any`), + /// this returns the `TypeId` of the underlying + /// concrete type, not that of `dyn Any` itself. + /// + /// # Examples + /// + /// ``` + /// use std::any::{Any, TypeId}; + /// + /// fn is_string(s: &dyn Any) -> bool { + /// TypeId::of::() == s.type_id() + /// } + /// + /// assert_eq!(is_string(&0), false); + /// assert_eq!(is_string(&"cookie monster".to_string()), true); + /// ``` + #[stable(feature = "get_type_id", since = "1.34.0")] + fn type_id(&self) -> TypeId; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Any for T { + fn type_id(&self) -> TypeId { + TypeId::of::() + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Extension methods for Any trait objects. +/////////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for dyn Any { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Any").finish_non_exhaustive() + } +} + +// Ensure that the result of e.g., joining a thread can be printed and +// hence used with `unwrap`. May eventually no longer be needed if +// dispatch works with upcasting. +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for dyn Any + Send { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Any").finish_non_exhaustive() + } +} + +#[stable(feature = "any_send_sync_methods", since = "1.28.0")] +impl fmt::Debug for dyn Any + Send + Sync { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Any").finish_non_exhaustive() + } +} + +impl dyn Any { + /// Returns `true` if the inner type is the same as `T`. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn is_string(s: &dyn Any) { + /// if s.is::() { + /// println!("It's a string!"); + /// } else { + /// println!("Not a string..."); + /// } + /// } + /// + /// is_string(&0); + /// is_string(&"cookie monster".to_string()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is(&self) -> bool { + // Get `TypeId` of the type this function is instantiated with. + let t = TypeId::of::(); + + // Get `TypeId` of the type in the trait object (`self`). + let concrete = self.type_id(); + + // Compare both `TypeId`s on equality. + t == concrete + } + + /// Returns some reference to the inner value if it is of type `T`, or + /// `None` if it isn't. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn print_if_string(s: &dyn Any) { + /// if let Some(string) = s.downcast_ref::() { + /// println!("It's a string({}): '{}'", string.len(), string); + /// } else { + /// println!("Not a string..."); + /// } + /// } + /// + /// print_if_string(&0); + /// print_if_string(&"cookie monster".to_string()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + if self.is::() { + // SAFETY: just checked whether we are pointing to the correct type, and we can rely on + // that check for memory safety because we have implemented Any for all types; no other + // impls can exist as they would conflict with our impl. + unsafe { Some(self.downcast_ref_unchecked()) } + } else { + None + } + } + + /// Returns some mutable reference to the inner value if it is of type `T`, or + /// `None` if it isn't. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn modify_if_u32(s: &mut dyn Any) { + /// if let Some(num) = s.downcast_mut::() { + /// *num = 42; + /// } + /// } + /// + /// let mut x = 10u32; + /// let mut s = "starlord".to_string(); + /// + /// modify_if_u32(&mut x); + /// modify_if_u32(&mut s); + /// + /// assert_eq!(x, 42); + /// assert_eq!(&s, "starlord"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + if self.is::() { + // SAFETY: just checked whether we are pointing to the correct type, and we can rely on + // that check for memory safety because we have implemented Any for all types; no other + // impls can exist as they would conflict with our impl. + unsafe { Some(self.downcast_mut_unchecked()) } + } else { + None + } + } + + /// Returns a reference to the inner value as type `dyn T`. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_ref_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + #[unstable(feature = "downcast_unchecked", issue = "90850")] + #[inline] + pub unsafe fn downcast_ref_unchecked(&self) -> &T { + debug_assert!(self.is::()); + // SAFETY: caller guarantees that T is the correct type + unsafe { &*(self as *const dyn Any as *const T) } + } + + /// Returns a mutable reference to the inner value as type `dyn T`. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let mut x: Box = Box::new(1_usize); + /// + /// unsafe { + /// *x.downcast_mut_unchecked::() += 1; + /// } + /// + /// assert_eq!(*x.downcast_ref::().unwrap(), 2); + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + #[unstable(feature = "downcast_unchecked", issue = "90850")] + #[inline] + pub unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { + debug_assert!(self.is::()); + // SAFETY: caller guarantees that T is the correct type + unsafe { &mut *(self as *mut dyn Any as *mut T) } + } +} + +impl dyn Any + Send { + /// Forwards to the method defined on the type `dyn Any`. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn is_string(s: &(dyn Any + Send)) { + /// if s.is::() { + /// println!("It's a string!"); + /// } else { + /// println!("Not a string..."); + /// } + /// } + /// + /// is_string(&0); + /// is_string(&"cookie monster".to_string()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is(&self) -> bool { + ::is::(self) + } + + /// Forwards to the method defined on the type `dyn Any`. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn print_if_string(s: &(dyn Any + Send)) { + /// if let Some(string) = s.downcast_ref::() { + /// println!("It's a string({}): '{}'", string.len(), string); + /// } else { + /// println!("Not a string..."); + /// } + /// } + /// + /// print_if_string(&0); + /// print_if_string(&"cookie monster".to_string()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + ::downcast_ref::(self) + } + + /// Forwards to the method defined on the type `dyn Any`. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn modify_if_u32(s: &mut (dyn Any + Send)) { + /// if let Some(num) = s.downcast_mut::() { + /// *num = 42; + /// } + /// } + /// + /// let mut x = 10u32; + /// let mut s = "starlord".to_string(); + /// + /// modify_if_u32(&mut x); + /// modify_if_u32(&mut s); + /// + /// assert_eq!(x, 42); + /// assert_eq!(&s, "starlord"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + ::downcast_mut::(self) + } + + /// Forwards to the method defined on the type `dyn Any`. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_ref_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// Same as the method on the type `dyn Any`. + #[unstable(feature = "downcast_unchecked", issue = "90850")] + #[inline] + pub unsafe fn downcast_ref_unchecked(&self) -> &T { + // SAFETY: guaranteed by caller + unsafe { ::downcast_ref_unchecked::(self) } + } + + /// Forwards to the method defined on the type `dyn Any`. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let mut x: Box = Box::new(1_usize); + /// + /// unsafe { + /// *x.downcast_mut_unchecked::() += 1; + /// } + /// + /// assert_eq!(*x.downcast_ref::().unwrap(), 2); + /// ``` + /// + /// # Safety + /// + /// Same as the method on the type `dyn Any`. + #[unstable(feature = "downcast_unchecked", issue = "90850")] + #[inline] + pub unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { + // SAFETY: guaranteed by caller + unsafe { ::downcast_mut_unchecked::(self) } + } +} + +impl dyn Any + Send + Sync { + /// Forwards to the method defined on the type `Any`. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn is_string(s: &(dyn Any + Send + Sync)) { + /// if s.is::() { + /// println!("It's a string!"); + /// } else { + /// println!("Not a string..."); + /// } + /// } + /// + /// is_string(&0); + /// is_string(&"cookie monster".to_string()); + /// ``` + #[stable(feature = "any_send_sync_methods", since = "1.28.0")] + #[inline] + pub fn is(&self) -> bool { + ::is::(self) + } + + /// Forwards to the method defined on the type `Any`. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn print_if_string(s: &(dyn Any + Send + Sync)) { + /// if let Some(string) = s.downcast_ref::() { + /// println!("It's a string({}): '{}'", string.len(), string); + /// } else { + /// println!("Not a string..."); + /// } + /// } + /// + /// print_if_string(&0); + /// print_if_string(&"cookie monster".to_string()); + /// ``` + #[stable(feature = "any_send_sync_methods", since = "1.28.0")] + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + ::downcast_ref::(self) + } + + /// Forwards to the method defined on the type `Any`. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn modify_if_u32(s: &mut (dyn Any + Send + Sync)) { + /// if let Some(num) = s.downcast_mut::() { + /// *num = 42; + /// } + /// } + /// + /// let mut x = 10u32; + /// let mut s = "starlord".to_string(); + /// + /// modify_if_u32(&mut x); + /// modify_if_u32(&mut s); + /// + /// assert_eq!(x, 42); + /// assert_eq!(&s, "starlord"); + /// ``` + #[stable(feature = "any_send_sync_methods", since = "1.28.0")] + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + ::downcast_mut::(self) + } + + /// Forwards to the method defined on the type `Any`. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_ref_unchecked::(), 1); + /// } + /// ``` + #[unstable(feature = "downcast_unchecked", issue = "90850")] + #[inline] + pub unsafe fn downcast_ref_unchecked(&self) -> &T { + // SAFETY: guaranteed by caller + unsafe { ::downcast_ref_unchecked::(self) } + } + + /// Forwards to the method defined on the type `Any`. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let mut x: Box = Box::new(1_usize); + /// + /// unsafe { + /// *x.downcast_mut_unchecked::() += 1; + /// } + /// + /// assert_eq!(*x.downcast_ref::().unwrap(), 2); + /// ``` + #[unstable(feature = "downcast_unchecked", issue = "90850")] + #[inline] + pub unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { + // SAFETY: guaranteed by caller + unsafe { ::downcast_mut_unchecked::(self) } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// TypeID and its methods +/////////////////////////////////////////////////////////////////////////////// + +/// A `TypeId` represents a globally unique identifier for a type. +/// +/// Each `TypeId` is an opaque object which does not allow inspection of what's +/// inside but does allow basic operations such as cloning, comparison, +/// printing, and showing. +/// +/// A `TypeId` is currently only available for types which ascribe to `'static`, +/// but this limitation may be removed in the future. +/// +/// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth +/// noting that the hashes and ordering will vary between Rust releases. Beware +/// of relying on them inside of your code! +#[derive(Clone, Copy, Eq, PartialOrd, Ord)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct TypeId { + // We avoid using `u128` because that imposes higher alignment requirements on many platforms. + // See issue #115620 for more information. + t: (u64, u64), +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for TypeId { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.t == other.t + } +} + +impl TypeId { + /// Returns the `TypeId` of the type this generic function has been + /// instantiated with. + /// + /// # Examples + /// + /// ``` + /// use std::any::{Any, TypeId}; + /// + /// fn is_string(_s: &T) -> bool { + /// TypeId::of::() == TypeId::of::() + /// } + /// + /// assert_eq!(is_string(&0), false); + /// assert_eq!(is_string(&"cookie monster".to_string()), true); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_type_id", issue = "77125")] + pub const fn of() -> TypeId { + let t: u128 = intrinsics::type_id::(); + + let t1 = (t >> 64) as u64; + let t2 = t as u64; + TypeId { t: (t1, t2) } + } + + fn as_u128(self) -> u128 { + u128::from(self.t.0) << 64 | u128::from(self.t.1) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl hash::Hash for TypeId { + #[inline] + fn hash(&self, state: &mut H) { + // We only hash the lower 64 bits of our (128 bit) internal numeric ID, + // because: + // - The hashing algorithm which backs `TypeId` is expected to be + // unbiased and high quality, meaning further mixing would be somewhat + // redundant compared to choosing (the lower) 64 bits arbitrarily. + // - `Hasher::finish` returns a u64 anyway, so the extra entropy we'd + // get from hashing the full value would probably not be useful + // (especially given the previous point about the lower 64 bits being + // high quality on their own). + // - It is correct to do so -- only hashing a subset of `self` is still + // with an `Eq` implementation that considers the entire value, as + // ours does. + self.t.1.hash(state); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for TypeId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + write!(f, "TypeId({:#034x})", self.as_u128()) + } +} + +/// Returns the name of a type as a string slice. +/// +/// # Note +/// +/// This is intended for diagnostic use. The exact contents and format of the +/// string returned are not specified, other than being a best-effort +/// description of the type. For example, amongst the strings +/// that `type_name::>()` might return are `"Option"` and +/// `"std::option::Option"`. +/// +/// The returned string must not be considered to be a unique identifier of a +/// type as multiple types may map to the same type name. Similarly, there is no +/// guarantee that all parts of a type will appear in the returned string: for +/// example, lifetime specifiers are currently not included. In addition, the +/// output may change between versions of the compiler. +/// +/// The current implementation uses the same infrastructure as compiler +/// diagnostics and debuginfo, but this is not guaranteed. +/// +/// # Examples +/// +/// ```rust +/// assert_eq!( +/// std::any::type_name::>(), +/// "core::option::Option", +/// ); +/// ``` +#[must_use] +#[stable(feature = "type_name", since = "1.38.0")] +#[rustc_const_unstable(feature = "const_type_name", issue = "63084")] +pub const fn type_name() -> &'static str { + intrinsics::type_name::() +} + +/// Returns the type name of the pointed-to value as a string slice. +/// +/// This is the same as `type_name::()`, but can be used where the type of a +/// variable is not easily available. +/// +/// # Note +/// +/// Like [`type_name`], this is intended for diagnostic use and the exact output is not +/// guaranteed. It provides a best-effort description, but the output may change between +/// versions of the compiler. +/// +/// In short: use this for debugging, avoid using the output to affect program behavior. More +/// information is available at [`type_name`]. +/// +/// Additionally, this function does not resolve trait objects. This means that +/// `type_name_of_val(&7u32 as &dyn Debug)` may return `"dyn Debug"`, but will not return `"u32"` +/// at this time. +/// +/// # Examples +/// +/// Prints the default integer and float types. +/// +/// ```rust +/// use std::any::type_name_of_val; +/// +/// let s = "foo"; +/// let x: i32 = 1; +/// let y: f32 = 1.0; +/// +/// assert!(type_name_of_val(&s).contains("str")); +/// assert!(type_name_of_val(&x).contains("i32")); +/// assert!(type_name_of_val(&y).contains("f32")); +/// ``` +#[must_use] +#[stable(feature = "type_name_of_val", since = "1.76.0")] +#[rustc_const_unstable(feature = "const_type_name", issue = "63084")] +pub const fn type_name_of_val(_val: &T) -> &'static str { + type_name::() +} diff --git a/CoqOfRust/core/arch.rs b/CoqOfRust/core/arch.rs new file mode 100644 index 000000000..95d88c7f6 --- /dev/null +++ b/CoqOfRust/core/arch.rs @@ -0,0 +1,71 @@ +#![doc = include_str!("../../stdarch/crates/core_arch/src/core_arch_docs.md")] + +#[allow(unused_imports)] +#[stable(feature = "simd_arch", since = "1.27.0")] +pub use crate::core_arch::arch::*; + +/// Inline assembly. +/// +/// Refer to [Rust By Example] for a usage guide and the [reference] for +/// detailed information about the syntax and available options. +/// +/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html +/// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html +#[stable(feature = "asm", since = "1.59.0")] +#[rustc_builtin_macro] +pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { + /* compiler built-in */ +} + +/// Inline assembly used in combination with `#[naked]` functions. +/// +/// Refer to [Rust By Example] for a usage guide and the [reference] for +/// detailed information about the syntax and available options. +/// +/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html +/// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html +#[unstable(feature = "naked_functions", issue = "90957")] +#[rustc_builtin_macro] +pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?) { + /* compiler built-in */ +} + +/// Module-level inline assembly. +/// +/// Refer to [Rust By Example] for a usage guide and the [reference] for +/// detailed information about the syntax and available options. +/// +/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html +/// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html +#[stable(feature = "global_asm", since = "1.59.0")] +#[rustc_builtin_macro] +pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) { + /* compiler built-in */ +} + +/// Compiles to a target-specific software breakpoint instruction or equivalent. +/// +/// This will typically abort the program. It may result in a core dump, and/or the system logging +/// debug information. Additional target-specific capabilities may be possible depending on +/// debuggers or other tooling; in particular, a debugger may be able to resume execution. +/// +/// If possible, this will produce an instruction sequence that allows a debugger to resume *after* +/// the breakpoint, rather than resuming *at* the breakpoint; however, the exact behavior is +/// target-specific and debugger-specific, and not guaranteed. +/// +/// If the target platform does not have any kind of debug breakpoint instruction, this may compile +/// to a trapping instruction (e.g. an undefined instruction) instead, or to some other form of +/// target-specific abort that may or may not support convenient resumption. +/// +/// The precise behavior and the precise instruction generated are not guaranteed, except that in +/// normal execution with no debug tooling involved this will not continue executing. +/// +/// - On x86 targets, this produces an `int3` instruction. +/// - On aarch64 targets, this produces a `brk #0xf000` instruction. +// When stabilizing this, update the comment on `core::intrinsics::breakpoint`. +#[unstable(feature = "breakpoint", issue = "133724")] +#[inline(always)] +#[cfg(not(bootstrap))] +pub fn breakpoint() { + core::intrinsics::breakpoint(); +} diff --git a/CoqOfRust/core/array/ascii.rs b/CoqOfRust/core/array/ascii.rs new file mode 100644 index 000000000..e2faef855 --- /dev/null +++ b/CoqOfRust/core/array/ascii.rs @@ -0,0 +1,46 @@ +use crate::ascii; + +#[cfg(not(test))] +impl [u8; N] { + /// Converts this array of bytes into an array of ASCII characters, + /// or returns `None` if any of the characters is non-ASCII. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char)] + /// + /// const HEX_DIGITS: [std::ascii::Char; 16] = + /// *b"0123456789abcdef".as_ascii().unwrap(); + /// + /// assert_eq!(HEX_DIGITS[1].as_str(), "1"); + /// assert_eq!(HEX_DIGITS[10].as_str(), "a"); + /// ``` + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub const fn as_ascii(&self) -> Option<&[ascii::Char; N]> { + if self.is_ascii() { + // SAFETY: Just checked that it's ASCII + Some(unsafe { self.as_ascii_unchecked() }) + } else { + None + } + } + + /// Converts this array of bytes into an array of ASCII characters, + /// without checking whether they're valid. + /// + /// # Safety + /// + /// Every byte in the array must be in `0..=127`, or else this is UB. + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub const unsafe fn as_ascii_unchecked(&self) -> &[ascii::Char; N] { + let byte_ptr: *const [u8; N] = self; + let ascii_ptr = byte_ptr as *const [ascii::Char; N]; + // SAFETY: The caller promised all the bytes are ASCII + unsafe { &*ascii_ptr } + } +} diff --git a/CoqOfRust/core/array/drain.rs b/CoqOfRust/core/array/drain.rs new file mode 100644 index 000000000..5fadf907b --- /dev/null +++ b/CoqOfRust/core/array/drain.rs @@ -0,0 +1,76 @@ +use crate::iter::{TrustedLen, UncheckedIterator}; +use crate::mem::ManuallyDrop; +use crate::ptr::drop_in_place; +use crate::slice; + +/// A situationally-optimized version of `array.into_iter().for_each(func)`. +/// +/// [`crate::array::IntoIter`]s are great when you need an owned iterator, but +/// storing the entire array *inside* the iterator like that can sometimes +/// pessimize code. Notable, it can be more bytes than you really want to move +/// around, and because the array accesses index into it SRoA has a harder time +/// optimizing away the type than it does iterators that just hold a couple pointers. +/// +/// Thus this function exists, which gives a way to get *moved* access to the +/// elements of an array using a small iterator -- no bigger than a slice iterator. +/// +/// The function-taking-a-closure structure makes it safe, as it keeps callers +/// from looking at already-dropped elements. +pub(crate) fn drain_array_with( + array: [T; N], + func: impl for<'a> FnOnce(Drain<'a, T>) -> R, +) -> R { + let mut array = ManuallyDrop::new(array); + // SAFETY: Now that the local won't drop it, it's ok to construct the `Drain` which will. + let drain = Drain(array.iter_mut()); + func(drain) +} + +/// See [`drain_array_with`] -- this is `pub(crate)` only so it's allowed to be +/// mentioned in the signature of that method. (Otherwise it hits `E0446`.) +// INVARIANT: It's ok to drop the remainder of the inner iterator. +pub(crate) struct Drain<'a, T>(slice::IterMut<'a, T>); + +impl Drop for Drain<'_, T> { + fn drop(&mut self) { + // SAFETY: By the type invariant, we're allowed to drop all these. + unsafe { drop_in_place(self.0.as_mut_slice()) } + } +} + +impl Iterator for Drain<'_, T> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + let p: *const T = self.0.next()?; + // SAFETY: The iterator was already advanced, so we won't drop this later. + Some(unsafe { p.read() }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let n = self.len(); + (n, Some(n)) + } +} + +impl ExactSizeIterator for Drain<'_, T> { + #[inline] + fn len(&self) -> usize { + self.0.len() + } +} + +// SAFETY: This is a 1:1 wrapper for a slice iterator, which is also `TrustedLen`. +unsafe impl TrustedLen for Drain<'_, T> {} + +impl UncheckedIterator for Drain<'_, T> { + unsafe fn next_unchecked(&mut self) -> T { + // SAFETY: `Drain` is 1:1 with the inner iterator, so if the caller promised + // that there's an element left, the inner iterator has one too. + let p: *const T = unsafe { self.0.next_unchecked() }; + // SAFETY: The iterator was already advanced, so we won't drop this later. + unsafe { p.read() } + } +} diff --git a/CoqOfRust/core/array/equality.rs b/CoqOfRust/core/array/equality.rs new file mode 100644 index 000000000..bb668d2a6 --- /dev/null +++ b/CoqOfRust/core/array/equality.rs @@ -0,0 +1,155 @@ +use crate::cmp::BytewiseEq; + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[U; N]> for [T; N] +where + T: PartialEq, +{ + #[inline] + fn eq(&self, other: &[U; N]) -> bool { + SpecArrayEq::spec_eq(self, other) + } + #[inline] + fn ne(&self, other: &[U; N]) -> bool { + SpecArrayEq::spec_ne(self, other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[U]> for [T; N] +where + T: PartialEq, +{ + #[inline] + fn eq(&self, other: &[U]) -> bool { + let b: Result<&[U; N], _> = other.try_into(); + match b { + Ok(b) => *self == *b, + Err(_) => false, + } + } + #[inline] + fn ne(&self, other: &[U]) -> bool { + let b: Result<&[U; N], _> = other.try_into(); + match b { + Ok(b) => *self != *b, + Err(_) => true, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[U; N]> for [T] +where + T: PartialEq, +{ + #[inline] + fn eq(&self, other: &[U; N]) -> bool { + let b: Result<&[T; N], _> = self.try_into(); + match b { + Ok(b) => *b == *other, + Err(_) => false, + } + } + #[inline] + fn ne(&self, other: &[U; N]) -> bool { + let b: Result<&[T; N], _> = self.try_into(); + match b { + Ok(b) => *b != *other, + Err(_) => true, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<&[U]> for [T; N] +where + T: PartialEq, +{ + #[inline] + fn eq(&self, other: &&[U]) -> bool { + *self == **other + } + #[inline] + fn ne(&self, other: &&[U]) -> bool { + *self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[U; N]> for &[T] +where + T: PartialEq, +{ + #[inline] + fn eq(&self, other: &[U; N]) -> bool { + **self == *other + } + #[inline] + fn ne(&self, other: &[U; N]) -> bool { + **self != *other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<&mut [U]> for [T; N] +where + T: PartialEq, +{ + #[inline] + fn eq(&self, other: &&mut [U]) -> bool { + *self == **other + } + #[inline] + fn ne(&self, other: &&mut [U]) -> bool { + *self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[U; N]> for &mut [T] +where + T: PartialEq, +{ + #[inline] + fn eq(&self, other: &[U; N]) -> bool { + **self == *other + } + #[inline] + fn ne(&self, other: &[U; N]) -> bool { + **self != *other + } +} + +// NOTE: some less important impls are omitted to reduce code bloat +// __impl_slice_eq2! { [A; $N], &'b [B; $N] } +// __impl_slice_eq2! { [A; $N], &'b mut [B; $N] } + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for [T; N] {} + +trait SpecArrayEq: Sized { + fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool; + fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool; +} + +impl, Other, const N: usize> SpecArrayEq for T { + default fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool { + a[..] == b[..] + } + default fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool { + a[..] != b[..] + } +} + +impl, U, const N: usize> SpecArrayEq for T { + fn spec_eq(a: &[T; N], b: &[U; N]) -> bool { + // SAFETY: Arrays are compared element-wise, and don't add any padding + // between elements, so when the elements are `BytewiseEq`, we can + // compare the entire array at once. + unsafe { crate::intrinsics::raw_eq(a, crate::mem::transmute(b)) } + } + fn spec_ne(a: &[T; N], b: &[U; N]) -> bool { + !Self::spec_eq(a, b) + } +} diff --git a/CoqOfRust/core/array/iter.rs b/CoqOfRust/core/array/iter.rs new file mode 100644 index 000000000..9ce0eb61e --- /dev/null +++ b/CoqOfRust/core/array/iter.rs @@ -0,0 +1,427 @@ +//! Defines the `IntoIter` owned iterator for arrays. + +use crate::intrinsics::transmute_unchecked; +use crate::iter::{self, FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce}; +use crate::mem::MaybeUninit; +use crate::num::NonZero; +use crate::ops::{IndexRange, Range}; +use crate::{fmt, ptr}; + +/// A by-value [array] iterator. +#[stable(feature = "array_value_iter", since = "1.51.0")] +#[rustc_insignificant_dtor] +#[rustc_diagnostic_item = "ArrayIntoIter"] +pub struct IntoIter { + /// This is the array we are iterating over. + /// + /// Elements with index `i` where `alive.start <= i < alive.end` have not + /// been yielded yet and are valid array entries. Elements with indices `i + /// < alive.start` or `i >= alive.end` have been yielded already and must + /// not be accessed anymore! Those dead elements might even be in a + /// completely uninitialized state! + /// + /// So the invariants are: + /// - `data[alive]` is alive (i.e. contains valid elements) + /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the + /// elements were already read and must not be touched anymore!) + data: [MaybeUninit; N], + + /// The elements in `data` that have not been yielded yet. + /// + /// Invariants: + /// - `alive.end <= N` + /// + /// (And the `IndexRange` type requires `alive.start <= alive.end`.) + alive: IndexRange, +} + +// Note: the `#[rustc_skip_during_method_dispatch(array)]` on `trait IntoIterator` +// hides this implementation from explicit `.into_iter()` calls on editions < 2021, +// so those calls will still resolve to the slice implementation, by reference. +#[stable(feature = "array_into_iter_impl", since = "1.53.0")] +impl IntoIterator for [T; N] { + type Item = T; + type IntoIter = IntoIter; + + /// Creates a consuming iterator, that is, one that moves each value out of + /// the array (from start to end). + /// + /// The array cannot be used after calling this unless `T` implements + /// `Copy`, so the whole array is copied. + /// + /// Arrays have special behavior when calling `.into_iter()` prior to the + /// 2021 edition -- see the [array] Editions section for more information. + /// + /// [array]: prim@array + fn into_iter(self) -> Self::IntoIter { + // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit` + // promise: + // + // > `MaybeUninit` is guaranteed to have the same size and alignment + // > as `T`. + // + // The docs even show a transmute from an array of `MaybeUninit` to + // an array of `T`. + // + // With that, this initialization satisfies the invariants. + // + // FIXME: If normal `transmute` ever gets smart enough to allow this + // directly, use it instead of `transmute_unchecked`. + let data: [MaybeUninit; N] = unsafe { transmute_unchecked(self) }; + IntoIter { data, alive: IndexRange::zero_to(N) } + } +} + +impl IntoIter { + /// Creates a new iterator over the given `array`. + #[stable(feature = "array_value_iter", since = "1.51.0")] + #[deprecated(since = "1.59.0", note = "use `IntoIterator::into_iter` instead")] + pub fn new(array: [T; N]) -> Self { + IntoIterator::into_iter(array) + } + + /// Creates an iterator over the elements in a partially-initialized buffer. + /// + /// If you have a fully-initialized array, then use [`IntoIterator`]. + /// But this is useful for returning partial results from unsafe code. + /// + /// # Safety + /// + /// - The `buffer[initialized]` elements must all be initialized. + /// - The range must be canonical, with `initialized.start <= initialized.end`. + /// - The range must be in-bounds for the buffer, with `initialized.end <= N`. + /// (Like how indexing `[0][100..100]` fails despite the range being empty.) + /// + /// It's sound to have more elements initialized than mentioned, though that + /// will most likely result in them being leaked. + /// + /// # Examples + /// + /// ``` + /// #![feature(array_into_iter_constructors)] + /// #![feature(maybe_uninit_uninit_array_transpose)] + /// use std::array::IntoIter; + /// use std::mem::MaybeUninit; + /// + /// # // Hi! Thanks for reading the code. This is restricted to `Copy` because + /// # // otherwise it could leak. A fully-general version this would need a drop + /// # // guard to handle panics from the iterator, but this works for an example. + /// fn next_chunk( + /// it: &mut impl Iterator, + /// ) -> Result<[T; N], IntoIter> { + /// let mut buffer = [const { MaybeUninit::uninit() }; N]; + /// let mut i = 0; + /// while i < N { + /// match it.next() { + /// Some(x) => { + /// buffer[i].write(x); + /// i += 1; + /// } + /// None => { + /// // SAFETY: We've initialized the first `i` items + /// unsafe { + /// return Err(IntoIter::new_unchecked(buffer, 0..i)); + /// } + /// } + /// } + /// } + /// + /// // SAFETY: We've initialized all N items + /// unsafe { Ok(buffer.transpose().assume_init()) } + /// } + /// + /// let r: [_; 4] = next_chunk(&mut (10..16)).unwrap(); + /// assert_eq!(r, [10, 11, 12, 13]); + /// let r: IntoIter<_, 40> = next_chunk(&mut (10..16)).unwrap_err(); + /// assert_eq!(r.collect::>(), vec![10, 11, 12, 13, 14, 15]); + /// ``` + #[unstable(feature = "array_into_iter_constructors", issue = "91583")] + pub const unsafe fn new_unchecked( + buffer: [MaybeUninit; N], + initialized: Range, + ) -> Self { + // SAFETY: one of our safety conditions is that the range is canonical. + let alive = unsafe { IndexRange::new_unchecked(initialized.start, initialized.end) }; + Self { data: buffer, alive } + } + + /// Creates an iterator over `T` which returns no elements. + /// + /// If you just need an empty iterator, then use + /// [`iter::empty()`](crate::iter::empty) instead. + /// And if you need an empty array, use `[]`. + /// + /// But this is useful when you need an `array::IntoIter` *specifically*. + /// + /// # Examples + /// + /// ``` + /// #![feature(array_into_iter_constructors)] + /// use std::array::IntoIter; + /// + /// let empty = IntoIter::::empty(); + /// assert_eq!(empty.len(), 0); + /// assert_eq!(empty.as_slice(), &[]); + /// + /// let empty = IntoIter::::empty(); + /// assert_eq!(empty.len(), 0); + /// ``` + /// + /// `[1, 2].into_iter()` and `[].into_iter()` have different types + /// ```should_fail,edition2021 + /// #![feature(array_into_iter_constructors)] + /// use std::array::IntoIter; + /// + /// pub fn get_bytes(b: bool) -> IntoIter { + /// if b { + /// [1, 2, 3, 4].into_iter() + /// } else { + /// [].into_iter() // error[E0308]: mismatched types + /// } + /// } + /// ``` + /// + /// But using this method you can get an empty iterator of appropriate size: + /// ```edition2021 + /// #![feature(array_into_iter_constructors)] + /// use std::array::IntoIter; + /// + /// pub fn get_bytes(b: bool) -> IntoIter { + /// if b { + /// [1, 2, 3, 4].into_iter() + /// } else { + /// IntoIter::empty() + /// } + /// } + /// + /// assert_eq!(get_bytes(true).collect::>(), vec![1, 2, 3, 4]); + /// assert_eq!(get_bytes(false).collect::>(), vec![]); + /// ``` + #[unstable(feature = "array_into_iter_constructors", issue = "91583")] + pub const fn empty() -> Self { + let buffer = [const { MaybeUninit::uninit() }; N]; + let initialized = 0..0; + + // SAFETY: We're telling it that none of the elements are initialized, + // which is trivially true. And ∀N: usize, 0 <= N. + unsafe { Self::new_unchecked(buffer, initialized) } + } + + /// Returns an immutable slice of all elements that have not been yielded + /// yet. + #[stable(feature = "array_value_iter", since = "1.51.0")] + pub fn as_slice(&self) -> &[T] { + // SAFETY: We know that all elements within `alive` are properly initialized. + unsafe { + let slice = self.data.get_unchecked(self.alive.clone()); + MaybeUninit::slice_assume_init_ref(slice) + } + } + + /// Returns a mutable slice of all elements that have not been yielded yet. + #[stable(feature = "array_value_iter", since = "1.51.0")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: We know that all elements within `alive` are properly initialized. + unsafe { + let slice = self.data.get_unchecked_mut(self.alive.clone()); + MaybeUninit::slice_assume_init_mut(slice) + } + } +} + +#[stable(feature = "array_value_iter_impls", since = "1.40.0")] +impl Iterator for IntoIter { + type Item = T; + fn next(&mut self) -> Option { + // Get the next index from the front. + // + // Increasing `alive.start` by 1 maintains the invariant regarding + // `alive`. However, due to this change, for a short time, the alive + // zone is not `data[alive]` anymore, but `data[idx..alive.end]`. + self.alive.next().map(|idx| { + // Read the element from the array. + // SAFETY: `idx` is an index into the former "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 `data[alive]` again, restoring + // all invariants. + unsafe { self.data.get_unchecked(idx).assume_init_read() } + }) + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } + + #[inline] + fn fold(mut self, init: Acc, mut fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + let data = &mut self.data; + iter::ByRefSized(&mut self.alive).fold(init, |acc, idx| { + // SAFETY: idx is obtained by folding over the `alive` range, which implies the + // value is currently considered alive but as the range is being consumed each value + // we read here will only be read once and then considered dead. + fold(acc, unsafe { data.get_unchecked(idx).assume_init_read() }) + }) + } + + fn count(self) -> usize { + self.len() + } + + fn last(mut self) -> Option { + self.next_back() + } + + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + // This also moves the start, which marks them as conceptually "dropped", + // so if anything goes bad then our drop impl won't double-free them. + let range_to_drop = self.alive.take_prefix(n); + let remaining = n - range_to_drop.len(); + + // SAFETY: These elements are currently initialized, so it's fine to drop them. + unsafe { + let slice = self.data.get_unchecked_mut(range_to_drop); + ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice)); + } + + NonZero::new(remaining).map_or(Ok(()), Err) + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + // SAFETY: The caller must provide an idx that is in bound of the remainder. + unsafe { self.data.as_ptr().add(self.alive.start()).add(idx).cast::().read() } + } +} + +#[stable(feature = "array_value_iter_impls", since = "1.40.0")] +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { + // Get the next index from the back. + // + // Decreasing `alive.end` by 1 maintains the invariant regarding + // `alive`. However, due to this change, for a short time, the alive + // zone is not `data[alive]` anymore, but `data[alive.start..=idx]`. + self.alive.next_back().map(|idx| { + // Read the element from the array. + // SAFETY: `idx` is an index into the former "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 end of the + // alive-zone, the alive zone is now `data[alive]` again, restoring + // all invariants. + unsafe { self.data.get_unchecked(idx).assume_init_read() } + }) + } + + #[inline] + fn rfold(mut self, init: Acc, mut rfold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + let data = &mut self.data; + iter::ByRefSized(&mut self.alive).rfold(init, |acc, idx| { + // SAFETY: idx is obtained by folding over the `alive` range, which implies the + // value is currently considered alive but as the range is being consumed each value + // we read here will only be read once and then considered dead. + rfold(acc, unsafe { data.get_unchecked(idx).assume_init_read() }) + }) + } + + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + // This also moves the end, which marks them as conceptually "dropped", + // so if anything goes bad then our drop impl won't double-free them. + let range_to_drop = self.alive.take_suffix(n); + let remaining = n - range_to_drop.len(); + + // SAFETY: These elements are currently initialized, so it's fine to drop them. + unsafe { + let slice = self.data.get_unchecked_mut(range_to_drop); + ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice)); + } + + NonZero::new(remaining).map_or(Ok(()), Err) + } +} + +#[stable(feature = "array_value_iter_impls", since = "1.40.0")] +impl Drop for IntoIter { + fn drop(&mut self) { + // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice + // of elements that have not been moved out yet and that remain + // to be dropped. + unsafe { ptr::drop_in_place(self.as_mut_slice()) } + } +} + +#[stable(feature = "array_value_iter_impls", since = "1.40.0")] +impl ExactSizeIterator for IntoIter { + fn len(&self) -> usize { + self.alive.len() + } + fn is_empty(&self) -> bool { + self.alive.is_empty() + } +} + +#[stable(feature = "array_value_iter_impls", since = "1.40.0")] +impl FusedIterator for IntoIter {} + +// The iterator indeed reports the correct length. The number of "alive" +// elements (that will still be yielded) is the length of the range `alive`. +// This range is decremented in length in either `next` or `next_back`. It is +// always decremented by 1 in those methods, but only if `Some(_)` is returned. +#[stable(feature = "array_value_iter_impls", since = "1.40.0")] +unsafe impl TrustedLen for IntoIter {} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "std_internals")] +#[rustc_unsafe_specialization_marker] +pub trait NonDrop {} + +// T: Copy as approximation for !Drop since get_unchecked does not advance self.alive +// and thus we can't implement drop-handling +#[unstable(issue = "none", feature = "std_internals")] +impl NonDrop for T {} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "std_internals")] +unsafe impl TrustedRandomAccessNoCoerce for IntoIter +where + T: NonDrop, +{ + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +#[stable(feature = "array_value_iter_impls", since = "1.40.0")] +impl Clone for IntoIter { + fn clone(&self) -> Self { + // Note, we don't really need to match the exact same alive range, so + // we can just clone into offset 0 regardless of where `self` is. + let mut new = + Self { data: [const { MaybeUninit::uninit() }; N], alive: IndexRange::zero_to(0) }; + + // Clone all alive elements. + for (src, dst) in iter::zip(self.as_slice(), &mut new.data) { + // Write a clone into the new array, then update its alive range. + // If cloning panics, we'll correctly drop the previous items. + dst.write(src.clone()); + // This addition cannot overflow as we're iterating a slice + new.alive = IndexRange::zero_to(new.alive.end() + 1); + } + + new + } +} + +#[stable(feature = "array_value_iter_impls", since = "1.40.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Only print the elements that were not yielded yet: we cannot + // access the yielded elements anymore. + f.debug_tuple("IntoIter").field(&self.as_slice()).finish() + } +} diff --git a/CoqOfRust/core/array/mod.rs b/CoqOfRust/core/array/mod.rs new file mode 100644 index 000000000..95c1eb460 --- /dev/null +++ b/CoqOfRust/core/array/mod.rs @@ -0,0 +1,977 @@ +//! Utilities for the array primitive type. +//! +//! *[See also the array primitive type](array).* + +#![stable(feature = "core_array", since = "1.35.0")] + +use crate::borrow::{Borrow, BorrowMut}; +use crate::cmp::Ordering; +use crate::convert::Infallible; +use crate::error::Error; +use crate::fmt; +use crate::hash::{self, Hash}; +use crate::intrinsics::transmute_unchecked; +use crate::iter::{UncheckedIterator, repeat_n}; +use crate::mem::{self, MaybeUninit}; +use crate::ops::{ + ChangeOutputType, ControlFlow, FromResidual, Index, IndexMut, NeverShortCircuit, Residual, Try, +}; +use crate::ptr::{null, null_mut}; +use crate::slice::{Iter, IterMut}; + +mod ascii; +mod drain; +mod equality; +mod iter; + +pub(crate) use drain::drain_array_with; +#[stable(feature = "array_value_iter", since = "1.51.0")] +pub use iter::IntoIter; + +/// Creates an array of type `[T; N]` by repeatedly cloning a value. +/// +/// This is the same as `[val; N]`, but it also works for types that do not +/// implement [`Copy`]. +/// +/// The provided value will be used as an element of the resulting array and +/// will be cloned N - 1 times to fill up the rest. If N is zero, the value +/// will be dropped. +/// +/// # Example +/// +/// Creating multiple copies of a `String`: +/// ```rust +/// #![feature(array_repeat)] +/// +/// use std::array; +/// +/// let string = "Hello there!".to_string(); +/// let strings = array::repeat(string); +/// assert_eq!(strings, ["Hello there!", "Hello there!"]); +/// ``` +#[inline] +#[unstable(feature = "array_repeat", issue = "126695")] +pub fn repeat(val: T) -> [T; N] { + from_trusted_iterator(repeat_n(val, N)) +} + +/// Creates an array of type [T; N], where each element `T` is the returned value from `cb` +/// using that element's index. +/// +/// # Arguments +/// +/// * `cb`: Callback where the passed argument is the current array index. +/// +/// # Example +/// +/// ```rust +/// // type inference is helping us here, the way `from_fn` knows how many +/// // elements to produce is the length of array down there: only arrays of +/// // equal lengths can be compared, so the const generic parameter `N` is +/// // inferred to be 5, thus creating array of 5 elements. +/// +/// let array = core::array::from_fn(|i| i); +/// // indexes are: 0 1 2 3 4 +/// assert_eq!(array, [0, 1, 2, 3, 4]); +/// +/// let array2: [usize; 8] = core::array::from_fn(|i| i * 2); +/// // indexes are: 0 1 2 3 4 5 6 7 +/// assert_eq!(array2, [0, 2, 4, 6, 8, 10, 12, 14]); +/// +/// let bool_arr = core::array::from_fn::<_, 5, _>(|i| i % 2 == 0); +/// // indexes are: 0 1 2 3 4 +/// assert_eq!(bool_arr, [true, false, true, false, true]); +/// ``` +#[inline] +#[stable(feature = "array_from_fn", since = "1.63.0")] +pub fn from_fn(cb: F) -> [T; N] +where + F: FnMut(usize) -> T, +{ + try_from_fn(NeverShortCircuit::wrap_mut_1(cb)).0 +} + +/// Creates an array `[T; N]` where each fallible array element `T` is returned by the `cb` call. +/// Unlike [`from_fn`], where the element creation can't fail, this version will return an error +/// if any element creation was unsuccessful. +/// +/// The return type of this function depends on the return type of the closure. +/// If you return `Result` from the closure, you'll get a `Result<[T; N], E>`. +/// If you return `Option` from the closure, you'll get an `Option<[T; N]>`. +/// +/// # Arguments +/// +/// * `cb`: Callback where the passed argument is the current array index. +/// +/// # Example +/// +/// ```rust +/// #![feature(array_try_from_fn)] +/// +/// let array: Result<[u8; 5], _> = std::array::try_from_fn(|i| i.try_into()); +/// assert_eq!(array, Ok([0, 1, 2, 3, 4])); +/// +/// let array: Result<[i8; 200], _> = std::array::try_from_fn(|i| i.try_into()); +/// assert!(array.is_err()); +/// +/// let array: Option<[_; 4]> = std::array::try_from_fn(|i| i.checked_add(100)); +/// assert_eq!(array, Some([100, 101, 102, 103])); +/// +/// let array: Option<[_; 4]> = std::array::try_from_fn(|i| i.checked_sub(100)); +/// assert_eq!(array, None); +/// ``` +#[inline] +#[unstable(feature = "array_try_from_fn", issue = "89379")] +pub fn try_from_fn(cb: F) -> ChangeOutputType +where + F: FnMut(usize) -> R, + R: Try, + R::Residual: Residual<[R::Output; N]>, +{ + let mut array = [const { MaybeUninit::uninit() }; N]; + match try_from_fn_erased(&mut array, cb) { + ControlFlow::Break(r) => FromResidual::from_residual(r), + ControlFlow::Continue(()) => { + // SAFETY: All elements of the array were populated. + try { unsafe { MaybeUninit::array_assume_init(array) } } + } + } +} + +/// Converts a reference to `T` into a reference to an array of length 1 (without copying). +#[stable(feature = "array_from_ref", since = "1.53.0")] +#[rustc_const_stable(feature = "const_array_from_ref_shared", since = "1.63.0")] +pub const fn from_ref(s: &T) -> &[T; 1] { + // SAFETY: Converting `&T` to `&[T; 1]` is sound. + unsafe { &*(s as *const T).cast::<[T; 1]>() } +} + +/// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying). +#[stable(feature = "array_from_ref", since = "1.53.0")] +#[rustc_const_stable(feature = "const_array_from_ref", since = "1.83.0")] +pub const fn from_mut(s: &mut T) -> &mut [T; 1] { + // SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound. + unsafe { &mut *(s as *mut T).cast::<[T; 1]>() } +} + +/// The error type returned when a conversion from a slice to an array fails. +#[stable(feature = "try_from", since = "1.34.0")] +#[rustc_allowed_through_unstable_modules] +#[derive(Debug, Copy, Clone)] +pub struct TryFromSliceError(()); + +#[stable(feature = "core_array", since = "1.35.0")] +impl fmt::Display for TryFromSliceError { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + #[allow(deprecated)] + self.description().fmt(f) + } +} + +#[stable(feature = "try_from", since = "1.34.0")] +impl Error for TryFromSliceError { + #[allow(deprecated)] + fn description(&self) -> &str { + "could not convert slice to array" + } +} + +#[stable(feature = "try_from_slice_error", since = "1.36.0")] +impl From for TryFromSliceError { + fn from(x: Infallible) -> TryFromSliceError { + match x {} + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef<[T]> for [T; N] { + #[inline] + fn as_ref(&self) -> &[T] { + &self[..] + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsMut<[T]> for [T; N] { + #[inline] + fn as_mut(&mut self) -> &mut [T] { + &mut self[..] + } +} + +#[stable(feature = "array_borrow", since = "1.4.0")] +impl Borrow<[T]> for [T; N] { + fn borrow(&self) -> &[T] { + self + } +} + +#[stable(feature = "array_borrow", since = "1.4.0")] +impl BorrowMut<[T]> for [T; N] { + fn borrow_mut(&mut self) -> &mut [T] { + self + } +} + +/// Tries to create an array `[T; N]` by copying from a slice `&[T]`. +/// Succeeds if `slice.len() == N`. +/// +/// ``` +/// let bytes: [u8; 3] = [1, 0, 2]; +/// +/// let bytes_head: [u8; 2] = <[u8; 2]>::try_from(&bytes[0..2]).unwrap(); +/// assert_eq!(1, u16::from_le_bytes(bytes_head)); +/// +/// let bytes_tail: [u8; 2] = bytes[1..3].try_into().unwrap(); +/// assert_eq!(512, u16::from_le_bytes(bytes_tail)); +/// ``` +#[stable(feature = "try_from", since = "1.34.0")] +impl TryFrom<&[T]> for [T; N] +where + T: Copy, +{ + type Error = TryFromSliceError; + + #[inline] + fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> { + <&Self>::try_from(slice).copied() + } +} + +/// Tries to create an array `[T; N]` by copying from a mutable slice `&mut [T]`. +/// Succeeds if `slice.len() == N`. +/// +/// ``` +/// let mut bytes: [u8; 3] = [1, 0, 2]; +/// +/// let bytes_head: [u8; 2] = <[u8; 2]>::try_from(&mut bytes[0..2]).unwrap(); +/// assert_eq!(1, u16::from_le_bytes(bytes_head)); +/// +/// let bytes_tail: [u8; 2] = (&mut bytes[1..3]).try_into().unwrap(); +/// assert_eq!(512, u16::from_le_bytes(bytes_tail)); +/// ``` +#[stable(feature = "try_from_mut_slice_to_array", since = "1.59.0")] +impl TryFrom<&mut [T]> for [T; N] +where + T: Copy, +{ + type Error = TryFromSliceError; + + #[inline] + fn try_from(slice: &mut [T]) -> Result<[T; N], TryFromSliceError> { + ::try_from(&*slice) + } +} + +/// Tries to create an array ref `&[T; N]` from a slice ref `&[T]`. Succeeds if +/// `slice.len() == N`. +/// +/// ``` +/// let bytes: [u8; 3] = [1, 0, 2]; +/// +/// let bytes_head: &[u8; 2] = <&[u8; 2]>::try_from(&bytes[0..2]).unwrap(); +/// assert_eq!(1, u16::from_le_bytes(*bytes_head)); +/// +/// let bytes_tail: &[u8; 2] = bytes[1..3].try_into().unwrap(); +/// assert_eq!(512, u16::from_le_bytes(*bytes_tail)); +/// ``` +#[stable(feature = "try_from", since = "1.34.0")] +impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] { + type Error = TryFromSliceError; + + #[inline] + fn try_from(slice: &'a [T]) -> Result<&'a [T; N], TryFromSliceError> { + slice.as_array().ok_or(TryFromSliceError(())) + } +} + +/// Tries to create a mutable array ref `&mut [T; N]` from a mutable slice ref +/// `&mut [T]`. Succeeds if `slice.len() == N`. +/// +/// ``` +/// let mut bytes: [u8; 3] = [1, 0, 2]; +/// +/// let bytes_head: &mut [u8; 2] = <&mut [u8; 2]>::try_from(&mut bytes[0..2]).unwrap(); +/// assert_eq!(1, u16::from_le_bytes(*bytes_head)); +/// +/// let bytes_tail: &mut [u8; 2] = (&mut bytes[1..3]).try_into().unwrap(); +/// assert_eq!(512, u16::from_le_bytes(*bytes_tail)); +/// ``` +#[stable(feature = "try_from", since = "1.34.0")] +impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] { + type Error = TryFromSliceError; + + #[inline] + fn try_from(slice: &'a mut [T]) -> Result<&'a mut [T; N], TryFromSliceError> { + slice.as_mut_array().ok_or(TryFromSliceError(())) + } +} + +/// The hash of an array is the same as that of the corresponding slice, +/// as required by the `Borrow` implementation. +/// +/// ``` +/// use std::hash::BuildHasher; +/// +/// let b = std::hash::RandomState::new(); +/// let a: [u8; 3] = [0xa8, 0x3c, 0x09]; +/// let s: &[u8] = &[0xa8, 0x3c, 0x09]; +/// assert_eq!(b.hash_one(a), b.hash_one(s)); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for [T; N] { + fn hash(&self, state: &mut H) { + Hash::hash(&self[..], state) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for [T; N] { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&&self[..], f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, const N: usize> IntoIterator for &'a [T; N] { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N] { + type Item = &'a mut T; + type IntoIter = IterMut<'a, T>; + + fn into_iter(self) -> IterMut<'a, T> { + self.iter_mut() + } +} + +#[stable(feature = "index_trait_on_arrays", since = "1.50.0")] +impl Index for [T; N] +where + [T]: Index, +{ + type Output = <[T] as Index>::Output; + + #[inline] + fn index(&self, index: I) -> &Self::Output { + Index::index(self as &[T], index) + } +} + +#[stable(feature = "index_trait_on_arrays", since = "1.50.0")] +impl IndexMut for [T; N] +where + [T]: IndexMut, +{ + #[inline] + fn index_mut(&mut self, index: I) -> &mut Self::Output { + IndexMut::index_mut(self as &mut [T], index) + } +} + +/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison). +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for [T; N] { + #[inline] + fn partial_cmp(&self, other: &[T; N]) -> Option { + PartialOrd::partial_cmp(&&self[..], &&other[..]) + } + #[inline] + fn lt(&self, other: &[T; N]) -> bool { + PartialOrd::lt(&&self[..], &&other[..]) + } + #[inline] + fn le(&self, other: &[T; N]) -> bool { + PartialOrd::le(&&self[..], &&other[..]) + } + #[inline] + fn ge(&self, other: &[T; N]) -> bool { + PartialOrd::ge(&&self[..], &&other[..]) + } + #[inline] + fn gt(&self, other: &[T; N]) -> bool { + PartialOrd::gt(&&self[..], &&other[..]) + } +} + +/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison). +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for [T; N] { + #[inline] + fn cmp(&self, other: &[T; N]) -> Ordering { + Ord::cmp(&&self[..], &&other[..]) + } +} + +#[stable(feature = "copy_clone_array_lib", since = "1.58.0")] +impl Copy for [T; N] {} + +#[stable(feature = "copy_clone_array_lib", since = "1.58.0")] +impl Clone for [T; N] { + #[inline] + fn clone(&self) -> Self { + SpecArrayClone::clone(self) + } + + #[inline] + fn clone_from(&mut self, other: &Self) { + self.clone_from_slice(other); + } +} + +trait SpecArrayClone: Clone { + fn clone(array: &[Self; N]) -> [Self; N]; +} + +impl SpecArrayClone for T { + #[inline] + default fn clone(array: &[T; N]) -> [T; N] { + from_trusted_iterator(array.iter().cloned()) + } +} + +impl SpecArrayClone for T { + #[inline] + fn clone(array: &[T; N]) -> [T; N] { + *array + } +} + +// The Default impls cannot be done with const generics because `[T; 0]` doesn't +// require Default to be implemented, and having different impl blocks for +// different numbers isn't supported yet. + +macro_rules! array_impl_default { + {$n:expr, $t:ident $($ts:ident)*} => { + #[stable(since = "1.4.0", feature = "array_default")] + impl Default for [T; $n] where T: Default { + fn default() -> [T; $n] { + [$t::default(), $($ts::default()),*] + } + } + array_impl_default!{($n - 1), $($ts)*} + }; + {$n:expr,} => { + #[stable(since = "1.4.0", feature = "array_default")] + impl Default for [T; $n] { + fn default() -> [T; $n] { [] } + } + }; +} + +array_impl_default! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T} + +impl [T; N] { + /// Returns an array of the same size as `self`, with function `f` applied to each element + /// in order. + /// + /// If you don't necessarily need a new fixed-size array, consider using + /// [`Iterator::map`] instead. + /// + /// + /// # Note on performance and stack usage + /// + /// Unfortunately, usages of this method are currently not always optimized + /// as well as they could be. This mainly concerns large arrays, as mapping + /// over small arrays seem to be optimized just fine. Also note that in + /// debug mode (i.e. without any optimizations), this method can use a lot + /// of stack space (a few times the size of the array or more). + /// + /// Therefore, in performance-critical code, try to avoid using this method + /// on large arrays or check the emitted code. Also try to avoid chained + /// maps (e.g. `arr.map(...).map(...)`). + /// + /// In many cases, you can instead use [`Iterator::map`] by calling `.iter()` + /// or `.into_iter()` on your array. `[T; N]::map` is only necessary if you + /// really need a new array of the same size as the result. Rust's lazy + /// iterators tend to get optimized very well. + /// + /// + /// # Examples + /// + /// ``` + /// let x = [1, 2, 3]; + /// let y = x.map(|v| v + 1); + /// assert_eq!(y, [2, 3, 4]); + /// + /// let x = [1, 2, 3]; + /// let mut temp = 0; + /// let y = x.map(|v| { temp += 1; v * temp }); + /// assert_eq!(y, [1, 4, 9]); + /// + /// let x = ["Ferris", "Bueller's", "Day", "Off"]; + /// let y = x.map(|v| v.len()); + /// assert_eq!(y, [6, 9, 3, 3]); + /// ``` + #[stable(feature = "array_map", since = "1.55.0")] + pub fn map(self, f: F) -> [U; N] + where + F: FnMut(T) -> U, + { + self.try_map(NeverShortCircuit::wrap_mut_1(f)).0 + } + + /// A fallible function `f` applied to each element on array `self` in order to + /// return an array the same size as `self` or the first error encountered. + /// + /// The return type of this function depends on the return type of the closure. + /// If you return `Result` from the closure, you'll get a `Result<[T; N], E>`. + /// If you return `Option` from the closure, you'll get an `Option<[T; N]>`. + /// + /// # Examples + /// + /// ``` + /// #![feature(array_try_map)] + /// + /// let a = ["1", "2", "3"]; + /// let b = a.try_map(|v| v.parse::()).unwrap().map(|v| v + 1); + /// assert_eq!(b, [2, 3, 4]); + /// + /// let a = ["1", "2a", "3"]; + /// let b = a.try_map(|v| v.parse::()); + /// assert!(b.is_err()); + /// + /// use std::num::NonZero; + /// + /// let z = [1, 2, 0, 3, 4]; + /// assert_eq!(z.try_map(NonZero::new), None); + /// + /// let a = [1, 2, 3]; + /// let b = a.try_map(NonZero::new); + /// let c = b.map(|x| x.map(NonZero::get)); + /// assert_eq!(c, Some(a)); + /// ``` + #[unstable(feature = "array_try_map", issue = "79711")] + pub fn try_map(self, f: impl FnMut(T) -> R) -> ChangeOutputType + where + R: Try>, + { + drain_array_with(self, |iter| try_from_trusted_iterator(iter.map(f))) + } + + /// Returns a slice containing the entire array. Equivalent to `&s[..]`. + #[stable(feature = "array_as_slice", since = "1.57.0")] + #[rustc_const_stable(feature = "array_as_slice", since = "1.57.0")] + pub const fn as_slice(&self) -> &[T] { + self + } + + /// Returns a mutable slice containing the entire array. Equivalent to + /// `&mut s[..]`. + #[stable(feature = "array_as_slice", since = "1.57.0")] + #[rustc_const_unstable(feature = "const_array_as_mut_slice", issue = "133333")] + pub const fn as_mut_slice(&mut self) -> &mut [T] { + self + } + + /// Borrows each element and returns an array of references with the same + /// size as `self`. + /// + /// + /// # Example + /// + /// ``` + /// let floats = [3.1, 2.7, -1.0]; + /// let float_refs: [&f64; 3] = floats.each_ref(); + /// assert_eq!(float_refs, [&3.1, &2.7, &-1.0]); + /// ``` + /// + /// This method is particularly useful if combined with other methods, like + /// [`map`](#method.map). This way, you can avoid moving the original + /// array if its elements are not [`Copy`]. + /// + /// ``` + /// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()]; + /// let is_ascii = strings.each_ref().map(|s| s.is_ascii()); + /// assert_eq!(is_ascii, [true, false, true]); + /// + /// // We can still access the original array: it has not been moved. + /// assert_eq!(strings.len(), 3); + /// ``` + #[stable(feature = "array_methods", since = "1.77.0")] + #[rustc_const_unstable(feature = "const_array_each_ref", issue = "133289")] + pub const fn each_ref(&self) -> [&T; N] { + let mut buf = [null::(); N]; + + // FIXME(const-hack): We would like to simply use iterators for this (as in the original implementation), but this is not allowed in constant expressions. + let mut i = 0; + while i < N { + buf[i] = &raw const self[i]; + + i += 1; + } + + // SAFETY: `*const T` has the same layout as `&T`, and we've also initialised each pointer as a valid reference. + unsafe { transmute_unchecked(buf) } + } + + /// Borrows each element mutably and returns an array of mutable references + /// with the same size as `self`. + /// + /// + /// # Example + /// + /// ``` + /// + /// let mut floats = [3.1, 2.7, -1.0]; + /// let float_refs: [&mut f64; 3] = floats.each_mut(); + /// *float_refs[0] = 0.0; + /// assert_eq!(float_refs, [&mut 0.0, &mut 2.7, &mut -1.0]); + /// assert_eq!(floats, [0.0, 2.7, -1.0]); + /// ``` + #[stable(feature = "array_methods", since = "1.77.0")] + #[rustc_const_unstable(feature = "const_array_each_ref", issue = "133289")] + pub const fn each_mut(&mut self) -> [&mut T; N] { + let mut buf = [null_mut::(); N]; + + // FIXME(const-hack): We would like to simply use iterators for this (as in the original implementation), but this is not allowed in constant expressions. + let mut i = 0; + while i < N { + buf[i] = &raw mut self[i]; + + i += 1; + } + + // SAFETY: `*mut T` has the same layout as `&mut T`, and we've also initialised each pointer as a valid reference. + unsafe { transmute_unchecked(buf) } + } + + /// Divides one array reference into two at an index. + /// + /// The first will contain all indices from `[0, M)` (excluding + /// the index `M` itself) and the second will contain all + /// indices from `[M, N)` (excluding the index `N` itself). + /// + /// # Panics + /// + /// Panics if `M > N`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let v = [1, 2, 3, 4, 5, 6]; + /// + /// { + /// let (left, right) = v.split_array_ref::<0>(); + /// assert_eq!(left, &[]); + /// assert_eq!(right, &[1, 2, 3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_array_ref::<2>(); + /// assert_eq!(left, &[1, 2]); + /// assert_eq!(right, &[3, 4, 5, 6]); + /// } + /// + /// { + /// let (left, right) = v.split_array_ref::<6>(); + /// assert_eq!(left, &[1, 2, 3, 4, 5, 6]); + /// assert_eq!(right, &[]); + /// } + /// ``` + #[unstable( + feature = "split_array", + reason = "return type should have array as 2nd element", + issue = "90091" + )] + #[inline] + pub fn split_array_ref(&self) -> (&[T; M], &[T]) { + (&self[..]).split_first_chunk::().unwrap() + } + + /// Divides one mutable array reference into two at an index. + /// + /// The first will contain all indices from `[0, M)` (excluding + /// the index `M` itself) and the second will contain all + /// indices from `[M, N)` (excluding the index `N` itself). + /// + /// # Panics + /// + /// Panics if `M > N`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let mut v = [1, 0, 3, 0, 5, 6]; + /// let (left, right) = v.split_array_mut::<2>(); + /// assert_eq!(left, &mut [1, 0][..]); + /// assert_eq!(right, &mut [3, 0, 5, 6]); + /// left[1] = 2; + /// right[1] = 4; + /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); + /// ``` + #[unstable( + feature = "split_array", + reason = "return type should have array as 2nd element", + issue = "90091" + )] + #[inline] + pub fn split_array_mut(&mut self) -> (&mut [T; M], &mut [T]) { + (&mut self[..]).split_first_chunk_mut::().unwrap() + } + + /// Divides one array reference into two at an index from the end. + /// + /// The first will contain all indices from `[0, N - M)` (excluding + /// the index `N - M` itself) and the second will contain all + /// indices from `[N - M, N)` (excluding the index `N` itself). + /// + /// # Panics + /// + /// Panics if `M > N`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let v = [1, 2, 3, 4, 5, 6]; + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<0>(); + /// assert_eq!(left, &[1, 2, 3, 4, 5, 6]); + /// assert_eq!(right, &[]); + /// } + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<2>(); + /// assert_eq!(left, &[1, 2, 3, 4]); + /// assert_eq!(right, &[5, 6]); + /// } + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<6>(); + /// assert_eq!(left, &[]); + /// assert_eq!(right, &[1, 2, 3, 4, 5, 6]); + /// } + /// ``` + #[unstable( + feature = "split_array", + reason = "return type should have array as 2nd element", + issue = "90091" + )] + #[inline] + pub fn rsplit_array_ref(&self) -> (&[T], &[T; M]) { + (&self[..]).split_last_chunk::().unwrap() + } + + /// Divides one mutable array reference into two at an index from the end. + /// + /// The first will contain all indices from `[0, N - M)` (excluding + /// the index `N - M` itself) and the second will contain all + /// indices from `[N - M, N)` (excluding the index `N` itself). + /// + /// # Panics + /// + /// Panics if `M > N`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let mut v = [1, 0, 3, 0, 5, 6]; + /// let (left, right) = v.rsplit_array_mut::<4>(); + /// assert_eq!(left, &mut [1, 0]); + /// assert_eq!(right, &mut [3, 0, 5, 6][..]); + /// left[1] = 2; + /// right[1] = 4; + /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); + /// ``` + #[unstable( + feature = "split_array", + reason = "return type should have array as 2nd element", + issue = "90091" + )] + #[inline] + pub fn rsplit_array_mut(&mut self) -> (&mut [T], &mut [T; M]) { + (&mut self[..]).split_last_chunk_mut::().unwrap() + } +} + +/// Populate an array from the first `N` elements of `iter` +/// +/// # Panics +/// +/// If the iterator doesn't actually have enough items. +/// +/// By depending on `TrustedLen`, however, we can do that check up-front (where +/// it easily optimizes away) so it doesn't impact the loop that fills the array. +#[inline] +fn from_trusted_iterator(iter: impl UncheckedIterator) -> [T; N] { + try_from_trusted_iterator(iter.map(NeverShortCircuit)).0 +} + +#[inline] +fn try_from_trusted_iterator( + iter: impl UncheckedIterator, +) -> ChangeOutputType +where + R: Try, + R::Residual: Residual<[T; N]>, +{ + assert!(iter.size_hint().0 >= N); + fn next(mut iter: impl UncheckedIterator) -> impl FnMut(usize) -> T { + move |_| { + // SAFETY: We know that `from_fn` will call this at most N times, + // and we checked to ensure that we have at least that many items. + unsafe { iter.next_unchecked() } + } + } + + try_from_fn(next(iter)) +} + +/// Version of [`try_from_fn`] using a passed-in slice in order to avoid +/// needing to monomorphize for every array length. +/// +/// This takes a generator rather than an iterator so that *at the type level* +/// it never needs to worry about running out of items. When combined with +/// an infallible `Try` type, that means the loop canonicalizes easily, allowing +/// it to optimize well. +/// +/// It would be *possible* to unify this and [`iter_next_chunk_erased`] into one +/// function that does the union of both things, but last time it was that way +/// it resulted in poor codegen from the "are there enough source items?" checks +/// not optimizing away. So if you give it a shot, make sure to watch what +/// happens in the codegen tests. +#[inline] +fn try_from_fn_erased( + buffer: &mut [MaybeUninit], + mut generator: impl FnMut(usize) -> R, +) -> ControlFlow +where + R: Try, +{ + let mut guard = Guard { array_mut: buffer, initialized: 0 }; + + while guard.initialized < guard.array_mut.len() { + let item = generator(guard.initialized).branch()?; + + // SAFETY: The loop condition ensures we have space to push the item + unsafe { guard.push_unchecked(item) }; + } + + mem::forget(guard); + ControlFlow::Continue(()) +} + +/// Panic guard for incremental initialization of arrays. +/// +/// Disarm the guard with `mem::forget` once the array has been initialized. +/// +/// # Safety +/// +/// All write accesses to this structure are unsafe and must maintain a correct +/// count of `initialized` elements. +/// +/// To minimize indirection fields are still pub but callers should at least use +/// `push_unchecked` to signal that something unsafe is going on. +struct Guard<'a, T> { + /// The array to be initialized. + pub array_mut: &'a mut [MaybeUninit], + /// The number of items that have been initialized so far. + pub initialized: usize, +} + +impl Guard<'_, T> { + /// Adds an item to the array and updates the initialized item counter. + /// + /// # Safety + /// + /// No more than N elements must be initialized. + #[inline] + pub unsafe fn push_unchecked(&mut self, item: T) { + // SAFETY: If `initialized` was correct before and the caller does not + // invoke this method more than N times then writes will be in-bounds + // and slots will not be initialized more than once. + unsafe { + self.array_mut.get_unchecked_mut(self.initialized).write(item); + self.initialized = self.initialized.unchecked_add(1); + } + } +} + +impl Drop for Guard<'_, T> { + #[inline] + fn drop(&mut self) { + debug_assert!(self.initialized <= self.array_mut.len()); + + // SAFETY: this slice will contain only initialized objects. + unsafe { + crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut( + self.array_mut.get_unchecked_mut(..self.initialized), + )); + } + } +} + +/// Pulls `N` items from `iter` and returns them as an array. If the iterator +/// yields fewer than `N` items, `Err` is returned containing an iterator over +/// the already yielded items. +/// +/// Since the iterator is passed as a mutable reference and this function calls +/// `next` at most `N` times, the iterator can still be used afterwards to +/// retrieve the remaining items. +/// +/// If `iter.next()` panicks, all items already yielded by the iterator are +/// dropped. +/// +/// Used for [`Iterator::next_chunk`]. +#[inline] +pub(crate) fn iter_next_chunk( + iter: &mut impl Iterator, +) -> Result<[T; N], IntoIter> { + let mut array = [const { MaybeUninit::uninit() }; N]; + let r = iter_next_chunk_erased(&mut array, iter); + match r { + Ok(()) => { + // SAFETY: All elements of `array` were populated. + Ok(unsafe { MaybeUninit::array_assume_init(array) }) + } + Err(initialized) => { + // SAFETY: Only the first `initialized` elements were populated + Err(unsafe { IntoIter::new_unchecked(array, 0..initialized) }) + } + } +} + +/// Version of [`iter_next_chunk`] using a passed-in slice in order to avoid +/// needing to monomorphize for every array length. +/// +/// Unfortunately this loop has two exit conditions, the buffer filling up +/// or the iterator running out of items, making it tend to optimize poorly. +#[inline] +fn iter_next_chunk_erased( + buffer: &mut [MaybeUninit], + iter: &mut impl Iterator, +) -> Result<(), usize> { + let mut guard = Guard { array_mut: buffer, initialized: 0 }; + while guard.initialized < guard.array_mut.len() { + let Some(item) = iter.next() else { + // Unlike `try_from_fn_erased`, we want to keep the partial results, + // so we need to defuse the guard instead of using `?`. + let initialized = guard.initialized; + mem::forget(guard); + return Err(initialized); + }; + + // SAFETY: The loop condition ensures we have space to push the item + unsafe { guard.push_unchecked(item) }; + } + + mem::forget(guard); + Ok(()) +} diff --git a/CoqOfRust/core/ascii.rs b/CoqOfRust/core/ascii.rs new file mode 100644 index 000000000..5b3711b40 --- /dev/null +++ b/CoqOfRust/core/ascii.rs @@ -0,0 +1,180 @@ +//! Operations on ASCII strings and characters. +//! +//! Most string operations in Rust act on UTF-8 strings. However, at times it +//! makes more sense to only consider the ASCII character set for a specific +//! operation. +//! +//! The [`escape_default`] function provides an iterator over the bytes of an +//! escaped version of the character given. + +#![stable(feature = "core_ascii", since = "1.26.0")] + +use crate::iter::FusedIterator; +use crate::num::NonZero; +use crate::{escape, fmt}; + +mod ascii_char; +#[unstable(feature = "ascii_char", issue = "110998")] +pub use ascii_char::AsciiChar as Char; + +/// An iterator over the escaped version of a byte. +/// +/// This `struct` is created by the [`escape_default`] function. See its +/// documentation for more. +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] +pub struct EscapeDefault(escape::EscapeIterInner<4>); + +/// Returns an iterator that produces an escaped version of a `u8`. +/// +/// The default is chosen with a bias toward producing literals that are +/// legal in a variety of languages, including C++11 and similar C-family +/// languages. The exact rules are: +/// +/// * Tab is escaped as `\t`. +/// * Carriage return is escaped as `\r`. +/// * Line feed is escaped as `\n`. +/// * Single quote is escaped as `\'`. +/// * Double quote is escaped as `\"`. +/// * Backslash is escaped as `\\`. +/// * Any character in the 'printable ASCII' range `0x20` .. `0x7e` +/// inclusive is not escaped. +/// * Any other chars are given hex escapes of the form '\xNN'. +/// * Unicode escapes are never generated by this function. +/// +/// # Examples +/// +/// ``` +/// use std::ascii; +/// +/// let escaped = ascii::escape_default(b'0').next().unwrap(); +/// assert_eq!(b'0', escaped); +/// +/// let mut escaped = ascii::escape_default(b'\t'); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b't', escaped.next().unwrap()); +/// +/// let mut escaped = ascii::escape_default(b'\r'); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b'r', escaped.next().unwrap()); +/// +/// let mut escaped = ascii::escape_default(b'\n'); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b'n', escaped.next().unwrap()); +/// +/// let mut escaped = ascii::escape_default(b'\''); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b'\'', escaped.next().unwrap()); +/// +/// let mut escaped = ascii::escape_default(b'"'); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b'"', escaped.next().unwrap()); +/// +/// let mut escaped = ascii::escape_default(b'\\'); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// +/// let mut escaped = ascii::escape_default(b'\x9d'); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b'x', escaped.next().unwrap()); +/// assert_eq!(b'9', escaped.next().unwrap()); +/// assert_eq!(b'd', escaped.next().unwrap()); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub fn escape_default(c: u8) -> EscapeDefault { + EscapeDefault::new(c) +} + +impl EscapeDefault { + #[inline] + pub(crate) const fn new(c: u8) -> Self { + Self(escape::EscapeIterInner::ascii(c)) + } + + #[inline] + pub(crate) fn empty() -> Self { + Self(escape::EscapeIterInner::empty()) + } + + #[inline] + pub(crate) fn as_str(&self) -> &str { + self.0.as_str() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for EscapeDefault { + type Item = u8; + + #[inline] + fn next(&mut self) -> Option { + self.0.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let n = self.0.len(); + (n, Some(n)) + } + + #[inline] + fn count(self) -> usize { + self.0.len() + } + + #[inline] + fn last(mut self) -> Option { + self.0.next_back() + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.0.advance_by(n) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for EscapeDefault { + #[inline] + fn next_back(&mut self) -> Option { + self.0.next_back() + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.0.advance_back_by(n) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for EscapeDefault { + #[inline] + fn len(&self) -> usize { + self.0.len() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +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 { + f.write_str(self.0.as_str()) + } +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for EscapeDefault { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("EscapeDefault").finish_non_exhaustive() + } +} diff --git a/CoqOfRust/core/ascii/ascii_char.rs b/CoqOfRust/core/ascii/ascii_char.rs new file mode 100644 index 000000000..48de4f17b --- /dev/null +++ b/CoqOfRust/core/ascii/ascii_char.rs @@ -0,0 +1,616 @@ +//! This uses the name `AsciiChar`, even though it's not exposed that way right now, +//! because it avoids a whole bunch of "are you sure you didn't mean `char`?" +//! suggestions from rustc if you get anything slightly wrong in here, and overall +//! helps with clarity as we're also referring to `char` intentionally in here. + +use crate::mem::transmute; +use crate::{assert_unsafe_precondition, fmt}; + +/// One of the 128 Unicode characters from U+0000 through U+007F, +/// often known as the [ASCII] subset. +/// +/// Officially, this is the first [block] in Unicode, _Basic Latin_. +/// For details, see the [*C0 Controls and Basic Latin*][chart] code chart. +/// +/// This block was based on older 7-bit character code standards such as +/// ANSI X3.4-1977, ISO 646-1973, and [NIST FIPS 1-2]. +/// +/// # When to use this +/// +/// The main advantage of this subset is that it's always valid UTF-8. As such, +/// the `&[ascii::Char]` -> `&str` conversion function (as well as other related +/// ones) are O(1): *no* runtime checks are needed. +/// +/// If you're consuming strings, you should usually handle Unicode and thus +/// accept `str`s, not limit yourself to `ascii::Char`s. +/// +/// However, certain formats are intentionally designed to produce ASCII-only +/// output in order to be 8-bit-clean. In those cases, it can be simpler and +/// faster to generate `ascii::Char`s instead of dealing with the variable width +/// properties of general UTF-8 encoded strings, while still allowing the result +/// to be used freely with other Rust things that deal in general `str`s. +/// +/// For example, a UUID library might offer a way to produce the string +/// representation of a UUID as an `[ascii::Char; 36]` to avoid memory +/// allocation yet still allow it to be used as UTF-8 via `as_str` without +/// paying for validation (or needing `unsafe` code) the way it would if it +/// were provided as a `[u8; 36]`. +/// +/// # Layout +/// +/// This type is guaranteed to have a size and alignment of 1 byte. +/// +/// # Names +/// +/// The variants on this type are [Unicode names][NamesList] of the characters +/// in upper camel case, with a few tweaks: +/// - For `` characters, the primary alias name is used. +/// - `LATIN` is dropped, as this block has no non-latin letters. +/// - `LETTER` is dropped, as `CAPITAL`/`SMALL` suffices in this block. +/// - `DIGIT`s use a single digit rather than writing out `ZERO`, `ONE`, etc. +/// +/// [ASCII]: https://www.unicode.org/glossary/index.html#ASCII +/// [block]: https://www.unicode.org/glossary/index.html#block +/// [chart]: https://www.unicode.org/charts/PDF/U0000.pdf +/// [NIST FIPS 1-2]: https://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub1-2-1977.pdf +/// [NamesList]: https://www.unicode.org/Public/15.0.0/ucd/NamesList.txt +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[unstable(feature = "ascii_char", issue = "110998")] +#[repr(u8)] +pub enum AsciiChar { + /// U+0000 (The default variant) + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Null = 0, + /// U+0001 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + StartOfHeading = 1, + /// U+0002 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + StartOfText = 2, + /// U+0003 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EndOfText = 3, + /// U+0004 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EndOfTransmission = 4, + /// U+0005 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Enquiry = 5, + /// U+0006 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Acknowledge = 6, + /// U+0007 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Bell = 7, + /// U+0008 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Backspace = 8, + /// U+0009 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CharacterTabulation = 9, + /// U+000A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LineFeed = 10, + /// U+000B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LineTabulation = 11, + /// U+000C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + FormFeed = 12, + /// U+000D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CarriageReturn = 13, + /// U+000E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + ShiftOut = 14, + /// U+000F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + ShiftIn = 15, + /// U+0010 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DataLinkEscape = 16, + /// U+0011 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DeviceControlOne = 17, + /// U+0012 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DeviceControlTwo = 18, + /// U+0013 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DeviceControlThree = 19, + /// U+0014 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DeviceControlFour = 20, + /// U+0015 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + NegativeAcknowledge = 21, + /// U+0016 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SynchronousIdle = 22, + /// U+0017 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EndOfTransmissionBlock = 23, + /// U+0018 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Cancel = 24, + /// U+0019 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EndOfMedium = 25, + /// U+001A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Substitute = 26, + /// U+001B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Escape = 27, + /// U+001C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + InformationSeparatorFour = 28, + /// U+001D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + InformationSeparatorThree = 29, + /// U+001E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + InformationSeparatorTwo = 30, + /// U+001F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + InformationSeparatorOne = 31, + /// U+0020 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Space = 32, + /// U+0021 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + ExclamationMark = 33, + /// U+0022 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + QuotationMark = 34, + /// U+0023 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + NumberSign = 35, + /// U+0024 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DollarSign = 36, + /// U+0025 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + PercentSign = 37, + /// U+0026 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Ampersand = 38, + /// U+0027 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Apostrophe = 39, + /// U+0028 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LeftParenthesis = 40, + /// U+0029 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + RightParenthesis = 41, + /// U+002A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Asterisk = 42, + /// U+002B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + PlusSign = 43, + /// U+002C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Comma = 44, + /// U+002D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + HyphenMinus = 45, + /// U+002E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + FullStop = 46, + /// U+002F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Solidus = 47, + /// U+0030 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit0 = 48, + /// U+0031 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit1 = 49, + /// U+0032 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit2 = 50, + /// U+0033 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit3 = 51, + /// U+0034 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit4 = 52, + /// U+0035 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit5 = 53, + /// U+0036 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit6 = 54, + /// U+0037 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit7 = 55, + /// U+0038 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit8 = 56, + /// U+0039 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit9 = 57, + /// U+003A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Colon = 58, + /// U+003B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Semicolon = 59, + /// U+003C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LessThanSign = 60, + /// U+003D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EqualsSign = 61, + /// U+003E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + GreaterThanSign = 62, + /// U+003F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + QuestionMark = 63, + /// U+0040 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CommercialAt = 64, + /// U+0041 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalA = 65, + /// U+0042 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalB = 66, + /// U+0043 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalC = 67, + /// U+0044 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalD = 68, + /// U+0045 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalE = 69, + /// U+0046 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalF = 70, + /// U+0047 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalG = 71, + /// U+0048 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalH = 72, + /// U+0049 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalI = 73, + /// U+004A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalJ = 74, + /// U+004B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalK = 75, + /// U+004C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalL = 76, + /// U+004D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalM = 77, + /// U+004E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalN = 78, + /// U+004F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalO = 79, + /// U+0050 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalP = 80, + /// U+0051 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalQ = 81, + /// U+0052 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalR = 82, + /// U+0053 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalS = 83, + /// U+0054 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalT = 84, + /// U+0055 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalU = 85, + /// U+0056 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalV = 86, + /// U+0057 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalW = 87, + /// U+0058 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalX = 88, + /// U+0059 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalY = 89, + /// U+005A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalZ = 90, + /// U+005B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LeftSquareBracket = 91, + /// U+005C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + ReverseSolidus = 92, + /// U+005D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + RightSquareBracket = 93, + /// U+005E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CircumflexAccent = 94, + /// U+005F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LowLine = 95, + /// U+0060 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + GraveAccent = 96, + /// U+0061 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallA = 97, + /// U+0062 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallB = 98, + /// U+0063 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallC = 99, + /// U+0064 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallD = 100, + /// U+0065 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallE = 101, + /// U+0066 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallF = 102, + /// U+0067 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallG = 103, + /// U+0068 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallH = 104, + /// U+0069 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallI = 105, + /// U+006A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallJ = 106, + /// U+006B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallK = 107, + /// U+006C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallL = 108, + /// U+006D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallM = 109, + /// U+006E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallN = 110, + /// U+006F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallO = 111, + /// U+0070 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallP = 112, + /// U+0071 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallQ = 113, + /// U+0072 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallR = 114, + /// U+0073 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallS = 115, + /// U+0074 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallT = 116, + /// U+0075 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallU = 117, + /// U+0076 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallV = 118, + /// U+0077 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallW = 119, + /// U+0078 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallX = 120, + /// U+0079 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallY = 121, + /// U+007A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallZ = 122, + /// U+007B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LeftCurlyBracket = 123, + /// U+007C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + VerticalLine = 124, + /// U+007D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + RightCurlyBracket = 125, + /// U+007E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Tilde = 126, + /// U+007F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Delete = 127, +} + +impl AsciiChar { + /// Creates an ascii character from the byte `b`, + /// or returns `None` if it's too large. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn from_u8(b: u8) -> Option { + if b <= 127 { + // SAFETY: Just checked that `b` is in-range + Some(unsafe { Self::from_u8_unchecked(b) }) + } else { + None + } + } + + /// Creates an ASCII character from the byte `b`, + /// without checking whether it's valid. + /// + /// # Safety + /// + /// `b` must be in `0..=127`, or else this is UB. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const unsafe fn from_u8_unchecked(b: u8) -> Self { + // SAFETY: Our safety precondition is that `b` is in-range. + unsafe { transmute(b) } + } + + /// When passed the *number* `0`, `1`, …, `9`, returns the *character* + /// `'0'`, `'1'`, …, `'9'` respectively. + /// + /// If `d >= 10`, returns `None`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn digit(d: u8) -> Option { + if d < 10 { + // SAFETY: Just checked it's in-range. + Some(unsafe { Self::digit_unchecked(d) }) + } else { + None + } + } + + /// When passed the *number* `0`, `1`, …, `9`, returns the *character* + /// `'0'`, `'1'`, …, `'9'` respectively, without checking that it's in-range. + /// + /// # Safety + /// + /// This is immediate UB if called with `d > 64`. + /// + /// If `d >= 10` and `d <= 64`, this is allowed to return any value or panic. + /// Notably, it should not be expected to return hex digits, or any other + /// reasonable extension of the decimal digits. + /// + /// (This loose safety condition is intended to simplify soundness proofs + /// when writing code using this method, since the implementation doesn't + /// need something really specific, not to make those other arguments do + /// something useful. It might be tightened before stabilization.) + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const unsafe fn digit_unchecked(d: u8) -> Self { + assert_unsafe_precondition!( + check_language_ub, + "`ascii::Char::digit_unchecked` input cannot exceed 9.", + (d: u8 = d) => d < 10 + ); + + // SAFETY: `'0'` through `'9'` are U+00030 through U+0039, + // so because `d` must be 64 or less the addition can return at most + // 112 (0x70), which doesn't overflow and is within the ASCII range. + unsafe { + let byte = b'0'.unchecked_add(d); + Self::from_u8_unchecked(byte) + } + } + + /// Gets this ASCII character as a byte. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn to_u8(self) -> u8 { + self as u8 + } + + /// Gets this ASCII character as a `char` Unicode Scalar Value. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn to_char(self) -> char { + self as u8 as char + } + + /// Views this ASCII character as a one-code-unit UTF-8 `str`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_str(&self) -> &str { + crate::slice::from_ref(self).as_str() + } +} + +macro_rules! into_int_impl { + ($($ty:ty)*) => { + $( + #[unstable(feature = "ascii_char", issue = "110998")] + impl From for $ty { + #[inline] + fn from(chr: AsciiChar) -> $ty { + chr as u8 as $ty + } + } + )* + } +} + +into_int_impl!(u8 u16 u32 u64 u128 char); + +impl [AsciiChar] { + /// Views this slice of ASCII characters as a UTF-8 `str`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_str(&self) -> &str { + let ascii_ptr: *const Self = self; + let str_ptr = ascii_ptr as *const str; + // SAFETY: Each ASCII codepoint in UTF-8 is encoded as one single-byte + // code unit having the same value as the ASCII byte. + unsafe { &*str_ptr } + } + + /// Views this slice of ASCII characters as a slice of `u8` bytes. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_bytes(&self) -> &[u8] { + self.as_str().as_bytes() + } +} + +#[unstable(feature = "ascii_char", issue = "110998")] +impl fmt::Display for AsciiChar { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ::fmt(self.as_str(), f) + } +} + +#[unstable(feature = "ascii_char", issue = "110998")] +impl fmt::Debug for AsciiChar { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use AsciiChar::{Apostrophe, Null, ReverseSolidus as Backslash}; + + fn backslash(a: AsciiChar) -> ([AsciiChar; 6], usize) { + ([Apostrophe, Backslash, a, Apostrophe, Null, Null], 4) + } + + let (buf, len) = match self { + AsciiChar::Null => backslash(AsciiChar::Digit0), + AsciiChar::CharacterTabulation => backslash(AsciiChar::SmallT), + AsciiChar::CarriageReturn => backslash(AsciiChar::SmallR), + AsciiChar::LineFeed => backslash(AsciiChar::SmallN), + AsciiChar::ReverseSolidus => backslash(AsciiChar::ReverseSolidus), + AsciiChar::Apostrophe => backslash(AsciiChar::Apostrophe), + _ if self.to_u8().is_ascii_control() => { + const HEX_DIGITS: [AsciiChar; 16] = *b"0123456789abcdef".as_ascii().unwrap(); + + let byte = self.to_u8(); + let hi = HEX_DIGITS[usize::from(byte >> 4)]; + let lo = HEX_DIGITS[usize::from(byte & 0xf)]; + ([Apostrophe, Backslash, AsciiChar::SmallX, hi, lo, Apostrophe], 6) + } + _ => ([Apostrophe, *self, Apostrophe, Null, Null, Null], 3), + }; + + f.write_str(buf[..len].as_str()) + } +} diff --git a/CoqOfRust/core/asserting.rs b/CoqOfRust/core/asserting.rs new file mode 100644 index 000000000..3015aa562 --- /dev/null +++ b/CoqOfRust/core/asserting.rs @@ -0,0 +1,107 @@ +// Contains the machinery necessary to print useful `assert!` messages. Not intended for public +// usage, not even nightly use-cases. +// +// Based on https://github.com/dtolnay/case-studies/tree/master/autoref-specialization. When +// 'specialization' is robust enough (5 years? 10 years? Never?), `Capture` can be specialized +// to [Printable]. + +#![allow(missing_debug_implementations)] +#![doc(hidden)] +#![unstable(feature = "generic_assert_internals", issue = "44838")] + +use crate::fmt::{Debug, Formatter}; +use crate::marker::PhantomData; + +// ***** TryCapture - Generic ***** + +/// Marker used by [Capture] +#[unstable(feature = "generic_assert_internals", issue = "44838")] +pub struct TryCaptureWithoutDebug; + +/// Catches an arbitrary `E` and modifies `to` accordingly +#[unstable(feature = "generic_assert_internals", issue = "44838")] +pub trait TryCaptureGeneric { + /// Similar to [TryCapturePrintable] but generic to any `E`. + fn try_capture(&self, to: &mut Capture); +} + +impl TryCaptureGeneric for &Wrapper<&E> { + #[inline] + fn try_capture(&self, _: &mut Capture) {} +} + +impl Debug for Capture { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> { + f.write_str("N/A") + } +} + +// ***** TryCapture - Printable ***** + +/// Marker used by [Capture] +#[unstable(feature = "generic_assert_internals", issue = "44838")] +pub struct TryCaptureWithDebug; + +/// Catches an arbitrary `E: Printable` and modifies `to` accordingly +#[unstable(feature = "generic_assert_internals", issue = "44838")] +pub trait TryCapturePrintable { + /// Similar as [TryCaptureGeneric] but specialized to any `E: Printable`. + fn try_capture(&self, to: &mut Capture); +} + +impl TryCapturePrintable for Wrapper<&E> +where + E: Printable, +{ + #[inline] + fn try_capture(&self, to: &mut Capture) { + to.elem = Some(*self.0); + } +} + +impl Debug for Capture +where + E: Printable, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> { + match self.elem { + None => f.write_str("N/A"), + Some(ref value) => Debug::fmt(value, f), + } + } +} + +// ***** Others ***** + +/// All possible captured `assert!` elements +/// +/// # Types +/// +/// * `E`: **E**lement that is going to be displayed. +/// * `M`: **M**arker used to differentiate [Capture]s in regards to [Debug]. +#[unstable(feature = "generic_assert_internals", issue = "44838")] +pub struct Capture { + // If None, then `E` does not implements [Printable] or `E` wasn't evaluated (`assert!( ... )` + // short-circuited). + // + // If Some, then `E` implements [Printable] and was evaluated. + pub elem: Option, + phantom: PhantomData, +} + +impl Capture { + #[inline] + pub const fn new() -> Self { + Self { elem: None, phantom: PhantomData } + } +} + +/// Necessary for the implementations of `TryCapture*` +#[unstable(feature = "generic_assert_internals", issue = "44838")] +pub struct Wrapper(pub T); + +/// Tells which elements can be copied and displayed +#[unstable(feature = "generic_assert_internals", issue = "44838")] +pub trait Printable: Copy + Debug {} + +impl Printable for T where T: Copy + Debug {} diff --git a/CoqOfRust/core/async_iter/async_iter.rs b/CoqOfRust/core/async_iter/async_iter.rs new file mode 100644 index 000000000..069c50c25 --- /dev/null +++ b/CoqOfRust/core/async_iter/async_iter.rs @@ -0,0 +1,163 @@ +use crate::ops::DerefMut; +use crate::pin::Pin; +use crate::task::{Context, Poll}; + +/// A trait for dealing with asynchronous iterators. +/// +/// This is the main async iterator trait. For more about the concept of async iterators +/// generally, please see the [module-level documentation]. In particular, you +/// may want to know how to [implement `AsyncIterator`][impl]. +/// +/// [module-level documentation]: index.html +/// [impl]: index.html#implementing-async-iterator +#[unstable(feature = "async_iterator", issue = "79024")] +#[must_use = "async iterators do nothing unless polled"] +#[doc(alias = "Stream")] +#[lang = "async_iterator"] +pub trait AsyncIterator { + /// The type of items yielded by the async iterator. + type Item; + + /// Attempts to pull out the next value of this async iterator, registering the + /// current task for wakeup if the value is not yet available, and returning + /// `None` if the async iterator is exhausted. + /// + /// # Return value + /// + /// There are several possible return values, each indicating a distinct + /// async iterator state: + /// + /// - `Poll::Pending` means that this async iterator's next value is not ready + /// yet. Implementations will ensure that the current task will be notified + /// when the next value may be ready. + /// + /// - `Poll::Ready(Some(val))` means that the async iterator has successfully + /// produced a value, `val`, and may produce further values on subsequent + /// `poll_next` calls. + /// + /// - `Poll::Ready(None)` means that the async iterator has terminated, and + /// `poll_next` should not be invoked again. + /// + /// # Panics + /// + /// Once an async iterator has finished (returned `Ready(None)` from `poll_next`), calling its + /// `poll_next` method again may panic, block forever, or cause other kinds of + /// problems; the `AsyncIterator` trait places no requirements on the effects of + /// such a call. However, as the `poll_next` method is not marked `unsafe`, + /// Rust's usual rules apply: calls must never cause undefined behavior + /// (memory corruption, incorrect use of `unsafe` functions, or the like), + /// regardless of the async iterator's state. + #[lang = "async_iterator_poll_next"] + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; + + /// Returns the bounds on the remaining length of the async iterator. + /// + /// Specifically, `size_hint()` returns a tuple where the first element + /// is the lower bound, and the second element is the upper bound. + /// + /// The second half of the tuple that is returned is an [Option]<[usize]>. + /// A [`None`] here means that either there is no known upper bound, or the + /// upper bound is larger than [`usize`]. + /// + /// # Implementation notes + /// + /// It is not enforced that an async iterator implementation yields the declared + /// number of elements. A buggy async iterator may yield less than the lower bound + /// or more than the upper bound of elements. + /// + /// `size_hint()` is primarily intended to be used for optimizations such as + /// reserving space for the elements of the async iterator, but must not be + /// trusted to e.g., omit bounds checks in unsafe code. An incorrect + /// implementation of `size_hint()` should not lead to memory safety + /// violations. + /// + /// That said, the implementation should provide a correct estimation, + /// because otherwise it would be a violation of the trait's protocol. + /// + /// The default implementation returns (0, [None]) which is correct for any + /// async iterator. + #[inline] + fn size_hint(&self) -> (usize, Option) { + (0, None) + } +} + +#[unstable(feature = "async_iterator", issue = "79024")] +impl AsyncIterator for &mut S { + type Item = S::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + S::poll_next(Pin::new(&mut **self), cx) + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } +} + +#[unstable(feature = "async_iterator", issue = "79024")] +impl